-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchat.go
162 lines (143 loc) · 4.63 KB
/
chat.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package main
import (
"golang.org/x/net/websocket"
"html/template"
"log"
"net/http"
"os"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"github.com/ytkang/golang_chat_bot/jarvis"
"github.com/ytkang/golang_chat_bot/network"
"strings"
"strconv"
)
const (
Host = "mongodb://ds161209.mlab.com:61209"
Username = "mongo"
Password = "mongo123"
Database = "ytchat"
)
var (
pwd, _ = os.Getwd()
RootTemp = template.Must(template.ParseFiles(pwd + "/chat.html"))
JSON = websocket.JSON // codec for JSON
Message = websocket.Message // codec for string, []byte
ActiveClients = make(map[network.ClientConn]int) // map containing clients
mongo *mgo.Session = nil
jarvis *SmartJarvis.Jarvis
listenAddr = "0.0.0.0:"+os.Getenv("PORT") // server address
)
// Initialize handlers and websocket handlers
func init() {
http.HandleFunc("/", RootHandler)
http.Handle("/sock", websocket.Handler(SockServer))
}
// WebSocket server to handle chat between clients
func SockServer(ws *websocket.Conn) {
var err error
var clientMessage string
// use []byte if websocket binary type is blob or arraybuffer
// var clientMessage []byte
// cleanup on server side
defer func() {
if err = ws.Close(); err != nil {
log.Println("Websocket could not be closed", err.Error())
}
}()
client := ws.Request().RemoteAddr
log.Println("Client connected:", client)
sockCli := network.ClientConn{ws, client}
ActiveClients[sockCli] = 0
activeClientsCount := len(ActiveClients)
log.Println("Number of clients connected ...", activeClientsCount)
// for loop so the websocket stays open otherwise
// it'll close after one Receieve and Send
Message.Send(sockCli.Websocket, "$%$%YOUR IP$%$%:"+sockCli.ClientIP)
Message.Send(sockCli.Websocket, "Jarvis Said: 안녕! 현재 접속자수: "+strconv.Itoa(activeClientsCount))
for {
if err = Message.Receive(ws, &clientMessage); err != nil {
// If we cannot Read then the connection is closed
log.Println("Websocket Disconnected waiting", err.Error())
// remove the ws client conn from our active clients
delete(ActiveClients, sockCli)
log.Println("Number of clients still connected ...", len(ActiveClients))
return
}
sendingMessage := sockCli.ClientIP + " Said: " + clientMessage
clientMessage = strings.Replace(clientMessage, "\n", "", -1)
if len(clientMessage) == 0 {
continue
}
if !strings.Contains(clientMessage, "ㄷ:") {
for cs, _ := range ActiveClients {
// go Message.Send(cs.websocket, clientMessage) // DO NOT THIS! This handler is already called from go routine
if mongo != nil {
var msg network.Msg = network.Msg{}
c := mongo.DB("ytchat").C("messages")
change := mgo.Change{
Update: bson.M{"text": clientMessage},
Upsert: true,
}
info, err := c.Find(bson.M{"text": clientMessage}).Apply(change, &msg)
//err = c.Insert(&Msg{Text:clientMessage})
if err != nil {
log.Println("Error: could not insert new message!")
log.Panic(err)
}else if info.UpsertedId != nil {
jarvis.SetPrevMessageId(info.UpsertedId.(bson.ObjectId))
} else {
jarvis.SetPrevMessageId(msg.ID)
}
} else {
log.Println("mongo db is nil")
}
log.Println("will send broadcast message to clients")
if err = Message.Send(cs.Websocket, sendingMessage); err != nil {
// we could not send the message to a peer
log.Println("Could not send message to ", cs.ClientIP, err.Error())
} else {
log.Println("broadcast done")
}
}
}
if mongo != nil {
go jarvis.Answer(&Message, ActiveClients, clientMessage, mongo)
}
}
}
// RootHandler renders the template for the root page
func RootHandler(w http.ResponseWriter, req *http.Request) {
err := RootTemp.Execute(w, listenAddr)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func main() {
var m_err error = nil
log.Println("MongoDB connection..")
mongo, m_err = mgo.Dial("mongodb://mongo:[email protected]:61209/ytchat")
// session, m_err := mgo.DialWithInfo(&mgo.DialInfo{
// Addrs: []string{Host},
// Username: Username,
// Password: Password,
// Database: Database,
// DialServer: func(addr *mgo.ServerAddr) (net.Conn, error) {
// return tls.Dial("tcp", addr.String(), &tls.Config{})
// },
// })
// mongo = session
if m_err != nil {
panic(m_err)
log.Println("[Error] MongoDB connecting failed")
} else {
log.Println("MongoDB connected")
}
mongo.SetMode(mgo.Monotonic, true)
jarvis = SmartJarvis.NewJarvis()
log.Println("Starting..", listenAddr)
err := http.ListenAndServe(listenAddr, nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}