-
Notifications
You must be signed in to change notification settings - Fork 59
/
Copy pathmicrochat.go
133 lines (123 loc) · 4.23 KB
/
microchat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Super simple chat server with some pre-defined rooms and login-less posting
// using display names. No attempt is made at security.
// This shows how one could use categories and the longpoll pub-sub to make
// a chat server with individual rooms/topics.
package main
import (
"flag"
"fmt"
"log"
"net/http"
"github.com/jcuga/golongpoll"
)
func main() {
listenAddress := flag.String("serve", "127.0.0.1:8080", "address:port to serve.")
staticClientJs := flag.String("clientJs", "./js-client/client.js", "where the static js-client/client.js is located relative to where this binary runs")
flag.Parse()
http.HandleFunc("/js/client.js", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, *staticClientJs)
})
// NOTE: to have chats persist across program runs, use Options.AddOn: FilePersistorAddOn.
manager, err := golongpoll.StartLongpoll(golongpoll.Options{
// How many chats per topic to hang on to:
MaxEventBufferSize: 1000,
LoggingEnabled: true,
})
if err != nil {
log.Fatalf("Failed to create chat longpoll manager: %q\n", err)
}
http.HandleFunc("/", indexPage)
http.HandleFunc("/topic/news", topicPage("news"))
http.HandleFunc("/topic/sports", topicPage("sports"))
http.HandleFunc("/topic/politics", topicPage("politics"))
http.HandleFunc("/topic/humor", topicPage("humor"))
// NOTE: using the plain publish handler. If one wanted to add
// additional behavior like escaping or validating data, one could make a
// http handler function that has a closure capturing the longpoll manager
// and then call manager.Publish directly.
http.HandleFunc("/post", manager.PublishHandler)
http.HandleFunc("/events", manager.SubscriptionHandler)
log.Printf("Launching chat server on http://%s\n", *listenAddress)
http.ListenAndServe(*listenAddress, nil)
}
func indexPage(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `
<html>
<head>
<title>golongpoll microchat</title>
</head>
<body>
<h2>Chat Rooms</h2>
<ul>
<li><a href="/topic/news">News</a></li>
<li><a href="/topic/sports">Sports</a></li>
<li><a href="/topic/politics">Politics</a></li>
<li><a href="/topic/humor">Humor</a></li>
</ul>
</body>
</html>`)
}
func topicPage(topic string) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `
<html>
<head>
<title>golongpoll microchat</title>
</head>
<body>
<a href="/">Select Room</a>
<h2>Chat Room: %s</h2>
<ul id="chats"></ul>
Display Name:
<input id="display-name-input" type="text" /><br/>
Message:
<input id="chat-input" type="text" /><br/>
<button id="chat-send">Send</button>
<!-- Serving the gonlongpoll js client at this address: -->
<script src="/js/client.js"></script>
<script>
var client = golongpoll.newClient({
subscribeUrl: "/events",
category: "%s",
publishUrl: "/post",
// get events since last 24 hours
sinceTime: Date.now() - (24 * 60 * 60 * 1000),
loggingEnabled: true,
onEvent: function (event) {
// NOTE: this does NOTE escape the event.data.chat field!
// In a real webpage, one would want to do so to avoid arbitrary html/js injected here!
document.getElementById("chats").insertAdjacentHTML('beforeend', "<li><i>" + (new Date(event.timestamp).toLocaleTimeString()) +
"</i> <b>" + event.data["display_name"] + "</b>: " + event.data["chat"] + "</li>");
},
});
// newClient returns null if failed.
if (!client) {
alert("Failed to create golongpoll client.");
} else {
console.log(client);
}
document.getElementById("chat-send").onclick = function(event) {
var msg = document.getElementById("chat-input").value;
if (msg.length == 0) {
alert("message cannot be empty");
return;
}
var displayName = document.getElementById("display-name-input").value;
if (displayName.length == 0) {
alert("display name cannot be empty");
return;
}
client.publish("%s", {display_name: displayName, chat: msg},
function () {
document.getElementById("chat-input").value = '';
},
function(status, resp) {
alert("publish post request failed. status: " + status + ", resp: " + resp);
}
);
};
</script>
</body>
</html>`, topic, topic, topic)
}
}