@atcute/bluesky-moderation 1.0.1

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 (55) hide show
  1. package/LICENSE +17 -0
  2. package/README.md +174 -0
  3. package/dist/behaviors.d.ts +41 -0
  4. package/dist/behaviors.js +56 -0
  5. package/dist/behaviors.js.map +1 -0
  6. package/dist/decision.d.ts +85 -0
  7. package/dist/decision.js +214 -0
  8. package/dist/decision.js.map +1 -0
  9. package/dist/index.d.ts +12 -0
  10. package/dist/index.js +13 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/internal/keyword-filter.d.ts +8 -0
  13. package/dist/internal/keyword-filter.js +27 -0
  14. package/dist/internal/keyword-filter.js.map +1 -0
  15. package/dist/keyword-filter.d.ts +26 -0
  16. package/dist/keyword-filter.js +61 -0
  17. package/dist/keyword-filter.js.map +1 -0
  18. package/dist/label.d.ts +73 -0
  19. package/dist/label.js +286 -0
  20. package/dist/label.js.map +1 -0
  21. package/dist/subjects/feed-generator.d.ts +3 -0
  22. package/dist/subjects/feed-generator.js +10 -0
  23. package/dist/subjects/feed-generator.js.map +1 -0
  24. package/dist/subjects/list.d.ts +3 -0
  25. package/dist/subjects/list.js +27 -0
  26. package/dist/subjects/list.js.map +1 -0
  27. package/dist/subjects/notification.d.ts +3 -0
  28. package/dist/subjects/notification.js +10 -0
  29. package/dist/subjects/notification.js.map +1 -0
  30. package/dist/subjects/post.d.ts +3 -0
  31. package/dist/subjects/post.js +215 -0
  32. package/dist/subjects/post.js.map +1 -0
  33. package/dist/subjects/profile.d.ts +3 -0
  34. package/dist/subjects/profile.js +27 -0
  35. package/dist/subjects/profile.js.map +1 -0
  36. package/dist/types.d.ts +39 -0
  37. package/dist/types.js +2 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/ui.d.ts +10 -0
  40. package/dist/ui.js +145 -0
  41. package/dist/ui.js.map +1 -0
  42. package/lib/behaviors.ts +65 -0
  43. package/lib/decision.ts +363 -0
  44. package/lib/index.ts +63 -0
  45. package/lib/internal/keyword-filter.ts +45 -0
  46. package/lib/keyword-filter.ts +95 -0
  47. package/lib/label.ts +353 -0
  48. package/lib/subjects/feed-generator.ts +22 -0
  49. package/lib/subjects/list.ts +41 -0
  50. package/lib/subjects/notification.ts +22 -0
  51. package/lib/subjects/post.ts +316 -0
  52. package/lib/subjects/profile.ts +42 -0
  53. package/lib/types.ts +61 -0
  54. package/lib/ui.ts +183 -0
  55. package/package.json +36 -0
