mirror of https://git.sr.ht/~ashkeel/strimertul
feat: move to a multi-key system for events
This commit is contained in:
parent
f35f3f0458
commit
bcdecf50c0
|
@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
|
||||
- The windows can now shrink no more than 480x300 but the UI will now better adapt to small window sizes
|
||||
- A new part of the dashboard will now inform the user if any configuration problems have been detected.
|
||||
|
||||
### Changed
|
||||
|
||||
- The required set of permissions has changed. Existing users must re-authenticate their users to the app connected to strimertül.
|
||||
- The `twitch/ev/eventsub-event` and `twitch/eventsub-history` keys have been replaced by a set of keys in the format `twitch/ev/eventsub-event/<event-id>` and `twitch/eventsub-history/<event-id>`. Users of the old system will have to adjust their logic. A simple trick is to change from get/subscribing from a single key to the entire prefix. The data structure is the same.
|
||||
|
||||
## 3.3.1 - 2023-11-12
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ function TwitchEvent({ data }: { data: EventSubNotification }) {
|
|||
const client = useAppSelector((state) => state.api.client);
|
||||
|
||||
const replay = () => {
|
||||
void client.putJSON('twitch/ev/eventsub-event', {
|
||||
void client.putJSON(`twitch/ev/eventsub-event/${data.subscription.type}`, {
|
||||
...data,
|
||||
subscription: {
|
||||
...data.subscription,
|
||||
|
@ -430,10 +430,33 @@ function TwitchStreamStatus({ info }: { info: StreamInfo }) {
|
|||
function TwitchSection() {
|
||||
const { t } = useTranslation();
|
||||
const twitchInfo = useLiveKey<StreamInfo[]>('twitch/stream-info');
|
||||
// const twitchActivity = useLiveKey<StreamInfo[]>('twitch/chat-activity');
|
||||
const twitchEvents = useLiveKey<EventSubNotification[]>(
|
||||
'twitch/eventsub-history',
|
||||
);
|
||||
const kv = useAppSelector((state) => state.api.client);
|
||||
const [twitchEvents, setTwitchEvents] = useState<EventSubNotification[]>([]);
|
||||
|
||||
const loadRecentEvents = async () => {
|
||||
const keymap = await kv.getKeysByPrefix('twitch/eventsub-history/');
|
||||
const events = Object.values(keymap)
|
||||
.map((value) => JSON.parse(value) as EventSubNotification[])
|
||||
.flat()
|
||||
.sort((a, b) => Date.parse(b.date) - Date.parse(a.date));
|
||||
|
||||
setTwitchEvents(events);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
void loadRecentEvents();
|
||||
|
||||
const onKeyChange = (value: string) => {
|
||||
const event = JSON.parse(value) as EventSubNotification;
|
||||
void setTwitchEvents((prev) => [event, ...prev]);
|
||||
};
|
||||
|
||||
void kv.subscribePrefix('twitch/ev/eventsub-event/', onKeyChange);
|
||||
|
||||
return () => {
|
||||
void kv.unsubscribePrefix('twitch/ev/eventsub-event/', onKeyChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -412,12 +412,13 @@ function TwitchEventSubSettings() {
|
|||
|
||||
const sendFakeEvent = async (event: keyof typeof eventsubTests) => {
|
||||
const data = eventsubTests[event];
|
||||
await kv.putJSON('twitch/ev/eventsub-event', {
|
||||
await kv.putJSON(`twitch/ev/eventsub-event/${event}`, {
|
||||
...data,
|
||||
subscription: {
|
||||
...data.subscription,
|
||||
created_at: new Date().toISOString(),
|
||||
},
|
||||
date: new Date().toISOString(),
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
bot.logger.Error("Could not set-up bot alert reload subscription", zap.Error(err))
|
||||
}
|
||||
|
||||
mod.cancelTwitchEventSub, err = bot.api.db.SubscribeKey(EventSubEventKey, mod.onEventSubEvent)
|
||||
mod.cancelTwitchEventSub, err = bot.api.db.SubscribePrefix(mod.onEventSubEvent, EventSubEventKeyPrefix)
|
||||
if err != nil {
|
||||
bot.logger.Error("Could not setup twitch alert subscription", zap.Error(err))
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
return mod
|
||||
}
|
||||
|
||||
func (m *BotAlertsModule) onEventSubEvent(value string) {
|
||||
func (m *BotAlertsModule) onEventSubEvent(_ string, value string) {
|
||||
var ev eventSubNotification
|
||||
err := json.UnmarshalFromString(value, &ev)
|
||||
if err != nil {
|
||||
|
|
|
@ -31,10 +31,10 @@ var scopes = []string{
|
|||
"moderator:manage:announcements",
|
||||
"moderator:read:chatters",
|
||||
"moderator:read:followers",
|
||||
"user_read",
|
||||
"user:bot",
|
||||
"user:manage:whispers",
|
||||
"user:read:chat",
|
||||
"user_read",
|
||||
"whispers:edit",
|
||||
"whispers:read",
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ func (c *Client) CheckScopes() (bool, error) {
|
|||
|
||||
// Sort scopes for comparison
|
||||
slices.Sort(authResp.Scope)
|
||||
slices.Sort(scopes)
|
||||
|
||||
return slices.Equal(scopes, authResp.Scope), nil
|
||||
}
|
||||
|
|
|
@ -143,13 +143,16 @@ func (c *Client) processEvent(message EventSubWebsocketMessage) {
|
|||
}
|
||||
notificationData.Date = time.Now()
|
||||
|
||||
err = c.db.PutJSON(EventSubEventKey, notificationData)
|
||||
eventKey := fmt.Sprintf("%s%s", EventSubEventKeyPrefix, notificationData.Subscription.Type)
|
||||
historyKey := fmt.Sprintf("%s%s", EventSubHistoryKeyPrefix, notificationData.Subscription.Type)
|
||||
err = c.db.PutJSON(eventKey, notificationData)
|
||||
c.logger.Info("Stored event", zap.String("key", eventKey), zap.String("notification-type", notificationData.Subscription.Type))
|
||||
if err != nil {
|
||||
c.logger.Error("Error storing event to database", zap.String("key", EventSubEventKey), zap.Error(err))
|
||||
c.logger.Error("Error storing event to database", zap.String("key", eventKey), zap.Error(err))
|
||||
}
|
||||
|
||||
var archive []NotificationMessagePayload
|
||||
err = c.db.GetJSON(EventSubHistoryKey, &archive)
|
||||
err = c.db.GetJSON(historyKey, &archive)
|
||||
if err != nil {
|
||||
archive = []NotificationMessagePayload{}
|
||||
}
|
||||
|
@ -157,9 +160,9 @@ func (c *Client) processEvent(message EventSubWebsocketMessage) {
|
|||
if len(archive) > EventSubHistorySize {
|
||||
archive = archive[len(archive)-EventSubHistorySize:]
|
||||
}
|
||||
err = c.db.PutJSON(EventSubHistoryKey, archive)
|
||||
err = c.db.PutJSON(historyKey, archive)
|
||||
if err != nil {
|
||||
c.logger.Error("Error storing event to database", zap.String("key", EventSubHistoryKey), zap.Error(err))
|
||||
c.logger.Error("Error storing event to database", zap.String("key", historyKey), zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,15 +198,24 @@ func (c *Client) addSubscriptionsForSession(userClient *helix.Client, session st
|
|||
|
||||
func topicCondition(topic string, id string) helix.EventSubCondition {
|
||||
switch topic {
|
||||
case "channel.raid":
|
||||
case helix.EventSubTypeChannelRaid:
|
||||
return helix.EventSubCondition{
|
||||
ToBroadcasterUserID: id,
|
||||
}
|
||||
case "channel.follow":
|
||||
case helix.EventSubTypeChannelFollow:
|
||||
return helix.EventSubCondition{
|
||||
BroadcasterUserID: id,
|
||||
ModeratorUserID: id,
|
||||
}
|
||||
case
|
||||
helix.EventSubTypeChannelChatMessage,
|
||||
helix.EventSubTypeChannelChatNotification:
|
||||
{
|
||||
return helix.EventSubCondition{
|
||||
BroadcasterUserID: id,
|
||||
UserID: id,
|
||||
}
|
||||
}
|
||||
default:
|
||||
return helix.EventSubCondition{
|
||||
BroadcasterUserID: id,
|
||||
|
@ -248,6 +260,8 @@ var subscriptionVersions = map[string]string{
|
|||
helix.EventSubTypeChannelSubscriptionMessage: "1",
|
||||
helix.EventSubTypeChannelCheer: "1",
|
||||
helix.EventSubTypeChannelRaid: "1",
|
||||
helix.EventSubTypeChannelChatMessage: "1",
|
||||
helix.EventSubTypeChannelChatNotification: "1",
|
||||
helix.EventSubTypeChannelPollBegin: "1",
|
||||
helix.EventSubTypeChannelPollProgress: "1",
|
||||
helix.EventSubTypeChannelPollEnd: "1",
|
||||
|
|
|
@ -97,8 +97,8 @@ const BotCounterPrefix = "twitch/bot-counters/"
|
|||
const AuthKey = "twitch/auth-keys"
|
||||
|
||||
const (
|
||||
EventSubEventKey = "twitch/ev/eventsub-event"
|
||||
EventSubHistoryKey = "twitch/eventsub-history"
|
||||
EventSubEventKeyPrefix = "twitch/ev/eventsub-event/"
|
||||
EventSubHistoryKeyPrefix = "twitch/eventsub-history/"
|
||||
)
|
||||
|
||||
const EventSubHistorySize = 100
|
||||
|
|
|
@ -45,13 +45,13 @@ var Keys = interfaces.KeyMap{
|
|||
Description: "User access token for the twitch subsystem",
|
||||
Type: reflect.TypeOf(AuthResponse{}),
|
||||
},
|
||||
EventSubEventKey: interfaces.KeyDef{
|
||||
Description: "On Eventsub event received",
|
||||
EventSubEventKeyPrefix + "[event-name]": interfaces.KeyDef{
|
||||
Description: "On Eventsub event [event-name] received",
|
||||
Type: reflect.TypeOf(NotificationMessagePayload{}),
|
||||
Tags: []interfaces.KeyTag{interfaces.TagEvent},
|
||||
},
|
||||
EventSubHistoryKey: interfaces.KeyDef{
|
||||
Description: "Last eventsub notifications received",
|
||||
EventSubHistoryKeyPrefix + "[event-name]": interfaces.KeyDef{
|
||||
Description: "Last eventsub notifications received for [event-name]",
|
||||
Type: reflect.TypeOf([]NotificationMessagePayload{}),
|
||||
Tags: []interfaces.KeyTag{interfaces.TagHistory},
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue