import NDK, {NDKPrivateKeySigner} from "@nostr-dev-kit/ndk"; import * as nip19 from 'nostr-tools/nip19' import { createRestAPIClient, createStreamingAPIClient } from "masto"; import * as masto from "masto"; type MastodonClient = masto.mastodon.rest.Client; type MastodonStreamClient = masto.mastodon.streaming.Client; export class MastodonCompoundClient { public rest: MastodonClient; public stream: MastodonStreamClient; public constructor(c: MastodonClient, s: MastodonStreamClient) { this.rest = c; this.stream = s; } } export class Adapter { public nickname: string = ""; public protocol: string = ""; public identity: any | null; private _self: NDK | MastodonCompoundClient | null = null ; public init(): void {}; public getInbox(): void {}; public publish(): void {}; public getFollowers(): any[] { return [] }; public getFollowing(): any[] { return [] }; public updateMetadata(): void {}; public getMetadata(): any { return {} }; // according to the docs NDK must be a singleton... // this probalby will make having more than one nostr adapter at once problematic private static ndk: NDK | null = null; public static create(): Adapter { return new Adapter(); } public static toNostr(adapter: Adapter, settings: any): Adapter { adapter.identity = { privkey: settings.privkey }; adapter.nickname = settings.nickname; adapter.init = ()=> { if (!Adapter.ndk) { let privkey_raw = nip19.decode(settings.privkey); Adapter.ndk = new NDK({ signer: new NDKPrivateKeySigner(privkey_raw.data), explicitRelayUrls: [ settings.relays ] }); adapter._self = Adapter.ndk; Adapter.ndk.connect(); } else { Adapter.ndk.signer = new NDKPrivateKeySigner(settings.privatekey); for (let i of settings.relays) { Adapter.ndk.addExplicitRelay(i); } } }; adapter.getInbox = async () => { if (Adapter.ndk) { const sub = Adapter.ndk.subscribe({ kinds: [1] }); // Get all kind:1s sub.on("event", (event) => console.log(event.content)); // Show the content sub.on("eose", () => console.log("All relays have reached the end of the event stream")); sub.on("close", () => console.log("Subscription closed")); setTimeout(() => sub.stop(), 10000); // Stop the subscription after 10 seconds } }; return adapter; } public static toMasto(adapter: Adapter, settings: any): Adapter { adapter.identity = { server: settings.server, apiKey: settings.apiKey }; adapter.nickname = settings.nickname; adapter.init = () => { const rawServer: string = adapter.identity.server.split("://")[1]; adapter._self = new MastodonCompoundClient(createRestAPIClient({ url: adapter.identity.server, accessToken: adapter.identity.apiKey }), createStreamingAPIClient({ streamingApiUrl: `https://${rawServer}/v1/api/streaming`, accessToken: adapter.identity.apiKey })); } adapter.getInbox = async () => { const rawServer: string = adapter.identity.server.split("://")[1]; let conn = new WebSocket(`wss://${rawServer}/streaming/?i=${adapter.identity.apiKey}`) conn.addEventListener("open", async (e:any)=> { console.log(e); let filter = { type: "connect", body: { channel: "localTimeline", id: crypto.randomUUID() }}; let data = await JSON.stringify(filter); console.log(data); conn.send(data); conn.addEventListener("message", (e:any)=>{console.log(e)}); }); } return adapter; } } export default { Adapter }