Skip to content

Commit

Permalink
feat: add emotes statistic to dashboard (#726)
Browse files Browse the repository at this point in the history
Co-authored-by: Vitalij Ryndin <crashmax.dev@gmail.com>
  • Loading branch information
Satont and crashmax-dev authored May 5, 2024
1 parent 4cd3bff commit 84ad3a8
Show file tree
Hide file tree
Showing 46 changed files with 1,958 additions and 296 deletions.
223 changes: 223 additions & 0 deletions apps/api-gql/internal/gql/resolvers/emotes-statistic.resolver.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package resolvers

import (
"context"
"database/sql"
"fmt"
"time"

model "github.com/satont/twir/libs/gomodels"
"github.com/twirapp/twir/apps/api-gql/internal/gql/gqlmodel"
)

func (r *queryResolver) getEmoteStatisticUsagesForRange(
ctx context.Context,
emoteName string,
timeRange gqlmodel.EmoteStatisticRange,
) ([]gqlmodel.EmoteStatisticUsage, error) {
dashboardId, err := r.sessions.GetSelectedDashboard(ctx)
if err != nil {
return nil, err
}

var usages []emoteStatisticUsageModel

var interval string
var truncateBy string
switch timeRange {
case gqlmodel.EmoteStatisticRangeLastDay:
interval = "24 hours"
truncateBy = "hour"
case gqlmodel.EmoteStatisticRangeLastWeek:
interval = "7 days"
truncateBy = "day"
case gqlmodel.EmoteStatisticRangeLastMonth:
interval = "30 days"
truncateBy = "day"
case gqlmodel.EmoteStatisticRangeLastThreeMonth:
interval = "90 days"
truncateBy = "day"
case gqlmodel.EmoteStatisticRangeLastYear:
interval = "365 days"
truncateBy = "day"
default:
}

query := fmt.Sprintf(
`
SELECT
hh AS time, COUNT(emote) AS count
FROM (select
generate_series(
DATE_TRUNC(@truncate_by, NOW() - INTERVAL '%s'),
DATE_TRUNC(@truncate_by, NOW()),
INTERVAL '1 %s'
) as hh
) s
left join channels_emotes_usages on DATE_TRUNC(@truncate_by, "createdAt") = hh AND "channelId" = @dashboard_id AND emote = @emote_name
GROUP BY
time
ORDER BY
time asc;
`, interval, truncateBy,
)

if err := r.gorm.
WithContext(ctx).
Raw(
query,
sql.Named("truncate_by", truncateBy),
sql.Named("my_interval", interval),
sql.Named("dashboard_id", dashboardId),
sql.Named("emote_name", emoteName),
).
Find(&usages).Error; err != nil {
return nil, err
}

result := make([]gqlmodel.EmoteStatisticUsage, 0, len(usages))
for _, usage := range usages {
result = append(
result,
gqlmodel.EmoteStatisticUsage{
Count: usage.Count,
Timestamp: int(usage.Time.UTC().UnixMilli()),
},
)
}

return result, nil
}

type emoteEntityModelWithCount struct {
model.ChannelEmoteUsage
Count int `gorm:"column:count"`
}

type emoteStatisticUsageModel struct {
Emote string `gorm:"column:emote"`
Count int `gorm:"column:count"`
Time time.Time `gorm:"column:time"`
}
64 changes: 64 additions & 0 deletions apps/api-gql/schema/emotes-statistic.graphqls
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
extend type Query {
emotesStatistics(opts: EmotesStatisticsOpts!): EmotesStatisticResponse! @isAuthenticated
emotesStatisticEmoteDetailedInformation(opts: EmotesStatisticEmoteDetailedOpts!): EmotesStatisticEmoteDetailedResponse! @isAuthenticated
}

type EmotesStatisticResponse {
emotes: [EmotesStatistic!]!
total: Int!
}

type EmotesStatistic {
emoteName: String!
totalUsages: Int!
lastUsedTimestamp: Int!
graphicUsages: [EmoteStatisticUsage!]!
}

enum EmotesStatisticsOptsOrder {
ASC
DESC
}

input EmotesStatisticsOpts {
search: String
page: Int
perPage: Int
graphicRange: EmoteStatisticRange
order: EmotesStatisticsOptsOrder
}

enum EmoteStatisticRange {
LAST_DAY
LAST_WEEK
LAST_MONTH
LAST_THREE_MONTH
LAST_YEAR
}

input EmotesStatisticEmoteDetailedOpts {
emoteName: String!
range: EmoteStatisticRange!
usagesByUsersPage: Int
usagesByUsersPerPage: Int
}

type EmotesStatisticEmoteDetailedResponse {
emoteName: String!
totalUsages: Int!
lastUsedTimestamp: Int!
graphicUsages: [EmoteStatisticUsage!]!
usagesByUsers: [EmoteStatisticUserUsage!]!
usagesByUsersTotal: Int!
}

type EmoteStatisticUsage {
count: Int!
timestamp: Int!
}

type EmoteStatisticUserUsage {
userId: String!
twitchProfile: TwirUserTwitchInfo! @goField(forceResolver: true)
date: Time!
}
Loading

0 comments on commit 84ad3a8

Please sign in to comment.