|
190 | 190 | </template> |
191 | 191 |
|
192 | 192 | <script lang="ts"> |
193 | | -import { generateSecretKey, getPublicKey, nip19 } from "nostr-tools"; |
| 193 | +import { |
| 194 | + generateSecretKey, |
| 195 | + getPublicKey, |
| 196 | + nip19, |
| 197 | + SimplePool, |
| 198 | + getEventHash, |
| 199 | +} from "nostr-tools"; |
| 200 | +import Dexie from "../../ts/indexDB"; |
| 201 | +import * as Y from "yjs"; |
| 202 | +import { IndexeddbPersistence } from "y-indexeddb"; |
| 203 | +import * as Utils from "../../ts/utils"; |
194 | 204 |
|
195 | 205 | export default { |
196 | 206 | name: "NostrModal", |
@@ -303,18 +313,116 @@ export default { |
303 | 313 | localStorage.removeItem("nostrPublicKey"); |
304 | 314 | } |
305 | 315 |
|
306 | | - // Here we would implement the actual Nostr publishing logic |
307 | | - // This would use the nostr-tools library to: |
308 | | - // 1. Creating a Nostr event with course link |
309 | | - // 2. Signing it with the user's private key (if available) |
310 | | - // 3. Publishing to relays |
311 | | -
|
312 | | - // For now, we'll just simulate success |
313 | | - setTimeout(() => { |
314 | | - this.step = "success"; |
315 | | - // Clear private key after successful publish for security |
316 | | - this.privateKey = ""; |
317 | | - }, 1000); |
| 316 | + // Loading indicator could be added here |
| 317 | + this.publishStatus = "loading"; |
| 318 | +
|
| 319 | + const database = new Dexie(); |
| 320 | + const meta = database.get(this.storageId); |
| 321 | + const config = Utils.loadConfig(); |
| 322 | +
|
| 323 | + const yDoc = new Y.Doc(); |
| 324 | + const provider = new IndexeddbPersistence(this.storageId, yDoc); |
| 325 | +
|
| 326 | + provider.on("synced", async (_: any) => { |
| 327 | + try { |
| 328 | + const metaData = await meta; |
| 329 | + const contentData = yDoc.getText(this.storageId).toJSON(); |
| 330 | +
|
| 331 | + console.log("Content Data:", contentData); |
| 332 | + console.log("Meta Data:", metaData); |
| 333 | +
|
| 334 | + // 1. Create a pool for relays |
| 335 | + const pool = new SimplePool(); |
| 336 | + const relays = [ |
| 337 | + "wss://relay.damus.io", |
| 338 | + "wss://relay.nostr.band", |
| 339 | + "wss://nos.lol", |
| 340 | + ]; |
| 341 | +
|
| 342 | + // 2. Decode the user's public key from npub format |
| 343 | + let pubkey; |
| 344 | + try { |
| 345 | + const decoded = nip19.decode(this.publicKey); |
| 346 | + pubkey = decoded.data; |
| 347 | + } catch (e) { |
| 348 | + console.error("Error decoding public key:", e); |
| 349 | + alert("Invalid public key format"); |
| 350 | + return; |
| 351 | + } |
| 352 | +
|
| 353 | + // 3. Prepare content |
| 354 | + const title = metaData?.title || "LiaScript Course"; |
| 355 | +
|
| 356 | + // Format content as markdown with header |
| 357 | + const fullContent = `# ${title}\n\n${contentData}`; |
| 358 | +
|
| 359 | + // 4. Create the event (NIP-33 parameterized replaceable event) |
| 360 | + const event = { |
| 361 | + kind: 30023, // Long-form content |
| 362 | + pubkey: pubkey, |
| 363 | + created_at: Math.floor(Date.now() / 1000), |
| 364 | + tags: [ |
| 365 | + ["d", this.storageId], // Use storageId as identifier |
| 366 | + ["title", title], |
| 367 | + ["summary", metaData?.description || "LiaScript course material"], |
| 368 | + ...this.tags.map((tag) => ["t", tag]), |
| 369 | + ], |
| 370 | + content: fullContent, |
| 371 | + }; |
| 372 | +
|
| 373 | + // 5. If user has provided private key, sign and publish |
| 374 | + if (this.privateKey) { |
| 375 | + try { |
| 376 | + // Decode private key |
| 377 | + const decoded = nip19.decode(this.privateKey); |
| 378 | + const privkey = decoded.data; |
| 379 | +
|
| 380 | + // Sign the event - updated approach for newer nostr-tools |
| 381 | + event.id = getEventHash(event); |
| 382 | + const signedEvent = signEvent(event, privkey); |
| 383 | +
|
| 384 | + // Publish to relays |
| 385 | + console.log("Publishing event:", signedEvent); |
| 386 | +
|
| 387 | + const pubs = pool.publish(relays, signedEvent); |
| 388 | +
|
| 389 | + // Wait for at least one successful publish |
| 390 | + await Promise.any(pubs); |
| 391 | +
|
| 392 | + // Create the naddr representation |
| 393 | + const naddr = nip19.naddrEncode({ |
| 394 | + kind: 30023, |
| 395 | + pubkey: pubkey, |
| 396 | + identifier: this.storageId, |
| 397 | + }); |
| 398 | +
|
| 399 | + console.log("Published as naddr:", naddr); |
| 400 | +
|
| 401 | + // Success! |
| 402 | + this.step = "success"; |
| 403 | + this.publishStatus = "success"; |
| 404 | +
|
| 405 | + // Clear private key after successful publish for security |
| 406 | + this.privateKey = ""; |
| 407 | + } catch (e) { |
| 408 | + console.error("Error publishing:", e); |
| 409 | + alert("Failed to publish to Nostr network. Please try again."); |
| 410 | + this.publishStatus = "failed"; |
| 411 | + } |
| 412 | + } else { |
| 413 | + alert("Please provide your private key to sign and publish the post."); |
| 414 | + this.publishStatus = null; |
| 415 | + } |
| 416 | + } catch (error) { |
| 417 | + console.error("Error processing data:", error); |
| 418 | + alert("Error processing document data."); |
| 419 | + this.publishStatus = "failed"; |
| 420 | + } finally { |
| 421 | + // Clean up |
| 422 | + provider.destroy(); |
| 423 | + yDoc.destroy(); |
| 424 | + } |
| 425 | + }); |
318 | 426 | }, |
319 | 427 | }, |
320 | 428 | }; |
|
0 commit comments