nappup 1.5.6 → 1.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "url": "git+https://github.com/44billion/nappup.git"
7
7
  },
8
8
  "license": "MIT",
9
- "version": "1.5.6",
9
+ "version": "1.5.7",
10
10
  "description": "Nostr App Uploader",
11
11
  "type": "module",
12
12
  "scripts": {
@@ -9,6 +9,20 @@ export function extractHtmlMetadata (htmlContent) {
9
9
  name = titleMatch[1].trim()
10
10
  }
11
11
 
12
+ if (!name) {
13
+ const ogTitleRegex = /<meta\s+[^>]*(?:property|name)\s*=\s*["']og:title["'][^>]*content\s*=\s*["']([^"']+)["'][^>]*>/i
14
+ const ogTitleMatch = htmlContent.match(ogTitleRegex)
15
+ if (ogTitleMatch && ogTitleMatch[1]) {
16
+ name = ogTitleMatch[1].trim()
17
+ } else {
18
+ const altOgTitleRegex = /<meta\s+[^>]*content\s*=\s*["']([^"']+)["'][^>]*(?:property|name)\s*=\s*["']og:title["'][^>]*>/i
19
+ const altOgTitleMatch = htmlContent.match(altOgTitleRegex)
20
+ if (altOgTitleMatch && altOgTitleMatch[1]) {
21
+ name = altOgTitleMatch[1].trim()
22
+ }
23
+ }
24
+ }
25
+
12
26
  const metaDescRegex = /<meta\s+[^>]*name\s*=\s*["']description["'][^>]*content\s*=\s*["']([^"']+)["'][^>]*>/i
13
27
  const metaDescMatch = htmlContent.match(metaDescRegex)
14
28
  if (metaDescMatch && metaDescMatch[1]) {
@@ -22,6 +36,20 @@ export function extractHtmlMetadata (htmlContent) {
22
36
  description = altMetaDescMatch[1].trim()
23
37
  }
24
38
  }
39
+
40
+ if (!description) {
41
+ const ogDescRegex = /<meta\s+[^>]*(?:property|name)\s*=\s*["']og:description["'][^>]*content\s*=\s*["']([^"']+)["'][^>]*>/i
42
+ const ogDescMatch = htmlContent.match(ogDescRegex)
43
+ if (ogDescMatch && ogDescMatch[1]) {
44
+ description = ogDescMatch[1].trim()
45
+ } else {
46
+ const altOgDescRegex = /<meta\s+[^>]*content\s*=\s*["']([^"']+)["'][^>]*(?:property|name)\s*=\s*["']og:description["'][^>]*>/i
47
+ const altOgDescMatch = htmlContent.match(altOgDescRegex)
48
+ if (altOgDescMatch && altOgDescMatch[1]) {
49
+ description = altOgDescMatch[1].trim()
50
+ }
51
+ }
52
+ }
25
53
  } catch (_) {
26
54
  // ignore
27
55
  }
package/src/index.js CHANGED
@@ -182,6 +182,12 @@ async function uploadBinaryDataChunks ({ nmmr, signer, filename, chunkLength, lo
182
182
  ;({ pause } = (await throttledSendEvent(foundEvent, missingRelays, { pause, log, trailingPause: true, minSuccessfulRelays: 0 })))
183
183
  continue
184
184
  }
185
+
186
+ const createdAt = Math.floor(Date.now() / 1000)
187
+ let effectiveCreatedAt = (foundEvent && foundEvent.created_at >= createdAt) ? foundEvent.created_at + 1 : createdAt
188
+ const maxCreatedAt = createdAt + 172800 // 2 days ahead
189
+ if (effectiveCreatedAt > maxCreatedAt) effectiveCreatedAt = maxCreatedAt
190
+
185
191
  const binaryDataChunk = {
186
192
  kind: 34600,
187
193
  tags: [
@@ -192,7 +198,7 @@ async function uploadBinaryDataChunks ({ nmmr, signer, filename, chunkLength, lo
192
198
  ],
193
199
  // These chunks already have the expected size of 51000 bytes
194
200
  content: new Base93Encoder().update(chunk.contentBytes).getEncoded(),
195
- created_at: Math.floor(Date.now() / 1000)
201
+ created_at: effectiveCreatedAt
196
202
  }
197
203
 
198
204
  const event = await signer.signEvent(binaryDataChunk)
@@ -329,59 +335,65 @@ async function uploadBundle ({ dTag, channel, fileMetadata, signer, pause = 0, s
329
335
 
330
336
  const writeRelays = [...new Set([...(await signer.getRelays()).write, ...nappRelays])]
331
337
 
332
- if (!shouldReupload) {
333
- const events = (await nostrRelays.getEvents({
334
- kinds: [kind],
335
- authors: [await signer.getPublicKey()],
336
- '#d': [dTag],
337
- limit: 1
338
- }, writeRelays)).result
339
-
340
- if (events.length > 0) {
341
- events.sort((a, b) => {
342
- if (b.created_at !== a.created_at) return b.created_at - a.created_at
343
- if (a.id < b.id) return -1
344
- if (a.id > b.id) return 1
345
- return 0
346
- })
338
+ let mostRecentEvent
339
+ const events = (await nostrRelays.getEvents({
340
+ kinds: [kind],
341
+ authors: [await signer.getPublicKey()],
342
+ '#d': [dTag],
343
+ limit: 1
344
+ }, writeRelays)).result
345
+
346
+ if (events.length > 0) {
347
+ events.sort((a, b) => {
348
+ if (b.created_at !== a.created_at) return b.created_at - a.created_at
349
+ if (a.id < b.id) return -1
350
+ if (a.id > b.id) return 1
351
+ return 0
352
+ })
353
+ mostRecentEvent = events[0]
354
+ }
347
355
 
348
- const mostRecentEvent = events[0]
349
- const recentFileTags = mostRecentEvent.tags
350
- .filter(t => t[0] === 'file' && t[2] !== '.well-known/napp.json')
351
- .sort((a, b) => (a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0))
356
+ if (!shouldReupload && mostRecentEvent) {
357
+ const recentFileTags = mostRecentEvent.tags
358
+ .filter(t => t[0] === 'file' && t[2] !== '.well-known/napp.json')
359
+ .sort((a, b) => (a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0))
352
360
 
353
- const currentFileTags = fileTags
354
- .filter(t => t[2] !== '.well-known/napp.json')
355
- .sort((a, b) => (a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0))
361
+ const currentFileTags = fileTags
362
+ .filter(t => t[2] !== '.well-known/napp.json')
363
+ .sort((a, b) => (a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0))
356
364
 
357
- const isSame = currentFileTags.length === recentFileTags.length && currentFileTags.every((t, i) => {
358
- const rt = recentFileTags[i]
359
- return rt.length >= 4 && rt[1] === t[1] && rt[2] === t[2] && rt[3] === t[3]
360
- })
365
+ const isSame = currentFileTags.length === recentFileTags.length && currentFileTags.every((t, i) => {
366
+ const rt = recentFileTags[i]
367
+ return rt.length >= 4 && rt[1] === t[1] && rt[2] === t[2] && rt[3] === t[3]
368
+ })
361
369
 
362
- if (isSame) {
363
- log(`Bundle based on ${fileTags.length} files is up-to-date (id: ${mostRecentEvent.id} - created_at: ${new Date(mostRecentEvent.created_at * 1000).toISOString()})`)
370
+ if (isSame) {
371
+ log(`Bundle based on ${fileTags.length} files is up-to-date (id: ${mostRecentEvent.id} - created_at: ${new Date(mostRecentEvent.created_at * 1000).toISOString()})`)
364
372
 
365
- const matchingEvents = events.filter(e => e.id === mostRecentEvent.id)
366
- const coveredRelays = new Set(matchingEvents.map(e => e.meta?.relay).filter(Boolean))
367
- const missingRelays = writeRelays.filter(r => !coveredRelays.has(r))
373
+ const matchingEvents = events.filter(e => e.id === mostRecentEvent.id)
374
+ const coveredRelays = new Set(matchingEvents.map(e => e.meta?.relay).filter(Boolean))
375
+ const missingRelays = writeRelays.filter(r => !coveredRelays.has(r))
368
376
 
369
- if (missingRelays.length === 0) return mostRecentEvent
377
+ if (missingRelays.length === 0) return mostRecentEvent
370
378
 
371
- // nostrRelays.getEvents currently doesn't tell us which event came from which relay,
372
- // so we re-upload to all relays to ensure consistency
373
- log(`Re-uploading existing bundle event to ${missingRelays.length} missing relays (out of ${writeRelays.length})`)
374
- await throttledSendEvent(mostRecentEvent, missingRelays, { pause, trailingPause: true, log, minSuccessfulRelays: 0 })
375
- return mostRecentEvent
376
- }
379
+ // nostrRelays.getEvents currently doesn't tell us which event came from which relay,
380
+ // so we re-upload to all relays to ensure consistency
381
+ log(`Re-uploading existing bundle event to ${missingRelays.length} missing relays (out of ${writeRelays.length})`)
382
+ await throttledSendEvent(mostRecentEvent, missingRelays, { pause, trailingPause: true, log, minSuccessfulRelays: 0 })
383
+ return mostRecentEvent
377
384
  }
378
385
  }
379
386
 
387
+ const createdAt = Math.floor(Date.now() / 1000)
388
+ let effectiveCreatedAt = (mostRecentEvent && mostRecentEvent.created_at >= createdAt) ? mostRecentEvent.created_at + 1 : createdAt
389
+ const maxCreatedAt = createdAt + 172800 // 2 days ahead
390
+ if (effectiveCreatedAt > maxCreatedAt) effectiveCreatedAt = maxCreatedAt
391
+
380
392
  const appBundle = {
381
393
  kind,
382
394
  tags,
383
395
  content: '',
384
- created_at: Math.floor(Date.now() / 1000)
396
+ created_at: effectiveCreatedAt
385
397
  }
386
398
  const event = await signer.signEvent(appBundle)
387
399
  await throttledSendEvent(event, writeRelays, { pause, trailingPause: true, log })
@@ -420,7 +432,10 @@ async function maybeUploadStall ({
420
432
 
421
433
  const previousResult = await getPreviousStall(dTag, relays, signer, channel)
422
434
  const previous = previousResult?.previous
423
- if (!previous && !hasMetadata) return { pause }
435
+ if (!previous && !hasMetadata) {
436
+ if (shouldReupload) log('Skipping stall event upload: No previous event found and no metadata provided.')
437
+ return { pause }
438
+ }
424
439
 
425
440
  const publishStall = async (event) => {
426
441
  const signedEvent = await signer.signEvent(event)
@@ -495,7 +510,10 @@ async function maybeUploadStall ({
495
510
  if (isSummaryAuto) tags.push(['auto', 'summary'])
496
511
  }
497
512
 
498
- if (!hasIcon || !hasName) return { pause }
513
+ if (!hasIcon || !hasName) {
514
+ log(`Skipping stall event creation: Missing required metadata.${!hasName ? ' Name is missing.' : ''}${!hasIcon ? ' Icon is missing.' : ''}`)
515
+ return { pause }
516
+ }
499
517
 
500
518
  return await publishStall({
501
519
  kind,
@@ -662,11 +680,15 @@ async function maybeUploadStall ({
662
680
  return await throttledSendEvent(previous, missingRelays, { pause, log, trailingPause: true, minSuccessfulRelays: 0 })
663
681
  }
664
682
 
683
+ let effectiveCreatedAt = (previous && previous.created_at >= createdAt) ? previous.created_at + 1 : createdAt
684
+ const maxCreatedAt = createdAt + 172800 // 2 days ahead
685
+ if (effectiveCreatedAt > maxCreatedAt) effectiveCreatedAt = maxCreatedAt
686
+
665
687
  return await publishStall({
666
688
  kind,
667
689
  tags,
668
690
  content: typeof previous.content === 'string' ? previous.content : '',
669
- created_at: createdAt
691
+ created_at: effectiveCreatedAt
670
692
  })
671
693
  }
672
694