diff options
| -rw-r--r-- | 18.md | 8 | ||||
| -rw-r--r-- | 23.md | 2 | ||||
| -rw-r--r-- | 55.md | 124 | ||||
| -rw-r--r-- | 71.md | 117 | ||||
| -rw-r--r-- | 94.md | 13 | ||||
| -rw-r--r-- | 99.md | 2 | ||||
| -rw-r--r-- | BREAKING.md | 1 | ||||
| -rw-r--r-- | README.md | 6 |
8 files changed, 176 insertions, 97 deletions
| @@ -25,6 +25,14 @@ quote reposted. The `q` tag ensures quote reposts are not pulled and included | |||
| 25 | as replies in threads. It also allows you to easily pull and count all of the | 25 | as replies in threads. It also allows you to easily pull and count all of the |
| 26 | quotes for a post. | 26 | quotes for a post. |
| 27 | 27 | ||
| 28 | `q` tags should follow the same conventions as NIP 10 `e` tags, with the exception | ||
| 29 | of the `mark` argument. | ||
| 30 | |||
| 31 | `["q", <event-id>, <relay-url>, <pubkey>]` | ||
| 32 | |||
| 33 | Quote reposts MUST include the [NIP-21](21.md) `nevent`, `note`, or `naddr` of the | ||
| 34 | event in the content. | ||
| 35 | |||
| 28 | ## Generic Reposts | 36 | ## Generic Reposts |
| 29 | 37 | ||
| 30 | Since `kind 6` reposts are reserved for `kind 1` contents, we use `kind 16` | 38 | Since `kind 6` reposts are reserved for `kind 1` contents, we use `kind 16` |
| @@ -20,7 +20,7 @@ The `.content` of these events should be a string text in Markdown syntax. To ma | |||
| 20 | 20 | ||
| 21 | ### Metadata | 21 | ### Metadata |
| 22 | 22 | ||
| 23 | For the date of the last update the `.created_at` field should be used, for "tags"/"hashtags" (i.e. topics about which the event might be of relevance) the `t` tag should be used, as per NIP-12. | 23 | For the date of the last update the `.created_at` field should be used, for "tags"/"hashtags" (i.e. topics about which the event might be of relevance) the `t` tag should be used. |
| 24 | 24 | ||
| 25 | Other metadata fields can be added as tags to the event as necessary. Here we standardize 4 that may be useful, although they remain strictly optional: | 25 | Other metadata fields can be added as tags to the event as necessary. Here we standardize 4 that may be useful, although they remain strictly optional: |
| 26 | 26 | ||
| @@ -101,10 +101,10 @@ launcher.launch(intent) | |||
| 101 | context.startActivity(intent) | 101 | context.startActivity(intent) |
| 102 | ``` | 102 | ``` |
| 103 | - result: | 103 | - result: |
| 104 | - If the user approved intent it will return the **npub** in the signature field | 104 | - If the user approved intent it will return the **pubkey** in the signature field |
| 105 | 105 | ||
| 106 | ```kotlin | 106 | ```kotlin |
| 107 | val npub = intent.data?.getStringExtra("signature") | 107 | val pubkey = intent.data?.getStringExtra("signature") |
| 108 | // The package name of the signer application | 108 | // The package name of the signer application |
| 109 | val packageName = intent.data?.getStringExtra("package") | 109 | val packageName = intent.data?.getStringExtra("package") |
| 110 | ``` | 110 | ``` |
| @@ -118,8 +118,8 @@ launcher.launch(intent) | |||
| 118 | intent.putExtra("type", "sign_event") | 118 | intent.putExtra("type", "sign_event") |
| 119 | // To handle results when not waiting between intents | 119 | // To handle results when not waiting between intents |
| 120 | intent.putExtra("id", event.id) | 120 | intent.putExtra("id", event.id) |
| 121 | // Send the current logged in user npub | 121 | // Send the current logged in user pubkey |
| 122 | intent.putExtra("current_user", npub) | 122 | intent.putExtra("current_user", pubkey) |
| 123 | 123 | ||
| 124 | context.startActivity(intent) | 124 | context.startActivity(intent) |
| 125 | ``` | 125 | ``` |
| @@ -142,10 +142,10 @@ launcher.launch(intent) | |||
| 142 | intent.putExtra("type", "nip04_encrypt") | 142 | intent.putExtra("type", "nip04_encrypt") |
| 143 | // to control the result in your application in case you are not waiting the result before sending another intent | 143 | // to control the result in your application in case you are not waiting the result before sending another intent |
| 144 | intent.putExtra("id", "some_id") | 144 | intent.putExtra("id", "some_id") |
| 145 | // Send the current logged in user npub | 145 | // Send the current logged in user pubkey |
| 146 | intent.putExtra("current_user", account.keyPair.pubKey.toNpub()) | 146 | intent.putExtra("current_user", account.keyPair.pubkey) |
| 147 | // Send the hex pubKey that will be used for encrypting the data | 147 | // Send the hex pubkey that will be used for encrypting the data |
| 148 | intent.putExtra("pubKey", pubKey) | 148 | intent.putExtra("pubkey", pubkey) |
| 149 | 149 | ||
| 150 | context.startActivity(intent) | 150 | context.startActivity(intent) |
| 151 | ``` | 151 | ``` |
| @@ -167,10 +167,10 @@ launcher.launch(intent) | |||
| 167 | intent.putExtra("type", "nip44_encrypt") | 167 | intent.putExtra("type", "nip44_encrypt") |
| 168 | // to control the result in your application in case you are not waiting the result before sending another intent | 168 | // to control the result in your application in case you are not waiting the result before sending another intent |
| 169 | intent.putExtra("id", "some_id") | 169 | intent.putExtra("id", "some_id") |
| 170 | // Send the current logged in user npub | 170 | // Send the current logged in user pubkey |
| 171 | intent.putExtra("current_user", account.keyPair.pubKey.toNpub()) | 171 | intent.putExtra("current_user", account.keyPair.pubkey) |
| 172 | // Send the hex pubKey that will be used for encrypting the data | 172 | // Send the hex pubkey that will be used for encrypting the data |
| 173 | intent.putExtra("pubKey", pubKey) | 173 | intent.putExtra("pubkey", pubkey) |
| 174 | 174 | ||
| 175 | context.startActivity(intent) | 175 | context.startActivity(intent) |
| 176 | ``` | 176 | ``` |
| @@ -192,10 +192,10 @@ launcher.launch(intent) | |||
| 192 | intent.putExtra("type", "nip04_decrypt") | 192 | intent.putExtra("type", "nip04_decrypt") |
| 193 | // to control the result in your application in case you are not waiting the result before sending another intent | 193 | // to control the result in your application in case you are not waiting the result before sending another intent |
| 194 | intent.putExtra("id", "some_id") | 194 | intent.putExtra("id", "some_id") |
| 195 | // Send the current logged in user npub | 195 | // Send the current logged in user pubkey |
| 196 | intent.putExtra("current_user", account.keyPair.pubKey.toNpub()) | 196 | intent.putExtra("current_user", account.keyPair.pubkey) |
| 197 | // Send the hex pubKey that will be used for decrypting the data | 197 | // Send the hex pubkey that will be used for decrypting the data |
| 198 | intent.putExtra("pubKey", pubKey) | 198 | intent.putExtra("pubkey", pubkey) |
| 199 | 199 | ||
| 200 | context.startActivity(intent) | 200 | context.startActivity(intent) |
| 201 | ``` | 201 | ``` |
| @@ -217,10 +217,10 @@ launcher.launch(intent) | |||
| 217 | intent.putExtra("type", "nip04_decrypt") | 217 | intent.putExtra("type", "nip04_decrypt") |
| 218 | // to control the result in your application in case you are not waiting the result before sending another intent | 218 | // to control the result in your application in case you are not waiting the result before sending another intent |
| 219 | intent.putExtra("id", "some_id") | 219 | intent.putExtra("id", "some_id") |
| 220 | // Send the current logged in user npub | 220 | // Send the current logged in user pubkey |
| 221 | intent.putExtra("current_user", account.keyPair.pubKey.toNpub()) | 221 | intent.putExtra("current_user", account.keyPair.pubkey) |
| 222 | // Send the hex pubKey that will be used for decrypting the data | 222 | // Send the hex pubkey that will be used for decrypting the data |
| 223 | intent.putExtra("pubKey", pubKey) | 223 | intent.putExtra("pubkey", pubkey) |
| 224 | 224 | ||
| 225 | context.startActivity(intent) | 225 | context.startActivity(intent) |
| 226 | ``` | 226 | ``` |
| @@ -233,6 +233,29 @@ launcher.launch(intent) | |||
| 233 | val id = intent.data?.getStringExtra("id") | 233 | val id = intent.data?.getStringExtra("id") |
| 234 | ``` | 234 | ``` |
| 235 | 235 | ||
| 236 | - **get_relays** | ||
| 237 | - params: | ||
| 238 | |||
| 239 | ```kotlin | ||
| 240 | val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:")) | ||
| 241 | intent.`package` = "com.example.signer" | ||
| 242 | intent.putExtra("type", "get_relays") | ||
| 243 | // to control the result in your application in case you are not waiting the result before sending another intent | ||
| 244 | intent.putExtra("id", "some_id") | ||
| 245 | // Send the current logged in user pubkey | ||
| 246 | intent.putExtra("current_user", account.keyPair.pubkey) | ||
| 247 | |||
| 248 | context.startActivity(intent) | ||
| 249 | ``` | ||
| 250 | - result: | ||
| 251 | - If the user approved intent it will return the **signature** and **id** fields | ||
| 252 | |||
| 253 | ```kotlin | ||
| 254 | val relayJsonText = intent.data?.getStringExtra("signature") | ||
| 255 | // the id you sent | ||
| 256 | val id = intent.data?.getStringExtra("id") | ||
| 257 | ``` | ||
| 258 | |||
| 236 | - **decrypt_zap_event** | 259 | - **decrypt_zap_event** |
| 237 | - params: | 260 | - params: |
| 238 | 261 | ||
| @@ -242,8 +265,8 @@ launcher.launch(intent) | |||
| 242 | intent.putExtra("type", "decrypt_zap_event") | 265 | intent.putExtra("type", "decrypt_zap_event") |
| 243 | // to control the result in your application in case you are not waiting the result before sending another intent | 266 | // to control the result in your application in case you are not waiting the result before sending another intent |
| 244 | intent.putExtra("id", "some_id") | 267 | intent.putExtra("id", "some_id") |
| 245 | // Send the current logged in user npub | 268 | // Send the current logged in user pubkey |
| 246 | intent.putExtra("current_user", account.keyPair.pubKey.toNpub()) | 269 | intent.putExtra("current_user", account.keyPair.pubkey) |
| 247 | context.startActivity(intent) | 270 | context.startActivity(intent) |
| 248 | ``` | 271 | ``` |
| 249 | - result: | 272 | - result: |
| @@ -259,7 +282,7 @@ launcher.launch(intent) | |||
| 259 | 282 | ||
| 260 | To get the result back from Signer Application you should use contentResolver.query in Kotlin. If you are using another framework check the documentation of your framework or a third party library to get the result. | 283 | To get the result back from Signer Application you should use contentResolver.query in Kotlin. If you are using another framework check the documentation of your framework or a third party library to get the result. |
| 261 | 284 | ||
| 262 | If the user did not check the "remember my choice" option, the npub is not in Signer Application or the signer type is not recognized the `contentResolver` will return null | 285 | If the user did not check the "remember my choice" option, the pubkey is not in Signer Application or the signer type is not recognized the `contentResolver` will return null |
| 263 | 286 | ||
| 264 | For the SIGN_EVENT type Signer Application returns two columns "signature" and "event". The column event is the signed event json | 287 | For the SIGN_EVENT type Signer Application returns two columns "signature" and "event". The column event is the signed event json |
| 265 | 288 | ||
| @@ -282,7 +305,7 @@ If the user chose to always reject the event, signer application will return the | |||
| 282 | ) | 305 | ) |
| 283 | ``` | 306 | ``` |
| 284 | - result: | 307 | - result: |
| 285 | - Will return the **npub** in the signature column | 308 | - Will return the **pubkey** in the signature column |
| 286 | 309 | ||
| 287 | ```kotlin | 310 | ```kotlin |
| 288 | if (result == null) return | 311 | if (result == null) return |
| @@ -290,7 +313,7 @@ If the user chose to always reject the event, signer application will return the | |||
| 290 | if (result.moveToFirst()) { | 313 | if (result.moveToFirst()) { |
| 291 | val index = it.getColumnIndex("signature") | 314 | val index = it.getColumnIndex("signature") |
| 292 | if (index < 0) return | 315 | if (index < 0) return |
| 293 | val npub = it.getString(index) | 316 | val pubkey = it.getString(index) |
| 294 | } | 317 | } |
| 295 | ``` | 318 | ``` |
| 296 | 319 | ||
| @@ -300,7 +323,7 @@ If the user chose to always reject the event, signer application will return the | |||
| 300 | ```kotlin | 323 | ```kotlin |
| 301 | val result = context.contentResolver.query( | 324 | val result = context.contentResolver.query( |
| 302 | Uri.parse("content://com.example.signer.SIGN_EVENT"), | 325 | Uri.parse("content://com.example.signer.SIGN_EVENT"), |
| 303 | listOf("$eventJson", "", "${logged_in_user_npub}"), | 326 | listOf("$eventJson", "", "${logged_in_user_pubkey}"), |
| 304 | null, | 327 | null, |
| 305 | null, | 328 | null, |
| 306 | null | 329 | null |
| @@ -326,7 +349,7 @@ If the user chose to always reject the event, signer application will return the | |||
| 326 | ```kotlin | 349 | ```kotlin |
| 327 | val result = context.contentResolver.query( | 350 | val result = context.contentResolver.query( |
| 328 | Uri.parse("content://com.example.signer.NIP04_ENCRYPT"), | 351 | Uri.parse("content://com.example.signer.NIP04_ENCRYPT"), |
| 329 | listOf("$plainText", "${hex_pub_key}", "${logged_in_user_npub}"), | 352 | listOf("$plainText", "${hex_pub_key}", "${logged_in_user_pubkey}"), |
| 330 | null, | 353 | null, |
| 331 | null, | 354 | null, |
| 332 | null | 355 | null |
| @@ -350,7 +373,7 @@ If the user chose to always reject the event, signer application will return the | |||
| 350 | ```kotlin | 373 | ```kotlin |
| 351 | val result = context.contentResolver.query( | 374 | val result = context.contentResolver.query( |
| 352 | Uri.parse("content://com.example.signer.NIP44_ENCRYPT"), | 375 | Uri.parse("content://com.example.signer.NIP44_ENCRYPT"), |
| 353 | listOf("$plainText", "${hex_pub_key}", "${logged_in_user_npub}"), | 376 | listOf("$plainText", "${hex_pub_key}", "${logged_in_user_pubkey}"), |
| 354 | null, | 377 | null, |
| 355 | null, | 378 | null, |
| 356 | null | 379 | null |
| @@ -374,7 +397,7 @@ If the user chose to always reject the event, signer application will return the | |||
| 374 | ```kotlin | 397 | ```kotlin |
| 375 | val result = context.contentResolver.query( | 398 | val result = context.contentResolver.query( |
| 376 | Uri.parse("content://com.example.signer.NIP04_DECRYPT"), | 399 | Uri.parse("content://com.example.signer.NIP04_DECRYPT"), |
| 377 | listOf("$encryptedText", "${hex_pub_key}", "${logged_in_user_npub}"), | 400 | listOf("$encryptedText", "${hex_pub_key}", "${logged_in_user_pubkey}"), |
| 378 | null, | 401 | null, |
| 379 | null, | 402 | null, |
| 380 | null | 403 | null |
| @@ -398,7 +421,7 @@ If the user chose to always reject the event, signer application will return the | |||
| 398 | ```kotlin | 421 | ```kotlin |
| 399 | val result = context.contentResolver.query( | 422 | val result = context.contentResolver.query( |
| 400 | Uri.parse("content://com.example.signer.NIP44_DECRYPT"), | 423 | Uri.parse("content://com.example.signer.NIP44_DECRYPT"), |
| 401 | listOf("$encryptedText", "${hex_pub_key}", "${logged_in_user_npub}"), | 424 | listOf("$encryptedText", "${hex_pub_key}", "${logged_in_user_pubkey}"), |
| 402 | null, | 425 | null, |
| 403 | null, | 426 | null, |
| 404 | null | 427 | null |
| @@ -416,13 +439,37 @@ If the user chose to always reject the event, signer application will return the | |||
| 416 | } | 439 | } |
| 417 | ``` | 440 | ``` |
| 418 | 441 | ||
| 442 | - **get_relays** | ||
| 443 | - params: | ||
| 444 | |||
| 445 | ```kotlin | ||
| 446 | val result = context.contentResolver.query( | ||
| 447 | Uri.parse("content://com.example.signer.GET_RELAYS"), | ||
| 448 | listOf("${logged_in_user_pubkey}"), | ||
| 449 | null, | ||
| 450 | null, | ||
| 451 | null | ||
| 452 | ) | ||
| 453 | ``` | ||
| 454 | - result: | ||
| 455 | - Will return the **signature** column | ||
| 456 | |||
| 457 | ```kotlin | ||
| 458 | if (result == null) return | ||
| 459 | |||
| 460 | if (result.moveToFirst()) { | ||
| 461 | val index = it.getColumnIndex("signature") | ||
| 462 | val relayJsonText = it.getString(index) | ||
| 463 | } | ||
| 464 | ``` | ||
| 465 | |||
| 419 | - **decrypt_zap_event** | 466 | - **decrypt_zap_event** |
| 420 | - params: | 467 | - params: |
| 421 | 468 | ||
| 422 | ```kotlin | 469 | ```kotlin |
| 423 | val result = context.contentResolver.query( | 470 | val result = context.contentResolver.query( |
| 424 | Uri.parse("content://com.example.signer.DECRYPT_ZAP_EVENT"), | 471 | Uri.parse("content://com.example.signer.DECRYPT_ZAP_EVENT"), |
| 425 | listOf("$eventJson", "", "${logged_in_user_npub}"), | 472 | listOf("$eventJson", "", "${logged_in_user_pubkey}"), |
| 426 | null, | 473 | null, |
| 427 | null, | 474 | null, |
| 428 | null | 475 | null |
| @@ -472,28 +519,35 @@ Android intents and browser urls have limitations, so if you are using the `retu | |||
| 472 | - params: | 519 | - params: |
| 473 | 520 | ||
| 474 | ```js | 521 | ```js |
| 475 | window.href = `nostrsigner:${plainText}?pubKey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip04_encrypt&callbackUrl=https://example.com/?event=`; | 522 | window.href = `nostrsigner:${plainText}?pubkey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip04_encrypt&callbackUrl=https://example.com/?event=`; |
| 476 | ``` | 523 | ``` |
| 477 | 524 | ||
| 478 | - **nip44_encrypt** | 525 | - **nip44_encrypt** |
| 479 | - params: | 526 | - params: |
| 480 | 527 | ||
| 481 | ```js | 528 | ```js |
| 482 | window.href = `nostrsigner:${plainText}?pubKey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip44_encrypt&callbackUrl=https://example.com/?event=`; | 529 | window.href = `nostrsigner:${plainText}?pubkey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip44_encrypt&callbackUrl=https://example.com/?event=`; |
| 483 | ``` | 530 | ``` |
| 484 | 531 | ||
| 485 | - **nip04_decrypt** | 532 | - **nip04_decrypt** |
| 486 | - params: | 533 | - params: |
| 487 | 534 | ||
| 488 | ```js | 535 | ```js |
| 489 | window.href = `nostrsigner:${encryptedText}?pubKey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip04_decrypt&callbackUrl=https://example.com/?event=`; | 536 | window.href = `nostrsigner:${encryptedText}?pubkey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip04_decrypt&callbackUrl=https://example.com/?event=`; |
| 490 | ``` | 537 | ``` |
| 491 | 538 | ||
| 492 | - **nip44_decrypt** | 539 | - **nip44_decrypt** |
| 493 | - params: | 540 | - params: |
| 494 | 541 | ||
| 495 | ```js | 542 | ```js |
| 496 | window.href = `nostrsigner:${encryptedText}?pubKey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip44_decrypt&callbackUrl=https://example.com/?event=`; | 543 | window.href = `nostrsigner:${encryptedText}?pubkey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip44_decrypt&callbackUrl=https://example.com/?event=`; |
| 544 | ``` | ||
| 545 | |||
| 546 | - **get_relays** | ||
| 547 | - params: | ||
| 548 | |||
| 549 | ```js | ||
| 550 | window.href = `nostrsigner:?compressionType=none&returnType=signature&type=get_relays&callbackUrl=https://example.com/?event=`; | ||
| 497 | ``` | 551 | ``` |
| 498 | 552 | ||
| 499 | - **decrypt_zap_event** | 553 | - **decrypt_zap_event** |
| @@ -20,21 +20,60 @@ The format uses an _addressable event_ kind `34235` for horizontal videos and `3 | |||
| 20 | 20 | ||
| 21 | The `.content` of these events is a summary or description on the video content. | 21 | The `.content` of these events is a summary or description on the video content. |
| 22 | 22 | ||
| 23 | The list of tags are as follows: | 23 | The primary source of video information is the `imeta` tags which is defined in [NIP-92](92.md) |
| 24 | * `d` (required) universally unique identifier (UUID). Generated by the client creating the video event. | 24 | |
| 25 | * `url` (required) the url to the video file | 25 | Each `imeta` tag can be used to specify a variant of the video by the `dim` & `m` properties. |
| 26 | * `m` a string indicating the data type of the file. The [MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) format must be used, and they should be lowercase. | 26 | |
| 27 | Example: | ||
| 28 | ```json | ||
| 29 | [ | ||
| 30 | ["imeta", | ||
| 31 | "dim 1920x1080", | ||
| 32 | "url https://myvideo.com/1080/12345.mp4", | ||
| 33 | "x 3093509d1e0bc604ff60cb9286f4cd7c781553bc8991937befaacfdc28ec5cdc", | ||
| 34 | "m video/mp4", | ||
| 35 | "image https://myvideo.com/1080/12345.jpg", | ||
| 36 | "image https://myotherserver.com/1080/12345.jpg", | ||
| 37 | "fallback https://myotherserver.com/1080/12345.mp4", | ||
| 38 | "fallback https://andanotherserver.com/1080/12345.mp4", | ||
| 39 | "service nip96", | ||
| 40 | ], | ||
| 41 | ["imeta", | ||
| 42 | "dim 1280x720", | ||
| 43 | "url https://myvideo.com/720/12345.mp4", | ||
| 44 | "x e1d4f808dae475ed32fb23ce52ef8ac82e3cc760702fca10d62d382d2da3697d", | ||
| 45 | "m video/mp4", | ||
| 46 | "image https://myvideo.com/720/12345.jpg", | ||
| 47 | "image https://myotherserver.com/720/12345.jpg", | ||
| 48 | "fallback https://myotherserver.com/720/12345.mp4", | ||
| 49 | "fallback https://andanotherserver.com/720/12345.mp4", | ||
| 50 | "service nip96", | ||
| 51 | ], | ||
| 52 | ["imeta", | ||
| 53 | "dim 1280x720", | ||
| 54 | "url https://myvideo.com/720/12345.m3u8", | ||
| 55 | "x 704e720af2697f5d6a198ad377789d462054b6e8d790f8a3903afbc1e044014f", | ||
| 56 | "m application/x-mpegURL", | ||
| 57 | "image https://myvideo.com/720/12345.jpg", | ||
| 58 | "image https://myotherserver.com/720/12345.jpg", | ||
| 59 | "fallback https://myotherserver.com/720/12345.m3u8", | ||
| 60 | "fallback https://andanotherserver.com/720/12345.m3u8", | ||
| 61 | "service nip96", | ||
| 62 | ], | ||
| 63 | ] | ||
| 64 | ``` | ||
| 65 | |||
| 66 | Where `url` is the primary server url and `fallback` are other servers hosting the same file, both `url` and `fallback` should be weighted equally and clients are recommended to use any of the provided video urls. | ||
| 67 | |||
| 68 | The `image` tag contains a preview image (at the same resolution). Multiple `image` tags may be used to specify fallback copies in the same way `fallback` is used for `url`. | ||
| 69 | |||
| 70 | Additionally `service nip96` may be included to allow clients to search the authors NIP-96 server list to find the file using the hash. | ||
| 71 | |||
| 72 | ### Other tags: | ||
| 27 | * `title` (required) title of the video | 73 | * `title` (required) title of the video |
| 28 | * `"published_at"`, for the timestamp in unix seconds (stringified) of the first time the video was published | 74 | * `published_at`, for the timestamp in unix seconds (stringified) of the first time the video was published |
| 29 | * `x` containing the SHA-256 hexencoded string of the file. | ||
| 30 | * `size` (optional) size of file in bytes | ||
| 31 | * `dim` (optional) size of file in pixels in the form `<width>x<height>` | ||
| 32 | * `duration` (optional) video duration in seconds | 75 | * `duration` (optional) video duration in seconds |
| 33 | * `magnet` (optional) URI to magnet file | ||
| 34 | * `i` (optional) torrent infohash | ||
| 35 | * `text-track` (optional, repeated) link to WebVTT file for video, type of supplementary information (captions/subtitles/chapters/metadata), optional language code | 76 | * `text-track` (optional, repeated) link to WebVTT file for video, type of supplementary information (captions/subtitles/chapters/metadata), optional language code |
| 36 | * `thumb` (optional) url of thumbnail with same aspect ratio | ||
| 37 | * `image` (optional) url of preview image with same dimensions | ||
| 38 | * `content-warning` (optional) warning about content of NSFW video | 77 | * `content-warning` (optional) warning about content of NSFW video |
| 39 | * `alt` (optional) description for accessibility | 78 | * `alt` (optional) description for accessibility |
| 40 | * `segment` (optional, repeated) start timestamp in format `HH:MM:SS.sss`, end timestamp in format `HH:MM:SS.sss`, chapter/segment title, chapter thumbnail-url | 79 | * `segment` (optional, repeated) start timestamp in format `HH:MM:SS.sss`, end timestamp in format `HH:MM:SS.sss`, chapter/segment title, chapter thumbnail-url |
| @@ -53,19 +92,23 @@ The list of tags are as follows: | |||
| 53 | ["d", "<UUID>"], | 92 | ["d", "<UUID>"], |
| 54 | 93 | ||
| 55 | ["title", "<title of video>"], | 94 | ["title", "<title of video>"], |
| 56 | ["thumb", "<thumbnail image for video>"], | ||
| 57 | ["published_at", "<unix timestamp>"], | 95 | ["published_at", "<unix timestamp>"], |
| 58 | ["alt", <description>], | 96 | ["alt", <description>], |
| 59 | 97 | ||
| 60 | // Video Data | 98 | // Video Data |
| 61 | ["url",<string with URI of file>], | 99 | ["imeta", |
| 62 | ["m", <MIME type>], | 100 | "dim 1920x1080", |
| 63 | ["x",<Hash SHA-256>], | 101 | "url https://myvideo.com/1080/12345.mp4", |
| 64 | ["size", <size of file in bytes>], | 102 | "x 3093509d1e0bc604ff60cb9286f4cd7c781553bc8991937befaacfdc28ec5cdc", |
| 103 | "m video/mp4", | ||
| 104 | "image https://myvideo.com/1080/12345.jpg", | ||
| 105 | "image https://myotherserver.com/1080/12345.jpg", | ||
| 106 | "fallback https://myotherserver.com/1080/12345.mp4", | ||
| 107 | "fallback https://andanotherserver.com/1080/12345.mp4", | ||
| 108 | "service nip96", | ||
| 109 | ], | ||
| 110 | |||
| 65 | ["duration", <duration of video in seconds>], | 111 | ["duration", <duration of video in seconds>], |
| 66 | ["dim", <size of file in pixels>], | ||
| 67 | ["magnet",<magnet URI> ], | ||
| 68 | ["i",<torrent infohash>], | ||
| 69 | ["text-track", "<encoded `kind 6000` event>", "<recommended relay urls>"], | 112 | ["text-track", "<encoded `kind 6000` event>", "<recommended relay urls>"], |
| 70 | ["content-warning", "<reason>"], | 113 | ["content-warning", "<reason>"], |
| 71 | ["segment", <start>, <end>, "<title>", "<thumbnail URL>"], | 114 | ["segment", <start>, <end>, "<title>", "<thumbnail URL>"], |
| @@ -83,36 +126,4 @@ The list of tags are as follows: | |||
| 83 | ["r", "<url>"] | 126 | ["r", "<url>"] |
| 84 | ] | 127 | ] |
| 85 | } | 128 | } |
| 86 | ``` | 129 | ``` \ No newline at end of file |
| 87 | |||
| 88 | ## Video View | ||
| 89 | |||
| 90 | A video event view is a response to a video event to track a user's view or progress viewing the video. | ||
| 91 | |||
| 92 | ### Format | ||
| 93 | |||
| 94 | The format uses an _addressable event_ kind `34237`. | ||
| 95 | |||
| 96 | The `.content` of these events is optional and could be a free-form note that acts like a bookmark for the user. | ||
| 97 | |||
| 98 | The list of tags are as follows: | ||
| 99 | * `a` (required) reference tag to kind `34235` or `34236` video event being viewed | ||
| 100 | * `d` (required) same as `a` reference tag value | ||
| 101 | * `viewed` (optional, repeated) timestamp of the user's start time in seconds, timestamp of the user's end time in seconds | ||
| 102 | |||
| 103 | |||
| 104 | ```json | ||
| 105 | { | ||
| 106 | "id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>, | ||
| 107 | "pubkey": <32-bytes lowercase hex-encoded public key of the event creator>, | ||
| 108 | "created_at": <Unix timestamp in seconds>, | ||
| 109 | "kind": 34237, | ||
| 110 | "content": "<note>", | ||
| 111 | "tags": [ | ||
| 112 | ["a", "<34235 | 34236>:<video event author pubkey>:<d-identifier of video event>", "<optional relay url>"], | ||
| 113 | ["e", "<event-id", "<relay-url>"] | ||
| 114 | ["d", "<34235 | 34236>:<video event author pubkey>:<d-identifier of video event>"], | ||
| 115 | ["viewed", <start>, <end>], | ||
| 116 | ] | ||
| 117 | } | ||
| 118 | ``` | ||
| @@ -26,6 +26,7 @@ This NIP specifies the use of the `1063` event type, having in `content` a descr | |||
| 26 | * `summary` (optional) text excerpt | 26 | * `summary` (optional) text excerpt |
| 27 | * `alt` (optional) description for accessibility | 27 | * `alt` (optional) description for accessibility |
| 28 | * `fallback` (optional) zero or more fallback file sources in case `url` fails | 28 | * `fallback` (optional) zero or more fallback file sources in case `url` fails |
| 29 | * `service` (optional) service type which is serving the file (eg. [NIP-96](96.md)) | ||
| 29 | 30 | ||
| 30 | ```jsonc | 31 | ```jsonc |
| 31 | { | 32 | { |
| @@ -33,15 +34,15 @@ This NIP specifies the use of the `1063` event type, having in `content` a descr | |||
| 33 | "tags": [ | 34 | "tags": [ |
| 34 | ["url",<string with URI of file>], | 35 | ["url",<string with URI of file>], |
| 35 | ["m", <MIME type>], | 36 | ["m", <MIME type>], |
| 36 | ["x",<Hash SHA-256>], | 37 | ["x", <Hash SHA-256>], |
| 37 | ["ox",<Hash SHA-256>], | 38 | ["ox", <Hash SHA-256>], |
| 38 | ["size", <size of file in bytes>], | 39 | ["size", <size of file in bytes>], |
| 39 | ["dim", <size of file in pixels>], | 40 | ["dim", <size of file in pixels>], |
| 40 | ["magnet",<magnet URI> ], | 41 | ["magnet", <magnet URI> ], |
| 41 | ["i",<torrent infohash>], | 42 | ["i", <torrent infohash>], |
| 42 | ["blurhash", <value>], | 43 | ["blurhash", <value>], |
| 43 | ["thumb", <string with thumbnail URI>], | 44 | ["thumb", <string with thumbnail URI>, <Hash SHA-256>], |
| 44 | ["image", <string with preview URI>], | 45 | ["image", <string with preview URI>, <Hash SHA-256>], |
| 45 | ["summary", <excerpt>], | 46 | ["summary", <excerpt>], |
| 46 | ["alt", <description>] | 47 | ["alt", <description>] |
| 47 | ], | 48 | ], |
| @@ -26,7 +26,7 @@ The `.pubkey` field of these events are treated as the party creating the listin | |||
| 26 | 26 | ||
| 27 | ### Metadata | 27 | ### Metadata |
| 28 | 28 | ||
| 29 | - For "tags"/"hashtags" (i.e. categories or keywords of relevance for the listing) the `"t"` event tag should be used, as per [NIP-12](12.md). | 29 | - For "tags"/"hashtags" (i.e. categories or keywords of relevance for the listing) the `"t"` event tag should be used. |
| 30 | - For images, whether included in the markdown content or not, clients SHOULD use `image` tags as described in [NIP-58](58.md). This allows clients to display images in carousel format more easily. | 30 | - For images, whether included in the markdown content or not, clients SHOULD use `image` tags as described in [NIP-58](58.md). This allows clients to display images in carousel format more easily. |
| 31 | 31 | ||
| 32 | The following tags, used for structured metadata, are standardized and SHOULD be included. Other tags may be added as necessary. | 32 | The following tags, used for structured metadata, are standardized and SHOULD be included. Other tags may be added as necessary. |
diff --git a/BREAKING.md b/BREAKING.md index 83b104b..aba5b83 100644 --- a/BREAKING.md +++ b/BREAKING.md | |||
| @@ -5,6 +5,7 @@ reverse chronological order. | |||
| 5 | 5 | ||
| 6 | | Date | Commit | NIP | Change | | 6 | | Date | Commit | NIP | Change | |
| 7 | | ----------- | --------- | -------- | ------ | | 7 | | ----------- | --------- | -------- | ------ | |
| 8 | | 2024-10-07 | [7bb8997b](https://github.com/nostr-protocol/nips/commit/7bb8997b) | [NIP-55](55.md) | some fields and passing data were changed | | ||
| 8 | | 2024-08-18 | [3aff37bd](https://github.com/nostr-protocol/nips/commit/3aff37bd) | [NIP-54](54.md) | content should be Asciidoc | | 9 | | 2024-08-18 | [3aff37bd](https://github.com/nostr-protocol/nips/commit/3aff37bd) | [NIP-54](54.md) | content should be Asciidoc | |
| 9 | | 2024-07-31 | [3ea2f1a4](https://github.com/nostr-protocol/nips/commit/3ea2f1a4) | [NIP-45](45.md) | [444ad28d](https://github.com/nostr-protocol/nips/commit/444ad28d) was reverted | | 10 | | 2024-07-31 | [3ea2f1a4](https://github.com/nostr-protocol/nips/commit/3ea2f1a4) | [NIP-45](45.md) | [444ad28d](https://github.com/nostr-protocol/nips/commit/444ad28d) was reverted | |
| 10 | | 2024-07-30 | [444ad28d](https://github.com/nostr-protocol/nips/commit/444ad28d) | [NIP-45](45.md) | NIP-45 was deprecated | | 11 | | 2024-07-30 | [444ad28d](https://github.com/nostr-protocol/nips/commit/444ad28d) | [NIP-45](45.md) | NIP-45 was deprecated | |
| @@ -191,12 +191,14 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | |||
| 191 | | `30078` | Application-specific Data | [78](78.md) | | 191 | | `30078` | Application-specific Data | [78](78.md) | |
| 192 | | `30311` | Live Event | [53](53.md) | | 192 | | `30311` | Live Event | [53](53.md) | |
| 193 | | `30315` | User Statuses | [38](38.md) | | 193 | | `30315` | User Statuses | [38](38.md) | |
| 194 | | `30388` | Slide Set | [Corny Chat][cornychat-slideset] | | ||
| 194 | | `30402` | Classified Listing | [99](99.md) | | 195 | | `30402` | Classified Listing | [99](99.md) | |
| 195 | | `30403` | Draft Classified Listing | [99](99.md) | | 196 | | `30403` | Draft Classified Listing | [99](99.md) | |
| 196 | | `30617` | Repository announcements | [34](34.md) | | 197 | | `30617` | Repository announcements | [34](34.md) | |
| 197 | | `30618` | Repository state announcements | [34](34.md) | | 198 | | `30618` | Repository state announcements | [34](34.md) | |
| 198 | | `30818` | Wiki article | [54](54.md) | | 199 | | `30818` | Wiki article | [54](54.md) | |
| 199 | | `30819` | Redirects | [54](54.md) | | 200 | | `30819` | Redirects | [54](54.md) | |
| 201 | | `31388` | Link Set | [Corny Chat][cornychat-linkset] | | ||
| 200 | | `31890` | Feed | [NUD: Custom Feeds][NUD: Custom Feeds] | | 202 | | `31890` | Feed | [NUD: Custom Feeds][NUD: Custom Feeds] | |
| 201 | | `31922` | Date-Based Calendar Event | [52](52.md) | | 203 | | `31922` | Date-Based Calendar Event | [52](52.md) | |
| 202 | | `31923` | Time-Based Calendar Event | [52](52.md) | | 204 | | `31923` | Time-Based Calendar Event | [52](52.md) | |
| @@ -213,6 +215,8 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | |||
| 213 | [NUD: Custom Feeds]: https://wikifreedia.xyz/cip-01/ | 215 | [NUD: Custom Feeds]: https://wikifreedia.xyz/cip-01/ |
| 214 | [nostrocket]: https://github.com/nostrocket/NIPS/blob/main/Problems.md | 216 | [nostrocket]: https://github.com/nostrocket/NIPS/blob/main/Problems.md |
| 215 | [lnpub]: https://github.com/shocknet/Lightning.Pub/blob/master/proto/autogenerated/client.md | 217 | [lnpub]: https://github.com/shocknet/Lightning.Pub/blob/master/proto/autogenerated/client.md |
| 218 | [cornychat-slideset]: https://cornychat.com/datatypes#kind30388slideset | ||
| 219 | [cornychat-linkset]: https://cornychat.com/datatypes#kind31388linkset | ||
| 216 | [joinstr]: https://gitlab.com/1440000bytes/joinstr/-/blob/main/NIP.md | 220 | [joinstr]: https://gitlab.com/1440000bytes/joinstr/-/blob/main/NIP.md |
| 217 | [NKBIP-01]: https://wikistr.com/nkbip-01 | 221 | [NKBIP-01]: https://wikistr.com/nkbip-01 |
| 218 | [NKBIP-02]: https://wikistr.com/nkbip-02 | 222 | [NKBIP-02]: https://wikistr.com/nkbip-02 |
| @@ -259,7 +263,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | |||
| 259 | | `l` | label, label namespace | -- | [32](32.md) | | 263 | | `l` | label, label namespace | -- | [32](32.md) | |
| 260 | | `L` | label namespace | -- | [32](32.md) | | 264 | | `L` | label namespace | -- | [32](32.md) | |
| 261 | | `m` | MIME type | -- | [94](94.md) | | 265 | | `m` | MIME type | -- | [94](94.md) | |
| 262 | | `q` | event id (hex) | relay URL | [18](18.md) | | 266 | | `q` | event id (hex) | relay URL, pubkey (hex) | [18](18.md) | |
| 263 | | `r` | a reference (URL, etc) | -- | [24](24.md), [25](25.md) | | 267 | | `r` | a reference (URL, etc) | -- | [24](24.md), [25](25.md) | |
| 264 | | `r` | relay url | marker | [65](65.md) | | 268 | | `r` | relay url | marker | [65](65.md) | |
| 265 | | `t` | hashtag | -- | [24](24.md), [34](34.md) | | 269 | | `t` | hashtag | -- | [24](24.md), [34](34.md) | |