[MM-42742] Add top reactions endpoint (#19850)

Этот коммит содержится в:
Mylon Suren
2022-04-14 13:09:35 -04:00
коммит произвёл GitHub
родитель a98975b00f
Коммит 99f02fe96e
18 изменённых файлов: 1360 добавлений и 0 удалений

Просмотреть файл

@@ -6496,6 +6496,39 @@ func (c *Client4) GetBulkReactions(postIds []string) (map[string][]*Reaction, *R
return reactions, BuildResponse(r), nil
}
func (c *Client4) GetTopReactionsForTeamSince(teamId string, timeRange string, page int, perPage int) (*TopReactionList, *Response, error) {
query := fmt.Sprintf("?time_range=%v&page=%v&per_page=%v", timeRange, page, perPage)
r, err := c.DoAPIGet(c.teamRoute(teamId)+"/top/reactions"+query, "")
if err != nil {
return nil, BuildResponse(r), err
}
defer closeBody(r)
var topReactions *TopReactionList
if jsonErr := json.NewDecoder(r.Body).Decode(&topReactions); jsonErr != nil {
return nil, nil, NewAppError("GetTopReactionsForTeamSince", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
}
return topReactions, BuildResponse(r), nil
}
func (c *Client4) GetTopReactionsForUserSince(teamId string, timeRange string, page int, perPage int) (*TopReactionList, *Response, error) {
query := fmt.Sprintf("?time_range=%v&page=%v&per_page=%v", timeRange, page, perPage)
if teamId != "" {
query += fmt.Sprintf("&team_id=%v", teamId)
}
r, err := c.DoAPIGet(c.usersRoute()+"/me/top/reactions"+query, "")
if err != nil {
return nil, BuildResponse(r), err
}
defer closeBody(r)
var topReactions *TopReactionList
if jsonErr := json.NewDecoder(r.Body).Decode(&topReactions); jsonErr != nil {
return nil, nil, NewAppError("GetTopReactionsForUserSince", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
}
return topReactions, BuildResponse(r), nil
}
// Timezone Section
// GetSupportedTimezone returns a page of supported timezones on the system.

76
model/insights.go Обычный файл
Просмотреть файл

@@ -0,0 +1,76 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import (
"net/http"
"time"
)
const (
TimeRangeToday string = "today"
TimeRange7Day string = "7_day"
TimeRange28Day string = "28_day"
)
type InsightsOpts struct {
StartUnixMilli int64
Page int
PerPage int
}
type InsightsListData struct {
HasNext bool `json:"has_next"`
}
type InsightsData struct {
Rank int `json:"rank"`
}
type TopReactionList struct {
InsightsListData
Items []*TopReaction `json:"items"`
}
type TopReaction struct {
InsightsData
EmojiName string `json:"emoji_name"`
Count int64 `json:"count"`
}
// GetStartUnixMilliForTimeRange gets the unix start time in milliseconds from the given time range.
// Time range can be one of: "1_day", "7_day", or "28_day".
func GetStartUnixMilliForTimeRange(timeRange string) (int64, *AppError) {
now := time.Now()
_, offset := now.Zone()
switch timeRange {
case TimeRangeToday:
return GetStartOfDayMillis(now, offset), nil
case TimeRange7Day:
return GetStartOfDayMillis(now.Add(time.Hour*time.Duration(-168)), offset), nil
case TimeRange28Day:
return GetStartOfDayMillis(now.Add(time.Hour*time.Duration(-672)), offset), nil
}
return GetStartOfDayMillis(now, offset), NewAppError("Insights.IsValidRequest", "model.insights.time_range.app_error", nil, "", http.StatusBadRequest)
}
// GetTopReactionListWithRankAndPagination adds a rank to each item in the given list of TopReaction and checks if there is
// another page that can be fetched based on the given limit and offset. The given list of TopReaction is assumed to be
// sorted by Count. Returns a TopReactionList.
func GetTopReactionListWithRankAndPagination(reactions []*TopReaction, limit int, offset int) *TopReactionList {
// Add pagination support
var hasNext bool
if (limit != 0) && (len(reactions) == limit+1) {
hasNext = true
reactions = reactions[:len(reactions)-1]
}
// Assign rank to each reaction
for i, reaction := range reactions {
reaction.Rank = offset + i + 1
}
return &TopReactionList{InsightsListData: InsightsListData{HasNext: hasNext}, Items: reactions}
}

81
model/insights_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,81 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetStartUnixMilliForTimeRang(t *testing.T) {
tc := [3]string{"today", "7_day", "28_day"}
for _, timeRange := range tc {
t.Run(timeRange, func(t *testing.T) {
_, err := GetStartUnixMilliForTimeRange(timeRange)
assert.Nil(t, err)
})
}
invalidTimeRanges := [3]string{"", "1_day", "10_day"}
for _, timeRange := range invalidTimeRanges {
t.Run(timeRange, func(t *testing.T) {
_, err := GetStartUnixMilliForTimeRange(timeRange)
assert.NotNil(t, err)
})
}
}
func TestGetTopReactionListWithRankAndPagination(t *testing.T) {
reactions := []*TopReaction{
{EmojiName: "smile", Count: 200},
{EmojiName: "+1", Count: 190},
{EmojiName: "100", Count: 100},
{EmojiName: "-1", Count: 75},
{EmojiName: "checkmark", Count: 50},
{EmojiName: "mattermost", Count: 49}}
hasNextTC := []struct {
Description string
Limit int
Offset int
Expected *TopReactionList
}{
{
Description: "has one page",
Limit: len(reactions),
Offset: 0,
Expected: &TopReactionList{InsightsListData: InsightsListData{HasNext: false}, Items: reactions},
},
{
Description: "has more than one page",
Limit: len(reactions) - 1,
Offset: 0,
Expected: &TopReactionList{InsightsListData: InsightsListData{HasNext: true}, Items: reactions},
},
}
for _, test := range hasNextTC {
t.Run(test.Description, func(t *testing.T) {
actual := GetTopReactionListWithRankAndPagination(reactions, test.Limit, test.Offset)
assert.Equal(t, test.Expected.HasNext, actual.HasNext)
})
}
t.Run("ranks for first and second page", func(t *testing.T) {
firstPage := GetTopReactionListWithRankAndPagination(reactions, 5, 0)
for i, r := range firstPage.Items {
assert.Equal(t, i+1, r.Rank)
}
secondPage := GetTopReactionListWithRankAndPagination(reactions, 5, 5)
for i, r := range secondPage.Items {
assert.Equal(t, i+1+5, r.Rank)
}
})
}