diff --git a/js/app.js b/js/app.js index 4c1b40cf..ef0270f6 100644 --- a/js/app.js +++ b/js/app.js @@ -5513,7 +5513,12 @@ class Application { : new Set(); const preferenceSource = - typeof this.getHashtagPreferences === "function" + this.hashtagPreferencesSnapshot && + typeof this.hashtagPreferencesSnapshot === "object" + ? this.hashtagPreferencesSnapshot + : typeof this.createHashtagPreferencesSnapshot === "function" + ? this.createHashtagPreferencesSnapshot() + : typeof this.getHashtagPreferences === "function" ? this.getHashtagPreferences() : {}; const { interests = [], disinterests = [] } = preferenceSource || {}; diff --git a/tests/feed-engine/tag-preference-filter.test.mjs b/tests/feed-engine/tag-preference-filter.test.mjs new file mode 100644 index 00000000..f689b8ef --- /dev/null +++ b/tests/feed-engine/tag-preference-filter.test.mjs @@ -0,0 +1,86 @@ +import test from "node:test"; +import assert from "node:assert/strict"; + +import { createTagPreferenceFilterStage } from "../../js/feedEngine/stages.js"; + +test("tag preference stage filters by interests and excludes disinterests", async () => { + const stage = createTagPreferenceFilterStage(); + + const items = [ + { + video: { + id: "keep", + pubkey: "a".repeat(64), + tags: [["t", "Cats"]], + }, + metadata: {}, + }, + { + video: { + id: "exclude-disinterest", + pubkey: "b".repeat(64), + tags: [["t", "Dogs"]], + }, + metadata: {}, + }, + { + video: { + id: "exclude-no-interest", + pubkey: "c".repeat(64), + tags: [["t", "Birds"]], + }, + metadata: {}, + }, + { + video: { + id: "exclude-mixed", + pubkey: "d".repeat(64), + tags: [["t", "Cats"], ["t", "Dogs"]], + }, + metadata: {}, + }, + ]; + + const result = await stage(items, { + runtime: { + tagPreferences: { + interests: ["cats"], + disinterests: ["dogs"], + }, + }, + addWhy() {}, + }); + + assert.equal(result.length, 1); + assert.equal(result[0].video.id, "keep"); + assert.deepEqual(result[0].metadata.matchedInterests, ["cats"]); +}); + +test("tag preference stage accepts interests from nip71 hashtags", async () => { + const stage = createTagPreferenceFilterStage(); + + const items = [ + { + video: { + id: "nip71", + pubkey: "e".repeat(64), + nip71: { hashtags: ["Space"] }, + }, + metadata: {}, + }, + ]; + + const result = await stage(items, { + runtime: { + tagPreferences: { + interests: ["space"], + disinterests: [], + }, + }, + addWhy() {}, + }); + + assert.equal(result.length, 1); + assert.equal(result[0].video.id, "nip71"); + assert.deepEqual(result[0].metadata.matchedInterests, ["space"]); +});