예제 #1
0
// 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
}
예제 #2
0
// 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
}
예제 #3
0
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
}
예제 #4
0
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
}
예제 #5
0
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
}
예제 #6
0
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
}
예제 #7
0
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
}
예제 #8
0
// 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)
}