Merge pull request #1129 from PR0M3TH3AN/tag-pref-filter-stage-2603521350073003498

Incorporate tag preferences into blacklist filter stage
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-01-07 19:56:34 -05:00
commit cc130ae513
2 files changed
+43 -4

No files matched your search

+15 -4
View File
@@ -10,7 +10,7 @@ import nostrService from "../services/nostrService.js";
import moderationService from "../services/moderationService.js";
import logger from "../utils/logger.js";
import { dedupeToNewestByRoot } from "../utils/videoDeduper.js";
import { isPlainObject, toSet } from "./utils.js";
import { isPlainObject, toSet, hasDisinterestedTag } from "./utils.js";
const FEED_HIDE_BYPASS_NAMES = new Set(["home", "recent"]);
@@ -276,9 +276,9 @@ export function createBlacklistFilterStage({
const options = { blacklistedEventIds: blacklist, isAuthorBlocked };
// TODO(tag-preferences): incorporate context.runtime.tagPreferences once the
// filtering helpers are in place so this stage can drop disinterested tags
// without disturbing existing blacklist logic.
const tagPreferences = context?.runtime?.tagPreferences;
const disinterests = toSet(tagPreferences?.disinterests);
const hasTagPreferences = disinterests.size > 0;
const results = [];
@@ -289,6 +289,17 @@ export function createBlacklistFilterStage({
continue;
}
if (hasTagPreferences && hasDisinterestedTag(video, disinterests)) {
context?.addWhy?.({
stage: stageName,
type: "filter",
reason: "disinterested-tag",
videoId: typeof video.id === "string" ? video.id : null,
pubkey: typeof video.pubkey === "string" ? video.pubkey : null,
});
continue;
}
let include = false;
try {
include = includeFn(video, options) !== false;
+28
View File
@@ -27,3 +27,31 @@ export function toArray(value) {
}
return [value];
}
export function hasDisinterestedTag(video, disinterestsSet) {
if (!video || !disinterestsSet || !(disinterestsSet instanceof Set) || disinterestsSet.size === 0) {
return false;
}
// Check raw tags
if (Array.isArray(video.tags)) {
for (const tag of video.tags) {
if (Array.isArray(tag) && tag[0] === "t" && typeof tag[1] === "string") {
if (disinterestsSet.has(tag[1].toLowerCase())) {
return true;
}
}
}
}
// Check NIP-71 metadata hashtags if available
if (video.nip71 && Array.isArray(video.nip71.hashtags)) {
for (const tag of video.nip71.hashtags) {
if (typeof tag === "string" && disinterestsSet.has(tag.toLowerCase())) {
return true;
}
}
}
return false;
}