mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Remove legacy hashtag preference fallback
This commit is contained in:
1 parent
53cb2e32ac
commit
4caa4d4877
3 files changed
+13
-31
No files matched your search
@@ -81,8 +81,8 @@ The profile modal now exposes blur, autoplay, and hide thresholds so operators c
|
||||
|
||||
- The Profile modal’s Hashtags tab is wired to [`HashtagPreferencesService`](../../js/services/hashtagPreferencesService.js), which maintains a local snapshot of the viewer’s interests and disinterests, normalizes every tag, and guarantees that the two sets stay mutually exclusive before broadcasting UI change events.【F:js/services/hashtagPreferencesService.js†L206-L276】【F:js/services/hashtagPreferencesService.js†L304-L324】
|
||||
- `bitvidApp` resolves the active pubkey’s preferences at login, listens for `CHANGE` events, and forwards the normalized snapshot to controllers so moderation and discovery logic can react without querying relays again.【F:js/app.js†L3811-L3906】【F:js/app.js†L3940-L4050】
|
||||
- Publishing writes a replaceable `kind 30015` list (legacy `30005` remains readable) with `d=bitvid:tag-preferences`, encrypting the `{ version, interests, disinterests }` payload via the best available NIP-44/NIP-04 scheme before hitting every configured write relay.【F:docs/nostr-event-schemas.md†L150-L201】【F:js/services/hashtagPreferencesService.js†L520-L711】
|
||||
- Legacy `30005` events are still fetched and decrypted; saving or toggling a tag republishes them as `30015`, so operators only need to prompt a re-save if they want faster convergence than organic edits provide.【F:js/services/hashtagPreferencesService.js†L360-L470】【F:docs/nostr-event-schemas.md†L196-L201】
|
||||
- Publishing writes a replaceable `kind 30015` list with `d=bitvid:tag-preferences`, encrypting the `{ version, interests, disinterests }` payload via the best available NIP-44/NIP-04 scheme before hitting every configured write relay.【F:docs/nostr-event-schemas.md†L150-L201】【F:js/services/hashtagPreferencesService.js†L520-L711】
|
||||
- Legacy `30005` events are ignored; saving or toggling a tag republishes preferences as `30015`, so prompt users to re-save if they previously only published the deprecated kind.【F:js/services/hashtagPreferencesService.js†L360-L470】【F:docs/nostr-event-schemas.md†L196-L201】
|
||||
|
||||
### Runtime flags
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ import { updateWatchHistoryListWithDefaultClient } from "./nostrWatchHistoryFaca
|
||||
| Watch history month (`NOTE_TYPES.WATCH_HISTORY_INDEX`) | `WATCH_HISTORY_KIND` (default `30079`, clients also read legacy `30078`) | Replaceable list tag `['d', `${WATCH_HISTORY_LIST_IDENTIFIER}:<YYYY-MM>`]` with optional `['month', <YYYY-MM>]` marker plus schema append tags; no chunk pointers required. | JSON payload `{ version, month: 'YYYY-MM', items: [{ id: <eventId\|address>, watched_at?: <unix seconds> }] }` |
|
||||
| Subscription list (`NOTE_TYPES.SUBSCRIPTION_LIST`) | `30000` | `['d', 'subscriptions']` | NIP-04/NIP-44 encrypted JSON array of NIP-51 follow-set tuples (e.g., `[['p', <hex>], …]`) |
|
||||
| User block list (`NOTE_TYPES.USER_BLOCK_LIST`) | `10000` | `['d', 'user-blocks']` | NIP-04/NIP-44 encrypted JSON `{ blockedPubkeys: string[] }` |
|
||||
| Hashtag preferences (`NOTE_TYPES.HASHTAG_PREFERENCES`) | `30015` (reads legacy `30005`) | `['d', 'bitvid:tag-preferences']` plus schema-appended `['encrypted','nip44_v2']` | NIP-44 encrypted JSON `{ version, interests: string[], disinterests: string[] }` |
|
||||
| Hashtag preferences (`NOTE_TYPES.HASHTAG_PREFERENCES`) | `30015` | `['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 |
|
||||
@@ -187,15 +187,16 @@ 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. Readers continue to accept legacy `30005` payloads so previously
|
||||
published preferences remain visible.
|
||||
relays.
|
||||
|
||||
### Migration approach: auto-republish on next user change
|
||||
|
||||
We are **not** shipping a one-off migration helper. Instead, the existing
|
||||
`HashtagPreferencesService.publish()` flow reissues preferences as kind `30015`
|
||||
the next time a user saves their interests from the profile modal. That publish
|
||||
path already:
|
||||
the next time a user saves their interests from the profile modal. Legacy
|
||||
`30005` payloads are no longer read, so users with only legacy events must
|
||||
resave their preferences to publish the canonical kind. That publish path
|
||||
already:
|
||||
|
||||
* rehydrates the signer via `getActiveSigner()` and aborts when no signer is
|
||||
available, so background jobs cannot emit preferences without user consent;
|
||||
@@ -218,9 +219,8 @@ Operators should monitor the rollout as follows:
|
||||
1. After deploying this change, review relay dashboards or logs for accounts
|
||||
saving preferences to confirm new `30015` writes are accepted (look for the
|
||||
`bitvid:tag-preferences` `d` tag).
|
||||
2. Spot-check a few migrated accounts by fetching both `30015` and legacy
|
||||
`30005` events; the canonical kind should present the newest `created_at`
|
||||
timestamp once a user saves.
|
||||
2. Spot-check a few migrated accounts by fetching `30015` events; the canonical
|
||||
kind should present the newest `created_at` timestamp once a user saves.
|
||||
3. If relays reject events, correlate the warnings emitted by
|
||||
`HashtagPreferencesService.publish()` in operator consoles to identify relay
|
||||
outages or permission errors.
|
||||
|
||||
@@ -378,12 +378,8 @@ class HashtagPreferencesService {
|
||||
|
||||
const schema = getNostrEventSchema(NOTE_TYPES.HASHTAG_PREFERENCES);
|
||||
const canonicalKind = schema?.kind ?? 30015;
|
||||
const legacyKind = 30005;
|
||||
const filterKinds = canonicalKind === legacyKind
|
||||
? [canonicalKind]
|
||||
: [canonicalKind, legacyKind];
|
||||
const filter = {
|
||||
kinds: filterKinds,
|
||||
kinds: [canonicalKind],
|
||||
authors: [normalized],
|
||||
"#d": [HASHTAG_IDENTIFIER],
|
||||
limit: 50,
|
||||
@@ -409,15 +405,6 @@ class HashtagPreferencesService {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prefer the newest event, breaking timestamp ties by prioritizing the
|
||||
// canonical kind (30015) before falling back to the legacy 30005 payload.
|
||||
const preferredKinds = filterKinds;
|
||||
const getKindPriority = (event) => {
|
||||
const kindValue = Number(event?.kind);
|
||||
const index = preferredKinds.indexOf(kindValue);
|
||||
return index === -1 ? preferredKinds.length : index;
|
||||
};
|
||||
|
||||
const latest = events.reduce((current, candidate) => {
|
||||
if (!candidate) {
|
||||
return current;
|
||||
@@ -428,11 +415,6 @@ class HashtagPreferencesService {
|
||||
const candidateTs = Number(candidate.created_at) || 0;
|
||||
const currentTs = Number(current.created_at) || 0;
|
||||
if (candidateTs === currentTs) {
|
||||
const candidatePriority = getKindPriority(candidate);
|
||||
const currentPriority = getKindPriority(current);
|
||||
if (candidatePriority !== currentPriority) {
|
||||
return candidatePriority < currentPriority ? candidate : current;
|
||||
}
|
||||
return candidate.id > current.id ? candidate : current;
|
||||
}
|
||||
return candidateTs > currentTs ? candidate : current;
|
||||
@@ -457,8 +439,8 @@ class HashtagPreferencesService {
|
||||
|
||||
try {
|
||||
const payload = JSON.parse(decryptResult.plaintext);
|
||||
// Normalize whichever source kind we decrypted into the canonical
|
||||
// preferences payload so downstream consumers receive a single shape.
|
||||
// Normalize the decrypted payload into the canonical preferences shape so
|
||||
// downstream consumers receive a single structure.
|
||||
const normalizedPayload = normalizePreferencesPayload(payload);
|
||||
|
||||
this.preferencesVersion = normalizedPayload.version;
|
||||
|
||||
Reference in new issue
Block a user