@atproto/ozone 0.1.171 → 0.1.173

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.
Files changed (80) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/daemon/event-reverser.d.ts +1 -0
  3. package/dist/daemon/event-reverser.d.ts.map +1 -1
  4. package/dist/daemon/event-reverser.js +42 -1
  5. package/dist/daemon/event-reverser.js.map +1 -1
  6. package/dist/db/migrations/20260428T000000000Z-add-expiring-tag-table.d.ts +4 -0
  7. package/dist/db/migrations/20260428T000000000Z-add-expiring-tag-table.d.ts.map +1 -0
  8. package/dist/db/migrations/20260428T000000000Z-add-expiring-tag-table.js +32 -0
  9. package/dist/db/migrations/20260428T000000000Z-add-expiring-tag-table.js.map +1 -0
  10. package/dist/db/migrations/index.d.ts +1 -0
  11. package/dist/db/migrations/index.d.ts.map +1 -1
  12. package/dist/db/migrations/index.js +2 -1
  13. package/dist/db/migrations/index.js.map +1 -1
  14. package/dist/db/schema/expiring_tag.d.ts +15 -0
  15. package/dist/db/schema/expiring_tag.d.ts.map +1 -0
  16. package/dist/db/schema/expiring_tag.js +5 -0
  17. package/dist/db/schema/expiring_tag.js.map +1 -0
  18. package/dist/db/schema/index.d.ts +2 -1
  19. package/dist/db/schema/index.d.ts.map +1 -1
  20. package/dist/db/schema/index.js.map +1 -1
  21. package/dist/lexicon/index.d.ts +2 -0
  22. package/dist/lexicon/index.d.ts.map +1 -1
  23. package/dist/lexicon/index.js +4 -0
  24. package/dist/lexicon/index.js.map +1 -1
  25. package/dist/lexicon/lexicons.d.ts +444 -64
  26. package/dist/lexicon/lexicons.d.ts.map +1 -1
  27. package/dist/lexicon/lexicons.js +225 -31
  28. package/dist/lexicon/lexicons.js.map +1 -1
  29. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +1 -0
  30. package/dist/lexicon/types/app/bsky/actor/defs.d.ts.map +1 -1
  31. package/dist/lexicon/types/app/bsky/actor/defs.js.map +1 -1
  32. package/dist/lexicon/types/chat/bsky/actor/defs.d.ts +8 -2
  33. package/dist/lexicon/types/chat/bsky/actor/defs.d.ts.map +1 -1
  34. package/dist/lexicon/types/chat/bsky/actor/defs.js +9 -0
  35. package/dist/lexicon/types/chat/bsky/actor/defs.js.map +1 -1
  36. package/dist/lexicon/types/chat/bsky/convo/defs.d.ts +52 -22
  37. package/dist/lexicon/types/chat/bsky/convo/defs.d.ts.map +1 -1
  38. package/dist/lexicon/types/chat/bsky/convo/defs.js +9 -0
  39. package/dist/lexicon/types/chat/bsky/convo/defs.js.map +1 -1
  40. package/dist/lexicon/types/chat/bsky/convo/getConvoMembers.d.ts +26 -0
  41. package/dist/lexicon/types/chat/bsky/convo/getConvoMembers.d.ts.map +1 -0
  42. package/dist/lexicon/types/chat/bsky/convo/getConvoMembers.js +7 -0
  43. package/dist/lexicon/types/chat/bsky/convo/getConvoMembers.js.map +1 -0
  44. package/dist/lexicon/types/chat/bsky/convo/getMessages.d.ts +3 -0
  45. package/dist/lexicon/types/chat/bsky/convo/getMessages.d.ts.map +1 -1
  46. package/dist/lexicon/types/chat/bsky/convo/getMessages.js.map +1 -1
  47. package/dist/lexicon/types/chat/bsky/group/addMembers.d.ts +2 -0
  48. package/dist/lexicon/types/chat/bsky/group/addMembers.d.ts.map +1 -1
  49. package/dist/lexicon/types/chat/bsky/group/addMembers.js.map +1 -1
  50. package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts +2 -0
  51. package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts.map +1 -1
  52. package/dist/lexicon/types/tools/ozone/moderation/defs.js.map +1 -1
  53. package/dist/mod-service/expiring-tags.d.ts +27 -0
  54. package/dist/mod-service/expiring-tags.d.ts.map +1 -0
  55. package/dist/mod-service/expiring-tags.js +62 -0
  56. package/dist/mod-service/expiring-tags.js.map +1 -0
  57. package/dist/mod-service/index.d.ts.map +1 -1
  58. package/dist/mod-service/index.js +22 -0
  59. package/dist/mod-service/index.js.map +1 -1
  60. package/dist/mod-service/status.d.ts +4 -0
  61. package/dist/mod-service/status.d.ts.map +1 -1
  62. package/package.json +6 -6
  63. package/src/daemon/event-reverser.ts +50 -1
  64. package/src/db/migrations/20260428T000000000Z-add-expiring-tag-table.ts +32 -0
  65. package/src/db/migrations/index.ts +1 -0
  66. package/src/db/schema/expiring_tag.ts +17 -0
  67. package/src/db/schema/index.ts +3 -1
  68. package/src/lexicon/index.ts +13 -0
  69. package/src/lexicon/lexicons.ts +245 -31
  70. package/src/lexicon/types/app/bsky/actor/defs.ts +1 -0
  71. package/src/lexicon/types/chat/bsky/actor/defs.ts +17 -1
  72. package/src/lexicon/types/chat/bsky/convo/defs.ts +65 -22
  73. package/src/lexicon/types/chat/bsky/convo/getConvoMembers.ts +44 -0
  74. package/src/lexicon/types/chat/bsky/convo/getMessages.ts +3 -0
  75. package/src/lexicon/types/chat/bsky/group/addMembers.ts +2 -0
  76. package/src/lexicon/types/tools/ozone/moderation/defs.ts +2 -0
  77. package/src/mod-service/expiring-tags.ts +98 -0
  78. package/src/mod-service/index.ts +26 -0
  79. package/tests/expiring-tags.test.ts +231 -0
  80. package/tsconfig.build.tsbuildinfo +1 -1
