101 lines
4.3 KiB
JavaScript
101 lines
4.3 KiB
JavaScript
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 { NotificationConverter } from "../../converters/notification.js";
|
|
import { AnnouncementConverter } from "../../converters/announcement.js";
|
|
import isQuote from "../../../../../misc/is-quote.js";
|
|
export class MastodonStreamUser extends MastodonStream {
|
|
static shouldShare = true;
|
|
static requireCredential = true;
|
|
static requiredScopes = [
|
|
'read:statuses',
|
|
'read:notifications'
|
|
];
|
|
notificationsOnly;
|
|
constructor(connection, name){
|
|
super(connection, name);
|
|
this.notificationsOnly = name === "user:notification";
|
|
this.onNote = this.onNote.bind(this);
|
|
this.onNoteEvent = this.onNoteEvent.bind(this);
|
|
this.onUserEvent = this.onUserEvent.bind(this);
|
|
this.onBroadcastEvent = this.onBroadcastEvent.bind(this);
|
|
}
|
|
get user() {
|
|
return this.connection.user;
|
|
}
|
|
async init() {
|
|
this.subscriber.on(`mainStream:${this.user.id}`, this.onUserEvent);
|
|
if (!this.notificationsOnly) {
|
|
this.subscriber.on("notesStream", this.onNote);
|
|
this.subscriber.on("noteUpdatesStream", this.onNoteEvent);
|
|
this.subscriber.on("broadcast", this.onBroadcastEvent);
|
|
}
|
|
}
|
|
async onNote(note) {
|
|
if (!await this.shouldProcessNote(note)) return;
|
|
const encoded = await NoteConverter.encodeEvent(note, this.user, 'home');
|
|
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, 'home');
|
|
this.connection.send(this.chName, "status.update", encoded);
|
|
break;
|
|
case "deleted":
|
|
this.connection.send(this.chName, "delete", note.id);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
async onUserEvent(data) {
|
|
switch(data.type){
|
|
case "notification":
|
|
const encoded = await NotificationConverter.encodeEvent(data.body.id, this.user, 'notifications');
|
|
if (encoded) this.connection.send(this.chName, "notification", encoded);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
async onBroadcastEvent(data) {
|
|
switch(data.type){
|
|
case "announcementAdded":
|
|
// This shouldn't be necessary but is for some reason
|
|
data.body.createdAt = new Date(data.body.createdAt);
|
|
this.connection.send(this.chName, "announcement", await AnnouncementConverter.encode(data.body, false));
|
|
break;
|
|
case "announcementDeleted":
|
|
this.connection.send(this.chName, "announcement.delete", data.body);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
async shouldProcessNote(note) {
|
|
if (note.visibility === "hidden") return false;
|
|
if (note.userId === this.user.id) return true;
|
|
if (note.visibility === "specified") return note.visibleUserIds?.includes(this.user.id);
|
|
if (note.channelId) return false;
|
|
if (this.user.id !== note.userId && !this.following.has(note.userId)) 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 (isUserRelated(note, this.hidden)) return false;
|
|
if (note.renoteId !== null && !isQuote(note) && this.renoteMuting.has(note.userId)) return false;
|
|
return true;
|
|
}
|
|
dispose() {
|
|
this.subscriber.off(`mainStream:${this.user.id}`, this.onUserEvent);
|
|
if (!this.notificationsOnly) {
|
|
this.subscriber.off("notesStream", this.onNote);
|
|
this.subscriber.off("noteUpdatesStream", this.onNoteEvent);
|
|
this.subscriber.off("broadcast", this.onBroadcastEvent);
|
|
}
|
|
}
|
|
}
|