mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-29 00:42:30 +00:00
Add hashtag preference schema and feature flag
This commit is contained in:
1 parent
3d1a615ed3
commit
372cb8ca6f
3 files changed
+78
No files matched your search
@@ -147,6 +147,7 @@ import { updateWatchHistoryListWithDefaultClient } from "./nostrWatchHistoryFaca
|
||||
| Watch history chunk (`NOTE_TYPES.WATCH_HISTORY_CHUNK`) | `WATCH_HISTORY_KIND` (default `30079`, clients also read legacy `30078`) | `['d', <snapshotId:index>]`, `['encrypted','nip04']`, `['snapshot', <id>]`, `['chunk', <index>, <total>]`, optional leading `['head','1']` on the first chunk, pointer tags for each item, plus schema append tags | NIP-04 encrypted JSON chunk (`{ version, snapshot, chunkIndex, totalChunks, items[] }`) |
|
||||
| Subscription list (`NOTE_TYPES.SUBSCRIPTION_LIST`) | `30002` | `['d', 'subscriptions']` | NIP-04 encrypted JSON `{ subPubkeys: string[] }` |
|
||||
| User block list (`NOTE_TYPES.USER_BLOCK_LIST`) | `30002` | `['d', 'user-blocks']` | NIP-04 encrypted JSON `{ blockedPubkeys: string[] }` |
|
||||
| Hashtag preferences (`NOTE_TYPES.HASHTAG_PREFERENCES`) | `30005` | `['d', 'bitvid:tag-preferences']` plus schema-appended `['encrypted','nip44_v2']` | NIP-44 encrypted JSON `{ version, interests: string[], disinterests: string[] }` |
|
||||
| Admin moderation list (`NOTE_TYPES.ADMIN_MODERATION_LIST`) | `30000` | `['d', 'bitvid:admin:editors']`, repeated `['p', <pubkey>]` entries | Empty content |
|
||||
| Admin blacklist (`NOTE_TYPES.ADMIN_BLACKLIST`) | `30000` | `['d', 'bitvid:admin:blacklist']`, repeated `['p', <pubkey>]` entries | Empty content |
|
||||
| Admin whitelist (`NOTE_TYPES.ADMIN_WHITELIST`) | `30000` | `['d', 'bitvid:admin:whitelist']`, repeated `['p', <pubkey>]` entries | Empty content |
|
||||
@@ -157,6 +158,17 @@ If you introduce a new Nostr feature, add its schema to
|
||||
`js/nostrEventSchemas.js` so that the catalogue stays complete and so existing
|
||||
builders inherit the same debugging knobs.
|
||||
|
||||
### Hashtag preference lists
|
||||
|
||||
Hashtag preference events (`NOTE_TYPES.HASHTAG_PREFERENCES`) live on a
|
||||
replaceable `30005` list with a stable identifier tag of
|
||||
`['d','bitvid:tag-preferences']`. The builder appends `['encrypted','nip44_v2']`
|
||||
so downstream clients can detect that the payload is encrypted. The `content`
|
||||
field must be a NIP-44 ciphertext representing the JSON shape
|
||||
`{ version, interests: string[], disinterests: string[] }`, allowing clients to
|
||||
share their preferred and muted hashtags without exposing the raw preferences on
|
||||
relays.
|
||||
|
||||
### NIP-71 rollout
|
||||
|
||||
bitvid now emits a paired NIP-71 event (kind `21` for long-form, `22` for short
|
||||
|
||||
@@ -147,6 +147,7 @@ const DEFAULT_FLAGS = Object.freeze({
|
||||
VIEW_FILTER_INCLUDE_LEGACY_VIDEO: false,
|
||||
FEATURE_WATCH_HISTORY_V2: true,
|
||||
FEATURE_PUBLISH_NIP71: false,
|
||||
FEATURE_HASHTAG_PREFERENCES: false,
|
||||
FEATURE_TRUST_SEEDS: true, // Rollback: disable to drop baseline trust seeds without code changes.
|
||||
FEATURE_TRUSTED_HIDE_CONTROLS: true,
|
||||
TRUSTED_MUTE_HIDE_THRESHOLD: DEFAULT_TRUSTED_MUTE_HIDE_THRESHOLD,
|
||||
@@ -167,6 +168,7 @@ const runtimeFlags = (() => {
|
||||
DEFAULT_FLAGS.VIEW_FILTER_INCLUDE_LEGACY_VIDEO,
|
||||
FEATURE_WATCH_HISTORY_V2: DEFAULT_FLAGS.FEATURE_WATCH_HISTORY_V2,
|
||||
FEATURE_PUBLISH_NIP71: DEFAULT_FLAGS.FEATURE_PUBLISH_NIP71,
|
||||
FEATURE_HASHTAG_PREFERENCES: DEFAULT_FLAGS.FEATURE_HASHTAG_PREFERENCES,
|
||||
FEATURE_TRUST_SEEDS: DEFAULT_FLAGS.FEATURE_TRUST_SEEDS,
|
||||
FEATURE_TRUSTED_HIDE_CONTROLS: DEFAULT_FLAGS.FEATURE_TRUSTED_HIDE_CONTROLS,
|
||||
TRUSTED_MUTE_HIDE_THRESHOLD: DEFAULT_FLAGS.TRUSTED_MUTE_HIDE_THRESHOLD,
|
||||
@@ -204,6 +206,11 @@ export let FEATURE_PUBLISH_NIP71 = coerceBoolean(
|
||||
DEFAULT_FLAGS.FEATURE_PUBLISH_NIP71
|
||||
);
|
||||
|
||||
export let FEATURE_HASHTAG_PREFERENCES = coerceBoolean(
|
||||
runtimeFlags.FEATURE_HASHTAG_PREFERENCES,
|
||||
DEFAULT_FLAGS.FEATURE_HASHTAG_PREFERENCES
|
||||
);
|
||||
|
||||
export let FEATURE_TRUST_SEEDS = coerceBoolean(
|
||||
runtimeFlags.FEATURE_TRUST_SEEDS,
|
||||
DEFAULT_FLAGS.FEATURE_TRUST_SEEDS
|
||||
@@ -292,6 +299,20 @@ Object.defineProperty(runtimeFlags, "FEATURE_PUBLISH_NIP71", {
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(runtimeFlags, "FEATURE_HASHTAG_PREFERENCES", {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get() {
|
||||
return FEATURE_HASHTAG_PREFERENCES;
|
||||
},
|
||||
set(next) {
|
||||
FEATURE_HASHTAG_PREFERENCES = coerceBoolean(
|
||||
next,
|
||||
DEFAULT_FLAGS.FEATURE_HASHTAG_PREFERENCES
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(runtimeFlags, "FEATURE_TRUST_SEEDS", {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
@@ -367,6 +388,7 @@ runtimeFlags.ACCEPT_LEGACY_V1 = ACCEPT_LEGACY_V1;
|
||||
runtimeFlags.VIEW_FILTER_INCLUDE_LEGACY_VIDEO = VIEW_FILTER_INCLUDE_LEGACY_VIDEO;
|
||||
runtimeFlags.FEATURE_WATCH_HISTORY_V2 = FEATURE_WATCH_HISTORY_V2;
|
||||
runtimeFlags.FEATURE_PUBLISH_NIP71 = FEATURE_PUBLISH_NIP71;
|
||||
runtimeFlags.FEATURE_HASHTAG_PREFERENCES = FEATURE_HASHTAG_PREFERENCES;
|
||||
runtimeFlags.FEATURE_TRUST_SEEDS = FEATURE_TRUST_SEEDS;
|
||||
runtimeFlags.FEATURE_TRUSTED_HIDE_CONTROLS = FEATURE_TRUSTED_HIDE_CONTROLS;
|
||||
runtimeFlags.WSS_TRACKERS = WSS_TRACKERS;
|
||||
@@ -407,6 +429,11 @@ export function setTrustedHideControlsEnabled(next) {
|
||||
return FEATURE_TRUSTED_HIDE_CONTROLS;
|
||||
}
|
||||
|
||||
export function setHashtagPreferencesEnabled(next) {
|
||||
runtimeFlags.FEATURE_HASHTAG_PREFERENCES = next;
|
||||
return FEATURE_HASHTAG_PREFERENCES;
|
||||
}
|
||||
|
||||
export function resetRuntimeFlags() {
|
||||
setUrlFirstEnabled(DEFAULT_FLAGS.URL_FIRST_ENABLED);
|
||||
setAcceptLegacyV1(DEFAULT_FLAGS.ACCEPT_LEGACY_V1);
|
||||
@@ -414,6 +441,7 @@ export function resetRuntimeFlags() {
|
||||
DEFAULT_FLAGS.VIEW_FILTER_INCLUDE_LEGACY_VIDEO
|
||||
);
|
||||
setWatchHistoryV2Enabled(DEFAULT_FLAGS.FEATURE_WATCH_HISTORY_V2);
|
||||
setHashtagPreferencesEnabled(DEFAULT_FLAGS.FEATURE_HASHTAG_PREFERENCES);
|
||||
setTrustSeedsEnabled(DEFAULT_FLAGS.FEATURE_TRUST_SEEDS);
|
||||
setTrustedHideControlsEnabled(DEFAULT_FLAGS.FEATURE_TRUSTED_HIDE_CONTROLS);
|
||||
setTrustedMuteHideThreshold(DEFAULT_FLAGS.TRUSTED_MUTE_HIDE_THRESHOLD);
|
||||
|
||||
@@ -22,6 +22,7 @@ export const NOTE_TYPES = Object.freeze({
|
||||
WATCH_HISTORY_CHUNK: "watchHistoryChunk",
|
||||
SUBSCRIPTION_LIST: "subscriptionList",
|
||||
USER_BLOCK_LIST: "userBlockList",
|
||||
HASHTAG_PREFERENCES: "hashtagPreferences",
|
||||
ADMIN_MODERATION_LIST: "adminModerationList",
|
||||
ADMIN_BLACKLIST: "adminBlacklist",
|
||||
ADMIN_WHITELIST: "adminWhitelist",
|
||||
@@ -313,6 +314,21 @@ const BASE_SCHEMAS = {
|
||||
description: "Encrypted JSON: { blockedPubkeys: string[] }.",
|
||||
},
|
||||
},
|
||||
[NOTE_TYPES.HASHTAG_PREFERENCES]: {
|
||||
type: NOTE_TYPES.HASHTAG_PREFERENCES,
|
||||
label: "Hashtag preferences",
|
||||
kind: 30005,
|
||||
identifierTag: {
|
||||
name: "d",
|
||||
value: "bitvid:tag-preferences",
|
||||
},
|
||||
appendTags: [["encrypted", "nip44_v2"]],
|
||||
content: {
|
||||
format: "nip44-json",
|
||||
description:
|
||||
"NIP-44 encrypted JSON: { version, interests: string[], disinterests: string[] }.",
|
||||
},
|
||||
},
|
||||
[NOTE_TYPES.ADMIN_MODERATION_LIST]: {
|
||||
type: NOTE_TYPES.ADMIN_MODERATION_LIST,
|
||||
label: "Admin moderation list",
|
||||
@@ -1133,6 +1149,28 @@ export function buildBlockListEvent({
|
||||
};
|
||||
}
|
||||
|
||||
export function buildHashtagPreferenceEvent({
|
||||
pubkey,
|
||||
created_at,
|
||||
content,
|
||||
}) {
|
||||
const schema = getNostrEventSchema(NOTE_TYPES.HASHTAG_PREFERENCES);
|
||||
const tags = [];
|
||||
const identifierName = schema?.identifierTag?.name || "d";
|
||||
const identifierValue = schema?.identifierTag?.value || "bitvid:tag-preferences";
|
||||
if (identifierName && identifierValue) {
|
||||
tags.push([identifierName, identifierValue]);
|
||||
}
|
||||
appendSchemaTags(tags, schema);
|
||||
return {
|
||||
kind: schema?.kind ?? 30005,
|
||||
pubkey,
|
||||
created_at,
|
||||
tags,
|
||||
content: typeof content === "string" ? content : String(content ?? ""),
|
||||
};
|
||||
}
|
||||
|
||||
function resolveAdminNoteType(listKey) {
|
||||
switch (listKey) {
|
||||
case "moderation":
|
||||
|
||||
Reference in new issue
Block a user