Add support for TOML file data source

This commit is contained in:
Max Goodhart
2020-07-01 00:03:08 -07:00
parent cc14f2a17f
commit b2215aa42d
7 changed files with 135 additions and 64 deletions

View File

@@ -1,5 +1,10 @@
import { once } from 'events'
import { promises as fsPromises } from 'fs'
import { promisify } from 'util'
import { Repeater } from '@repeaterjs/repeater'
import TOML from '@iarna/toml'
import fetch from 'node-fetch'
import chokidar from 'chokidar'
const sleep = promisify(setTimeout)
@@ -7,14 +12,13 @@ function filterLive(data) {
return data.filter(({ status }) => status === 'Live' || status === 'Unknown')
}
export async function* pollPublicData() {
const publicDataURL = 'https://woke.net/api/streams.json'
export async function* pollDataURL(url) {
const refreshInterval = 5 * 1000
let lastData = []
while (true) {
let data = []
try {
const resp = await fetch(publicDataURL)
const resp = await fetch(url)
data = await resp.json()
} catch (err) {
console.warn('error loading stream data', err)
@@ -32,17 +36,52 @@ export async function* pollPublicData() {
}
}
export async function* watchDataFile(path) {
const watcher = chokidar.watch(path)
while (true) {
let data
try {
const text = await fsPromises.readFile(path)
data = TOML.parse(text)
} catch (err) {
console.warn('error reading data file', err)
}
if (data) {
yield data.streams || []
}
await once(watcher, 'change')
}
}
export async function* markDataSource(dataSource, name) {
for await (const streamList of dataSource) {
for (const s of streamList) {
s._dataSource = name
}
yield streamList
}
}
export async function* combineDataSources(dataSources) {
for await (const streamLists of Repeater.latest(dataSources)) {
yield [].concat(...streamLists)
}
}
export class StreamIDGenerator {
constructor(parent) {
this.idMap = new Map(parent ? parent.idMap : null)
this.idSet = new Set(this.idMap.values())
constructor() {
this.idMap = new Map()
this.idSet = new Set()
}
process(streams) {
const { idMap, idSet } = this
const localIdMap = new Map(idMap)
const localIdSet = new Set(idSet)
for (const stream of streams) {
const { link, source, label } = stream
if (!idMap.has(link)) {
const { link, source, label, _dataSource } = stream
if (!localIdMap.has(link)) {
let counter = 0
let newId
const normalizedText = (source || label || link)
@@ -54,11 +93,20 @@ export class StreamIDGenerator {
const counterPart = counter === 0 && textPart ? '' : counter
newId = `${textPart}${counterPart}`
counter++
} while (idSet.has(newId))
idMap.set(link, newId)
idSet.add(newId)
} while (localIdSet.has(newId))
localIdMap.set(link, newId)
localIdSet.add(newId)
// Custom stream ids are not persisted so that editing them doesn't create a bunch of unused ids.
const persistId = _dataSource !== 'custom'
if (persistId) {
idMap.set(link, newId)
idSet.add(newId)
}
}
stream._id = idMap.get(link)
stream._id = localIdMap.get(link)
}
return streams
}