You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
5.1 KiB
203 lines
5.1 KiB
// Helper functions and constants for the ORLY dashboard |
|
|
|
// Comprehensive kind names mapping |
|
export const KIND_NAMES = { |
|
0: "Profile Metadata", |
|
1: "Text Note", |
|
2: "Recommend Relay", |
|
3: "Contacts", |
|
4: "Encrypted DM", |
|
5: "Delete Request", |
|
6: "Repost", |
|
7: "Reaction", |
|
8: "Badge Award", |
|
16: "Generic Repost", |
|
40: "Channel Creation", |
|
41: "Channel Metadata", |
|
42: "Channel Message", |
|
43: "Channel Hide Message", |
|
44: "Channel Mute User", |
|
1063: "File Metadata", |
|
1311: "Live Chat Message", |
|
1984: "Reporting", |
|
1985: "Label", |
|
9734: "Zap Request", |
|
9735: "Zap Receipt", |
|
10000: "Mute List", |
|
10001: "Pin List", |
|
10002: "Relay List Metadata", |
|
10003: "Bookmark List", |
|
10004: "Communities List", |
|
10005: "Public Chats List", |
|
10006: "Blocked Relays List", |
|
10007: "Search Relays List", |
|
10009: "User Groups", |
|
10015: "Interests List", |
|
10030: "User Emoji List", |
|
13194: "Wallet Info", |
|
22242: "Client Auth", |
|
23194: "Wallet Request", |
|
23195: "Wallet Response", |
|
24133: "Nostr Connect", |
|
27235: "HTTP Auth", |
|
30000: "Categorized People List", |
|
30001: "Categorized Bookmarks", |
|
30002: "Categorized Relay List", |
|
30003: "Bookmark Sets", |
|
30004: "Curation Sets", |
|
30005: "Video Sets", |
|
30008: "Profile Badges", |
|
30009: "Badge Definition", |
|
30015: "Interest Sets", |
|
30017: "Create/Update Stall", |
|
30018: "Create/Update Product", |
|
30019: "Marketplace UI/UX", |
|
30020: "Product Sold As Auction", |
|
30023: "Long-form Content", |
|
30024: "Draft Long-form Content", |
|
30030: "Emoji Sets", |
|
30063: "Release Artifact Sets", |
|
30078: "Application-specific Data", |
|
30311: "Live Event", |
|
30315: "User Statuses", |
|
30388: "Slide Set", |
|
30402: "Classified Listing", |
|
30403: "Draft Classified Listing", |
|
30617: "Repository Announcement", |
|
30618: "Repository State Announcement", |
|
30818: "Wiki Article", |
|
30819: "Redirects", |
|
31922: "Date-Based Calendar Event", |
|
31923: "Time-Based Calendar Event", |
|
31924: "Calendar", |
|
31925: "Calendar Event RSVP", |
|
31989: "Handler Recommendation", |
|
31990: "Handler Information", |
|
34550: "Community Definition", |
|
34551: "Community Post Approval", |
|
}; |
|
|
|
// Get human-readable kind name |
|
export function getKindName(kind) { |
|
return KIND_NAMES[kind] || `Kind ${kind}`; |
|
} |
|
|
|
// Validate hex string (for pubkeys and event IDs) |
|
export function isValidHex(str, length = null) { |
|
if (!str || typeof str !== "string") return false; |
|
const hexRegex = /^[0-9a-fA-F]+$/; |
|
if (!hexRegex.test(str)) return false; |
|
if (length && str.length !== length) return false; |
|
return true; |
|
} |
|
|
|
// Validate pubkey (64 character hex) |
|
export function isValidPubkey(pubkey) { |
|
return isValidHex(pubkey, 64); |
|
} |
|
|
|
// Validate event ID (64 character hex) |
|
export function isValidEventId(eventId) { |
|
return isValidHex(eventId, 64); |
|
} |
|
|
|
// Validate tag name (single letter a-zA-Z) |
|
export function isValidTagName(tagName) { |
|
return /^[a-zA-Z]$/.test(tagName); |
|
} |
|
|
|
// Format timestamp to localized string |
|
export function formatTimestamp(timestamp) { |
|
return new Date(timestamp * 1000).toLocaleString(); |
|
} |
|
|
|
// Format timestamp for datetime-local input |
|
export function formatDateTimeLocal(timestamp) { |
|
const date = new Date(timestamp * 1000); |
|
const year = date.getFullYear(); |
|
const month = String(date.getMonth() + 1).padStart(2, '0'); |
|
const day = String(date.getDate()).padStart(2, '0'); |
|
const hours = String(date.getHours()).padStart(2, '0'); |
|
const minutes = String(date.getMinutes()).padStart(2, '0'); |
|
return `${year}-${month}-${day}T${hours}:${minutes}`; |
|
} |
|
|
|
// Parse datetime-local input to unix timestamp |
|
export function parseDateTimeLocal(dateTimeString) { |
|
return Math.floor(new Date(dateTimeString).getTime() / 1000); |
|
} |
|
|
|
// Truncate pubkey for display |
|
export function truncatePubkey(pubkey) { |
|
if (!pubkey) return ""; |
|
return pubkey.slice(0, 8) + "..." + pubkey.slice(-8); |
|
} |
|
|
|
// Truncate content for display |
|
export function truncateContent(content, maxLength = 100) { |
|
if (!content) return ""; |
|
return content.length > maxLength ? content.slice(0, maxLength) + "..." : content; |
|
} |
|
|
|
// Build Nostr filter from form data |
|
export function buildFilter({ |
|
searchText = null, |
|
kinds = [], |
|
authors = [], |
|
ids = [], |
|
tags = [], |
|
since = null, |
|
until = null, |
|
limit = null, |
|
}) { |
|
const filter = {}; |
|
|
|
if (searchText && searchText.trim()) { |
|
filter.search = searchText.trim(); |
|
} |
|
|
|
if (kinds && kinds.length > 0) { |
|
filter.kinds = kinds; |
|
} |
|
|
|
if (authors && authors.length > 0) { |
|
filter.authors = authors; |
|
} |
|
|
|
if (ids && ids.length > 0) { |
|
filter.ids = ids; |
|
} |
|
|
|
// Add tag filters (e.g., #e, #p, #a) |
|
if (tags && tags.length > 0) { |
|
tags.forEach(tag => { |
|
if (tag.name && tag.value) { |
|
const tagKey = `#${tag.name}`; |
|
if (!filter[tagKey]) { |
|
filter[tagKey] = []; |
|
} |
|
filter[tagKey].push(tag.value); |
|
} |
|
}); |
|
} |
|
|
|
if (since) { |
|
filter.since = since; |
|
} |
|
|
|
if (until) { |
|
filter.until = until; |
|
} |
|
|
|
if (limit && limit > 0) { |
|
filter.limit = limit; |
|
} |
|
|
|
return filter; |
|
} |
|
|
|
// Pretty print JSON with word breaking for long strings |
|
export function prettyPrintFilter(filter) { |
|
return JSON.stringify(filter, null, 2); |
|
} |
|
|
|
|