func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) { messageId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } accountId, err := request.GetURIInt64(u, "accountId") if err != nil { return response.NewBadRequest(err) } reply := models.NewMessageReply() reply.MessageId = messageId messages, err := reply.List(request.GetQuery(u)) if err != nil { return response.NewBadRequest(err) } return response.HandleResultAndError( helpers.ConvertMessagesToMessageContainers( messages, accountId, ), ) }
func ListPosts(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { query := request.GetQuery(u) query = context.OverrideQuery(query) buildMessageQuery := query.Clone() accountId, err := request.GetId(u) if err != nil { return response.NewBadRequest(err) } c, err := models.Cache.Channel.ByGroupName(query.GroupName) if err != nil { return response.NewBadRequest(err) } // fetch only channel messages query.Type = models.ChannelMessage_TYPE_POST query.AccountId = accountId cm := models.NewChannelMessage() messages, err := cm.FetchMessagesByChannelId(c.Id, query) if err != nil { return response.NewBadRequest(err) } buildMessageQuery.Limit = 3 return response.HandleResultAndError( cm.BuildMessages(buildMessageQuery, messages), ) }
func List(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { query := context.OverrideQuery(request.GetQuery(u)) if query.Id == 0 { return response.NewBadRequest(errors.New("channel id is not set")) } c, err := models.Cache.Channel.ById(query.Id) if err != nil { return response.NewBadRequest(err) } canOpen, err := c.CanOpen(query.AccountId) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewAccessDenied(fmt.Errorf("user %d tried to open unattended channel %d", query.AccountId, query.Id)) } return response.HandleResultAndError( fetchChannelParticipants(query), ) }
func ParticipatedChannelCount(u *url.URL, h http.Header, _ interface{}, c *models.Context) (int, http.Header, interface{}, error) { accountId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if !c.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } if accountId != c.Client.Account.Id { return response.NewBadRequest(models.ErrAccessDenied) } query := request.GetQuery(u) query = c.OverrideQuery(query) if query.Type == "" { query.Type = models.Channel_TYPE_TOPIC } cp := models.NewChannelParticipant() a := &models.Account{Id: query.AccountId} return response.HandleResultAndError(cp.ParticipatedChannelCount(a, query)) }
// lists followed channels of an account func ListChannels(u *url.URL, h http.Header, _ interface{}, c *models.Context) (int, http.Header, interface{}, error) { accountId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if !c.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } if accountId != c.Client.Account.Id { return response.NewBadRequest(models.ErrAccessDenied) } query := request.GetQuery(u) query = c.OverrideQuery(query) if query.Type == "" { query.Type = models.Channel_TYPE_TOPIC } a := &models.Account{Id: accountId} channels, err := a.FetchChannels(query) if err != nil { return response.NewBadRequest(err) } cc := models.NewChannelContainers() cc.PopulateWith(channels, query.AccountId).AddUnreadCount(query.AccountId) return response.HandleResultAndError(cc, cc.Err()) }
func Get(u *url.URL, h http.Header, _ interface{}, ctx *models.Context) (int, http.Header, interface{}, error) { cm, err := getMessageByUrl(u) if err != nil { return response.NewBadRequest(err) } if cm.Id == 0 { return response.NewNotFound() } ch, err := models.Cache.Channel.ById(cm.InitialChannelId) if err != nil { response.NewBadRequest(err) } canOpen, err := ch.CanOpen(ctx.Client.Account.Id) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewAccessDenied(models.ErrCannotOpenChannel) } cmc := models.NewChannelMessageContainer() return response.HandleResultAndError(cmc, cmc.Fetch(cm.Id, request.GetQuery(u))) }
func GetWithRelated(u *url.URL, h http.Header, _ interface{}, ctx *models.Context) (int, http.Header, interface{}, error) { cm, err := getMessageByUrl(u) if err != nil { return response.NewBadRequest(err) } if cm.Id == 0 { return response.NewNotFound() } ch, err := models.Cache.Channel.ById(cm.InitialChannelId) if err != nil { return response.NewBadRequest(err) } q := request.GetQuery(u) query := ctx.OverrideQuery(q) canOpen, err := ch.CanOpen(query.AccountId) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewBadRequest(models.ErrCannotOpenChannel) } cmc := models.NewChannelMessageContainer() if err := cmc.Fetch(cm.Id, query); err != nil { return response.NewBadRequest(err) } return response.HandleResultAndError(cmc, cmc.Err) }
// GetSubscription gets the subscription of group func GetSubscription(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { if !context.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } return response.HandleResultAndError( payment.GetSubscriptionForGroup(context.GroupName), ) }
// CreateSubscription creates the subscription of group func CreateSubscription(u *url.URL, h http.Header, params *stripe.SubParams, context *models.Context) (int, http.Header, interface{}, error) { if !context.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } return response.HandleResultAndError( payment.EnsureSubscriptionForGroup(context.GroupName, params), ) }
// GetCustomer returns the customer info of a group func GetCustomer(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { if err := context.IsGroupAdmin(); err != nil { return response.NewBadRequest(err) } return response.HandleResultAndError( payment.GetCustomerForGroup(context.GroupName), ) }
// ListMembers lists the members of group func ListMembers(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { if err := context.IsGroupAdmin(); err != nil { return response.NewBadRequest(err) } query := request.GetQuery(u) query = context.OverrideQuery(query) p := &models.PresenceDaily{} return response.HandleResultAndError(p.FetchActiveAccounts(query)) }
// ByParticipants finds private message channels by their participants func ByParticipants(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { // only logged in users if !context.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } query := request.GetQuery(u) query = context.OverrideQuery(query) participantsStr, ok := u.Query()["id"] if !ok { return response.NewBadRequest(errors.New("participants not set")) } if len(participantsStr) == 0 { return response.NewBadRequest(errors.New("at least one participant is required")) } unify := make(map[string]interface{}) // add current account to participants list unify[strconv.FormatInt(context.Client.Account.Id, 10)] = struct{}{} // remove duplicates from participants for i := range participantsStr { unify[participantsStr[i]] = struct{}{} } participants := make([]int64, 0) // convert strings to int64 for participantStr := range unify { i, err := strconv.ParseInt(participantStr, 10, 64) if err != nil { return response.NewBadRequest(err) } participants = append(participants, i) } channels, err := models.NewChannel().ByParticipants(participants, query) if err != nil { if err == bongo.RecordNotFound { return response.NewNotFound() } } cc := models.NewChannelContainers(). PopulateWith(channels, context.Client.Account.Id). AddLastMessage(context.Client.Account.Id). AddUnreadCount(context.Client.Account.Id) return response.HandleResultAndError(cc, cc.Err()) }
// PostMessage posts a message to a slack channel/group func (s *Slack) PostMessage(u *url.URL, h http.Header, req *SlackMessageRequest, context *models.Context) (int, http.Header, interface{}, error) { if !context.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } token, err := getSlackToken(context) if err != nil { return response.NewBadRequest(err) } return response.HandleResultAndError(postMessage(token, req)) }
func Create(u *url.URL, h http.Header, reply *models.ChannelMessage, c *models.Context) (int, http.Header, interface{}, error) { parentId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } // fetch the parent message parent, err := models.Cache.Message.ById(parentId) if err != nil { return response.NewBadRequest(err) } parentChannel, err := models.Cache.Channel.ById(parent.InitialChannelId) if err != nil { return response.NewBadRequest(err) } canOpen, err := parentChannel.CanOpen(c.Client.Account.Id) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewAccessDenied(models.ErrCannotOpenChannel) } // first create reply as a message reply.TypeConstant = models.ChannelMessage_TYPE_REPLY // set initial channel id for message creation reply.InitialChannelId = parent.InitialChannelId reply.AccountId = c.Client.Account.Id if err := reply.Create(); err != nil { // todo this should be internal server error return response.NewBadRequest(err) } // then add this message as a reply to a parent message mr := models.NewMessageReply() mr.MessageId = parentId mr.ReplyId = reply.Id mr.CreatedAt = reply.CreatedAt mr.ClientRequestId = reply.ClientRequestId if err := mr.Create(); err != nil { // todo this should be internal server error return response.NewBadRequest(err) } return response.HandleResultAndError( reply.BuildEmptyMessageContainer(), ) }
func Send(u *url.URL, h http.Header, req *models.ChannelRequest, ctx *models.Context) (int, http.Header, interface{}, error) { // check if user logged in or not if !ctx.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } req.AccountId = ctx.Client.Account.Id req.GroupName = ctx.GroupName return response.HandleResultAndError(req.Send()) }
// ListChannels lists the channels of a slack team func (s *Slack) ListChannels(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { if !context.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } var groupToken string userToken, err := getSlackToken(context) if err != nil || userToken == "" { groupToken, err = getAnySlackTokenWithGroup(context) if err != nil { return response.NewBadRequest(err) } } if userToken != "" { return response.HandleResultAndError(getChannels(userToken)) } else { return response.HandleResultAndError(getOnlyChannels(groupToken)) } }
func Unfollow(u *url.URL, h http.Header, req *models.Account, context *models.Context) (int, http.Header, interface{}, error) { targetId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if !context.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } return response.HandleResultAndError(req.Unfollow(targetId)) }
// TeamInfo shows basic info regarding a slack team func (s *Slack) TeamInfo(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { if !context.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } token, err := getSlackToken(context) if err != nil { return response.NewBadRequest(err) } return response.HandleResultAndError(getTeamInfo(token)) }
func handleChannelListResponse(channelList []models.Channel, q *request.Query) (int, http.Header, interface{}, error) { cc := models.NewChannelContainers() if err := cc.Fetch(channelList, q); err != nil { return response.NewBadRequest(err) } cc.AddIsParticipant(q.AccountId) // TODO this should be in the channel cache by default cc.AddLastMessage(q.AccountId) return response.HandleResultAndError(cc, cc.Err()) }
// CreateCustomer creates the customer for a group func CreateCustomer(u *url.URL, h http.Header, req *stripe.CustomerParams, context *models.Context) (int, http.Header, interface{}, error) { if err := context.IsGroupAdmin(); err != nil { return response.NewBadRequest(err) } return response.HandleResultAndError( payment.EnsureCustomerForGroup( context.Client.Account.Nick, context.GroupName, req, ), ) }
// Info return usage info for a group func Info(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { if err := context.IsGroupAdmin(); err != nil { return response.NewBadRequest(err) } group, err := modelhelper.GetGroup(context.GroupName) if err != nil { return response.NewBadRequest(err) } return response.HandleResultAndError( payment.EnsureInfoForGroup(group, context.Client.Account.Nick), ) }
func List(u *url.URL, h http.Header, _ interface{}, ctx *models.Context) (int, http.Header, interface{}, error) { // check if user logged in or not if !ctx.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } query := request.GetQuery(u) q := ctx.OverrideQuery(query) channelList, err := getPrivateChannels(q) if err != nil { return response.NewBadRequest(err) } return response.HandleResultAndError(buildContainer(channelList, q)) }
func List(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { channelId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } query := request.GetQuery(u) query = context.OverrideQuery(query) c, err := models.Cache.Channel.ById(channelId) if err != nil { return response.NewBadRequest(err) } if !query.ShowExempt { query.ShowExempt = context.Client.Account.IsTroll } // if channel is exempt and user should see the // content, return not found err if c.MetaBits.Is(models.Troll) && !query.ShowExempt { return response.NewNotFound() } canOpen, err := c.CanOpen(query.AccountId) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewAccessDenied( fmt.Errorf( "account (%d) tried to retrieve the unattended private channel (%d)", query.AccountId, c.Id, )) } cml := models.NewChannelMessageList() cml.ChannelId = c.Id return response.HandleResultAndError( cml.List(query, false), ) }
func Update(u *url.URL, h http.Header, req *models.ChannelMessage, c *models.Context) (int, http.Header, interface{}, error) { if !c.IsLoggedIn() { return response.NewBadRequest(models.ErrAccessDenied) } id, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } body := req.Body payload := req.Payload if err := req.ById(id); err != nil { if err == bongo.RecordNotFound { return response.NewNotFound() } return response.NewBadRequest(err) } if req.AccountId != c.Client.Account.Id { isAdmin, err := modelhelper.IsAdmin(c.Client.Account.Nick, c.GroupName) if err != nil { return response.NewBadRequest(err) } if !isAdmin { return response.NewBadRequest(models.ErrAccessDenied) } } if req.Id == 0 { return response.NewBadRequest(err) } req.Body = body req.Payload = payload if err := req.Update(); err != nil { return response.NewBadRequest(err) } cmc := models.NewChannelMessageContainer() return response.HandleResultAndError(cmc, cmc.Fetch(id, request.GetQuery(u))) }
// ListInvoice lists invoices of group func ListInvoice(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { if err := context.IsGroupAdmin(); err != nil { return response.NewBadRequest(err) } urlQuery := u.Query() limit, _ := strconv.Atoi(urlQuery.Get("limit")) if limit == 0 { limit = 10 } return response.HandleResultAndError( payment.ListInvoicesForGroup( context.GroupName, urlQuery.Get("startingAfter"), limit, ), ) }
func handleChannelResponse(c models.Channel, q *request.Query) (int, http.Header, interface{}, error) { // add troll mode filter if c.MetaBits.Is(models.Troll) && !q.ShowExempt { return response.NewNotFound() } canOpen, err := c.CanOpen(q.AccountId) if err != nil { return response.NewBadRequest(err) } if !canOpen { cp := models.NewChannelParticipant() cp.ChannelId = c.Id isInvited, err := cp.IsInvited(q.AccountId) if err != nil { return response.NewBadRequest(err) } if !isInvited { return response.NewAccessDenied( fmt.Errorf( "account (%d) tried to retrieve the unattended channel (%d)", q.AccountId, c.Id, ), ) } } cc := models.NewChannelContainer() if err := cc.Fetch(c.GetId(), q); err != nil { return response.NewBadRequest(err) } cc.AddIsParticipant(q.AccountId) // TODO this should be in the channel cache by default cc.AddLastMessage(q.AccountId) cc.AddUnreadCount(q.AccountId) return response.HandleResultAndError(cc, cc.Err) }
func ListGroupChannels(u *url.URL, h http.Header, _ interface{}, c *models.Context) (int, http.Header, interface{}, error) { if !c.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } cp := models.NewChannelParticipant() cids, err := cp.FetchAllParticipatedChannelIdsInGroup(c.Client.Account.Id, c.GroupName) if err != nil { return response.NewBadRequest(err) } channels, err := models.NewChannel().FetchByIds(cids) if err != nil { return response.NewBadRequest(err) } cc := models.NewChannelContainers() cc.PopulateWith(channels, c.Client.Account.Id) return response.HandleResultAndError(cc, cc.Err()) }
func GetBySlug(u *url.URL, h http.Header, _ interface{}, ctx *models.Context) (int, http.Header, interface{}, error) { q := request.GetQuery(u) if q.Slug == "" { return response.NewBadRequest(errors.New("slug is not set")) } cm := models.NewChannelMessage() if err := cm.BySlug(q); err != nil { if err == bongo.RecordNotFound { return response.NewNotFound() } return response.NewBadRequest(err) } ch := models.NewChannel() if err := ch.ById(cm.InitialChannelId); err != nil { return response.NewBadRequest(err) } query := ctx.OverrideQuery(q) // check if user can open canOpen, err := ch.CanOpen(query.AccountId) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewBadRequest(models.ErrCannotOpenChannel) } cmc := models.NewChannelMessageContainer() if err := cmc.Fetch(cm.Id, query); err != nil { return response.NewBadRequest(err) } return response.HandleResultAndError(cmc, cmc.Err) }
func Create(u *url.URL, h http.Header, req *models.ChannelMessage, c *models.Context) (int, http.Header, interface{}, error) { if !c.IsLoggedIn() { return response.NewBadRequest(models.ErrAccessDenied) } channelId, err := fetchInitialChannelId(u, c) if err != nil { return response.NewBadRequest(err) } ch := models.NewChannel() if err := ch.ById(channelId); err != nil { return response.NewBadRequest(models.ErrChannelNotFound) } canOpen, err := ch.CanOpen(c.Client.Account.Id) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewBadRequest(models.ErrCannotOpenChannel) } // override message type // all of the messages coming from client-side // should be marked as POST req.TypeConstant = models.ChannelMessage_TYPE_POST req.InitialChannelId = channelId req.AccountId = c.Client.Account.Id if req.Payload == nil { req.Payload = gorm.Hstore{} } if c.Client.Account.IsShareLocationEnabled() { // gets the IP of the Client // and adds it to the payload of the ChannelMessage location := parseLocation(c) req.Payload["location"] = location } if err := checkThrottle(channelId, req.AccountId); err != nil { return response.NewBadRequest(err) } if err := req.Create(); err != nil { // todo this should be internal server error return response.NewBadRequest(err) } cml := models.NewChannelMessageList() // override channel id cml.ChannelId = channelId cml.MessageId = req.Id cml.ClientRequestId = req.ClientRequestId if err := cml.Create(); err != nil && !models.IsUniqueConstraintError(err) { // todo this should be internal server error return response.NewBadRequest(err) } cmc := models.NewChannelMessageContainer() err = cmc.Fetch(req.Id, request.GetQuery(u)) if err != nil { return response.NewBadRequest(err) } // assign client request id back to message response because // client uses it for latency compansation cmc.Message.ClientRequestId = req.ClientRequestId return response.HandleResultAndError(cmc, err) }