Пример #1
0
//MsgHistChannel get message history of a channel
//It will fetch message history from the latest to oldest
func MsgHistChannel(em *EndptMsg, ws *websocket.Conn) {
	channel, ok := em.GetDataString("channel")
	if !ok {
		log.Error("MsgHistChannel() null channel")
		return
	}

	log.Debug("[MsgHistChannel] userId=" + em.UserID + ".channel = " + channel)

	i := 0
	for {
		var res []MessageHist

		query := bson.M{"userId": em.UserID, "target": channel}
		err := DBQueryArr("ircboks", "msghist", query, "-timestamp", 50, 50*i, &res)
		if err != nil {
			log.Error("[MsgHistChannel]fetching channel history:" + err.Error())
			return
		}

		m := map[string]interface{}{
			"logs":    res,
			"channel": channel,
		}

		//send the result
		websocket.Message.Send(ws, jsonMarshal("msghistChannel", m))

		if len(res) == 0 || res[len(res)-1].ReadFlag == true {
			break
		}
		i = i + 1
	}
}
Пример #2
0
// serveWeb starts a webserver that can serve a page and websocket events as
// they are seen.
// It is expected to be run only once and uses the http package global request
// router. It does NOT return.
func serveWeb(port uint16, events chan *gitsync.GitChange) {
	// the container for websocket clients, passed into every websocket handler
	// below
	var cs = clientSet{
		clients: make(map[*websocket.Conn]chan gitsync.GitChange)}

	// Handle any static files (JS/CSS files)
	if handler, err := webcontent.NewMapHandler(webcontent.Paths); err != nil {
		log.Error("Error building templates for web content: %s", err)
	} else {
		log.Debug("Registering / handler")
		http.Handle("/", handler)
	}

	// Events endpoint
	// Note: we wrap the handler in a closure to pass in the clientSet
	http.Handle("/events", websocket.Handler(func(ws *websocket.Conn) {
		handleGitChangeWebClient(&cs, ws)
	}))

	log.Info("Attempting to spawn webserver on %d", port)
	go cs.distribute(events)
	if err := http.ListenAndServe(fmt.Sprintf(":%v", port), nil); err != nil {
		log.Error("Error listening on %d: %s", port, err)
	}
}
Пример #3
0
//UserRegister handle user registration
func UserRegister(e *EndptMsg, ws *websocket.Conn) {
	userID := e.UserID
	password, ok := e.GetDataString("password")
	if !ok {
		websocket.Message.Send(ws, `{"event":"registrationResult", "data" : {"result":"failed", "reason":null password"}}`)
		return
	}

	//check if user already exist
	if isUserExist(userID) {
		log.Info("[registerUser]User '" + userID + "' already registered")
		websocket.Message.Send(ws, `{"event":"registrationResult", "data" : {"result":"failed", "reason":"email address already registered"}}`)
		return
	}

	log.Info("[registerUser] registering " + userID)

	hashedPass, err := authHassPassword(password)
	if err != nil {
		log.Error("[RegisterUser]:failed to hass password : "******"event":"registrationResult", "data" : {"result":"failed", "reason":"internal error"}}`)
		return
	}

	if len(hashedPass) == 0 {
		log.Error("[RegisterUser]:failed to hass password : password len = 0")
		websocket.Message.Send(ws, `{"event":"registrationResult", "data" : {"result":"failed", "reason":"invalid password"}}`)
		return
	}
	log.Debug("generated password = "******"mongodb_uri")

	sess, err := mgo.Dial(uri)
	if err != nil {
		log.Error("Can't connect to mongo, go error :" + err.Error())
		websocket.Message.Send(ws, `{"event":"registrationResult", "data" : {"result":"failed", "reason":"internal DB error"}}`)
		return
	}
	defer sess.Close()

	sess.SetSafe(&mgo.Safe{})
	collection := sess.DB("ircboks").C("user")
	doc := AuthInfo{bson.NewObjectId(), userID, hashedPass}
	err = collection.Insert(doc)
	if err != nil {
		log.Error("Can't insert new user:"******"event":"registrationResult", "data" : {"result":"failed", "reason":"internal DB error"}}`)
		return
	}
	websocket.Message.Send(ws, `{"event":"registrationResult", "data" : {"result":"ok"}}`)
}
Пример #4
0
//Part or leave a channel
func (c *IRCClient) Part(em *EndptMsg) {
	if len(em.Args) == 0 {
		log.Error("part() invalid args len = 0")
		return
	}
	c.client.Part(em.Args[0], "")
}
Пример #5
0
//handle IRCBoks message
func dispatchBoksHandler(wsCtx *wsContext, em *EndptMsg) {
	resp := "{}"
	if em.Event == "login" {
		resp, isLoginOK, _ := UserLogin(em, wsCtx.Ws)
		wsCtx.LoggedIn = isLoginOK
		websocket.Message.Send(wsCtx.Ws, resp)
		return
	} else if em.Event == "userRegister" {
		UserRegister(em, wsCtx.Ws)
		return
	}

	if !wsCtx.LoggedIn {
		em := EndptMsg{
			Event: "illegalAccess",
			Data: map[string]interface{}{
				"reason": "needLogin",
			},
		}
		websocket.Message.Send(wsCtx.Ws, em.Marshal())
	}

	if fn, ok := boksHandlers[em.Event]; ok {
		go fn(em, wsCtx.Ws)
	} else {
		log.Error("dispatchBoksHandler() unhandled event:" + em.Event)
	}
}
Пример #6
0
//processIrcMsg will unmarshal irc command json string and dispatch it to respective handler
func (c *IRCClient) processIrcMsg(em *EndptMsg) {
	//handler for IRC Command
	handlers := map[string]func(*EndptMsg){
		"join":    c.Join,
		"privmsg": c.PrivMsg,
		"part":    c.Part,
		"names":   c.Names,
		"nick":    c.Nick,
		"topic":   c.Topic,
	}

	if fn, ok := handlers[em.Event]; ok {
		fn(em)
		return
	}

	switch em.Event {
	case "ircBoxInfo":
		info := c.dumpInfo()
		EndpointPublishID(em.UserID, info)

	case "killMe":
		c.client.Stop()
		go func() {
			c.stopChan <- true
		}()
	default:
		log.Error("processIrcMessage() unknown command :" + em.Event)
	}
}
Пример #7
0
//DBUpdateOne update a doc
func DBUpdateOne(dbName, colName, oid string, updateQuery bson.M) error {
	sess, err := getSession()
	if err != nil {
		log.Error("[DBUpdateOne]failed to connect to server :" + err.Error())
		return nil
	}
	defer sess.Close()

	sess.SetSafe(&mgo.Safe{})

	err = sess.DB(dbName).C(colName).Update(bson.M{"_id": bson.ObjectIdHex(oid)}, updateQuery)
	if err != nil {
		log.Error("[DBUpdateOne]dbName = " + dbName + ".collection = " + colName + ".oid = " + oid + ". err = " + err.Error())
	}
	return err
}
Пример #8
0
//Nick change nick of this client
func (c *IRCClient) Nick(em *EndptMsg) {
	if newNick, ok := em.GetDataString("new_nick"); ok {
		c.client.SetNick(newNick)
	} else {
		log.Error("SetNick() empty nick")
	}
}
Пример #9
0
func msgHistNick(userID, nick string, ws *websocket.Conn) {
	i := 0
	query1 := bson.M{"userId": userID, "nick": nick, "to_channel": false} //message from this nick, not in channel
	query2 := bson.M{"userId": userID, "target": nick}                    //message to this nick
	query := bson.M{"$or": []bson.M{query1, query2}}

	for {
		var hists []MessageHist

		err := DBQueryArr("ircboks", "msghist", query, "-timestamp", 50, 50*i, &hists)
		if err != nil {
			log.Error("[MsgHistNick]fetching channel nick:" + err.Error())
			return
		}

		m := map[string]interface{}{
			"logs": hists,
			"nick": nick,
		}

		//send it back
		websocket.Message.Send(ws, jsonMarshal("msghistNickResp", m))

		if len(hists) == 0 || hists[len(hists)-1].ReadFlag == true {
			break
		}
		i++
	}
}
Пример #10
0
//websocket main handler
func wsMain(ws *websocket.Conn) {
	defer ws.Close()

	wsCtx := newWSContext(ws)

	var msg string
	for {
		//read message
		err := websocket.Message.Receive(ws, &msg)
		if err != nil {
			break
		}
		log.Debug("[wsMain]endpoint's msg = " + msg)

		//parse message
		wsMsg, err := NewEndptMsgFromStr(msg)

		if err != nil {
			log.Error("[wsMain]failed to unmarshal json :" + err.Error())
			continue
		}
		wsCtx.UserID = wsMsg.UserID

		if wsMsg.Domain == "irc" && wsCtx.LoggedIn {
			ClientDoIRCCmd(wsMsg, ws)
		} else {
			dispatchBoksHandler(wsCtx, wsMsg)
		}
	}

	if wsCtx.LoggedIn {
		UserLogout(wsCtx.UserID, ws)
	}
	log.Debug("[wsMain]endpoint exited")
}
Пример #11
0
//UserLogout will log out the user
func UserLogout(userID string, ws *websocket.Conn) {
	ctx, found := ContextMap.Get(userID)
	if !found {
		log.Error("[UserLogout]can't find = " + userID)
		return
	}
	ctx.DelWs(ws)
}
Пример #12
0
//ClientDoIRCCmd receive IRC command and run it
func ClientDoIRCCmd(em *EndptMsg, ws *websocket.Conn) {
	ctx, found := ContextMap.Get(em.UserID)
	if !found {
		log.Error("Can't find client ctx for userId = " + em.UserID)
		return
	}
	ctx.InChan <- em
}
Пример #13
0
//MsgHistNick get message history of a nick
func MsgHistNick(em *EndptMsg, ws *websocket.Conn) {
	nick, ok := em.GetDataString("nick")
	if !ok {
		log.Error("MsgHistNick() empty nick")
		return
	}
	msgHistNick(em.UserID, nick, ws)
}
Пример #14
0
//DBSelectDistinct do similar operation like 'select ... distinct ...' on SQL
func DBSelectDistinct(dbName, colName string, query bson.M, distinctBy string, res interface{}) error {
	sess, err := getSession()
	if err != nil {
		log.Error("[DBSelectDistinct]Error getSession:", err.Error())
		return err
	}
	defer sess.Close()
	return sess.DB(dbName).C(colName).Find(query).Distinct(distinctBy, res)
}
Пример #15
0
//process JOIN event
func (c *IRCClient) processJoined(e *ogric.Event) {
	if len(e.Arguments) == 0 {
		log.Error("processJoined() invalid event args len = 0")
	} else {
		log.Debug("process join nick=" + e.Nick)
		channelName := e.Arguments[0]
		c.chanJoinedSet[channelName] = true
	}
	c.forwardEvent(e)
}
Пример #16
0
//DBQueryArr retrieve array of document from mongodb server
func DBQueryArr(dbName, colName string, query bson.M, sortStr string, limit, skip int, res interface{}) error {
	sess, err := getSession()
	if err != nil {
		log.Error("[DBQueryArr]Can't connect to mongo. error:", err.Error())
		return err
	}
	defer sess.Close()

	return sess.DB(dbName).C(colName).Find(query).Sort(sortStr).Skip(skip).Limit(limit).All(res)
}
Пример #17
0
//jsonMarshal marshal map to json string
//this function is deprecated, we should use EndptMsg.MarshalJson
func jsonMarshal(event string, data map[string]interface{}) string {
	em := &EndptMsg{Event: event, Data: data}

	b, err := json.Marshal(em)
	if err != nil {
		log.Error("jsonMarshal() failed. err =", err.Error())
		return "{}"
	}
	return string(b)
}
Пример #18
0
//getSession return cloned session of mongodb connection.
//It will create the connection when needed
func getSession() (*mgo.Session, error) {
	var err error
	if mgoSes == nil {
		mgoSes, err = mgo.Dial(Config.GetString("mongodb_uri"))
		if err != nil {
			log.Error("failed to connect to mongodb :" + err.Error())
			return nil, err
		}
	}
	return mgoSes.Clone(), nil
}
Пример #19
0
//MsgHistMarkRead mark messages readFlag as read
func MsgHistMarkRead(em *EndptMsg, ws *websocket.Conn) {
	oids := em.Args
	if len(oids) == 0 {
		log.Error("MsgHistMarkRead() empty oids")
		return
	}
	for _, oid := range oids {
		updQuery := bson.M{"$set": bson.M{"read_flag": true}}

		DBUpdateOne("ircboks", "msghist", oid, updQuery)
	}
}
Пример #20
0
//process PART
func (c *IRCClient) processPart(e *ogric.Event) {
	if len(e.Arguments) == 0 {
		log.Error("processPart() invalid event args len = 0")
	} else if e.Nick == c.nick {
		channelName := e.Arguments[0]
		c.chanJoinedSet[channelName] = true
		if _, exist := c.chanJoinedSet[channelName]; exist {
			delete(c.chanJoinedSet, channelName)
		}
	}
	c.forwardEvent(e)
}
Пример #21
0
//MsgHistInsert save a message to DB
func MsgHistInsert(userID, target, nick, message string, timestamp int64, readFlag, incoming bool) bson.ObjectId {
	objectID := bson.NewObjectId()
	toChannel := false
	if string(target[0]) == "#" {
		toChannel = true
	}
	doc := MessageHist{objectID, userID, target, nick, message, timestamp, readFlag, toChannel, incoming}
	err := DBInsert("ircboks", "msghist", &doc)
	if err != nil {
		log.Error("[insertMsgHistory] failed : " + err.Error())
	}
	return objectID
}
Пример #22
0
//MsgHistNicksUnread get all unread messages that is not from channel
func MsgHistNicksUnread(em *EndptMsg, ws *websocket.Conn) {
	var unreadNicks []string

	query := bson.M{"userId": em.UserID, "to_channel": false, "incoming": true, "read_flag": false}
	if err := DBSelectDistinct("ircboks", "msghist", query, "nick", &unreadNicks); err != nil {
		log.Error("MsgHistNicksUnread:selecr distinct err :" + err.Error())
		return
	}

	m := map[string]interface{}{
		"nicks": unreadNicks,
	}

	websocket.Message.Send(ws, jsonMarshal("msghistNicksUnread", m))
}
Пример #23
0
//ClientDestroy kill the client
func ClientDestroy(em *EndptMsg, ws *websocket.Conn) {
	ctx, found := ContextMap.Get(em.UserID)
	if !found {
		log.Error("Can't find client ctx for userId = " + em.UserID)
		return
	}
	ctx.InChan <- em

	ContextMap.Del(em.UserID)

	em = &EndptMsg{Event: "ircClientDestroyed"}
	jsonStr := em.Marshal()

	websocket.Message.Send(ws, jsonStr)
}
Пример #24
0
//DBGetOne retrieve a document from DB
func DBGetOne(dbName, colName string, bsonM bson.M, doc interface{}) error {
	sess, err := getSession()
	if err != nil {
		log.Error("[DBGetOne]failed to connect to server :" + err.Error())
		return nil
	}
	defer sess.Close()

	col := sess.DB(dbName).C(colName)
	err = col.Find(bsonM).One(doc)
	if err != nil {
		//TODO : handle in case error is not "not found" error
		return err
	}
	return nil
}
Пример #25
0
//EndpointPublisher is
func EndpointPublisher() {
	for {
		msg := <-endpointMsgChan
		if msg.ClientCtx == nil {
			ctx, found := ContextMap.Get(msg.UserID)
			if !found {
				log.Error("[EndpointWriter] failed to find context for :" + msg.UserID)
				continue
			}
			msg.ClientCtx = ctx
		}

		for _, ws := range msg.ClientCtx.wsArr {
			websocket.Message.Send(ws, msg.Msg)
		}
	}
}
Пример #26
0
func main() {
	log.LoadConfiguration("timber.xml")
	r := mux.NewRouter()

	r.Handle("/irc/", websocket.Handler(wsMain))
	r.PathPrefix("/").Handler(http.FileServer(http.Dir("../ui/build/")))

	ContextMapInit()
	go EndpointPublisher()

	log.Debug("Starting ircboks server ..")

	if err := http.ListenAndServe(Config.GetString("host_port"), r); err != nil {
		log.Error("ListenAndServer error :", err.Error())
	}
	log.Close()
}
Пример #27
0
// handleGitChangeWebClient will build and register a channel to revieve events
// on from a distributor in clientSet. It will exit on error but will consume
// one more event after a client disconnects before it does so.
func handleGitChangeWebClient(cs *clientSet, ws *websocket.Conn) {
	var events = make(chan gitsync.GitChange)

	log.Info("Begin handling %s", makeWebsocketName(ws))
	defer log.Info("End handling %s", makeWebsocketName(ws))

	cs.AddClient(ws, events)
	defer cs.RemoveClient(ws)

	for event := range events {
		if data, err := json.Marshal(event); err != nil {
			log.Info("%s: Cannot marshall event data %+v. %s", makeWebsocketName(ws), event, err)
		} else {
			if _, err := ws.Write(data); err != nil {
				ws.Close()
				log.Error("%s: Cannot write out event: %s", makeWebsocketName(ws), err)
				return
			} else {
				log.Info("%s: Wrote out data", makeWebsocketName(ws))
			}
		}
	}
}
Пример #28
0
func (log TimberLog) Warn(v ...interface{}) {
	tl.Error("", v)
}
Пример #29
0
func (log TimberLog) Info(v ...interface{}) {
	tl.Error("", v)
}