func (this *Counter) ReadNotificationItem(input *ReadNotificationInput, reply *CountNotification) (err error) {

	defer func() {
		if x := recover(); x != nil {
			utils.PrintfStackAndError("Error: %+v \n For:", x.(error), input)
		}
	}()

	var myCount *qortexapi.MyCount
	serv, err := MakeWsService(input.OrganizationId, input.ReaderId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}
	if myCount, err = serv.ReadNotificationItem(input.NotificationItemId, input.GroupId); err != nil {
		utils.PrintStackAndError(err)
		return
	}

	if serv.OnlineUser == nil {
		return
	}

	newReply := CountNotification{
		Method:           COUNTER_READ_NOTIFICATION,
		MyCount:          myCount,
		NewMessageNumber: len(serv.OnlineUser.NewMessageIds),
	}
	serv.OnlineUser.SendReply(newReply)

	return
}
Example #2
0
func CreateNews(input *duoerlapi.NewsInput) (originInput *duoerlapi.NewsInput, err error) {
	originInput = input

	newsId, err := utils.ToObjectId(input.Id)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	brandId, err := utils.ToObjectId(input.BrandId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	authorId, err := utils.ToObjectId(input.AuthorId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	dbNews := &news.News{
		Id:      newsId,
		BrandId: brandId,
		Article: *articles.NewArticle(input.Title, input.Content, authorId),
	}

	if err = dbNews.Save(); err != nil {
		utils.PrintStackAndError(err)
		return
	}

	return
}
Example #3
0
func UpdateNews(input *duoerlapi.NewsInput) (originInput *duoerlapi.NewsInput, err error) {
	originInput = input

	newsId, err := utils.ToObjectId(input.Id)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	brandId, err := utils.ToObjectId(input.BrandId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	dbNews, err := news.FindById(newsId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	dbNews.BrandId = brandId
	dbNews.Title = input.Title
	dbNews.Content = input.Content

	if err = dbNews.Save(); err != nil {
		utils.PrintStackAndError(err)
		return
	}

	return
}
Example #4
0
func ShowNews(newsIdHex, userIdHex string) (apiNews *duoerlapi.News, err error) {
	newsId, err := utils.ToObjectId(newsIdHex)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	dbNews, err := news.FindById(newsId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	brand, err := brands.FindById(dbNews.BrandId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	author, err := users.FindById(dbNews.AuthorId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	apiNews = toApiNews(dbNews, brand, author)

	return
}
Example #5
0
func InitConsumers() (err error) {

	// Put consumers here
	consumers := []Consumer{
		&nfts.EntryNtfsConsumer{},
	}

	for _, consumer := range consumers {

		topic, channel := consumer.TopicAndChannel()
		reader, err := nsq.NewReader(topic, channel)
		if err != nil {
			utils.PrintStackAndError(err)
			return err
		}

		reader.AddHandler(consumer)

		err = reader.ConnectToLookupd(configs.NsqLookupAdddr)
		if err != nil {
			utils.PrintStackAndError(err)
			return err
		}
	}

	return
}
// Make the service object in web socket connection
func MakeWsService(orgIdHex, userIdHex string) (wsService *WsService, err error) {

	userId, err := utils.ToObjectId(userIdHex)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	activeOrg, err := MyActiveOrg(orgIdHex)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	wsService = new(WsService)
	onlineUser, err := activeOrg.GetOnlineUserById(userId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	wsService.OnlineUser = onlineUser
	wsService.LoggedInUser = onlineUser.User
	wsService.CurrentOrg = activeOrg.Organization
	wsService.AllDBs = activeOrg.AllDBs

	return
}
// Entrance that builds and maintains the websocket connection for users
func BuildConnection(conn *websocket.Conn) {

	defer func() {
		if err := recover(); err != nil {
			log.Printf("********** WebSocket Error: %+v ***********\n", err)
			debug.PrintStack()
		}
	}()

	orgIdHex := conn.Request().URL.Query().Get("o")
	if orgIdHex == "" {
		return
	}

	wsCookie := ""
	for _, cc := range conn.Request().Cookies() {
		if cc.Name == "qortex" {
			wsCookie = cc.Value
			break
		}
	}
	if wsCookie == "" {
		return
	}

	member, _ := getSessionMember(wsCookie)
	if member == nil {
		return
	}

	activeOrg, err := MyActiveOrg(orgIdHex)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	user, err := users.FindById(activeOrg.Organization.Database, member.Id)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	onlineUser := activeOrg.GetOrInitOnlineUser(user, conn)
	log.Printf("----> New websocket connection for: %s, %+v running totally",
		user.Email, len(onlineUser.WsConns))

	// Holding the connection
	jsonrpc.ServeConn(conn)

	// Cut current connection and clean up related resources
	onlineUser.KillWebsocket(conn)
}
func MyActiveOrg(orgIdHex string) (activeOrg *ws.ActiveOrg, err error) {
	mu.Lock()
	defer mu.Unlock()

	// Validation: The org id should be valid
	orgId, err := utils.ToObjectId(orgIdHex)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	// Already running in the map
	activeOrg, exist := activeOrgMap[orgIdHex]
	if exist {
		return
	}

	// Should init the org and put into map for further use
	org, err := organizations.FindById(orgId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	// Find and maintain all dbs for handling shared groups
	allDBs := []*mgodb.Database{org.Database}
	embedOrgs, err := organizations.FindByIds(org.EmbededOrgIds)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	for _, embedOrg := range embedOrgs {
		allDBs = append(allDBs, embedOrg.Database)
	}

	// Init the activeOrg and put it into the map
	activeOrg = &ws.ActiveOrg{
		OrgId:        orgIdHex,
		Organization: org,
		OnlineUsers:  make(map[bson.ObjectId]*ws.OnlineUser),
		Broadcast:    make(chan ws.GenericPushingMessage),
		CloseSign:    make(chan bool),
		AllDBs:       allDBs,
	}

	go runActiveOrg(activeOrg)
	activeOrgMap[orgIdHex] = activeOrg

	return
}
func (this *Counter) ReadEntry(input *ReadEntryInput, reply *CountNotification) (err error) {

	defer func() {
		if x := recover(); x != nil {
			utils.PrintfStackAndError("Error: %+v \n For:", x.(error), input)
		}
	}()

	if !input.isValid() {
		return
	}

	var myCount *qortexapi.MyCount
	serv, err := MakeWsService(input.OrganizationId, input.ReaderId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	var method string
	switch {
	case input.isReadEntry():
		method = COUNTER_READ_ENTRY
		myCount, err = serv.ReadEntry(input.EntryId, input.GroupId)
	case input.isReadMyMessage():
		method = COUNTER_READ_MESSAGE
		myCount, err = serv.ReadMyMessage(input.ConversationId)
	default:
		return
	}
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	if serv.OnlineUser == nil {
		return
	}

	newReply := CountNotification{
		Method:           method,
		EntryId:          input.EntryId,
		GroupId:          input.GroupId,
		MyCount:          myCount,
		NewMessageNumber: serv.OnlineUser.ClearNewMessageId(),
	}
	serv.OnlineUser.SendReply(newReply)

	return
}
Example #10
0
func (this *OnlineUser) SendReply(reply GenericPushingMessage) {
	defer func() {
		if err := recover(); err != nil {
			utils.PrintStackAndError(err.(error))
		}
	}()
	this.Send <- reply
}
func (this *Pulse) Send(input *PulseInput, reply *string) (err error) {

	defer func() {
		if e := recover(); e != nil {
			utils.PrintStackAndError(e.(error))
		}
	}()
	*reply = "Pulse.Get"
	return
}
Example #12
0
func GetNewsInBrand(brandIdHex string) (apiNews []*duoerlapi.News, err error) {
	brandId, err := utils.ToObjectId(brandIdHex)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	newz, err := news.FindSomeByBrandId(brandId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	for _, dbNews := range newz {
		apiNews = append(apiNews, toApiNews(dbNews, nil, nil))
	}

	return
}
Example #13
0
func (this *EntryNtfsConsumer) HandleMessage(msg *nsq.Message) (err error) {

	entryTopicData := new(nsqproducers.EntryTopicData)
	err = json.Unmarshal(msg.Body, &entryTopicData)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	services.SendEntryNotification(entryTopicData)
	return
}
func (this *Counter) Refresh(input *RefreshInput, reply *CountNotification) (err error) {

	defer func() {
		if x := recover(); x != nil {
			utils.PrintfStackAndError("Error: %+v \n For:", x.(error), input)
		}
	}()

	reply.Method = COUNTER_REFRESH
	serv, err := MakeWsService(input.OrganizationId, input.LoggedInUserId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	reply.MyCount, err = serv.GetMyCount()
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}
	return
}
Example #15
0
func EditNews(user *users.User, newsIdHex string) (newsInput *duoerlapi.NewsInput, err error) {
	newsId, err := utils.ToObjectId(newsIdHex)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	dbNews, err := news.FindById(newsId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	if dbNews.AuthorId != user.Id {
		err = global.PermissionDeniedError
		return
	}

	newsInput = toNewsInput(dbNews)

	return
}
func SendEntryNotification(entryTopicData *nsqproducers.EntryTopicData) (err error) {

	serv, err := MakeWsService(entryTopicData.OrgId, entryTopicData.UserId)
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	apiEntry := entryTopicData.ApiEntry
	currentOrg := serv.CurrentOrg
	currentUser := serv.LoggedInUser

	// TODO: the db should be group db, not current org db
	db := currentOrg.Database

	entry, err := entries.FindById(db, bson.ObjectIdHex(apiEntry.Id))
	if err != nil {
		utils.PrintStackAndError(err)
		return
	}

	var entity notifications.Entity

	switch entryTopicData.Status {
	case nsqproducers.TOPIC_STATUS_CREATE, nsqproducers.TOPIC_STATUS_DELETE, nsqproducers.TOPIC_STATUS_UPDATE:
		entity = notifications.MakeEntryEntity(db, currentOrg, currentUser, entry)

	case nsqproducers.TOPIC_STATUS_LIKE, nsqproducers.TOPIC_STATUS_REMOVE_LIKE:
		hasLiked := (entryTopicData.Status == nsqproducers.TOPIC_STATUS_LIKE)
		entity = notifications.NewLikeEntity(currentOrg, currentUser, entry, hasLiked)
	}

	// currentTime := time.Now()
	causedEntry := entity.CausedEntry()
	causedEntries := entity.CausedEntries()
	eventMap := entity.Events(db)

	// Save or delete notification items
	if err := entity.HandleNotificationItems(db, eventMap); err != nil {
		utils.PrintStackAndError(err) // dont' return
	}

	orgIds := entity.GetToNotifyOrgIds()

	// Build organization map for shared group user
	orgMap := make(map[string]*organizations.Organization)
	orgs, err := organizations.FindByIds(utils.TurnPlainIdsToObjectIds(orgIds))
	if err == nil {
		for _, org := range orgs {
			orgMap[org.Id.Hex()] = org
		}
	}

	onlineUsers := GetOnlineUsersByOrgIds(orgIds)
	emailToUserMap := make(map[string]bool)

	// Handle event for each user
	for toUserId, event := range eventMap {
		// If it is Qortex Support, then the key of the eventMap is "userId-organizationId",
		// which is used to differentiate same user in different organizations
		toUserId = strings.Split(toUserId, "-")[0]

		toUserObjectId := bson.ObjectIdHex(toUserId)
		orgId := bson.ObjectIdHex(event.ToUser.OriginalOrgId)

		// don't notify anything to sender
		if currentUser.Id == toUserObjectId && entity.NotNotifySelf() {
			continue
		}

		if entity.NeedResetUserCount() {

			if causedEntries != nil {
				for _, causedEntry := range causedEntries {
					notifications.ResetCount(db, toUserObjectId, causedEntry.GroupId, orgId)
				}

			} else {
				// Reset user mycount for event user
				notifications.ResetCount(db, toUserObjectId, causedEntry.GroupId, orgId)
			}
		}

		onlineUser := pickOnlineUser(toUserObjectId, onlineUsers)
		if onlineUser == nil {

			// Don't send mail multi times to the same member when posting a Qortex Support
			_, exist := emailToUserMap[toUserId]
			if !exist && event.NeedToSendNotificationMail() {
				// Send Mail if user offline, only work in Dev and Production
				// serv.SendNotificationMail(event, apiEntry, currentTime, orgMap)
			}

		} else if entity.NeetToSendRealtimeNotification(onlineUser.User) {
			makeAndPushEventReply(currentUser, event, entity, onlineUser)
		}

		emailToUserMap[toUserId] = true
	}

	return
}