@notidotbot/noti-api-client 1.4.16 → 1.4.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,128 @@
1
+ // Game-deal subscriptions (Noti Games API integration).
2
+ //
3
+ // One GuildGameConfig per guild holds the routing + filter configuration. It mirrors the
4
+ // `noti-vision-server` localStorage shape from the gameApi `/viewer` dashboard mockup, but
5
+ // persisted in Postgres so the web dashboard + Discord commands share one source of truth.
6
+ //
7
+ // Premium gating is enforced in Noti (see INTEGRATION.md "Premium tiers"): the API serves
8
+ // everything unconditionally. Free guilds get free/upcoming/weekend game alerts, genre/tag
9
+ // filters, min-discount + max-price filters, and up to 2 tracked games. Premium unlocks
10
+ // per-category channel/role routing (webhook identity), all-time-low alerts, unlimited
11
+ // tracked games, and digest window customization.
12
+
13
+ model GuildGameConfig {
14
+ dbId String @id @default(uuid())
15
+
16
+ guildId String @unique
17
+
18
+ enabled Boolean @default(false)
19
+
20
+ // Default routing — the free-tier "one channel + one mention role" target. Every
21
+ // notification falls back here unless a premium category route overrides it.
22
+ notificationChannelId String?
23
+ pingRoleId String?
24
+
25
+ // Delivery tier. Window/day customization (digestHourUTC / digestWeekday) is premium;
26
+ // free guilds get the fixed evening window on any day.
27
+ deliveryMode GameDeliveryEnum @default(instant)
28
+ digestHourUTC Int? // Premium. 0-23 UTC. Null = default evening window.
29
+ digestWeekday Int? // Premium. 0-6 (Sun-Sat) for weekly digests. Null = any/default.
30
+
31
+ // Free-to-keep games (free.new). The headline growth-loop feature — never gated.
32
+ freeGamesEnabled Boolean @default(true)
33
+ freeDlcEnabled Boolean @default(false)
34
+ freeGameStores GameStoreEnum[]
35
+ upcomingFreeEnabled Boolean @default(false)
36
+ freeWeekendEnabled Boolean @default(false) // Steam play-for-free windows (NOT free to keep)
37
+
38
+ // Discount alerts (deal.new). Min-discount + max-price filters are free.
39
+ discountsEnabled Boolean @default(false)
40
+ discountStores GameStoreEnum[]
41
+ minDiscountPercent Int? // 0-100. price.discountPercent >= n
42
+ maxPriceCents Int? // price.finalCents <= n
43
+
44
+ // Category / studio filters (free, multi-select). Empty = no filter (match all).
45
+ // Matched case-insensitively against item.genres / item.tags / developers+publishers.
46
+ genres String[]
47
+ tags String[]
48
+ studios String[]
49
+
50
+ // All-Time-Low alerts (PREMIUM) — deal.lowest events / flags.allTimeLow.
51
+ allTimeLowEnabled Boolean @default(false)
52
+ allTimeLowMaxPriceCents Int?
53
+
54
+ // Game changelogs (PatchBot-style) — independent of price tracking.
55
+ changelogChannelId String?
56
+ changelogPingRoleId String?
57
+
58
+ categoryRoutes GuildGameCategoryRoute[]
59
+ trackedGames GuildTrackedGame[]
60
+ changelogGames GuildGameChangelog[]
61
+ }
62
+
63
+ // PREMIUM: per-category channel/role routing. The first route (lowest `priority`) whose
64
+ // match criteria the event satisfies wins; webhook identity is also premium-only.
65
+ model GuildGameCategoryRoute {
66
+ dbId String @id @default(uuid())
67
+
68
+ // Match criteria (empty array / null = "any").
69
+ kinds GameKindEnum[]
70
+ stores GameStoreEnum[]
71
+ flags GameFlagEnum[]
72
+ genres String[]
73
+ tags String[]
74
+ minDiscountPercent Int?
75
+
76
+ // Routing target for matching events.
77
+ channelId String?
78
+ pingRoleId String?
79
+
80
+ // Custom webhook identity (premium). When set, the notification is posted via a webhook
81
+ // with this name/avatar instead of the bot user.
82
+ webhookEnabled Boolean? @default(false)
83
+ webhookUsername String?
84
+ webhookAvatarUrl String?
85
+
86
+ priority Int @default(0)
87
+
88
+ gameConfigId String
89
+ gameConfig GuildGameConfig? @relation(fields: [gameConfigId], references: [dbId], onUpdate: Cascade, onDelete: Cascade)
90
+
91
+ @@unique([gameConfigId, priority])
92
+ }
93
+
94
+ // A specific followed game. Tracked games are registered on the API watchlist so even a 5%
95
+ // discount is tracked. Free guilds: 2 per guild; premium: unlimited (API cap 500 global).
96
+ model GuildTrackedGame {
97
+ dbId String @id @default(uuid())
98
+
99
+ steamAppId Int? // resolved to a CheapShark id by the API; null for Epic-only titles
100
+ title String? // normalized-title match for games without a Steam appid
101
+ itemId String? // canonical deal id once observed (steam:730 / epic:...)
102
+
103
+ // Optional per-game routing override (else uses the guild default channel/role).
104
+ channelId String?
105
+ pingRoleId String?
106
+
107
+ minDiscountPercent Int?
108
+ atlOnly Boolean @default(false)
109
+
110
+ gameConfigId String
111
+ gameConfig GuildGameConfig? @relation(fields: [gameConfigId], references: [dbId], onUpdate: Cascade, onDelete: Cascade)
112
+
113
+ @@unique([gameConfigId, steamAppId])
114
+ @@unique([gameConfigId, title])
115
+ }
116
+
117
+ // A game whose Steam patch notes / announcements this guild follows (changelog.new).
118
+ model GuildGameChangelog {
119
+ dbId String @id @default(uuid())
120
+
121
+ steamAppId Int
122
+ title String?
123
+
124
+ gameConfigId String
125
+ gameConfig GuildGameConfig? @relation(fields: [gameConfigId], references: [dbId], onUpdate: Cascade, onDelete: Cascade)
126
+
127
+ @@unique([gameConfigId, steamAppId])
128
+ }
@@ -17,8 +17,8 @@ model YoutubeStreamer {
17
17
  videoNotificationChannelId String?
18
18
  showNotifyButton Boolean?
19
19
 
20
- pingRoleId String? // Pinged on live notifications (and videos when videoRoleId is unset).
21
- videoRoleId String? // Pinged on video notifications; falls back to pingRoleId when null.
20
+ pingRoleId String? // Pinged on live notifications only.
21
+ videoRoleId String? // Pinged on video notifications only; mentions no one when null (independent of pingRoleId).
22
22
  customCoolDownBeforeNextLive Int? // Premium. In minutes.
23
23
 
24
24
  liveRoleId String?
@@ -1,182 +1,216 @@
1
1
  generator client {
2
- provider = "prisma-client-js"
2
+ provider = "prisma-client-js"
3
3
  }
4
4
 
5
5
  datasource db {
6
- provider = "postgresql"
7
- url = env("DATABASE_URL")
6
+ provider = "postgresql"
7
+ url = env("DATABASE_URL")
8
8
  }
9
9
 
10
10
  generator tsPrisma {
11
- provider = "ts-prisma-generator"
11
+ provider = "ts-prisma-generator"
12
12
  }
13
13
 
14
14
  enum LeaderBoardTypesEnum {
15
- weekly
16
- monthly
17
- overall
15
+ weekly
16
+ monthly
17
+ overall
18
18
  }
19
19
 
20
20
  enum SingleMessageTypeEnum {
21
- autoLiveRoleAdded
22
- autoLiveRoleRemoved
23
- statusRoleAdded
24
- statusRoleRemoved
25
- statChannelLive
26
- statChannelOffline
27
- statFollowers
21
+ autoLiveRoleAdded
22
+ autoLiveRoleRemoved
23
+ statusRoleAdded
24
+ statusRoleRemoved
25
+ statChannelLive
26
+ statChannelOffline
27
+ statFollowers
28
28
  }
29
29
 
30
30
  enum StreamerMessageTypeEnum {
31
- clip
32
- kickBuiltInClip
33
- vod
34
- kickLive
35
- kickOffline
36
- twitchLive
37
- twitchOffline
38
- rumbleLive
39
- rumbleOffline
40
- tiktokLive
41
- tiktokOffline
42
- tiktokVideo
43
- youtubeLive
44
- youtubeVideo
31
+ clip
32
+ kickBuiltInClip
33
+ vod
34
+ kickLive
35
+ kickOffline
36
+ twitchLive
37
+ twitchOffline
38
+ rumbleLive
39
+ rumbleOffline
40
+ tiktokLive
41
+ tiktokOffline
42
+ tiktokVideo
43
+ youtubeLive
44
+ youtubeVideo
45
45
  }
46
46
 
47
47
  enum GuildMessageTypeEnum {
48
- giveawayRerolled
49
- giveawayWinner
50
- giveawayEnded
51
- giveawayDM
52
- linkedRole
53
- giveaway
54
- birthday
55
- welcome
56
- leave
57
-
58
- // StreamerMessageTypeEnum
59
- clip
60
- kickBuiltInClip
61
- vod
62
- kickLive
63
- kickOffline
64
- twitchLive
65
- twitchOffline
66
- rumbleLive
67
- rumbleOffline
68
- tiktokLive
69
- tiktokOffline
70
- tiktokVideo
71
- youtubeLive
72
- youtubeVideo
48
+ giveawayRerolled
49
+ giveawayWinner
50
+ giveawayEnded
51
+ giveawayDM
52
+ linkedRole
53
+ giveaway
54
+ birthday
55
+ welcome
56
+ leave
57
+
58
+ // StreamerMessageTypeEnum
59
+ clip
60
+ kickBuiltInClip
61
+ vod
62
+ kickLive
63
+ kickOffline
64
+ twitchLive
65
+ twitchOffline
66
+ rumbleLive
67
+ rumbleOffline
68
+ tiktokLive
69
+ tiktokOffline
70
+ tiktokVideo
71
+ youtubeLive
72
+ youtubeVideo
73
73
  }
74
74
 
75
75
  enum GuildSingleMessageTypeEnum {
76
- autoLiveRoleAdded
77
- autoLiveRoleRemoved
78
- statusRoleAdded
79
- statusRoleRemoved
80
- statChannelLive
81
- statChannelOffline
82
- statFollowers
76
+ autoLiveRoleAdded
77
+ autoLiveRoleRemoved
78
+ statusRoleAdded
79
+ statusRoleRemoved
80
+ statChannelLive
81
+ statChannelOffline
82
+ statFollowers
83
83
  }
84
84
 
85
85
  enum OverridesEnum {
86
- autoPublish
87
- cancel
88
- dontPublish
86
+ autoPublish
87
+ cancel
88
+ dontPublish
89
89
  }
90
90
 
91
91
  enum PlatformEnum {
92
- kick
93
- twitch
94
- rumble
95
- tiktok
96
- youtube
92
+ kick
93
+ twitch
94
+ rumble
95
+ tiktok
96
+ youtube
97
97
  }
98
98
 
99
99
  enum ClipperCategoryEnum {
100
- vip
101
- sub
102
- mod
103
- broadcaster
100
+ vip
101
+ sub
102
+ mod
103
+ broadcaster
104
104
  }
105
105
 
106
106
  enum UserMediaSharePermissionsEnum {
107
- vip
108
- sub
109
- mod
110
- broadcaster
111
- everyone
107
+ vip
108
+ sub
109
+ mod
110
+ broadcaster
111
+ everyone
112
112
  }
113
113
 
114
114
  enum PlatformsWithVideosEnum {
115
- tiktok
116
- youtube
115
+ tiktok
116
+ youtube
117
117
  }
118
118
 
119
119
  enum RumbleTypeEnum {
120
- channel
121
- user
120
+ channel
121
+ user
122
122
  }
123
123
 
124
124
  enum QueryInEnum {
125
- title
126
- category
127
- description
125
+ title
126
+ category
127
+ description
128
128
  }
129
129
 
130
130
  enum FilterEnum {
131
- whitelist
132
- blacklist
131
+ whitelist
132
+ blacklist
133
133
  }
134
134
 
135
135
  enum MediaShareTypesEnum {
136
- tiktok
137
- youtube
138
- shorts
136
+ tiktok
137
+ youtube
138
+ shorts
139
139
  }
140
140
 
141
141
  enum MediaShareCommandsEnum {
142
- request
143
- skip
144
- pause
145
- clear
146
- rban
147
- play
148
- mode
149
- runban
142
+ request
143
+ skip
144
+ pause
145
+ clear
146
+ rban
147
+ play
148
+ mode
149
+ runban
150
150
  }
151
151
 
152
152
  enum RoleBonusEnum {
153
- stackable
154
- highest
153
+ stackable
154
+ highest
155
155
  }
156
156
 
157
157
  enum UserNotificationSeverityEnum {
158
- info
159
- warning
160
- emergency
158
+ info
159
+ warning
160
+ emergency
161
+ }
162
+
163
+ // Game-deal integration (Noti Games API). `GameStoreEnum` mirrors the API's `store`,
164
+ // `GameKindEnum` mirrors `DealKind`, `GameFlagEnum` the notify-worthy `DealItem.flags`.
165
+ enum GameStoreEnum {
166
+ steam
167
+ epic
168
+ gog
169
+ prime
170
+ }
171
+
172
+ enum GameKindEnum {
173
+ free_game
174
+ free_dlc_or_loot
175
+ discount
176
+ upcoming_free
177
+ }
178
+
179
+ enum GameFlagEnum {
180
+ freeWeekend
181
+ allTimeLow
182
+ featured
183
+ aaa
184
+ earlyAccess
185
+ }
186
+
187
+ enum GameDeliveryEnum {
188
+ instant
189
+ daily
190
+ weekly
161
191
  }
162
192
 
163
193
  model AllEnumsModel {
164
- dbId String @id @default(uuid())
165
-
166
- leaderBoardTypes LeaderBoardTypesEnum
167
- singleMessageTypes SingleMessageTypeEnum
168
- streamerMessageTypes StreamerMessageTypeEnum
169
- guildMessageTypes GuildMessageTypeEnum
170
- overrides OverridesEnum
171
- platform PlatformEnum
172
- clipperCategories ClipperCategoryEnum
173
- userMediaSharePerms UserMediaSharePermissionsEnum
174
- platformsWithVideos PlatformsWithVideosEnum
175
- rumbleTypes RumbleTypeEnum
176
- queryIns QueryInEnum
177
- roleFilters FilterEnum
178
- mediaShareTypes MediaShareTypesEnum
179
- mediaShareCommands MediaShareCommandsEnum
180
- roleBonusTypes RoleBonusEnum
181
- userNotificationSev UserNotificationSeverityEnum
194
+ dbId String @id @default(uuid())
195
+
196
+ leaderBoardTypes LeaderBoardTypesEnum
197
+ singleMessageTypes SingleMessageTypeEnum
198
+ streamerMessageTypes StreamerMessageTypeEnum
199
+ guildMessageTypes GuildMessageTypeEnum
200
+ overrides OverridesEnum
201
+ platform PlatformEnum
202
+ clipperCategories ClipperCategoryEnum
203
+ userMediaSharePerms UserMediaSharePermissionsEnum
204
+ platformsWithVideos PlatformsWithVideosEnum
205
+ rumbleTypes RumbleTypeEnum
206
+ queryIns QueryInEnum
207
+ roleFilters FilterEnum
208
+ mediaShareTypes MediaShareTypesEnum
209
+ mediaShareCommands MediaShareCommandsEnum
210
+ roleBonusTypes RoleBonusEnum
211
+ userNotificationSev UserNotificationSeverityEnum
212
+ gameStores GameStoreEnum
213
+ gameKinds GameKindEnum
214
+ gameFlags GameFlagEnum
215
+ gameDelivery GameDeliveryEnum
182
216
  }