mirror of
https://git.sr.ht/~ashkeel/strimertul
synced 2024-09-20 02:00:49 +00:00
Add alerts (missing variations)
This commit is contained in:
parent
41a150c343
commit
4a10599021
5 changed files with 309 additions and 5 deletions
|
@ -150,6 +150,17 @@
|
||||||
"no-pwd-note": " If the database has no password (for example, it was recently changed from having one to none), leave the field empty.",
|
"no-pwd-note": " If the database has no password (for example, it was recently changed from having one to none), leave the field empty.",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"submit": "Authenticate"
|
"submit": "Authenticate"
|
||||||
|
},
|
||||||
|
"alerts": {
|
||||||
|
"title": "Chat alerts",
|
||||||
|
"desc": "Send chat messages when your viewers follow, subscribe and other events",
|
||||||
|
"follow-enable": "Enable new follow message",
|
||||||
|
"messages": "Messages",
|
||||||
|
"msg-info": "If multiple messages are present, one will be picked at random",
|
||||||
|
"subscription-enable": "Enable subscription message",
|
||||||
|
"gift_sub-enable": "Enable gifted subscription message",
|
||||||
|
"raid-enable": "Enable raid message",
|
||||||
|
"cheer-enable": "Enable cheering message"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"form-actions": {
|
"form-actions": {
|
||||||
|
|
|
@ -29,6 +29,7 @@ import TwitchSettingsPage from './pages/TwitchSettings';
|
||||||
import TwitchBotCommandsPage from './pages/BotCommands';
|
import TwitchBotCommandsPage from './pages/BotCommands';
|
||||||
import TwitchBotTimersPage from './pages/BotTimers';
|
import TwitchBotTimersPage from './pages/BotTimers';
|
||||||
import AuthDialog from './pages/AuthDialog';
|
import AuthDialog from './pages/AuthDialog';
|
||||||
|
import ChatAlertsPage from './pages/ChatAlerts';
|
||||||
|
|
||||||
const LoadingDiv = styled('div', {
|
const LoadingDiv = styled('div', {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
@ -188,6 +189,7 @@ export default function App(): JSX.Element {
|
||||||
path="/twitch/bot/timers"
|
path="/twitch/bot/timers"
|
||||||
element={<TwitchBotTimersPage />}
|
element={<TwitchBotTimersPage />}
|
||||||
/>
|
/>
|
||||||
|
<Route path="/twitch/bot/alerts" element={<ChatAlertsPage />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
|
|
|
@ -3,19 +3,21 @@ import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, FlexRow, Textarea } from '../theme';
|
import { Button, FlexRow, Textarea } from '../theme';
|
||||||
|
|
||||||
export interface MessageArrayProps {
|
export interface MultiInputProps {
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
value: string[];
|
value: string[];
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
onChange: (value: string[]) => void;
|
onChange: (value: string[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MessageArray({
|
function MultiInput({
|
||||||
value,
|
value,
|
||||||
placeholder,
|
placeholder,
|
||||||
onChange,
|
onChange,
|
||||||
required,
|
required,
|
||||||
}: MessageArrayProps) {
|
disabled,
|
||||||
|
}: MultiInputProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -27,6 +29,7 @@ function MessageArray({
|
||||||
>
|
>
|
||||||
<FlexRow border="form" css={{ flex: 1, alignItems: 'stretch' }}>
|
<FlexRow border="form" css={{ flex: 1, alignItems: 'stretch' }}>
|
||||||
<Textarea
|
<Textarea
|
||||||
|
disabled={disabled}
|
||||||
border="none"
|
border="none"
|
||||||
required={required}
|
required={required}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
@ -50,6 +53,7 @@ function MessageArray({
|
||||||
</Textarea>
|
</Textarea>
|
||||||
{value.length > 1 && (
|
{value.length > 1 && (
|
||||||
<Button
|
<Button
|
||||||
|
disabled={disabled}
|
||||||
type="button"
|
type="button"
|
||||||
variation="danger"
|
variation="danger"
|
||||||
styling="form"
|
styling="form"
|
||||||
|
@ -71,6 +75,7 @@ function MessageArray({
|
||||||
))}
|
))}
|
||||||
<FlexRow align="left">
|
<FlexRow align="left">
|
||||||
<Button
|
<Button
|
||||||
|
disabled={disabled}
|
||||||
size="small"
|
size="small"
|
||||||
styling="link"
|
styling="link"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -86,4 +91,4 @@ function MessageArray({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default React.memo(MessageArray);
|
export default React.memo(MultiInput);
|
||||||
|
|
286
frontend/src/ui/pages/ChatAlerts.tsx
Normal file
286
frontend/src/ui/pages/ChatAlerts.tsx
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { CheckIcon } from '@radix-ui/react-icons';
|
||||||
|
import { useModule, useStatus } from '../../lib/react-utils';
|
||||||
|
import { modules } from '../../store/api/reducer';
|
||||||
|
import MultiInput from '../components/MultiInput';
|
||||||
|
import {
|
||||||
|
Checkbox,
|
||||||
|
CheckboxIndicator,
|
||||||
|
Field,
|
||||||
|
FlexRow,
|
||||||
|
Label,
|
||||||
|
PageContainer,
|
||||||
|
PageHeader,
|
||||||
|
PageTitle,
|
||||||
|
TabButton,
|
||||||
|
TabContainer,
|
||||||
|
TabContent,
|
||||||
|
TabList,
|
||||||
|
TextBlock,
|
||||||
|
} from '../theme';
|
||||||
|
|
||||||
|
export default function ChatAlertsPage(): React.ReactElement {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [alerts, setAlerts] = useModule(modules.twitchBotAlerts);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContainer>
|
||||||
|
<form
|
||||||
|
onSubmit={(ev) => {
|
||||||
|
dispatch(setAlerts(alerts));
|
||||||
|
ev.preventDefault();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PageHeader>
|
||||||
|
<PageTitle>{t('pages.alerts.title')}</PageTitle>
|
||||||
|
<TextBlock>{t('pages.alerts.desc')}</TextBlock>
|
||||||
|
</PageHeader>
|
||||||
|
<TabContainer defaultValue="follow">
|
||||||
|
<TabList>
|
||||||
|
<TabButton value="follow">New follow</TabButton>
|
||||||
|
<TabButton value="sub">Subscription</TabButton>
|
||||||
|
<TabButton value="gift">Gift sub</TabButton>
|
||||||
|
<TabButton value="raid">Raid</TabButton>
|
||||||
|
<TabButton value="cheer">Cheer</TabButton>
|
||||||
|
</TabList>
|
||||||
|
<TabContent value="follow">
|
||||||
|
<Field size="fullWidth">
|
||||||
|
<FlexRow spacing={1} align="left">
|
||||||
|
<Checkbox
|
||||||
|
checked={alerts?.follow?.enabled ?? false}
|
||||||
|
onCheckedChange={(ev) =>
|
||||||
|
dispatch(
|
||||||
|
setAlerts({
|
||||||
|
...alerts,
|
||||||
|
follow: {
|
||||||
|
...alerts.follow,
|
||||||
|
enabled: !!ev,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
id="follow-enabled"
|
||||||
|
>
|
||||||
|
<CheckboxIndicator>
|
||||||
|
{alerts?.follow?.enabled && <CheckIcon />}
|
||||||
|
</CheckboxIndicator>
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
<Label htmlFor="follow-enabled">
|
||||||
|
{t('pages.alerts.follow-enable')}
|
||||||
|
</Label>
|
||||||
|
</FlexRow>
|
||||||
|
</Field>
|
||||||
|
<Field size="fullWidth">
|
||||||
|
<Label>{t('pages.alerts.messages')}</Label>
|
||||||
|
<small>{t('pages.alerts.msg-info')}</small>
|
||||||
|
<MultiInput
|
||||||
|
value={alerts?.follow?.messages ?? ['']}
|
||||||
|
disabled={!alerts?.follow?.enabled ?? true}
|
||||||
|
required={alerts?.follow?.enabled ?? false}
|
||||||
|
onChange={(messages) => {
|
||||||
|
dispatch(
|
||||||
|
setAlerts({
|
||||||
|
...alerts,
|
||||||
|
follow: { ...alerts.follow, messages },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</TabContent>
|
||||||
|
<TabContent value="sub">
|
||||||
|
<Field size="fullWidth">
|
||||||
|
<FlexRow spacing={1} align="left">
|
||||||
|
<Checkbox
|
||||||
|
checked={alerts?.subscription?.enabled ?? false}
|
||||||
|
onCheckedChange={(ev) =>
|
||||||
|
dispatch(
|
||||||
|
setAlerts({
|
||||||
|
...alerts,
|
||||||
|
subscription: {
|
||||||
|
...alerts.subscription,
|
||||||
|
enabled: !!ev,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
id="subscription-enabled"
|
||||||
|
>
|
||||||
|
<CheckboxIndicator>
|
||||||
|
{alerts?.subscription?.enabled && <CheckIcon />}
|
||||||
|
</CheckboxIndicator>
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
<Label htmlFor="subscription-enabled">
|
||||||
|
{t('pages.alerts.subscription-enable')}
|
||||||
|
</Label>
|
||||||
|
</FlexRow>
|
||||||
|
</Field>
|
||||||
|
<Field size="fullWidth">
|
||||||
|
<Label>{t('pages.alerts.messages')}</Label>
|
||||||
|
<small>{t('pages.alerts.msg-info')}</small>
|
||||||
|
<MultiInput
|
||||||
|
value={alerts?.subscription?.messages ?? ['']}
|
||||||
|
disabled={!alerts?.subscription?.enabled ?? true}
|
||||||
|
required={alerts?.subscription?.enabled ?? false}
|
||||||
|
onChange={(messages) => {
|
||||||
|
dispatch(
|
||||||
|
setAlerts({
|
||||||
|
...alerts,
|
||||||
|
subscription: { ...alerts.subscription, messages },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</TabContent>
|
||||||
|
|
||||||
|
<TabContent value="gift">
|
||||||
|
<Field size="fullWidth">
|
||||||
|
<FlexRow spacing={1} align="left">
|
||||||
|
<Checkbox
|
||||||
|
checked={alerts?.gift_sub?.enabled ?? false}
|
||||||
|
onCheckedChange={(ev) =>
|
||||||
|
dispatch(
|
||||||
|
setAlerts({
|
||||||
|
...alerts,
|
||||||
|
gift_sub: {
|
||||||
|
...alerts.gift_sub,
|
||||||
|
enabled: !!ev,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
id="gift_sub-enabled"
|
||||||
|
>
|
||||||
|
<CheckboxIndicator>
|
||||||
|
{alerts?.gift_sub?.enabled && <CheckIcon />}
|
||||||
|
</CheckboxIndicator>
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
<Label htmlFor="gift_sub-enabled">
|
||||||
|
{t('pages.alerts.gift_sub-enable')}
|
||||||
|
</Label>
|
||||||
|
</FlexRow>
|
||||||
|
</Field>
|
||||||
|
<Field size="fullWidth">
|
||||||
|
<Label>{t('pages.alerts.messages')}</Label>
|
||||||
|
<small>{t('pages.alerts.msg-info')}</small>
|
||||||
|
<MultiInput
|
||||||
|
value={alerts?.gift_sub?.messages ?? ['']}
|
||||||
|
disabled={!alerts?.gift_sub?.enabled ?? true}
|
||||||
|
required={alerts?.gift_sub?.enabled ?? false}
|
||||||
|
onChange={(messages) => {
|
||||||
|
dispatch(
|
||||||
|
setAlerts({
|
||||||
|
...alerts,
|
||||||
|
gift_sub: { ...alerts.gift_sub, messages },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</TabContent>
|
||||||
|
|
||||||
|
<TabContent value="raid">
|
||||||
|
<Field size="fullWidth">
|
||||||
|
<FlexRow spacing={1} align="left">
|
||||||
|
<Checkbox
|
||||||
|
checked={alerts?.raid?.enabled ?? false}
|
||||||
|
onCheckedChange={(ev) =>
|
||||||
|
dispatch(
|
||||||
|
setAlerts({
|
||||||
|
...alerts,
|
||||||
|
raid: {
|
||||||
|
...alerts.raid,
|
||||||
|
enabled: !!ev,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
id="raid-enabled"
|
||||||
|
>
|
||||||
|
<CheckboxIndicator>
|
||||||
|
{alerts?.raid?.enabled && <CheckIcon />}
|
||||||
|
</CheckboxIndicator>
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
<Label htmlFor="raid-enabled">
|
||||||
|
{t('pages.alerts.raid-enable')}
|
||||||
|
</Label>
|
||||||
|
</FlexRow>
|
||||||
|
</Field>
|
||||||
|
<Field size="fullWidth">
|
||||||
|
<Label>{t('pages.alerts.messages')}</Label>
|
||||||
|
<small>{t('pages.alerts.msg-info')}</small>
|
||||||
|
<MultiInput
|
||||||
|
value={alerts?.raid?.messages ?? ['']}
|
||||||
|
disabled={!alerts?.raid?.enabled ?? true}
|
||||||
|
required={alerts?.raid?.enabled ?? false}
|
||||||
|
onChange={(messages) => {
|
||||||
|
dispatch(
|
||||||
|
setAlerts({
|
||||||
|
...alerts,
|
||||||
|
raid: { ...alerts.raid, messages },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</TabContent>
|
||||||
|
|
||||||
|
<TabContent value="cheer">
|
||||||
|
<Field size="fullWidth">
|
||||||
|
<FlexRow spacing={1} align="left">
|
||||||
|
<Checkbox
|
||||||
|
checked={alerts?.cheer?.enabled ?? false}
|
||||||
|
onCheckedChange={(ev) =>
|
||||||
|
dispatch(
|
||||||
|
setAlerts({
|
||||||
|
...alerts,
|
||||||
|
cheer: {
|
||||||
|
...alerts.cheer,
|
||||||
|
enabled: !!ev,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
id="raid-enabled"
|
||||||
|
>
|
||||||
|
<CheckboxIndicator>
|
||||||
|
{alerts?.cheer?.enabled && <CheckIcon />}
|
||||||
|
</CheckboxIndicator>
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
<Label htmlFor="cheer-enabled">
|
||||||
|
{t('pages.alerts.cheer-enable')}
|
||||||
|
</Label>
|
||||||
|
</FlexRow>
|
||||||
|
</Field>
|
||||||
|
<Field size="fullWidth">
|
||||||
|
<Label>{t('pages.alerts.messages')}</Label>
|
||||||
|
<small>{t('pages.alerts.msg-info')}</small>
|
||||||
|
<MultiInput
|
||||||
|
value={alerts?.cheer?.messages ?? ['']}
|
||||||
|
disabled={!alerts?.cheer?.enabled ?? true}
|
||||||
|
required={alerts?.cheer?.enabled ?? false}
|
||||||
|
onChange={(messages) => {
|
||||||
|
dispatch(
|
||||||
|
setAlerts({
|
||||||
|
...alerts,
|
||||||
|
cheer: { ...alerts.cheer, messages },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</TabContent>
|
||||||
|
</TabContainer>
|
||||||
|
</form>
|
||||||
|
</PageContainer>
|
||||||
|
);
|
||||||
|
}
|
|
@ -120,7 +120,7 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bot.logger.WithError(err).Debug("error reloading timer config")
|
bot.logger.WithError(err).Debug("error reloading timer config")
|
||||||
} else {
|
} else {
|
||||||
bot.logger.Info("reloaded timer config")
|
bot.logger.Info("reloaded alert config")
|
||||||
}
|
}
|
||||||
mod.compileTemplates()
|
mod.compileTemplates()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue