@clioplaylists/clio 0.1.0

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 (170) hide show
  1. package/dist/.env +7 -0
  2. package/dist/api/com/clioplaylists/alpha/actor/getProfile.js +37 -0
  3. package/dist/api/com/clioplaylists/alpha/feed/getSongs.js +37 -0
  4. package/dist/api/health.js +32 -0
  5. package/dist/api/index.js +43 -0
  6. package/dist/api/util.js +17 -0
  7. package/dist/auth-verifier.js +473 -0
  8. package/dist/client.js +40 -0
  9. package/dist/config.js +65 -0
  10. package/dist/context.js +19 -0
  11. package/dist/dataplane/bsync/index.js +150 -0
  12. package/dist/dataplane/client.js +165 -0
  13. package/dist/dataplane/index.js +18 -0
  14. package/dist/dataplane/server/background.js +51 -0
  15. package/dist/dataplane/server/db/database-schema.js +2 -0
  16. package/dist/dataplane/server/db/db.js +228 -0
  17. package/dist/dataplane/server/db/index.js +17 -0
  18. package/dist/dataplane/server/db/migrations/20230309T045948368Z-init.js +117 -0
  19. package/dist/dataplane/server/db/migrations/20230420T211446071Z-did-cache.js +15 -0
  20. package/dist/dataplane/server/db/migrations/index.js +41 -0
  21. package/dist/dataplane/server/db/migrations/provider.js +31 -0
  22. package/dist/dataplane/server/db/pagination.js +144 -0
  23. package/dist/dataplane/server/db/tables/actor-sync.js +4 -0
  24. package/dist/dataplane/server/db/tables/actor.js +4 -0
  25. package/dist/dataplane/server/db/tables/artist-list-item.js +4 -0
  26. package/dist/dataplane/server/db/tables/artist.js +4 -0
  27. package/dist/dataplane/server/db/tables/playlist-idea.js +4 -0
  28. package/dist/dataplane/server/db/tables/playlist-item.js +4 -0
  29. package/dist/dataplane/server/db/tables/playlist.js +4 -0
  30. package/dist/dataplane/server/db/tables/profile.js +4 -0
  31. package/dist/dataplane/server/db/tables/record.js +4 -0
  32. package/dist/dataplane/server/db/tables/song.js +4 -0
  33. package/dist/dataplane/server/db/types.js +2 -0
  34. package/dist/dataplane/server/db/util.js +48 -0
  35. package/dist/dataplane/server/index.js +52 -0
  36. package/dist/dataplane/server/indexing/index.js +321 -0
  37. package/dist/dataplane/server/indexing/plugins/playlist-idea.js +163 -0
  38. package/dist/dataplane/server/indexing/plugins/profile.js +81 -0
  39. package/dist/dataplane/server/indexing/processor.js +90 -0
  40. package/dist/dataplane/server/routes/blocks.js +95 -0
  41. package/dist/dataplane/server/routes/feed-gens.js +56 -0
  42. package/dist/dataplane/server/routes/feeds.js +128 -0
  43. package/dist/dataplane/server/routes/follows.js +122 -0
  44. package/dist/dataplane/server/routes/identity.js +56 -0
  45. package/dist/dataplane/server/routes/index.js +19 -0
  46. package/dist/dataplane/server/routes/interactions.js +111 -0
  47. package/dist/dataplane/server/routes/labels.js +73 -0
  48. package/dist/dataplane/server/routes/likes.js +76 -0
  49. package/dist/dataplane/server/routes/lists.js +77 -0
  50. package/dist/dataplane/server/routes/moderation.js +92 -0
  51. package/dist/dataplane/server/routes/mutes.js +166 -0
  52. package/dist/dataplane/server/routes/notifs.js +137 -0
  53. package/dist/dataplane/server/routes/posts.js +19 -0
  54. package/dist/dataplane/server/routes/profile.js +61 -0
  55. package/dist/dataplane/server/routes/quotes.js +26 -0
  56. package/dist/dataplane/server/routes/records.js +88 -0
  57. package/dist/dataplane/server/routes/relationships.js +157 -0
  58. package/dist/dataplane/server/routes/reposts.js +59 -0
  59. package/dist/dataplane/server/routes/search.js +70 -0
  60. package/dist/dataplane/server/routes/starter-packs.js +24 -0
  61. package/dist/dataplane/server/routes/suggestions.js +134 -0
  62. package/dist/dataplane/server/routes/sync.js +14 -0
  63. package/dist/dataplane/server/routes/threads.js +31 -0
  64. package/dist/dataplane/server/subscription.js +114 -0
  65. package/dist/dataplane/server/util.js +117 -0
  66. package/dist/error.js +14 -0
  67. package/dist/index.js +115 -0
  68. package/dist/lexicons/index.js +638 -0
  69. package/dist/lexicons/lexicons.js +4551 -0
  70. package/dist/lexicons/types/com/atproto/admin/defs.js +54 -0
  71. package/dist/lexicons/types/com/atproto/admin/deleteAccount.js +2 -0
  72. package/dist/lexicons/types/com/atproto/admin/disableAccountInvites.js +2 -0
  73. package/dist/lexicons/types/com/atproto/admin/disableInviteCodes.js +2 -0
  74. package/dist/lexicons/types/com/atproto/admin/enableAccountInvites.js +2 -0
  75. package/dist/lexicons/types/com/atproto/admin/getAccountInfo.js +2 -0
  76. package/dist/lexicons/types/com/atproto/admin/getAccountInfos.js +2 -0
  77. package/dist/lexicons/types/com/atproto/admin/getInviteCodes.js +2 -0
  78. package/dist/lexicons/types/com/atproto/admin/getSubjectStatus.js +2 -0
  79. package/dist/lexicons/types/com/atproto/admin/searchAccounts.js +2 -0
  80. package/dist/lexicons/types/com/atproto/admin/sendEmail.js +2 -0
  81. package/dist/lexicons/types/com/atproto/admin/updateAccountEmail.js +2 -0
  82. package/dist/lexicons/types/com/atproto/admin/updateAccountHandle.js +2 -0
  83. package/dist/lexicons/types/com/atproto/admin/updateAccountPassword.js +2 -0
  84. package/dist/lexicons/types/com/atproto/admin/updateSubjectStatus.js +2 -0
  85. package/dist/lexicons/types/com/atproto/identity/defs.js +14 -0
  86. package/dist/lexicons/types/com/atproto/identity/getRecommendedDidCredentials.js +2 -0
  87. package/dist/lexicons/types/com/atproto/identity/refreshIdentity.js +2 -0
  88. package/dist/lexicons/types/com/atproto/identity/requestPlcOperationSignature.js +2 -0
  89. package/dist/lexicons/types/com/atproto/identity/resolveDid.js +2 -0
  90. package/dist/lexicons/types/com/atproto/identity/resolveHandle.js +2 -0
  91. package/dist/lexicons/types/com/atproto/identity/resolveIdentity.js +2 -0
  92. package/dist/lexicons/types/com/atproto/identity/signPlcOperation.js +2 -0
  93. package/dist/lexicons/types/com/atproto/identity/submitPlcOperation.js +2 -0
  94. package/dist/lexicons/types/com/atproto/identity/updateHandle.js +2 -0
  95. package/dist/lexicons/types/com/atproto/label/defs.js +54 -0
  96. package/dist/lexicons/types/com/atproto/label/queryLabels.js +2 -0
  97. package/dist/lexicons/types/com/atproto/label/subscribeLabels.js +24 -0
  98. package/dist/lexicons/types/com/atproto/lexicon/schema.js +15 -0
  99. package/dist/lexicons/types/com/atproto/moderation/createReport.js +2 -0
  100. package/dist/lexicons/types/com/atproto/moderation/defs.js +20 -0
  101. package/dist/lexicons/types/com/atproto/repo/applyWrites.js +64 -0
  102. package/dist/lexicons/types/com/atproto/repo/createRecord.js +2 -0
  103. package/dist/lexicons/types/com/atproto/repo/defs.js +14 -0
  104. package/dist/lexicons/types/com/atproto/repo/deleteRecord.js +2 -0
  105. package/dist/lexicons/types/com/atproto/repo/describeRepo.js +2 -0
  106. package/dist/lexicons/types/com/atproto/repo/getRecord.js +2 -0
  107. package/dist/lexicons/types/com/atproto/repo/importRepo.js +2 -0
  108. package/dist/lexicons/types/com/atproto/repo/listMissingBlobs.js +14 -0
  109. package/dist/lexicons/types/com/atproto/repo/listRecords.js +14 -0
  110. package/dist/lexicons/types/com/atproto/repo/putRecord.js +2 -0
  111. package/dist/lexicons/types/com/atproto/repo/strongRef.js +15 -0
  112. package/dist/lexicons/types/com/atproto/repo/uploadBlob.js +2 -0
  113. package/dist/lexicons/types/com/atproto/server/activateAccount.js +2 -0
  114. package/dist/lexicons/types/com/atproto/server/checkAccountStatus.js +2 -0
  115. package/dist/lexicons/types/com/atproto/server/confirmEmail.js +2 -0
  116. package/dist/lexicons/types/com/atproto/server/createAccount.js +2 -0
  117. package/dist/lexicons/types/com/atproto/server/createAppPassword.js +14 -0
  118. package/dist/lexicons/types/com/atproto/server/createInviteCode.js +2 -0
  119. package/dist/lexicons/types/com/atproto/server/createInviteCodes.js +14 -0
  120. package/dist/lexicons/types/com/atproto/server/createSession.js +2 -0
  121. package/dist/lexicons/types/com/atproto/server/deactivateAccount.js +2 -0
  122. package/dist/lexicons/types/com/atproto/server/defs.js +24 -0
  123. package/dist/lexicons/types/com/atproto/server/deleteAccount.js +2 -0
  124. package/dist/lexicons/types/com/atproto/server/deleteSession.js +2 -0
  125. package/dist/lexicons/types/com/atproto/server/describeServer.js +24 -0
  126. package/dist/lexicons/types/com/atproto/server/getAccountInviteCodes.js +2 -0
  127. package/dist/lexicons/types/com/atproto/server/getServiceAuth.js +2 -0
  128. package/dist/lexicons/types/com/atproto/server/getSession.js +2 -0
  129. package/dist/lexicons/types/com/atproto/server/listAppPasswords.js +14 -0
  130. package/dist/lexicons/types/com/atproto/server/refreshSession.js +2 -0
  131. package/dist/lexicons/types/com/atproto/server/requestAccountDelete.js +2 -0
  132. package/dist/lexicons/types/com/atproto/server/requestEmailConfirmation.js +2 -0
  133. package/dist/lexicons/types/com/atproto/server/requestEmailUpdate.js +2 -0
  134. package/dist/lexicons/types/com/atproto/server/requestPasswordReset.js +2 -0
  135. package/dist/lexicons/types/com/atproto/server/reserveSigningKey.js +2 -0
  136. package/dist/lexicons/types/com/atproto/server/resetPassword.js +2 -0
  137. package/dist/lexicons/types/com/atproto/server/revokeAppPassword.js +2 -0
  138. package/dist/lexicons/types/com/atproto/server/updateEmail.js +2 -0
  139. package/dist/lexicons/types/com/atproto/sync/getBlob.js +2 -0
  140. package/dist/lexicons/types/com/atproto/sync/getBlocks.js +2 -0
  141. package/dist/lexicons/types/com/atproto/sync/getCheckout.js +2 -0
  142. package/dist/lexicons/types/com/atproto/sync/getHead.js +2 -0
  143. package/dist/lexicons/types/com/atproto/sync/getLatestCommit.js +2 -0
  144. package/dist/lexicons/types/com/atproto/sync/getRecord.js +2 -0
  145. package/dist/lexicons/types/com/atproto/sync/getRepo.js +2 -0
  146. package/dist/lexicons/types/com/atproto/sync/getRepoStatus.js +2 -0
  147. package/dist/lexicons/types/com/atproto/sync/listBlobs.js +2 -0
  148. package/dist/lexicons/types/com/atproto/sync/listRepos.js +14 -0
  149. package/dist/lexicons/types/com/atproto/sync/listReposByCollection.js +14 -0
  150. package/dist/lexicons/types/com/atproto/sync/notifyOfUpdate.js +2 -0
  151. package/dist/lexicons/types/com/atproto/sync/requestCrawl.js +2 -0
  152. package/dist/lexicons/types/com/atproto/sync/subscribeRepos.js +64 -0
  153. package/dist/lexicons/types/com/atproto/temp/addReservedHandle.js +2 -0
  154. package/dist/lexicons/types/com/atproto/temp/checkSignupQueue.js +2 -0
  155. package/dist/lexicons/types/com/atproto/temp/fetchLabels.js +2 -0
  156. package/dist/lexicons/types/com/atproto/temp/requestPhoneVerification.js +2 -0
  157. package/dist/lexicons/types/com/clioplaylists/alpha/actor/profile.js +15 -0
  158. package/dist/lexicons/types/com/clioplaylists/alpha/feed/defs.js +24 -0
  159. package/dist/lexicons/types/com/clioplaylists/alpha/feed/getSongs.js +2 -0
  160. package/dist/lexicons/types/com/clioplaylists/alpha/feed/playlistIdea.js +35 -0
  161. package/dist/lexicons/types/com/clioplaylists/alpha/feed/song.js +25 -0
  162. package/dist/lexicons/util.js +13 -0
  163. package/dist/logger.js +26 -0
  164. package/dist/rpc/clio_connect.js +110 -0
  165. package/dist/rpc/clio_pb.js +1365 -0
  166. package/dist/start.js +13 -0
  167. package/dist/util/retry.js +16 -0
  168. package/dist/util/uris.js +7 -0
  169. package/dist/util.js +119 -0
  170. package/package.json +73 -0
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const ui8 = __importStar(require("uint8arrays"));
37
+ const common_1 = require("@atproto/common");
38
+ exports.default = (db) => ({
39
+ async getLabels(req) {
40
+ const { subjects, issuers } = req;
41
+ if (subjects.length === 0 || issuers.length === 0) {
42
+ return { labels: [] };
43
+ }
44
+ const res = await db.db
45
+ .selectFrom('label')
46
+ .where('uri', 'in', subjects)
47
+ .where('src', 'in', issuers)
48
+ .selectAll()
49
+ .execute();
50
+ const labelsBySubject = new Map();
51
+ res.forEach((l) => {
52
+ const labels = labelsBySubject.get(l.uri) ?? [];
53
+ labels.push(l);
54
+ labelsBySubject.set(l.uri, labels);
55
+ });
56
+ // intentionally duplicate label results, appview frontend should be defensive to this
57
+ const labels = subjects.flatMap((sub) => {
58
+ const labelsForSub = labelsBySubject.get(sub) ?? [];
59
+ return labelsForSub.map((l) => {
60
+ const formatted = (0, common_1.noUndefinedVals)({
61
+ ...l,
62
+ cid: l.cid === '' ? undefined : l.cid,
63
+ neg: l.neg === true ? true : undefined,
64
+ });
65
+ return ui8.fromString(JSON.stringify(formatted), 'utf8');
66
+ });
67
+ });
68
+ return { labels };
69
+ },
70
+ async getAllLabelers() {
71
+ throw new Error('not implemented');
72
+ },
73
+ });
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_assert_1 = __importDefault(require("node:assert"));
7
+ const common_1 = require("@atproto/common");
8
+ const pagination_1 = require("../db/pagination");
9
+ exports.default = (db) => ({
10
+ async getLikesBySubjectSorted(req) {
11
+ const { subject, cursor, limit } = req;
12
+ const { ref } = db.db.dynamic;
13
+ if (!subject?.uri) {
14
+ return { uris: [] };
15
+ }
16
+ // @NOTE ignoring subject.cid
17
+ let builder = db.db
18
+ .selectFrom('like')
19
+ .where('like.subject', '=', subject?.uri)
20
+ .selectAll('like');
21
+ const keyset = new pagination_1.TimeCidKeyset(ref('like.sortAt'), ref('like.cid'));
22
+ builder = (0, pagination_1.paginate)(builder, {
23
+ limit,
24
+ cursor,
25
+ keyset,
26
+ });
27
+ const likes = await builder.execute();
28
+ return {
29
+ uris: likes.map((l) => l.uri),
30
+ cursor: keyset.packFromResult(likes),
31
+ };
32
+ },
33
+ // @NOTE deprecated in favor of getLikesBySubjectSorted
34
+ async getLikesBySubject(req, context) {
35
+ (0, node_assert_1.default)(this.getLikesBySubjectSorted);
36
+ return this.getLikesBySubjectSorted(req, context);
37
+ },
38
+ async getLikesByActorAndSubjects(req) {
39
+ const { actorDid, refs } = req;
40
+ if (refs.length === 0) {
41
+ return { uris: [] };
42
+ }
43
+ // @NOTE ignoring ref.cid
44
+ const res = await db.db
45
+ .selectFrom('like')
46
+ .where('creator', '=', actorDid)
47
+ .where('subject', 'in', refs.map(({ uri }) => uri))
48
+ .selectAll()
49
+ .execute();
50
+ const bySubject = (0, common_1.keyBy)(res, 'subject');
51
+ const uris = refs.map(({ uri }) => bySubject.get(uri)?.uri ?? '');
52
+ return { uris };
53
+ },
54
+ async getActorLikes(req) {
55
+ const { actorDid, limit, cursor } = req;
56
+ const { ref } = db.db.dynamic;
57
+ let builder = db.db
58
+ .selectFrom('like')
59
+ .where('like.creator', '=', actorDid)
60
+ .selectAll();
61
+ const keyset = new pagination_1.TimeCidKeyset(ref('like.sortAt'), ref('like.cid'));
62
+ builder = (0, pagination_1.paginate)(builder, {
63
+ limit,
64
+ cursor,
65
+ keyset,
66
+ });
67
+ const likes = await builder.execute();
68
+ return {
69
+ likes: likes.map((l) => ({
70
+ uri: l.uri,
71
+ subject: l.subject,
72
+ })),
73
+ cursor: keyset.packFromResult(likes),
74
+ };
75
+ },
76
+ });
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const common_1 = require("@atproto/common");
4
+ const pagination_1 = require("../db/pagination");
5
+ const util_1 = require("../db/util");
6
+ exports.default = (db) => ({
7
+ async getActorLists(req) {
8
+ const { actorDid, cursor, limit } = req;
9
+ const { ref } = db.db.dynamic;
10
+ let builder = db.db
11
+ .selectFrom('list')
12
+ .where('creator', '=', actorDid)
13
+ .selectAll();
14
+ const keyset = new pagination_1.TimeCidKeyset(ref('list.sortAt'), ref('list.cid'));
15
+ builder = (0, pagination_1.paginate)(builder, {
16
+ limit,
17
+ cursor,
18
+ keyset,
19
+ tryIndex: true,
20
+ });
21
+ const lists = await builder.execute();
22
+ return {
23
+ listUris: lists.map((item) => item.uri),
24
+ cursor: keyset.packFromResult(lists),
25
+ };
26
+ },
27
+ async getListMembers(req) {
28
+ const { listUri, cursor, limit } = req;
29
+ const { ref } = db.db.dynamic;
30
+ let builder = db.db
31
+ .selectFrom('list_item')
32
+ .where('listUri', '=', listUri)
33
+ .selectAll();
34
+ const keyset = new pagination_1.TimeCidKeyset(ref('list_item.sortAt'), ref('list_item.cid'));
35
+ builder = (0, pagination_1.paginate)(builder, {
36
+ limit,
37
+ cursor,
38
+ keyset,
39
+ tryIndex: true,
40
+ });
41
+ const listItems = await builder.execute();
42
+ return {
43
+ listitems: listItems.map((item) => ({
44
+ uri: item.uri,
45
+ did: item.subjectDid,
46
+ })),
47
+ cursor: keyset.packFromResult(listItems),
48
+ };
49
+ },
50
+ async getListMembership(req) {
51
+ const { actorDid, listUris } = req;
52
+ if (listUris.length === 0) {
53
+ return { listitemUris: [] };
54
+ }
55
+ const res = await db.db
56
+ .selectFrom('list_item')
57
+ .where('subjectDid', '=', actorDid)
58
+ .where('listUri', 'in', listUris)
59
+ .selectAll()
60
+ .execute();
61
+ const byListUri = (0, common_1.keyBy)(res, 'listUri');
62
+ const listitemUris = listUris.map((uri) => byListUri.get(uri)?.uri ?? '');
63
+ return {
64
+ listitemUris,
65
+ };
66
+ },
67
+ async getListCount(req) {
68
+ const res = await db.db
69
+ .selectFrom('list_item')
70
+ .select(util_1.countAll.as('count'))
71
+ .where('list_item.listUri', '=', req.listUri)
72
+ .executeTakeFirst();
73
+ return {
74
+ count: res?.count,
75
+ };
76
+ },
77
+ });
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = (db) => ({
4
+ async getActorTakedown(req) {
5
+ const { did } = req;
6
+ const res = await db.db
7
+ .selectFrom('actor')
8
+ .where('did', '=', did)
9
+ .select('takedownRef')
10
+ .executeTakeFirst();
11
+ return {
12
+ takenDown: !!res?.takedownRef,
13
+ takedownRef: res?.takedownRef || undefined,
14
+ };
15
+ },
16
+ async getBlobTakedown(req) {
17
+ const { did, cid } = req;
18
+ const res = await db.db
19
+ .selectFrom('blob_takedown')
20
+ .where('did', '=', did)
21
+ .where('cid', '=', cid)
22
+ .select('takedownRef')
23
+ .executeTakeFirst();
24
+ return {
25
+ takenDown: !!res,
26
+ takedownRef: res?.takedownRef || undefined,
27
+ };
28
+ },
29
+ async getRecordTakedown(req) {
30
+ const { recordUri } = req;
31
+ const res = await db.db
32
+ .selectFrom('record')
33
+ .where('uri', '=', recordUri)
34
+ .select('takedownRef')
35
+ .executeTakeFirst();
36
+ return {
37
+ takenDown: !!res?.takedownRef,
38
+ takedownRef: res?.takedownRef || undefined,
39
+ };
40
+ },
41
+ async takedownActor(req) {
42
+ const { did, ref } = req;
43
+ await db.db
44
+ .updateTable('actor')
45
+ .set({ takedownRef: ref || 'TAKEDOWN' })
46
+ .where('did', '=', did)
47
+ .execute();
48
+ },
49
+ async takedownBlob(req) {
50
+ const { did, cid, ref } = req;
51
+ await db.db
52
+ .insertInto('blob_takedown')
53
+ .values({
54
+ did,
55
+ cid,
56
+ takedownRef: ref || 'TAKEDOWN',
57
+ })
58
+ .execute();
59
+ },
60
+ async takedownRecord(req) {
61
+ const { recordUri, ref } = req;
62
+ await db.db
63
+ .updateTable('record')
64
+ .set({ takedownRef: ref || 'TAKEDOWN' })
65
+ .where('uri', '=', recordUri)
66
+ .execute();
67
+ },
68
+ async untakedownActor(req) {
69
+ const { did } = req;
70
+ await db.db
71
+ .updateTable('actor')
72
+ .set({ takedownRef: null })
73
+ .where('did', '=', did)
74
+ .execute();
75
+ },
76
+ async untakedownBlob(req) {
77
+ const { did, cid } = req;
78
+ await db.db
79
+ .deleteFrom('blob_takedown')
80
+ .where('did', '=', did)
81
+ .where('cid', '=', cid)
82
+ .executeTakeFirst();
83
+ },
84
+ async untakedownRecord(req) {
85
+ const { recordUri } = req;
86
+ await db.db
87
+ .updateTable('record')
88
+ .set({ takedownRef: null })
89
+ .where('uri', '=', recordUri)
90
+ .execute();
91
+ },
92
+ });
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_assert_1 = __importDefault(require("node:assert"));
7
+ const common_1 = require("@atproto/common");
8
+ const syntax_1 = require("@atproto/syntax");
9
+ const lexicons_1 = require("../../../lexicon/lexicons");
10
+ const pagination_1 = require("../db/pagination");
11
+ exports.default = (db) => ({
12
+ async getActorMutesActor(req) {
13
+ const { actorDid, targetDid } = req;
14
+ const res = await db.db
15
+ .selectFrom('mute')
16
+ .selectAll()
17
+ .where('mutedByDid', '=', actorDid)
18
+ .where('subjectDid', '=', targetDid)
19
+ .executeTakeFirst();
20
+ return {
21
+ muted: !!res,
22
+ };
23
+ },
24
+ async getMutes(req) {
25
+ const { actorDid, limit, cursor } = req;
26
+ const { ref } = db.db.dynamic;
27
+ let builder = db.db
28
+ .selectFrom('mute')
29
+ .innerJoin('actor', 'actor.did', 'mute.subjectDid')
30
+ .where('mute.mutedByDid', '=', actorDid)
31
+ .selectAll('actor')
32
+ .select('mute.createdAt as createdAt');
33
+ const keyset = new pagination_1.CreatedAtDidKeyset(ref('mute.createdAt'), ref('mute.subjectDid'));
34
+ builder = (0, pagination_1.paginate)(builder, {
35
+ limit,
36
+ cursor,
37
+ keyset,
38
+ });
39
+ const mutes = await builder.execute();
40
+ return {
41
+ dids: mutes.map((m) => m.did),
42
+ cursor: keyset.packFromResult(mutes),
43
+ };
44
+ },
45
+ async getActorMutesActorViaList(req) {
46
+ const { actorDid, targetDid } = req;
47
+ const res = await db.db
48
+ .selectFrom('list_mute')
49
+ .innerJoin('list_item', 'list_item.listUri', 'list_mute.listUri')
50
+ .where('list_mute.mutedByDid', '=', actorDid)
51
+ .where('list_item.subjectDid', '=', targetDid)
52
+ .select('list_mute.listUri')
53
+ .limit(1)
54
+ .executeTakeFirst();
55
+ return {
56
+ listUri: res?.listUri,
57
+ };
58
+ },
59
+ async getMutelistSubscription(req) {
60
+ const { actorDid, listUri } = req;
61
+ const res = await db.db
62
+ .selectFrom('list_mute')
63
+ .where('mutedByDid', '=', actorDid)
64
+ .where('listUri', '=', listUri)
65
+ .selectAll()
66
+ .limit(1)
67
+ .executeTakeFirst();
68
+ return {
69
+ subscribed: !!res,
70
+ };
71
+ },
72
+ async getMutelistSubscriptions(req) {
73
+ const { actorDid, limit, cursor } = req;
74
+ const { ref } = db.db.dynamic;
75
+ let builder = db.db
76
+ .selectFrom('list')
77
+ .whereExists(db.db
78
+ .selectFrom('list_mute')
79
+ .where('list_mute.mutedByDid', '=', actorDid)
80
+ .whereRef('list_mute.listUri', '=', ref('list.uri'))
81
+ .selectAll())
82
+ .selectAll('list');
83
+ const keyset = new pagination_1.TimeCidKeyset(ref('list.createdAt'), ref('list.cid'));
84
+ builder = (0, pagination_1.paginate)(builder, {
85
+ limit,
86
+ cursor,
87
+ keyset,
88
+ });
89
+ const lists = await builder.execute();
90
+ return {
91
+ listUris: lists.map((l) => l.uri),
92
+ cursor: keyset.packFromResult(lists),
93
+ };
94
+ },
95
+ async createActorMute(req) {
96
+ const { actorDid, subjectDid } = req;
97
+ (0, node_assert_1.default)(actorDid !== subjectDid, 'cannot mute yourself'); // @TODO pass message through in http error
98
+ await db.db
99
+ .insertInto('mute')
100
+ .values({
101
+ subjectDid,
102
+ mutedByDid: actorDid,
103
+ createdAt: new Date().toISOString(),
104
+ })
105
+ .onConflict((oc) => oc.doNothing())
106
+ .execute();
107
+ },
108
+ async deleteActorMute(req) {
109
+ const { actorDid, subjectDid } = req;
110
+ (0, node_assert_1.default)(actorDid !== subjectDid, 'cannot mute yourself');
111
+ await db.db
112
+ .deleteFrom('mute')
113
+ .where('subjectDid', '=', subjectDid)
114
+ .where('mutedByDid', '=', actorDid)
115
+ .execute();
116
+ },
117
+ async clearActorMutes(req) {
118
+ const { actorDid } = req;
119
+ await db.db.deleteFrom('mute').where('mutedByDid', '=', actorDid).execute();
120
+ },
121
+ async createActorMutelistSubscription(req) {
122
+ const { actorDid, subjectUri } = req;
123
+ (0, node_assert_1.default)(isListUri(subjectUri), 'must mute a list');
124
+ await db.db
125
+ .insertInto('list_mute')
126
+ .values({
127
+ listUri: subjectUri,
128
+ mutedByDid: actorDid,
129
+ createdAt: new Date().toISOString(),
130
+ })
131
+ .onConflict((oc) => oc.doNothing())
132
+ .execute();
133
+ },
134
+ async deleteActorMutelistSubscription(req) {
135
+ const { actorDid, subjectUri } = req;
136
+ (0, node_assert_1.default)(isListUri(subjectUri), 'must mute a list');
137
+ await db.db
138
+ .deleteFrom('list_mute')
139
+ .where('listUri', '=', subjectUri)
140
+ .where('mutedByDid', '=', actorDid)
141
+ .execute();
142
+ },
143
+ async clearActorMutelistSubscriptions(req) {
144
+ const { actorDid } = req;
145
+ await db.db
146
+ .deleteFrom('list_mute')
147
+ .where('mutedByDid', '=', actorDid)
148
+ .execute();
149
+ },
150
+ async getThreadMutesOnSubjects(req) {
151
+ const { actorDid, threadRoots } = req;
152
+ if (threadRoots.length === 0) {
153
+ return { muted: [] };
154
+ }
155
+ const res = await db.db
156
+ .selectFrom('thread_mute')
157
+ .selectAll()
158
+ .where('mutedByDid', '=', actorDid)
159
+ .where('rootUri', 'in', threadRoots)
160
+ .execute();
161
+ const byRootUri = (0, common_1.keyBy)(res, 'rootUri');
162
+ const muted = threadRoots.map((uri) => !!byRootUri.get(uri));
163
+ return { muted };
164
+ },
165
+ });
166
+ const isListUri = (uri) => new syntax_1.AtUri(uri).collection === lexicons_1.ids.AppBskyGraphList;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const protobuf_1 = require("@bufbuild/protobuf");
4
+ const kysely_1 = require("kysely");
5
+ const pagination_1 = require("../db/pagination");
6
+ const util_1 = require("../db/util");
7
+ exports.default = (db) => ({
8
+ async getNotifications(req) {
9
+ const { actorDid, limit, cursor, priority } = req;
10
+ const { ref } = db.db.dynamic;
11
+ const priorityFollowQb = db.db
12
+ .selectFrom('follow')
13
+ .select((0, kysely_1.sql) `${true}`.as('val'))
14
+ .where('creator', '=', actorDid)
15
+ .whereRef('subjectDid', '=', ref('notif.author'))
16
+ .limit(1);
17
+ let builder = db.db
18
+ .selectFrom('notification as notif')
19
+ .where('notif.did', '=', actorDid)
20
+ .where((clause) => clause
21
+ .where('reasonSubject', 'is', null)
22
+ .orWhereExists(db.db
23
+ .selectFrom('record as subject')
24
+ .selectAll()
25
+ .whereRef('subject.uri', '=', ref('notif.reasonSubject'))))
26
+ .if(priority, (qb) => qb.whereExists(priorityFollowQb))
27
+ .select([
28
+ 'notif.author as authorDid',
29
+ 'notif.recordUri as uri',
30
+ 'notif.recordCid as cid',
31
+ 'notif.reason as reason',
32
+ 'notif.reasonSubject as reasonSubject',
33
+ 'notif.sortAt as sortAt',
34
+ ])
35
+ .select(priorityFollowQb.as('priority'));
36
+ const keyset = new pagination_1.TimeCidKeyset(ref('notif.sortAt'), ref('notif.recordCid'));
37
+ builder = (0, pagination_1.paginate)(builder, {
38
+ cursor,
39
+ limit,
40
+ keyset,
41
+ tryIndex: true,
42
+ });
43
+ const notifsRes = await builder.execute();
44
+ const notifications = notifsRes.map((notif) => ({
45
+ recipientDid: actorDid,
46
+ uri: notif.uri,
47
+ reason: notif.reason,
48
+ reasonSubject: notif.reasonSubject ?? undefined,
49
+ timestamp: protobuf_1.Timestamp.fromDate(new Date(notif.sortAt)),
50
+ priority: notif.priority ?? false,
51
+ }));
52
+ return {
53
+ notifications,
54
+ cursor: keyset.packFromResult(notifsRes),
55
+ };
56
+ },
57
+ async getNotificationSeen(req) {
58
+ const { actorDid, priority } = req;
59
+ const res = await db.db
60
+ .selectFrom('actor_state')
61
+ .where('did', '=', actorDid)
62
+ .selectAll()
63
+ .executeTakeFirst();
64
+ if (!res) {
65
+ return {};
66
+ }
67
+ const lastSeen = priority && res.lastSeenPriorityNotifs
68
+ ? res.lastSeenPriorityNotifs
69
+ : res.lastSeenNotifs;
70
+ return {
71
+ timestamp: protobuf_1.Timestamp.fromDate(new Date(lastSeen)),
72
+ };
73
+ },
74
+ async getUnreadNotificationCount(req) {
75
+ const { actorDid, priority } = req;
76
+ const { ref } = db.db.dynamic;
77
+ const lastSeenRes = await db.db
78
+ .selectFrom('actor_state')
79
+ .where('did', '=', actorDid)
80
+ .selectAll()
81
+ .executeTakeFirst();
82
+ const lastSeen = priority && lastSeenRes?.lastSeenPriorityNotifs
83
+ ? lastSeenRes.lastSeenPriorityNotifs
84
+ : lastSeenRes?.lastSeenNotifs;
85
+ const result = await db.db
86
+ .selectFrom('notification')
87
+ .select(util_1.countAll.as('count'))
88
+ .innerJoin('actor', 'actor.did', 'notification.did')
89
+ .leftJoin('actor_state', 'actor_state.did', 'actor.did')
90
+ .innerJoin('record', 'record.uri', 'notification.recordUri')
91
+ .where((0, util_1.notSoftDeletedClause)(ref('record')))
92
+ .where((0, util_1.notSoftDeletedClause)(ref('actor')))
93
+ // Ensure to hit notification_did_sortat_idx, handling case where lastSeenNotifs is null.
94
+ .where('notification.did', '=', actorDid)
95
+ .where('notification.sortAt', '>', lastSeen ?? '')
96
+ .if(priority, (qb) => qb.whereExists(db.db
97
+ .selectFrom('follow')
98
+ .select((0, kysely_1.sql) `${true}`.as('val'))
99
+ .where('creator', '=', actorDid)
100
+ .whereRef('subjectDid', '=', ref('notification.author'))))
101
+ .executeTakeFirst();
102
+ return {
103
+ count: result?.count,
104
+ };
105
+ },
106
+ async updateNotificationSeen(req) {
107
+ const { actorDid, timestamp, priority } = req;
108
+ if (!timestamp) {
109
+ return;
110
+ }
111
+ const timestampIso = timestamp.toDate().toISOString();
112
+ let builder = db.db
113
+ .updateTable('actor_state')
114
+ .where('did', '=', actorDid)
115
+ .returningAll();
116
+ if (priority) {
117
+ builder = builder.set({ lastSeenPriorityNotifs: timestampIso });
118
+ }
119
+ else {
120
+ builder = builder.set({ lastSeenNotifs: timestampIso });
121
+ }
122
+ const updateRes = await builder.executeTakeFirst();
123
+ if (updateRes) {
124
+ return;
125
+ }
126
+ await db.db
127
+ .insertInto('actor_state')
128
+ .values({
129
+ did: actorDid,
130
+ lastSeenNotifs: timestampIso,
131
+ priorityNotifs: priority,
132
+ lastSeenPriorityNotifs: priority ? timestampIso : undefined,
133
+ })
134
+ .onConflict((oc) => oc.doNothing())
135
+ .executeTakeFirst();
136
+ },
137
+ });
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const common_1 = require("@atproto/common");
4
+ exports.default = (db) => ({
5
+ async getPostReplyCounts(req) {
6
+ const uris = req.refs.map((ref) => ref.uri);
7
+ if (uris.length === 0) {
8
+ return { counts: [] };
9
+ }
10
+ const res = await db.db
11
+ .selectFrom('post_agg')
12
+ .select(['uri', 'replyCount'])
13
+ .where('uri', 'in', uris)
14
+ .execute();
15
+ const byUri = (0, common_1.keyBy)(res, 'uri');
16
+ const counts = uris.map((uri) => byUri.get(uri)?.replyCount ?? 0);
17
+ return { counts };
18
+ },
19
+ });