@@ -85,6 +85,25 @@ export function validateMessageView<V>(v: V) {
85
85
  return validate<MessageView & V>(v, id, hashMessageView)
86
86
  }
87
87
 
88
+ export interface SystemMessageReferredUser {
89
+ $type?: 'chat.bsky.convo.defs#systemMessageReferredUser'
90
+ did: string
91
+ }
92
+
93
+ const hashSystemMessageReferredUser = 'systemMessageReferredUser'
94
+
95
+ export function isSystemMessageReferredUser<V>(v: V) {
96
+ return is$typed(v, id, hashSystemMessageReferredUser)
97
+ }
98
+
99
+ export function validateSystemMessageReferredUser<V>(v: V) {
100
+ return validate<SystemMessageReferredUser & V>(
101
+ v,
102
+ id,
103
+ hashSystemMessageReferredUser,
104
+ )
105
+ }
106
+
88
107
  /** [NOTE: This is under active development and should be considered unstable while this note is here]. */
89
108
  export interface SystemMessageView {
90
109
  $type?: 'chat.bsky.convo.defs#systemMessageView'
@@ -120,9 +139,9 @@ export function validateSystemMessageView<V>(v: V) {
120
139
  /** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was added to the group convo. */
121
140
  export interface SystemMessageDataAddMember {
122
141
  $type?: 'chat.bsky.convo.defs#systemMessageDataAddMember'
123
- member: ChatBskyActorDefs.ProfileViewBasic
142
+ member: SystemMessageReferredUser
124
143
  role: ChatBskyActorDefs.MemberRole
125
- addedBy: ChatBskyActorDefs.ProfileViewBasic
144
+ addedBy: SystemMessageReferredUser
126
145
  }
127
146
 
128
147
  const hashSystemMessageDataAddMember = 'systemMessageDataAddMember'
@@ -142,8 +161,8 @@ export function validateSystemMessageDataAddMember<V>(v: V) {
142
161
  /** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was removed from the group convo. */
143
162
  export interface SystemMessageDataRemoveMember {
144
163
  $type?: 'chat.bsky.convo.defs#systemMessageDataRemoveMember'
145
- member: ChatBskyActorDefs.ProfileViewBasic
146
- removedBy: ChatBskyActorDefs.ProfileViewBasic
164
+ member: SystemMessageReferredUser
165
+ removedBy: SystemMessageReferredUser
147
166
  }
148
167
 
149
168
  const hashSystemMessageDataRemoveMember = 'systemMessageDataRemoveMember'
@@ -163,9 +182,9 @@ export function validateSystemMessageDataRemoveMember<V>(v: V) {
163
182
  /** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user joined the group convo via join link. */
164
183
  export interface SystemMessageDataMemberJoin {
165
184
  $type?: 'chat.bsky.convo.defs#systemMessageDataMemberJoin'
166
- member: ChatBskyActorDefs.ProfileViewBasic
185
+ member: SystemMessageReferredUser
167
186
  role: ChatBskyActorDefs.MemberRole
168
- approvedBy?: ChatBskyActorDefs.ProfileViewBasic
187
+ approvedBy?: SystemMessageReferredUser
169
188
  }
170
189
 
171
190
  const hashSystemMessageDataMemberJoin = 'systemMessageDataMemberJoin'
@@ -185,7 +204,7 @@ export function validateSystemMessageDataMemberJoin<V>(v: V) {
185
204
  /** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user voluntarily left the group convo. */
186
205
  export interface SystemMessageDataMemberLeave {
187
206
  $type?: 'chat.bsky.convo.defs#systemMessageDataMemberLeave'
188
- member: ChatBskyActorDefs.ProfileViewBasic
207
+ member: SystemMessageReferredUser
189
208
  }
190
209
 
191
210
  const hashSystemMessageDataMemberLeave = 'systemMessageDataMemberLeave'
@@ -205,7 +224,7 @@ export function validateSystemMessageDataMemberLeave<V>(v: V) {
205
224
  /** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked. */
206
225
  export interface SystemMessageDataLockConvo {
207
226
  $type?: 'chat.bsky.convo.defs#systemMessageDataLockConvo'
208
- lockedBy: ChatBskyActorDefs.ProfileViewBasic
227
+ lockedBy: SystemMessageReferredUser
209
228
  }
210
229
 
211
230
  const hashSystemMessageDataLockConvo = 'systemMessageDataLockConvo'
@@ -225,7 +244,7 @@ export function validateSystemMessageDataLockConvo<V>(v: V) {
225
244
  /** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was unlocked. */
226
245
  export interface SystemMessageDataUnlockConvo {
227
246
  $type?: 'chat.bsky.convo.defs#systemMessageDataUnlockConvo'
228
- unlockedBy: ChatBskyActorDefs.ProfileViewBasic
247
+ unlockedBy: SystemMessageReferredUser
229
248
  }
230
249
 
231
250
  const hashSystemMessageDataUnlockConvo = 'systemMessageDataUnlockConvo'
@@ -245,7 +264,7 @@ export function validateSystemMessageDataUnlockConvo<V>(v: V) {
245
264
  /** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked permanently. */
246
265
  export interface SystemMessageDataLockConvoPermanently {
247
266
  $type?: 'chat.bsky.convo.defs#systemMessageDataLockConvoPermanently'
248
- lockedBy: ChatBskyActorDefs.ProfileViewBasic
267
+ lockedBy: SystemMessageReferredUser
249
268
  }
250
269
 
251
270
  const hashSystemMessageDataLockConvoPermanently =
@@ -447,6 +466,7 @@ export interface ConvoView {
447
466
  $type?: 'chat.bsky.convo.defs#convoView'
448
467
  id: string
449
468
  rev: string
469
+ /** Members of this conversation. For direct convos, it will be an immutable list of the 2 members. For group convos, it will a list of important members (the first few members, the viewer, the member who invited the viewer, the member who sent the last message, the member who sent the last reaction), but will not contain the full list of members. Use chat.bsky.convo.getConvoMembers to list all members. */
450
470
  members: ChatBskyActorDefs.ProfileViewBasic[]
451
471
  lastMessage?:
452
472
  | $Typed<MessageView>
@@ -490,6 +510,9 @@ export interface GroupConvo {
490
510
  $type?: 'chat.bsky.convo.defs#groupConvo'
491
511
  /** The display name of the group conversation. */
492
512
  name: string
513
+ /** The total number of members in the group conversation. */
514
+ memberCount: number
515
+ createdAt: string
493
516
  joinLink?: ChatBskyGroupDefs.JoinLinkView
494
517
  lockStatus: ConvoLockStatus
495
518
  }
@@ -595,6 +618,8 @@ export interface LogCreateMessage {
595
618
  rev: string
596
619
  convoId: string
597
620
  message: $Typed<MessageView> | $Typed<DeletedMessageView> | { $type: string }
621
+ /** Profiles referred to in the message view. This isn't required for compatibility, because it was added later, but should generally be present. */
622
+ relatedProfiles?: ChatBskyActorDefs.ProfileViewBasic[]
598
623
  }
599
624
 
600
625
  const hashLogCreateMessage = 'logCreateMessage'
@@ -654,6 +679,8 @@ export interface LogAddReaction {
654
679
  convoId: string
655
680
  message: $Typed<MessageView> | $Typed<DeletedMessageView> | { $type: string }
656
681
  reaction: ReactionView
682
+ /** Profiles referred in the message and reaction views. This isn't required for compatibility, because it was added later, but should generally be present. */
683
+ relatedProfiles?: ChatBskyActorDefs.ProfileViewBasic[]
657
684
  }
658
685
 
659
686
  const hashLogAddReaction = 'logAddReaction'
@@ -673,6 +700,8 @@ export interface LogRemoveReaction {
673
700
  convoId: string
674
701
  message: $Typed<MessageView> | $Typed<DeletedMessageView> | { $type: string }
675
702
  reaction: ReactionView
703
+ /** Profiles referred in the message and reaction views. This isn't required for compatibility, because it was added later, but should generally be present. */
704
+ relatedProfiles?: ChatBskyActorDefs.ProfileViewBasic[]
676
705
  }
677
706
 
678
707
  const hashLogRemoveReaction = 'logRemoveReaction'
@@ -712,7 +741,9 @@ export interface LogAddMember {
712
741
  $type?: 'chat.bsky.convo.defs#logAddMember'
713
742
  rev: string
714
743
  convoId: string
715
- message: SystemMessageDataAddMember
744
+ message: SystemMessageView
745
+ /** Profiles referred in the system message. */
746
+ relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[]
716
747
  }
717
748
 
718
749
  const hashLogAddMember = 'logAddMember'
@@ -730,7 +761,9 @@ export interface LogRemoveMember {
730
761
  $type?: 'chat.bsky.convo.defs#logRemoveMember'
731
762
  rev: string
732
763
  convoId: string
733
- message: SystemMessageDataRemoveMember
764
+ message: SystemMessageView
765
+ /** Profiles referred in the system message. */
766
+ relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[]
734
767
  }
735
768
 
736
769
  const hashLogRemoveMember = 'logRemoveMember'
@@ -748,7 +781,9 @@ export interface LogMemberJoin {
748
781
  $type?: 'chat.bsky.convo.defs#logMemberJoin'
749
782
  rev: string
750
783
  convoId: string
751
- message: SystemMessageDataMemberJoin
784
+ message: SystemMessageView
785
+ /** Profiles referred in the system message. */
786
+ relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[]
752
787
  }
753
788
 
754
789
  const hashLogMemberJoin = 'logMemberJoin'
@@ -766,7 +801,9 @@ export interface LogMemberLeave {
766
801
  $type?: 'chat.bsky.convo.defs#logMemberLeave'
767
802
  rev: string
768
803
  convoId: string
769
- message: SystemMessageDataMemberLeave
804
+ message: SystemMessageView
805
+ /** Profiles referred in the system message. */
806
+ relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[]
770
807
  }
771
808
 
772
809
  const hashLogMemberLeave = 'logMemberLeave'
@@ -784,7 +821,9 @@ export interface LogLockConvo {
784
821
  $type?: 'chat.bsky.convo.defs#logLockConvo'
785
822
  rev: string
786
823
  convoId: string
787
- message: SystemMessageDataLockConvo
824
+ message: SystemMessageView
825
+ /** Profiles referred in the system message. */
826
+ relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[]
788
827
  }
789
828
 
790
829
  const hashLogLockConvo = 'logLockConvo'
@@ -802,7 +841,9 @@ export interface LogUnlockConvo {
802
841
  $type?: 'chat.bsky.convo.defs#logUnlockConvo'
803
842
  rev: string
804
843
  convoId: string
805
- message: SystemMessageDataUnlockConvo
844
+ message: SystemMessageView
845
+ /** Profiles referred in the system message. */
846
+ relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[]
806
847
  }
807
848
 
808
849
  const hashLogUnlockConvo = 'logUnlockConvo'
@@ -820,7 +861,9 @@ export interface LogLockConvoPermanently {
820
861
  $type?: 'chat.bsky.convo.defs#logLockConvoPermanently'
821
862
  rev: string
822
863
  convoId: string
823
- message: SystemMessageDataLockConvoPermanently
864
+ message: SystemMessageView
865
+ /** Profiles referred in the system message. */
866
+ relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[]
824
867
  }
825
868
 
826
869
  const hashLogLockConvoPermanently = 'logLockConvoPermanently'
@@ -842,7 +885,7 @@ export interface LogEditGroup {
842
885
  $type?: 'chat.bsky.convo.defs#logEditGroup'
843
886
  rev: string
844
887
  convoId: string
845
- message: SystemMessageDataEditGroup
888
+ message: SystemMessageView
846
889
  }
847
890
 
848
891
  const hashLogEditGroup = 'logEditGroup'
@@ -860,7 +903,7 @@ export interface LogCreateJoinLink {
860
903
  $type?: 'chat.bsky.convo.defs#logCreateJoinLink'
861
904
  rev: string
862
905
  convoId: string
863
- message: SystemMessageDataCreateJoinLink
906
+ message: SystemMessageView
864
907
  }
865
908
 
866
909
  const hashLogCreateJoinLink = 'logCreateJoinLink'
@@ -878,7 +921,7 @@ export interface LogEditJoinLink {
878
921
  $type?: 'chat.bsky.convo.defs#logEditJoinLink'
879
922
  rev: string
880
923
  convoId: string
881
- message: SystemMessageDataEditJoinLink
924
+ message: SystemMessageView
882
925
  }
883
926
 
884
927
  const hashLogEditJoinLink = 'logEditJoinLink'
@@ -896,7 +939,7 @@ export interface LogEnableJoinLink {
896
939
  $type?: 'chat.bsky.convo.defs#logEnableJoinLink'
897
940
  rev: string
898
941
  convoId: string
899
- message: SystemMessageDataEnableJoinLink
942
+ message: SystemMessageView
900
943
  }
901
944
 
902
945
  const hashLogEnableJoinLink = 'logEnableJoinLink'
@@ -914,7 +957,7 @@ export interface LogDisableJoinLink {
914
957
  $type?: 'chat.bsky.convo.defs#logDisableJoinLink'
915
958
  rev: string
916
959
  convoId: string
917
- message: SystemMessageDataDisableJoinLink
960
+ message: SystemMessageView
918
961
  }
919
962
 
920
963
  const hashLogDisableJoinLink = 'logDisableJoinLink'
@@ -0,0 +1,44 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+ import { CID } from 'multiformats/cid'
6
+ import { validate as _validate } from '../../../../lexicons'
7
+ import {
8
+ type $Typed,
9
+ is$typed as _is$typed,
10
+ type OmitKey,
11
+ } from '../../../../util'
12
+ import type * as ChatBskyActorDefs from '../actor/defs.js'
13
+
14
+ const is$typed = _is$typed,
15
+ validate = _validate
16
+ const id = 'chat.bsky.convo.getConvoMembers'
17
+
18
+ export type QueryParams = {
19
+ convoId: string
20
+ limit: number
21
+ cursor?: string
22
+ }
23
+ export type InputSchema = undefined
24
+
25
+ export interface OutputSchema {
26
+ cursor?: string
27
+ members: ChatBskyActorDefs.ProfileViewBasic[]
28
+ }
29
+
30
+ export type HandlerInput = void
31
+
32
+ export interface HandlerSuccess {
33
+ encoding: 'application/json'
34
+ body: OutputSchema
35
+ headers?: { [key: string]: string }
36
+ }
37
+
38
+ export interface HandlerError {
39
+ status: number
40
+ message?: string
41
+ error?: 'InvalidConvo'
42
+ }
43
+
44
+ export type HandlerOutput = HandlerError | HandlerSuccess
@@ -10,6 +10,7 @@ import {
10
10
  type OmitKey,
11
11
  } from '../../../../util'
12
12
  import type * as ChatBskyConvoDefs from './defs.js'
13
+ import type * as ChatBskyActorDefs from '../actor/defs.js'
13
14
 
14
15
  const is$typed = _is$typed,
15
16
  validate = _validate
@@ -30,6 +31,8 @@ export interface OutputSchema {
30
31
  | $Typed<ChatBskyConvoDefs.SystemMessageView>
31
32
  | { $type: string }
32
33
  )[]
34
+ /** Set of all members who authored or reacted to the returned messages. Members referred to by system messages are also included. */
35
+ relatedProfiles?: ChatBskyActorDefs.ProfileViewBasic[]
33
36
  }
34
37
 
35
38
  export type HandlerInput = void
@@ -10,6 +10,7 @@ import {
10
10
  type OmitKey,
11
11
  } from '../../../../util'
12
12
  import type * as ChatBskyConvoDefs from '../convo/defs.js'
13
+ import type * as ChatBskyActorDefs from '../actor/defs.js'
13
14
 
14
15
  const is$typed = _is$typed,
15
16
  validate = _validate
@@ -24,6 +25,7 @@ export interface InputSchema {
24
25
 
25
26
  export interface OutputSchema {
26
27
  convo: ChatBskyConvoDefs.ConvoView
28
+ addedMembers?: ChatBskyActorDefs.ProfileViewBasic[]
27
29
  }
28
30
 
29
31
  export interface HandlerInput {
@@ -701,6 +701,8 @@ export interface ModEventTag {
701
701
  remove: string[]
702
702
  /** Additional comment about added/removed tags. */
703
703
  comment?: string
704
+ /** Indicates how long the tags being added should remain before automatically being removed. Only applies to tags being added. */
705
+ durationInHours?: number
704
706
  }
705
707
 
706
708
  const hashModEventTag = 'modEventTag'
@@ -0,0 +1,98 @@
1
+ import { Selectable } from 'kysely'
2
+ import { Database } from '../db'
3
+ import { ExpiringTag } from '../db/schema/expiring_tag'
4
+
5
+ export type ExpiringTagRow = Selectable<ExpiringTag>
6
+
7
+ export type ExpiringTagGroup = {
8
+ did: string
9
+ recordPath: string
10
+ createdBy: string
11
+ tags: string[]
12
+ ids: number[]
13
+ }
14
+
15
+ export async function insertExpiringTags(
16
+ db: Database,
17
+ params: {
18
+ eventId: number
19
+ did: string
20
+ recordPath: string
21
+ tags: string[]
22
+ expiresAt: string
23
+ createdBy: string
24
+ },
25
+ ): Promise<void> {
26
+ await db.db
27
+ .insertInto('expiring_tag')
28
+ .values(
29
+ params.tags.map((tag) => ({
30
+ eventId: params.eventId,
31
+ did: params.did,
32
+ recordPath: params.recordPath,
33
+ tag,
34
+ expiresAt: params.expiresAt,
35
+ createdBy: params.createdBy,
36
+ })),
37
+ )
38
+ .execute()
39
+ }
40
+
41
+ export async function removeExpiringTags(
42
+ db: Database,
43
+ params: {
44
+ did: string
45
+ recordPath: string
46
+ tags: string[]
47
+ },
48
+ ): Promise<void> {
49
+ await db.db
50
+ .deleteFrom('expiring_tag')
51
+ .where('did', '=', params.did)
52
+ .where('recordPath', '=', params.recordPath)
53
+ .where('tag', 'in', params.tags)
54
+ .execute()
55
+ }
56
+
57
+ export async function deleteExpiringTagsByIds(
58
+ db: Database,
59
+ ids: number[],
60
+ ): Promise<void> {
61
+ await db.db.deleteFrom('expiring_tag').where('id', 'in', ids).execute()
62
+ }
63
+
64
+ export async function getExpiredTags(
65
+ db: Database,
66
+ ): Promise<ExpiringTagGroup[]> {
67
+ const now = new Date().toISOString()
68
+ const rows = await db.db
69
+ .selectFrom('expiring_tag')
70
+ .where('expiresAt', '<', now)
71
+ .selectAll()
72
+ .execute()
73
+
74
+ if (!rows.length) return []
75
+
76
+ // Group by (did, recordPath, createdBy) so each reversal event has the correct author
77
+ const grouped = new Map<string, ExpiringTagGroup>()
78
+ for (const row of rows) {
79
+ const key = `${row.did}|${row.recordPath}|${row.createdBy}`
80
+ let group = grouped.get(key)
81
+ if (!group) {
82
+ group = {
83
+ did: row.did,
84
+ recordPath: row.recordPath,
85
+ createdBy: row.createdBy,
86
+ tags: [],
87
+ ids: [],
88
+ }
89
+ grouped.set(key, group)
90
+ }
91
+ if (!group.tags.includes(row.tag)) {
92
+ group.tags.push(row.tag)
93
+ }
94
+ group.ids.push(row.id)
95
+ }
96
+
97
+ return [...grouped.values()]
98
+ }
@@ -46,6 +46,7 @@ import {
46
46
  import { QueryParams as QueryStatusParams } from '../lexicon/types/tools/ozone/moderation/queryStatuses'
47
47
  import { httpLogger as log } from '../logger'
48
48
  import { LABELER_HEADER_NAME, ParsedLabelers } from '../util'
49
+ import { insertExpiringTags, removeExpiringTags } from './expiring-tags'
49
50
  import {
50
51
  adjustModerationSubjectStatus,
51
52
  getStatusIdentifierFromSubject,
@@ -666,6 +667,31 @@ export class ModerationService {
666
667
  subject.blobCids,
667
668
  )
668
669
 
670
+ // Manage expiring tag rows for temporary tags
671
+ if (isModEventTag(event)) {
672
+ if (event.durationInHours && event.add.length > 0) {
673
+ const expiresAt = addHoursToDate(
674
+ event.durationInHours,
675
+ createdAt,
676
+ ).toISOString()
677
+ await insertExpiringTags(this.db, {
678
+ eventId: modEvent.id,
679
+ did: subjectInfo.subjectDid,
680
+ recordPath: subjectInfo.subjectUri ?? '',
681
+ tags: event.add,
682
+ expiresAt,
683
+ createdBy,
684
+ })
685
+ }
686
+ if (event.remove.length > 0) {
687
+ await removeExpiringTags(this.db, {
688
+ did: subjectInfo.subjectDid,
689
+ recordPath: subjectInfo.subjectUri ?? '',
690
+ tags: event.remove,
691
+ })
692
+ }
693
+ }
694
+
669
695
  if (isAgeAssurancePurgeEvent(event)) {
670
696
  await this.purgeAgeAssuranceEvents(subjectInfo.subjectDid)
671
697
  }