diff --git a/.env.example b/.env.example index c47fc14..38e3818 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,7 @@ TMDB_ACCESS_TOKEN= OMDB_API_KEY= + +# @svelte-atproto/oauth +ORIGIN= +COOKIE_SECRET= +CLIENT_ASSERTION_KEY= diff --git a/contrail.lock.json b/contrail.lock.json new file mode 100644 index 0000000..bdca287 --- /dev/null +++ b/contrail.lock.json @@ -0,0 +1,35 @@ +{ + "format": "contrail.provider-lock", + "version": 1, + "endpoint": "http://127.0.0.1:8787", + "namespace": "watch.atmo", + "contractDigest": "sha256:0f5f5b7930ba4502e4ef35f81ac33abd71896958e45841c96f55748a631e4d19", + "lexiconDigest": "sha256:ec400c9703839dd015a9d006e626f3b7d03f52815db8b4d7b183de23bb387385", + "methods": [ + "watch.atmo.comment.getRecord", + "watch.atmo.comment.listRecords", + "watch.atmo.getCursor", + "watch.atmo.getProfile", + "watch.atmo.like.getRecord", + "watch.atmo.like.listRecords", + "watch.atmo.list.getRecord", + "watch.atmo.list.listRecords", + "watch.atmo.listItem.getRecord", + "watch.atmo.listItem.listRecords", + "watch.atmo.profile.getRecord", + "watch.atmo.profile.listRecords", + "watch.atmo.review.getRecord", + "watch.atmo.review.listRecords" + ], + "collections": [ + "social.popfeed.actor.profile", + "social.popfeed.feed.comment", + "social.popfeed.feed.like", + "social.popfeed.feed.list", + "social.popfeed.feed.listItem", + "social.popfeed.feed.review" + ], + "serviceAuth": null, + "lexiconRoot": "src/lib/contrail/lexicons", + "allowInsecureHttp": true +} diff --git a/lex.config.js b/lex.config.js new file mode 100644 index 0000000..1f75dc4 --- /dev/null +++ b/lex.config.js @@ -0,0 +1,20 @@ +// Generated by `contrail connect`. Re-run the command to update; do not edit. +export default { + contrail: { + endpoint: "http://127.0.0.1:8787", + serviceDid: null, + scope: null, + collections: [ + "social.popfeed.actor.profile", + "social.popfeed.feed.comment", + "social.popfeed.feed.like", + "social.popfeed.feed.list", + "social.popfeed.feed.listItem", + "social.popfeed.feed.review", + ], + }, + generate: { + files: ["src/lib/contrail/lexicons/**/*.json"], + outdir: "src/lib/contrail/types/", + }, +}; diff --git a/package.json b/package.json index 36759d8..fc04f63 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,9 @@ "version": "0.0.1", "type": "module", "scripts": { + "atproto:setup": "atproto-oauth setup", + "atproto:keygen": "atproto-oauth keygen", + "atproto:secret": "atproto-oauth secret", "dev": "vite dev", "build": "vite build", "preview": "vite preview", @@ -45,12 +48,15 @@ "vitest-browser-svelte": "^2.1.1" }, "dependencies": { + "@atcute/atproto": "^4.0.0", "@atcute/client": "^5.1.1", "@atcute/lexicons": "^2.0.3", "@atmo-dev/contrail": "^0.17.0", "@lorenzopant/tmdb": "^1.25.3", + "@svelte-atproto/oauth": "^0.3.0", "add": "^2.0.9", "bits-ui": "^2.18.1", - "pnpm": "^11.21.0" + "pnpm": "^11.21.0", + "valibot": "^1.0.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 362bcbf..0451311 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@atcute/atproto': + specifier: ^4.0.0 + version: 4.0.4(@atcute/lexicons@2.0.3) '@atcute/client': specifier: ^5.1.1 version: 5.1.1(@atcute/lexicons@2.0.3)(typescript@6.0.3) @@ -20,6 +23,9 @@ importers: '@lorenzopant/tmdb': specifier: ^1.25.3 version: 1.25.3 + '@svelte-atproto/oauth': + specifier: ^0.3.0 + version: 0.3.0(@atcute/identity@2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@sveltejs/kit@2.70.2(@sveltejs/vite-plugin-svelte@7.3.0(svelte@5.56.9(@typescript-eslint/types@8.67.0))(vite@8.2.1(@types/node@24.13.3)(jiti@2.7.0)))(svelte@5.56.9(@typescript-eslint/types@8.67.0))(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(jiti@2.7.0)))(svelte@5.56.9(@typescript-eslint/types@8.67.0))(typescript@6.0.3) add: specifier: ^2.0.9 version: 2.0.9 @@ -29,6 +35,9 @@ importers: pnpm: specifier: ^11.21.0 version: 11.21.0 + valibot: + specifier: ^1.0.0 + version: 1.4.2(typescript@6.0.3) devDependencies: '@eslint/js': specifier: ^10.0.1 @@ -116,6 +125,11 @@ packages: peerDependencies: '@atcute/lexicons': ^2.0.0 + '@atcute/bluesky@4.0.18': + resolution: {integrity: sha512-cbwJWdu69arjoxdIFSQYcSVUGtkG1IDYdG/uK4Grk5epWv6mEe6XVkr9UNWB0PmYxvX1f0s1jLSFeSAagUxewA==} + peerDependencies: + '@atcute/lexicons': ^2.0.0 + '@atcute/car@6.0.2': resolution: {integrity: sha512-6AaLjO0zrFD8R/aK7jwrqHEmLzfVilu/5pv4LAcUjxIYfBrw+nThV2FVLPtA4Jt59tIhjp5tQDP+9sx1eqQp+A==} peerDependencies: @@ -188,6 +202,27 @@ packages: '@atcute/multibase@1.2.5': resolution: {integrity: sha512-cReTONgYpQo/VHD3ZmzPNoyBKJgSk1J4h//cvvdVVJBMar+SjlQ/sUXeTjQfuyfmDKv+TLKhmutLcvbMcQ9Rvw==} + '@atcute/oauth-browser-client@4.0.1': + resolution: {integrity: sha512-k5GGDFWUqTifbi7bMk4LhwG12XWNJop9atZ3ocBpzHJvXboTqp7E2zaD/arhJWxHXp5+0A1R3EKXdHsVbWjHyA==} + peerDependencies: + '@atcute/identity-resolver': ^2.0.0 + '@atcute/lexicons': ^2.0.0 + + '@atcute/oauth-crypto@1.0.1': + resolution: {integrity: sha512-ghC8ceFx0r6pi5X3dNoET1K6PNg8afeAOZLD4PKLhrpVYdRtRrgY4uqAe3ojtSIjoS6GXmVm063CoJ2xtg/MoQ==} + + '@atcute/oauth-keyset@0.1.3': + resolution: {integrity: sha512-VSNUb2TLUTyntgzfn58kwNL4kp4TD+M868tyyrFWlCaDVy0pDnVFfUXa1z1W+DBWLL9ICy2qTdPitRokAZKivw==} + + '@atcute/oauth-node-client@2.0.1': + resolution: {integrity: sha512-MgqN9Rnt5nuUH5zriETtbQrwcx/tWaELKaFVQtqggMtRI4k4IP5+ZbnG40tiJjbZfSclapA2kwOnT14kO0nAxg==} + peerDependencies: + '@atcute/identity-resolver': ^2.0.0 + '@atcute/lexicons': ^2.0.0 + + '@atcute/oauth-types@1.0.1': + resolution: {integrity: sha512-9uFP/nK0PgPDsaNbLArzrCHvTZO1k04cSEX5jZ75W2Jh7Jxbh/CSTenSrad3CZXuX6y6hDquEtl6H/IqLtTmHw==} + '@atcute/repo@1.0.2': resolution: {integrity: sha512-fsAuGbagOW52nSFtf/TWBx25A6xpZvzxBk0+S14Bp5sGNq7JoQ0zyu40P7b6+L8b/buB+1ACHPntYsKqCI4Awg==} peerDependencies: @@ -450,6 +485,13 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@svelte-atproto/oauth@0.3.0': + resolution: {integrity: sha512-Tijm4GGMg15NrA2EH715GoGE0yHxPBL4dk8h+Zmb3L7ea/TLKayjVso3OgNg5drvBjrgrthO0oI3BYSudTbT0A==} + hasBin: true + peerDependencies: + '@sveltejs/kit': ^2.0.0 + svelte: ^5.0.0 + '@sveltejs/acorn-typescript@1.0.13': resolution: {integrity: sha512-wgKggnhZVL9Bfx1OaKKTrYY9BFRk6C8UAkQNUcIv1+llzYrIqy+RZm5HPKzn0NpEBvTVhTqB4kQyllZywsRBRQ==} peerDependencies: @@ -1238,6 +1280,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@5.1.16: + resolution: {integrity: sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ==} + engines: {node: ^18 || >=20} + hasBin: true + nanoid@6.0.1: resolution: {integrity: sha512-3wVS3i51pE2pi1k5FFL/95BGfVS0kSsvDVuGXHOtxox/TywUmtgq+3qiTOTbs9J7KfHaXPiN171k/A6dBnaXFw==} engines: {node: ^22 || ^24 || >=26} @@ -1726,6 +1773,11 @@ snapshots: dependencies: '@atcute/lexicons': 2.0.3 + '@atcute/bluesky@4.0.18(@atcute/lexicons@2.0.3)': + dependencies: + '@atcute/atproto': 4.0.4(@atcute/lexicons@2.0.3) + '@atcute/lexicons': 2.0.3 + '@atcute/car@6.0.2(@atcute/cbor@2.3.6(@atcute/cid@2.4.2))(@atcute/cid@2.4.2)': dependencies: '@atcute/cbor': 2.3.6(@atcute/cid@2.4.2) @@ -1846,6 +1898,57 @@ snapshots: dependencies: '@atcute/uint8array': 1.1.5 + '@atcute/oauth-browser-client@4.0.1(@atcute/identity-resolver@2.0.1(@atcute/identity@2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3)': + dependencies: + '@atcute/client': 5.1.1(@atcute/lexicons@2.0.3)(typescript@6.0.3) + '@atcute/identity-resolver': 2.0.1(@atcute/identity@2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3) + '@atcute/lexicons': 2.0.3 + '@atcute/multibase': 1.2.5 + '@atcute/oauth-crypto': 1.0.1(typescript@6.0.3) + '@atcute/oauth-types': 1.0.1(typescript@6.0.3) + nanoid: 5.1.16 + transitivePeerDependencies: + - typescript + + '@atcute/oauth-crypto@1.0.1(typescript@6.0.3)': + dependencies: + '@atcute/multibase': 1.2.5 + '@atcute/uint8array': 1.1.5 + nanoid: 5.1.16 + valibot: 1.4.2(typescript@6.0.3) + transitivePeerDependencies: + - typescript + + '@atcute/oauth-keyset@0.1.3(typescript@6.0.3)': + dependencies: + '@atcute/oauth-crypto': 1.0.1(typescript@6.0.3) + transitivePeerDependencies: + - typescript + + '@atcute/oauth-node-client@2.0.1(@atcute/identity-resolver@2.0.1(@atcute/identity@2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3)': + dependencies: + '@atcute/client': 5.1.1(@atcute/lexicons@2.0.3)(typescript@6.0.3) + '@atcute/identity': 2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3) + '@atcute/identity-resolver': 2.0.1(@atcute/identity@2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3) + '@atcute/lexicons': 2.0.3 + '@atcute/oauth-crypto': 1.0.1(typescript@6.0.3) + '@atcute/oauth-keyset': 0.1.3(typescript@6.0.3) + '@atcute/oauth-types': 1.0.1(typescript@6.0.3) + '@atcute/util-fetch': 2.0.2(typescript@6.0.3) + nanoid: 5.1.16 + valibot: 1.4.2(typescript@6.0.3) + transitivePeerDependencies: + - typescript + + '@atcute/oauth-types@1.0.1(typescript@6.0.3)': + dependencies: + '@atcute/identity': 2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3) + '@atcute/lexicons': 2.0.3 + '@atcute/oauth-keyset': 0.1.3(typescript@6.0.3) + valibot: 1.4.2(typescript@6.0.3) + transitivePeerDependencies: + - typescript + '@atcute/repo@1.0.2(@atcute/cbor@2.3.6(@atcute/cid@2.4.2))(@atcute/cid@2.4.2)(@atcute/lexicons@2.0.3)': dependencies: '@atcute/car': 6.0.2(@atcute/cbor@2.3.6(@atcute/cid@2.4.2))(@atcute/cid@2.4.2) @@ -2072,6 +2175,22 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@svelte-atproto/oauth@0.3.0(@atcute/identity@2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@sveltejs/kit@2.70.2(@sveltejs/vite-plugin-svelte@7.3.0(svelte@5.56.9(@typescript-eslint/types@8.67.0))(vite@8.2.1(@types/node@24.13.3)(jiti@2.7.0)))(svelte@5.56.9(@typescript-eslint/types@8.67.0))(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(jiti@2.7.0)))(svelte@5.56.9(@typescript-eslint/types@8.67.0))(typescript@6.0.3)': + dependencies: + '@atcute/atproto': 4.0.4(@atcute/lexicons@2.0.3) + '@atcute/bluesky': 4.0.18(@atcute/lexicons@2.0.3) + '@atcute/client': 5.1.1(@atcute/lexicons@2.0.3)(typescript@6.0.3) + '@atcute/identity-resolver': 2.0.1(@atcute/identity@2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3) + '@atcute/lexicons': 2.0.3 + '@atcute/oauth-browser-client': 4.0.1(@atcute/identity-resolver@2.0.1(@atcute/identity@2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3) + '@atcute/oauth-node-client': 2.0.1(@atcute/identity-resolver@2.0.1(@atcute/identity@2.0.2(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3))(@atcute/lexicons@2.0.3)(typescript@6.0.3) + '@atcute/tid': 1.1.4 + '@sveltejs/kit': 2.70.2(@sveltejs/vite-plugin-svelte@7.3.0(svelte@5.56.9(@typescript-eslint/types@8.67.0))(vite@8.2.1(@types/node@24.13.3)(jiti@2.7.0)))(svelte@5.56.9(@typescript-eslint/types@8.67.0))(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(jiti@2.7.0)) + svelte: 5.56.9(@typescript-eslint/types@8.67.0) + transitivePeerDependencies: + - '@atcute/identity' + - typescript + '@sveltejs/acorn-typescript@1.0.13(acorn@8.18.0)': dependencies: acorn: 8.18.0 @@ -2797,6 +2916,8 @@ snapshots: nanoid@3.3.18: {} + nanoid@5.1.16: {} + nanoid@6.0.1: {} natural-compare@1.4.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index efc037a..5ed0b5a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,2 @@ -onlyBuiltDependencies: - - esbuild +allowBuilds: + esbuild: true diff --git a/src/app.d.ts b/src/app.d.ts index da08e6d..3a78063 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -1,9 +1,16 @@ // See https://svelte.dev/docs/kit/types#app.d.ts -// for information about these interfaces +import type { OAuthSession } from '@atcute/oauth-node-client'; +import type { Client } from '@atcute/client'; +import type { Did } from '@atcute/lexicons'; + declare global { namespace App { // interface Error {} - // interface Locals {} + interface Locals { + session: OAuthSession | null; + client: Client | null; + did: Did | null; + } // interface PageData {} // interface PageState {} // interface Platform {} diff --git a/src/app.html b/src/app.html index 66d9a6b..bd6d335 100644 --- a/src/app.html +++ b/src/app.html @@ -6,7 +6,7 @@ %sveltekit.head% - +
%sveltekit.body%
diff --git a/src/hooks.server.ts b/src/hooks.server.ts new file mode 100644 index 0000000..e9dba0a --- /dev/null +++ b/src/hooks.server.ts @@ -0,0 +1,3 @@ +import { atproto } from '$lib/atproto'; + +export const handle = atproto.handle; diff --git a/src/lib/atproto/index.ts b/src/lib/atproto/index.ts new file mode 100644 index 0000000..555eb72 --- /dev/null +++ b/src/lib/atproto/index.ts @@ -0,0 +1,15 @@ +// Side-effect: loads `com.atproto.*` lexicon types into the atcute Client. +import '@atcute/atproto'; +import { createAtprotoAuth } from '@svelte-atproto/oauth/server'; +import { cloudflareKV } from '@svelte-atproto/oauth/server/stores/cloudflare'; +import { env } from '$env/dynamic/private'; + +// To enable signup, add: signupPDS: 'https://your-pds.example/' +export const atproto = createAtprotoAuth({ + origin: env.ORIGIN, + cookieSecret: env.COOKIE_SECRET, + clientAssertionKey: env.CLIENT_ASSERTION_KEY, + scope: 'atproto repo:xyz.statusphere.status', + sessions: cloudflareKV('OAUTH_SESSIONS'), + states: cloudflareKV('OAUTH_STATES', { ttl: 600 }) +}); diff --git a/src/lib/atproto/oauth.remote.ts b/src/lib/atproto/oauth.remote.ts new file mode 100644 index 0000000..c4e7f7c --- /dev/null +++ b/src/lib/atproto/oauth.remote.ts @@ -0,0 +1,37 @@ +import { command, getRequestEvent } from '$app/server'; +import { error } from '@sveltejs/kit'; +import * as v from 'valibot'; +import { atproto } from '$lib/atproto'; +import { createTID } from '@svelte-atproto/oauth/helper'; + +export const oauthLogin = command( + v.object({ + handle: v.optional(v.pipe(v.string(), v.minLength(3))), + signup: v.optional(v.boolean()), + returnTo: v.optional(v.string()) + }), + (input) => atproto.api.startLogin(input) +); + +export const oauthLogout = command(() => atproto.api.logout()); + +const COLLECTION = 'xyz.statusphere.status'; + +export const setStatus = command(v.string(), async (status) => { + const { locals } = getRequestEvent(); + if (!locals.client || !locals.did) error(401, 'Not signed in'); + + await locals.client.post('com.atproto.repo.putRecord', { + input: { + repo: locals.did, + collection: COLLECTION, + rkey: createTID(), + record: { + $type: COLLECTION, + status, + createdAt: new Date().toISOString() + } + } + }); + return { ok: true }; +}); diff --git a/src/lib/contrail.config.ts b/src/lib/contrail.config.ts new file mode 100644 index 0000000..c5371d2 --- /dev/null +++ b/src/lib/contrail.config.ts @@ -0,0 +1,22 @@ +import type { ContrailConfig } from '@atmo-dev/contrail'; + +export const config: ContrailConfig = { + namespace: 'watch.atmo', + collections: { + review: { + collection: 'social.popfeed.feed.review' + }, + like: { + collection: 'social.popfeed.feed.like' + }, + list: { + collection: 'social.popfeed.feed.list' + }, + listItem: { + collection: 'social.popfeed.feed.listItem' + }, + comment: { + collection: 'social.popfeed.feed.comment' + } + } +}; diff --git a/src/lib/contrail/index.ts b/src/lib/contrail/index.ts new file mode 100644 index 0000000..a6beffa --- /dev/null +++ b/src/lib/contrail/index.ts @@ -0,0 +1,34 @@ +// Generated by `contrail connect`. Re-run the command to update; do not edit. +import { createPublicServiceClient } from "@atmo-dev/contrail/client"; +import type {} from "./types/index.js"; + +export const contrail = createPublicServiceClient({ + endpoint: "http://127.0.0.1:8787", + allowInsecureHttp: true, + contractDigest: "sha256:0f5f5b7930ba4502e4ef35f81ac33abd71896958e45841c96f55748a631e4d19", + serviceMethods: [ + "watch.atmo.comment.getRecord", + "watch.atmo.comment.listRecords", + "watch.atmo.getCursor", + "watch.atmo.getProfile", + "watch.atmo.like.getRecord", + "watch.atmo.like.listRecords", + "watch.atmo.list.getRecord", + "watch.atmo.list.listRecords", + "watch.atmo.listItem.getRecord", + "watch.atmo.listItem.listRecords", + "watch.atmo.profile.getRecord", + "watch.atmo.profile.listRecords", + "watch.atmo.review.getRecord", + "watch.atmo.review.listRecords", + ], + collections: [ + "social.popfeed.actor.profile", + "social.popfeed.feed.comment", + "social.popfeed.feed.like", + "social.popfeed.feed.list", + "social.popfeed.feed.listItem", + "social.popfeed.feed.review", + ], + notifyMethod: "watch.atmo.notifyOfUpdate", +}); diff --git a/src/lib/contrail/lexicons/watch/atmo/comment/getRecord.json b/src/lib/contrail/lexicons/watch/atmo/comment/getRecord.json new file mode 100644 index 0000000..24f2aeb --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/comment/getRecord.json @@ -0,0 +1,109 @@ +{ + "defs": { + "main": { + "description": "Get a social.popfeed.feed.comment record by AT URI", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.feed.comment#main", + "type": "ref" + } + }, + "required": [ + "uri", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + }, + "uri": { + "description": "AT URI of the record", + "format": "at-uri", + "type": "string" + } + }, + "required": [ + "uri" + ], + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + } + }, + "id": "watch.atmo.comment.getRecord", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/comment/listRecords.json b/src/lib/contrail/lexicons/watch/atmo/comment/listRecords.json new file mode 100644 index 0000000..b8dda53 --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/comment/listRecords.json @@ -0,0 +1,134 @@ +{ + "defs": { + "main": { + "description": "Query social.popfeed.feed.comment records", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cursor": { + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "records": { + "items": { + "ref": "#record", + "type": "ref" + }, + "type": "array" + } + }, + "required": [ + "records" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "actor": { + "description": "Filter by an indexed DID or cached handle", + "format": "at-identifier", + "type": "string" + }, + "cursor": { + "type": "string" + }, + "limit": { + "default": 50, + "maximum": 200, + "minimum": 1, + "type": "integer" + }, + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + } + }, + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + }, + "record": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.feed.comment#main", + "type": "ref" + } + }, + "required": [ + "uri", + "cid", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "id": "watch.atmo.comment.listRecords", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/getCursor.json b/src/lib/contrail/lexicons/watch/atmo/getCursor.json new file mode 100644 index 0000000..e34e1a8 --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/getCursor.json @@ -0,0 +1,48 @@ +{ + "defs": { + "main": { + "description": "Get the committed primary ordered-source position", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "position": { + "ref": "#sourcePosition", + "type": "ref" + }, + "updatedAt": { + "type": "integer" + }, + "updatedAtDate": { + "format": "datetime", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "query" + }, + "sourcePosition": { + "properties": { + "cursor": { + "type": "string" + }, + "epoch": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "required": [ + "source", + "epoch", + "cursor" + ], + "type": "object" + } + }, + "id": "watch.atmo.getCursor", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/getProfile.json b/src/lib/contrail/lexicons/watch/atmo/getProfile.json new file mode 100644 index 0000000..2ba86f0 --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/getProfile.json @@ -0,0 +1,72 @@ +{ + "defs": { + "main": { + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + } + }, + "required": [ + "profiles" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "actor": { + "format": "at-identifier", + "type": "string" + } + }, + "required": [ + "actor" + ], + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + } + }, + "id": "watch.atmo.getProfile", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/like/getRecord.json b/src/lib/contrail/lexicons/watch/atmo/like/getRecord.json new file mode 100644 index 0000000..3c7c6ab --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/like/getRecord.json @@ -0,0 +1,109 @@ +{ + "defs": { + "main": { + "description": "Get a social.popfeed.feed.like record by AT URI", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.feed.like#main", + "type": "ref" + } + }, + "required": [ + "uri", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + }, + "uri": { + "description": "AT URI of the record", + "format": "at-uri", + "type": "string" + } + }, + "required": [ + "uri" + ], + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + } + }, + "id": "watch.atmo.like.getRecord", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/like/listRecords.json b/src/lib/contrail/lexicons/watch/atmo/like/listRecords.json new file mode 100644 index 0000000..c3cb7ce --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/like/listRecords.json @@ -0,0 +1,134 @@ +{ + "defs": { + "main": { + "description": "Query social.popfeed.feed.like records", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cursor": { + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "records": { + "items": { + "ref": "#record", + "type": "ref" + }, + "type": "array" + } + }, + "required": [ + "records" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "actor": { + "description": "Filter by an indexed DID or cached handle", + "format": "at-identifier", + "type": "string" + }, + "cursor": { + "type": "string" + }, + "limit": { + "default": 50, + "maximum": 200, + "minimum": 1, + "type": "integer" + }, + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + } + }, + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + }, + "record": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.feed.like#main", + "type": "ref" + } + }, + "required": [ + "uri", + "cid", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "id": "watch.atmo.like.listRecords", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/list/getRecord.json b/src/lib/contrail/lexicons/watch/atmo/list/getRecord.json new file mode 100644 index 0000000..bbb60cd --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/list/getRecord.json @@ -0,0 +1,109 @@ +{ + "defs": { + "main": { + "description": "Get a social.popfeed.feed.list record by AT URI", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.feed.list#main", + "type": "ref" + } + }, + "required": [ + "uri", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + }, + "uri": { + "description": "AT URI of the record", + "format": "at-uri", + "type": "string" + } + }, + "required": [ + "uri" + ], + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + } + }, + "id": "watch.atmo.list.getRecord", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/list/listRecords.json b/src/lib/contrail/lexicons/watch/atmo/list/listRecords.json new file mode 100644 index 0000000..07d8a9b --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/list/listRecords.json @@ -0,0 +1,134 @@ +{ + "defs": { + "main": { + "description": "Query social.popfeed.feed.list records", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cursor": { + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "records": { + "items": { + "ref": "#record", + "type": "ref" + }, + "type": "array" + } + }, + "required": [ + "records" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "actor": { + "description": "Filter by an indexed DID or cached handle", + "format": "at-identifier", + "type": "string" + }, + "cursor": { + "type": "string" + }, + "limit": { + "default": 50, + "maximum": 200, + "minimum": 1, + "type": "integer" + }, + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + } + }, + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + }, + "record": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.feed.list#main", + "type": "ref" + } + }, + "required": [ + "uri", + "cid", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "id": "watch.atmo.list.listRecords", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/listItem/getRecord.json b/src/lib/contrail/lexicons/watch/atmo/listItem/getRecord.json new file mode 100644 index 0000000..7087dbb --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/listItem/getRecord.json @@ -0,0 +1,109 @@ +{ + "defs": { + "main": { + "description": "Get a social.popfeed.feed.listItem record by AT URI", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.feed.listItem#main", + "type": "ref" + } + }, + "required": [ + "uri", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + }, + "uri": { + "description": "AT URI of the record", + "format": "at-uri", + "type": "string" + } + }, + "required": [ + "uri" + ], + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + } + }, + "id": "watch.atmo.listItem.getRecord", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/listItem/listRecords.json b/src/lib/contrail/lexicons/watch/atmo/listItem/listRecords.json new file mode 100644 index 0000000..58acdaa --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/listItem/listRecords.json @@ -0,0 +1,134 @@ +{ + "defs": { + "main": { + "description": "Query social.popfeed.feed.listItem records", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cursor": { + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "records": { + "items": { + "ref": "#record", + "type": "ref" + }, + "type": "array" + } + }, + "required": [ + "records" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "actor": { + "description": "Filter by an indexed DID or cached handle", + "format": "at-identifier", + "type": "string" + }, + "cursor": { + "type": "string" + }, + "limit": { + "default": 50, + "maximum": 200, + "minimum": 1, + "type": "integer" + }, + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + } + }, + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + }, + "record": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.feed.listItem#main", + "type": "ref" + } + }, + "required": [ + "uri", + "cid", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "id": "watch.atmo.listItem.listRecords", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/notifyOfUpdate.json b/src/lib/contrail/lexicons/watch/atmo/notifyOfUpdate.json new file mode 100644 index 0000000..9acb986 --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/notifyOfUpdate.json @@ -0,0 +1,56 @@ +{ + "defs": { + "main": { + "description": "Fetch changed records from their authoritative PDS for immediate indexing", + "input": { + "encoding": "application/json", + "schema": { + "properties": { + "uri": { + "format": "at-uri", + "type": "string" + }, + "uris": { + "items": { + "format": "at-uri", + "type": "string" + }, + "maxLength": 25, + "type": "array" + } + }, + "type": "object" + } + }, + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "deleted": { + "minimum": 0, + "type": "integer" + }, + "errors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "indexed": { + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "indexed", + "deleted" + ], + "type": "object" + } + }, + "type": "procedure" + } + }, + "id": "watch.atmo.notifyOfUpdate", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/profile/getRecord.json b/src/lib/contrail/lexicons/watch/atmo/profile/getRecord.json new file mode 100644 index 0000000..b776845 --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/profile/getRecord.json @@ -0,0 +1,109 @@ +{ + "defs": { + "main": { + "description": "Get a social.popfeed.actor.profile record by AT URI", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.actor.profile#main", + "type": "ref" + } + }, + "required": [ + "uri", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + }, + "uri": { + "description": "AT URI of the record", + "format": "at-uri", + "type": "string" + } + }, + "required": [ + "uri" + ], + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + } + }, + "id": "watch.atmo.profile.getRecord", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/profile/listRecords.json b/src/lib/contrail/lexicons/watch/atmo/profile/listRecords.json new file mode 100644 index 0000000..536264f --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/profile/listRecords.json @@ -0,0 +1,134 @@ +{ + "defs": { + "main": { + "description": "Query social.popfeed.actor.profile records", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cursor": { + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "records": { + "items": { + "ref": "#record", + "type": "ref" + }, + "type": "array" + } + }, + "required": [ + "records" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "actor": { + "description": "Filter by an indexed DID or cached handle", + "format": "at-identifier", + "type": "string" + }, + "cursor": { + "type": "string" + }, + "limit": { + "default": 50, + "maximum": 200, + "minimum": 1, + "type": "integer" + }, + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + } + }, + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + }, + "record": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.actor.profile#main", + "type": "ref" + } + }, + "required": [ + "uri", + "cid", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "id": "watch.atmo.profile.listRecords", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/review/getRecord.json b/src/lib/contrail/lexicons/watch/atmo/review/getRecord.json new file mode 100644 index 0000000..e78cdaa --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/review/getRecord.json @@ -0,0 +1,109 @@ +{ + "defs": { + "main": { + "description": "Get a social.popfeed.feed.review record by AT URI", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.feed.review#main", + "type": "ref" + } + }, + "required": [ + "uri", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + }, + "uri": { + "description": "AT URI of the record", + "format": "at-uri", + "type": "string" + } + }, + "required": [ + "uri" + ], + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + } + }, + "id": "watch.atmo.review.getRecord", + "lexicon": 1 +} diff --git a/src/lib/contrail/lexicons/watch/atmo/review/listRecords.json b/src/lib/contrail/lexicons/watch/atmo/review/listRecords.json new file mode 100644 index 0000000..cab01d0 --- /dev/null +++ b/src/lib/contrail/lexicons/watch/atmo/review/listRecords.json @@ -0,0 +1,134 @@ +{ + "defs": { + "main": { + "description": "Query social.popfeed.feed.review records", + "output": { + "encoding": "application/json", + "schema": { + "properties": { + "cursor": { + "type": "string" + }, + "profiles": { + "items": { + "ref": "#profileEntry", + "type": "ref" + }, + "type": "array" + }, + "records": { + "items": { + "ref": "#record", + "type": "ref" + }, + "type": "array" + } + }, + "required": [ + "records" + ], + "type": "object" + } + }, + "parameters": { + "properties": { + "actor": { + "description": "Filter by an indexed DID or cached handle", + "format": "at-identifier", + "type": "string" + }, + "cursor": { + "type": "string" + }, + "limit": { + "default": 50, + "maximum": 200, + "minimum": 1, + "type": "integer" + }, + "profiles": { + "description": "Include indexed profile and identity information", + "type": "boolean" + } + }, + "type": "params" + }, + "type": "query" + }, + "profileEntry": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "handle": { + "type": "string" + }, + "rkey": { + "type": "string" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "type": "unknown" + } + }, + "required": [ + "did" + ], + "type": "object" + }, + "record": { + "properties": { + "cid": { + "format": "cid", + "type": "string" + }, + "collection": { + "format": "nsid", + "type": "string" + }, + "did": { + "format": "did", + "type": "string" + }, + "rkey": { + "type": "string" + }, + "time_us": { + "type": "integer" + }, + "uri": { + "format": "at-uri", + "type": "string" + }, + "value": { + "ref": "social.popfeed.feed.review#main", + "type": "ref" + } + }, + "required": [ + "uri", + "cid", + "value", + "did", + "collection", + "rkey", + "time_us" + ], + "type": "object" + } + }, + "id": "watch.atmo.review.listRecords", + "lexicon": 1 +} diff --git a/src/lib/contrail/types/index.ts b/src/lib/contrail/types/index.ts new file mode 100644 index 0000000..b5da30d --- /dev/null +++ b/src/lib/contrail/types/index.ts @@ -0,0 +1,22 @@ +export * as SocialPopfeedActorProfile from "./types/social/popfeed/actor/profile.js"; +export * as SocialPopfeedFeedComment from "./types/social/popfeed/feed/comment.js"; +export * as SocialPopfeedFeedLike from "./types/social/popfeed/feed/like.js"; +export * as SocialPopfeedFeedList from "./types/social/popfeed/feed/list.js"; +export * as SocialPopfeedFeedListItem from "./types/social/popfeed/feed/listItem.js"; +export * as SocialPopfeedFeedReview from "./types/social/popfeed/feed/review.js"; +export * as SocialPopfeedRichtextFacet from "./types/social/popfeed/richtext/facet.js"; +export * as WatchAtmoCommentGetRecord from "./types/watch/atmo/comment/getRecord.js"; +export * as WatchAtmoCommentListRecords from "./types/watch/atmo/comment/listRecords.js"; +export * as WatchAtmoGetCursor from "./types/watch/atmo/getCursor.js"; +export * as WatchAtmoGetProfile from "./types/watch/atmo/getProfile.js"; +export * as WatchAtmoLikeGetRecord from "./types/watch/atmo/like/getRecord.js"; +export * as WatchAtmoLikeListRecords from "./types/watch/atmo/like/listRecords.js"; +export * as WatchAtmoListGetRecord from "./types/watch/atmo/list/getRecord.js"; +export * as WatchAtmoListListRecords from "./types/watch/atmo/list/listRecords.js"; +export * as WatchAtmoListItemGetRecord from "./types/watch/atmo/listItem/getRecord.js"; +export * as WatchAtmoListItemListRecords from "./types/watch/atmo/listItem/listRecords.js"; +export * as WatchAtmoNotifyOfUpdate from "./types/watch/atmo/notifyOfUpdate.js"; +export * as WatchAtmoProfileGetRecord from "./types/watch/atmo/profile/getRecord.js"; +export * as WatchAtmoProfileListRecords from "./types/watch/atmo/profile/listRecords.js"; +export * as WatchAtmoReviewGetRecord from "./types/watch/atmo/review/getRecord.js"; +export * as WatchAtmoReviewListRecords from "./types/watch/atmo/review/listRecords.js"; diff --git a/src/lib/contrail/types/types/social/popfeed/actor/profile.ts b/src/lib/contrail/types/types/social/popfeed/actor/profile.ts new file mode 100644 index 0000000..db20a3c --- /dev/null +++ b/src/lib/contrail/types/types/social/popfeed/actor/profile.ts @@ -0,0 +1,92 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; + +const _externalLinkSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.actor.profile#externalLink")), + /** + * Name of the external service (e.g., 'Twitter', 'GitHub'). + * @maxLength 100 + */ + "service": /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 100)] + ), + /** + * URL to the user's profile on the external service. + */ + "url": /*#__PURE__*/ v.genericUriString(), + } +); +const _mainSchema = /*#__PURE__*/ v.record( + /*#__PURE__*/ v.literal("self"), + /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.literal("social.popfeed.actor.profile"), + /** + * Larger horizontal image to display behind profile view. Have not fully cut over yet so may not be shown + * @accept image/png, image/jpeg + * @maxSize 1000000 + */ + "banner": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.blob(), + [ + /*#__PURE__*/ v.blobSize(1000000), + /*#__PURE__*/ v.blobAccept(["image/png", "image/jpeg"]) + ] + )), + /** + * Optional URL to a banner image. DEPRECATED - soon to be ignored + */ + "bannerUrl": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), + "createdAt": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), + /** + * Free-form profile description text. + * @maxLength 2560 + * @maxGraphemes 256 + */ + "description": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [ + /*#__PURE__*/ v.stringLength(0, 2560), + /*#__PURE__*/ v.stringGraphemes(0, 256) + ] + )), + /** + * @maxLength 640 + * @maxGraphemes 64 + */ + "displayName": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [ + /*#__PURE__*/ v.stringLength(0, 640), + /*#__PURE__*/ v.stringGraphemes(0, 64) + ] + )), + /** + * List of external links to the user's profiles on other services. + */ + get "externalLinks"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(externalLinkSchema)) + }, + } + ) +); +type externalLink$schematype = typeof _externalLinkSchema; +type main$schematype = typeof _mainSchema; + +export interface externalLinkSchema extends externalLink$schematype {} + +export interface mainSchema extends main$schematype {} +export const externalLinkSchema = _externalLinkSchema as externalLinkSchema; +export const mainSchema = _mainSchema as mainSchema; + +export interface ExternalLink extends v.InferInput {} + +export interface Main extends v.InferInput {} +declare module '@atcute/lexicons/ambient' { + interface Records { + "social.popfeed.actor.profile": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/social/popfeed/feed/comment.ts b/src/lib/contrail/types/types/social/popfeed/feed/comment.ts new file mode 100644 index 0000000..be74e41 --- /dev/null +++ b/src/lib/contrail/types/types/social/popfeed/feed/comment.ts @@ -0,0 +1,59 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedRichtextFacet from "../richtext/facet.js"; + +const _mainSchema = /*#__PURE__*/ v.record( + /*#__PURE__*/ v.tidString(), + /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.literal("social.popfeed.feed.comment"), + /** + * Client-declared timestamp when this comment was created. + */ + "createdAt": /*#__PURE__*/ v.datetimeString(), + /** + * Annotations of text (mentions, URLs, hashtags, etc). + */ + get "facets"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(SocialPopfeedRichtextFacet.mainSchema)) + }, + /** + * The URI of the root entity of the comment thread, if applicable. + */ + "rootUri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), + /** + * The type of subject being commented on, e.g., 'review'. + */ + "subjectType": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literalEnum([ + "comment", + "list", + "post", + "review" + ])), + /** + * The URI of the review being commented on. + */ + "subjectUri": /*#__PURE__*/ v.genericUriString(), + /** + * The primary comment content. + * @maxLength 1000 + */ + "text": /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 1000)] + ), + } + ) +); +type main$schematype = typeof _mainSchema; + +export interface mainSchema extends main$schematype {} +export const mainSchema = _mainSchema as mainSchema; + +export interface Main extends v.InferInput {} +declare module '@atcute/lexicons/ambient' { + interface Records { + "social.popfeed.feed.comment": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/social/popfeed/feed/like.ts b/src/lib/contrail/types/types/social/popfeed/feed/like.ts new file mode 100644 index 0000000..d26f0bd --- /dev/null +++ b/src/lib/contrail/types/types/social/popfeed/feed/like.ts @@ -0,0 +1,40 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; + +const _mainSchema = /*#__PURE__*/ v.record( + /*#__PURE__*/ v.tidString(), + /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.literal("social.popfeed.feed.like"), + /** + * Client-declared timestamp when this like was created. + */ + "createdAt": /*#__PURE__*/ v.datetimeString(), + /** + * The type of subject being liked, e.g., 'review'. + */ + "subjectType": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literalEnum([ + "comment", + "list", + "post", + "review" + ])), + /** + * The type of subject being liked, e.g., 'review'. + */ + "subjectUri": /*#__PURE__*/ v.genericUriString(), + } + ) +); +type main$schematype = typeof _mainSchema; + +export interface mainSchema extends main$schematype {} +export const mainSchema = _mainSchema as mainSchema; + +export interface Main extends v.InferInput {} +declare module '@atcute/lexicons/ambient' { + interface Records { + "social.popfeed.feed.like": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/social/popfeed/feed/list.ts b/src/lib/contrail/types/types/social/popfeed/feed/list.ts new file mode 100644 index 0000000..b0b061f --- /dev/null +++ b/src/lib/contrail/types/types/social/popfeed/feed/list.ts @@ -0,0 +1,66 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; + +const _mainSchema = /*#__PURE__*/ v.record( + /*#__PURE__*/ v.tidString(), + /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.literal("social.popfeed.feed.list"), + /** + * The timestamp when the list was created. + */ + "createdAt": /*#__PURE__*/ v.datetimeString(), + /** + * Optional description of the list. + * @maxLength 500 + */ + "description": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 500)] + )), + /** + * An array of item uris in the order they appear in the list. Stored separately from the items themselves to allow for efficient reordering without needing to update each item record. + */ + "itemOrder": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(/*#__PURE__*/ v.genericUriString())), + /** + * The type of list, e.g., 'watchlist', 'favorites', 'to-read', etc. + * @maxLength 50 + */ + "listType": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 50)] + )), + /** + * The name of the list. + * @maxLength 100 + */ + "name": /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 100)] + ), + /** + * Indicates whether the list is ordered or unordered. + */ + "ordered": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + /** + * Optional array of tags for categorizing or describing the list. + */ + "tags": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 50)] + ))), + } + ) +); +type main$schematype = typeof _mainSchema; + +export interface mainSchema extends main$schematype {} +export const mainSchema = _mainSchema as mainSchema; + +export interface Main extends v.InferInput {} +declare module '@atcute/lexicons/ambient' { + interface Records { + "social.popfeed.feed.list": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/social/popfeed/feed/listItem.ts b/src/lib/contrail/types/types/social/popfeed/feed/listItem.ts new file mode 100644 index 0000000..dc5019e --- /dev/null +++ b/src/lib/contrail/types/types/social/popfeed/feed/listItem.ts @@ -0,0 +1,280 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; + +const _bookProgressSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.feed.listItem#bookProgress")), + /** + * Current chapter number (optional alternative to pages). + */ + "currentChapter": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + /** + * Current page number (if applicable). + */ + "currentPage": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + /** + * Optional explicit progress percentage (0–100). + */ + "percent": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + /** + * Overall progress state. + */ + "status": /*#__PURE__*/ v.literalEnum(["completed", "in_progress", "paused"]), + /** + * Total chapters (if known). + */ + "totalChapters": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + /** + * Total pages (if known). + */ + "totalPages": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + /** + * Last time progress was updated. + */ + "updatedAt": /*#__PURE__*/ v.datetimeString(), + } +); +const _identifiersSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.feed.listItem#identifiers")), + /** + * Amazon Standard ID + */ + "asin": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * Episode number for TV shows or series + */ + "episodeNumber": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + /** + * IGDB ID for games + */ + "igdbId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * IMDb ID + */ + "imdbId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * ISBN-10 for books + */ + "isbn10": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * ISBN-13 for books + */ + "isbn13": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * DEPRECATED - soon to be ignored + */ + "mbId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * MusicBrainz ID for specific releases (albums, EPs, tracks) + */ + "mbReleaseId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * Other external ID + */ + "other": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * MusicBrainz ID for parent release (e.g., album for a track) + */ + "parentMbReleaseId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * Season number for TV shows or series + */ + "seasonNumber": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + /** + * TMDb ID for movies/TV shows + */ + "tmdbId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * TMDb ID for TV series + */ + "tmdbTvSeriesId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + } +); +const _mainSchema = /*#__PURE__*/ v.record( + /*#__PURE__*/ v.tidString(), + /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.literal("social.popfeed.feed.listItem"), + /** + * Timestamp when the creative work was added to the list. + */ + "addedAt": /*#__PURE__*/ v.datetimeString(), + /** + * @accept image/* + * @maxSize 4000000 + */ + "backdrop": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.blob(), + [ + /*#__PURE__*/ v.blobSize(4000000), + /*#__PURE__*/ v.blobAccept(["image/*"]) + ] + )), + /** + * Backdrop image URL for the creative work. Soon to be deprecated in favor of the 'backdrop' blob field + */ + "backdropUrl": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), + /** + * Reading progress for books or book series (also supports audiobooks via time fields). + */ + get "bookProgress"() { + return /*#__PURE__*/ v.optional(bookProgressSchema) + }, + /** + * Timestamp when the user finished the creative work. Most relevant for books, TV shows, and video games. + */ + "completedAt": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), + /** + * The type of creative work this item represents. + */ + "creativeWorkType": /*#__PURE__*/ v.literalEnum([ + "album", + "album", + "book", + "book_series", + "ep", + "episode", + "movie", + "track", + "tv_episode", + "tv_season", + "tv_show", + "video_game" + ]), + /** + * Optional description or commentary for the list item. + * @maxLength 5000 + */ + "description": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 5000)] + )), + "genres": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 50)] + ))), + /** + * External identifiers for the creative work. + */ + get "identifiers"() { + return identifiersSchema + }, + /** + * The type of list, e.g., 'watchlist', 'favorites', 'to-read', etc. + * @maxLength 50 + */ + "listType": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 50)] + )), + /** + * URI of the list where the item is stored. + */ + "listUri": /*#__PURE__*/ v.genericUriString(), + /** + * Main actor, director, author, or artist of the creative work. + * @maxLength 1000 + */ + "mainCredit": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 1000)] + )), + /** + * The role of the main credit. + */ + "mainCreditRole": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literalEnum([ + "artist", + "author", + "creator", + "developer", + "director", + "lead_actor", + "network", + "performer", + "publisher", + "showrunner", + "studio" + ])), + /** + * DEPRECATED + * @deprecated + */ + "position": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + /** + * @accept image/* + * @maxSize 2000000 + */ + "poster": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.blob(), + [ + /*#__PURE__*/ v.blobSize(2000000), + /*#__PURE__*/ v.blobAccept(["image/*"]) + ] + )), + /** + * Poster or cover image URL for the creative work. Soon to be deprecated in favor of the 'poster' blob field + */ + "posterUrl": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), + /** + * Release date of the creative work. + */ + "releaseDate": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), + /** + * Timestamp when the user started the creative work. Most relevant for books, TV shows, and video games. + */ + "startedAt": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), + "status": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string<"#abandoned" | "#backlog" | "#finished" | "#in_progress" | (string & {})>()), + /** + * Title of the creative work. + * @maxLength 1000 + */ + "title": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 1000)] + )), + /** + * For TV shows, the episodes the user has watched. + */ + get "watchedEpisodes"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(watchedEpisodeSchema)) + }, + } + ) +); +const _watchedEpisodeSchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.feed.listItem#watchedEpisode")), + "episodeNumber": /*#__PURE__*/ v.integer(), + "seasonNumber": /*#__PURE__*/ v.integer(), + "tmdbId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), +}); +type bookProgress$schematype = typeof _bookProgressSchema; +type identifiers$schematype = typeof _identifiersSchema; +type main$schematype = typeof _mainSchema; +type watchedEpisode$schematype = typeof _watchedEpisodeSchema; + +export interface bookProgressSchema extends bookProgress$schematype {} + +export interface identifiersSchema extends identifiers$schematype {} + +export interface mainSchema extends main$schematype {} + +export interface watchedEpisodeSchema extends watchedEpisode$schematype {} +export const bookProgressSchema = _bookProgressSchema as bookProgressSchema; +export const identifiersSchema = _identifiersSchema as identifiersSchema; +export const mainSchema = _mainSchema as mainSchema; +export const watchedEpisodeSchema = _watchedEpisodeSchema as watchedEpisodeSchema; + +export interface BookProgress extends v.InferInput {} + +export interface Identifiers extends v.InferInput {} + +export interface Main extends v.InferInput {} + +export interface WatchedEpisode extends v.InferInput {} +declare module '@atcute/lexicons/ambient' { + interface Records { + "social.popfeed.feed.listItem": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/social/popfeed/feed/review.ts b/src/lib/contrail/types/types/social/popfeed/feed/review.ts new file mode 100644 index 0000000..ca14b5a --- /dev/null +++ b/src/lib/contrail/types/types/social/popfeed/feed/review.ts @@ -0,0 +1,213 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedRichtextFacet from "../richtext/facet.js"; + +const _crossPostsSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.feed.review#crossPosts")), + /** + * The URI of the original Bluesky post being cross-posted. + */ + "bluesky": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), + /** + * The URI of the original Leaflet post being cross-posted. + */ + "leaflet": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), + } +); +const _identifiersSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.feed.review#identifiers")), + "asin": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * Episode number for TV shows or series + */ + "episodeNumber": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + "igdbId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "imdbId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "isbn10": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "isbn13": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * DEPRECATED - soon to be ignored + */ + "mbId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * MusicBrainz ID for specific releases (albums, EPs, tracks) + */ + "mbReleaseId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "other": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * MusicBrainz ID for parent release (e.g., album for a track) + */ + "parentMbReleaseId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * Season number for TV shows or series + */ + "seasonNumber": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + "tmdbId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * TMDb ID for TV series + */ + "tmdbTvSeriesId": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + } +); +const _mainSchema = /*#__PURE__*/ v.record( + /*#__PURE__*/ v.tidString(), + /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.literal("social.popfeed.feed.review"), + /** + * Backdrop image for the review post. Have not fully cut over yet so may not be shown + * @accept image/* + * @maxSize 4000000 + */ + "backdrop": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.blob(), + [ + /*#__PURE__*/ v.blobSize(4000000), + /*#__PURE__*/ v.blobAccept(["image/*"]) + ] + )), + /** + * Backdrop image URL for the creative work. Soon to be deprecated in favor of the 'backdrop' blob field + */ + "backdropUrl": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), + /** + * Indicates if the review contains spoilers. + */ + "containsSpoilers": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + "createdAt": /*#__PURE__*/ v.datetimeString(), + "creativeWorkType": /*#__PURE__*/ v.literalEnum([ + "album", + "album", + "book", + "book_series", + "ep", + "episode", + "movie", + "track", + "tv_episode", + "tv_season", + "tv_show", + "video_game" + ]), + /** + * Information about cross-posting to other platforms. + */ + get "crossPosts"() { + return /*#__PURE__*/ v.optional(crossPostsSchema) + }, + /** + * Annotations of text (mentions, URLs, hashtags, etc) + */ + get "facets"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(SocialPopfeedRichtextFacet.mainSchema)) + }, + "genres": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 50)] + ))), + get "identifiers"() { + return identifiersSchema + }, + /** + * Indicates if the user has experienced this work before (re-watch, re-read, replay). + */ + "isRevisit": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + /** + * Main actor, director, author, or artist of the creative work. + * @maxLength 1000 + */ + "mainCredit": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 1000)] + )), + /** + * The role of the main credit. + */ + "mainCreditRole": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literalEnum([ + "artist", + "author", + "creator", + "developer", + "director", + "lead_actor", + "network", + "performer", + "publisher", + "showrunner", + "studio" + ])), + /** + * @accept image/* + * @maxSize 2000000 + */ + "poster": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.blob(), + [ + /*#__PURE__*/ v.blobSize(2000000), + /*#__PURE__*/ v.blobAccept(["image/*"]) + ] + )), + /** + * Poster or cover image URL for the creative work. Soon to be deprecated in favor of the 'poster' blob field + */ + "posterUrl": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), + /** + * @minimum 0 + * @maximum 10 + */ + "rating": /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.integer(), + [/*#__PURE__*/ v.integerRange(0, 10)] + ), + /** + * Release date of the creative work. + */ + "releaseDate": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), + "tags": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 50)] + ))), + /** + * @maxLength 100000 + */ + "text": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 100000)] + )), + /** + * Title of the creative work. + * @maxLength 1000 + */ + "title": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [/*#__PURE__*/ v.stringLength(0, 1000)] + )), + } + ) +); +type crossPosts$schematype = typeof _crossPostsSchema; +type identifiers$schematype = typeof _identifiersSchema; +type main$schematype = typeof _mainSchema; + +export interface crossPostsSchema extends crossPosts$schematype {} + +export interface identifiersSchema extends identifiers$schematype {} + +export interface mainSchema extends main$schematype {} +export const crossPostsSchema = _crossPostsSchema as crossPostsSchema; +export const identifiersSchema = _identifiersSchema as identifiersSchema; +export const mainSchema = _mainSchema as mainSchema; + +export interface CrossPosts extends v.InferInput {} + +export interface Identifiers extends v.InferInput {} + +export interface Main extends v.InferInput {} +declare module '@atcute/lexicons/ambient' { + interface Records { + "social.popfeed.feed.review": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/social/popfeed/richtext/facet.ts b/src/lib/contrail/types/types/social/popfeed/richtext/facet.ts new file mode 100644 index 0000000..07494b4 --- /dev/null +++ b/src/lib/contrail/types/types/social/popfeed/richtext/facet.ts @@ -0,0 +1,85 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; + +const _byteSliceSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.richtext.facet#byteSlice")), + /** + * @minimum 0 + */ + "byteEnd": /*#__PURE__*/ v.integer(), + /** + * @minimum 0 + */ + "byteStart": /*#__PURE__*/ v.integer(), + } +); +const _linkSchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.richtext.facet#link")), + "uri": /*#__PURE__*/ v.genericUriString(), +}); +const _mainSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.richtext.facet")), + get "features"() { + return /*#__PURE__*/ v.array(/*#__PURE__*/ v.variant([ + linkSchema, + mentionSchema, + tagSchema + ])) + }, + get "index"() { + return byteSliceSchema + }, + } +); +const _mentionSchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.richtext.facet#mention")), + "did": /*#__PURE__*/ v.didString(), +}); +const _tagSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("social.popfeed.richtext.facet#tag")), + /** + * @maxLength 640 + * @maxGraphemes 64 + */ + "tag": /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.string(), + [ + /*#__PURE__*/ v.stringLength(0, 640), + /*#__PURE__*/ v.stringGraphemes(0, 64) + ] + ), + } +); +type byteSlice$schematype = typeof _byteSliceSchema; +type link$schematype = typeof _linkSchema; +type main$schematype = typeof _mainSchema; +type mention$schematype = typeof _mentionSchema; +type tag$schematype = typeof _tagSchema; + +export interface byteSliceSchema extends byteSlice$schematype {} + +export interface linkSchema extends link$schematype {} + +export interface mainSchema extends main$schematype {} + +export interface mentionSchema extends mention$schematype {} + +export interface tagSchema extends tag$schematype {} +export const byteSliceSchema = _byteSliceSchema as byteSliceSchema; +export const linkSchema = _linkSchema as linkSchema; +export const mainSchema = _mainSchema as mainSchema; +export const mentionSchema = _mentionSchema as mentionSchema; +export const tagSchema = _tagSchema as tagSchema; + +export interface ByteSlice extends v.InferInput {} + +export interface Link extends v.InferInput {} + +export interface Main extends v.InferInput {} + +export interface Mention extends v.InferInput {} + +export interface Tag extends v.InferInput {} diff --git a/src/lib/contrail/types/types/watch/atmo/comment/getRecord.ts b/src/lib/contrail/types/types/watch/atmo/comment/getRecord.ts new file mode 100644 index 0000000..e623b3c --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/comment/getRecord.ts @@ -0,0 +1,70 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedFeedComment from "../../../social/popfeed/feed/comment.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.comment.getRecord", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + /** + * AT URI of the record + */ + "uri": /*#__PURE__*/ v.resourceUriString(), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedFeedComment.mainSchema + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.comment.getRecord#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.comment.getRecord": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/comment/listRecords.ts b/src/lib/contrail/types/types/watch/atmo/comment/listRecords.ts new file mode 100644 index 0000000..0fce879 --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/comment/listRecords.ts @@ -0,0 +1,98 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedFeedComment from "../../../social/popfeed/feed/comment.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.comment.listRecords", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Filter by an indexed DID or cached handle + */ + "actor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.actorIdentifierString()), + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * @minimum 1 + * @maximum 200 + * @default 50 + */ + "limit": /*#__PURE__*/ v.optional( + /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.integer(), + [/*#__PURE__*/ v.integerRange(1, 200)] + ), + 50 + ), + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + get "records"() { + return /*#__PURE__*/ v.array(recordSchema) + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.comment.listRecords#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +const _recordSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.comment.listRecords#record")), + "cid": /*#__PURE__*/ v.cidString(), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedFeedComment.mainSchema + }, + } +); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; +type record$schematype = typeof _recordSchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} + +export interface recordSchema extends record$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; +export const recordSchema = _recordSchema as recordSchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface Record extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.comment.listRecords": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/getCursor.ts b/src/lib/contrail/types/types/watch/atmo/getCursor.ts new file mode 100644 index 0000000..03a1b6d --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/getCursor.ts @@ -0,0 +1,47 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.getCursor", + { + "params": null, + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + get "position"() { + return /*#__PURE__*/ v.optional(sourcePositionSchema) + }, + "updatedAt": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), + "updatedAtDate": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), + } + ), + } + } +); +const _sourcePositionSchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.getCursor#sourcePosition")), + "cursor": /*#__PURE__*/ v.string(), + "epoch": /*#__PURE__*/ v.string(), + "source": /*#__PURE__*/ v.string(), +}); +type main$schematype = typeof _mainSchema; +type sourcePosition$schematype = typeof _sourcePositionSchema; + +export interface mainSchema extends main$schematype {} + +export interface sourcePositionSchema extends sourcePosition$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const sourcePositionSchema = _sourcePositionSchema as sourcePositionSchema; + +export interface SourcePosition extends v.InferInput {} + +export interface $params {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.getCursor": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/getProfile.ts b/src/lib/contrail/types/types/watch/atmo/getProfile.ts new file mode 100644 index 0000000..7d93fb1 --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/getProfile.ts @@ -0,0 +1,51 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.getProfile", + { + "params": /*#__PURE__*/ v.object({ + "actor": /*#__PURE__*/ v.actorIdentifierString(), + }), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + get "profiles"() { + return /*#__PURE__*/ v.array(profileEntrySchema) + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.getProfile#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.getProfile": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/like/getRecord.ts b/src/lib/contrail/types/types/watch/atmo/like/getRecord.ts new file mode 100644 index 0000000..a73796d --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/like/getRecord.ts @@ -0,0 +1,70 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedFeedLike from "../../../social/popfeed/feed/like.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.like.getRecord", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + /** + * AT URI of the record + */ + "uri": /*#__PURE__*/ v.resourceUriString(), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedFeedLike.mainSchema + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.like.getRecord#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.like.getRecord": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/like/listRecords.ts b/src/lib/contrail/types/types/watch/atmo/like/listRecords.ts new file mode 100644 index 0000000..b4fc5fc --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/like/listRecords.ts @@ -0,0 +1,98 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedFeedLike from "../../../social/popfeed/feed/like.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.like.listRecords", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Filter by an indexed DID or cached handle + */ + "actor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.actorIdentifierString()), + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * @minimum 1 + * @maximum 200 + * @default 50 + */ + "limit": /*#__PURE__*/ v.optional( + /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.integer(), + [/*#__PURE__*/ v.integerRange(1, 200)] + ), + 50 + ), + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + get "records"() { + return /*#__PURE__*/ v.array(recordSchema) + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.like.listRecords#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +const _recordSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.like.listRecords#record")), + "cid": /*#__PURE__*/ v.cidString(), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedFeedLike.mainSchema + }, + } +); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; +type record$schematype = typeof _recordSchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} + +export interface recordSchema extends record$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; +export const recordSchema = _recordSchema as recordSchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface Record extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.like.listRecords": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/list/getRecord.ts b/src/lib/contrail/types/types/watch/atmo/list/getRecord.ts new file mode 100644 index 0000000..efbe30b --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/list/getRecord.ts @@ -0,0 +1,70 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedFeedList from "../../../social/popfeed/feed/list.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.list.getRecord", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + /** + * AT URI of the record + */ + "uri": /*#__PURE__*/ v.resourceUriString(), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedFeedList.mainSchema + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.list.getRecord#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.list.getRecord": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/list/listRecords.ts b/src/lib/contrail/types/types/watch/atmo/list/listRecords.ts new file mode 100644 index 0000000..537a1eb --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/list/listRecords.ts @@ -0,0 +1,98 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedFeedList from "../../../social/popfeed/feed/list.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.list.listRecords", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Filter by an indexed DID or cached handle + */ + "actor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.actorIdentifierString()), + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * @minimum 1 + * @maximum 200 + * @default 50 + */ + "limit": /*#__PURE__*/ v.optional( + /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.integer(), + [/*#__PURE__*/ v.integerRange(1, 200)] + ), + 50 + ), + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + get "records"() { + return /*#__PURE__*/ v.array(recordSchema) + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.list.listRecords#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +const _recordSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.list.listRecords#record")), + "cid": /*#__PURE__*/ v.cidString(), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedFeedList.mainSchema + }, + } +); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; +type record$schematype = typeof _recordSchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} + +export interface recordSchema extends record$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; +export const recordSchema = _recordSchema as recordSchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface Record extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.list.listRecords": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/listItem/getRecord.ts b/src/lib/contrail/types/types/watch/atmo/listItem/getRecord.ts new file mode 100644 index 0000000..3ac28a9 --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/listItem/getRecord.ts @@ -0,0 +1,70 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedFeedListItem from "../../../social/popfeed/feed/listItem.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.listItem.getRecord", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + /** + * AT URI of the record + */ + "uri": /*#__PURE__*/ v.resourceUriString(), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedFeedListItem.mainSchema + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.listItem.getRecord#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.listItem.getRecord": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/listItem/listRecords.ts b/src/lib/contrail/types/types/watch/atmo/listItem/listRecords.ts new file mode 100644 index 0000000..ff8d1d1 --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/listItem/listRecords.ts @@ -0,0 +1,98 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedFeedListItem from "../../../social/popfeed/feed/listItem.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.listItem.listRecords", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Filter by an indexed DID or cached handle + */ + "actor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.actorIdentifierString()), + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * @minimum 1 + * @maximum 200 + * @default 50 + */ + "limit": /*#__PURE__*/ v.optional( + /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.integer(), + [/*#__PURE__*/ v.integerRange(1, 200)] + ), + 50 + ), + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + get "records"() { + return /*#__PURE__*/ v.array(recordSchema) + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.listItem.listRecords#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +const _recordSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.listItem.listRecords#record")), + "cid": /*#__PURE__*/ v.cidString(), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedFeedListItem.mainSchema + }, + } +); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; +type record$schematype = typeof _recordSchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} + +export interface recordSchema extends record$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; +export const recordSchema = _recordSchema as recordSchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface Record extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.listItem.listRecords": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/notifyOfUpdate.ts b/src/lib/contrail/types/types/watch/atmo/notifyOfUpdate.ts new file mode 100644 index 0000000..0cdbb50 --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/notifyOfUpdate.ts @@ -0,0 +1,56 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; + +const _mainSchema = /*#__PURE__*/ v.procedure( + "watch.atmo.notifyOfUpdate", + { + "params": null, + "input": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + /** + * @maxLength 25 + */ + "uris": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.array(/*#__PURE__*/ v.resourceUriString()), + [/*#__PURE__*/ v.arrayLength(0, 25)] + )), + } + ), + }, + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + /** + * @minimum 0 + */ + "deleted": /*#__PURE__*/ v.integer(), + "errors": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(/*#__PURE__*/ v.string())), + /** + * @minimum 0 + */ + "indexed": /*#__PURE__*/ v.integer(), + } + ), + } + } +); +type main$schematype = typeof _mainSchema; + +export interface mainSchema extends main$schematype {} +export const mainSchema = _mainSchema as mainSchema; + +export interface $params {} + +export interface $input extends v.InferXRPCBodyInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCProcedures { + "watch.atmo.notifyOfUpdate": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/profile/getRecord.ts b/src/lib/contrail/types/types/watch/atmo/profile/getRecord.ts new file mode 100644 index 0000000..c302be7 --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/profile/getRecord.ts @@ -0,0 +1,70 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedActorProfile from "../../../social/popfeed/actor/profile.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.profile.getRecord", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + /** + * AT URI of the record + */ + "uri": /*#__PURE__*/ v.resourceUriString(), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedActorProfile.mainSchema + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.profile.getRecord#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.profile.getRecord": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/profile/listRecords.ts b/src/lib/contrail/types/types/watch/atmo/profile/listRecords.ts new file mode 100644 index 0000000..0e84039 --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/profile/listRecords.ts @@ -0,0 +1,98 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedActorProfile from "../../../social/popfeed/actor/profile.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.profile.listRecords", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Filter by an indexed DID or cached handle + */ + "actor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.actorIdentifierString()), + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * @minimum 1 + * @maximum 200 + * @default 50 + */ + "limit": /*#__PURE__*/ v.optional( + /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.integer(), + [/*#__PURE__*/ v.integerRange(1, 200)] + ), + 50 + ), + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + get "records"() { + return /*#__PURE__*/ v.array(recordSchema) + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.profile.listRecords#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +const _recordSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.profile.listRecords#record")), + "cid": /*#__PURE__*/ v.cidString(), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedActorProfile.mainSchema + }, + } +); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; +type record$schematype = typeof _recordSchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} + +export interface recordSchema extends record$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; +export const recordSchema = _recordSchema as recordSchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface Record extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.profile.listRecords": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/review/getRecord.ts b/src/lib/contrail/types/types/watch/atmo/review/getRecord.ts new file mode 100644 index 0000000..0aa4d3b --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/review/getRecord.ts @@ -0,0 +1,70 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedFeedReview from "../../../social/popfeed/feed/review.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.review.getRecord", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + /** + * AT URI of the record + */ + "uri": /*#__PURE__*/ v.resourceUriString(), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedFeedReview.mainSchema + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.review.getRecord#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.review.getRecord": mainSchema; + } +} diff --git a/src/lib/contrail/types/types/watch/atmo/review/listRecords.ts b/src/lib/contrail/types/types/watch/atmo/review/listRecords.ts new file mode 100644 index 0000000..fe44e51 --- /dev/null +++ b/src/lib/contrail/types/types/watch/atmo/review/listRecords.ts @@ -0,0 +1,98 @@ +import type {} from '@atcute/lexicons'; +import * as v from '@atcute/lexicons/validations'; +import type {} from '@atcute/lexicons/ambient'; +import * as SocialPopfeedFeedReview from "../../../social/popfeed/feed/review.js"; + +const _mainSchema = /*#__PURE__*/ v.query( + "watch.atmo.review.listRecords", + { + "params": /*#__PURE__*/ v.object( + { + /** + * Filter by an indexed DID or cached handle + */ + "actor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.actorIdentifierString()), + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + /** + * @minimum 1 + * @maximum 200 + * @default 50 + */ + "limit": /*#__PURE__*/ v.optional( + /*#__PURE__*/ v.constrain( + /*#__PURE__*/ v.integer(), + [/*#__PURE__*/ v.integerRange(1, 200)] + ), + 50 + ), + /** + * Include indexed profile and identity information + */ + "profiles": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.boolean()), + } + ), + "output": { + "type": "lex", + "schema": /*#__PURE__*/ v.object( + { + "cursor": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + get "profiles"() { + return /*#__PURE__*/ v.optional(/*#__PURE__*/ v.array(profileEntrySchema)) + }, + get "records"() { + return /*#__PURE__*/ v.array(recordSchema) + }, + } + ), + } + } +); +const _profileEntrySchema = /*#__PURE__*/ v.object({ + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.review.listRecords#profileEntry")), + "cid": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidString()), + "collection": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.nsidString()), + "did": /*#__PURE__*/ v.didString(), + "handle": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "rkey": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), + "uri": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.resourceUriString()), + "value": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.unknown()), +}); +const _recordSchema = /*#__PURE__*/ v.object( + { + "$type": /*#__PURE__*/ v.optional(/*#__PURE__*/ v.literal("watch.atmo.review.listRecords#record")), + "cid": /*#__PURE__*/ v.cidString(), + "collection": /*#__PURE__*/ v.nsidString(), + "did": /*#__PURE__*/ v.didString(), + "rkey": /*#__PURE__*/ v.string(), + "time_us": /*#__PURE__*/ v.integer(), + "uri": /*#__PURE__*/ v.resourceUriString(), + get "value"() { + return SocialPopfeedFeedReview.mainSchema + }, + } +); +type main$schematype = typeof _mainSchema; +type profileEntry$schematype = typeof _profileEntrySchema; +type record$schematype = typeof _recordSchema; + +export interface mainSchema extends main$schematype {} + +export interface profileEntrySchema extends profileEntry$schematype {} + +export interface recordSchema extends record$schematype {} +export const mainSchema = _mainSchema as mainSchema; +export const profileEntrySchema = _profileEntrySchema as profileEntrySchema; +export const recordSchema = _recordSchema as recordSchema; + +export interface ProfileEntry extends v.InferInput {} + +export interface Record extends v.InferInput {} + +export interface $params extends v.InferInput {} + +export interface $output extends v.InferXRPCBodyInput {} +declare module '@atcute/lexicons/ambient' { + interface XRPCQueries { + "watch.atmo.review.listRecords": mainSchema; + } +} diff --git a/src/routes/(app)/_components/ItemPage.svelte b/src/routes/(app)/_components/ItemPage.svelte index 32f982b..4de08ed 100644 --- a/src/routes/(app)/_components/ItemPage.svelte +++ b/src/routes/(app)/_components/ItemPage.svelte @@ -120,7 +120,7 @@ {#if selectedSection === 'similar' && data.recommendations.length > 0} {:else if selectedSection === 'cast' && data.cast.length > 0} -
+
{#each data.cast as castMember (castMember.id)} -
+
{#each items as item (`${item.media_type}-${item.id}`)} {/each} diff --git a/src/routes/(app)/_lib/images.ts b/src/routes/(app)/_lib/images.ts index 5ec3df7..3eb984b 100644 --- a/src/routes/(app)/_lib/images.ts +++ b/src/routes/(app)/_lib/images.ts @@ -17,6 +17,7 @@ export function logoUrl(path: string | null | undefined, size: LogoSize = 'w92') } export function posterUrl(path: string | null | undefined, size: PosterSize = 'w500') { + if (path?.startsWith('https://')) return path; return path ? images.poster(path, size) : undefined; } diff --git a/src/routes/(app)/profile/[actor]/+layout.server.ts b/src/routes/(app)/profile/[actor]/+layout.server.ts new file mode 100644 index 0000000..6a58b4a --- /dev/null +++ b/src/routes/(app)/profile/[actor]/+layout.server.ts @@ -0,0 +1,62 @@ +import { contrail } from '$lib/contrail'; +import type { PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ params }) => { + const actor = params.actor; + + const reviews = await contrail.get('watch.atmo.review.listRecords', { + params: { + actor, + profiles: true + } + }); + + const profile = await contrail.get('watch.atmo.getProfile', { + params: { + actor + } + }); + + if (!reviews.ok) return; + + const data = reviews.data.records; + console.log(data); + + // export type Item = { + // id: number; + // ref: TmdbRef; + // media_type: MediaKind; + // title: string; + // poster_path: string | null; + // backdrop_path: string | null; + // overview: string; + // order?: number; + // }; + + const items = data + .filter( + (review) => + (review.value.creativeWorkType === 'tv_show' || + review.value.creativeWorkType === 'movie') && + review.value.identifiers.tmdbId && + review.value.posterUrl && + review.value.title + ) + .map((review) => { + const type = review.value.creativeWorkType == 'tv_show' ? 'tv' : 'movie'; + const id = (type == 'movie' ? `tmdb:m-` : `tmdb:t-`) + review.value.identifiers.tmdbId; + + return { + id: review.value.identifiers.tmdbId, + ref: id, + media_type: type, + title: review.value.title ?? 'Untitled', + poster_path: review.value.posterUrl + }; + }); + console.log(reviews.data.profiles); + + if (!profile.ok) return; + + return { items, profile: profile.data }; +}; diff --git a/src/routes/(app)/profile/[actor]/+page.svelte b/src/routes/(app)/profile/[actor]/+page.svelte new file mode 100644 index 0000000..2e00355 --- /dev/null +++ b/src/routes/(app)/profile/[actor]/+page.svelte @@ -0,0 +1,17 @@ + + + + {#if data?.items?.length > 0} + + {:else} + + {/if} + diff --git a/src/routes/demo/atproto/+page.server.ts b/src/routes/demo/atproto/+page.server.ts new file mode 100644 index 0000000..bfd9d48 --- /dev/null +++ b/src/routes/demo/atproto/+page.server.ts @@ -0,0 +1,66 @@ +import { redirect } from '@sveltejs/kit'; +import type { PageServerLoad } from './$types'; +import { loadHandle, recentRecords, loadHandles, listRecords, parseUri } from '@svelte-atproto/oauth/helper'; +import { memory } from '@svelte-atproto/oauth/server/stores/memory'; + +// In-memory cache for handle lookups β€” fine for dev. For prod, swap in +// cloudflareKV or upstashRedis (any `Store` works). +const profileCache = memory(); +const COLLECTION = 'xyz.statusphere.status'; + +export const load: PageServerLoad = async ({ locals, url }) => { + if (!locals.did) { + const returnTo = encodeURIComponent(url.pathname + url.search); + redirect(302, `/demo/atproto/login?returnTo=${returnTo}`); + } + + // Lightweight: just resolve the handle from the user's PDS. + // For richer Bluesky profile data (display name, avatar) swap to: + // import { loadBskyProfile } from '@svelte-atproto/oauth/bsky'; + // const profile = await loadBskyProfile(locals.did, { cache: profileCache }); + const handle = await loadHandle(locals.did, { cache: profileCache }); + + // Recent statuses globally, from the firehose via UFO. UFO is slightly + // behind the firehose, so we also pull the user's own records and merge + // them in front so just-published statuses show up immediately. + const [globalRecent, own] = await Promise.all([ + recentRecords(COLLECTION), + locals.client + ? listRecords({ did: locals.did, collection: COLLECTION, client: locals.client, limit: 10 }) + : Promise.resolve([]) + ]); + + const ownAsItems = own.map((r) => { + const parts = parseUri(r.uri); + const record = r.value as { $type: string; createdAt?: string; [k: string]: unknown }; + const parsed = typeof record.createdAt === 'string' ? new Date(record.createdAt).getTime() : NaN; + const time_us = (Number.isFinite(parsed) ? parsed : Date.now()) * 1000; + return { + did: parts?.repo ?? locals.did, + collection: parts?.collection ?? COLLECTION, + rkey: parts?.rkey ?? '', + record, + time_us + }; + }); + + // Own records first so they win the dedupe (UFO can be stale on a record + // the user just published). Then sort by time_us so the merged list is + // in true reverse-chronological order regardless of source. + const seen = new Set(); + const merged = []; + for (const item of [...ownAsItems, ...globalRecent]) { + const key = `${item.did}/${item.rkey}`; + if (seen.has(key)) continue; + seen.add(key); + merged.push(item); + } + const recent = merged.sort((a, b) => b.time_us - a.time_us); + + // Resolve the author handles in parallel (cached). + // For richer profile data, swap `loadHandles` for: + // import { loadBskyProfiles } from '@svelte-atproto/oauth/bsky'; + const authorDids = [...new Set(recent.map((r) => r.did))]; + const authors = await loadHandles(authorDids, { cache: profileCache }); + return { did: locals.did, handle, recent, authors }; +}; diff --git a/src/routes/demo/atproto/+page.svelte b/src/routes/demo/atproto/+page.svelte new file mode 100644 index 0000000..7b21fd4 --- /dev/null +++ b/src/routes/demo/atproto/+page.svelte @@ -0,0 +1,52 @@ + + +
+

What's your status?

+

Hi {data.handle ?? data.did}.

+ +
+ {#each emojis as emoji} + + {/each} +
+ + {#if data.recent?.length} +

Recent statuses (firehose)

+
    + {#each data.recent as item} +
  • + {item.record.status} + @{data.authors[item.did] ?? item.did} + {item.record.createdAt} +
  • + {/each} +
+ {/if} + + +
diff --git a/src/routes/demo/atproto/login/+page.server.ts b/src/routes/demo/atproto/login/+page.server.ts new file mode 100644 index 0000000..e578edb --- /dev/null +++ b/src/routes/demo/atproto/login/+page.server.ts @@ -0,0 +1,19 @@ +import { redirect } from '@sveltejs/kit'; +import type { PageServerLoad } from './$types'; + +const DEFAULT_RETURN_TO = '/demo/atproto'; + +function safeReturnTo(value: string | null | undefined): string { + if (!value) return DEFAULT_RETURN_TO; + try { + const decoded = decodeURIComponent(value); + if (decoded.startsWith('/') && !decoded.startsWith('//')) return decoded; + } catch {} + return DEFAULT_RETURN_TO; +} + +export const load: PageServerLoad = ({ locals, url }) => { + const returnTo = safeReturnTo(url.searchParams.get('returnTo')); + if (locals.did) redirect(302, returnTo); + return { returnTo }; +}; diff --git a/src/routes/demo/atproto/login/+page.svelte b/src/routes/demo/atproto/login/+page.svelte new file mode 100644 index 0000000..318663a --- /dev/null +++ b/src/routes/demo/atproto/login/+page.svelte @@ -0,0 +1,42 @@ + + +
+

Sign in with atproto

+ +
+ + + {#if error} +

{error}

+ {/if} + + +
+
diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..0add4f0 --- /dev/null +++ b/todo.md @@ -0,0 +1,4 @@ +- login with atproto, show account button at bottom of side menu (if not logged in show login modal, otherwise open profile) +- show profile: avatar, handle, reviews, lists +- create reviews +- show reviews in movie/show detail page diff --git a/vite.config.ts b/vite.config.ts index a2d09d6..78610e4 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,18 +5,24 @@ import adapter from '@sveltejs/adapter-auto'; import { sveltekit } from '@sveltejs/kit/vite'; export default defineConfig({ + server: { host: '127.0.0.1' }, plugins: [ tailwindcss(), sveltekit({ compilerOptions: { // Force runes mode for the project, except for libraries. Can be removed in svelte 6. - runes: ({ filename }) => filename.split(/[/\\]/).includes('node_modules') ? undefined : true + runes: ({ filename }) => + filename.split(/[/\\]/).includes('node_modules') ? undefined : true }, // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. // If your environment is not supported, or you settled on a specific environment, switch out the adapter. // See https://svelte.dev/docs/kit/adapters for more information about adapters. - adapter: adapter() + adapter: adapter(), + + experimental: { + remoteFunctions: true + } }) ], test: {