1
0
Fork 0
mirror of https://git.sr.ht/~ashkeel/strimertul synced 2024-09-18 01:50:50 +00:00

feat: Add sending chat command responses as whispers/replies/announcements

This commit is contained in:
Ash Keel 2023-05-04 13:10:11 +02:00
parent f83a6c6180
commit 29880bdc23
No known key found for this signature in database
GPG key ID: BAD8D93E7314ED3E
9 changed files with 97 additions and 3 deletions

View file

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [current]
### Added
- Custom chat commands can now be sent as replies, whispers and announcements. Due to some API shenanigans yet to be solved, the latter two will always be sent from your main account, not the bot account (if they are different)
## [3.2.0] - 2023-05-03
### Added

View file

@ -116,6 +116,12 @@
"command-response-placeholder": "Hello {0}!",
"command-acl": "Access level",
"command-acl-help": "This specifies the minimum level, eg. if you choose VIPs, moderators and streamer can still use the command",
"response-types": {
"chat": "Message",
"reply": "Reply",
"whisper": "Whisper",
"announce": "Announcement"
},
"acl": {
"everyone": "Everyone",
"subscribers": "Subscribers",

View file

@ -112,7 +112,13 @@
"subscribers": "Abbonati",
"vip": "VIP"
},
"command-already-in-use": "Nome comando già in uso"
"command-already-in-use": "Nome comando già in uso",
"response-types": {
"announce": "Annuncio",
"chat": "Canale",
"reply": "Risposta",
"whisper": "Chat privata"
}
},
"bottimers": {
"add-button": "Nuovo timer",

View file

@ -34,10 +34,12 @@ export const accessLevels = [
export type AccessLevelType = (typeof accessLevels)[number];
export type ReplyType = 'chat' | 'reply' | 'whisper' | 'announce';
export interface TwitchBotCustomCommand {
description: string;
access_level: AccessLevelType;
response: string;
response_type: ReplyType;
enabled: boolean;
}

View file

@ -7,6 +7,7 @@ import { modules } from '~/store/api/reducer';
import {
accessLevels,
AccessLevelType,
ReplyType,
TwitchBotCustomCommand,
} from '~/store/api/types';
import AlertContent from '../components/AlertContent';
@ -23,6 +24,8 @@ import {
InputBox,
Label,
MultiButton,
MultiToggle,
MultiToggleItem,
NoneText,
PageContainer,
PageHeader,
@ -185,11 +188,15 @@ function CommandDialog({
const [commands] = useModule(modules.twitchBotCommands);
const [commandName, setCommandName] = useState(name ?? '');
const [description, setDescription] = useState(item?.description ?? '');
const [responseType, setResponseType] = useState(
item?.response_type ?? 'chat',
);
const [response, setResponse] = useState(item?.response ?? '');
const [accessLevel, setAccessLevel] = useState(
item?.access_level ?? 'everyone',
);
const { t } = useTranslation();
const replyTypes: ReplyType[] = ['chat', 'reply', 'whisper', 'announce'];
return (
<DialogContent
@ -207,6 +214,7 @@ function CommandDialog({
...item,
description,
response,
response_type: responseType,
access_level: accessLevel,
});
}
@ -248,6 +256,20 @@ function CommandDialog({
<Field spacing="narrow" size="fullWidth">
<Label htmlFor="command-response">
{t('pages.botcommands.command-response')}
<MultiToggle
css={{ marginLeft: '0.5rem' }}
value={responseType}
type="single"
onValueChange={(newType) => {
setResponseType(newType as ReplyType);
}}
>
{replyTypes.map((replyType) => (
<MultiToggleItem size="small" key={replyType} value={replyType}>
{t(`pages.botcommands.response-types.${replyType}`)}
</MultiToggleItem>
))}
</MultiToggle>
</Label>
<Textarea
value={response}

View file

@ -22,7 +22,7 @@ func (c *Client) GetAuthorizationURL() string {
}
return c.API.GetAuthorizationURL(&helix.AuthorizationURLParams{
ResponseType: "code",
Scopes: []string{"bits:read channel:read:subscriptions channel:read:redemptions channel:read:polls channel:read:predictions channel:read:hype_train user_read chat:read chat:edit channel:moderate whispers:read whispers:edit moderator:read:chatters moderator:read:followers"},
Scopes: []string{"bits:read channel:read:subscriptions channel:read:redemptions channel:read:polls channel:read:predictions channel:read:hype_train user_read chat:read chat:edit channel:moderate whispers:read whispers:edit moderator:read:chatters moderator:read:followers user:manage:whispers moderator:manage:announcements"},
})
}

View file

@ -58,7 +58,40 @@ func cmdCustom(bot *Bot, cmd string, data BotCustomCommand, message irc.PrivateM
bot.logger.Error("Failed to execute custom command template", zap.Error(err))
return
}
switch data.ResponseType {
case ResponseTypeDefault, ResponseTypeChat:
bot.Client.Say(message.Channel, buf.String())
case ResponseTypeReply:
bot.Client.Reply(message.Channel, message.ID, buf.String())
case ResponseTypeWhisper:
client, err := bot.api.GetUserClient(false)
reply, err := client.SendUserWhisper(&helix.SendUserWhisperParams{
FromUserID: bot.api.User.ID,
ToUserID: message.User.ID,
Message: buf.String(),
})
if reply.Error != "" {
bot.logger.Error("Failed to send whisper", zap.String("code", reply.Error), zap.String("message", reply.ErrorMessage))
}
if err != nil {
bot.logger.Error("Failed to send whisper", zap.Error(err))
}
case ResponseTypeAnnounce:
client, err := bot.api.GetUserClient(false)
reply, err := client.SendChatAnnouncement(&helix.SendChatAnnouncementParams{
BroadcasterID: bot.api.User.ID,
ModeratorID: bot.api.User.ID,
Message: buf.String(),
})
if reply.Error != "" {
bot.logger.Error("Failed to send announcement", zap.String("code", reply.Error), zap.String("message", reply.ErrorMessage))
}
if err != nil {
bot.logger.Error("Failed to send announcement", zap.Error(err))
}
}
}
func (b *Bot) setupFunctions() {

View file

@ -44,6 +44,16 @@ const (
ChatActivityKey = "twitch/chat-activity"
)
type ResponseType string
const (
ResponseTypeDefault ResponseType = ""
ResponseTypeChat ResponseType = "chat"
ResponseTypeWhisper ResponseType = "whisper"
ResponseTypeReply ResponseType = "reply"
ResponseTypeAnnounce ResponseType = "announce"
)
// BotCustomCommand is a definition of a custom command of the chatbot
type BotCustomCommand struct {
// Command description
@ -57,6 +67,9 @@ type BotCustomCommand struct {
// Is the command enabled?
Enabled bool `json:"enabled" desc:"Is the command enabled?"`
// How to respond to the user
ResponseType ResponseType `json:"response_type" desc:"How to respond to the user"`
}
const CustomCommandsKey = "twitch/bot-custom-commands"

View file

@ -80,4 +80,12 @@ var Enums = interfaces.EnumMap{
ALTStreamer,
},
},
"ResponseType": interfaces.Enum{
Values: []any{
ResponseTypeChat,
ResponseTypeReply,
ResponseTypeWhisper,
ResponseTypeAnnounce,
},
},
}