Skip to content

Commit

Permalink
feat: add category bound responses of commands
Browse files Browse the repository at this point in the history
fixes #739
  • Loading branch information
Satont committed Jul 8, 2024
1 parent 288c9bb commit b4c04d8
Show file tree
Hide file tree
Showing 17 changed files with 9,487 additions and 6,987 deletions.
3 changes: 3 additions & 0 deletions apps/api-gql/gqlgen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,6 @@ models:
DateTime:
model:
- github.com/99designs/gqlgen/graphql.Time
UUID:
model:
- github.com/99designs/gqlgen/graphql.UUID
61 changes: 50 additions & 11 deletions apps/api-gql/internal/gql/resolvers/commands.resolver.go

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

5 changes: 4 additions & 1 deletion apps/api-gql/schema/commands.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ type CommandResponse {
commandId: ID!
text: String!
order: Int!
twitchCategoriesIds: [String!]!
twitchCategories: [TwitchCategory!]! @goField(forceResolver: true)
}

type PublicCommand {
Expand Down Expand Up @@ -106,5 +108,6 @@ input CommandsUpdateOpts {

input CreateOrUpdateCommandResponseInput {
text: String! @validate(constraint: "max=500")
order: Int!
order: Int! @validate(constraint: "max=500")
twitchCategoriesIds: [String!]! @validate(constraint: "max=500")
}
1 change: 1 addition & 0 deletions apps/api-gql/schema/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ directive @validate(constraint: String!) on INPUT_FIELD_DEFINITION | ARGUMENT_DE

scalar Upload
scalar Time
scalar UUID
7 changes: 7 additions & 0 deletions apps/api-gql/schema/twitch.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,10 @@ type TwirTwitchChannelBadgeResponse {
type TwirTwitchGlobalBadgeResponse {
badges: [TwitchBadge!]!
}


type TwitchCategory {
id: String!
name: String!
boxArtUrl: String!
}
8 changes: 8 additions & 0 deletions apps/api/internal/impl_protected/twitch/twitch.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ func (c *Twitch) TwitchSearchCategories(
) (*twitch_protected.SearchCategoriesResponse, error) {
selectedDashboardId := c.SessionManager.Get(ctx, "dashboardId").(string)

if req.Query == "" {
return nil, fmt.Errorf("query is required")
}

twitchClient, err := twitch.NewUserClientWithContext(
ctx,
selectedDashboardId,
Expand Down Expand Up @@ -114,6 +118,10 @@ func (c *Twitch) TwitchGetCategories(
return nil, err
}

if len(req.Ids) == 0 {
return &twitch_protected.SearchCategoriesResponse{}, nil
}

twitchClient, err := twitch.NewUserClientWithContext(
ctx,
dashboardId,
Expand Down
32 changes: 31 additions & 1 deletion apps/parser/internal/commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"github.com/twirapp/twir/libs/grpc/events"
"github.com/twirapp/twir/libs/grpc/websockets"
"go.uber.org/zap"
"gorm.io/gorm"
)

type Commands struct {
Expand Down Expand Up @@ -309,6 +310,18 @@ func (c *Commands) ParseCommandResponses(
Command: command.Cmd,
}

channelStream := model.ChannelsStreams{}
if err := c.services.Gorm.WithContext(ctx).First(&channelStream).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
c.services.Logger.Sugar().Error(
"error happened on getting channel stream",
zap.Error(err),
zap.String("channel_id", requestData.BroadcasterUserId),
)
return nil
}
}

if command.Cmd.Default && defaultCommand != nil {
argsParser, err := command_arguments.NewParser(defaultCommand.Args, params)
if err != nil {
Expand Down Expand Up @@ -364,8 +377,25 @@ func (c *Commands) ParseCommandResponses(
},
)
} else {
responsesForCategory := make([]model.ChannelsCommandsResponses, 0, len(command.Cmd.Responses))
for _, r := range command.Cmd.Responses {
if len(r.TwitchCategoryIDs) > 0 && channelStream.ID != "" {
if !lo.ContainsBy(
r.TwitchCategoryIDs,
func(categoryId string) bool {
return categoryId == channelStream.GameId
},
) {
continue
}
}

responsesForCategory = append(responsesForCategory, *r)
}

result.Responses = lo.Map(
command.Cmd.Responses, func(r *model.ChannelsCommandsResponses, _ int) string {
responsesForCategory,
func(r model.ChannelsCommandsResponses, _ int) string {
return r.Text.String
},
)
Expand Down
4 changes: 3 additions & 1 deletion frontend/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"preview": "vite preview",
"analyze": "vite-bundle-visualizer",
"generate-pwa-assets": "pwa-assets-generator",
"codegen": "graphql-codegen"
"codegen": "graphql-codegen",
"shadcn": "shadcn-vue"
},
"dependencies": {
"@discord-message-components/vue": "0.2.1",
Expand Down Expand Up @@ -76,6 +77,7 @@
"autoprefixer": "10.4.19",
"rollup-plugin-visualizer": "5.12.0",
"sass": "1.75.0",
"shadcn-vue": "0.10.5",
"tailwindcss": "3.4.3",
"type-fest": "4.15.0",
"typescript": "5.4.5",
Expand Down
6 changes: 6 additions & 0 deletions frontend/dashboard/src/api/commands/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export const useCommandsApi = createGlobalState(() => {
commandId
text
order
twitchCategoriesIds
twitchCategories {
id
name
boxArtUrl
}
}
cooldown
cooldownType
Expand Down
47 changes: 25 additions & 22 deletions frontend/dashboard/src/components/twitch-category-search.vue
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
<script setup lang="ts">
import { refDebounced } from '@vueuse/core';
import { NSelect, SelectOption } from 'naive-ui';
import { computed, h, ref, VNodeChild, watch } from 'vue';
import { refDebounced } from '@vueuse/core'
import { NSelect } from 'naive-ui'
import { computed, h, ref, watch } from 'vue'
import { useTwitchGetCategories, useTwitchSearchCategories } from '@/api';
import type { SelectOption } from 'naive-ui'
import type { VNodeChild } from 'vue'
import { useTwitchGetCategories, useTwitchSearchCategories } from '@/api'
defineProps<{
multiple?: boolean
}>();
const category = defineModel<string | string[]>();
}>()
const category = defineModel<undefined | null | string | string[]>()
const categoriesSearch = ref('');
const categoriesSearchDebounced = refDebounced(categoriesSearch, 500);
const categoriesSearch = ref('')
const categoriesSearchDebounced = refDebounced(categoriesSearch, 500)
const {
data: searchCategoriesData,
isLoading: isSearchCategoriesLoading,
} = useTwitchSearchCategories(categoriesSearchDebounced);
} = useTwitchSearchCategories(categoriesSearchDebounced)
const getCategoriesRef = ref<string[]>([]);
const getCategoriesRef = ref<string[]>([])
watch(() => category.value, (v) => {
if (!v) return [];
getCategoriesRef.value = Array.isArray(v) ? v : [v];
}, { immediate: true, once: true });
if (!v) return []
getCategoriesRef.value = Array.isArray(v) ? v : [v]
}, { immediate: true, once: true })
const {
data: getCategoriesData,
isLoading: isGetCategoriesLoading,
} = useTwitchGetCategories(getCategoriesRef);
} = useTwitchGetCategories(getCategoriesRef)
const categoriesOptions = computed(() => {
return [
Expand All @@ -40,10 +43,10 @@ const categoriesOptions = computed(() => {
value: c.id,
image: c.image.replace('{width}', '144').replace('{height}', '192'),
})) ?? [],
];
});
]
})
const renderCategory = (o: SelectOption & { image?: string }): VNodeChild => {
function renderCategory(o: SelectOption & { image?: string }): VNodeChild {
return [h(
'div',
{ class: 'flex gap-2.5 h-24 items-center' },
Expand All @@ -54,22 +57,22 @@ const renderCategory = (o: SelectOption & { image?: string }): VNodeChild => {
}),
h('span', {}, o.label! as string),
],
)];
};
)]
}
</script>

<template>
<n-select
<NSelect
v-model:value="category"
filterable
placeholder="Search..."
placeholder="Search for category..."
:options="categoriesOptions"
remote
:multiple
:render-label="renderCategory"
:loading="isSearchCategoriesLoading || isGetCategoriesLoading"
:render-tag="(t) => t.option.label as string ?? ''"
clearable
@search="(v) => categoriesSearch = v"
/>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const defaultFormValue: EditableCommand = {
{
text: '',
order: 0,
twitchCategoriesIds: [],
},
],
description: '',
Expand Down Expand Up @@ -88,6 +89,7 @@ export const useCommandEdit = createGlobalState(() => {
responses: formValue.value.responses.map((response, i) => ({
text: response.text,
order: i,
twitchCategoriesIds: response.twitchCategoriesIds,
})),
}

Expand Down
Loading

0 comments on commit b4c04d8

Please sign in to comment.