// FetchParticipantIds gives ID of the accounts which ids are active in the channel func (c *Channel) FetchParticipantIds(q *request.Query) ([]int64, error) { var participantIds []int64 if c.Id == 0 { return participantIds, ErrChannelIdIsNotSet } cp := NewChannelParticipant() bq := bongo.B.DB. Table(cp.BongoName()). Where("channel_id = ?", c.Id). Where("status_constant in (?)", []string{ChannelParticipant_STATUS_ACTIVE, ChannelParticipant_STATUS_REQUEST_PENDING, }) if !q.ShowExempt { bq = bq.Where("meta_bits <> ?", Troll) } res := bq.Pluck("account_id", &participantIds) if err := bongo.CheckErr(res); err != nil { return nil, err } return participantIds, nil }
// fetchDefaultChannels fetchs the default channels of the system, currently we // have two different default channels, group channel and announcement channel // that everyone in the system should be a member of them, they cannot opt-out, // they will be able to see the contents of it, they will get the notifications, // they will see the unread count func (c *ChannelParticipant) fetchDefaultChannels(q *request.Query) ([]int64, error) { var channels []Channel channel := NewChannel() res := bongo.B.DB. Model(channel). Table(channel.BongoName()). Where( "group_name = ? AND type_constant IN (?)", q.GroupName, []string{Channel_TYPE_GROUP, Channel_TYPE_ANNOUNCEMENT}, ). // Order("type_constant ASC"). // order by increases query plan by x12K // no need to traverse all database, limit with a known count Limit(2). // only select ids Find(&channels) if err := bongo.CheckErr(res); err != nil { return nil, err } // be sure that this account is a participant of default channels if err := c.ensureParticipation(q.AccountId, channels); err != nil { return nil, err } // order channels in memory instead of ordering them in db channelIds := make([]int64, len(channels)) switch len(channels) { case 1: // we can have one result if group doesnt have announcement channel channelIds[0] = channels[0].Id case 2: for _, channel := range channels { if channel.TypeConstant == Channel_TYPE_GROUP { channelIds[0] = channel.Id } if channel.TypeConstant == Channel_TYPE_ANNOUNCEMENT { channelIds[1] = channel.Id } } default: return nil, nil } return channelIds, nil }
func FetchAccountsByNicks(nicks []string) ([]Account, error) { var accounts []Account if len(nicks) == 0 { return accounts, nil } a := NewAccount() res := bongo.B.DB. Table(a.BongoName()). Where("nick in (?)", nicks).Find(&accounts) if err := bongo.CheckErr(res); err != nil { return nil, err } return accounts, nil }
func (c *ChannelMessageList) getMessages(q *request.Query) ([]*ChannelMessageContainer, error) { if c.ChannelId == 0 { return nil, ErrChannelIdIsNotSet } query := &bongo.Query{ Selector: map[string]interface{}{ "channel_id": c.ChannelId, }, Pluck: "message_id", Pagination: *bongo.NewPagination(q.Limit, q.Skip), } query.AddScope(RemoveTrollContent(c, q.ShowExempt)) if q.SortOrder == "ASC" { query.AddScope(SortedByAddedAtASC) } else { query.AddScope(SortedByAddedAt) } bongoQuery := bongo.B.BuildQuery(c, query) if !q.From.IsZero() { if q.SortOrder == "ASC" { bongoQuery = bongoQuery.Where("added_at > ?", q.From) } else { bongoQuery = bongoQuery.Where("added_at < ?", q.From) } } var messages []int64 if err := bongo.CheckErr( bongoQuery.Pluck(query.Pluck, &messages), ); err != nil { return nil, err } populatedChannelMessages, err := c.PopulateChannelMessages(messages, q) if err != nil { return nil, err } return populatedChannelMessages, nil }
func (a *Account) FetchFollowerChannelIds(q *request.Query) ([]int64, error) { followerIds, err := a.FetchFollowerIds(q) if err != nil { return nil, err } cp := NewChannelParticipant() var channelIds []int64 res := bongo.B.DB. Table(cp.BongoName()). Where( "creator_id IN (?) and type_constant = ?", followerIds, Channel_TYPE_FOLLOWINGFEED, ).Find(&channelIds) if err := bongo.CheckErr(res); err != nil { return nil, err } return channelIds, nil }
func (c *Channel) Search(q *request.Query) ([]Channel, error) { if q.GroupName == "" { return nil, ErrGroupNameIsNotSet } if q.Type == "" { q.Type = Channel_TYPE_TOPIC } var channels []Channel bongoQuery := &bongo.Query{ Selector: map[string]interface{}{ "group_name": q.GroupName, "type_constant": q.Type, }, Pagination: *bongo.NewPagination(q.Limit, q.Skip), } bongoQuery.AddScope(RemoveTrollContent(c, q.ShowExempt)) query := bongo.B.BuildQuery(c, bongoQuery) // use 'ilike' for case-insensitive search query = query.Where("name ilike ?", "%"+q.Name+"%") if err := bongo.CheckErr( query.Find(&channels), ); err != nil { return nil, err } if channels == nil { return make([]Channel, 0), nil } return channels, nil }
func (m *MessageReply) fetchMessages(query *request.Query) ([]ChannelMessage, error) { if m.MessageId == 0 { return nil, ErrMessageIdIsNotSet } q := &bongo.Query{ Selector: map[string]interface{}{ "message_id": m.MessageId, }, Pluck: "reply_id", Pagination: *bongo.NewPagination(query.Limit, query.Skip), Sort: map[string]string{"created_at": "DESC"}, } q.AddScope(RemoveTrollContent(m, query.ShowExempt)) bongoQuery := bongo.B.BuildQuery(m, q) if !query.From.IsZero() { bongoQuery = bongoQuery.Where("created_at < ?", query.From) } var replies []int64 if err := bongo.CheckErr( bongoQuery.Pluck(q.Pluck, &replies), ); err != nil { return nil, err } parent := NewChannelMessage() channelMessageReplies, err := parent.FetchByIds(replies) if err != nil { return nil, err } return channelMessageReplies, nil }
// this is a TEMP function just for @usirin func TempList(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 channel is exempt and user should see the // content, return not found err if !query.ShowExempt { query.ShowExempt = context.Client.Account.IsTroll } if c.MetaBits.Is(models.Troll) && !query.ShowExempt { return response.NewNotFound() } // check if channel is accessible by the requester 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, )) } bq := &bongo.Query{ Selector: map[string]interface{}{ "initial_channel_id": c.Id, }, Pagination: *bongo.NewPagination(query.Limit, query.Skip), Pluck: "id", } bq.AddScope(models.SortedByCreatedAt) bq.AddScope(models.RemoveTrollContent(c, query.ShowExempt)) bq.AddScope(models.ExcludeFields(query.Exclude)) bq.AddScope(models.TillTo(query.From)) bqq := bongo.B.BuildQuery(models.NewChannelMessage(), bq) var messages []int64 if err := bongo.CheckErr( bqq.Pluck(bq.Pluck, &messages), ); err != nil { return response.NewBadRequest(err) } // get the messages in regarding channel cmcs, err := models. NewChannelMessageList(). PopulateChannelMessages( messages, query, ) if err != nil { return response.NewBadRequest(err) } // reduce replies replyIds := make([]int64, 0) for i := range cmcs { cmc := cmcs[i] if cmc.Message.TypeConstant == models.ChannelMessage_TYPE_REPLY { replyIds = append(replyIds, cmc.Message.Id) } } if len(replyIds) == 0 { return response.NewOK(cmcs) } // select replies var mrs []models.MessageReply gerr := bongo.B. BuildQuery(models.NewMessageReply(), &bongo.Query{}). Where("reply_id in (?)", replyIds). Find(&mrs) if err := bongo.CheckErr(gerr); err != nil { return response.NewBadRequest(err) } // set their parent ids for j, mr := range mrs { for i := range cmcs { if mr.ReplyId == cmcs[i].Message.Id { cmcs[i].ParentID = mrs[j].MessageId } } } // send response return response.NewOK(cmcs) }