1- import 'websocket-polyfill'
2- import { SimplePool , nip19 } from 'nostr-tools'
1+ import WebSocket from 'ws'
32import { loadConfig } from './config.js'
43import { verifyEvent , verifyAnchor } from './verify.js'
54import { gitSync , getCurrentCommit , runPostSync } from './git.js'
65
76export async function startDaemon ( configPath ) {
87 const config = loadConfig ( configPath )
9- const pool = new SimplePool ( )
10-
118 const repoIds = Object . keys ( config . repos )
129
1310 console . log ( '[daemon] Starting nostr-git-sync' )
1411 console . log ( `[daemon] Watching ${ repoIds . length } repo(s): ${ repoIds . join ( ', ' ) } ` )
1512 console . log ( `[daemon] Relays: ${ config . relays . join ( ', ' ) } ` )
1613
17- // Subscribe to 30618 events for our repos
18- const sub = pool . subscribeMany (
19- config . relays ,
20- [ { kinds : [ 30618 ] , '#d' : repoIds } ] ,
21- {
22- onevent : async ( event ) => {
23- await handleEvent ( event , config , nip19 )
24- } ,
25- oneose : ( ) => {
26- console . log ( '[daemon] Caught up with relay history' )
27- }
28- }
29- )
14+ const sockets = [ ]
3015
31- console . log ( '[daemon] Subscribed, waiting for events...' )
16+ // Connect to each relay
17+ config . relays . forEach ( ( url , index ) => {
18+ connectToRelay ( url , index , repoIds , config , sockets )
19+ } )
3220
3321 // Keep alive
3422 process . on ( 'SIGINT' , ( ) => {
3523 console . log ( '\n[daemon] Shutting down...' )
36- sub . close ( )
24+ sockets . forEach ( ws => ws . close ( ) )
3725 process . exit ( 0 )
3826 } )
3927}
4028
41- async function handleEvent ( event , config , nip19 ) {
29+ function connectToRelay ( url , index , repoIds , config , sockets ) {
30+ const ws = new WebSocket ( url )
31+
32+ ws . on ( 'open' , ( ) => {
33+ console . log ( `[daemon] Connected to ${ url } ` )
34+ sockets . push ( ws )
35+
36+ // Subscribe to 30618 events for our repos
37+ const subscription = JSON . stringify ( [
38+ 'REQ' ,
39+ `git-sync-${ index } ` ,
40+ { kinds : [ 30618 ] , '#d' : repoIds }
41+ ] )
42+ ws . send ( subscription )
43+ } )
44+
45+ ws . on ( 'message' , async ( data ) => {
46+ try {
47+ const message = JSON . parse ( data . toString ( ) )
48+
49+ if ( message [ 0 ] === 'EVENT' && message [ 2 ] ) {
50+ await handleEvent ( message [ 2 ] , config )
51+ } else if ( message [ 0 ] === 'EOSE' ) {
52+ console . log ( `[daemon] Caught up with ${ url } ` )
53+ } else if ( message [ 0 ] === 'NOTICE' ) {
54+ console . log ( `[notice] ${ url } : ${ message [ 1 ] } ` )
55+ }
56+ } catch ( err ) {
57+ console . error ( '[daemon] Error parsing message:' , err . message )
58+ }
59+ } )
60+
61+ ws . on ( 'error' , ( err ) => {
62+ console . log ( `[daemon] Error from ${ url } : ${ err . message } ` )
63+ } )
64+
65+ ws . on ( 'close' , ( ) => {
66+ console . log ( `[daemon] Disconnected from ${ url } , reconnecting in 10s...` )
67+ const idx = sockets . indexOf ( ws )
68+ if ( idx > - 1 ) sockets . splice ( idx , 1 )
69+
70+ setTimeout ( ( ) => {
71+ connectToRelay ( url , index , repoIds , config , sockets )
72+ } , 10000 )
73+ } )
74+ }
75+
76+ async function handleEvent ( event , config ) {
4277 // Extract repo ID from d tag
4378 const dTag = event . tags . find ( t => t [ 0 ] === 'd' )
4479 if ( ! dTag ) return
@@ -48,7 +83,7 @@ async function handleEvent(event, config, nip19) {
4883 if ( ! repo ) return
4984
5085 console . log ( `\n[event] Received 30618 for ${ repoId } ` )
51- console . log ( `[event] From: ${ nip19 . npubEncode ( event . pubkey ) . slice ( 0 , 20 ) } ...` )
86+ console . log ( `[event] From: ${ event . pubkey . slice ( 0 , 16 ) } ...` )
5287
5388 // Find branch ref
5489 const refTag = event . tags . find ( t => t [ 0 ] . startsWith ( 'refs/heads/' ) )
@@ -69,7 +104,7 @@ async function handleEvent(event, config, nip19) {
69104 }
70105
71106 // Verify pubkey is trusted
72- const verification = verifyEvent ( event , repo , nip19 )
107+ const verification = verifyEvent ( event , repo )
73108 if ( ! verification . ok ) {
74109 console . log ( `[event] ✗ Rejected: ${ verification . reason } ` )
75110 return
@@ -78,8 +113,7 @@ async function handleEvent(event, config, nip19) {
78113
79114 // Optional: verify Blocktrails anchor
80115 if ( repo . requireAnchor ) {
81- const npub = nip19 . npubEncode ( event . pubkey )
82- const anchor = await verifyAnchor ( npub , commit )
116+ const anchor = await verifyAnchor ( event . pubkey , commit )
83117 if ( ! anchor . ok ) {
84118 console . log ( `[event] ✗ Anchor required but not found: ${ anchor . reason } ` )
85119 return
0 commit comments