Experiment to rebuild Diffuse using web applets.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 140 lines 3.7 kB view raw
1import * as URI from "uri-js"; 2 3import type { 4 Consult, 5 ConsultGrouping, 6 GroupConsult, 7 InputWorkerTasks, 8 Track, 9} from "@applets/core/types"; 10import { groupTracksPerScheme, initialConnections, provide } from "@scripts/common"; 11 12//////////////////////////////////////////// 13// SETUP 14//////////////////////////////////////////// 15const actions = { 16 consult, 17 contextualize, 18 groupConsult, 19 list, 20 resolve, 21}; 22 23const { connections, tasks } = provide({ 24 actions, 25 connections: initialConnections<InputWorkerTasks>(["file+local", "opensubsonic", "s3"]), 26 tasks: actions, 27}); 28 29export type Actions = typeof actions; 30export type Tasks = typeof tasks; 31 32function isSupportedScheme(scheme: string) { 33 return !!connections[scheme]; 34} 35 36//////////////////////////////////////////// 37// ACTIONS 38//////////////////////////////////////////// 39 40async function consult(fileUriOrScheme: string): Promise<Consult> { 41 const scheme = fileUriOrScheme.includes(":") 42 ? URI.parse(fileUriOrScheme).scheme || fileUriOrScheme 43 : fileUriOrScheme; 44 45 if (!isSupportedScheme(scheme)) { 46 return { supported: false, reason: "Unsupported scheme" }; 47 } 48 49 const conn = await connections[scheme].promise; 50 return conn.consult(fileUriOrScheme); 51} 52 53async function contextualize(tracks: Track[]) { 54 const groups = groupTracks(tracks); 55 const promises = Object.entries(groups).map(async ([scheme, tracksGroup]: [string, Track[]]) => { 56 if (!isSupportedScheme(scheme) || tracksGroup.length === 0) return; 57 const conn = await connections[scheme].promise; 58 await conn.contextualize(tracksGroup); 59 }); 60 61 await Promise.all(promises); 62} 63 64async function groupConsult(tracks: Track[]) { 65 const groups = groupTracksPerScheme(tracks); 66 67 const consultations: GroupConsult[] = await Promise.all( 68 Object.keys(groups).map(async (scheme) => { 69 if (!isSupportedScheme(scheme)) { 70 return { 71 [scheme]: { 72 available: false, 73 reason: "Unsupported scheme", 74 tracks: groups[scheme] || [], 75 }, 76 }; 77 } 78 79 const conn = await connections[scheme].promise; 80 const result = await conn.groupConsult(groups[scheme] || {}); 81 82 return result; 83 }), 84 ); 85 86 return consultations.reduce((acc: GroupConsult, c: GroupConsult) => { 87 return { ...acc, ...c }; 88 }, {}); 89} 90 91async function list(cachedTracks: Track[] = []) { 92 const groups = await groupConsult(cachedTracks); 93 94 Object.keys(connections).forEach((scheme) => { 95 if (!groups[scheme]) groups[scheme] = { available: true, tracks: [] }; 96 }); 97 98 const promises = Object.entries(groups).map( 99 async ([scheme, { available, tracks }]: [string, ConsultGrouping]) => { 100 if (!available) return tracks; 101 if (!isSupportedScheme(scheme)) return tracks; 102 const conn = await connections[scheme].promise; 103 return conn.list(tracks); 104 }, 105 ); 106 107 const nested = await Promise.all(promises); 108 const tracks = nested.flat(1); 109 110 return tracks; 111} 112 113async function resolve(args: { method: string; uri: string }) { 114 const scheme = args.uri.split(":", 1)[0]; 115 if (!isSupportedScheme(scheme)) return undefined; 116 117 try { 118 const conn = await connections[scheme].promise; 119 return await conn.resolve(args); 120 } catch (err) { 121 console.error(`[configuration/input] Resolve error for scheme '${scheme}'.`, err); 122 } 123} 124 125//////////////////////////////////////////// 126// 🛠️ 127//////////////////////////////////////////// 128 129function groupTracks(tracks: Track[]) { 130 const grouped = groupTracksPerScheme( 131 tracks, 132 Object.fromEntries( 133 Object.entries(connections).map(([k, _v]) => { 134 return [k, []]; 135 }), 136 ), 137 ); 138 139 return grouped; 140}