Update store.js

This commit is contained in:
Arhey 2023-03-07 03:05:48 +03:00
parent 07aee4b7f8
commit 6d818f2e04

View file

@ -1,5 +1,6 @@
import { writable, get } from 'svelte/store' import { writable, get } from 'svelte/store'
import { transliterate } from 'transliteration' import { Playlist, Link } from 'iptv-playlist-generator'
import sj from '@freearhey/search-js'
import _ from 'lodash' import _ from 'lodash'
export const query = writable('') export const query = writable('')
@ -7,57 +8,23 @@ export const hasQuery = writable(false)
export const channels = writable([]) export const channels = writable([])
export const countries = writable({}) export const countries = writable({})
export const filteredChannels = writable([]) export const filteredChannels = writable([])
export const selected = writable([])
export const downloadMode = writable(false)
export function search(_query) { let searchIndex = {}
const parts = _query.toLowerCase().match(/(".*?"|[^"\s]+)+(?=\s*|\s*$)/g) || [] export function search(q) {
const filters = [] console.log('.')
for (let value of parts) { if (!q) {
let field = '_key'
if (value.includes(':')) {
;[field, value] = value.split(':')
}
value = value.replace(/\"/g, '')
if (field && value) {
let numerical = ['streams', 'guides'].includes(field)
filters.push({ field, numerical, value })
}
}
if (!filters.length) {
hasQuery.set(false)
filteredChannels.set(get(channels)) filteredChannels.set(get(channels))
hasQuery.set(false)
return return
} }
const filtered = get(channels).filter(c => { if (searchIndex.search) {
let results = [] let results = searchIndex.search(q)
for (let f of filters) { filteredChannels.set(results)
if (!f.value) return false
if (f.numerical) {
if (f.value.startsWith('<')) {
results.push(c._searchable[f.field] < parseInt(f.value.replace('<', '')))
} else if (f.value.startsWith('>')) {
results.push(c._searchable[f.field] > parseInt(f.value.replace('>', '')))
} else {
results.push(c._searchable[f.field] === parseInt(f.value))
}
} else {
const regex = new RegExp(f.value.replaceAll(',', '|'), 'i')
// console.log(regex, c._searchable[f.field])
results.push(regex.test(c._searchable[f.field]))
}
}
return results.every(Boolean)
})
filteredChannels.set(filtered)
hasQuery.set(true) hasQuery.set(true)
}
console.log('.')
} }
export async function fetchChannels() { export async function fetchChannels() {
@ -66,7 +33,6 @@ export async function fetchChannels() {
countries.set(api.countries) countries.set(api.countries)
let _channels = api.channels.map(c => { let _channels = api.channels.map(c => {
c._raw = copy(c)
c._streams = api.streams[c.id] || [] c._streams = api.streams[c.id] || []
c._guides = api.guides[c.id] || [] c._guides = api.guides[c.id] || []
c._country = api.countries[c.country] c._country = api.countries[c.country]
@ -84,63 +50,17 @@ export async function fetchChannels() {
return { type, ...api.subdivisions[code] } return { type, ...api.subdivisions[code] }
} }
}) })
c._searchable = generateSearchable(c) c.is = c.closed || c.replaced_by ? 'closed' : 'active'
c.streams = c._streams.length
c.guides = c._guides.length
// c._searchable = generateSearchable(c)
return c return c
}) })
channels.set(_channels) channels.set(_channels)
filteredChannels.set(_channels) filteredChannels.set(_channels)
} searchIndex = sj.createIndex(_channels)
function generateSearchable(c) {
const searchable = {}
for (let key in c) {
if (key.startsWith('_')) continue
if (Array.isArray(c[key])) {
searchable[key] = c[key].map(v => v.toString().toLowerCase()).join(',')
} else {
searchable[key] =
c[key] !== undefined && c[key] !== null ? c[key].toString().toLowerCase() : ''
}
}
searchable.streams = c._streams.length
searchable.guides = c._guides.length
searchable.is = c.closed || c.replaced_by ? 'closed' : 'active'
searchable._key = generateKey(c)
return searchable
}
function generateKey(c) {
const data = Object.values(
_.pick(c, [
'id',
'name',
'alt_names',
'network',
'country',
'subdivision',
'city',
'broadcast_area',
'languages',
'categories',
'launched',
'closed',
'replaced_by'
])
)
const translit = c.alt_names ? transliterate(c.alt_names) : null
return [...data, translit]
.map(v => v || '')
.filter(v => v)
.join('|')
.toLowerCase()
}
function copy(value) {
return JSON.parse(JSON.stringify(value))
} }
export function setSearchParam(key, value) { export function setSearchParam(key, value) {
@ -220,3 +140,77 @@ async function loadAPI() {
return api return api
} }
function getGuides() {
let guides = {}
get(selected).forEach(channel => {
let guide = channel._guides.length ? channel._guides[0] : null
if (guide && !guides[guide.url]) {
guides[guide.url] = guide.url
}
})
return Object.values(guides)
}
function getStreams() {
let streams = []
get(selected).forEach(channel => {
channel._streams.forEach(stream => {
if (stream.status === 'error') return
stream.channel = channel
streams.push(stream)
})
})
const levels = { online: 1, blocked: 2, timeout: 3, error: 4, default: 5 }
streams = _.orderBy(
streams,
[
s => s.channel.id.toLowerCase(),
s => levels[s.status] || levels['default'],
'height',
'frame_rate',
'url'
],
['asc', 'asc', 'desc', 'desc', 'asc']
)
streams = _.uniqBy(streams, stream => stream.channel.id || _.uniqueId())
return streams
}
export function createPlaylist() {
const playlist = new Playlist()
let guides = getGuides()
playlist.header = { 'x-tvg-url': guides.sort().join(',') }
let streams = getStreams()
streams.forEach(stream => {
const link = new Link(stream.url)
link.title = stream.channel.name
link.attrs = {
'tvg-id': stream.channel.id,
'tvg-logo': stream.channel.logo,
'group-title': stream.channel._categories
.map(c => c.name)
.sort()
.join(';')
}
if (stream.user_agent) {
link.attrs['user-agent'] = stream.user_agent
link.vlcOpts['http-user-agent'] = stream.user_agent
}
if (stream.http_referrer) {
link.vlcOpts['http-referrer'] = stream.http_referrer
}
playlist.links.push(link)
})
return playlist
}