···1import type { Agent } from "@atproto/api";
2import { TID } from "@atproto/common";
3import chalk from "chalk";
004import * as Play from "lexicon/types/fm/teal/alpha/feed/play";
5import type { MusicbrainzTrack } from "types/track";
6···76 });
77 const uri = res.data.uri;
78 console.log(`tealfm Play record created at ${uri}`);
0079 } catch (error) {
80 console.error("Error publishing teal.fm record:", error);
000000000000000000000000000000000000000000000000000081 }
82}
83
···1import type { Agent } from "@atproto/api";
2import { TID } from "@atproto/common";
3import chalk from "chalk";
4+import type * as Status from "lexicon/types/fm/teal/alpha/actor/status";
5+import type { PlayView } from "lexicon/types/fm/teal/alpha/feed/defs";
6import * as Play from "lexicon/types/fm/teal/alpha/feed/play";
7import type { MusicbrainzTrack } from "types/track";
8···78 });
79 const uri = res.data.uri;
80 console.log(`tealfm Play record created at ${uri}`);
81+82+ await publishStatus(agent, track, duration);
83 } catch (error) {
84 console.error("Error publishing teal.fm record:", error);
85+ }
86+}
87+88+async function publishStatus(
89+ agent: Agent,
90+ track: MusicbrainzTrack,
91+ duration: number
92+) {
93+ const item: PlayView = {
94+ trackName: track.name,
95+ duration,
96+ playedTime: track.timestamp,
97+ artists: track.artist.map((artist) => ({
98+ artistMbid: artist.mbid,
99+ artistName: artist.name,
100+ })),
101+ releaseMbid: track.releaseMBID,
102+ releaseName: track.album,
103+ recordingMbId: track.trackMBID,
104+ submissionClientAgent: SUBMISSION_CLIENT_AGENT,
105+ };
106+ const nowSec = Math.floor(Date.now() / 1000);
107+ const expirySec = nowSec + 10 * 60; // 10 minutes from now
108+ const record: Status.Record = {
109+ $type: "fm.teal.alpha.actor.status",
110+ item,
111+ time: String(nowSec),
112+ expiry: String(expirySec),
113+ };
114+ const swapRecord = await getStatusSwapRecord(agent);
115+ const res = await agent.com.atproto.repo.putRecord({
116+ repo: agent.assertDid,
117+ collection: "fm.teal.alpha.actor.status",
118+ rkey: "self",
119+ record,
120+ swapRecord,
121+ });
122+ console.log(`tealfm Status record published at ${res.data.uri}`);
123+}
124+125+async function getStatusSwapRecord(agent: Agent): Promise<string | undefined> {
126+ try {
127+ const res = await agent.com.atproto.repo.getRecord({
128+ repo: agent.assertDid,
129+ collection: "fm.teal.alpha.actor.status",
130+ rkey: "self",
131+ });
132+ return res.data.cid;
133+ } catch (err) {
134+ const status = err?.response?.status ?? err?.status;
135+ if (status === 400) return undefined;
136+ throw err;
137 }
138}
139