+5
-1
.env
+5
-1
.env
···
1
-
JETSTREAM_URL="wss://jetstream2.us-east.bsky.network"
1
+
# main indexers
2
+
JETSTREAM_URL="wss://jetstream.whey.party"
2
3
SPACEDUST_URL="wss://spacedust.microcosm.blue"
4
+
5
+
# for backfill (useless if you just started the instance right now)
3
6
CONSTELLATION_URL="https://constellation.microcosm.blue"
7
+
# i dont actually know why i need this
4
8
SLINGSHOT_URL="https://slingshot.microcosm.blue"
5
9
6
10
SERVICE_DID="did:web:local3768forumtest.whey.party"
+1
-1
index/onboardingBackfill.ts
+1
-1
index/onboardingBackfill.ts
+64
-64
indexclient/index.ts
+64
-64
indexclient/index.ts
···
5
5
XrpcClient,
6
6
type FetchHandler,
7
7
type FetchHandlerOptions,
8
-
} from '@atproto/xrpc'
9
-
import { schemas } from './lexicons.js'
10
-
import { CID } from 'multiformats/cid'
11
-
import { type OmitKey, type Un$Typed } from './util.js'
12
-
import * as AppBskyActorDefs from './types/app/bsky/actor/defs.js'
13
-
import * as AppBskyActorGetProfile from './types/app/bsky/actor/getProfile.js'
14
-
import * as AppBskyActorGetProfiles from './types/app/bsky/actor/getProfiles.js'
15
-
import * as AppBskyEmbedDefs from './types/app/bsky/embed/defs.js'
16
-
import * as AppBskyEmbedExternal from './types/app/bsky/embed/external.js'
17
-
import * as AppBskyEmbedImages from './types/app/bsky/embed/images.js'
18
-
import * as AppBskyEmbedRecord from './types/app/bsky/embed/record.js'
19
-
import * as AppBskyEmbedRecordWithMedia from './types/app/bsky/embed/recordWithMedia.js'
20
-
import * as AppBskyEmbedVideo from './types/app/bsky/embed/video.js'
21
-
import * as AppBskyFeedDefs from './types/app/bsky/feed/defs.js'
22
-
import * as AppBskyFeedGetActorFeeds from './types/app/bsky/feed/getActorFeeds.js'
23
-
import * as AppBskyFeedGetFeedGenerator from './types/app/bsky/feed/getFeedGenerator.js'
24
-
import * as AppBskyFeedGetFeedGenerators from './types/app/bsky/feed/getFeedGenerators.js'
25
-
import * as AppBskyFeedGetPosts from './types/app/bsky/feed/getPosts.js'
26
-
import * as AppBskyFeedPostgate from './types/app/bsky/feed/postgate.js'
27
-
import * as AppBskyFeedThreadgate from './types/app/bsky/feed/threadgate.js'
28
-
import * as AppBskyGraphDefs from './types/app/bsky/graph/defs.js'
29
-
import * as AppBskyNotificationDefs from './types/app/bsky/notification/defs.js'
30
-
import * as AppBskyRichtextFacet from './types/app/bsky/richtext/facet.js'
31
-
import * as ComAtprotoLabelDefs from './types/com/atproto/label/defs.js'
32
-
import * as ComAtprotoRepoStrongRef from './types/com/atproto/repo/strongRef.js'
33
-
import * as PartyWheyAppBskyActorDefs from './types/party/whey/app/bsky/actor/defs.js'
34
-
import * as PartyWheyAppBskyFeedDefs from './types/party/whey/app/bsky/feed/defs.js'
35
-
import * as PartyWheyAppBskyFeedGetActorLikesPartial from './types/party/whey/app/bsky/feed/getActorLikesPartial.js'
36
-
import * as PartyWheyAppBskyFeedGetAuthorFeedPartial from './types/party/whey/app/bsky/feed/getAuthorFeedPartial.js'
37
-
import * as PartyWheyAppBskyFeedGetLikesPartial from './types/party/whey/app/bsky/feed/getLikesPartial.js'
38
-
import * as PartyWheyAppBskyFeedGetListFeedPartial from './types/party/whey/app/bsky/feed/getListFeedPartial.js'
39
-
import * as PartyWheyAppBskyFeedGetPostThreadPartial from './types/party/whey/app/bsky/feed/getPostThreadPartial.js'
40
-
import * as PartyWheyAppBskyFeedGetQuotesPartial from './types/party/whey/app/bsky/feed/getQuotesPartial.js'
41
-
import * as PartyWheyAppBskyFeedGetRepostedByPartial from './types/party/whey/app/bsky/feed/getRepostedByPartial.js'
8
+
} from 'npm:@atproto/xrpc'
9
+
import { schemas } from './lexicons.ts'
10
+
import { CID } from 'npm:multiformats/cid'
11
+
import { type OmitKey, type Un$Typed } from './util.ts'
12
+
import * as AppBskyActorDefs from './types/app/bsky/actor/defs.ts'
13
+
import * as AppBskyActorGetProfile from './types/app/bsky/actor/getProfile.ts'
14
+
import * as AppBskyActorGetProfiles from './types/app/bsky/actor/getProfiles.ts'
15
+
import * as AppBskyEmbedDefs from './types/app/bsky/embed/defs.ts'
16
+
import * as AppBskyEmbedExternal from './types/app/bsky/embed/external.ts'
17
+
import * as AppBskyEmbedImages from './types/app/bsky/embed/images.ts'
18
+
import * as AppBskyEmbedRecord from './types/app/bsky/embed/record.ts'
19
+
import * as AppBskyEmbedRecordWithMedia from './types/app/bsky/embed/recordWithMedia.ts'
20
+
import * as AppBskyEmbedVideo from './types/app/bsky/embed/video.ts'
21
+
import * as AppBskyFeedDefs from './types/app/bsky/feed/defs.ts'
22
+
import * as AppBskyFeedGetActorFeeds from './types/app/bsky/feed/getActorFeeds.ts'
23
+
import * as AppBskyFeedGetFeedGenerator from './types/app/bsky/feed/getFeedGenerator.ts'
24
+
import * as AppBskyFeedGetFeedGenerators from './types/app/bsky/feed/getFeedGenerators.ts'
25
+
import * as AppBskyFeedGetPosts from './types/app/bsky/feed/getPosts.ts'
26
+
import * as AppBskyFeedPostgate from './types/app/bsky/feed/postgate.ts'
27
+
import * as AppBskyFeedThreadgate from './types/app/bsky/feed/threadgate.ts'
28
+
import * as AppBskyGraphDefs from './types/app/bsky/graph/defs.ts'
29
+
import * as AppBskyNotificationDefs from './types/app/bsky/notification/defs.ts'
30
+
import * as AppBskyRichtextFacet from './types/app/bsky/richtext/facet.ts'
31
+
import * as ComAtprotoLabelDefs from './types/com/atproto/label/defs.ts'
32
+
import * as ComAtprotoRepoStrongRef from './types/com/atproto/repo/strongRef.ts'
33
+
import * as PartyWheyAppBskyActorDefs from './types/party/whey/app/bsky/actor/defs.ts'
34
+
import * as PartyWheyAppBskyFeedDefs from './types/party/whey/app/bsky/feed/defs.ts'
35
+
import * as PartyWheyAppBskyFeedGetActorLikesPartial from './types/party/whey/app/bsky/feed/getActorLikesPartial.ts'
36
+
import * as PartyWheyAppBskyFeedGetAuthorFeedPartial from './types/party/whey/app/bsky/feed/getAuthorFeedPartial.ts'
37
+
import * as PartyWheyAppBskyFeedGetLikesPartial from './types/party/whey/app/bsky/feed/getLikesPartial.ts'
38
+
import * as PartyWheyAppBskyFeedGetListFeedPartial from './types/party/whey/app/bsky/feed/getListFeedPartial.ts'
39
+
import * as PartyWheyAppBskyFeedGetPostThreadPartial from './types/party/whey/app/bsky/feed/getPostThreadPartial.ts'
40
+
import * as PartyWheyAppBskyFeedGetQuotesPartial from './types/party/whey/app/bsky/feed/getQuotesPartial.ts'
41
+
import * as PartyWheyAppBskyFeedGetRepostedByPartial from './types/party/whey/app/bsky/feed/getRepostedByPartial.ts'
42
42
43
-
export * as AppBskyActorDefs from './types/app/bsky/actor/defs.js'
44
-
export * as AppBskyActorGetProfile from './types/app/bsky/actor/getProfile.js'
45
-
export * as AppBskyActorGetProfiles from './types/app/bsky/actor/getProfiles.js'
46
-
export * as AppBskyEmbedDefs from './types/app/bsky/embed/defs.js'
47
-
export * as AppBskyEmbedExternal from './types/app/bsky/embed/external.js'
48
-
export * as AppBskyEmbedImages from './types/app/bsky/embed/images.js'
49
-
export * as AppBskyEmbedRecord from './types/app/bsky/embed/record.js'
50
-
export * as AppBskyEmbedRecordWithMedia from './types/app/bsky/embed/recordWithMedia.js'
51
-
export * as AppBskyEmbedVideo from './types/app/bsky/embed/video.js'
52
-
export * as AppBskyFeedDefs from './types/app/bsky/feed/defs.js'
53
-
export * as AppBskyFeedGetActorFeeds from './types/app/bsky/feed/getActorFeeds.js'
54
-
export * as AppBskyFeedGetFeedGenerator from './types/app/bsky/feed/getFeedGenerator.js'
55
-
export * as AppBskyFeedGetFeedGenerators from './types/app/bsky/feed/getFeedGenerators.js'
56
-
export * as AppBskyFeedGetPosts from './types/app/bsky/feed/getPosts.js'
57
-
export * as AppBskyFeedPostgate from './types/app/bsky/feed/postgate.js'
58
-
export * as AppBskyFeedThreadgate from './types/app/bsky/feed/threadgate.js'
59
-
export * as AppBskyGraphDefs from './types/app/bsky/graph/defs.js'
60
-
export * as AppBskyNotificationDefs from './types/app/bsky/notification/defs.js'
61
-
export * as AppBskyRichtextFacet from './types/app/bsky/richtext/facet.js'
62
-
export * as ComAtprotoLabelDefs from './types/com/atproto/label/defs.js'
63
-
export * as ComAtprotoRepoStrongRef from './types/com/atproto/repo/strongRef.js'
64
-
export * as PartyWheyAppBskyActorDefs from './types/party/whey/app/bsky/actor/defs.js'
65
-
export * as PartyWheyAppBskyFeedDefs from './types/party/whey/app/bsky/feed/defs.js'
66
-
export * as PartyWheyAppBskyFeedGetActorLikesPartial from './types/party/whey/app/bsky/feed/getActorLikesPartial.js'
67
-
export * as PartyWheyAppBskyFeedGetAuthorFeedPartial from './types/party/whey/app/bsky/feed/getAuthorFeedPartial.js'
68
-
export * as PartyWheyAppBskyFeedGetLikesPartial from './types/party/whey/app/bsky/feed/getLikesPartial.js'
69
-
export * as PartyWheyAppBskyFeedGetListFeedPartial from './types/party/whey/app/bsky/feed/getListFeedPartial.js'
70
-
export * as PartyWheyAppBskyFeedGetPostThreadPartial from './types/party/whey/app/bsky/feed/getPostThreadPartial.js'
71
-
export * as PartyWheyAppBskyFeedGetQuotesPartial from './types/party/whey/app/bsky/feed/getQuotesPartial.js'
72
-
export * as PartyWheyAppBskyFeedGetRepostedByPartial from './types/party/whey/app/bsky/feed/getRepostedByPartial.js'
43
+
export * as AppBskyActorDefs from './types/app/bsky/actor/defs.ts'
44
+
export * as AppBskyActorGetProfile from './types/app/bsky/actor/getProfile.ts'
45
+
export * as AppBskyActorGetProfiles from './types/app/bsky/actor/getProfiles.ts'
46
+
export * as AppBskyEmbedDefs from './types/app/bsky/embed/defs.ts'
47
+
export * as AppBskyEmbedExternal from './types/app/bsky/embed/external.ts'
48
+
export * as AppBskyEmbedImages from './types/app/bsky/embed/images.ts'
49
+
export * as AppBskyEmbedRecord from './types/app/bsky/embed/record.ts'
50
+
export * as AppBskyEmbedRecordWithMedia from './types/app/bsky/embed/recordWithMedia.ts'
51
+
export * as AppBskyEmbedVideo from './types/app/bsky/embed/video.ts'
52
+
export * as AppBskyFeedDefs from './types/app/bsky/feed/defs.ts'
53
+
export * as AppBskyFeedGetActorFeeds from './types/app/bsky/feed/getActorFeeds.ts'
54
+
export * as AppBskyFeedGetFeedGenerator from './types/app/bsky/feed/getFeedGenerator.ts'
55
+
export * as AppBskyFeedGetFeedGenerators from './types/app/bsky/feed/getFeedGenerators.ts'
56
+
export * as AppBskyFeedGetPosts from './types/app/bsky/feed/getPosts.ts'
57
+
export * as AppBskyFeedPostgate from './types/app/bsky/feed/postgate.ts'
58
+
export * as AppBskyFeedThreadgate from './types/app/bsky/feed/threadgate.ts'
59
+
export * as AppBskyGraphDefs from './types/app/bsky/graph/defs.ts'
60
+
export * as AppBskyNotificationDefs from './types/app/bsky/notification/defs.ts'
61
+
export * as AppBskyRichtextFacet from './types/app/bsky/richtext/facet.ts'
62
+
export * as ComAtprotoLabelDefs from './types/com/atproto/label/defs.ts'
63
+
export * as ComAtprotoRepoStrongRef from './types/com/atproto/repo/strongRef.ts'
64
+
export * as PartyWheyAppBskyActorDefs from './types/party/whey/app/bsky/actor/defs.ts'
65
+
export * as PartyWheyAppBskyFeedDefs from './types/party/whey/app/bsky/feed/defs.ts'
66
+
export * as PartyWheyAppBskyFeedGetActorLikesPartial from './types/party/whey/app/bsky/feed/getActorLikesPartial.ts'
67
+
export * as PartyWheyAppBskyFeedGetAuthorFeedPartial from './types/party/whey/app/bsky/feed/getAuthorFeedPartial.ts'
68
+
export * as PartyWheyAppBskyFeedGetLikesPartial from './types/party/whey/app/bsky/feed/getLikesPartial.ts'
69
+
export * as PartyWheyAppBskyFeedGetListFeedPartial from './types/party/whey/app/bsky/feed/getListFeedPartial.ts'
70
+
export * as PartyWheyAppBskyFeedGetPostThreadPartial from './types/party/whey/app/bsky/feed/getPostThreadPartial.ts'
71
+
export * as PartyWheyAppBskyFeedGetQuotesPartial from './types/party/whey/app/bsky/feed/getQuotesPartial.ts'
72
+
export * as PartyWheyAppBskyFeedGetRepostedByPartial from './types/party/whey/app/bsky/feed/getRepostedByPartial.ts'
73
73
74
74
export const APP_BSKY_FEED = {
75
75
DefsRequestLess: 'app.bsky.feed.defs#requestLess',
+2
-2
indexclient/lexicons.ts
+2
-2
indexclient/lexicons.ts
···
6
6
Lexicons,
7
7
ValidationError,
8
8
type ValidationResult,
9
-
} from '@atproto/lexicon'
10
-
import { type $Typed, is$typed, maybe$typed } from './util.js'
9
+
} from 'npm:@atproto/lexicon'
10
+
import { type $Typed, is$typed, maybe$typed } from './util.ts'
11
11
12
12
export const schemaDict = {
13
13
AppBskyActorDefs: {
+11
-11
indexclient/types/app/bsky/actor/defs.ts
+11
-11
indexclient/types/app/bsky/actor/defs.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
12
-
import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.js'
13
-
import type * as AppBskyGraphDefs from '../graph/defs.js'
14
-
import type * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef.js'
15
-
import type * as AppBskyNotificationDefs from '../notification/defs.js'
16
-
import type * as AppBskyFeedThreadgate from '../feed/threadgate.js'
17
-
import type * as AppBskyFeedPostgate from '../feed/postgate.js'
18
-
import type * as AppBskyEmbedExternal from '../embed/external.js'
11
+
} from '../../../../util.ts'
12
+
import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.ts'
13
+
import type * as AppBskyGraphDefs from '../graph/defs.ts'
14
+
import type * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef.ts'
15
+
import type * as AppBskyNotificationDefs from '../notification/defs.ts'
16
+
import type * as AppBskyFeedThreadgate from '../feed/threadgate.ts'
17
+
import type * as AppBskyFeedPostgate from '../feed/postgate.ts'
18
+
import type * as AppBskyEmbedExternal from '../embed/external.ts'
19
19
20
20
const is$typed = _is$typed,
21
21
validate = _validate
+6
-6
indexclient/types/app/bsky/actor/getProfile.ts
+6
-6
indexclient/types/app/bsky/actor/getProfile.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../util'
13
-
import type * as AppBskyActorDefs from './defs.js'
12
+
} from '../../../../util.ts'
13
+
import type * as AppBskyActorDefs from './defs.ts'
14
14
15
15
const is$typed = _is$typed,
16
16
validate = _validate
+6
-6
indexclient/types/app/bsky/actor/getProfiles.ts
+6
-6
indexclient/types/app/bsky/actor/getProfiles.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../util'
13
-
import type * as AppBskyActorDefs from './defs.js'
12
+
} from '../../../../util.ts'
13
+
import type * as AppBskyActorDefs from './defs.ts'
14
14
15
15
const is$typed = _is$typed,
16
16
validate = _validate
+4
-4
indexclient/types/app/bsky/embed/defs.ts
+4
-4
indexclient/types/app/bsky/embed/defs.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
11
+
} from '../../../../util.ts'
12
12
13
13
const is$typed = _is$typed,
14
14
validate = _validate
+4
-4
indexclient/types/app/bsky/embed/external.ts
+4
-4
indexclient/types/app/bsky/embed/external.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
11
+
} from '../../../../util.ts'
12
12
13
13
const is$typed = _is$typed,
14
14
validate = _validate
+5
-5
indexclient/types/app/bsky/embed/images.ts
+5
-5
indexclient/types/app/bsky/embed/images.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
12
-
import type * as AppBskyEmbedDefs from './defs.js'
11
+
} from '../../../../util.ts'
12
+
import type * as AppBskyEmbedDefs from './defs.ts'
13
13
14
14
const is$typed = _is$typed,
15
15
validate = _validate
+14
-14
indexclient/types/app/bsky/embed/record.ts
+14
-14
indexclient/types/app/bsky/embed/record.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
12
-
import type * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef.js'
13
-
import type * as AppBskyFeedDefs from '../feed/defs.js'
14
-
import type * as AppBskyGraphDefs from '../graph/defs.js'
15
-
import type * as AppBskyLabelerDefs from '../labeler/defs.js'
16
-
import type * as AppBskyActorDefs from '../actor/defs.js'
17
-
import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.js'
18
-
import type * as AppBskyEmbedImages from './images.js'
19
-
import type * as AppBskyEmbedVideo from './video.js'
20
-
import type * as AppBskyEmbedExternal from './external.js'
21
-
import type * as AppBskyEmbedRecordWithMedia from './recordWithMedia.js'
11
+
} from '../../../../util.ts'
12
+
import type * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef.ts'
13
+
import type * as AppBskyFeedDefs from '../feed/defs.ts'
14
+
import type * as AppBskyGraphDefs from '../graph/defs.ts'
15
+
import type * as AppBskyLabelerDefs from '../labeler/defs.ts'
16
+
import type * as AppBskyActorDefs from '../actor/defs.ts'
17
+
import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.ts'
18
+
import type * as AppBskyEmbedImages from './images.ts'
19
+
import type * as AppBskyEmbedVideo from './video.ts'
20
+
import type * as AppBskyEmbedExternal from './external.ts'
21
+
import type * as AppBskyEmbedRecordWithMedia from './recordWithMedia.ts'
22
22
23
23
const is$typed = _is$typed,
24
24
validate = _validate
+8
-8
indexclient/types/app/bsky/embed/recordWithMedia.ts
+8
-8
indexclient/types/app/bsky/embed/recordWithMedia.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
12
-
import type * as AppBskyEmbedRecord from './record.js'
13
-
import type * as AppBskyEmbedImages from './images.js'
14
-
import type * as AppBskyEmbedVideo from './video.js'
15
-
import type * as AppBskyEmbedExternal from './external.js'
11
+
} from '../../../../util.ts'
12
+
import type * as AppBskyEmbedRecord from './record.ts'
13
+
import type * as AppBskyEmbedImages from './images.ts'
14
+
import type * as AppBskyEmbedVideo from './video.ts'
15
+
import type * as AppBskyEmbedExternal from './external.ts'
16
16
17
17
const is$typed = _is$typed,
18
18
validate = _validate
+5
-5
indexclient/types/app/bsky/embed/video.ts
+5
-5
indexclient/types/app/bsky/embed/video.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
12
-
import type * as AppBskyEmbedDefs from './defs.js'
11
+
} from '../../../../util.ts'
12
+
import type * as AppBskyEmbedDefs from './defs.ts'
13
13
14
14
const is$typed = _is$typed,
15
15
validate = _validate
+13
-13
indexclient/types/app/bsky/feed/defs.ts
+13
-13
indexclient/types/app/bsky/feed/defs.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
12
-
import type * as AppBskyActorDefs from '../actor/defs.js'
13
-
import type * as AppBskyEmbedImages from '../embed/images.js'
14
-
import type * as AppBskyEmbedVideo from '../embed/video.js'
15
-
import type * as AppBskyEmbedExternal from '../embed/external.js'
16
-
import type * as AppBskyEmbedRecord from '../embed/record.js'
17
-
import type * as AppBskyEmbedRecordWithMedia from '../embed/recordWithMedia.js'
18
-
import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.js'
19
-
import type * as AppBskyRichtextFacet from '../richtext/facet.js'
20
-
import type * as AppBskyGraphDefs from '../graph/defs.js'
11
+
} from '../../../../util.ts'
12
+
import type * as AppBskyActorDefs from '../actor/defs.ts'
13
+
import type * as AppBskyEmbedImages from '../embed/images.ts'
14
+
import type * as AppBskyEmbedVideo from '../embed/video.ts'
15
+
import type * as AppBskyEmbedExternal from '../embed/external.ts'
16
+
import type * as AppBskyEmbedRecord from '../embed/record.ts'
17
+
import type * as AppBskyEmbedRecordWithMedia from '../embed/recordWithMedia.ts'
18
+
import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.ts'
19
+
import type * as AppBskyRichtextFacet from '../richtext/facet.ts'
20
+
import type * as AppBskyGraphDefs from '../graph/defs.ts'
21
21
22
22
const is$typed = _is$typed,
23
23
validate = _validate
+6
-6
indexclient/types/app/bsky/feed/getActorFeeds.ts
+6
-6
indexclient/types/app/bsky/feed/getActorFeeds.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../util'
13
-
import type * as AppBskyFeedDefs from './defs.js'
12
+
} from '../../../../util.ts'
13
+
import type * as AppBskyFeedDefs from './defs.ts'
14
14
15
15
const is$typed = _is$typed,
16
16
validate = _validate
+6
-6
indexclient/types/app/bsky/feed/getFeedGenerator.ts
+6
-6
indexclient/types/app/bsky/feed/getFeedGenerator.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../util'
13
-
import type * as AppBskyFeedDefs from './defs.js'
12
+
} from '../../../../util.ts'
13
+
import type * as AppBskyFeedDefs from './defs.ts'
14
14
15
15
const is$typed = _is$typed,
16
16
validate = _validate
+6
-6
indexclient/types/app/bsky/feed/getFeedGenerators.ts
+6
-6
indexclient/types/app/bsky/feed/getFeedGenerators.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../util'
13
-
import type * as AppBskyFeedDefs from './defs.js'
12
+
} from '../../../../util.ts'
13
+
import type * as AppBskyFeedDefs from './defs.ts'
14
14
15
15
const is$typed = _is$typed,
16
16
validate = _validate
+6
-6
indexclient/types/app/bsky/feed/getPosts.ts
+6
-6
indexclient/types/app/bsky/feed/getPosts.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../util'
13
-
import type * as AppBskyFeedDefs from './defs.js'
12
+
} from '../../../../util.ts'
13
+
import type * as AppBskyFeedDefs from './defs.ts'
14
14
15
15
const is$typed = _is$typed,
16
16
validate = _validate
+4
-4
indexclient/types/app/bsky/feed/postgate.ts
+4
-4
indexclient/types/app/bsky/feed/postgate.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
11
+
} from '../../../../util.ts'
12
12
13
13
const is$typed = _is$typed,
14
14
validate = _validate
+4
-4
indexclient/types/app/bsky/feed/threadgate.ts
+4
-4
indexclient/types/app/bsky/feed/threadgate.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
11
+
} from '../../../../util.ts'
12
12
13
13
const is$typed = _is$typed,
14
14
validate = _validate
+8
-8
indexclient/types/app/bsky/graph/defs.ts
+8
-8
indexclient/types/app/bsky/graph/defs.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
12
-
import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.js'
13
-
import type * as AppBskyActorDefs from '../actor/defs.js'
14
-
import type * as AppBskyRichtextFacet from '../richtext/facet.js'
15
-
import type * as AppBskyFeedDefs from '../feed/defs.js'
11
+
} from '../../../../util.ts'
12
+
import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.ts'
13
+
import type * as AppBskyActorDefs from '../actor/defs.ts'
14
+
import type * as AppBskyRichtextFacet from '../richtext/facet.ts'
15
+
import type * as AppBskyFeedDefs from '../feed/defs.ts'
16
16
17
17
const is$typed = _is$typed,
18
18
validate = _validate
+4
-4
indexclient/types/app/bsky/notification/defs.ts
+4
-4
indexclient/types/app/bsky/notification/defs.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
11
+
} from '../../../../util.ts'
12
12
13
13
const is$typed = _is$typed,
14
14
validate = _validate
+4
-4
indexclient/types/app/bsky/richtext/facet.ts
+4
-4
indexclient/types/app/bsky/richtext/facet.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
11
+
} from '../../../../util.ts'
12
12
13
13
const is$typed = _is$typed,
14
14
validate = _validate
+4
-4
indexclient/types/com/atproto/label/defs.ts
+4
-4
indexclient/types/com/atproto/label/defs.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
11
+
} from '../../../../util.ts'
12
12
13
13
const is$typed = _is$typed,
14
14
validate = _validate
+4
-4
indexclient/types/com/atproto/repo/strongRef.ts
+4
-4
indexclient/types/com/atproto/repo/strongRef.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../util'
11
+
} from '../../../../util.ts'
12
12
13
13
const is$typed = _is$typed,
14
14
validate = _validate
+4
-4
indexclient/types/party/whey/app/bsky/actor/defs.ts
+4
-4
indexclient/types/party/whey/app/bsky/actor/defs.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../../../util'
11
+
} from '../../../../../../util.ts'
12
12
13
13
const is$typed = _is$typed,
14
14
validate = _validate
+7
-7
indexclient/types/party/whey/app/bsky/feed/defs.ts
+7
-7
indexclient/types/party/whey/app/bsky/feed/defs.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
-
import { CID } from 'multiformats/cid'
6
-
import { validate as _validate } from '../../../../../../lexicons'
4
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
5
+
import { CID } from 'npm:multiformats/cid'
6
+
import { validate as _validate } from '../../../../../../lexicons.ts'
7
7
import {
8
8
type $Typed,
9
9
is$typed as _is$typed,
10
10
type OmitKey,
11
-
} from '../../../../../../util'
12
-
import type * as AppBskyFeedDefs from '../../../../../app/bsky/feed/defs.js'
13
-
import type * as PartyWheyAppBskyActorDefs from '../actor/defs.js'
14
-
import type * as AppBskyActorDefs from '../../../../../app/bsky/actor/defs.js'
11
+
} from '../../../../../../util.ts'
12
+
import type * as AppBskyFeedDefs from '../../../../../app/bsky/feed/defs.ts'
13
+
import type * as PartyWheyAppBskyActorDefs from '../actor/defs.ts'
14
+
import type * as AppBskyActorDefs from '../../../../../app/bsky/actor/defs.ts'
15
15
16
16
const is$typed = _is$typed,
17
17
validate = _validate
+7
-7
indexclient/types/party/whey/app/bsky/feed/getActorLikesPartial.ts
+7
-7
indexclient/types/party/whey/app/bsky/feed/getActorLikesPartial.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../../../util'
13
-
import type * as PartyWheyAppBskyFeedDefs from './defs.js'
14
-
import type * as AppBskyFeedDefs from '../../../../../app/bsky/feed/defs.js'
12
+
} from '../../../../../../util.ts'
13
+
import type * as PartyWheyAppBskyFeedDefs from './defs.ts'
14
+
import type * as AppBskyFeedDefs from '../../../../../app/bsky/feed/defs.ts'
15
15
16
16
const is$typed = _is$typed,
17
17
validate = _validate
+7
-7
indexclient/types/party/whey/app/bsky/feed/getAuthorFeedPartial.ts
+7
-7
indexclient/types/party/whey/app/bsky/feed/getAuthorFeedPartial.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../../../util'
13
-
import type * as PartyWheyAppBskyFeedDefs from './defs.js'
14
-
import type * as AppBskyFeedDefs from '../../../../../app/bsky/feed/defs.js'
12
+
} from '../../../../../../util.ts'
13
+
import type * as PartyWheyAppBskyFeedDefs from './defs.ts'
14
+
import type * as AppBskyFeedDefs from '../../../../../app/bsky/feed/defs.ts'
15
15
16
16
const is$typed = _is$typed,
17
17
validate = _validate
+6
-6
indexclient/types/party/whey/app/bsky/feed/getLikesPartial.ts
+6
-6
indexclient/types/party/whey/app/bsky/feed/getLikesPartial.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../../../util'
13
-
import type * as PartyWheyAppBskyActorDefs from '../actor/defs.js'
12
+
} from '../../../../../../util.ts'
13
+
import type * as PartyWheyAppBskyActorDefs from '../actor/defs.ts'
14
14
15
15
const is$typed = _is$typed,
16
16
validate = _validate
+6
-6
indexclient/types/party/whey/app/bsky/feed/getListFeedPartial.ts
+6
-6
indexclient/types/party/whey/app/bsky/feed/getListFeedPartial.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../../../util'
13
-
import type * as PartyWheyAppBskyFeedDefs from './defs.js'
12
+
} from '../../../../../../util.ts'
13
+
import type * as PartyWheyAppBskyFeedDefs from './defs.ts'
14
14
15
15
const is$typed = _is$typed,
16
16
validate = _validate
+7
-7
indexclient/types/party/whey/app/bsky/feed/getPostThreadPartial.ts
+7
-7
indexclient/types/party/whey/app/bsky/feed/getPostThreadPartial.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../../../util'
13
-
import type * as PartyWheyAppBskyFeedDefs from './defs.js'
14
-
import type * as AppBskyFeedDefs from '../../../../../app/bsky/feed/defs.js'
12
+
} from '../../../../../../util.ts'
13
+
import type * as PartyWheyAppBskyFeedDefs from './defs.ts'
14
+
import type * as AppBskyFeedDefs from '../../../../../app/bsky/feed/defs.ts'
15
15
16
16
const is$typed = _is$typed,
17
17
validate = _validate
+7
-7
indexclient/types/party/whey/app/bsky/feed/getQuotesPartial.ts
+7
-7
indexclient/types/party/whey/app/bsky/feed/getQuotesPartial.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../../../util'
13
-
import type * as PartyWheyAppBskyFeedDefs from './defs.js'
14
-
import type * as AppBskyFeedDefs from '../../../../../app/bsky/feed/defs.js'
12
+
} from '../../../../../../util.ts'
13
+
import type * as PartyWheyAppBskyFeedDefs from './defs.ts'
14
+
import type * as AppBskyFeedDefs from '../../../../../app/bsky/feed/defs.ts'
15
15
16
16
const is$typed = _is$typed,
17
17
validate = _validate
+7
-7
indexclient/types/party/whey/app/bsky/feed/getRepostedByPartial.ts
+7
-7
indexclient/types/party/whey/app/bsky/feed/getRepostedByPartial.ts
···
1
1
/**
2
2
* GENERATED CODE - DO NOT MODIFY
3
3
*/
4
-
import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
-
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
-
import { CID } from 'multiformats/cid'
7
-
import { validate as _validate } from '../../../../../../lexicons'
4
+
import { HeadersMap, XRPCError } from 'npm:@atproto/xrpc'
5
+
import { type ValidationResult, BlobRef } from 'npm:@atproto/lexicon'
6
+
import { CID } from 'npm:multiformats/cid'
7
+
import { validate as _validate } from '../../../../../../lexicons.ts'
8
8
import {
9
9
type $Typed,
10
10
is$typed as _is$typed,
11
11
type OmitKey,
12
-
} from '../../../../../../util'
13
-
import type * as PartyWheyAppBskyActorDefs from '../actor/defs.js'
14
-
import type * as AppBskyActorDefs from '../../../../../app/bsky/actor/defs.js'
12
+
} from '../../../../../../util.ts'
13
+
import type * as PartyWheyAppBskyActorDefs from '../actor/defs.ts'
14
+
import type * as AppBskyActorDefs from '../../../../../app/bsky/actor/defs.ts'
15
15
16
16
const is$typed = _is$typed,
17
17
validate = _validate
+1
-1
indexclient/util.ts
+1
-1
indexclient/util.ts
+9
indexserver.ts
+9
indexserver.ts
+47
-713
main.ts
+47
-713
main.ts
···
1
1
import { setupAuth, getAuthenticatedDid, authVerifier } from "./utils/auth.ts";
2
2
import { JetstreamManager, SpacedustManager } from "./utils/sharders.ts";
3
3
import { resolveRecordFromURI, validateRecord } from "./utils/records.ts";
4
-
import dbsetup from "./utils/dbsetup.ts";
4
+
import { setupSystemDb } from "./utils/dbsystem.ts";
5
+
import { setupUserDb } from "./utils/dbuser.ts";
5
6
import { handleSpacedust, startSpacedust } from "./index/spacedust.ts";
6
7
import { handleJetstream, startJetstream } from "./index/jetstream.ts";
7
8
import { Database } from "jsr:@db/sqlite@0.11";
8
9
//import express from "npm:express";
9
10
//import { createServer } from "./xrpc/index.ts";
10
11
import { indexHandlerContext } from "./index/types.ts";
11
-
import * as XRPCTypes from "./utils/viewserver.ts";
12
+
import * as IndexServerTypes from "./utils/indexservertypes.ts";
13
+
import * as ViewServerTypes from "./utils/viewservertypes.ts";
12
14
import * as ATPAPI from "npm:@atproto/api";
13
15
import { didDocument } from "./utils/diddoc.ts";
14
-
15
-
import ky from "npm:ky";
16
-
import QuickLRU from "npm:quick-lru";
17
-
import { isGeneratorView } from "./viewserver/types/app/bsky/feed/defs.ts";
18
-
import { createHash } from "node:crypto";
19
-
20
-
const cache = new QuickLRU({ maxSize: 10000 });
21
-
22
-
function simpleHashAuth(auth: string): string {
23
-
return createHash("sha256").update(auth).digest("hex");
24
-
}
25
-
export async function cachedFetch(url: string, auth?: string) {
26
-
const cacheKey = auth ? `${url}|${simpleHashAuth(auth)}` : url;
27
-
if (cache.has(cacheKey)) return cache.get(cacheKey);
28
-
29
-
const data = await ky
30
-
.get(url, {
31
-
headers: {
32
-
Authorization: `${auth}`, // or `Basic`, etc. depending on your needs
33
-
},
34
-
})
35
-
.json();
36
-
37
-
cache.set(cacheKey, data);
38
-
return data;
39
-
}
16
+
import { cachedFetch, searchParamsToJson } from "./utils/server.ts";
17
+
import { indexServerHandler } from "./indexserver.ts";
18
+
import { viewServerHandler } from "./viewserver.ts";
40
19
41
-
const slingshoturl = Deno.env.get("SLINGSHOT_URL");
42
-
const constellationurl = Deno.env.get("CONSTELLATION_URL");
43
-
const spacedusturl = Deno.env.get("SPACEDUST_URL");
20
+
export const slingshoturl = Deno.env.get("SLINGSHOT_URL");
21
+
export const constellationurl = Deno.env.get("CONSTELLATION_URL");
22
+
export const spacedusturl = Deno.env.get("SPACEDUST_URL");
44
23
45
24
// ------------------------------------------
46
25
// AppView Setup
47
26
// ------------------------------------------
48
27
49
-
export const db = new Database("whatever.db");
50
-
dbsetup();
28
+
export const systemDB = new Database("system.db");
29
+
setupSystemDb(systemDB);
30
+
51
31
export const spacedustManager = new SpacedustManager((msg) =>
52
32
handleSpacedust(msg)
53
33
);
···
68
48
// XRPC Method Implementations
69
49
// ------------------------------------------
70
50
71
-
// begin the hell of implementing api requests and incoming records
72
-
//const seenStrings = new Set<string>();
73
-
74
-
type SlingshotMiniDoc = {
75
-
did: string;
76
-
handle: string;
77
-
pds: string;
78
-
signing_key: string;
79
-
};
80
-
type ConstellationDistinctDids = {
81
-
total: number;
82
-
linking_dids: string[];
83
-
cursor: string;
84
-
};
85
-
type GetRecord = {
86
-
uri: string;
87
-
cid: string;
88
-
value: Record<string, unknown>;
89
-
};
90
-
let preferences: any = undefined;
91
-
92
-
function searchParamsToJson(params: URLSearchParams): Record<string, unknown> {
93
-
const result: Record<string, string | string[]> = {};
94
-
95
-
for (const [key, value] of params.entries()) {
96
-
if (result.hasOwnProperty(key)) {
97
-
const existing = result[key];
98
-
if (Array.isArray(existing)) {
99
-
existing.push(value);
100
-
} else {
101
-
result[key] = [existing, value];
102
-
}
103
-
} else {
104
-
result[key] = value;
105
-
}
106
-
}
107
-
108
-
return result;
109
-
}
110
-
111
-
async function resolveIdentity(actor: string): Promise<SlingshotMiniDoc> {
112
-
const url = `${slingshoturl}/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${actor}`;
113
-
return (await cachedFetch(url)) as SlingshotMiniDoc;
114
-
}
115
-
async function getRecord({
116
-
pds,
117
-
did,
118
-
collection,
119
-
rkey,
120
-
}: {
121
-
pds: string;
122
-
did: string;
123
-
collection: string;
124
-
rkey: string;
125
-
}): Promise<{ cursor?: string; records: GetRecord[] }> {
126
-
const url = `${pds}/xrpc/com.atproto.repo.getRecord?repo=${did}&collection=${collection}&rkey=${rkey}`;
127
-
const result = (await cachedFetch(url)) as {
128
-
cursor?: string;
129
-
records: GetRecord[];
130
-
};
131
-
return result as {
132
-
cursor?: string;
133
-
records: {
134
-
uri: string;
135
-
cid: string;
136
-
value: ATPAPI.AppBskyFeedPost.Record;
137
-
}[];
138
-
};
139
-
}
140
-
141
-
async function listPostRecords({
142
-
pds,
143
-
did,
144
-
limit = 50,
145
-
cursor,
146
-
}: {
147
-
pds: string;
148
-
did: string;
149
-
limit: number;
150
-
cursor?: string;
151
-
}): Promise<{
152
-
cursor?: string;
153
-
records: { uri: string; cid: string; value: ATPAPI.AppBskyFeedPost.Record }[];
154
-
}> {
155
-
const url = `${pds}/xrpc/com.atproto.repo.listRecords?repo=${did}&collection=app.bsky.feed.post&limit=${limit}${
156
-
cursor ? `&cursor=${cursor}` : ""
157
-
}`;
158
-
const result = (await cachedFetch(url)) as {
159
-
cursor?: string;
160
-
records: GetRecord[];
161
-
};
162
-
return result as {
163
-
cursor?: string;
164
-
records: {
165
-
uri: string;
166
-
cid: string;
167
-
value: ATPAPI.AppBskyFeedPost.Record;
168
-
}[];
169
-
};
170
-
}
171
-
172
-
async function getSlingshotRecord(
173
-
did: string,
174
-
collection: string,
175
-
rkey: string
176
-
): Promise<GetRecord> {
177
-
const url = `${slingshoturl}/xrpc/com.atproto.repo.getRecord?repo=${did}&collection=${collection}&rkey=${rkey}`;
178
-
const result = (await cachedFetch(url)) as GetRecord;
179
-
return result as GetRecord;
180
-
}
181
-
182
-
// async function getProfileRecord(did: string): Promise<ATPAPI.AppBskyActorProfile.Record> {
183
-
// const url = `${slingshoturl}/xrpc/com.atproto.repo.getRecord?repo=${did}&collection=app.bsky.actor.profile&rkey=self`;
184
-
// const result = await cachedFetch(url) as GetRecord;
185
-
// return result.value as ATPAPI.AppBskyActorProfile.Record;
186
-
// }
187
-
188
-
async function getUniqueCount({
189
-
did,
190
-
collection,
191
-
path,
192
-
}: {
193
-
did: string;
194
-
collection: string;
195
-
path: string;
196
-
}): Promise<number> {
197
-
const url = `${constellationurl}/links/count/distinct-dids?target=${did}&collection=${collection}&path=${path}`;
198
-
const result = (await cachedFetch(url)) as ConstellationDistinctDids;
199
-
return result.total;
200
-
}
201
-
202
-
function buildBlobUrl(
203
-
pds: string,
204
-
did: string,
205
-
cid: string
206
-
): string | undefined {
207
-
if (!pds || !did || !cid) return undefined;
208
-
return `${pds}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}`;
209
-
}
210
-
211
-
function didWebToHttps(did: string) {
212
-
if (!did.startsWith("did:web:")) return null;
213
-
const parts = did.slice("did:web:".length).split(":");
214
-
const [domain, ...path] = parts;
215
-
return `https://${domain}${path.length ? "/" + path.join("/") : ""}`;
216
-
}
217
-
218
-
async function sendItToApiBskyApp(req: Request): Promise<Response> {
219
-
const url = new URL(req.url);
220
-
const pathname = url.pathname;
221
-
const searchParams = searchParamsToJson(url.searchParams);
222
-
let reqBody: undefined | string;
223
-
let jsonbody: undefined | Record<string, unknown>;
224
-
if (req.body) {
225
-
const body = await req.json();
226
-
jsonbody = body;
227
-
// console.log(
228
-
// `called at euh reqreqreqreq: ${pathname}\n\n${JSON.stringify(body)}`
229
-
// );
230
-
reqBody = JSON.stringify(body, null, 2);
231
-
}
232
-
const bskyUrl = `https://api.bsky.app${pathname}${url.search}`;
233
-
const proxyHeaders = new Headers(req.headers);
234
-
235
-
// Remove Authorization and set browser-like User-Agent
236
-
proxyHeaders.delete("authorization");
237
-
proxyHeaders.delete("Access-Control-Allow-Origin"),
238
-
proxyHeaders.set(
239
-
"user-agent",
240
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"
241
-
);
242
-
proxyHeaders.set("Access-Control-Allow-Origin", "*");
243
-
244
-
const proxyRes = await fetch(bskyUrl, {
245
-
method: req.method,
246
-
headers: proxyHeaders,
247
-
body: ["GET", "HEAD"].includes(req.method.toUpperCase())
248
-
? undefined
249
-
: reqBody,
250
-
});
251
-
252
-
const resBody = await proxyRes.text();
253
-
254
-
// console.log(
255
-
// "← Response:",
256
-
// JSON.stringify(await JSON.parse(resBody), null, 2)
257
-
// );
258
-
259
-
return new Response(resBody, {
260
-
status: proxyRes.status,
261
-
headers: proxyRes.headers,
262
-
});
263
-
}
51
+
const indexServerRoutes = new Set([
52
+
"/xrpc/app.bsky.actor.getProfile",
53
+
"/xrpc/app.bsky.actor.getProfiles",
54
+
"/xrpc/app.bsky.feed.getActorFeeds",
55
+
"/xrpc/app.bsky.feed.getFeedGenerator",
56
+
"/xrpc/app.bsky.feed.getFeedGenerators",
57
+
"/xrpc/app.bsky.feed.getPosts",
58
+
"/xrpc/party.whey.app.bsky.feed.getActorLikesPartial",
59
+
"/xrpc/party.whey.app.bsky.feed.getAuthorFeedPartial",
60
+
"/xrpc/party.whey.app.bsky.feed.getLikesPartial",
61
+
"/xrpc/party.whey.app.bsky.feed.getPostThreadPartial",
62
+
"/xrpc/party.whey.app.bsky.feed.getQuotesPartial",
63
+
"/xrpc/party.whey.app.bsky.feed.getRepostedByPartial",
64
+
]);
264
65
265
66
Deno.serve(
266
67
{ port: Number(`${Deno.env.get("SERVER_PORT")}`) },
267
68
async (req: Request): Promise<Response> => {
268
69
const url = new URL(req.url);
269
70
const pathname = url.pathname;
270
-
const searchParams = searchParamsToJson(url.searchParams);
271
-
let reqBody: undefined | string;
272
-
let jsonbody: undefined | Record<string, unknown>;
273
-
try {
274
-
const clone = req.clone();
275
-
jsonbody = await clone.json();
276
-
} catch (e) {
277
-
console.warn("Request body is not valid JSON:", e);
278
-
}
71
+
// const searchParams = searchParamsToJson(url.searchParams);
72
+
// let reqBody: undefined | string;
73
+
// let jsonbody: undefined | Record<string, unknown>;
74
+
// try {
75
+
// const clone = req.clone();
76
+
// jsonbody = await clone.json();
77
+
// } catch (e) {
78
+
// console.warn("Request body is not valid JSON:", e);
79
+
// }
279
80
if (pathname === "/.well-known/did.json") {
280
81
return new Response(JSON.stringify(didDocument), {
281
82
headers: withCors({ "Content-Type": "application/json" }),
···
299
100
},
300
101
});
301
102
}
302
-
303
-
// if (seenStrings.has(url.hash)) {
304
-
// // The string has been seen before
305
-
// seenStrings.delete(url.hash);
306
-
// return new Response("OK", {
307
-
// status: 204,
308
-
// headers: withCors({
309
-
// "Content-Type": "text/plain",
310
-
// }),
311
-
// });
312
-
// }
313
-
// seenStrings.add(url.hash);
314
-
//const reqBody = req.body ? await req.text() : null;
315
-
316
-
console.log("→ Path:", pathname);
317
-
console.log("→ Auth:", req.headers.get("authorization"));
318
-
console.log("→ Body:", reqBody);
319
-
console.log("→ Params:", searchParams);
320
-
321
-
const bskyUrl = `https://api.bsky.app${pathname}${url.search}`;
322
-
const hasAuth = req.headers.has("authorization");
323
-
const xrpcMethod = pathname.startsWith("/xrpc/")
324
-
? pathname.slice("/xrpc/".length)
325
-
: null;
326
-
327
-
if (xrpcMethod === "app.bsky.unspecced.getTrendingTopics") {
328
-
// const jsonTyped =
329
-
// jsonUntyped as XRPCTypes.AppBskyUnspeccedGetTrendingTopics.QueryParams;
330
-
331
-
const faketopics: ATPAPI.AppBskyUnspeccedDefs.TrendingTopic[] = [
332
-
{
333
-
$type: "app.bsky.unspecced.defs#trendingTopic",
334
-
topic: "Git Repo",
335
-
displayName: "Git Repo",
336
-
description: "Git Repo",
337
-
link: "https://tangled.sh/@whey.party/skylite",
338
-
},
339
-
{
340
-
$type: "app.bsky.unspecced.defs#trendingTopic",
341
-
topic: "Red Dwarf Lite",
342
-
displayName: "Red Dwarf Lite",
343
-
description: "Red Dwarf Lite",
344
-
link: "https://reddwarflite.whey.party/",
345
-
},
346
-
{
347
-
$type: "app.bsky.unspecced.defs#trendingTopic",
348
-
topic: "whey dot party",
349
-
displayName: "whey dot party",
350
-
description: "whey dot party",
351
-
link: "https://whey.party/",
352
-
},
353
-
];
354
-
355
-
const response: XRPCTypes.AppBskyUnspeccedGetTrendingTopics.OutputSchema =
356
-
{
357
-
topics: faketopics,
358
-
suggested: faketopics,
359
-
};
360
-
361
-
return new Response(JSON.stringify(response), {
362
-
headers: withCors({ "Content-Type": "application/json" }),
363
-
});
364
-
}
365
-
366
-
//if (xrpcMethod !== 'app.bsky.actor.getPreferences' && xrpcMethod !== 'app.bsky.notification.listNotifications') {
367
-
if (
368
-
!hasAuth
369
-
// (!hasAuth ||
370
-
// xrpcMethod === "app.bsky.labeler.getServices" ||
371
-
// xrpcMethod === "app.bsky.unspecced.getConfig") &&
372
-
// xrpcMethod !== "app.bsky.notification.putPreferences"
373
-
) {
374
-
return new Response(
375
-
JSON.stringify({
376
-
error: "XRPCNotSupported",
377
-
message:
378
-
"HEY hello there my name is whey dot party and you have used my custom appview that is very cool but have you considered that XRPC Not Supported",
379
-
}),
380
-
{
381
-
status: 404,
382
-
headers: withCors({ "Content-Type": "application/json" }),
383
-
}
384
-
);
385
-
//return await sendItToApiBskyApp(req);
386
-
}
387
-
if (
388
-
// !hasAuth ||
389
-
xrpcMethod === "app.bsky.labeler.getServices" ||
390
-
xrpcMethod === "app.bsky.unspecced.getConfig" //&&
391
-
//xrpcMethod !== "app.bsky.notification.putPreferences"
392
-
) {
393
-
return new Response(
394
-
JSON.stringify({
395
-
error: "XRPCNotSupported",
396
-
message:
397
-
"HEY hello there my name is whey dot party and you have used my custom appview that is very cool but have you considered that XRPC Not Supported",
398
-
}),
399
-
{
400
-
status: 404,
401
-
headers: withCors({ "Content-Type": "application/json" }),
402
-
}
403
-
);
404
-
//return await sendItToApiBskyApp(req);
405
-
}
406
-
407
-
const authDID = "did:plc:mn45tewwnse5btfftvd3powc"; //getAuthenticatedDid(req);
408
-
409
-
const jsonUntyped = searchParams;
410
-
411
-
switch (xrpcMethod) {
412
-
case "app.bsky.feed.getFeedGenerators": {
413
-
const jsonTyped =
414
-
jsonUntyped as XRPCTypes.AppBskyFeedGetFeedGenerators.QueryParams;
415
-
416
-
const feeds: ATPAPI.AppBskyFeedDefs.GeneratorView[] = (
417
-
await Promise.all(
418
-
jsonTyped.feeds.map(async (feed) => {
419
-
try {
420
-
const did = new ATPAPI.AtUri(feed).hostname;
421
-
const rkey = new ATPAPI.AtUri(feed).rkey;
422
-
const identity = await resolveIdentity(did);
423
-
const feedgetRecord = await getSlingshotRecord(
424
-
identity.did,
425
-
"app.bsky.feed.generator",
426
-
rkey
427
-
);
428
-
const profile = (
429
-
await getSlingshotRecord(
430
-
identity.did,
431
-
"app.bsky.actor.profile",
432
-
"self"
433
-
)
434
-
).value as ATPAPI.AppBskyActorProfile.Record;
435
-
const anyprofile = profile as any;
436
-
const value =
437
-
feedgetRecord.value as ATPAPI.AppBskyFeedGenerator.Record;
438
-
439
-
return {
440
-
$type: "app.bsky.feed.defs#generatorView",
441
-
uri: feed,
442
-
cid: feedgetRecord.cid,
443
-
did: identity.did,
444
-
creator: /*AppBskyActorDefs.ProfileView*/ {
445
-
$type: "app.bsky.actor.defs#profileView",
446
-
did: identity.did,
447
-
handle: identity.handle,
448
-
displayName: profile.displayName,
449
-
description: profile.description,
450
-
avatar: buildBlobUrl(
451
-
identity.pds,
452
-
identity.did,
453
-
anyprofile.avatar.ref["$link"]
454
-
),
455
-
//associated?: ProfileAssociated
456
-
//indexedAt?: string
457
-
//createdAt?: string
458
-
//viewer?: ViewerState
459
-
//labels?: ComAtprotoLabelDefs.Label[]
460
-
//verification?: VerificationState
461
-
//status?: StatusView
462
-
},
463
-
displayName: value.displayName,
464
-
description: value.description,
465
-
//descriptionFacets?: AppBskyRichtextFacet.Main[]
466
-
avatar: buildBlobUrl(
467
-
identity.pds,
468
-
identity.did,
469
-
(value as any).avatar.ref["$link"]
470
-
),
471
-
//likeCount?: number
472
-
//acceptsInteractions?: boolean
473
-
//labels?: ComAtprotoLabelDefs.Label[]
474
-
//viewer?: GeneratorViewerState
475
-
contentMode: value.contentMode,
476
-
indexedAt: new Date().toISOString(),
477
-
};
478
-
} catch (err) {
479
-
return undefined;
480
-
}
481
-
})
482
-
)
483
-
).filter(isGeneratorView);
484
-
485
-
const response: XRPCTypes.AppBskyFeedGetFeedGenerators.OutputSchema = {
486
-
feeds: feeds ? feeds : [],
487
-
};
488
-
489
-
return new Response(JSON.stringify(response), {
490
-
headers: withCors({ "Content-Type": "application/json" }),
491
-
});
492
-
}
493
-
case "app.bsky.feed.getFeed": {
494
-
const jsonTyped =
495
-
jsonUntyped as XRPCTypes.AppBskyFeedGetFeed.QueryParams;
496
-
const cursor = jsonTyped.cursor;
497
-
const feed = jsonTyped.feed;
498
-
const limit = jsonTyped.limit;
499
-
const proxyauth = req.headers.get("authorization") || "";
500
-
501
-
const did = new ATPAPI.AtUri(feed).hostname;
502
-
const rkey = new ATPAPI.AtUri(feed).rkey;
503
-
const identity = await resolveIdentity(did);
504
-
const feedgetRecord = (
505
-
await getSlingshotRecord(
506
-
identity.did,
507
-
"app.bsky.feed.generator",
508
-
rkey
509
-
)
510
-
).value as ATPAPI.AppBskyFeedGenerator.Record;
511
-
512
-
const skeleton = (await cachedFetch(
513
-
`${didWebToHttps(
514
-
feedgetRecord.did
515
-
)}/xrpc/app.bsky.feed.getFeedSkeleton?feed=${jsonTyped.feed}${
516
-
cursor ? `&cursor=${cursor}` : ""
517
-
}${limit ? `&limit=${limit}` : ""}`,
518
-
proxyauth
519
-
)) as ATPAPI.AppBskyFeedGetFeedSkeleton.OutputSchema;
520
-
521
-
const nextcursor = skeleton.cursor;
522
-
const dbgrqstid = skeleton.reqId;
523
-
const uriarray = skeleton.feed;
524
-
525
-
// Step 1: Chunk into 25 max
526
-
const chunks = [];
527
-
for (let i = 0; i < uriarray.length; i += 25) {
528
-
chunks.push(uriarray.slice(i, i + 25));
529
-
}
530
-
531
-
// Step 2: Hydrate via getPosts
532
-
const hydratedPosts: ATPAPI.AppBskyFeedDefs.FeedViewPost[] = [];
533
-
534
-
for (const chunk of chunks) {
535
-
const searchParams = new URLSearchParams();
536
-
for (const uri of chunk.map((item) => item.post)) {
537
-
searchParams.append("uris", uri);
538
-
}
539
-
540
-
const postResp = await ky
541
-
.get(`https://api.bsky.app/xrpc/app.bsky.feed.getPosts`, {
542
-
// headers: {
543
-
// Authorization: proxyauth,
544
-
// },
545
-
searchParams,
546
-
})
547
-
.json<ATPAPI.AppBskyFeedGetPosts.OutputSchema>();
548
-
549
-
for (const post of postResp.posts) {
550
-
const matchingSkeleton = uriarray.find(
551
-
(item) => item.post === post.uri
552
-
);
553
-
if (matchingSkeleton) {
554
-
//post.author.handle = post.author.handle + ".percent40.api.bsky.app"; // or any logic to modify it
555
-
hydratedPosts.push({
556
-
post,
557
-
reason: matchingSkeleton.reason,
558
-
//reply: matchingSkeleton,
559
-
});
560
-
}
561
-
}
562
-
}
563
-
564
-
// Step 3: Compose final response
565
-
const response: XRPCTypes.AppBskyFeedGetFeed.OutputSchema = {
566
-
feed: hydratedPosts,
567
-
cursor: nextcursor,
568
-
};
569
-
570
-
return new Response(JSON.stringify(response), {
571
-
headers: withCors({ "Content-Type": "application/json" }),
572
-
});
573
-
}
574
-
case "app.bsky.actor.getProfile": {
575
-
const jsonTyped =
576
-
jsonUntyped as XRPCTypes.AppBskyActorGetProfile.QueryParams;
577
-
578
-
const userindexservice = "";
579
-
const isbskyfallback = true;
580
-
if (isbskyfallback) {
581
-
return sendItToApiBskyApp(req);
582
-
}
583
-
584
-
const response: XRPCTypes.AppBskyActorGetProfile.OutputSchema = {};
585
-
586
-
return new Response(JSON.stringify(response), {
587
-
headers: withCors({ "Content-Type": "application/json" }),
588
-
});
589
-
}
590
-
591
-
case "app.bsky.actor.getProfiles": {
592
-
const jsonTyped =
593
-
jsonUntyped as XRPCTypes.AppBskyActorGetProfiles.QueryParams;
594
-
595
-
const userindexservice = "";
596
-
const isbskyfallback = true;
597
-
if (isbskyfallback) {
598
-
return sendItToApiBskyApp(req);
599
-
}
600
-
601
-
const response: XRPCTypes.AppBskyActorGetProfiles.OutputSchema = {};
602
-
603
-
return new Response(JSON.stringify(response), {
604
-
headers: withCors({ "Content-Type": "application/json" }),
605
-
});
606
-
}
607
-
case "app.bsky.feed.getAuthorFeed": {
608
-
const jsonTyped =
609
-
jsonUntyped as XRPCTypes.AppBskyFeedGetAuthorFeed.QueryParams;
610
-
611
-
const userindexservice = "";
612
-
const isbskyfallback = true;
613
-
if (isbskyfallback) {
614
-
return sendItToApiBskyApp(req);
615
-
}
616
-
617
-
const response: XRPCTypes.AppBskyFeedGetAuthorFeed.OutputSchema = {};
618
-
619
-
return new Response(JSON.stringify(response), {
620
-
headers: withCors({ "Content-Type": "application/json" }),
621
-
});
622
-
}
623
-
case "app.bsky.feed.getPostThread": {
624
-
const jsonTyped =
625
-
jsonUntyped as XRPCTypes.AppBskyFeedGetPostThread.QueryParams;
626
-
627
-
const userindexservice = "";
628
-
const isbskyfallback = true;
629
-
if (isbskyfallback) {
630
-
return sendItToApiBskyApp(req);
631
-
}
632
-
633
-
const response: XRPCTypes.AppBskyFeedGetPostThread.OutputSchema = {};
634
-
635
-
return new Response(JSON.stringify(response), {
636
-
headers: withCors({ "Content-Type": "application/json" }),
637
-
});
638
-
}
639
-
case "app.bsky.unspecced.getPostThreadV2": {
640
-
const jsonTyped =
641
-
jsonUntyped as XRPCTypes.AppBskyUnspeccedGetPostThreadV2.QueryParams;
642
-
643
-
const userindexservice = "";
644
-
const isbskyfallback = true;
645
-
if (isbskyfallback) {
646
-
return sendItToApiBskyApp(req);
647
-
}
648
-
649
-
const response: XRPCTypes.AppBskyUnspeccedGetPostThreadV2.OutputSchema =
650
-
{};
651
-
652
-
return new Response(JSON.stringify(response), {
653
-
headers: withCors({ "Content-Type": "application/json" }),
654
-
});
655
-
}
656
-
657
-
// case "app.bsky.actor.getProfile": {
658
-
// const jsonTyped =
659
-
// jsonUntyped as XRPCTypes.AppBskyActorGetProfile.QueryParams;
660
-
661
-
// const response: XRPCTypes.AppBskyActorGetProfile.OutputSchema= {};
662
-
663
-
// return new Response(JSON.stringify(response), {
664
-
// headers: withCors({ "Content-Type": "application/json" }),
665
-
// });
666
-
// }
667
-
// case "app.bsky.actor.getProfiles": {
668
-
// const jsonTyped = jsonUntyped as XRPCTypes.AppBskyActorGetProfiles.QueryParams;
669
-
670
-
// const response: XRPCTypes.AppBskyActorGetProfiles.OutputSchema = {};
671
-
672
-
// return new Response(JSON.stringify(response), {
673
-
// headers: withCors({ "Content-Type": "application/json" }),
674
-
// });
675
-
// }
676
-
// case "whatever": {
677
-
// const jsonTyped = jsonUntyped as XRPCTypes.AppBskyFeedGetAuthorFeed.QueryParams;
678
-
679
-
// const response: XRPCTypes.AppBskyFeedGetAuthorFeed.OutputSchema = {}
680
-
681
-
// return new Response(JSON.stringify(response), {
682
-
// headers: withCors({ "Content-Type": "application/json" }),
683
-
// });
684
-
// }
685
-
// case "app.bsky.notification.listNotifications": {
686
-
// const jsonTyped =
687
-
// jsonUntyped as XRPCTypes.AppBskyNotificationListNotifications.QueryParams;
688
-
689
-
// const response: XRPCTypes.AppBskyNotificationListNotifications.OutputSchema = {};
690
-
691
-
// return new Response(JSON.stringify(response), {
692
-
// headers: withCors({ "Content-Type": "application/json" }),
693
-
// });
694
-
// }
695
-
696
-
case "app.bsky.unspecced.getConfig": {
697
-
const jsonTyped =
698
-
jsonUntyped as XRPCTypes.AppBskyUnspeccedGetConfig.QueryParams;
699
-
700
-
const response: XRPCTypes.AppBskyUnspeccedGetConfig.OutputSchema = {
701
-
checkEmailConfirmed: true,
702
-
liveNow: [
703
-
{
704
-
$type: "app.bsky.unspecced.getConfig#liveNowConfig",
705
-
did: "did:plc:mn45tewwnse5btfftvd3powc",
706
-
domains: ["local3768forumtest.whey.party"],
707
-
},
708
-
],
709
-
};
710
-
711
-
return new Response(JSON.stringify(response), {
712
-
headers: withCors({ "Content-Type": "application/json" }),
713
-
});
714
-
}
715
-
case "app.bsky.graph.getLists": {
716
-
const jsonTyped =
717
-
jsonUntyped as XRPCTypes.AppBskyGraphGetLists.QueryParams;
718
-
719
-
const response: XRPCTypes.AppBskyGraphGetLists.OutputSchema = {
720
-
lists: [],
721
-
};
722
-
723
-
return new Response(JSON.stringify(response), {
724
-
headers: withCors({ "Content-Type": "application/json" }),
725
-
});
726
-
}
727
-
//https://shimeji.us-east.host.bsky.network/xrpc/app.bsky.unspecced.getTrendingTopics?limit=14
728
-
case "app.bsky.unspecced.getTrendingTopics": {
729
-
const jsonTyped =
730
-
jsonUntyped as XRPCTypes.AppBskyUnspeccedGetTrendingTopics.QueryParams;
731
-
732
-
const faketopics: ATPAPI.AppBskyUnspeccedDefs.TrendingTopic[] = [
733
-
{
734
-
$type: "app.bsky.unspecced.defs#trendingTopic",
735
-
topic: "Git Repo",
736
-
displayName: "Git Repo",
737
-
description: "Git Repo",
738
-
link: "https://tangled.sh/@whey.party/skylite",
739
-
},
740
-
{
741
-
$type: "app.bsky.unspecced.defs#trendingTopic",
742
-
topic: "Red Dwarf Lite",
743
-
displayName: "Red Dwarf Lite",
744
-
description: "Red Dwarf Lite",
745
-
link: "https://reddwarf.whey.party/",
746
-
},
747
-
{
748
-
$type: "app.bsky.unspecced.defs#trendingTopic",
749
-
topic: "whey dot party",
750
-
displayName: "whey dot party",
751
-
description: "whey dot party",
752
-
link: "https://whey.party/",
753
-
},
754
-
];
755
-
756
-
const response: XRPCTypes.AppBskyUnspeccedGetTrendingTopics.OutputSchema =
757
-
{
758
-
topics: faketopics,
759
-
suggested: faketopics,
760
-
};
761
-
762
-
return new Response(JSON.stringify(response), {
763
-
headers: withCors({ "Content-Type": "application/json" }),
764
-
});
765
-
}
766
-
default: {
767
-
return new Response(
768
-
JSON.stringify({
769
-
error: "XRPCNotSupported",
770
-
message:
771
-
"HEY hello there my name is whey dot party and you have used my custom appview that is very cool but have you considered that XRPC Not Supported",
772
-
}),
773
-
{
774
-
status: 404,
775
-
headers: withCors({ "Content-Type": "application/json" }),
776
-
}
777
-
);
778
-
}
103
+
// const bskyUrl = `https://api.bsky.app${pathname}${url.search}`;
104
+
// const hasAuth = req.headers.has("authorization");
105
+
// const xrpcMethod = pathname.startsWith("/xrpc/")
106
+
// ? pathname.slice("/xrpc/".length)
107
+
// : null;
108
+
109
+
if (indexServerRoutes.has(pathname)) {
110
+
return await indexServerHandler(req);
111
+
} else {
112
+
return await viewServerHandler(req);
779
113
}
780
114
}
781
115
);
782
116
783
-
function withCors(headers: HeadersInit = {}) {
117
+
export function withCors(headers: HeadersInit = {}) {
784
118
return {
785
119
"Access-Control-Allow-Origin": "*",
786
120
...headers,
-225
utils/dbsetup.ts
-225
utils/dbsetup.ts
···
1
-
import { db } from "../main.ts"
2
-
3
-
export default function dbsetup(){
4
-
5
-
const baseColumns = `
6
-
uri TEXT PRIMARY KEY NOT NULL,
7
-
did TEXT NOT NULL,
8
-
cid TEXT,
9
-
rev TEXT,
10
-
createdat INTEGER,
11
-
indexedat INTEGER NOT NULL,
12
-
json TEXT
13
-
`;
14
-
15
-
const innerArrayID = "id INTEGER PRIMARY KEY AUTOINCREMENT";
16
-
const createTableINE = "CREATE TABLE IF NOT EXISTS";
17
-
const createIndexINE = "CREATE INDEX IF NOT EXISTS";
18
-
19
-
db.exec(`
20
-
${createTableINE} users (
21
-
did TEXT PRIMARY KEY NOT NULL,
22
-
role TEXT,
23
-
registrationdate TEXT,
24
-
onboardingstatus TEXT
25
-
);
26
-
27
-
${createTableINE} remoteprofileview (
28
-
did TEXT PRIMARY KEY NOT NULL,
29
-
handle TEXT,
30
-
displayname TEXT,
31
-
description TEXT,
32
-
avatar TEXT,
33
-
banner TEXT
34
-
);
35
-
36
-
${createTableINE} did (
37
-
did TEXT PRIMARY KEY NOT NULL,
38
-
method TEXT,
39
-
string TEXT,
40
-
doc TEXT,
41
-
pds TEXT,
42
-
handle TEXT
43
-
);
44
-
${createIndexINE} idx_did_handle ON did(handle);
45
-
46
-
${createTableINE} prefs (
47
-
did TEXT PRIMARY KEY NOT NULL,
48
-
json TEXT
49
-
);
50
-
${createIndexINE} idx_prefs_did ON prefs(did);
51
-
52
-
${createTableINE} backlink_skeleton (
53
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
54
-
srcuri TEXT,
55
-
srcdid TEXT,
56
-
srcfield TEXT,
57
-
srccol TEXT,
58
-
suburi TEXT,
59
-
subdid TEXT,
60
-
subcol TEXT
61
-
);
62
-
${createIndexINE} idx_backlink_subdid_mod ON backlink_skeleton(subdid, srcdid);
63
-
${createIndexINE} idx_backlink_suburi_mod ON backlink_skeleton(suburi, srcdid);
64
-
${createIndexINE} idx_backlink_subdid_filter_mod ON backlink_skeleton(subdid, srccol, srcdid);
65
-
${createIndexINE} idx_backlink_suburi_filter_mod ON backlink_skeleton(suburi, srccol, srcdid);
66
-
67
-
${createTableINE} app_bsky_actor_profile (
68
-
${baseColumns},
69
-
displayname TEXT,
70
-
description TEXT,
71
-
avatarcid TEXT,
72
-
avatarmime TEXT,
73
-
bannercid TEXT,
74
-
bannermime TEXT
75
-
);
76
-
${createIndexINE} idx_actor_profile_did ON app_bsky_actor_profile(did);
77
-
78
-
${createTableINE} app_bsky_feed_post (
79
-
${baseColumns},
80
-
text TEXT,
81
-
replyroot TEXT,
82
-
replyparent TEXT,
83
-
quote TEXT,
84
-
imagecount INTEGER,
85
-
image1cid TEXT,
86
-
image1mime TEXT,
87
-
image1aspect TEXT,
88
-
image2cid TEXT,
89
-
image2mime TEXT,
90
-
image2aspect TEXT,
91
-
image3cid TEXT,
92
-
image3mime TEXT,
93
-
image3aspect TEXT,
94
-
image4cid TEXT,
95
-
image4mime TEXT,
96
-
image4aspect TEXT,
97
-
videocount INTEGER,
98
-
videocid TEXT,
99
-
videomime TEXT,
100
-
videoaspect TEXT
101
-
);
102
-
103
-
${createIndexINE} idx_post_author_timeline ON app_bsky_feed_post(did, createdat DESC);
104
-
${createIndexINE} idx_post_global_timeline ON app_bsky_feed_post(indexedat DESC);
105
-
${createIndexINE} idx_post_replyroot ON app_bsky_feed_post(replyroot);
106
-
${createIndexINE} idx_post_replyparent ON app_bsky_feed_post(replyparent);
107
-
${createIndexINE} idx_post_quote ON app_bsky_feed_post(quote);
108
-
109
-
${createTableINE} app_bsky_feed_post_langs (
110
-
${innerArrayID},
111
-
post TEXT NOT NULL,
112
-
lang TEXT NOT NULL
113
-
);
114
-
${createIndexINE} idx_post_langs_lang ON app_bsky_feed_post_langs(lang);
115
-
${createIndexINE} idx_post_langs_post ON app_bsky_feed_post_langs(post);
116
-
117
-
${createTableINE} app_bsky_feed_post_hashtags (
118
-
${innerArrayID},
119
-
post TEXT NOT NULL,
120
-
hashtag TEXT NOT NULL
121
-
);
122
-
${createIndexINE} idx_post_hashtags_hashtag ON app_bsky_feed_post_hashtags(hashtag);
123
-
${createIndexINE} idx_post_hashtags_post ON app_bsky_feed_post_hashtags(post);
124
-
125
-
${createTableINE} app_bsky_feed_post_mentions (
126
-
${innerArrayID},
127
-
post TEXT NOT NULL,
128
-
mention TEXT NOT NULL
129
-
);
130
-
${createIndexINE} idx_post_mentions_mention ON app_bsky_feed_post_mentions(mention);
131
-
${createIndexINE} idx_post_mentions_post ON app_bsky_feed_post_mentions(post);
132
-
133
-
134
-
${createTableINE} app_bsky_feed_like (
135
-
${baseColumns},
136
-
subject TEXT NOT NULL,
137
-
subjectcid TEXT
138
-
);
139
-
${createIndexINE} idx_like_author_timeline ON app_bsky_feed_like(did, createdat DESC);
140
-
${createIndexINE} idx_like_subject ON app_bsky_feed_like(subject);
141
-
142
-
${createTableINE} app_bsky_feed_repost (
143
-
${baseColumns},
144
-
subject TEXT NOT NULL,
145
-
subjectcid TEXT
146
-
);
147
-
${createIndexINE} idx_repost_author_timeline ON app_bsky_feed_repost(did, createdat DESC);
148
-
${createIndexINE} idx_repost_subject ON app_bsky_feed_repost(subject);
149
-
150
-
151
-
${createTableINE} app_bsky_graph_follow (
152
-
${baseColumns},
153
-
subject TEXT NOT NULL
154
-
);
155
-
${createIndexINE} idx_follow_author_timeline ON app_bsky_graph_follow(did, createdat DESC);
156
-
${createIndexINE} idx_follow_subject_timeline ON app_bsky_graph_follow(subject, createdat DESC);
157
-
158
-
${createTableINE} app_bsky_graph_block (
159
-
${baseColumns},
160
-
subject TEXT NOT NULL
161
-
);
162
-
${createIndexINE} idx_block_author ON app_bsky_graph_block(did);
163
-
${createIndexINE} idx_block_subject ON app_bsky_graph_block(subject);
164
-
165
-
${createTableINE} app_bsky_graph_list (
166
-
${baseColumns},
167
-
name TEXT,
168
-
description TEXT,
169
-
purpose TEXT,
170
-
avatarcid TEXT,
171
-
avatarmime TEXT
172
-
);
173
-
${createIndexINE} idx_list_author ON app_bsky_graph_list(did);
174
-
${createIndexINE} idx_list_purpose ON app_bsky_graph_list(purpose);
175
-
176
-
${createTableINE} app_bsky_graph_listitem (
177
-
${baseColumns},
178
-
list TEXT NOT NULL,
179
-
subject TEXT NOT NULL
180
-
);
181
-
${createIndexINE} idx_listitem_list ON app_bsky_graph_listitem(list);
182
-
${createIndexINE} idx_listitem_subject ON app_bsky_graph_listitem(subject);
183
-
${createIndexINE} idx_listitem_author ON app_bsky_graph_listitem(did);
184
-
185
-
186
-
187
-
${createTableINE} app_bsky_feed_generator (
188
-
${baseColumns},
189
-
displayname TEXT,
190
-
description TEXT,
191
-
avatarcid TEXT,
192
-
avatarmime TEXT
193
-
);
194
-
${createIndexINE} idx_feed_generator_author ON app_bsky_feed_generator(did);
195
-
196
-
${createTableINE} app_bsky_feed_threadgate (
197
-
${baseColumns},
198
-
post TEXT NOT NULL
199
-
);
200
-
${createIndexINE} idx_threadgate_post ON app_bsky_feed_threadgate(post);
201
-
${createIndexINE} idx_threadgate_author ON app_bsky_feed_threadgate(did);
202
-
203
-
204
-
${createTableINE} app_bsky_feed_threadgate_hiddenreplies (
205
-
${innerArrayID},
206
-
threadgate TEXT NOT NULL,
207
-
reply TEXT NOT NULL
208
-
);
209
-
${createIndexINE} idx_threadgate_hiddenreplies_gate ON app_bsky_feed_threadgate_hiddenreplies(threadgate);
210
-
211
-
${createTableINE} app_bsky_graph_listblock (
212
-
${baseColumns},
213
-
subject TEXT NOT NULL
214
-
);
215
-
${createIndexINE} idx_listblock_subject ON app_bsky_graph_listblock(subject);
216
-
${createIndexINE} idx_listblock_author ON app_bsky_graph_listblock(did);
217
-
218
-
${createTableINE} app_bsky_notification_declaration (
219
-
${baseColumns},
220
-
allowSubscriptions TEXT
221
-
);
222
-
${createIndexINE} idx_notification_declaration_author ON app_bsky_notification_declaration(did);
223
-
224
-
`);
225
-
}
+53
utils/dbsystem.ts
+53
utils/dbsystem.ts
···
1
+
import { Database } from "jsr:@db/sqlite@0.11";
2
+
3
+
export function setupSystemDb(db: Database) {
4
+
const createTableINE = "CREATE TABLE IF NOT EXISTS";
5
+
const createIndexINE = "CREATE INDEX IF NOT EXISTS";
6
+
7
+
db.exec(`
8
+
-- Master list of all users known to the system
9
+
${createTableINE} users (
10
+
did TEXT PRIMARY KEY NOT NULL,
11
+
role TEXT,
12
+
registrationdate TEXT,
13
+
onboardingstatus TEXT
14
+
);
15
+
16
+
-- Cache of profiles for *other* users, prevents storing this in every user's DB
17
+
${createTableINE} remoteprofileview (
18
+
did TEXT PRIMARY KEY NOT NULL,
19
+
handle TEXT,
20
+
displayname TEXT,
21
+
description TEXT,
22
+
avatar TEXT,
23
+
banner TEXT
24
+
);
25
+
26
+
-- Central DID document cache and handle resolution
27
+
${createTableINE} did (
28
+
did TEXT PRIMARY KEY NOT NULL,
29
+
method TEXT,
30
+
string TEXT,
31
+
doc TEXT,
32
+
pds TEXT,
33
+
handle TEXT
34
+
);
35
+
${createIndexINE} idx_did_handle ON did(handle);
36
+
37
+
-- A global index for relationships between any two pieces of content
38
+
${createTableINE} backlink_skeleton (
39
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
40
+
srcuri TEXT,
41
+
srcdid TEXT,
42
+
srcfield TEXT,
43
+
srccol TEXT,
44
+
suburi TEXT,
45
+
subdid TEXT,
46
+
subcol TEXT
47
+
);
48
+
${createIndexINE} idx_backlink_subdid_mod ON backlink_skeleton(subdid, srcdid);
49
+
${createIndexINE} idx_backlink_suburi_mod ON backlink_skeleton(suburi, srcdid);
50
+
${createIndexINE} idx_backlink_subdid_filter_mod ON backlink_skeleton(subdid, srccol, srcdid);
51
+
${createIndexINE} idx_backlink_suburi_filter_mod ON backlink_skeleton(suburi, srccol, srcdid);
52
+
`);
53
+
}
+135
utils/dbuser.ts
+135
utils/dbuser.ts
···
1
+
import { Database } from "jsr:@db/sqlite@0.11";
2
+
3
+
export function setupUserDb(db: Database) {
4
+
5
+
const baseColumns = `
6
+
uri TEXT PRIMARY KEY NOT NULL,
7
+
did TEXT NOT NULL,
8
+
cid TEXT,
9
+
rev TEXT,
10
+
createdat INTEGER,
11
+
indexedat INTEGER NOT NULL,
12
+
json TEXT
13
+
`;
14
+
15
+
const innerArrayID = "id INTEGER PRIMARY KEY AUTOINCREMENT";
16
+
const createTableINE = "CREATE TABLE IF NOT EXISTS";
17
+
const createIndexINE = "CREATE INDEX IF NOT EXISTS";
18
+
19
+
db.exec(`
20
+
-- User's own personal preferences
21
+
${createTableINE} prefs (
22
+
did TEXT PRIMARY KEY NOT NULL,
23
+
json TEXT
24
+
);
25
+
${createIndexINE} idx_prefs_did ON prefs(did);
26
+
27
+
-- The user's own profile record
28
+
${createTableINE} app_bsky_actor_profile (
29
+
${baseColumns},
30
+
displayname TEXT,
31
+
description TEXT,
32
+
avatarcid TEXT,
33
+
avatarmime TEXT,
34
+
bannercid TEXT,
35
+
bannermime TEXT
36
+
);
37
+
${createIndexINE} idx_actor_profile_did ON app_bsky_actor_profile(did);
38
+
39
+
-- All posts created by the user
40
+
${createTableINE} app_bsky_feed_post (
41
+
${baseColumns},
42
+
text TEXT,
43
+
replyroot TEXT,
44
+
replyparent TEXT,
45
+
quote TEXT,
46
+
imagecount INTEGER,
47
+
image1cid TEXT,
48
+
image1mime TEXT,
49
+
image1aspect TEXT,
50
+
image2cid TEXT,
51
+
image2mime TEXT,
52
+
image2aspect TEXT,
53
+
image3cid TEXT,
54
+
image3mime TEXT,
55
+
image3aspect TEXT,
56
+
image4cid TEXT,
57
+
image4mime TEXT,
58
+
image4aspect TEXT,
59
+
videocount INTEGER,
60
+
videocid TEXT,
61
+
videomime TEXT,
62
+
videoaspect TEXT
63
+
);
64
+
${createIndexINE} idx_post_author_timeline ON app_bsky_feed_post(did, createdat DESC);
65
+
${createIndexINE} idx_post_global_timeline ON app_bsky_feed_post(indexedat DESC);
66
+
${createIndexINE} idx_post_replyroot ON app_bsky_feed_post(replyroot);
67
+
${createIndexINE} idx_post_replyparent ON app_bsky_feed_post(replyparent);
68
+
${createIndexINE} idx_post_quote ON app_bsky_feed_post(quote);
69
+
70
+
-- Data related to the user's posts
71
+
${createTableINE} app_bsky_feed_post_langs ( ${innerArrayID}, post TEXT NOT NULL, lang TEXT NOT NULL );
72
+
${createIndexINE} idx_post_langs_lang ON app_bsky_feed_post_langs(lang);
73
+
${createIndexINE} idx_post_langs_post ON app_bsky_feed_post_langs(post);
74
+
75
+
${createTableINE} app_bsky_feed_post_hashtags ( ${innerArrayID}, post TEXT NOT NULL, hashtag TEXT NOT NULL );
76
+
${createIndexINE} idx_post_hashtags_hashtag ON app_bsky_feed_post_hashtags(hashtag);
77
+
${createIndexINE} idx_post_hashtags_post ON app_bsky_feed_post_hashtags(post);
78
+
79
+
${createTableINE} app_bsky_feed_post_mentions ( ${innerArrayID}, post TEXT NOT NULL, mention TEXT NOT NULL );
80
+
${createIndexINE} idx_post_mentions_mention ON app_bsky_feed_post_mentions(mention);
81
+
${createIndexINE} idx_post_mentions_post ON app_bsky_feed_post_mentions(post);
82
+
83
+
-- All likes created by the user
84
+
${createTableINE} app_bsky_feed_like ( ${baseColumns}, subject TEXT NOT NULL, subjectcid TEXT );
85
+
${createIndexINE} idx_like_author_timeline ON app_bsky_feed_like(did, createdat DESC);
86
+
${createIndexINE} idx_like_subject ON app_bsky_feed_like(subject);
87
+
88
+
-- All reposts created by the user
89
+
${createTableINE} app_bsky_feed_repost ( ${baseColumns}, subject TEXT NOT NULL, subjectcid TEXT );
90
+
${createIndexINE} idx_repost_author_timeline ON app_bsky_feed_repost(did, createdat DESC);
91
+
${createIndexINE} idx_repost_subject ON app_bsky_feed_repost(subject);
92
+
93
+
-- All follows created by the user
94
+
${createTableINE} app_bsky_graph_follow ( ${baseColumns}, subject TEXT NOT NULL );
95
+
${createIndexINE} idx_follow_author_timeline ON app_bsky_graph_follow(did, createdat DESC);
96
+
${createIndexINE} idx_follow_subject_timeline ON app_bsky_graph_follow(subject, createdat DESC);
97
+
98
+
-- All blocks created by the user
99
+
${createTableINE} app_bsky_graph_block ( ${baseColumns}, subject TEXT NOT NULL );
100
+
${createIndexINE} idx_block_author ON app_bsky_graph_block(did);
101
+
${createIndexINE} idx_block_subject ON app_bsky_graph_block(subject);
102
+
103
+
-- All lists created by the user
104
+
${createTableINE} app_bsky_graph_list ( ${baseColumns}, name TEXT, description TEXT, purpose TEXT, avatarcid TEXT, avatarmime TEXT );
105
+
${createIndexINE} idx_list_author ON app_bsky_graph_list(did);
106
+
${createIndexINE} idx_list_purpose ON app_bsky_graph_list(purpose);
107
+
108
+
-- All list items created by the user
109
+
${createTableINE} app_bsky_graph_listitem ( ${baseColumns}, list TEXT NOT NULL, subject TEXT NOT NULL );
110
+
${createIndexINE} idx_listitem_list ON app_bsky_graph_listitem(list);
111
+
${createIndexINE} idx_listitem_subject ON app_bsky_graph_listitem(subject);
112
+
${createIndexINE} idx_listitem_author ON app_bsky_graph_listitem(did);
113
+
114
+
-- All feed generators created by the user
115
+
${createTableINE} app_bsky_feed_generator ( ${baseColumns}, displayname TEXT, description TEXT, avatarcid TEXT, avatarmime TEXT );
116
+
${createIndexINE} idx_feed_generator_author ON app_bsky_feed_generator(did);
117
+
118
+
-- All threadgates created by the user
119
+
${createTableINE} app_bsky_feed_threadgate ( ${baseColumns}, post TEXT NOT NULL );
120
+
${createIndexINE} idx_threadgate_post ON app_bsky_feed_threadgate(post);
121
+
${createIndexINE} idx_threadgate_author ON app_bsky_feed_threadgate(did);
122
+
123
+
${createTableINE} app_bsky_feed_threadgate_hiddenreplies ( ${innerArrayID}, threadgate TEXT NOT NULL, reply TEXT NOT NULL );
124
+
${createIndexINE} idx_threadgate_hiddenreplies_gate ON app_bsky_feed_threadgate_hiddenreplies(threadgate);
125
+
126
+
-- All list blocks created by the user
127
+
${createTableINE} app_bsky_graph_listblock ( ${baseColumns}, subject TEXT NOT NULL );
128
+
${createIndexINE} idx_listblock_subject ON app_bsky_graph_listblock(subject);
129
+
${createIndexINE} idx_listblock_author ON app_bsky_graph_listblock(did);
130
+
131
+
-- User's notification settings declaration
132
+
${createTableINE} app_bsky_notification_declaration ( ${baseColumns}, allowSubscriptions TEXT );
133
+
${createIndexINE} idx_notification_declaration_author ON app_bsky_notification_declaration(did);
134
+
`);
135
+
}
+7
-7
utils/identity.ts
+7
-7
utils/identity.ts
···
1
1
2
2
import { DidResolver, HandleResolver } from "npm:@atproto/identity";
3
-
import { db } from "../main.ts";
3
+
import { systemDB } from "../main.ts";
4
4
type DidMethod = "web" | "plc";
5
5
type DidDoc = {
6
6
"@context"?: unknown;
···
35
35
}
36
36
37
37
function getDidFromHandle(handle: string): { did: string } | null {
38
-
const row = db.prepare("SELECT did FROM did WHERE handle = ?").get(handle);
38
+
const row = systemDB.prepare("SELECT did FROM did WHERE handle = ?").get(handle);
39
39
if (!row) return null;
40
40
41
41
try {
···
65
65
function getDidDoc(
66
66
did: string
67
67
): { method: "web" | "plc"; doc: DidDoc } | null {
68
-
const row = db.prepare("SELECT method, doc FROM did WHERE did = ?").get(did);
68
+
const row = systemDB.prepare("SELECT method, doc FROM did WHERE did = ?").get(did);
69
69
if (!row) return null;
70
70
71
71
try {
···
126
126
function getPDSAndHandleFromDid(
127
127
did: string
128
128
): { pds: string; handle?: string } | null {
129
-
const row = db.prepare("SELECT pds, handle FROM did WHERE did = ?").get(did);
129
+
const row = systemDB.prepare("SELECT pds, handle FROM did WHERE did = ?").get(did);
130
130
131
131
if (!row) return null;
132
132
return {
···
144
144
const { did } = await resolveDidFromHandle(handle);
145
145
const { diddoc, didmethod } = await resolveDidDoc(did);
146
146
147
-
db.prepare(
147
+
systemDB.prepare(
148
148
"INSERT OR REPLACE INTO did (did, handle, doc, method) VALUES (?, ?, ?, ?)"
149
149
).run(did, handle, JSON.stringify(diddoc), didmethod);
150
150
···
162
162
try {
163
163
const { diddoc, didmethod } = await resolveDidDoc(did);
164
164
165
-
db.prepare(
165
+
systemDB.prepare(
166
166
"INSERT OR REPLACE INTO did (did, doc, method) VALUES (?, ?, ?)"
167
167
).run(did, JSON.stringify(diddoc), didmethod);
168
168
···
215
215
if (aka) handle = aka.slice("at://".length);
216
216
}
217
217
218
-
db.prepare(
218
+
systemDB.prepare(
219
219
"INSERT OR REPLACE INTO did (did, pds, handle) VALUES (?, ?, ?)"
220
220
).run(did, serviceEndpoint, handle ?? null);
221
221
utils/indexserver.ts
utils/indexserver.ts
This is a binary file and will not be displayed.
+13
utils/indexservertypes.ts
+13
utils/indexservertypes.ts
···
1
+
export * as AppBskyActorGetProfile from '../indexserver/types/app/bsky/actor/getProfile.ts'
2
+
export * as AppBskyActorGetProfiles from '../indexserver/types/app/bsky/actor/getProfiles.ts'
3
+
export * as AppBskyFeedGetActorFeeds from '../indexserver/types/app/bsky/feed/getActorFeeds.ts'
4
+
export * as AppBskyFeedGetFeedGenerator from '../indexserver/types/app/bsky/feed/getFeedGenerator.ts'
5
+
export * as AppBskyFeedGetFeedGenerators from '../indexserver/types/app/bsky/feed/getFeedGenerators.ts'
6
+
export * as AppBskyFeedGetPosts from '../indexserver/types/app/bsky/feed/getPosts.ts'
7
+
export * as PartyWheyAppBskyFeedGetActorLikesPartial from '../indexserver/types/party/whey/app/bsky/feed/getActorLikesPartial.ts'
8
+
export * as PartyWheyAppBskyFeedGetAuthorFeedPartial from '../indexserver/types/party/whey/app/bsky/feed/getAuthorFeedPartial.ts'
9
+
export * as PartyWheyAppBskyFeedGetLikesPartial from '../indexserver/types/party/whey/app/bsky/feed/getLikesPartial.ts'
10
+
export * as PartyWheyAppBskyFeedGetListFeedPartial from '../indexserver/types/party/whey/app/bsky/feed/getListFeedPartial.ts'
11
+
export * as PartyWheyAppBskyFeedGetPostThreadPartial from '../indexserver/types/party/whey/app/bsky/feed/getPostThreadPartial.ts'
12
+
export * as PartyWheyAppBskyFeedGetQuotesPartial from '../indexserver/types/party/whey/app/bsky/feed/getQuotesPartial.ts'
13
+
export * as PartyWheyAppBskyFeedGetRepostedByPartial from '../indexserver/types/party/whey/app/bsky/feed/getRepostedByPartial.ts'
+175
utils/server.ts
+175
utils/server.ts
···
1
+
import ky from "npm:ky";
2
+
import QuickLRU from "npm:quick-lru";
3
+
import { createHash } from "node:crypto";
4
+
import { slingshoturl, constellationurl } from "../main.ts";
5
+
import * as ATPAPI from "npm:@atproto/api";
6
+
7
+
const cache = new QuickLRU({ maxSize: 10000 });
8
+
9
+
function simpleHashAuth(auth: string): string {
10
+
return createHash("sha256").update(auth).digest("hex");
11
+
}
12
+
export async function cachedFetch(url: string, auth?: string) {
13
+
const cacheKey = auth ? `${url}|${simpleHashAuth(auth)}` : url;
14
+
if (cache.has(cacheKey)) return cache.get(cacheKey);
15
+
16
+
const data = await ky
17
+
.get(url, {
18
+
headers: {
19
+
Authorization: `${auth}`,
20
+
},
21
+
})
22
+
.json();
23
+
24
+
cache.set(cacheKey, data);
25
+
return data;
26
+
}
27
+
28
+
export type SlingshotMiniDoc = {
29
+
did: string;
30
+
handle: string;
31
+
pds: string;
32
+
signing_key: string;
33
+
};
34
+
let preferences: any = undefined;
35
+
36
+
export function searchParamsToJson(
37
+
params: URLSearchParams
38
+
): Record<string, unknown> {
39
+
const result: Record<string, string | string[]> = {};
40
+
41
+
for (const [key, value] of params.entries()) {
42
+
if (result.hasOwnProperty(key)) {
43
+
const existing = result[key];
44
+
if (Array.isArray(existing)) {
45
+
existing.push(value);
46
+
} else {
47
+
result[key] = [existing, value];
48
+
}
49
+
} else {
50
+
result[key] = value;
51
+
}
52
+
}
53
+
54
+
return result;
55
+
}
56
+
57
+
export async function resolveIdentity(
58
+
actor: string
59
+
): Promise<SlingshotMiniDoc> {
60
+
const url = `${slingshoturl}/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${actor}`;
61
+
return (await cachedFetch(url)) as SlingshotMiniDoc;
62
+
}
63
+
export async function getRecord({
64
+
pds,
65
+
did,
66
+
collection,
67
+
rkey,
68
+
}: {
69
+
pds: string;
70
+
did: string;
71
+
collection: string;
72
+
rkey: string;
73
+
}): Promise<{ cursor?: string; records: GetRecord[] }> {
74
+
const url = `${pds}/xrpc/com.atproto.repo.getRecord?repo=${did}&collection=${collection}&rkey=${rkey}`;
75
+
const result = (await cachedFetch(url)) as {
76
+
cursor?: string;
77
+
records: GetRecord[];
78
+
};
79
+
return result as {
80
+
cursor?: string;
81
+
records: {
82
+
uri: string;
83
+
cid: string;
84
+
value: ATPAPI.AppBskyFeedPost.Record;
85
+
}[];
86
+
};
87
+
}
88
+
89
+
export async function listPostRecords({
90
+
pds,
91
+
did,
92
+
limit = 50,
93
+
cursor,
94
+
}: {
95
+
pds: string;
96
+
did: string;
97
+
limit: number;
98
+
cursor?: string;
99
+
}): Promise<{
100
+
cursor?: string;
101
+
records: { uri: string; cid: string; value: ATPAPI.AppBskyFeedPost.Record }[];
102
+
}> {
103
+
const url = `${pds}/xrpc/com.atproto.repo.listRecords?repo=${did}&collection=app.bsky.feed.post&limit=${limit}${
104
+
cursor ? `&cursor=${cursor}` : ""
105
+
}`;
106
+
const result = (await cachedFetch(url)) as {
107
+
cursor?: string;
108
+
records: GetRecord[];
109
+
};
110
+
return result as {
111
+
cursor?: string;
112
+
records: {
113
+
uri: string;
114
+
cid: string;
115
+
value: ATPAPI.AppBskyFeedPost.Record;
116
+
}[];
117
+
};
118
+
}
119
+
120
+
// async function getProfileRecord(did: string): Promise<ATPAPI.AppBskyActorProfile.Record> {
121
+
// const url = `${slingshoturl}/xrpc/com.atproto.repo.getRecord?repo=${did}&collection=app.bsky.actor.profile&rkey=self`;
122
+
// const result = await cachedFetch(url) as GetRecord;
123
+
// return result.value as ATPAPI.AppBskyActorProfile.Record;
124
+
// }
125
+
126
+
export function buildBlobUrl(
127
+
pds: string,
128
+
did: string,
129
+
cid: string
130
+
): string | undefined {
131
+
if (!pds || !did || !cid) return undefined;
132
+
return `${pds}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}`;
133
+
}
134
+
135
+
export type ConstellationDistinctDids = {
136
+
total: number;
137
+
linking_dids: string[];
138
+
cursor: string;
139
+
};
140
+
export type GetRecord = {
141
+
uri: string;
142
+
cid: string;
143
+
value: Record<string, unknown>;
144
+
};
145
+
146
+
export function didWebToHttps(did: string) {
147
+
if (!did.startsWith("did:web:")) return null;
148
+
const parts = did.slice("did:web:".length).split(":");
149
+
const [domain, ...path] = parts;
150
+
return `https://${domain}${path.length ? "/" + path.join("/") : ""}`;
151
+
}
152
+
153
+
export async function getSlingshotRecord(
154
+
did: string,
155
+
collection: string,
156
+
rkey: string
157
+
): Promise<GetRecord> {
158
+
const url = `${slingshoturl}/xrpc/com.atproto.repo.getRecord?repo=${did}&collection=${collection}&rkey=${rkey}`;
159
+
const result = (await cachedFetch(url)) as GetRecord;
160
+
return result as GetRecord;
161
+
}
162
+
163
+
export async function getUniqueCount({
164
+
did,
165
+
collection,
166
+
path,
167
+
}: {
168
+
did: string;
169
+
collection: string;
170
+
path: string;
171
+
}): Promise<number> {
172
+
const url = `${constellationurl}/links/count/distinct-dids?target=${did}&collection=${collection}&path=${path}`;
173
+
const result = (await cachedFetch(url)) as ConstellationDistinctDids;
174
+
return result.total;
175
+
}
utils/viewserver.ts
utils/viewservertypes.ts
utils/viewserver.ts
utils/viewservertypes.ts
+525
viewserver.ts
+525
viewserver.ts
···
1
+
import ky from "npm:ky";
2
+
import { isGeneratorView } from "./indexserver/types/app/bsky/feed/defs.ts";
3
+
import { withCors } from "./main.ts";
4
+
import * as ViewServerTypes from "./utils/viewservertypes.ts";
5
+
import * as ATPAPI from "npm:@atproto/api";
6
+
import {
7
+
searchParamsToJson,
8
+
resolveIdentity,
9
+
buildBlobUrl,
10
+
cachedFetch,
11
+
didWebToHttps,
12
+
getSlingshotRecord,
13
+
} from "./utils/server.ts";
14
+
15
+
export async function viewServerHandler(req: Request): Promise<Response> {
16
+
const url = new URL(req.url);
17
+
const pathname = url.pathname;
18
+
const bskyUrl = `https://api.bsky.app${pathname}${url.search}`;
19
+
const hasAuth = req.headers.has("authorization");
20
+
const xrpcMethod = pathname.startsWith("/xrpc/")
21
+
? pathname.slice("/xrpc/".length)
22
+
: null;
23
+
const searchParams = searchParamsToJson(url.searchParams);
24
+
const jsonUntyped = searchParams;
25
+
26
+
if (xrpcMethod === "app.bsky.unspecced.getTrendingTopics") {
27
+
// const jsonTyped =
28
+
// jsonUntyped as ViewServerTypes.AppBskyUnspeccedGetTrendingTopics.QueryParams;
29
+
30
+
const faketopics: ATPAPI.AppBskyUnspeccedDefs.TrendingTopic[] = [
31
+
{
32
+
$type: "app.bsky.unspecced.defs#trendingTopic",
33
+
topic: "Git Repo",
34
+
displayName: "Git Repo",
35
+
description: "Git Repo",
36
+
link: "https://tangled.sh/@whey.party/skylite",
37
+
},
38
+
{
39
+
$type: "app.bsky.unspecced.defs#trendingTopic",
40
+
topic: "Red Dwarf Lite",
41
+
displayName: "Red Dwarf Lite",
42
+
description: "Red Dwarf Lite",
43
+
link: "https://reddwarflite.whey.party/",
44
+
},
45
+
{
46
+
$type: "app.bsky.unspecced.defs#trendingTopic",
47
+
topic: "whey dot party",
48
+
displayName: "whey dot party",
49
+
description: "whey dot party",
50
+
link: "https://whey.party/",
51
+
},
52
+
];
53
+
54
+
const response: ViewServerTypes.AppBskyUnspeccedGetTrendingTopics.OutputSchema =
55
+
{
56
+
topics: faketopics,
57
+
suggested: faketopics,
58
+
};
59
+
60
+
return new Response(JSON.stringify(response), {
61
+
headers: withCors({ "Content-Type": "application/json" }),
62
+
});
63
+
}
64
+
65
+
//if (xrpcMethod !== 'app.bsky.actor.getPreferences' && xrpcMethod !== 'app.bsky.notification.listNotifications') {
66
+
if (
67
+
!hasAuth
68
+
// (!hasAuth ||
69
+
// xrpcMethod === "app.bsky.labeler.getServices" ||
70
+
// xrpcMethod === "app.bsky.unspecced.getConfig") &&
71
+
// xrpcMethod !== "app.bsky.notification.putPreferences"
72
+
) {
73
+
return new Response(
74
+
JSON.stringify({
75
+
error: "XRPCNotSupported",
76
+
message:
77
+
"HEY hello there my name is whey dot party and you have used my custom appview that is very cool but have you considered that XRPC Not Supported",
78
+
}),
79
+
{
80
+
status: 404,
81
+
headers: withCors({ "Content-Type": "application/json" }),
82
+
}
83
+
);
84
+
//return await sendItToApiBskyApp(req);
85
+
}
86
+
if (
87
+
// !hasAuth ||
88
+
xrpcMethod === "app.bsky.labeler.getServices" ||
89
+
xrpcMethod === "app.bsky.unspecced.getConfig" //&&
90
+
//xrpcMethod !== "app.bsky.notification.putPreferences"
91
+
) {
92
+
return new Response(
93
+
JSON.stringify({
94
+
error: "XRPCNotSupported",
95
+
message:
96
+
"HEY hello there my name is whey dot party and you have used my custom appview that is very cool but have you considered that XRPC Not Supported",
97
+
}),
98
+
{
99
+
status: 404,
100
+
headers: withCors({ "Content-Type": "application/json" }),
101
+
}
102
+
);
103
+
//return await sendItToApiBskyApp(req);
104
+
}
105
+
106
+
const authDID = "did:plc:mn45tewwnse5btfftvd3powc"; //getAuthenticatedDid(req);
107
+
108
+
switch (xrpcMethod) {
109
+
case "app.bsky.feed.getFeedGenerators": {
110
+
const jsonTyped =
111
+
jsonUntyped as ViewServerTypes.AppBskyFeedGetFeedGenerators.QueryParams;
112
+
113
+
const feeds: ATPAPI.AppBskyFeedDefs.GeneratorView[] = (
114
+
await Promise.all(
115
+
jsonTyped.feeds.map(async (feed) => {
116
+
try {
117
+
const did = new ATPAPI.AtUri(feed).hostname;
118
+
const rkey = new ATPAPI.AtUri(feed).rkey;
119
+
const identity = await resolveIdentity(did);
120
+
const feedgetRecord = await getSlingshotRecord(
121
+
identity.did,
122
+
"app.bsky.feed.generator",
123
+
rkey
124
+
);
125
+
const profile = (
126
+
await getSlingshotRecord(
127
+
identity.did,
128
+
"app.bsky.actor.profile",
129
+
"self"
130
+
)
131
+
).value as ATPAPI.AppBskyActorProfile.Record;
132
+
const anyprofile = profile as any;
133
+
const value =
134
+
feedgetRecord.value as ATPAPI.AppBskyFeedGenerator.Record;
135
+
136
+
return {
137
+
$type: "app.bsky.feed.defs#generatorView",
138
+
uri: feed,
139
+
cid: feedgetRecord.cid,
140
+
did: identity.did,
141
+
creator: /*AppBskyActorDefs.ProfileView*/ {
142
+
$type: "app.bsky.actor.defs#profileView",
143
+
did: identity.did,
144
+
handle: identity.handle,
145
+
displayName: profile.displayName,
146
+
description: profile.description,
147
+
avatar: buildBlobUrl(
148
+
identity.pds,
149
+
identity.did,
150
+
anyprofile.avatar.ref["$link"]
151
+
),
152
+
//associated?: ProfileAssociated
153
+
//indexedAt?: string
154
+
//createdAt?: string
155
+
//viewer?: ViewerState
156
+
//labels?: ComAtprotoLabelDefs.Label[]
157
+
//verification?: VerificationState
158
+
//status?: StatusView
159
+
},
160
+
displayName: value.displayName,
161
+
description: value.description,
162
+
//descriptionFacets?: AppBskyRichtextFacet.Main[]
163
+
avatar: buildBlobUrl(
164
+
identity.pds,
165
+
identity.did,
166
+
(value as any).avatar.ref["$link"]
167
+
),
168
+
//likeCount?: number
169
+
//acceptsInteractions?: boolean
170
+
//labels?: ComAtprotoLabelDefs.Label[]
171
+
//viewer?: GeneratorViewerState
172
+
contentMode: value.contentMode,
173
+
indexedAt: new Date().toISOString(),
174
+
};
175
+
} catch (err) {
176
+
return undefined;
177
+
}
178
+
})
179
+
)
180
+
).filter(isGeneratorView);
181
+
182
+
const response: ViewServerTypes.AppBskyFeedGetFeedGenerators.OutputSchema =
183
+
{
184
+
feeds: feeds ? feeds : [],
185
+
};
186
+
187
+
return new Response(JSON.stringify(response), {
188
+
headers: withCors({ "Content-Type": "application/json" }),
189
+
});
190
+
}
191
+
case "app.bsky.feed.getFeed": {
192
+
const jsonTyped =
193
+
jsonUntyped as ViewServerTypes.AppBskyFeedGetFeed.QueryParams;
194
+
const cursor = jsonTyped.cursor;
195
+
const feed = jsonTyped.feed;
196
+
const limit = jsonTyped.limit;
197
+
const proxyauth = req.headers.get("authorization") || "";
198
+
199
+
const did = new ATPAPI.AtUri(feed).hostname;
200
+
const rkey = new ATPAPI.AtUri(feed).rkey;
201
+
const identity = await resolveIdentity(did);
202
+
const feedgetRecord = (
203
+
await getSlingshotRecord(identity.did, "app.bsky.feed.generator", rkey)
204
+
).value as ATPAPI.AppBskyFeedGenerator.Record;
205
+
206
+
const skeleton = (await cachedFetch(
207
+
`${didWebToHttps(
208
+
feedgetRecord.did
209
+
)}/xrpc/app.bsky.feed.getFeedSkeleton?feed=${jsonTyped.feed}${
210
+
cursor ? `&cursor=${cursor}` : ""
211
+
}${limit ? `&limit=${limit}` : ""}`,
212
+
proxyauth
213
+
)) as ATPAPI.AppBskyFeedGetFeedSkeleton.OutputSchema;
214
+
215
+
const nextcursor = skeleton.cursor;
216
+
const dbgrqstid = skeleton.reqId;
217
+
const uriarray = skeleton.feed;
218
+
219
+
// Step 1: Chunk into 25 max
220
+
const chunks = [];
221
+
for (let i = 0; i < uriarray.length; i += 25) {
222
+
chunks.push(uriarray.slice(i, i + 25));
223
+
}
224
+
225
+
// Step 2: Hydrate via getPosts
226
+
const hydratedPosts: ATPAPI.AppBskyFeedDefs.FeedViewPost[] = [];
227
+
228
+
for (const chunk of chunks) {
229
+
const searchParams = new URLSearchParams();
230
+
for (const uri of chunk.map((item) => item.post)) {
231
+
searchParams.append("uris", uri);
232
+
}
233
+
234
+
const postResp = await ky
235
+
.get(`https://api.bsky.app/xrpc/app.bsky.feed.getPosts`, {
236
+
// headers: {
237
+
// Authorization: proxyauth,
238
+
// },
239
+
searchParams,
240
+
})
241
+
.json<ATPAPI.AppBskyFeedGetPosts.OutputSchema>();
242
+
243
+
for (const post of postResp.posts) {
244
+
const matchingSkeleton = uriarray.find(
245
+
(item) => item.post === post.uri
246
+
);
247
+
if (matchingSkeleton) {
248
+
//post.author.handle = post.author.handle + ".percent40.api.bsky.app"; // or any logic to modify it
249
+
hydratedPosts.push({
250
+
post,
251
+
reason: matchingSkeleton.reason,
252
+
//reply: matchingSkeleton,
253
+
});
254
+
}
255
+
}
256
+
}
257
+
258
+
// Step 3: Compose final response
259
+
const response: ViewServerTypes.AppBskyFeedGetFeed.OutputSchema = {
260
+
feed: hydratedPosts,
261
+
cursor: nextcursor,
262
+
};
263
+
264
+
return new Response(JSON.stringify(response), {
265
+
headers: withCors({ "Content-Type": "application/json" }),
266
+
});
267
+
}
268
+
case "app.bsky.actor.getProfile": {
269
+
const jsonTyped =
270
+
jsonUntyped as ViewServerTypes.AppBskyActorGetProfile.QueryParams;
271
+
272
+
const userindexservice = "";
273
+
const isbskyfallback = true;
274
+
if (isbskyfallback) {
275
+
return sendItToApiBskyApp(req);
276
+
}
277
+
278
+
const response: ViewServerTypes.AppBskyActorGetProfile.OutputSchema = {};
279
+
280
+
return new Response(JSON.stringify(response), {
281
+
headers: withCors({ "Content-Type": "application/json" }),
282
+
});
283
+
}
284
+
285
+
case "app.bsky.actor.getProfiles": {
286
+
const jsonTyped =
287
+
jsonUntyped as ViewServerTypes.AppBskyActorGetProfiles.QueryParams;
288
+
289
+
const userindexservice = "";
290
+
const isbskyfallback = true;
291
+
if (isbskyfallback) {
292
+
return sendItToApiBskyApp(req);
293
+
}
294
+
295
+
const response: ViewServerTypes.AppBskyActorGetProfiles.OutputSchema = {};
296
+
297
+
return new Response(JSON.stringify(response), {
298
+
headers: withCors({ "Content-Type": "application/json" }),
299
+
});
300
+
}
301
+
case "app.bsky.feed.getAuthorFeed": {
302
+
const jsonTyped =
303
+
jsonUntyped as ViewServerTypes.AppBskyFeedGetAuthorFeed.QueryParams;
304
+
305
+
const userindexservice = "";
306
+
const isbskyfallback = true;
307
+
if (isbskyfallback) {
308
+
return sendItToApiBskyApp(req);
309
+
}
310
+
311
+
const response: ViewServerTypes.AppBskyFeedGetAuthorFeed.OutputSchema =
312
+
{};
313
+
314
+
return new Response(JSON.stringify(response), {
315
+
headers: withCors({ "Content-Type": "application/json" }),
316
+
});
317
+
}
318
+
case "app.bsky.feed.getPostThread": {
319
+
const jsonTyped =
320
+
jsonUntyped as ViewServerTypes.AppBskyFeedGetPostThread.QueryParams;
321
+
322
+
const userindexservice = "";
323
+
const isbskyfallback = true;
324
+
if (isbskyfallback) {
325
+
return sendItToApiBskyApp(req);
326
+
}
327
+
328
+
const response: ViewServerTypes.AppBskyFeedGetPostThread.OutputSchema =
329
+
{};
330
+
331
+
return new Response(JSON.stringify(response), {
332
+
headers: withCors({ "Content-Type": "application/json" }),
333
+
});
334
+
}
335
+
case "app.bsky.unspecced.getPostThreadV2": {
336
+
const jsonTyped =
337
+
jsonUntyped as ViewServerTypes.AppBskyUnspeccedGetPostThreadV2.QueryParams;
338
+
339
+
const userindexservice = "";
340
+
const isbskyfallback = true;
341
+
if (isbskyfallback) {
342
+
return sendItToApiBskyApp(req);
343
+
}
344
+
345
+
const response: ViewServerTypes.AppBskyUnspeccedGetPostThreadV2.OutputSchema =
346
+
{};
347
+
348
+
return new Response(JSON.stringify(response), {
349
+
headers: withCors({ "Content-Type": "application/json" }),
350
+
});
351
+
}
352
+
353
+
// case "app.bsky.actor.getProfile": {
354
+
// const jsonTyped =
355
+
// jsonUntyped as ViewServerTypes.AppBskyActorGetProfile.QueryParams;
356
+
357
+
// const response: ViewServerTypes.AppBskyActorGetProfile.OutputSchema= {};
358
+
359
+
// return new Response(JSON.stringify(response), {
360
+
// headers: withCors({ "Content-Type": "application/json" }),
361
+
// });
362
+
// }
363
+
// case "app.bsky.actor.getProfiles": {
364
+
// const jsonTyped = jsonUntyped as ViewServerTypes.AppBskyActorGetProfiles.QueryParams;
365
+
366
+
// const response: ViewServerTypes.AppBskyActorGetProfiles.OutputSchema = {};
367
+
368
+
// return new Response(JSON.stringify(response), {
369
+
// headers: withCors({ "Content-Type": "application/json" }),
370
+
// });
371
+
// }
372
+
// case "whatever": {
373
+
// const jsonTyped = jsonUntyped as ViewServerTypes.AppBskyFeedGetAuthorFeed.QueryParams;
374
+
375
+
// const response: ViewServerTypes.AppBskyFeedGetAuthorFeed.OutputSchema = {}
376
+
377
+
// return new Response(JSON.stringify(response), {
378
+
// headers: withCors({ "Content-Type": "application/json" }),
379
+
// });
380
+
// }
381
+
// case "app.bsky.notification.listNotifications": {
382
+
// const jsonTyped =
383
+
// jsonUntyped as ViewServerTypes.AppBskyNotificationListNotifications.QueryParams;
384
+
385
+
// const response: ViewServerTypes.AppBskyNotificationListNotifications.OutputSchema = {};
386
+
387
+
// return new Response(JSON.stringify(response), {
388
+
// headers: withCors({ "Content-Type": "application/json" }),
389
+
// });
390
+
// }
391
+
392
+
case "app.bsky.unspecced.getConfig": {
393
+
const jsonTyped =
394
+
jsonUntyped as ViewServerTypes.AppBskyUnspeccedGetConfig.QueryParams;
395
+
396
+
const response: ViewServerTypes.AppBskyUnspeccedGetConfig.OutputSchema = {
397
+
checkEmailConfirmed: true,
398
+
liveNow: [
399
+
{
400
+
$type: "app.bsky.unspecced.getConfig#liveNowConfig",
401
+
did: "did:plc:mn45tewwnse5btfftvd3powc",
402
+
domains: ["local3768forumtest.whey.party"],
403
+
},
404
+
],
405
+
};
406
+
407
+
return new Response(JSON.stringify(response), {
408
+
headers: withCors({ "Content-Type": "application/json" }),
409
+
});
410
+
}
411
+
case "app.bsky.graph.getLists": {
412
+
const jsonTyped =
413
+
jsonUntyped as ViewServerTypes.AppBskyGraphGetLists.QueryParams;
414
+
415
+
const response: ViewServerTypes.AppBskyGraphGetLists.OutputSchema = {
416
+
lists: [],
417
+
};
418
+
419
+
return new Response(JSON.stringify(response), {
420
+
headers: withCors({ "Content-Type": "application/json" }),
421
+
});
422
+
}
423
+
//https://shimeji.us-east.host.bsky.network/xrpc/app.bsky.unspecced.getTrendingTopics?limit=14
424
+
case "app.bsky.unspecced.getTrendingTopics": {
425
+
const jsonTyped =
426
+
jsonUntyped as ViewServerTypes.AppBskyUnspeccedGetTrendingTopics.QueryParams;
427
+
428
+
const faketopics: ATPAPI.AppBskyUnspeccedDefs.TrendingTopic[] = [
429
+
{
430
+
$type: "app.bsky.unspecced.defs#trendingTopic",
431
+
topic: "Git Repo",
432
+
displayName: "Git Repo",
433
+
description: "Git Repo",
434
+
link: "https://tangled.sh/@whey.party/skylite",
435
+
},
436
+
{
437
+
$type: "app.bsky.unspecced.defs#trendingTopic",
438
+
topic: "Red Dwarf Lite",
439
+
displayName: "Red Dwarf Lite",
440
+
description: "Red Dwarf Lite",
441
+
link: "https://reddwarf.whey.party/",
442
+
},
443
+
{
444
+
$type: "app.bsky.unspecced.defs#trendingTopic",
445
+
topic: "whey dot party",
446
+
displayName: "whey dot party",
447
+
description: "whey dot party",
448
+
link: "https://whey.party/",
449
+
},
450
+
];
451
+
452
+
const response: ViewServerTypes.AppBskyUnspeccedGetTrendingTopics.OutputSchema =
453
+
{
454
+
topics: faketopics,
455
+
suggested: faketopics,
456
+
};
457
+
458
+
return new Response(JSON.stringify(response), {
459
+
headers: withCors({ "Content-Type": "application/json" }),
460
+
});
461
+
}
462
+
default: {
463
+
return new Response(
464
+
JSON.stringify({
465
+
error: "XRPCNotSupported",
466
+
message:
467
+
"HEY hello there my name is whey dot party and you have used my custom appview that is very cool but have you considered that XRPC Not Supported",
468
+
}),
469
+
{
470
+
status: 404,
471
+
headers: withCors({ "Content-Type": "application/json" }),
472
+
}
473
+
);
474
+
}
475
+
}
476
+
477
+
return new Response("Not Found", { status: 404 });
478
+
}
479
+
480
+
async function sendItToApiBskyApp(req: Request): Promise<Response> {
481
+
const url = new URL(req.url);
482
+
const pathname = url.pathname;
483
+
const searchParams = searchParamsToJson(url.searchParams);
484
+
let reqBody: undefined | string;
485
+
let jsonbody: undefined | Record<string, unknown>;
486
+
if (req.body) {
487
+
const body = await req.json();
488
+
jsonbody = body;
489
+
// console.log(
490
+
// `called at euh reqreqreqreq: ${pathname}\n\n${JSON.stringify(body)}`
491
+
// );
492
+
reqBody = JSON.stringify(body, null, 2);
493
+
}
494
+
const bskyUrl = `https://api.bsky.app${pathname}${url.search}`;
495
+
const proxyHeaders = new Headers(req.headers);
496
+
497
+
// Remove Authorization and set browser-like User-Agent
498
+
proxyHeaders.delete("authorization");
499
+
proxyHeaders.delete("Access-Control-Allow-Origin"),
500
+
proxyHeaders.set(
501
+
"user-agent",
502
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"
503
+
);
504
+
proxyHeaders.set("Access-Control-Allow-Origin", "*");
505
+
506
+
const proxyRes = await fetch(bskyUrl, {
507
+
method: req.method,
508
+
headers: proxyHeaders,
509
+
body: ["GET", "HEAD"].includes(req.method.toUpperCase())
510
+
? undefined
511
+
: reqBody,
512
+
});
513
+
514
+
const resBody = await proxyRes.text();
515
+
516
+
// console.log(
517
+
// "← Response:",
518
+
// JSON.stringify(await JSON.parse(resBody), null, 2)
519
+
// );
520
+
521
+
return new Response(resBody, {
522
+
status: proxyRes.status,
523
+
headers: proxyRes.headers,
524
+
});
525
+
}