import { MastodonStream } from "../channel.js"; import { isUserRelated } from "../../../../../misc/is-user-related.js"; import { isInstanceMuted } from "../../../../../misc/is-instance-muted.js"; import { NoteConverter } from "../../converters/note.js"; import { fetchMeta } from "../../../../../misc/fetch-meta.js"; import isQuote from "../../../../../misc/is-quote.js"; export class MastodonStreamPublic extends MastodonStream { static shouldShare = true; static requireCredential = false; mediaOnly; localOnly; remoteOnly; allowLocalOnly; constructor(connection, name){ super(connection, name); this.mediaOnly = name.endsWith(":media"); this.localOnly = name.startsWith("public:local"); this.remoteOnly = name.startsWith("public:remote"); this.allowLocalOnly = name.startsWith("public:allow_local_only"); this.onNote = this.onNote.bind(this); this.onNoteEvent = this.onNoteEvent.bind(this); } async init() { const meta = await fetchMeta(); if (meta.disableGlobalTimeline) { if (this.user == null || !(this.user.isAdmin || this.user.isModerator)) return; } this.subscriber.on("notesStream", this.onNote); this.subscriber.on("noteUpdatesStream", this.onNoteEvent); } async onNote(note) { if (!await this.shouldProcessNote(note)) return; const encoded = await NoteConverter.encodeEvent(note, this.user, 'public'); this.connection.send(this.chName, "update", encoded); } async onNoteEvent(data) { const note = data.body; if (!await this.shouldProcessNote(note)) return; switch(data.type){ case "updated": const encoded = await NoteConverter.encodeEvent(note, this.user, 'public'); this.connection.send(this.chName, "status.update", encoded); break; case "deleted": this.connection.send(this.chName, "delete", note.id); break; default: break; } } async shouldProcessNote(note) { if (note.visibility !== "public") return false; if (note.channelId != null) return false; if (this.mediaOnly && note.fileIds.length < 1) return false; if (this.localOnly && note.userHost !== null) return false; if (this.remoteOnly && note.userHost === null) return false; if (note.localOnly && !this.allowLocalOnly && !this.localOnly) return false; if (isInstanceMuted(note, new Set(this.userProfile?.mutedInstances ?? []))) return false; if (isUserRelated(note, this.muting)) return false; if (isUserRelated(note, this.blocking)) return false; if (note.renoteId !== null && !isQuote(note) && this.renoteMuting.has(note.userId)) return false; return true; } dispose() { this.subscriber.off("notesStream", this.onNote); this.subscriber.off("noteUpdatesStream", this.onNoteEvent); } }