@atproto/api
Version:
Client library for atproto and Bluesky
352 lines • 14.2 kB
JavaScript
import { AppBskyEmbedExternal, AppBskyEmbedGallery, AppBskyEmbedImages, AppBskyEmbedRecord, AppBskyEmbedRecordWithMedia, AppBskyFeedPost, } from '../../client/index.js';
import { ModerationDecision } from '../decision.js';
import { matchMuteWords } from '../mutewords.js';
import { decideAccount } from './account.js';
import { decideProfile } from './profile.js';
export function decidePost(subject, opts) {
return ModerationDecision.merge(decideSubject(subject, opts), decideEmbed(subject.embed, opts)?.downgrade(), decideAccount(subject.author, opts), decideProfile(subject.author, opts));
}
function decideSubject(subject, opts) {
const acc = new ModerationDecision();
acc.setDid(subject.author.did);
acc.setIsMe(subject.author.did === opts.userDid);
if (subject.labels?.length) {
for (const label of subject.labels) {
acc.addLabel('content', label, opts);
}
}
acc.addHidden(checkHiddenPost(subject, opts.prefs.hiddenPosts));
if (!acc.isMe) {
acc.addMutedWord(matchAllMuteWords(subject, opts.prefs.mutedWords));
}
return acc;
}
function decideEmbed(embed, opts) {
if (embed) {
if ((AppBskyEmbedRecord.isView(embed) ||
AppBskyEmbedRecordWithMedia.isView(embed)) &&
AppBskyEmbedRecord.isViewRecord(embed.record)) {
// quote post
return decideQuotedPost(embed.record, opts);
}
else if (AppBskyEmbedRecordWithMedia.isView(embed) &&
AppBskyEmbedRecord.isViewRecord(embed.record.record)) {
// quoted post with media
return decideQuotedPost(embed.record.record, opts);
}
else if ((AppBskyEmbedRecord.isView(embed) ||
AppBskyEmbedRecordWithMedia.isView(embed)) &&
AppBskyEmbedRecord.isViewBlocked(embed.record)) {
// blocked quote post
return decideBlockedQuotedPost(embed.record, opts);
}
else if (AppBskyEmbedRecordWithMedia.isView(embed) &&
AppBskyEmbedRecord.isViewBlocked(embed.record.record)) {
// blocked quoted post with media
return decideBlockedQuotedPost(embed.record.record, opts);
}
}
return undefined;
}
function decideQuotedPost(subject, opts) {
const acc = new ModerationDecision();
acc.setDid(subject.author.did);
acc.setIsMe(subject.author.did === opts.userDid);
if (subject.labels?.length) {
for (const label of subject.labels) {
acc.addLabel('content', label, opts);
}
}
return ModerationDecision.merge(acc, decideAccount(subject.author, opts), decideProfile(subject.author, opts));
}
function decideBlockedQuotedPost(subject, opts) {
const acc = new ModerationDecision();
acc.setDid(subject.author.did);
acc.setIsMe(subject.author.did === opts.userDid);
if (subject.author.viewer?.muted) {
if (subject.author.viewer?.mutedByList) {
acc.addMutedByList(subject.author.viewer?.mutedByList);
}
else {
acc.addMuted(subject.author.viewer?.muted);
}
}
if (subject.author.viewer?.blocking) {
if (subject.author.viewer?.blockingByList) {
acc.addBlockingByList(subject.author.viewer?.blockingByList);
}
else {
acc.addBlocking(subject.author.viewer?.blocking);
}
}
acc.addBlockedBy(subject.author.viewer?.blockedBy);
return acc;
}
function checkHiddenPost(subject, hiddenPosts) {
if (!hiddenPosts?.length) {
return false;
}
if (hiddenPosts.includes(subject.uri)) {
return true;
}
if (subject.embed) {
if (AppBskyEmbedRecord.isView(subject.embed) &&
AppBskyEmbedRecord.isViewRecord(subject.embed.record) &&
hiddenPosts.includes(subject.embed.record.uri)) {
return true;
}
if (AppBskyEmbedRecordWithMedia.isView(subject.embed) &&
AppBskyEmbedRecord.isViewRecord(subject.embed.record.record) &&
hiddenPosts.includes(subject.embed.record.record.uri)) {
return true;
}
}
return false;
}
function matchAllMuteWords(subject, mutedWords) {
if (!mutedWords?.length) {
return;
}
const postAuthor = subject.author;
if (AppBskyFeedPost.isRecord(subject.record)) {
const post = subject.record;
const matches = matchMuteWords({
mutedWords,
text: post.text,
facets: post.facets,
outlineTags: post.tags,
languages: post.langs,
actor: postAuthor,
});
// post text
if (matches) {
return matches;
}
if (post.embed && AppBskyEmbedImages.isMain(post.embed)) {
// post images
for (const image of post.embed.images) {
const matches = matchMuteWords({
mutedWords,
text: image.alt,
languages: post.langs,
actor: postAuthor,
});
if (matches) {
return matches;
}
}
}
if (post.embed && AppBskyEmbedGallery.isMain(post.embed)) {
// post gallery items
for (const item of post.embed.items) {
if (AppBskyEmbedGallery.isImage(item)) {
const matches = matchMuteWords({
mutedWords,
text: item.alt,
languages: post.langs,
actor: postAuthor,
});
if (matches) {
return matches;
}
}
}
}
}
const { embed } = subject;
if (embed) {
// quote post
if ((AppBskyEmbedRecord.isView(embed) ||
AppBskyEmbedRecordWithMedia.isView(embed)) &&
AppBskyEmbedRecord.isViewRecord(embed.record)) {
if (AppBskyFeedPost.isRecord(embed.record.value)) {
const embeddedPost = embed.record.value;
const embedAuthor = embed.record.author;
const matches = matchMuteWords({
mutedWords,
text: embeddedPost.text,
facets: embeddedPost.facets,
outlineTags: embeddedPost.tags,
languages: embeddedPost.langs,
actor: embedAuthor,
});
// quoted post text
if (matches) {
return matches;
}
// quoted post's images
if (AppBskyEmbedImages.isMain(embeddedPost.embed)) {
for (const image of embeddedPost.embed.images) {
const matches = matchMuteWords({
mutedWords,
text: image.alt,
languages: embeddedPost.langs,
actor: embedAuthor,
});
if (matches) {
return matches;
}
}
}
// quoted post's gallery
if (AppBskyEmbedGallery.isMain(embeddedPost.embed)) {
for (const item of embeddedPost.embed.items) {
if (AppBskyEmbedGallery.isImage(item)) {
const matches = matchMuteWords({
mutedWords,
text: item.alt,
languages: embeddedPost.langs,
actor: embedAuthor,
});
if (matches) {
return matches;
}
}
}
}
// quoted post's link card
if (AppBskyEmbedExternal.isMain(embeddedPost.embed)) {
const { external } = embeddedPost.embed;
const matches = matchMuteWords({
mutedWords,
text: external.title + ' ' + external.description,
languages: [],
actor: embedAuthor,
});
if (matches) {
return matches;
}
}
if (AppBskyEmbedRecordWithMedia.isMain(embeddedPost.embed)) {
// quoted post's link card when it did a quote + media
if (AppBskyEmbedExternal.isMain(embeddedPost.embed.media)) {
const { external } = embeddedPost.embed.media;
const matches = matchMuteWords({
mutedWords,
text: external.title + ' ' + external.description,
languages: [],
actor: embedAuthor,
});
if (matches) {
return matches;
}
}
// quoted post's images when it did a quote + media
if (AppBskyEmbedImages.isMain(embeddedPost.embed.media)) {
for (const image of embeddedPost.embed.media.images) {
const matches = matchMuteWords({
mutedWords,
text: image.alt,
languages: AppBskyFeedPost.isRecord(embeddedPost.record)
? embeddedPost.langs
: [],
actor: embedAuthor,
});
if (matches) {
return matches;
}
}
}
// quoted post's gallery when it did a quote + media
if (AppBskyEmbedGallery.isMain(embeddedPost.embed.media)) {
for (const item of embeddedPost.embed.media.items) {
if (AppBskyEmbedGallery.isImage(item)) {
const matches = matchMuteWords({
mutedWords,
text: item.alt,
languages: AppBskyFeedPost.isRecord(embeddedPost.record)
? embeddedPost.langs
: [],
actor: embedAuthor,
});
if (matches) {
return matches;
}
}
}
}
}
}
}
// link card
else if (AppBskyEmbedExternal.isView(embed)) {
const { external } = embed;
const matches = matchMuteWords({
mutedWords,
text: external.title + ' ' + external.description,
languages: [],
actor: postAuthor,
});
if (matches) {
return matches;
}
}
// quote post with media
else if (AppBskyEmbedRecordWithMedia.isView(embed) &&
AppBskyEmbedRecord.isViewRecord(embed.record.record)) {
const embedAuthor = embed.record.record.author;
// quoted post text
if (AppBskyFeedPost.isRecord(embed.record.record.value)) {
const post = embed.record.record.value;
const matches = matchMuteWords({
mutedWords,
text: post.text,
facets: post.facets,
outlineTags: post.tags,
languages: post.langs,
actor: embedAuthor,
});
if (matches) {
return matches;
}
}
// quoted post images
if (AppBskyEmbedImages.isView(embed.media)) {
for (const image of embed.media.images) {
const matches = matchMuteWords({
mutedWords,
text: image.alt,
languages: AppBskyFeedPost.isRecord(subject.record)
? subject.record.langs
: [],
actor: embedAuthor,
});
if (matches) {
return matches;
}
}
}
// quoted post gallery
if (AppBskyEmbedGallery.isView(embed.media)) {
for (const item of embed.media.items) {
if (AppBskyEmbedGallery.isViewImage(item)) {
const matches = matchMuteWords({
mutedWords,
text: item.alt,
languages: AppBskyFeedPost.isRecord(subject.record)
? subject.record.langs
: [],
actor: embedAuthor,
});
if (matches) {
return matches;
}
}
}
}
if (AppBskyEmbedExternal.isView(embed.media)) {
const { external } = embed.media;
const matches = matchMuteWords({
mutedWords,
text: external.title + ' ' + external.description,
languages: [],
actor: embedAuthor,
});
if (matches) {
return matches;
}
}
}
}
}
//# sourceMappingURL=post.js.map