function encodeRoutePart(value = '') { return encodeURIComponent(String(value || '').trim()); } function decodeRoutePart(value = '') { try { return decodeURIComponent(String(value || '')); } catch { return String(value || ''); } } const SHINE_ROUTE_SEGMENT = 'SHiNE'; export function normalizeLogin(value = '') { return String(value || '').trim().replace(/^@+/, ''); } export function extractLoginFromBlockchainName(value = '') { const raw = String(value || '').trim(); const match = raw.match(/^(.+)-\d+$/); if (!match) return normalizeLogin(raw); return normalizeLogin(String(match[1] || '')); } export function makeProfileRoute(login = '') { const clean = normalizeLogin(login); return clean ? `${SHINE_ROUTE_SEGMENT}/${encodeRoutePart(clean)}` : 'profile'; } export function makeProfileLinksRoute(login = '') { const clean = normalizeLogin(login); return clean ? `${SHINE_ROUTE_SEGMENT}/${encodeRoutePart(clean)}/links` : 'network/keep-history'; } export function makeProfileChannelsRoute(login = '', scope = 'all') { const clean = normalizeLogin(login); if (!clean) return 'channels/feed'; const normalizedScope = String(scope || '').trim().toLowerCase(); if (normalizedScope === 'owned') return `${SHINE_ROUTE_SEGMENT}/${encodeRoutePart(clean)}/channels/owned`; if (normalizedScope === 'following') return `${SHINE_ROUTE_SEGMENT}/${encodeRoutePart(clean)}/channels/following`; return `${SHINE_ROUTE_SEGMENT}/${encodeRoutePart(clean)}/channels`; } export function makeShineChannelRoute({ ownerLogin = '', ownerBlockchainName = '', channelName = '', messageBlockNumber = '' }) { const ownerBch = String(ownerBlockchainName || '').trim(); const chName = String(channelName || '').trim(); const msgNo = String(messageBlockNumber || '').trim(); if (!ownerBch || !chName) return ''; if (msgNo) return `${SHINE_ROUTE_SEGMENT}/${encodeRoutePart(ownerBch)}/${encodeRoutePart(chName)}/${encodeRoutePart(msgNo)}`; return `${SHINE_ROUTE_SEGMENT}/${encodeRoutePart(ownerBch)}/${encodeRoutePart(chName)}`; } export function makeShineChannelRootRoute({ ownerBlockchainName = '', channelRootBlockNumber = '', channelRootBlockHash = '' }) { const ownerBch = String(ownerBlockchainName || '').trim(); const rootNo = String(channelRootBlockNumber || '').trim(); const rootHash = String(channelRootBlockHash || '').trim(); if (!ownerBch || !rootNo || !rootHash) return ''; return `channel/${encodeRoutePart(ownerBch)}/${encodeRoutePart(rootNo)}/${encodeRoutePart(rootHash)}`; } export function makeShineChannelAboutRoute({ ownerBlockchainName = '', channelRootBlockNumber = '', channelRootBlockHash = '' }) { const base = makeShineChannelRootRoute({ ownerBlockchainName, channelRootBlockNumber, channelRootBlockHash }); return base ? `${base}/about` : ''; } export function makeShineChannelShortRoute({ ownerBlockchainName = '', channelName = '' }) { const ownerBch = String(ownerBlockchainName || '').trim(); const chName = String(channelName || '').trim(); if (!ownerBch || !chName) return ''; return `${encodeRoutePart(ownerBch)}/${encodeRoutePart(chName)}`; } export function makeShineMessageRoute({ ownerLogin = '', messageBlockchainName = '', messageBlockNumber = '' }) { const msgBch = String(messageBlockchainName || '').trim(); const msgNo = String(messageBlockNumber || '').trim(); if (!msgBch || !msgNo) return ''; return `${SHINE_ROUTE_SEGMENT}/${encodeRoutePart(msgBch)}/${encodeRoutePart(msgNo)}`; } export function parseShineRouteParts(segments = []) { const parts = Array.isArray(segments) ? segments.map((value) => String(value || '').trim()) : []; if (!parts.length) return null; if (String(parts[0] || '').toLowerCase() === SHINE_ROUTE_SEGMENT.toLowerCase()) { const entity = normalizeLogin(decodeRoutePart(parts[1] || '')); if (!entity) return null; return { entity, offset: 2, format: 'slash' }; } const raw = String(parts[0] || '').trim(); const legacyPrefix = `${SHINE_ROUTE_SEGMENT}.`; if (!raw.toLowerCase().startsWith(legacyPrefix.toLowerCase())) return null; return { entity: normalizeLogin(decodeRoutePart(raw.slice(legacyPrefix.length))), offset: 1, format: 'dot', }; }