mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Merge pull request #811 from PR0M3TH3AN/codex/refactor-module-imports-and-documentation
Refactor Nostr module imports and update documentation
This commit is contained in:
14 files changed
+113
-41
No files matched your search
@@ -12,11 +12,11 @@ Most operators can ship with the defaults—24-hour deduplication, a 90-day back
|
||||
|
||||
### Anonymous session keys
|
||||
|
||||
Playback telemetry runs even when a viewer has not connected a Nostr account. The client first calls [`ensureSessionActor`](../js/nostr.js#L2011-L2105) to mint or restore an ephemeral keypair stored in `localStorage`. That session actor signs view events until the user authenticates, ensuring relays still see consistent pubkeys without blocking anonymous playback.
|
||||
Playback telemetry runs even when a viewer has not connected a Nostr account. The client first calls [`ensureSessionActor`](../js/nostr/client.js#L2445-L2504) to mint or restore an ephemeral keypair stored in `localStorage`. That session actor signs view events until the user authenticates, ensuring relays still see consistent pubkeys without blocking anonymous playback.
|
||||
|
||||
### Publish latency expectations
|
||||
|
||||
When a player crosses the 12-second watch threshold, bitvid invokes [`publishViewEvent`](../js/nostr.js#L2159-L2323) through the view-only [`recordVideoView`](../js/nostr.js#L4516-L4555) contract. The helper considers the publish successful as soon as any configured relay acknowledges the event, which in practice keeps latency under a second on public relays. The UI optimistically increments totals by feeding the signed event into [`ingestLocalViewEvent`](../js/viewCounter.js#L608-L640), so cards and modals reflect the new view immediately even while other relays finish syncing.
|
||||
When a player crosses the 12-second watch threshold, bitvid invokes [`publishViewEvent`](../js/nostr/viewEvents.js#L662-L838) through the view-only [`recordVideoView`](../js/nostr/viewEvents.js#L854-L879) contract. The helper considers the publish successful as soon as any configured relay acknowledges the event, which in practice keeps latency under a second on public relays. The UI optimistically increments totals by feeding the signed event into [`ingestLocalViewEvent`](../js/viewCounter.js#L619-L633), so cards and modals reflect the new view immediately even while other relays finish syncing.
|
||||
|
||||
The watch history pipeline has been retired; `recordVideoView` now focuses solely on analytics publishing.
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ Authentication providers should register their capabilities with the
|
||||
`nostrClient` after login so every publish helper can reuse them:
|
||||
|
||||
```js
|
||||
import { setActiveSigner } from "./nostr.js";
|
||||
import { setActiveSigner } from "./nostr/index.js";
|
||||
|
||||
setActiveSigner({
|
||||
type: "extension", // optional label, used to request NIP-07 permissions
|
||||
@@ -143,7 +143,7 @@ plus an optional leading `['head','1']` marker so relays can prioritize the firs
|
||||
ciphertext. All chunk content is encrypted with NIP-04 and stores only pointer
|
||||
entries; richer metadata remains on-device via the
|
||||
[`WatchHistoryService`](../js/watchHistoryService.js) APIs, which default to
|
||||
pointer-only writes and local-only metadata caches.【F:config/instance-config.js†L60-L78】【F:js/nostrEventSchemas.js†L157-L189】【F:js/nostr.js†L2329-L2369】【F:js/watchHistoryService.js†L331-L376】
|
||||
pointer-only writes and local-only metadata caches.【F:config/instance-config.js†L60-L78】【F:js/nostrEventSchemas.js†L157-L189】【F:js/nostr/watchHistory.js†L1343-L1400】【F:js/watchHistoryService.js†L331-L376】
|
||||
|
||||
Refer to the [`WatchHistoryService`](../js/watchHistoryService.js) for queue
|
||||
management hooks, manual snapshot helpers, and metadata toggle controls that
|
||||
|
||||
@@ -16,16 +16,16 @@ Snapshots publish two event types to the shared `WATCH_HISTORY_KIND` stream:
|
||||
`['encrypted','nip04']`. The first chunk is additionally marked as
|
||||
`['head','1']` and may append `"a"` tags that reference previous chunk
|
||||
addresses, allowing readers to reconstruct the full set even when relays
|
||||
deduplicate aggressively.【F:js/nostrEventSchemas.js†L175-L189】【F:js/nostr.js†L2329-L2369】
|
||||
deduplicate aggressively.【F:js/nostrEventSchemas.js†L175-L189】【F:js/nostr/watchHistory.js†L1343-L1400】
|
||||
2. **Pointer event** — After chunks are accepted, bitvid emits a compact index
|
||||
event containing the canonical list identifier (`['d', WATCH_HISTORY_LIST_IDENTIFIER]`),
|
||||
the `snapshot` label, the total chunk count, and an `a` tag for each chunk
|
||||
address.【F:js/nostrEventSchemas.js†L157-L170】【F:js/nostr.js†L2425-L2441】
|
||||
address.【F:js/nostrEventSchemas.js†L157-L170】【F:js/nostr/watchHistory.js†L1434-L1462】
|
||||
|
||||
Chunk content is a NIP-04 encrypted JSON envelope of `{ version: 2, snapshot,
|
||||
chunkIndex, totalChunks, items[] }`. Items are pointer descriptors (`e` or `a`
|
||||
references plus optional relay hints) so that relays never learn which titles
|
||||
were played—only which events or addresses the client can dereference later.【F:js/nostr.js†L2337-L2364】
|
||||
were played—only which events or addresses the client can dereference later.【F:js/nostr/watchHistory.js†L1362-L1375】
|
||||
|
||||
## Batching configuration
|
||||
|
||||
@@ -34,7 +34,7 @@ optionally cap each response by defining `WATCH_HISTORY_BATCH_PAGE_SIZE` in
|
||||
`config/instance-config.js`. Leaving the page size unset returns the full
|
||||
`WATCH_HISTORY_MAX_ITEMS` window while still letting the UI paginate locally,
|
||||
but setting a positive integer keeps API payloads in lockstep with batched
|
||||
renderers like `historyView`.【F:config/instance-config.js†L101-L123】【F:js/nostr.js†L2987-L2998】【F:js/historyView.js†L1-L38】
|
||||
renderers like `historyView`.【F:config/instance-config.js†L101-L123】【F:js/nostr/watchHistory.js†L2218-L2256】【F:js/historyView.js†L1-L38】
|
||||
|
||||
## Snapshot cadence
|
||||
|
||||
@@ -52,7 +52,7 @@ When a snapshot publish fails but the response is retryable, the service stores
|
||||
the returned `snapshotId`, records the originating reason, and delegates to the
|
||||
Nostr client to retry with exponential backoff. Retries start after two seconds,
|
||||
double per attempt with 25% jitter, cap at five minutes, and stop after eight
|
||||
attempts unless a publish succeeds sooner.【F:js/watchHistoryService.js†L948-L985】【F:js/watchHistoryService.js†L723-L777】【F:js/nostr.js†L1988-L2087】
|
||||
attempts unless a publish succeeds sooner.【F:js/watchHistoryService.js†L948-L985】【F:js/watchHistoryService.js†L723-L777】【F:js/nostr/watchHistory.js†L929-L999】
|
||||
|
||||
## Legacy payload handling
|
||||
|
||||
@@ -60,7 +60,7 @@ Readers hydrate history by combining the pointer event, any encrypted chunks,
|
||||
and fallback metadata embedded in legacy watch-history lists. The resolver still
|
||||
accepts the `watch-history:v2:index` identifier, merges pointer tags from the
|
||||
index event, and falls back to plaintext content when decryption fails so older
|
||||
relays remain compatible.【F:config/instance-config.js†L60-L78】【F:js/nostr.js†L2704-L2779】【F:js/nostr.js†L5216-L5264】
|
||||
relays remain compatible.【F:config/instance-config.js†L60-L78】【F:js/nostr/watchHistory.js†L2120-L2170】【F:js/nostr/watchHistory.js†L660-L689】
|
||||
|
||||
## Local metadata toggles
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// js/app.js
|
||||
|
||||
import { nostrClient, recordVideoView as recordVideoViewApi } from "./nostr.js";
|
||||
import { nostrClient } from "./nostr.js";
|
||||
import { recordVideoView } from "./nostr/index.js";
|
||||
import { torrentClient } from "./webtorrent.js";
|
||||
import {
|
||||
isDevMode,
|
||||
@@ -137,6 +138,8 @@ import {
|
||||
urlHealthConstants,
|
||||
} from "./state/cache.js";
|
||||
|
||||
const recordVideoViewApi = (...args) => recordVideoView(nostrClient, ...args);
|
||||
|
||||
const UNSUPPORTED_BTITH_MESSAGE =
|
||||
"This magnet link is missing a compatible BitTorrent v1 info hash.";
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// js/channelProfile.js
|
||||
|
||||
import {
|
||||
nostrClient,
|
||||
convertEventToVideo as sharedConvertEventToVideo,
|
||||
} from "./nostr.js";
|
||||
import { nostrClient } from "./nostr.js";
|
||||
import { convertEventToVideo as sharedConvertEventToVideo } from "./nostr/index.js";
|
||||
import { DEFAULT_RELAY_URLS } from "./nostr/toolkit.js";
|
||||
import { subscriptions } from "./subscriptions.js";
|
||||
import { attachHealthBadges } from "./gridHealth.js";
|
||||
|
||||
+11
-1
@@ -1,7 +1,10 @@
|
||||
// js/historyView.js
|
||||
|
||||
import watchHistoryService from "./watchHistoryService.js";
|
||||
import { nostrClient, updateWatchHistoryList } from "./nostr.js";
|
||||
import { nostrClient } from "./nostr.js";
|
||||
import {
|
||||
updateWatchHistoryList as updateWatchHistoryListWithManager,
|
||||
} from "./nostr/index.js";
|
||||
import { pointerKey, normalizePointerInput } from "./nostr/watchHistory.js";
|
||||
import {
|
||||
WATCH_HISTORY_BATCH_RESOLVE,
|
||||
@@ -33,6 +36,13 @@ const FALLBACK_AVATAR = "assets/svg/default-profile.svg";
|
||||
const isDevEnv =
|
||||
typeof process !== "undefined" && process?.env?.NODE_ENV !== "production";
|
||||
|
||||
const updateWatchHistoryList = (items, options) =>
|
||||
updateWatchHistoryListWithManager(
|
||||
nostrClient.watchHistory,
|
||||
items,
|
||||
options,
|
||||
);
|
||||
|
||||
function escapeSelector(value) {
|
||||
if (typeof value !== "string") {
|
||||
return "";
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
export {
|
||||
NostrClient,
|
||||
getActiveSigner,
|
||||
setActiveSigner,
|
||||
clearActiveSigner,
|
||||
resolveActiveSigner,
|
||||
shouldRequestExtensionPermissions,
|
||||
} from "./client.js";
|
||||
|
||||
export {
|
||||
DEFAULT_NIP07_ENCRYPTION_METHODS,
|
||||
DEFAULT_NIP07_PERMISSION_METHODS,
|
||||
} from "./nip07Permissions.js";
|
||||
|
||||
export {
|
||||
buildNip71MetadataTags,
|
||||
buildNip71VideoEvent,
|
||||
collectNip71PointerRequests,
|
||||
convertEventToVideo,
|
||||
extractNip71MetadataFromTags,
|
||||
getDTagValueFromTags,
|
||||
mergeNip71MetadataIntoVideo,
|
||||
populateNip71MetadataForVideos,
|
||||
processNip71Events,
|
||||
buildVideoPointerValue,
|
||||
stringFromInput,
|
||||
} from "./nip71.js";
|
||||
|
||||
export {
|
||||
normalizePointerInput,
|
||||
pointerKey,
|
||||
chunkWatchHistoryPayloadItems,
|
||||
normalizeActorKey,
|
||||
parseWatchHistoryContentWithFallback,
|
||||
isNip04EncryptedWatchHistoryEvent,
|
||||
watchHistoryHelpers,
|
||||
updateWatchHistoryList,
|
||||
removeWatchHistoryItem,
|
||||
} from "./watchHistory.js";
|
||||
|
||||
export {
|
||||
deriveViewEventBucketIndex,
|
||||
deriveViewEventPointerScope,
|
||||
hasRecentViewPublish,
|
||||
rememberViewPublish,
|
||||
createVideoViewEventFilters,
|
||||
getViewEventGuardWindowMs,
|
||||
listVideoViewEvents,
|
||||
subscribeVideoViewEvents,
|
||||
countVideoViewEvents,
|
||||
publishViewEvent,
|
||||
recordVideoView,
|
||||
} from "./viewEvents.js";
|
||||
+3
-5
@@ -1,10 +1,8 @@
|
||||
import { isDevMode } from "./config.js";
|
||||
import { DEFAULT_RELAY_URLS } from "./nostr/toolkit.js";
|
||||
import {
|
||||
getActiveSigner,
|
||||
nostrClient,
|
||||
requestDefaultExtensionPermissions,
|
||||
} from "./nostr.js";
|
||||
import { nostrClient } from "./nostr.js";
|
||||
import { getActiveSigner } from "./nostr/index.js";
|
||||
import { requestDefaultExtensionPermissions } from "./nostrClientRegistry.js";
|
||||
import { buildRelayListEvent } from "./nostrEventSchemas.js";
|
||||
import { devLogger, userLogger } from "./utils/logger.js";
|
||||
import {
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
getCurrentUserNpub,
|
||||
} from "../state/appState.js";
|
||||
import { userLogger } from "../utils/logger.js";
|
||||
import { requestDefaultExtensionPermissions } from "../nostr.js";
|
||||
import { requestDefaultExtensionPermissions } from "../nostrClientRegistry.js";
|
||||
import {
|
||||
getSavedProfiles,
|
||||
getActiveProfilePubkey,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {
|
||||
nostrClient,
|
||||
convertEventToVideo,
|
||||
} from "../nostr.js";
|
||||
import { nostrClient } from "../nostr.js";
|
||||
import { convertEventToVideo } from "../nostr/index.js";
|
||||
import { accessControl } from "../accessControl.js";
|
||||
import { ALLOW_NSFW_CONTENT } from "../config.js";
|
||||
import { userLogger } from "../utils/logger.js";
|
||||
|
||||
+10
-5
@@ -1,12 +1,12 @@
|
||||
// js/subscriptions.js
|
||||
import { nostrClient } from "./nostr.js";
|
||||
import {
|
||||
getActiveSigner,
|
||||
nostrClient,
|
||||
convertEventToVideo as sharedConvertEventToVideo,
|
||||
requestDefaultExtensionPermissions,
|
||||
listVideoViewEvents as listVideoViewEventsApi,
|
||||
subscribeVideoViewEvents as subscribeVideoViewEventsApi,
|
||||
} from "./nostr.js";
|
||||
listVideoViewEvents,
|
||||
subscribeVideoViewEvents,
|
||||
} from "./nostr/index.js";
|
||||
import { requestDefaultExtensionPermissions } from "./nostrClientRegistry.js";
|
||||
import { DEFAULT_RELAY_URLS } from "./nostr/toolkit.js";
|
||||
import {
|
||||
buildSubscriptionListEvent,
|
||||
@@ -112,6 +112,11 @@ function determineDecryptionOrder(event, availableSchemes) {
|
||||
|
||||
const getApp = () => getApplication();
|
||||
|
||||
const listVideoViewEventsApi = (pointer, options) =>
|
||||
listVideoViewEvents(nostrClient, pointer, options);
|
||||
const subscribeVideoViewEventsApi = (pointer, options) =>
|
||||
subscribeVideoViewEvents(nostrClient, pointer, options);
|
||||
|
||||
/**
|
||||
* Manages the user's subscription list (kind=30002) *privately*,
|
||||
* using NIP-04 encryption for the content field.
|
||||
|
||||
+3
-5
@@ -1,9 +1,7 @@
|
||||
// js/userBlocks.js
|
||||
import {
|
||||
getActiveSigner,
|
||||
nostrClient,
|
||||
requestDefaultExtensionPermissions,
|
||||
} from "./nostr.js";
|
||||
import { nostrClient } from "./nostr.js";
|
||||
import { getActiveSigner } from "./nostr/index.js";
|
||||
import { requestDefaultExtensionPermissions } from "./nostrClientRegistry.js";
|
||||
import { buildBlockListEvent, BLOCK_LIST_IDENTIFIER } from "./nostrEventSchemas.js";
|
||||
import { userLogger } from "./utils/logger.js";
|
||||
import {
|
||||
|
||||
+12
-4
@@ -17,16 +17,24 @@ import {
|
||||
VIEW_COUNT_DEDUPE_WINDOW_SECONDS,
|
||||
} from "./config.js";
|
||||
import { userLogger } from "./utils/logger.js";
|
||||
import { nostrClient } from "./nostr.js";
|
||||
import {
|
||||
countVideoViewEvents as countVideoViewEventsApi,
|
||||
listVideoViewEvents as listVideoViewEventsApi,
|
||||
subscribeVideoViewEvents as subscribeVideoViewEventsApi,
|
||||
} from "./nostr.js";
|
||||
countVideoViewEvents,
|
||||
listVideoViewEvents,
|
||||
subscribeVideoViewEvents,
|
||||
} from "./nostr/index.js";
|
||||
|
||||
const VIEW_COUNTER_STORAGE_KEY = "bitvid:view-counter:v1";
|
||||
const STORAGE_DEBOUNCE_MS = 500;
|
||||
const SECONDS_PER_DAY = 86_400;
|
||||
|
||||
const listVideoViewEventsApi = (pointer, options) =>
|
||||
listVideoViewEvents(nostrClient, pointer, options);
|
||||
const subscribeVideoViewEventsApi = (pointer, options) =>
|
||||
subscribeVideoViewEvents(nostrClient, pointer, options);
|
||||
const countVideoViewEventsApi = (pointer, options) =>
|
||||
countVideoViewEvents(nostrClient, pointer, options);
|
||||
|
||||
/** @type {Map<string, ViewCounterState>} */
|
||||
const pointerStates = new Map();
|
||||
/** @type {Map<string, PointerListeners>} */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// js/watchHistoryService.js
|
||||
|
||||
import { nostrClient, requestDefaultExtensionPermissions } from "./nostr.js";
|
||||
import { nostrClient } from "./nostr.js";
|
||||
import { requestDefaultExtensionPermissions } from "./nostrClientRegistry.js";
|
||||
import {
|
||||
normalizePointerInput,
|
||||
pointerKey,
|
||||
|
||||
Reference in new issue
Block a user