package/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2
+ of this software and associated documentation files (the "Software"), to deal
3
+ in the Software without restriction, including without limitation the rights
4
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5
+ copies of the Software, and to permit persons to whom the Software is
6
+ furnished to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in all
9
+ copies or substantial portions of the Software.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,174 @@
1
+ # @atcute/bluesky-moderation
2
+
3
+ interprets Bluesky's content moderation labels.
4
+
5
+ ```ts
6
+ import type { XRPC } from '@atcute/client';
7
+ import type {
8
+ AppBskyActorDefs,
9
+ AppBskyFeedDefs,
10
+ AppBskyLabelerDefs,
11
+ At,
12
+ } from '@atcute/client/lexicons';
13
+
14
+ import {
15
+ DisplayContext,
16
+ getDisplayRestrictions,
17
+ interpretLabelerDefinitions,
18
+ interpretMutedWordPreferences,
19
+ LabelPreference,
20
+ moderatePost,
21
+ type ModerationPreferences,
22
+ } from '@atcute/bluesky-moderation';
23
+
24
+ declare const rpc: XRPC;
25
+
26
+ // first, let's get the user's preferences
27
+ const labelerDids = new Set<At.Did>([
28
+ // Bluesky moderation service
29
+ 'did:plc:ar7c4by46qjdydhdevvrndac',
30
+ ]);
31
+
32
+ const modPrefs: ModerationPreferences = {
33
+ adultContentEnabled: false,
34
+ globalLabelPrefs: {},
35
+ prefsByLabelers: {
36
+ 'did:plc:ar7c4by46qjdydhdevvrndac': {
37
+ labelPrefs: {},
38
+ },
39
+ },
40
+ keywordFilters: [],
41
+ hiddenPosts: [],
42
+ temporaryMutes: [],
43
+ };
44
+
45
+ {
46
+ const { data } = await rpc.get('app.bsky.actor.getPreferences', {});
47
+
48
+ const labelPrefs: AppBskyActorDefs.ContentLabelPref[] = [];
49
+
50
+ const globalLabelPrefs = (modPrefs.globalLabelPrefs ??= {});
51
+ const prefsByLabelers = (modPrefs.prefsByLabelers ??= {});
52
+
53
+ for (const pref of data.preferences) {
54
+ switch (pref.$type) {
55
+ case 'app.bsky.actor.defs#adultContentPref': {
56
+ modPrefs.adultContentEnabled = pref.enabled;
57
+ break;
58
+ }
59
+ case 'app.bsky.actor.defs#labelersPref': {
60
+ for (const labeler of pref.labelers) {
61
+ prefsByLabelers[labeler.did] ??= { labelPrefs: {} };
62
+ labelerDids.add(labeler.did);
63
+ }
64
+
65
+ break;
66
+ }
67
+ case 'app.bsky.actor.defs#contentLabelPref': {
68
+ labelPrefs.push(pref);
69
+ break;
70
+ }
71
+ case 'app.bsky.actor.defs#mutedWordsPref': {
72
+ modPrefs.keywordFilters = interpretMutedWordPreferences(pref);
73
+ break;
74
+ }
75
+ case 'app.bsky.actor.defs#hiddenPostsPref': {
76
+ modPrefs.hiddenPosts = pref.items as At.CanonicalResourceUri[];
77
+ break;
78
+ }
79
+ }
80
+ }
81
+
82
+ for (const { labelerDid, label, visibility } of labelPrefs) {
83
+ let pref: LabelPreference | undefined;
84
+ switch (visibility) {
85
+ case 'show':
86
+ case 'ignore': {
87
+ pref = LabelPreference.Ignore;
88
+ break;
89
+ }
90
+ case 'warn': {
91
+ pref = LabelPreference.Warn;
92
+ break;
93
+ }
94
+ case 'hide': {
95
+ pref = LabelPreference.Hide;
96
+ break;
97
+ }
98
+ }
99
+
100
+ if (labelerDid === undefined) {
101
+ globalLabelPrefs[label] = pref;
102
+ } else if (labelerDid in prefsByLabelers) {
103
+ const labelerPref = prefsByLabelers[labelerDid]!;
104
+
105
+ labelerPref.labelPrefs[label] = pref;
106
+ }
107
+ }
108
+ }
109
+
110
+ // grab labeler's definitions
111
+ let labelers: AppBskyLabelerDefs.LabelerViewDetailed[] = [];
112
+
113
+ {
114
+ const { data } = await rpc.get('app.bsky.labeler.getServices', {
115
+ params: {
116
+ dids: [...labelerDids],
117
+ detailed: true,
118
+ },
119
+ });
120
+
121
+ labelers = data.views.filter(
122
+ (view) => view.$type === 'app.bsky.labeler.defs#labelerViewDetailed',
123
+ );
124
+ }
125
+
126
+ // interpret the labeler's definitions into something the library can understand
127
+ const labelDefs = interpretLabelerDefinitions(labelers);
128
+
129
+ // then we call the appropriate moderation functions
130
+ {
131
+ declare const post: AppBskyFeedDefs.PostView;
132
+
133
+ const mod = moderatePost(post, {
134
+ viewerDid: 'did:plc:xyz',
135
+ labelDefs,
136
+ prefs: modPrefs,
137
+ });
138
+
139
+ // when displaying the post in feeds...
140
+ {
141
+ const ui = getDisplayRestrictions(mod, DisplayContext.ContentList);
142
+
143
+ if (ui.filters.length > 0) {
144
+ // don't include the post in the feed
145
+ }
146
+
147
+ if (ui.blurs.length > 0) {
148
+ // hide the post behind a cover
149
+
150
+ if (ui.noOverride) {
151
+ // don't allow the cover to be removed
152
+ }
153
+ }
154
+
155
+ if (ui.alerts.length > 0 || ui.informs.length > 0) {
156
+ // show warning/inform badges in the post
157
+ }
158
+ }
159
+
160
+ // when displaying an expanded version of the post...
161
+ {
162
+ const ui = getDisplayRestrictions(mod, DisplayContext.ContentView);
163
+
164
+ // ...
165
+ }
166
+
167
+ // when displaying images/videos of a post...
168
+ {
169
+ const ui = getDisplayRestrictions(mod, DisplayContext.ProfileMedia);
170
+
171
+ // ...
172
+ }
173
+ }
174
+ ```
@@ -0,0 +1,41 @@
1
+ export declare const enum LabelTarget {
2
+ /** label is intended for account's content */
3
+ Content = "content",
4
+ /** label is intended for account's profile */
5
+ Profile = "profile",
6
+ /** label is intended for account's content and profile */
7
+ Account = "account"
8
+ }
9
+ export declare const enum DisplayContext {
10
+ /** content in expanded view */
11
+ ContentView = "contentView",
12
+ /** images or video contained in content */
13
+ ContentMedia = "contentMedia",
14
+ /** content in a list/feed */
15
+ ContentList = "contentList",
16
+ /** profile in expanded view */
17
+ ProfileView = "profileView",
18
+ /** profile's avatar or banner */
19
+ ProfileMedia = "profileMedia",
20
+ /** profile in a list */
21
+ ProfileList = "profileList"
22
+ }
23
+ export declare const enum ModerationAction {
24
+ /** should cause blurring */
25
+ Blur = "blur",
26
+ /** should cause an alert */
27
+ Alert = "alert",
28
+ /** should cause a notice */
29
+ Inform = "inform"
30
+ }
31
+ export type BehaviorMapping = {
32
+ [C in DisplayContext]?: ModerationAction;
33
+ };
34
+ export type LabelBehaviorMatrix = {
35
+ [T in LabelTarget]: BehaviorMapping;
36
+ };
37
+ export declare const BLOCK_BEHAVIOR: BehaviorMapping;
38
+ export declare const MUTE_BEHAVIOR: BehaviorMapping;
39
+ export declare const KEYWORD_MUTE_BEHAVIOR: BehaviorMapping;
40
+ export declare const HIDE_BEHAVIOR: BehaviorMapping;
41
+ export declare const NOOP_BEHAVIOR: BehaviorMapping;
@@ -0,0 +1,56 @@
1
+ export var LabelTarget;
2
+ (function (LabelTarget) {
3
+ /** label is intended for account's content */
4
+ LabelTarget["Content"] = "content";
5
+ /** label is intended for account's profile */
6
+ LabelTarget["Profile"] = "profile";
7
+ /** label is intended for account's content and profile */
8
+ LabelTarget["Account"] = "account";
9
+ })(LabelTarget || (LabelTarget = {}));
10
+ export var DisplayContext;
11
+ (function (DisplayContext) {
12
+ /** content in expanded view */
13
+ DisplayContext["ContentView"] = "contentView";
14
+ /** images or video contained in content */
15
+ DisplayContext["ContentMedia"] = "contentMedia";
16
+ /** content in a list/feed */
17
+ DisplayContext["ContentList"] = "contentList";
18
+ /** profile in expanded view */
19
+ DisplayContext["ProfileView"] = "profileView";
20
+ /** profile's avatar or banner */
21
+ DisplayContext["ProfileMedia"] = "profileMedia";
22
+ /** profile in a list */
23
+ DisplayContext["ProfileList"] = "profileList";
24
+ })(DisplayContext || (DisplayContext = {}));
25
+ export var ModerationAction;
26
+ (function (ModerationAction) {
27
+ /** should cause blurring */
28
+ ModerationAction["Blur"] = "blur";
29
+ /** should cause an alert */
30
+ ModerationAction["Alert"] = "alert";
31
+ /** should cause a notice */
32
+ ModerationAction["Inform"] = "inform";
33
+ })(ModerationAction || (ModerationAction = {}));
34
+ export const BLOCK_BEHAVIOR = {
35
+ [DisplayContext.ProfileList]: ModerationAction.Blur,
36
+ [DisplayContext.ProfileView]: ModerationAction.Alert,
37
+ [DisplayContext.ProfileMedia]: ModerationAction.Blur,
38
+ [DisplayContext.ContentList]: ModerationAction.Blur,
39
+ [DisplayContext.ContentView]: ModerationAction.Blur,
40
+ };
41
+ export const MUTE_BEHAVIOR = {
42
+ [DisplayContext.ProfileList]: ModerationAction.Inform,
43
+ [DisplayContext.ProfileView]: ModerationAction.Alert,
44
+ [DisplayContext.ContentList]: ModerationAction.Blur,
45
+ [DisplayContext.ContentView]: ModerationAction.Inform,
46
+ };
47
+ export const KEYWORD_MUTE_BEHAVIOR = {
48
+ [DisplayContext.ContentList]: ModerationAction.Blur,
49
+ [DisplayContext.ContentView]: ModerationAction.Blur,
50
+ };
51
+ export const HIDE_BEHAVIOR = {
52
+ [DisplayContext.ContentList]: ModerationAction.Blur,
53
+ [DisplayContext.ContentView]: ModerationAction.Blur,
54
+ };
55
+ export const NOOP_BEHAVIOR = {};
56
+ //# sourceMappingURL=behaviors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behaviors.js","sourceRoot":"","sources":["../lib/behaviors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAkB,WAOjB;AAPD,WAAkB,WAAW;IAC5B,8CAA8C;IAC9C,kCAAmB,CAAA;IACnB,8CAA8C;IAC9C,kCAAmB,CAAA;IACnB,0DAA0D;IAC1D,kCAAmB,CAAA;AACpB,CAAC,EAPiB,WAAW,KAAX,WAAW,QAO5B;AAED,MAAM,CAAN,IAAkB,cAcjB;AAdD,WAAkB,cAAc;IAC/B,+BAA+B;IAC/B,6CAA2B,CAAA;IAC3B,2CAA2C;IAC3C,+CAA6B,CAAA;IAC7B,6BAA6B;IAC7B,6CAA2B,CAAA;IAE3B,+BAA+B;IAC/B,6CAA2B,CAAA;IAC3B,iCAAiC;IACjC,+CAA6B,CAAA;IAC7B,wBAAwB;IACxB,6CAA2B,CAAA;AAC5B,CAAC,EAdiB,cAAc,KAAd,cAAc,QAc/B;AAED,MAAM,CAAN,IAAkB,gBAOjB;AAPD,WAAkB,gBAAgB;IACjC,4BAA4B;IAC5B,iCAAa,CAAA;IACb,4BAA4B;IAC5B,mCAAe,CAAA;IACf,4BAA4B;IAC5B,qCAAiB,CAAA;AAClB,CAAC,EAPiB,gBAAgB,KAAhB,gBAAgB,QAOjC;AAKD,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC9C,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,IAAI;IACnD,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,KAAK;IACpD,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,gBAAgB,CAAC,IAAI;IAEpD,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,IAAI;IACnD,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,IAAI;CACnD,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAoB;IAC7C,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,MAAM;IACrD,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,KAAK;IAEpD,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,IAAI;IACnD,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,MAAM;CACrD,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAoB;IACrD,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,IAAI;IACnD,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,IAAI;CACnD,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAoB;IAC7C,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,IAAI;IACnD,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,IAAI;CACnD,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAoB,EAAE,CAAC"}
@@ -0,0 +1,85 @@
1
+ import type { AppBskyGraphDefs, At } from '@atcute/client/lexicons';
2
+ import { type BehaviorMapping, type LabelTarget } from './behaviors.js';
3
+ import type { Label, ModerationOptions } from './types.js';
4
+ import type { KeywordFilter } from './keyword-filter.js';
5
+ import { LabelPreference, type InterpretedLabelDefinition } from './label.js';
6
+ export declare const enum ModerationCauseType {
7
+ /** caused by a label */
8
+ Label = 1,
9
+ /** caused by viewer blocking the subject */
10
+ Blocking = 2,
11
+ /** caused by subject blocking the viewer */
12
+ BlockedBy = 3,
13
+ /** caused by viewer having a (permanent) mute on subject */
14
+ MutedPermanent = 4,
15
+ /** caused by a temporary mute */
16
+ MutedTemporary = 5,
17
+ /** caused by a keyword mute */
18
+ MutedKeyword = 6,
19
+ /** caused by a hidden post */
20
+ Hidden = 7
21
+ }
22
+ export interface BlockingModerationCause {
23
+ type: ModerationCauseType.Blocking;
24
+ priority: 3;
25
+ source: AppBskyGraphDefs.ListViewBasic | null;
26
+ downgraded: boolean;
27
+ }
28
+ export interface BlockedByModerationCause {
29
+ type: ModerationCauseType.BlockedBy;
30
+ priority: 4;
31
+ downgraded: boolean;
32
+ }
33
+ export interface HiddenModerationCause {
34
+ type: ModerationCauseType.Hidden;
35
+ priority: 6;
36
+ downgraded: boolean;
37
+ }
38
+ export interface LabelModerationCause {
39
+ type: ModerationCauseType.Label;
40
+ priority: 1 | 2 | 5 | 7 | 8;
41
+ source: At.Did | null;
42
+ label: Label;
43
+ labelDef: InterpretedLabelDefinition;
44
+ target: LabelTarget;
45
+ pref: LabelPreference;
46
+ behavior: BehaviorMapping;
47
+ noOverride: boolean;
48
+ downgraded: boolean;
49
+ }
50
+ export interface MutedPermanentModerationCause {
51
+ type: ModerationCauseType.MutedPermanent;
52
+ priority: 6;
53
+ source: AppBskyGraphDefs.ListViewBasic | null;
54
+ downgraded: boolean;
55
+ }
56
+ export interface MutedTemporaryModerationCause {
57
+ type: ModerationCauseType.MutedTemporary;
58
+ priority: 6;
59
+ downgraded: boolean;
60
+ }
61
+ export interface MutedKeywordModerationCause {
62
+ type: ModerationCauseType.MutedKeyword;
63
+ priority: 6;
64
+ source: KeywordFilter;
65
+ downgraded: boolean;
66
+ }
67
+ export type ModerationCause = BlockedByModerationCause | BlockingModerationCause | HiddenModerationCause | LabelModerationCause | MutedKeywordModerationCause | MutedPermanentModerationCause | MutedTemporaryModerationCause;
68
+ export interface ModerationDecision {
69
+ authorDid: At.Did;
70
+ isMe: boolean;
71
+ causes: ModerationCause[];
72
+ }
73
+ export declare const createModerationDecision: (authorDid: At.Did, { viewerDid }: ModerationOptions) => ModerationDecision;
74
+ type FalsyValue = 0 | '' | false | null | undefined;
75
+ export declare const mergeModerationDecisions: (sources_0: ModerationDecision, sources_1: ModerationDecision | FalsyValue, ...sources: (ModerationDecision | FalsyValue)[]) => ModerationDecision;
76
+ export declare const considerHidden: (decision: ModerationDecision) => void;
77
+ export declare const considerBlocking: (decision: ModerationDecision, source: AppBskyGraphDefs.ListViewBasic | null) => void;
78
+ export declare const considerBlockedBy: (decision: ModerationDecision) => void;
79
+ export declare const considerPermanentMute: (decision: ModerationDecision, source: AppBskyGraphDefs.ListViewBasic | null) => void;
80
+ export declare const considerTemporaryMute: (decision: ModerationDecision, { prefs }: ModerationOptions) => void;
81
+ export declare const considerKeywordMute: (decision: ModerationDecision, source: KeywordFilter) => void;
82
+ export declare const considerLabels: (decision: ModerationDecision, target: LabelTarget, labels: Label[] | undefined, opts: ModerationOptions) => void;
83
+ export declare const considerLabel: (decision: ModerationDecision, target: LabelTarget, label: Label, { viewerDid, prefs, labelDefs }: ModerationOptions) => void;
84
+ export declare const downgradeDecision: <T extends ModerationDecision | undefined>(decision: T) => T;
85
+ export {};
@@ -0,0 +1,214 @@
1
+ import { DisplayContext, ModerationAction } from './behaviors.js';
2
+ import { BUILTIN_LABELS, isCustomLabelValue, LabelFlags, LabelPreference, } from './label.js';
3
+ var ModerationSeverity;
4
+ (function (ModerationSeverity) {
5
+ ModerationSeverity[ModerationSeverity["High"] = 1] = "High";
6
+ ModerationSeverity[ModerationSeverity["Medium"] = 2] = "Medium";
7
+ ModerationSeverity[ModerationSeverity["Low"] = 3] = "Low";
8
+ })(ModerationSeverity || (ModerationSeverity = {}));
9
+ export var ModerationCauseType;
10
+ (function (ModerationCauseType) {
11
+ /** caused by a label */
12
+ ModerationCauseType[ModerationCauseType["Label"] = 1] = "Label";
13
+ /** caused by viewer blocking the subject */
14
+ ModerationCauseType[ModerationCauseType["Blocking"] = 2] = "Blocking";
15
+ /** caused by subject blocking the viewer */
16
+ ModerationCauseType[ModerationCauseType["BlockedBy"] = 3] = "BlockedBy";
17
+ /** caused by viewer having a (permanent) mute on subject */
18
+ ModerationCauseType[ModerationCauseType["MutedPermanent"] = 4] = "MutedPermanent";
19
+ /** caused by a temporary mute */
20
+ ModerationCauseType[ModerationCauseType["MutedTemporary"] = 5] = "MutedTemporary";
21
+ /** caused by a keyword mute */
22
+ ModerationCauseType[ModerationCauseType["MutedKeyword"] = 6] = "MutedKeyword";
23
+ /** caused by a hidden post */
24
+ ModerationCauseType[ModerationCauseType["Hidden"] = 7] = "Hidden";
25
+ })(ModerationCauseType || (ModerationCauseType = {}));
26
+ export const createModerationDecision = (authorDid, { viewerDid }) => {
27
+ return {
28
+ authorDid: authorDid,
29
+ isMe: authorDid === viewerDid,
30
+ causes: [],
31
+ };
32
+ };
33
+ export const mergeModerationDecisions = (...sources) => {
34
+ return {
35
+ authorDid: sources[0].authorDid,
36
+ isMe: sources[0].isMe,
37
+ causes: sources.filter((source) => !!source).flatMap((source) => source.causes),
38
+ };
39
+ };
40
+ export const considerHidden = (decision) => {
41
+ decision.causes.push({
42
+ type: ModerationCauseType.Hidden,
43
+ priority: 6,
44
+ downgraded: false,
45
+ });
46
+ };
47
+ export const considerBlocking = (decision, source) => {
48
+ if (decision.isMe) {
49
+ return;
50
+ }
51
+ decision.causes.push({
52
+ type: ModerationCauseType.Blocking,
53
+ priority: 3,
54
+ source: source,
55
+ downgraded: false,
56
+ });
57
+ };
58
+ export const considerBlockedBy = (decision) => {
59
+ if (decision.isMe) {
60
+ return;
61
+ }
62
+ decision.causes.push({
63
+ type: ModerationCauseType.BlockedBy,
64
+ priority: 4,
65
+ downgraded: false,
66
+ });
67
+ };
68
+ export const considerPermanentMute = (decision, source) => {
69
+ if (decision.isMe) {
70
+ return;
71
+ }
72
+ decision.causes.push({
73
+ type: ModerationCauseType.MutedPermanent,
74
+ priority: 6,
75
+ source: source,
76
+ downgraded: false,
77
+ });
78
+ };
79
+ export const considerTemporaryMute = (decision, { prefs }) => {
80
+ if (decision.isMe) {
81
+ return;
82
+ }
83
+ if (prefs.temporaryMutes?.includes(decision.authorDid)) {
84
+ decision.causes.push({
85
+ type: ModerationCauseType.MutedTemporary,
86
+ priority: 6,
87
+ downgraded: false,
88
+ });
89
+ }
90
+ };
91
+ export const considerKeywordMute = (decision, source) => {
92
+ decision.causes.push({
93
+ type: ModerationCauseType.MutedKeyword,
94
+ priority: 6,
95
+ source: source,
96
+ downgraded: false,
97
+ });
98
+ };
99
+ export const considerLabels = (decision, target, labels, opts) => {
100
+ if (labels?.length) {
101
+ for (let idx = 0, len = labels.length; idx < len; idx++) {
102
+ considerLabel(decision, target, labels[idx], opts);
103
+ }
104
+ }
105
+ };
106
+ export const considerLabel = (decision, target, label, { viewerDid, prefs, labelDefs }) => {
107
+ const { src, val } = label;
108
+ /// 1. grab the label definition
109
+ let labelDef;
110
+ if (isCustomLabelValue(val)) {
111
+ labelDef = labelDefs?.[src]?.[val];
112
+ }
113
+ if (labelDef === undefined) {
114
+ labelDef = BUILTIN_LABELS[val];
115
+ }
116
+ if (labelDef === undefined) {
117
+ return;
118
+ }
119
+ /// 2. check applicability
120
+ if (labelDef.flags & LabelFlags.UnauthenticatedOnly && viewerDid !== undefined) {
121
+ // skip if label is only for signed-out users
122
+ return;
123
+ }
124
+ const isConfigurable = !(labelDef.flags & LabelFlags.NoConfigurable);
125
+ const isAdultOnly = !!(labelDef.flags & LabelFlags.AdultOnly);
126
+ const isSelfApplied = src === decision.authorDid;
127
+ let labelerPref;
128
+ if (!isSelfApplied) {
129
+ labelerPref = prefs.prefsByLabelers?.[src];
130
+ if (labelerPref === undefined) {
131
+ // skip if we're looking at an unconfigured labeler
132
+ return;
133
+ }
134
+ }
135
+ else {
136
+ if (labelDef.flags & LabelFlags.NoSelf) {
137
+ // skip if label is not allowed to be self-applied
138
+ return;
139
+ }
140
+ }
141
+ let pref;
142
+ if (isConfigurable) {
143
+ if (isAdultOnly && !prefs.adultContentEnabled) {
144
+ pref = LabelPreference.Hide;
145
+ }
146
+ else {
147
+ pref = labelerPref?.labelPrefs[val] ?? prefs.globalLabelPrefs?.[val] ?? labelDef.defaultPref;
148
+ }
149
+ }
150
+ else {
151
+ pref = labelDef.defaultPref;
152
+ }
153
+ // skip if label is configured to ignore
154
+ if (pref === LabelPreference.Ignore) {
155
+ return;
156
+ }
157
+ const behavior = labelDef.behavior[target];
158
+ const severity = getModerationSeverity(behavior);
159
+ let priority;
160
+ if (labelDef.flags & LabelFlags.NoOverride || (isAdultOnly && !prefs.adultContentEnabled)) {
161
+ priority = 1;
162
+ }
163
+ else if (pref === LabelPreference.Hide) {
164
+ priority = 2;
165
+ }
166
+ else if (severity === ModerationSeverity.High) {
167
+ priority = 5;
168
+ }
169
+ else if (severity === ModerationSeverity.Medium) {
170
+ priority = 7;
171
+ }
172
+ else {
173
+ priority = 8;
174
+ }
175
+ let noOverride = false;
176
+ if (labelDef.flags & LabelFlags.NoOverride || (isAdultOnly && !prefs.adultContentEnabled)) {
177
+ noOverride = true;
178
+ }
179
+ decision.causes.push({
180
+ type: ModerationCauseType.Label,
181
+ priority,
182
+ source: isSelfApplied ? label.src : null,
183
+ label: label,
184
+ labelDef: labelDef,
185
+ target: target,
186
+ pref: pref,
187
+ behavior: behavior,
188
+ noOverride: noOverride,
189
+ downgraded: false,
190
+ });
191
+ };
192
+ const getModerationSeverity = (behavior) => {
193
+ if (behavior[DisplayContext.ProfileView] === ModerationAction.Blur ||
194
+ behavior[DisplayContext.ContentView] === ModerationAction.Blur) {
195
+ return ModerationSeverity.High;
196
+ }
197
+ if (behavior[DisplayContext.ContentList] === ModerationAction.Blur ||
198
+ behavior[DisplayContext.ContentMedia] === ModerationAction.Blur) {
199
+ return ModerationSeverity.Medium;
200
+ }
201
+ return ModerationSeverity.Low;
202
+ };
203
+ export const downgradeDecision = (decision) => {
204
+ if (decision === undefined) {
205
+ return decision;
206
+ }
207
+ const causes = decision.causes;
208
+ for (let idx = 0, len = causes.length; idx < len; idx++) {
209
+ const cause = causes[idx];
210
+ cause.downgraded = true;
211
+ }
212
+ return decision;
213
+ };
214
+ //# sourceMappingURL=decision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.js","sourceRoot":"","sources":["../lib/decision.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import '@atcute/bluesky/lexicons';
2
+ export { DisplayContext, LabelTarget, ModerationAction, type BehaviorMapping, type LabelBehaviorMatrix, } from './behaviors.js';
3
+ export { ModerationCauseType, type BlockedByModerationCause, type BlockingModerationCause, type HiddenModerationCause, type LabelModerationCause, type ModerationCause, type ModerationDecision, type MutedKeywordModerationCause, type MutedPermanentModerationCause, type MutedTemporaryModerationCause, } from './decision.js';
4
+ export { createKeywordPattern, interpretMutedWordPreference, interpretMutedWordPreferences, KeywordFilterFlags, type KeywordFilter, type KeywordMatch, } from './keyword-filter.js';
5
+ export { BlurLevel, interpretLabelerDefinition, interpretLabelerDefinitions, interpretLabelValueDefinition, isCustomLabelValue, LabelFlags, LabelPreference, SeverityLevel, type InterpretedLabelDefinition, type InterpretedLabelMapping, type LabelLocale, } from './label.js';
6
+ export { type FeedGeneratorSubject, type Label, type LabelerPreference, type ListSubject, type ModerationOptions, type ModerationPreferences, type NotificationSubject, type PostSubject, type ProfileSubject, } from './types.js';
7
+ export { getDisplayRestrictions, type DisplayRestrictions } from './ui.js';
8
+ export { moderateFeedGenerator } from './subjects/feed-generator.js';
9
+ export { moderateList } from './subjects/list.js';
10
+ export { moderateNotification } from './subjects/notification.js';
11
+ export { moderatePost } from './subjects/post.js';
12
+ export { moderateProfile } from './subjects/profile.js';
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ import '@atcute/bluesky/lexicons';
2
+ export { DisplayContext, LabelTarget, ModerationAction, } from './behaviors.js';
3
+ export { ModerationCauseType, } from './decision.js';
4
+ export { createKeywordPattern, interpretMutedWordPreference, interpretMutedWordPreferences, KeywordFilterFlags, } from './keyword-filter.js';
5
+ export { BlurLevel, interpretLabelerDefinition, interpretLabelerDefinitions, interpretLabelValueDefinition, isCustomLabelValue, LabelFlags, LabelPreference, SeverityLevel, } from './label.js';
6
+ export {} from './types.js';
7
+ export { getDisplayRestrictions } from './ui.js';
8
+ export { moderateFeedGenerator } from './subjects/feed-generator.js';
9
+ export { moderateList } from './subjects/list.js';
10
+ export { moderateNotification } from './subjects/notification.js';
11
+ export { moderatePost } from './subjects/post.js';
12
+ export { moderateProfile } from './subjects/profile.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,0BAA0B,CAAC;AAElC,OAAO,EACN,cAAc,EACd,WAAW,EACX,gBAAgB,GAGhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,mBAAmB,GAUnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACN,oBAAoB,EACpB,4BAA4B,EAC5B,6BAA6B,EAC7B,kBAAkB,GAGlB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,SAAS,EACT,0BAA0B,EAC1B,2BAA2B,EAC3B,6BAA6B,EAC7B,kBAAkB,EAClB,UAAU,EACV,eAAe,EACf,aAAa,GAIb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAUN,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,sBAAsB,EAA4B,MAAM,SAAS,CAAC;AAE3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { AppBskyActorDefs } from '@atcute/client/lexicons';
2
+ import { type KeywordFilter } from '../keyword-filter.js';
3
+ export declare const matchesKeywordFilters: ({ filters, text, tags, actor, }: {
4
+ filters: KeywordFilter[];
5
+ text: string;
6
+ tags?: string[];
7
+ actor?: AppBskyActorDefs.ProfileView | AppBskyActorDefs.ProfileViewBasic;
8
+ }) => KeywordFilter | null;
@@ -0,0 +1,27 @@
1
+ import { KeywordFilterFlags } from '../keyword-filter.js';
2
+ const EMPTY_ARRAY = [];
3
+ export const matchesKeywordFilters = ({ filters, text, tags = EMPTY_ARRAY, actor, }) => {
4
+ for (let i = 0, il = filters.length; i < il; i++) {
5
+ const filter = filters[i];
6
+ if (actor && filter.flags & KeywordFilterFlags.NoFollowing) {
7
+ if (actor.viewer?.following) {
8
+ continue;
9
+ }
10
+ }
11
+ if (filter.flags & KeywordFilterFlags.ApplyTopic) {
12
+ for (let j = 0, jl = tags.length; j < jl; j++) {
13
+ const tag = tags[j];
14
+ if (filter.pattern.test(tag)) {
15
+ return filter;
16
+ }
17
+ }
18
+ }
19
+ if (filter.flags & KeywordFilterFlags.ApplyContent) {
20
+ if (filter.pattern.test(text)) {
21
+ return filter;
22
+ }
23
+ }
24
+ }
25
+ return null;
26
+ };
27
+ //# sourceMappingURL=keyword-filter.js.map