refactor for better message handling
This commit is contained in:
parent
5eb46e96c3
commit
d1ac7da1a6
7 changed files with 240 additions and 73 deletions
|
|
@ -1,14 +1,24 @@
|
|||
export class ErrorHandler {
|
||||
static handle(error: unknown, context: string) {
|
||||
console.error(`Error in ${context}:`, error)
|
||||
|
||||
if (error instanceof Error) {
|
||||
// Handle specific error types
|
||||
if (error.name === 'TimeoutError') {
|
||||
return 'Connection timed out. Please try again.'
|
||||
}
|
||||
}
|
||||
|
||||
return 'An unexpected error occurred'
|
||||
export class NostrError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public code: string,
|
||||
public context?: any
|
||||
) {
|
||||
super(message)
|
||||
this.name = 'NostrError'
|
||||
}
|
||||
}
|
||||
|
||||
export function handleNostrError(error: unknown) {
|
||||
if (error instanceof NostrError) {
|
||||
switch (error.code) {
|
||||
case 'CONNECTION_FAILED':
|
||||
return 'Failed to connect to relay. Please check your connection.'
|
||||
case 'DECRYPT_FAILED':
|
||||
return 'Failed to decrypt message.'
|
||||
default:
|
||||
return error.message
|
||||
}
|
||||
}
|
||||
return 'An unexpected error occurred'
|
||||
}
|
||||
53
src/lib/messages.ts
Normal file
53
src/lib/messages.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
export class MessageManager {
|
||||
private messages = new Map<string, DirectMessage[]>()
|
||||
private processedIds = new Set<string>()
|
||||
|
||||
constructor() {
|
||||
this.loadFromStorage()
|
||||
}
|
||||
|
||||
addMessage(pubkey: string, message: DirectMessage) {
|
||||
if (this.processedIds.has(message.id)) return false
|
||||
if (this.isDuplicate(pubkey, message)) return false
|
||||
|
||||
this.processedIds.add(message.id)
|
||||
const messages = [...(this.messages.get(pubkey) || []), message]
|
||||
messages.sort((a, b) => a.created_at - b.created_at)
|
||||
this.messages.set(pubkey, messages)
|
||||
this.saveToStorage()
|
||||
return true
|
||||
}
|
||||
|
||||
private isDuplicate(pubkey: string, message: DirectMessage) {
|
||||
const existing = this.messages.get(pubkey) || []
|
||||
return existing.some(msg =>
|
||||
msg.content === message.content &&
|
||||
Math.abs(msg.created_at - message.created_at) < 1
|
||||
)
|
||||
}
|
||||
|
||||
private loadFromStorage() {
|
||||
try {
|
||||
const stored = localStorage.getItem('nostr_messages')
|
||||
if (stored) {
|
||||
this.messages = new Map(JSON.parse(stored))
|
||||
this.messages.forEach(msgs =>
|
||||
msgs.forEach(msg => this.processedIds.add(msg.id))
|
||||
)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load messages:', err)
|
||||
}
|
||||
}
|
||||
|
||||
private saveToStorage() {
|
||||
try {
|
||||
localStorage.setItem(
|
||||
'nostr_messages',
|
||||
JSON.stringify(Array.from(this.messages.entries()))
|
||||
)
|
||||
} catch (err) {
|
||||
console.error('Failed to save messages:', err)
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/lib/subscriptions.ts
Normal file
34
src/lib/subscriptions.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
export class SubscriptionManager {
|
||||
private currentSubs: any[] = []
|
||||
private isActive = false
|
||||
|
||||
async subscribe(relay: any, filters: any[], handlers: {
|
||||
onEvent: (event: NostrEvent) => void,
|
||||
onEose?: () => void
|
||||
}) {
|
||||
if (this.isActive) return
|
||||
|
||||
this.isActive = true
|
||||
const sub = relay.sub(filters)
|
||||
|
||||
sub.on('event', handlers.onEvent)
|
||||
if (handlers.onEose) {
|
||||
sub.on('eose', handlers.onEose)
|
||||
}
|
||||
|
||||
this.currentSubs.push(sub)
|
||||
return sub
|
||||
}
|
||||
|
||||
unsubscribe() {
|
||||
this.currentSubs.forEach(sub => {
|
||||
try {
|
||||
if (sub?.unsub) sub.unsub()
|
||||
} catch (err) {
|
||||
console.error('Failed to unsubscribe:', err)
|
||||
}
|
||||
})
|
||||
this.currentSubs = []
|
||||
this.isActive = false
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,24 @@
|
|||
// Create a new WebSocket manager class
|
||||
export class NostrWebSocketManager {
|
||||
private connections: Map<string, any> = new Map()
|
||||
private subscriptions: Map<string, any[]> = new Map()
|
||||
|
||||
async connect(url: string) {
|
||||
if (this.connections.has(url)) return this.connections.get(url)
|
||||
|
||||
private relayPool: any[] = []
|
||||
private subscriptions = new Map<string, any>()
|
||||
|
||||
async connect(relays: { url: string }[]) {
|
||||
// Close existing connections
|
||||
await this.disconnect()
|
||||
|
||||
// Connect to all relays
|
||||
this.relayPool = (await Promise.all(
|
||||
relays.map(relay => this.connectToRelay(relay.url))
|
||||
)).filter((relay): relay is any => relay !== null)
|
||||
|
||||
return this.relayPool.length > 0
|
||||
}
|
||||
|
||||
private async connectToRelay(url: string) {
|
||||
const relay = window.NostrTools.relayInit(url)
|
||||
try {
|
||||
await relay.connect()
|
||||
this.connections.set(url, relay)
|
||||
this.subscriptions.set(url, [])
|
||||
await withTimeout(relay.connect())
|
||||
return relay
|
||||
} catch (err) {
|
||||
console.error(`Failed to connect to ${url}:`, err)
|
||||
|
|
@ -18,18 +26,19 @@ export class NostrWebSocketManager {
|
|||
}
|
||||
}
|
||||
|
||||
addSubscription(url: string, sub: any) {
|
||||
const subs = this.subscriptions.get(url) || []
|
||||
subs.push(sub)
|
||||
this.subscriptions.set(url, subs)
|
||||
async publish(event: NostrEvent, relays: { url: string }[]) {
|
||||
return Promise.all(
|
||||
relays.map(({ url }) => this.publishToRelay(event, url))
|
||||
)
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
for (const [url, subs] of this.subscriptions.entries()) {
|
||||
subs.forEach(sub => sub.unsub?.())
|
||||
this.connections.get(url)?.close()
|
||||
}
|
||||
this.connections.clear()
|
||||
disconnect() {
|
||||
this.relayPool.forEach(relay => relay.close())
|
||||
this.relayPool = []
|
||||
this.subscriptions.clear()
|
||||
}
|
||||
|
||||
get isConnected() {
|
||||
return this.relayPool.length > 0
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue