Files
iptv/scripts/commands/report/create.ts

175 lines
5.9 KiB
TypeScript
Raw Normal View History

2025-04-16 20:54:55 +03:00
import { DataLoader, DataProcessor, IssueLoader, PlaylistParser } from '../../core'
2023-09-22 05:17:22 +03:00
import { Logger, Storage, Collection, Dictionary } from '@freearhey/core'
2025-04-16 20:54:55 +03:00
import { DataProcessorData } from '../../types/dataProcessor'
2023-09-17 04:08:50 +03:00
import { DATA_DIR, STREAMS_DIR } from '../../constants'
2025-04-16 20:54:55 +03:00
import { DataLoaderData } from '../../types/dataLoader'
import { Issue, Stream } from '../../models'
2023-09-15 18:40:35 +03:00
async function main() {
2023-09-17 04:08:50 +03:00
const logger = new Logger()
2025-04-16 20:54:55 +03:00
const issueLoader = new IssueLoader()
2025-03-29 11:39:46 +03:00
let report = new Collection()
2023-09-15 18:40:35 +03:00
2025-02-27 20:55:39 +03:00
logger.info('loading issues...')
2025-04-16 20:54:55 +03:00
const issues = await issueLoader.load()
2025-02-27 20:55:39 +03:00
2025-03-29 11:39:46 +03:00
logger.info('loading data from api...')
2025-04-16 20:54:55 +03:00
const processor = new DataProcessor()
2025-03-29 11:39:46 +03:00
const dataStorage = new Storage(DATA_DIR)
2025-04-16 20:54:55 +03:00
const dataLoader = new DataLoader({ storage: dataStorage })
const data: DataLoaderData = await dataLoader.load()
const {
channelsKeyById,
feedsGroupedByChannelId,
blocklistRecordsGroupedByChannelId
}: DataProcessorData = processor.process(data)
2025-03-29 11:39:46 +03:00
2025-02-27 20:55:39 +03:00
logger.info('loading streams...')
const streamsStorage = new Storage(STREAMS_DIR)
2025-03-29 11:39:46 +03:00
const parser = new PlaylistParser({
storage: streamsStorage,
2025-04-16 20:54:55 +03:00
channelsKeyById,
2025-03-29 11:39:46 +03:00
feedsGroupedByChannelId
})
2025-02-27 20:55:39 +03:00
const files = await streamsStorage.list('**/*.m3u')
const streams = await parser.parse(files)
const streamsGroupedByUrl = streams.groupBy((stream: Stream) => stream.url)
2025-03-29 11:39:46 +03:00
const streamsGroupedByChannelId = streams.groupBy((stream: Stream) => stream.channelId)
2025-04-16 20:54:55 +03:00
const streamsGroupedById = streams.groupBy((stream: Stream) => stream.getId())
2025-03-29 11:39:46 +03:00
2025-05-01 00:51:41 +03:00
logger.info('checking streams:remove requests...')
const removeRequests = issues.filter(issue =>
issue.labels.find((label: string) => label === 'streams:remove')
2025-03-29 11:39:46 +03:00
)
2025-05-01 00:51:41 +03:00
removeRequests.forEach((issue: Issue) => {
2025-05-02 05:58:55 +03:00
const streamUrls = issue.data.has('streamUrl') ? issue.data.getArray('streamUrl') : []
2025-03-29 11:39:46 +03:00
2025-05-01 00:51:41 +03:00
if (!streamUrls.length) {
2025-03-29 11:39:46 +03:00
const result = {
issueNumber: issue.number,
2025-05-01 00:51:41 +03:00
type: 'streams:remove',
2025-03-29 11:39:46 +03:00
streamId: undefined,
streamUrl: undefined,
status: 'missing_link'
}
2025-02-27 20:55:39 +03:00
2025-03-29 11:39:46 +03:00
report.add(result)
} else {
2025-05-01 00:51:41 +03:00
for (const streamUrl of streamUrls) {
2025-03-29 11:39:46 +03:00
const result = {
issueNumber: issue.number,
2025-05-01 00:51:41 +03:00
type: 'streams:remove',
2025-03-29 11:39:46 +03:00
streamId: undefined,
streamUrl: truncate(streamUrl),
status: 'pending'
}
2023-09-15 18:40:35 +03:00
2025-03-29 11:39:46 +03:00
if (streamsGroupedByUrl.missing(streamUrl)) {
result.status = 'wrong_link'
}
2023-09-15 18:40:35 +03:00
2025-03-29 11:39:46 +03:00
report.add(result)
}
}
})
2023-09-18 18:24:40 +03:00
logger.info('checking streams:add requests...')
2025-02-27 20:55:39 +03:00
const addRequests = issues.filter(issue => issue.labels.includes('streams:add'))
const addRequestsBuffer = new Dictionary()
2023-09-18 18:24:40 +03:00
addRequests.forEach((issue: Issue) => {
2025-03-29 11:39:46 +03:00
const streamId = issue.data.getString('streamId') || ''
const streamUrl = issue.data.getString('streamUrl') || ''
const [channelId] = streamId.split('@')
2023-09-15 18:40:35 +03:00
2025-03-29 11:39:46 +03:00
const result = {
2023-09-17 04:08:50 +03:00
issueNumber: issue.number,
2023-09-18 18:24:40 +03:00
type: 'streams:add',
2025-03-29 11:39:46 +03:00
streamId: streamId || undefined,
streamUrl: truncate(streamUrl),
2025-02-27 20:55:39 +03:00
status: 'pending'
2025-03-29 11:39:46 +03:00
}
2023-09-15 18:40:35 +03:00
2025-03-29 11:39:46 +03:00
if (!channelId) result.status = 'missing_id'
else if (!streamUrl) result.status = 'missing_link'
2025-04-16 20:54:55 +03:00
else if (blocklistRecordsGroupedByChannelId.has(channelId)) result.status = 'blocked'
else if (channelsKeyById.missing(channelId)) result.status = 'wrong_id'
2025-03-29 11:39:46 +03:00
else if (streamsGroupedByUrl.has(streamUrl)) result.status = 'on_playlist'
else if (addRequestsBuffer.has(streamUrl)) result.status = 'duplicate'
else result.status = 'pending'
2023-09-15 18:40:35 +03:00
2025-02-27 20:55:39 +03:00
addRequestsBuffer.set(streamUrl, true)
2023-09-15 18:40:35 +03:00
2025-03-29 11:39:46 +03:00
report.add(result)
2023-09-15 18:40:35 +03:00
})
2023-09-18 18:24:40 +03:00
logger.info('checking streams:edit requests...')
2025-03-29 11:39:46 +03:00
const editRequests = issues.filter(issue =>
issue.labels.find((label: string) => label === 'streams:edit')
)
2023-09-18 18:24:40 +03:00
editRequests.forEach((issue: Issue) => {
2025-03-29 11:39:46 +03:00
const streamId = issue.data.getString('streamId') || ''
const streamUrl = issue.data.getString('streamUrl') || ''
const [channelId] = streamId.split('@')
2023-09-18 18:24:40 +03:00
2025-03-29 11:39:46 +03:00
const result = {
2023-09-18 18:24:40 +03:00
issueNumber: issue.number,
type: 'streams:edit',
2025-03-29 11:39:46 +03:00
streamId: streamId || undefined,
streamUrl: truncate(streamUrl),
2025-02-27 20:55:39 +03:00
status: 'pending'
2025-03-29 11:39:46 +03:00
}
2025-02-27 20:55:39 +03:00
2025-03-29 11:39:46 +03:00
if (!streamUrl) result.status = 'missing_link'
else if (streamsGroupedByUrl.missing(streamUrl)) result.status = 'invalid_link'
2025-04-16 20:54:55 +03:00
else if (channelId && channelsKeyById.missing(channelId)) result.status = 'invalid_id'
2025-02-27 20:55:39 +03:00
2025-03-29 11:39:46 +03:00
report.add(result)
2025-02-27 20:55:39 +03:00
})
logger.info('checking channel search requests...')
const channelSearchRequests = issues.filter(issue =>
2025-03-29 11:39:46 +03:00
issue.labels.find((label: string) => label === 'channel search')
2025-02-27 20:55:39 +03:00
)
const channelSearchRequestsBuffer = new Dictionary()
channelSearchRequests.forEach((issue: Issue) => {
2025-03-29 11:39:46 +03:00
const streamId = issue.data.getString('channelId') || ''
2025-05-24 19:20:13 +03:00
const [channelId, feedId] = streamId.split('@')
2023-09-18 18:24:40 +03:00
2025-03-29 11:39:46 +03:00
const result = {
2023-09-18 18:24:40 +03:00
issueNumber: issue.number,
2025-02-27 20:55:39 +03:00
type: 'channel search',
2025-03-29 11:39:46 +03:00
streamId: streamId || undefined,
2025-02-27 20:55:39 +03:00
streamUrl: undefined,
status: 'pending'
2025-03-29 11:39:46 +03:00
}
2023-09-18 18:24:40 +03:00
2025-03-29 11:39:46 +03:00
if (!channelId) result.status = 'missing_id'
2025-04-16 20:54:55 +03:00
else if (channelsKeyById.missing(channelId)) result.status = 'invalid_id'
else if (channelSearchRequestsBuffer.has(streamId)) result.status = 'duplicate'
else if (blocklistRecordsGroupedByChannelId.has(channelId)) result.status = 'blocked'
else if (streamsGroupedById.has(streamId)) result.status = 'fulfilled'
2025-05-24 19:20:13 +03:00
else if (!feedId && streamsGroupedByChannelId.has(channelId)) result.status = 'fulfilled'
2025-02-27 22:05:31 +03:00
else {
2025-04-16 20:54:55 +03:00
const channelData = channelsKeyById.get(channelId)
2025-03-29 11:39:46 +03:00
if (channelData.length && channelData[0].closed) result.status = 'closed'
2025-02-27 22:05:31 +03:00
}
2025-02-27 20:55:39 +03:00
2025-04-16 20:54:55 +03:00
channelSearchRequestsBuffer.set(streamId, true)
2023-09-18 18:24:40 +03:00
2025-03-29 11:39:46 +03:00
report.add(result)
2023-09-18 18:24:40 +03:00
})
2025-02-27 20:55:39 +03:00
report = report.orderBy(item => item.issueNumber).filter(item => item.status !== 'pending')
2023-09-18 18:24:40 +03:00
2023-09-15 18:40:35 +03:00
console.table(report.all())
}
main()
2025-03-29 11:39:46 +03:00
function truncate(string: string, limit: number = 100) {
if (!string) return string
if (string.length < limit) return string
return string.slice(0, limit) + '...'
}