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 +1 -1
- package/src/helpers/app-metadata.js +28 -0
- package/src/index.js +65 -43
package/package.json
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
|
|
363
|
-
|
|
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
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
-
|
|
377
|
+
if (missingRelays.length === 0) return mostRecentEvent
|
|
370
378
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
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:
|
|
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)
|
|
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)
|
|
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:
|
|
691
|
+
created_at: effectiveCreatedAt
|
|
670
692
|
})
|
|
671
693
|
}
|
|
672
694
|
|