From e3c7a372f2793a9eacdf00bbc579a3eec0f54aa8 Mon Sep 17 00:00:00 2001 From: theofficialomega <30985701+BellezaEmporium@users.noreply.github.com> Date: Mon, 28 Jul 2025 22:28:48 +0200 Subject: [PATCH] stricter ESLint configuration, linebreak on stylistic per deprecation by ESLint, fixed changes. add attibutes to prevent blockade. --- .gitattributes | 2 + eslint.config.mjs | 112 +- package-lock.json | 45 + package.json | 1 + scripts/commands/channels/edit.ts | 432 +- scripts/commands/channels/parse.ts | 174 +- scripts/commands/channels/validate.ts | 184 +- scripts/commands/epg/grab.ts | 266 +- scripts/core/channelsParser.ts | 44 +- scripts/core/dataProcessor.ts | 111 +- scripts/core/grabber.ts | 210 +- scripts/core/guideManager.ts | 222 +- scripts/core/htmlTable.ts | 110 +- scripts/core/job.ts | 68 +- scripts/core/proxyParser.ts | 62 +- scripts/core/queue.ts | 90 +- scripts/core/queueCreator.ts | 126 +- scripts/functions/functions.ts | 154 +- scripts/models/channel.ts | 328 +- scripts/models/channelList.ts | 154 +- scripts/models/feed.ts | 248 +- scripts/models/guide.ts | 70 +- scripts/models/issue.ts | 48 +- scripts/models/logo.ts | 82 +- scripts/models/site.ts | 126 +- scripts/models/stream.ts | 116 +- scripts/types/channel.d.ts | 54 +- scripts/types/dataLoader.d.ts | 40 +- scripts/types/dataProcessor.d.ts | 32 +- scripts/types/feed.d.ts | 24 +- scripts/types/guide.d.ts | 16 +- scripts/types/logo.d.ts | 18 +- scripts/types/stream.d.ts | 20 +- sites/tvim.tv/tvim.tv.test.js | 82 +- sites/tvinsider.com/tvinsider.com.config.js | 254 +- sites/tvireland.ie/tvireland.ie.config.js | 198 +- sites/tvmusor.hu/tvmusor.hu.config.js | 162 +- sites/tvprofil.com/tvprofil.com.channels.xml | 11678 ++++++++-------- .../web.magentatv.de.config.js | 426 +- tests/commands/channels/lint.test.ts | 166 +- tests/commands/channels/validate.test.ts | 140 +- 41 files changed, 8471 insertions(+), 8424 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..f7cc30f0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Enforce the usage of CRLF in GitHub Actions per ESLint configuration. +* text eol=crlf \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs index 7d672612..7f8ffde6 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,55 +1,57 @@ -import typescriptEslint from '@typescript-eslint/eslint-plugin' -import globals from 'globals' -import tsParser from '@typescript-eslint/parser' -import path from 'node:path' -import { fileURLToPath } from 'node:url' -import js from '@eslint/js' -import { FlatCompat } from '@eslint/eslintrc' - -const __filename = fileURLToPath(import.meta.url) -const __dirname = path.dirname(__filename) -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all -}) - -export default [ - ...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'), - { - plugins: { - '@typescript-eslint': typescriptEslint - }, - - languageOptions: { - globals: { - ...globals.node, - ...globals.jest - }, - - parser: tsParser, - ecmaVersion: 'latest', - sourceType: 'module' - }, - - rules: { - '@typescript-eslint/no-require-imports': 'off', - '@typescript-eslint/no-var-requires': 'off', - 'no-case-declarations': 'off', - 'linebreak-style': ['error', process.env.CI ? 'unix' : 'windows'], - - quotes: [ - 'error', - 'single', - { - avoidEscape: true - } - ], - - semi: ['error', 'never'] - } - }, - { - ignores: ['tests/__data__/'] - } -] +import typescriptEslint from '@typescript-eslint/eslint-plugin' +import stylistic from '@stylistic/eslint-plugin' +import globals from 'globals' +import tsParser from '@typescript-eslint/parser' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import js from '@eslint/js' +import { FlatCompat } from '@eslint/eslintrc' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}) + +export default [ + ...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/strict', 'plugin:@typescript-eslint/stylistic', 'prettier'), + { + plugins: { + '@typescript-eslint': typescriptEslint, + '@stylistic': stylistic + }, + + languageOptions: { + globals: { + ...globals.node, + ...globals.jest + }, + + parser: tsParser, + ecmaVersion: 'latest', + sourceType: 'module' + }, + + rules: { + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/no-var-requires': 'off', + 'no-case-declarations': 'off', + '@stylistic/linebreak-style': ['error', 'windows'], + + quotes: [ + 'error', + 'single', + { + avoidEscape: true + } + ], + + semi: ['error', 'never'] + } + }, + { + ignores: ['tests/__data__/'] + } +] diff --git a/package-lock.json b/package-lock.json index 85708278..97f56541 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@octokit/core": "^7.0.3", "@octokit/plugin-paginate-rest": "^13.1.1", "@octokit/plugin-rest-endpoint-methods": "^16.0.0", + "@stylistic/eslint-plugin": "^5.2.2", "@swc/core": "^1.13.2", "@swc/jest": "^0.2.39", "@types/cli-progress": "^3.11.6", @@ -3146,6 +3147,50 @@ "@sinonjs/commons": "^3.0.1" } }, + "node_modules/@stylistic/eslint-plugin": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.2.2.tgz", + "integrity": "sha512-bE2DUjruqXlHYP3Q2Gpqiuj2bHq7/88FnuaS0FjeGGLCy+X6a07bGVuwtiOYnPSLHR6jmx5Bwdv+j7l8H+G97A==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.37.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "estraverse": "^5.3.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0" + } + }, + "node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@stylistic/eslint-plugin/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@swc/core": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.2.tgz", diff --git a/package.json b/package.json index 40fad1ec..d7235534 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "@octokit/core": "^7.0.3", "@octokit/plugin-paginate-rest": "^13.1.1", "@octokit/plugin-rest-endpoint-methods": "^16.0.0", + "@stylistic/eslint-plugin": "^5.2.2", "@swc/core": "^1.13.2", "@swc/jest": "^0.2.39", "@types/cli-progress": "^3.11.6", diff --git a/scripts/commands/channels/edit.ts b/scripts/commands/channels/edit.ts index 4a5e714a..3618fbff 100644 --- a/scripts/commands/channels/edit.ts +++ b/scripts/commands/channels/edit.ts @@ -1,216 +1,216 @@ -import { Storage, Collection, Logger, Dictionary } from '@freearhey/core' -import type { DataProcessorData } from '../../types/dataProcessor' -import type { DataLoaderData } from '../../types/dataLoader' -import { ChannelSearchableData } from '../../types/channel' -import { Channel, ChannelList, Feed } from '../../models' -import { DataProcessor, DataLoader } from '../../core' -import { select, input } from '@inquirer/prompts' -import { ChannelsParser } from '../../core' -import { DATA_DIR } from '../../constants' -import nodeCleanup from 'node-cleanup' -import sjs from '@freearhey/search-js' -import epgGrabber from 'epg-grabber' -import { Command } from 'commander' -import readline from 'readline' - -type ChoiceValue = { type: string; value?: Feed | Channel } -type Choice = { name: string; short?: string; value: ChoiceValue; default?: boolean } - -if (process.platform === 'win32') { - readline - .createInterface({ - input: process.stdin, - output: process.stdout - }) - .on('SIGINT', function () { - process.emit('SIGINT') - }) -} - -const program = new Command() - -program.argument('', 'Path to *.channels.xml file to edit').parse(process.argv) - -const filepath = program.args[0] -const logger = new Logger() -const storage = new Storage() -let channelList = new ChannelList({ channels: [] }) - -main(filepath) -nodeCleanup(() => { - save(filepath, channelList) -}) - -export default async function main(filepath: string) { - if (!(await storage.exists(filepath))) { - throw new Error(`File "${filepath}" does not exists`) - } - - logger.info('loading data from api...') - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const loader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await loader.load() - const { channels, channelsKeyById, feedsGroupedByChannelId }: DataProcessorData = - processor.process(data) - - logger.info('loading channels...') - const parser = new ChannelsParser({ storage }) - channelList = await parser.parse(filepath) - const parsedChannelsWithoutId = channelList.channels.filter( - (channel: epgGrabber.Channel) => !channel.xmltv_id - ) - - logger.info( - `found ${channelList.channels.count()} channels (including ${parsedChannelsWithoutId.count()} without ID)` - ) - - logger.info('creating search index...') - const items = channels.map((channel: Channel) => channel.getSearchable()).all() - const searchIndex = sjs.createIndex(items, { - searchable: ['name', 'altNames', 'guideNames', 'streamNames', 'feedFullNames'] - }) - - logger.info('starting...\n') - - for (const channel of parsedChannelsWithoutId.all()) { - try { - channel.xmltv_id = await selectChannel( - channel, - searchIndex, - feedsGroupedByChannelId, - channelsKeyById - ) - } catch (err) { - logger.info(err.message) - break - } - } - - parsedChannelsWithoutId.forEach((channel: epgGrabber.Channel) => { - if (channel.xmltv_id === '-') { - channel.xmltv_id = '' - } - }) -} - -async function selectChannel( - channel: epgGrabber.Channel, - searchIndex, - feedsGroupedByChannelId: Dictionary, - channelsKeyById: Dictionary -): Promise { - const query = escapeRegex(channel.name) - const similarChannels = searchIndex - .search(query) - .map((item: ChannelSearchableData) => channelsKeyById.get(item.id)) - - const selected: ChoiceValue = await select({ - message: `Select channel ID for "${channel.name}" (${channel.site_id}):`, - choices: getChannelChoises(new Collection(similarChannels)), - pageSize: 10 - }) - - switch (selected.type) { - case 'skip': - return '-' - case 'type': { - const typedChannelId = await input({ message: ' Channel ID:' }) - if (!typedChannelId) return '' - const selectedFeedId = await selectFeed(typedChannelId, feedsGroupedByChannelId) - if (selectedFeedId === '-') return typedChannelId - return [typedChannelId, selectedFeedId].join('@') - } - case 'channel': { - const selectedChannel = selected.value - if (!selectedChannel) return '' - const selectedFeedId = await selectFeed(selectedChannel.id || '', feedsGroupedByChannelId) - if (selectedFeedId === '-') return selectedChannel.id || '' - return [selectedChannel.id, selectedFeedId].join('@') - } - } - - return '' -} - -async function selectFeed(channelId: string, feedsGroupedByChannelId: Dictionary): Promise { - const channelFeeds = feedsGroupedByChannelId.has(channelId) - ? new Collection(feedsGroupedByChannelId.get(channelId)) - : new Collection() - const choices = getFeedChoises(channelFeeds) - - const selected: ChoiceValue = await select({ - message: `Select feed ID for "${channelId}":`, - choices, - pageSize: 10 - }) - - switch (selected.type) { - case 'skip': - return '-' - case 'type': - return await input({ message: ' Feed ID:', default: 'SD' }) - case 'feed': - const selectedFeed = selected.value - if (!selectedFeed) return '' - return selectedFeed.id || '' - } - - return '' -} - -function getChannelChoises(channels: Collection): Choice[] { - const choises: Choice[] = [] - - channels.forEach((channel: Channel) => { - const names = new Collection([channel.name, ...channel.getAltNames().all()]).uniq().join(', ') - - choises.push({ - value: { - type: 'channel', - value: channel - }, - name: `${channel.id} (${names})`, - short: `${channel.id}` - }) - }) - - choises.push({ name: 'Type...', value: { type: 'type' } }) - choises.push({ name: 'Skip', value: { type: 'skip' } }) - - return choises -} - -function getFeedChoises(feeds: Collection): Choice[] { - const choises: Choice[] = [] - - feeds.forEach((feed: Feed) => { - let name = `${feed.id} (${feed.name})` - if (feed.isMain) name += ' [main]' - - choises.push({ - value: { - type: 'feed', - value: feed - }, - default: feed.isMain, - name, - short: feed.id - }) - }) - - choises.push({ name: 'Type...', value: { type: 'type' } }) - choises.push({ name: 'Skip', value: { type: 'skip' } }) - - return choises -} - -function save(filepath: string, channelList: ChannelList) { - if (!storage.existsSync(filepath)) return - storage.saveSync(filepath, channelList.toString()) - logger.info(`\nFile '${filepath}' successfully saved`) -} - -function escapeRegex(string: string) { - return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&') -} +import { Storage, Collection, Logger, Dictionary } from '@freearhey/core' +import type { DataProcessorData } from '../../types/dataProcessor' +import type { DataLoaderData } from '../../types/dataLoader' +import { ChannelSearchableData } from '../../types/channel' +import { Channel, ChannelList, Feed } from '../../models' +import { DataProcessor, DataLoader } from '../../core' +import { select, input } from '@inquirer/prompts' +import { ChannelsParser } from '../../core' +import { DATA_DIR } from '../../constants' +import nodeCleanup from 'node-cleanup' +import sjs from '@freearhey/search-js' +import epgGrabber from 'epg-grabber' +import { Command } from 'commander' +import readline from 'readline' + +interface ChoiceValue { type: string; value?: Feed | Channel } +interface Choice { name: string; short?: string; value: ChoiceValue; default?: boolean } + +if (process.platform === 'win32') { + readline + .createInterface({ + input: process.stdin, + output: process.stdout + }) + .on('SIGINT', function () { + process.emit('SIGINT') + }) +} + +const program = new Command() + +program.argument('', 'Path to *.channels.xml file to edit').parse(process.argv) + +const filepath = program.args[0] +const logger = new Logger() +const storage = new Storage() +let channelList = new ChannelList({ channels: [] }) + +main(filepath) +nodeCleanup(() => { + save(filepath, channelList) +}) + +export default async function main(filepath: string) { + if (!(await storage.exists(filepath))) { + throw new Error(`File "${filepath}" does not exists`) + } + + logger.info('loading data from api...') + const processor = new DataProcessor() + const dataStorage = new Storage(DATA_DIR) + const loader = new DataLoader({ storage: dataStorage }) + const data: DataLoaderData = await loader.load() + const { channels, channelsKeyById, feedsGroupedByChannelId }: DataProcessorData = + processor.process(data) + + logger.info('loading channels...') + const parser = new ChannelsParser({ storage }) + channelList = await parser.parse(filepath) + const parsedChannelsWithoutId = channelList.channels.filter( + (channel: epgGrabber.Channel) => !channel.xmltv_id + ) + + logger.info( + `found ${channelList.channels.count()} channels (including ${parsedChannelsWithoutId.count()} without ID)` + ) + + logger.info('creating search index...') + const items = channels.map((channel: Channel) => channel.getSearchable()).all() + const searchIndex = sjs.createIndex(items, { + searchable: ['name', 'altNames', 'guideNames', 'streamNames', 'feedFullNames'] + }) + + logger.info('starting...\n') + + for (const channel of parsedChannelsWithoutId.all()) { + try { + channel.xmltv_id = await selectChannel( + channel, + searchIndex, + feedsGroupedByChannelId, + channelsKeyById + ) + } catch (err) { + logger.info(err.message) + break + } + } + + parsedChannelsWithoutId.forEach((channel: epgGrabber.Channel) => { + if (channel.xmltv_id === '-') { + channel.xmltv_id = '' + } + }) +} + +async function selectChannel( + channel: epgGrabber.Channel, + searchIndex, + feedsGroupedByChannelId: Dictionary, + channelsKeyById: Dictionary +): Promise { + const query = escapeRegex(channel.name) + const similarChannels = searchIndex + .search(query) + .map((item: ChannelSearchableData) => channelsKeyById.get(item.id)) + + const selected: ChoiceValue = await select({ + message: `Select channel ID for "${channel.name}" (${channel.site_id}):`, + choices: getChannelChoises(new Collection(similarChannels)), + pageSize: 10 + }) + + switch (selected.type) { + case 'skip': + return '-' + case 'type': { + const typedChannelId = await input({ message: ' Channel ID:' }) + if (!typedChannelId) return '' + const selectedFeedId = await selectFeed(typedChannelId, feedsGroupedByChannelId) + if (selectedFeedId === '-') return typedChannelId + return [typedChannelId, selectedFeedId].join('@') + } + case 'channel': { + const selectedChannel = selected.value + if (!selectedChannel) return '' + const selectedFeedId = await selectFeed(selectedChannel.id || '', feedsGroupedByChannelId) + if (selectedFeedId === '-') return selectedChannel.id || '' + return [selectedChannel.id, selectedFeedId].join('@') + } + } + + return '' +} + +async function selectFeed(channelId: string, feedsGroupedByChannelId: Dictionary): Promise { + const channelFeeds = feedsGroupedByChannelId.has(channelId) + ? new Collection(feedsGroupedByChannelId.get(channelId)) + : new Collection() + const choices = getFeedChoises(channelFeeds) + + const selected: ChoiceValue = await select({ + message: `Select feed ID for "${channelId}":`, + choices, + pageSize: 10 + }) + + switch (selected.type) { + case 'skip': + return '-' + case 'type': + return await input({ message: ' Feed ID:', default: 'SD' }) + case 'feed': + const selectedFeed = selected.value + if (!selectedFeed) return '' + return selectedFeed.id || '' + } + + return '' +} + +function getChannelChoises(channels: Collection): Choice[] { + const choises: Choice[] = [] + + channels.forEach((channel: Channel) => { + const names = new Collection([channel.name, ...channel.getAltNames().all()]).uniq().join(', ') + + choises.push({ + value: { + type: 'channel', + value: channel + }, + name: `${channel.id} (${names})`, + short: `${channel.id}` + }) + }) + + choises.push({ name: 'Type...', value: { type: 'type' } }) + choises.push({ name: 'Skip', value: { type: 'skip' } }) + + return choises +} + +function getFeedChoises(feeds: Collection): Choice[] { + const choises: Choice[] = [] + + feeds.forEach((feed: Feed) => { + let name = `${feed.id} (${feed.name})` + if (feed.isMain) name += ' [main]' + + choises.push({ + value: { + type: 'feed', + value: feed + }, + default: feed.isMain, + name, + short: feed.id + }) + }) + + choises.push({ name: 'Type...', value: { type: 'type' } }) + choises.push({ name: 'Skip', value: { type: 'skip' } }) + + return choises +} + +function save(filepath: string, channelList: ChannelList) { + if (!storage.existsSync(filepath)) return + storage.saveSync(filepath, channelList.toString()) + logger.info(`\nFile '${filepath}' successfully saved`) +} + +function escapeRegex(string: string) { + return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&') +} diff --git a/scripts/commands/channels/parse.ts b/scripts/commands/channels/parse.ts index fb0e0447..58eccd68 100644 --- a/scripts/commands/channels/parse.ts +++ b/scripts/commands/channels/parse.ts @@ -1,88 +1,86 @@ -import { Logger, File, Storage } from '@freearhey/core' -import { ChannelsParser } from '../../core' -import { ChannelList } from '../../models' -import { pathToFileURL } from 'node:url' -import epgGrabber from 'epg-grabber' -import { Command } from 'commander' - -const program = new Command() -program - .requiredOption('-c, --config ', 'Config file') - .option('-s, --set [args...]', 'Set custom arguments') - .option('-o, --output ', 'Output file') - .parse(process.argv) - -type ParseOptions = { - config: string - set?: string - output?: string - clean?: boolean -} - -const options: ParseOptions = program.opts() - -async function main() { - function isPromise(promise: object[] | Promise) { - return ( - !!promise && - typeof promise === 'object' && - typeof (promise as Promise).then === 'function' - ) - } - - const storage = new Storage() - const logger = new Logger() - const parser = new ChannelsParser({ storage }) - const file = new File(options.config) - const dir = file.dirname() - const config = (await import(pathToFileURL(options.config).toString())).default - const outputFilepath = options.output || `${dir}/${config.site}.channels.xml` - - let channelList = new ChannelList({ channels: [] }) - if (await storage.exists(outputFilepath)) { - channelList = await parser.parse(outputFilepath) - } - - const args: { - [key: string]: string - } = {} - - if (Array.isArray(options.set)) { - options.set.forEach((arg: string) => { - const [key, value] = arg.split(':') - args[key] = value - }) - } - - let parsedChannels = config.channels(args) - if (isPromise(parsedChannels)) { - parsedChannels = await parsedChannels - } - parsedChannels = parsedChannels.map((channel: epgGrabber.Channel) => { - channel.site = config.site - - return channel - }) - - const newChannelList = new ChannelList({ channels: [] }) - parsedChannels.forEach((channel: epgGrabber.Channel) => { - if (!channel.site_id) return - - const found: epgGrabber.Channel | undefined = channelList.get(channel.site_id) - - if (found) { - channel.xmltv_id = found.xmltv_id - channel.lang = found.lang - } - - newChannelList.add(channel) - }) - - newChannelList.sort() - - await storage.save(outputFilepath, newChannelList.toString()) - - logger.info(`File '${outputFilepath}' successfully saved`) -} - -main() +import { Logger, File, Storage } from '@freearhey/core' +import { ChannelsParser } from '../../core' +import { ChannelList } from '../../models' +import { pathToFileURL } from 'node:url' +import epgGrabber from 'epg-grabber' +import { Command } from 'commander' + +const program = new Command() +program + .requiredOption('-c, --config ', 'Config file') + .option('-s, --set [args...]', 'Set custom arguments') + .option('-o, --output ', 'Output file') + .parse(process.argv) + +interface ParseOptions { + config: string + set?: string + output?: string + clean?: boolean +} + +const options: ParseOptions = program.opts() + +async function main() { + function isPromise(promise: object[] | Promise) { + return ( + !!promise && + typeof promise === 'object' && + typeof (promise as Promise).then === 'function' + ) + } + + const storage = new Storage() + const logger = new Logger() + const parser = new ChannelsParser({ storage }) + const file = new File(options.config) + const dir = file.dirname() + const config = (await import(pathToFileURL(options.config).toString())).default + const outputFilepath = options.output || `${dir}/${config.site}.channels.xml` + + let channelList = new ChannelList({ channels: [] }) + if (await storage.exists(outputFilepath)) { + channelList = await parser.parse(outputFilepath) + } + + const args: Record = {} + + if (Array.isArray(options.set)) { + options.set.forEach((arg: string) => { + const [key, value] = arg.split(':') + args[key] = value + }) + } + + let parsedChannels = config.channels(args) + if (isPromise(parsedChannels)) { + parsedChannels = await parsedChannels + } + parsedChannels = parsedChannels.map((channel: epgGrabber.Channel) => { + channel.site = config.site + + return channel + }) + + const newChannelList = new ChannelList({ channels: [] }) + parsedChannels.forEach((channel: epgGrabber.Channel) => { + if (!channel.site_id) return + + const found: epgGrabber.Channel | undefined = channelList.get(channel.site_id) + + if (found) { + channel.xmltv_id = found.xmltv_id + channel.lang = found.lang + } + + newChannelList.add(channel) + }) + + newChannelList.sort() + + await storage.save(outputFilepath, newChannelList.toString()) + + logger.info(`File '${outputFilepath}' successfully saved`) +} + +main() diff --git a/scripts/commands/channels/validate.ts b/scripts/commands/channels/validate.ts index 358e1168..b9809a62 100644 --- a/scripts/commands/channels/validate.ts +++ b/scripts/commands/channels/validate.ts @@ -1,92 +1,92 @@ -import { ChannelsParser, DataLoader, DataProcessor } from '../../core' -import { DataProcessorData } from '../../types/dataProcessor' -import { Storage, Dictionary, File } from '@freearhey/core' -import { DataLoaderData } from '../../types/dataLoader' -import { ChannelList } from '../../models' -import { DATA_DIR } from '../../constants' -import epgGrabber from 'epg-grabber' -import { program } from 'commander' -import chalk from 'chalk' -import langs from 'langs' - -program.argument('[filepath...]', 'Path to *.channels.xml files to validate').parse(process.argv) - -type ValidationError = { - type: 'duplicate' | 'wrong_channel_id' | 'wrong_feed_id' | 'wrong_lang' - name: string - lang?: string - xmltv_id?: string - site_id?: string - logo?: string -} - -async function main() { - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const loader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await loader.load() - const { channelsKeyById, feedsKeyByStreamId }: DataProcessorData = processor.process(data) - const parser = new ChannelsParser({ - storage: new Storage() - }) - - let totalFiles = 0 - let totalErrors = 0 - - const storage = new Storage() - const files = program.args.length ? program.args : await storage.list('sites/**/*.channels.xml') - for (const filepath of files) { - const file = new File(filepath) - if (file.extension() !== 'xml') continue - - const channelList: ChannelList = await parser.parse(filepath) - - const bufferBySiteId = new Dictionary() - const errors: ValidationError[] = [] - channelList.channels.forEach((channel: epgGrabber.Channel) => { - const bufferId: string = channel.site_id - if (bufferBySiteId.missing(bufferId)) { - bufferBySiteId.set(bufferId, true) - } else { - errors.push({ type: 'duplicate', ...channel }) - totalErrors++ - } - - if (!langs.where('1', channel.lang ?? '')) { - errors.push({ type: 'wrong_lang', ...channel }) - totalErrors++ - } - - if (!channel.xmltv_id) return - const [channelId, feedId] = channel.xmltv_id.split('@') - - const foundChannel = channelsKeyById.get(channelId) - if (!foundChannel) { - errors.push({ type: 'wrong_channel_id', ...channel }) - totalErrors++ - } - - if (feedId) { - const foundFeed = feedsKeyByStreamId.get(channel.xmltv_id) - if (!foundFeed) { - errors.push({ type: 'wrong_feed_id', ...channel }) - totalErrors++ - } - } - }) - - if (errors.length) { - console.log(chalk.underline(filepath)) - console.table(errors, ['type', 'lang', 'xmltv_id', 'site_id', 'name']) - console.log() - totalFiles++ - } - } - - if (totalErrors > 0) { - console.log(chalk.red(`${totalErrors} error(s) in ${totalFiles} file(s)`)) - process.exit(1) - } -} - -main() +import { ChannelsParser, DataLoader, DataProcessor } from '../../core' +import { DataProcessorData } from '../../types/dataProcessor' +import { Storage, Dictionary, File } from '@freearhey/core' +import { DataLoaderData } from '../../types/dataLoader' +import { ChannelList } from '../../models' +import { DATA_DIR } from '../../constants' +import epgGrabber from 'epg-grabber' +import { program } from 'commander' +import chalk from 'chalk' +import langs from 'langs' + +program.argument('[filepath...]', 'Path to *.channels.xml files to validate').parse(process.argv) + +interface ValidationError { + type: 'duplicate' | 'wrong_channel_id' | 'wrong_feed_id' | 'wrong_lang' + name: string + lang?: string + xmltv_id?: string + site_id?: string + logo?: string +} + +async function main() { + const processor = new DataProcessor() + const dataStorage = new Storage(DATA_DIR) + const loader = new DataLoader({ storage: dataStorage }) + const data: DataLoaderData = await loader.load() + const { channelsKeyById, feedsKeyByStreamId }: DataProcessorData = processor.process(data) + const parser = new ChannelsParser({ + storage: new Storage() + }) + + let totalFiles = 0 + let totalErrors = 0 + + const storage = new Storage() + const files = program.args.length ? program.args : await storage.list('sites/**/*.channels.xml') + for (const filepath of files) { + const file = new File(filepath) + if (file.extension() !== 'xml') continue + + const channelList: ChannelList = await parser.parse(filepath) + + const bufferBySiteId = new Dictionary() + const errors: ValidationError[] = [] + channelList.channels.forEach((channel: epgGrabber.Channel) => { + const bufferId: string = channel.site_id + if (bufferBySiteId.missing(bufferId)) { + bufferBySiteId.set(bufferId, true) + } else { + errors.push({ type: 'duplicate', ...channel }) + totalErrors++ + } + + if (!langs.where('1', channel.lang ?? '')) { + errors.push({ type: 'wrong_lang', ...channel }) + totalErrors++ + } + + if (!channel.xmltv_id) return + const [channelId, feedId] = channel.xmltv_id.split('@') + + const foundChannel = channelsKeyById.get(channelId) + if (!foundChannel) { + errors.push({ type: 'wrong_channel_id', ...channel }) + totalErrors++ + } + + if (feedId) { + const foundFeed = feedsKeyByStreamId.get(channel.xmltv_id) + if (!foundFeed) { + errors.push({ type: 'wrong_feed_id', ...channel }) + totalErrors++ + } + } + }) + + if (errors.length) { + console.log(chalk.underline(filepath)) + console.table(errors, ['type', 'lang', 'xmltv_id', 'site_id', 'name']) + console.log() + totalFiles++ + } + } + + if (totalErrors > 0) { + console.log(chalk.red(`${totalErrors} error(s) in ${totalFiles} file(s)`)) + process.exit(1) + } +} + +main() diff --git a/scripts/commands/epg/grab.ts b/scripts/commands/epg/grab.ts index ebf94e70..9e111294 100644 --- a/scripts/commands/epg/grab.ts +++ b/scripts/commands/epg/grab.ts @@ -1,133 +1,133 @@ -import { Logger, Timer, Storage, Collection } from '@freearhey/core' -import { QueueCreator, Job, ChannelsParser } from '../../core' -import { Option, program } from 'commander' -import { SITES_DIR } from '../../constants' -import { Channel } from 'epg-grabber' -import path from 'path' -import { ChannelList } from '../../models' - -program - .addOption(new Option('-s, --site ', 'Name of the site to parse')) - .addOption( - new Option( - '-c, --channels ', - 'Path to *.channels.xml file (required if the "--site" attribute is not specified)' - ) - ) - .addOption(new Option('-o, --output ', 'Path to output file').default('guide.xml')) - .addOption(new Option('-l, --lang ', 'Filter channels by languages (ISO 639-1 codes)')) - .addOption( - new Option('-t, --timeout ', 'Override the default timeout for each request').env( - 'TIMEOUT' - ) - ) - .addOption( - new Option('-d, --delay ', 'Override the default delay between request').env( - 'DELAY' - ) - ) - .addOption(new Option('-x, --proxy ', 'Use the specified proxy').env('PROXY')) - .addOption( - new Option( - '--days ', - 'Override the number of days for which the program will be loaded (defaults to the value from the site config)' - ) - .argParser(value => parseInt(value)) - .env('DAYS') - ) - .addOption( - new Option('--maxConnections ', 'Limit on the number of concurrent requests') - .default(1) - .env('MAX_CONNECTIONS') - ) - .addOption( - new Option('--gzip', 'Create a compressed version of the guide as well') - .default(false) - .env('GZIP') - ) - .addOption(new Option('--curl', 'Display each request as CURL').default(false).env('CURL')) - .parse() - -export type GrabOptions = { - site?: string - channels?: string - output: string - gzip: boolean - curl: boolean - maxConnections: number - timeout?: string - delay?: string - lang?: string - days?: number - proxy?: string -} - -const options: GrabOptions = program.opts() - -async function main() { - if (!options.site && !options.channels) - throw new Error('One of the arguments must be presented: `--site` or `--channels`') - - const logger = new Logger() - - logger.start('starting...') - - logger.info('config:') - logger.tree(options) - - logger.info('loading channels...') - const storage = new Storage() - const parser = new ChannelsParser({ storage }) - - let files: string[] = [] - if (options.site) { - let pattern = path.join(SITES_DIR, options.site, '*.channels.xml') - pattern = pattern.replace(/\\/g, '/') - files = await storage.list(pattern) - } else if (options.channels) { - files = await storage.list(options.channels) - } - - let channels = new Collection() - for (const filepath of files) { - const channelList: ChannelList = await parser.parse(filepath) - - channels = channels.concat(channelList.channels) - } - - if (options.lang) { - channels = channels.filter((channel: Channel) => { - if (!options.lang || !channel.lang) return true - - return options.lang.includes(channel.lang) - }) - } - - logger.info(` found ${channels.count()} channel(s)`) - - logger.info('run:') - runJob({ logger, channels }) -} - -main() - -async function runJob({ logger, channels }: { logger: Logger; channels: Collection }) { - const timer = new Timer() - timer.start() - - const queueCreator = new QueueCreator({ - channels, - logger, - options - }) - const queue = await queueCreator.create() - const job = new Job({ - queue, - logger, - options - }) - - await job.run() - - logger.success(` done in ${timer.format('HH[h] mm[m] ss[s]')}`) -} +import { Logger, Timer, Storage, Collection } from '@freearhey/core' +import { QueueCreator, Job, ChannelsParser } from '../../core' +import { Option, program } from 'commander' +import { SITES_DIR } from '../../constants' +import { Channel } from 'epg-grabber' +import path from 'path' +import { ChannelList } from '../../models' + +program + .addOption(new Option('-s, --site ', 'Name of the site to parse')) + .addOption( + new Option( + '-c, --channels ', + 'Path to *.channels.xml file (required if the "--site" attribute is not specified)' + ) + ) + .addOption(new Option('-o, --output ', 'Path to output file').default('guide.xml')) + .addOption(new Option('-l, --lang ', 'Filter channels by languages (ISO 639-1 codes)')) + .addOption( + new Option('-t, --timeout ', 'Override the default timeout for each request').env( + 'TIMEOUT' + ) + ) + .addOption( + new Option('-d, --delay ', 'Override the default delay between request').env( + 'DELAY' + ) + ) + .addOption(new Option('-x, --proxy ', 'Use the specified proxy').env('PROXY')) + .addOption( + new Option( + '--days ', + 'Override the number of days for which the program will be loaded (defaults to the value from the site config)' + ) + .argParser(value => parseInt(value)) + .env('DAYS') + ) + .addOption( + new Option('--maxConnections ', 'Limit on the number of concurrent requests') + .default(1) + .env('MAX_CONNECTIONS') + ) + .addOption( + new Option('--gzip', 'Create a compressed version of the guide as well') + .default(false) + .env('GZIP') + ) + .addOption(new Option('--curl', 'Display each request as CURL').default(false).env('CURL')) + .parse() + +export interface GrabOptions { + site?: string + channels?: string + output: string + gzip: boolean + curl: boolean + maxConnections: number + timeout?: string + delay?: string + lang?: string + days?: number + proxy?: string +} + +const options: GrabOptions = program.opts() + +async function main() { + if (!options.site && !options.channels) + throw new Error('One of the arguments must be presented: `--site` or `--channels`') + + const logger = new Logger() + + logger.start('starting...') + + logger.info('config:') + logger.tree(options) + + logger.info('loading channels...') + const storage = new Storage() + const parser = new ChannelsParser({ storage }) + + let files: string[] = [] + if (options.site) { + let pattern = path.join(SITES_DIR, options.site, '*.channels.xml') + pattern = pattern.replace(/\\/g, '/') + files = await storage.list(pattern) + } else if (options.channels) { + files = await storage.list(options.channels) + } + + let channels = new Collection() + for (const filepath of files) { + const channelList: ChannelList = await parser.parse(filepath) + + channels = channels.concat(channelList.channels) + } + + if (options.lang) { + channels = channels.filter((channel: Channel) => { + if (!options.lang || !channel.lang) return true + + return options.lang.includes(channel.lang) + }) + } + + logger.info(` found ${channels.count()} channel(s)`) + + logger.info('run:') + runJob({ logger, channels }) +} + +main() + +async function runJob({ logger, channels }: { logger: Logger; channels: Collection }) { + const timer = new Timer() + timer.start() + + const queueCreator = new QueueCreator({ + channels, + logger, + options + }) + const queue = await queueCreator.create() + const job = new Job({ + queue, + logger, + options + }) + + await job.run() + + logger.success(` done in ${timer.format('HH[h] mm[m] ss[s]')}`) +} diff --git a/scripts/core/channelsParser.ts b/scripts/core/channelsParser.ts index 43a5f28b..d47aee7d 100644 --- a/scripts/core/channelsParser.ts +++ b/scripts/core/channelsParser.ts @@ -1,22 +1,22 @@ -import { parseChannels } from 'epg-grabber' -import { Storage } from '@freearhey/core' -import { ChannelList } from '../models' - -type ChannelsParserProps = { - storage: Storage -} - -export class ChannelsParser { - storage: Storage - - constructor({ storage }: ChannelsParserProps) { - this.storage = storage - } - - async parse(filepath: string): Promise { - const content = await this.storage.load(filepath) - const parsed = parseChannels(content) - - return new ChannelList({ channels: parsed }) - } -} +import { parseChannels } from 'epg-grabber' +import { Storage } from '@freearhey/core' +import { ChannelList } from '../models' + +interface ChannelsParserProps { + storage: Storage +} + +export class ChannelsParser { + storage: Storage + + constructor({ storage }: ChannelsParserProps) { + this.storage = storage + } + + async parse(filepath: string): Promise { + const content = await this.storage.load(filepath) + const parsed = parseChannels(content) + + return new ChannelList({ channels: parsed }) + } +} diff --git a/scripts/core/dataProcessor.ts b/scripts/core/dataProcessor.ts index 1f0252fc..a104e675 100644 --- a/scripts/core/dataProcessor.ts +++ b/scripts/core/dataProcessor.ts @@ -1,56 +1,55 @@ -import { Channel, Feed, GuideChannel, Logo, Stream } from '../models' -import { DataLoaderData } from '../types/dataLoader' -import { Collection } from '@freearhey/core' - -export class DataProcessor { - constructor() {} - - process(data: DataLoaderData) { - let channels = new Collection(data.channels).map(data => new Channel(data)) - const channelsKeyById = channels.keyBy((channel: Channel) => channel.id) - - const guideChannels = new Collection(data.guides).map(data => new GuideChannel(data)) - const guideChannelsGroupedByStreamId = guideChannels.groupBy((channel: GuideChannel) => - channel.getStreamId() - ) - - const streams = new Collection(data.streams).map(data => new Stream(data)) - const streamsGroupedById = streams.groupBy((stream: Stream) => stream.getId()) - - let feeds = new Collection(data.feeds).map(data => - new Feed(data) - .withGuideChannels(guideChannelsGroupedByStreamId) - .withStreams(streamsGroupedById) - .withChannel(channelsKeyById) - ) - const feedsKeyByStreamId = feeds.keyBy((feed: Feed) => feed.getStreamId()) - - const logos = new Collection(data.logos).map(data => - new Logo(data).withFeed(feedsKeyByStreamId) - ) - const logosGroupedByChannelId = logos.groupBy((logo: Logo) => logo.channelId) - const logosGroupedByStreamId = logos.groupBy((logo: Logo) => logo.getStreamId()) - - feeds = feeds.map((feed: Feed) => feed.withLogos(logosGroupedByStreamId)) - const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) => feed.channelId) - - channels = channels.map((channel: Channel) => - channel.withFeeds(feedsGroupedByChannelId).withLogos(logosGroupedByChannelId) - ) - - return { - guideChannelsGroupedByStreamId, - feedsGroupedByChannelId, - logosGroupedByChannelId, - logosGroupedByStreamId, - streamsGroupedById, - feedsKeyByStreamId, - channelsKeyById, - guideChannels, - channels, - streams, - feeds, - logos - } - } -} +import { Channel, Feed, GuideChannel, Logo, Stream } from '../models' +import { DataLoaderData } from '../types/dataLoader' +import { Collection } from '@freearhey/core' + +export class DataProcessor { + + process(data: DataLoaderData) { + let channels = new Collection(data.channels).map(data => new Channel(data)) + const channelsKeyById = channels.keyBy((channel: Channel) => channel.id) + + const guideChannels = new Collection(data.guides).map(data => new GuideChannel(data)) + const guideChannelsGroupedByStreamId = guideChannels.groupBy((channel: GuideChannel) => + channel.getStreamId() + ) + + const streams = new Collection(data.streams).map(data => new Stream(data)) + const streamsGroupedById = streams.groupBy((stream: Stream) => stream.getId()) + + let feeds = new Collection(data.feeds).map(data => + new Feed(data) + .withGuideChannels(guideChannelsGroupedByStreamId) + .withStreams(streamsGroupedById) + .withChannel(channelsKeyById) + ) + const feedsKeyByStreamId = feeds.keyBy((feed: Feed) => feed.getStreamId()) + + const logos = new Collection(data.logos).map(data => + new Logo(data).withFeed(feedsKeyByStreamId) + ) + const logosGroupedByChannelId = logos.groupBy((logo: Logo) => logo.channelId) + const logosGroupedByStreamId = logos.groupBy((logo: Logo) => logo.getStreamId()) + + feeds = feeds.map((feed: Feed) => feed.withLogos(logosGroupedByStreamId)) + const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) => feed.channelId) + + channels = channels.map((channel: Channel) => + channel.withFeeds(feedsGroupedByChannelId).withLogos(logosGroupedByChannelId) + ) + + return { + guideChannelsGroupedByStreamId, + feedsGroupedByChannelId, + logosGroupedByChannelId, + logosGroupedByStreamId, + streamsGroupedById, + feedsKeyByStreamId, + channelsKeyById, + guideChannels, + channels, + streams, + feeds, + logos + } + } +} diff --git a/scripts/core/grabber.ts b/scripts/core/grabber.ts index 57bd322d..d1881af7 100644 --- a/scripts/core/grabber.ts +++ b/scripts/core/grabber.ts @@ -1,105 +1,105 @@ -import { EPGGrabber, GrabCallbackData, EPGGrabberMock, SiteConfig, Channel } from 'epg-grabber' -import { Logger, Collection } from '@freearhey/core' -import { Queue, ProxyParser } from './' -import { GrabOptions } from '../commands/epg/grab' -import { TaskQueue, PromisyClass } from 'cwait' -import { SocksProxyAgent } from 'socks-proxy-agent' - -type GrabberProps = { - logger: Logger - queue: Queue - options: GrabOptions -} - -export class Grabber { - logger: Logger - queue: Queue - options: GrabOptions - grabber: EPGGrabber | EPGGrabberMock - - constructor({ logger, queue, options }: GrabberProps) { - this.logger = logger - this.queue = queue - this.options = options - this.grabber = process.env.NODE_ENV === 'test' ? new EPGGrabberMock() : new EPGGrabber() - } - - async grab(): Promise<{ channels: Collection; programs: Collection }> { - const proxyParser = new ProxyParser() - const taskQueue = new TaskQueue(Promise as PromisyClass, this.options.maxConnections) - - const total = this.queue.size() - - const channels = new Collection() - let programs = new Collection() - let i = 1 - - await Promise.all( - this.queue.items().map( - taskQueue.wrap( - async (queueItem: { channel: Channel; config: SiteConfig; date: string }) => { - const { channel, config, date } = queueItem - - channels.add(channel) - - if (this.options.timeout !== undefined) { - const timeout = parseInt(this.options.timeout) - config.request = { ...config.request, ...{ timeout } } - } - - if (this.options.delay !== undefined) { - const delay = parseInt(this.options.delay) - config.delay = delay - } - - if (this.options.proxy !== undefined) { - const proxy = proxyParser.parse(this.options.proxy) - - if ( - proxy.protocol && - ['socks', 'socks5', 'socks5h', 'socks4', 'socks4a'].includes(String(proxy.protocol)) - ) { - const socksProxyAgent = new SocksProxyAgent(this.options.proxy) - - config.request = { - ...config.request, - ...{ httpAgent: socksProxyAgent, httpsAgent: socksProxyAgent } - } - } else { - config.request = { ...config.request, ...{ proxy } } - } - } - - if (this.options.curl === true) { - config.curl = true - } - - const _programs = await this.grabber.grab( - channel, - date, - config, - (data: GrabCallbackData, error: Error | null) => { - const { programs, date } = data - - this.logger.info( - ` [${i}/${total}] ${channel.site} (${channel.lang}) - ${ - channel.xmltv_id - } - ${date.format('MMM D, YYYY')} (${programs.length} programs)` - ) - if (i < total) i++ - - if (error) { - this.logger.info(` ERR: ${error.message}`) - } - } - ) - - programs = programs.concat(new Collection(_programs)) - } - ) - ) - ) - - return { channels, programs } - } -} +import { EPGGrabber, GrabCallbackData, EPGGrabberMock, SiteConfig, Channel } from 'epg-grabber' +import { Logger, Collection } from '@freearhey/core' +import { Queue, ProxyParser } from './' +import { GrabOptions } from '../commands/epg/grab' +import { TaskQueue, PromisyClass } from 'cwait' +import { SocksProxyAgent } from 'socks-proxy-agent' + +interface GrabberProps { + logger: Logger + queue: Queue + options: GrabOptions +} + +export class Grabber { + logger: Logger + queue: Queue + options: GrabOptions + grabber: EPGGrabber | EPGGrabberMock + + constructor({ logger, queue, options }: GrabberProps) { + this.logger = logger + this.queue = queue + this.options = options + this.grabber = process.env.NODE_ENV === 'test' ? new EPGGrabberMock() : new EPGGrabber() + } + + async grab(): Promise<{ channels: Collection; programs: Collection }> { + const proxyParser = new ProxyParser() + const taskQueue = new TaskQueue(Promise as PromisyClass, this.options.maxConnections) + + const total = this.queue.size() + + const channels = new Collection() + let programs = new Collection() + let i = 1 + + await Promise.all( + this.queue.items().map( + taskQueue.wrap( + async (queueItem: { channel: Channel; config: SiteConfig; date: string }) => { + const { channel, config, date } = queueItem + + channels.add(channel) + + if (this.options.timeout !== undefined) { + const timeout = parseInt(this.options.timeout) + config.request = { ...config.request, ...{ timeout } } + } + + if (this.options.delay !== undefined) { + const delay = parseInt(this.options.delay) + config.delay = delay + } + + if (this.options.proxy !== undefined) { + const proxy = proxyParser.parse(this.options.proxy) + + if ( + proxy.protocol && + ['socks', 'socks5', 'socks5h', 'socks4', 'socks4a'].includes(String(proxy.protocol)) + ) { + const socksProxyAgent = new SocksProxyAgent(this.options.proxy) + + config.request = { + ...config.request, + ...{ httpAgent: socksProxyAgent, httpsAgent: socksProxyAgent } + } + } else { + config.request = { ...config.request, ...{ proxy } } + } + } + + if (this.options.curl === true) { + config.curl = true + } + + const _programs = await this.grabber.grab( + channel, + date, + config, + (data: GrabCallbackData, error: Error | null) => { + const { programs, date } = data + + this.logger.info( + ` [${i}/${total}] ${channel.site} (${channel.lang}) - ${ + channel.xmltv_id + } - ${date.format('MMM D, YYYY')} (${programs.length} programs)` + ) + if (i < total) i++ + + if (error) { + this.logger.info(` ERR: ${error.message}`) + } + } + ) + + programs = programs.concat(new Collection(_programs)) + } + ) + ) + ) + + return { channels, programs } + } +} diff --git a/scripts/core/guideManager.ts b/scripts/core/guideManager.ts index aee2f666..ea97d631 100644 --- a/scripts/core/guideManager.ts +++ b/scripts/core/guideManager.ts @@ -1,111 +1,111 @@ -import { Collection, Logger, Zip, Storage, StringTemplate } from '@freearhey/core' -import epgGrabber from 'epg-grabber' -import { OptionValues } from 'commander' -import { Channel, Feed, Guide } from '../models' -import path from 'path' -import { DataLoader, DataProcessor } from '.' -import { DataLoaderData } from '../types/dataLoader' -import { DataProcessorData } from '../types/dataProcessor' -import { DATA_DIR } from '../constants' - -type GuideManagerProps = { - options: OptionValues - logger: Logger - channels: Collection - programs: Collection -} - -export class GuideManager { - options: OptionValues - logger: Logger - channels: Collection - programs: Collection - - constructor({ channels, programs, logger, options }: GuideManagerProps) { - this.options = options - this.logger = logger - this.channels = channels - this.programs = programs - } - - async createGuides() { - const pathTemplate = new StringTemplate(this.options.output) - - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const loader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await loader.load() - const { feedsKeyByStreamId, channelsKeyById }: DataProcessorData = processor.process(data) - - const groupedChannels = this.channels - .map((channel: epgGrabber.Channel) => { - if (channel.xmltv_id && !channel.icon) { - const foundFeed: Feed = feedsKeyByStreamId.get(channel.xmltv_id) - if (foundFeed && foundFeed.hasLogo()) { - channel.icon = foundFeed.getLogoUrl() - } else { - const [channelId] = channel.xmltv_id.split('@') - const foundChannel: Channel = channelsKeyById.get(channelId) - if (foundChannel && foundChannel.hasLogo()) { - channel.icon = foundChannel.getLogoUrl() - } - } - } - - return channel - }) - .orderBy([ - (channel: epgGrabber.Channel) => channel.index, - (channel: epgGrabber.Channel) => channel.xmltv_id - ]) - .uniqBy( - (channel: epgGrabber.Channel) => `${channel.xmltv_id}:${channel.site}:${channel.lang}` - ) - .groupBy((channel: epgGrabber.Channel) => { - return pathTemplate.format({ lang: channel.lang || 'en', site: channel.site || '' }) - }) - - const groupedPrograms = this.programs - .orderBy([ - (program: epgGrabber.Program) => program.channel, - (program: epgGrabber.Program) => program.start - ]) - .groupBy((program: epgGrabber.Program) => { - const lang = - program.titles && program.titles.length && program.titles[0].lang - ? program.titles[0].lang - : 'en' - - return pathTemplate.format({ lang, site: program.site || '' }) - }) - - for (const groupKey of groupedPrograms.keys()) { - const guide = new Guide({ - filepath: groupKey, - gzip: this.options.gzip, - channels: new Collection(groupedChannels.get(groupKey)), - programs: new Collection(groupedPrograms.get(groupKey)) - }) - - await this.save(guide) - } - } - - async save(guide: Guide) { - const storage = new Storage(path.dirname(guide.filepath)) - const xmlFilepath = guide.filepath - const xmlFilename = path.basename(xmlFilepath) - this.logger.info(` saving to "${xmlFilepath}"...`) - const xmltv = guide.toString() - await storage.save(xmlFilename, xmltv) - - if (guide.gzip) { - const zip = new Zip() - const compressed = zip.compress(xmltv) - const gzFilepath = `${guide.filepath}.gz` - const gzFilename = path.basename(gzFilepath) - this.logger.info(` saving to "${gzFilepath}"...`) - await storage.save(gzFilename, compressed) - } - } -} +import { Collection, Logger, Zip, Storage, StringTemplate } from '@freearhey/core' +import epgGrabber from 'epg-grabber' +import { OptionValues } from 'commander' +import { Channel, Feed, Guide } from '../models' +import path from 'path' +import { DataLoader, DataProcessor } from '.' +import { DataLoaderData } from '../types/dataLoader' +import { DataProcessorData } from '../types/dataProcessor' +import { DATA_DIR } from '../constants' + +interface GuideManagerProps { + options: OptionValues + logger: Logger + channels: Collection + programs: Collection +} + +export class GuideManager { + options: OptionValues + logger: Logger + channels: Collection + programs: Collection + + constructor({ channels, programs, logger, options }: GuideManagerProps) { + this.options = options + this.logger = logger + this.channels = channels + this.programs = programs + } + + async createGuides() { + const pathTemplate = new StringTemplate(this.options.output) + + const processor = new DataProcessor() + const dataStorage = new Storage(DATA_DIR) + const loader = new DataLoader({ storage: dataStorage }) + const data: DataLoaderData = await loader.load() + const { feedsKeyByStreamId, channelsKeyById }: DataProcessorData = processor.process(data) + + const groupedChannels = this.channels + .map((channel: epgGrabber.Channel) => { + if (channel.xmltv_id && !channel.icon) { + const foundFeed: Feed = feedsKeyByStreamId.get(channel.xmltv_id) + if (foundFeed && foundFeed.hasLogo()) { + channel.icon = foundFeed.getLogoUrl() + } else { + const [channelId] = channel.xmltv_id.split('@') + const foundChannel: Channel = channelsKeyById.get(channelId) + if (foundChannel && foundChannel.hasLogo()) { + channel.icon = foundChannel.getLogoUrl() + } + } + } + + return channel + }) + .orderBy([ + (channel: epgGrabber.Channel) => channel.index, + (channel: epgGrabber.Channel) => channel.xmltv_id + ]) + .uniqBy( + (channel: epgGrabber.Channel) => `${channel.xmltv_id}:${channel.site}:${channel.lang}` + ) + .groupBy((channel: epgGrabber.Channel) => { + return pathTemplate.format({ lang: channel.lang || 'en', site: channel.site || '' }) + }) + + const groupedPrograms = this.programs + .orderBy([ + (program: epgGrabber.Program) => program.channel, + (program: epgGrabber.Program) => program.start + ]) + .groupBy((program: epgGrabber.Program) => { + const lang = + program.titles && program.titles.length && program.titles[0].lang + ? program.titles[0].lang + : 'en' + + return pathTemplate.format({ lang, site: program.site || '' }) + }) + + for (const groupKey of groupedPrograms.keys()) { + const guide = new Guide({ + filepath: groupKey, + gzip: this.options.gzip, + channels: new Collection(groupedChannels.get(groupKey)), + programs: new Collection(groupedPrograms.get(groupKey)) + }) + + await this.save(guide) + } + } + + async save(guide: Guide) { + const storage = new Storage(path.dirname(guide.filepath)) + const xmlFilepath = guide.filepath + const xmlFilename = path.basename(xmlFilepath) + this.logger.info(` saving to "${xmlFilepath}"...`) + const xmltv = guide.toString() + await storage.save(xmlFilename, xmltv) + + if (guide.gzip) { + const zip = new Zip() + const compressed = zip.compress(xmltv) + const gzFilepath = `${guide.filepath}.gz` + const gzFilename = path.basename(gzFilepath) + this.logger.info(` saving to "${gzFilepath}"...`) + await storage.save(gzFilename, compressed) + } + } +} diff --git a/scripts/core/htmlTable.ts b/scripts/core/htmlTable.ts index 144ba01b..6b917d6b 100644 --- a/scripts/core/htmlTable.ts +++ b/scripts/core/htmlTable.ts @@ -1,55 +1,55 @@ -type Column = { - name: string - nowrap?: boolean - align?: string - colspan?: number -} - -type DataItem = { - value: string - nowrap?: boolean - align?: string - colspan?: number -}[] - -export class HTMLTable { - data: DataItem[] - columns: Column[] - - constructor(data: DataItem[], columns: Column[]) { - this.data = data - this.columns = columns - } - - toString() { - let output = '\r\n' - - output += ' \r\n ' - for (const column of this.columns) { - const nowrap = column.nowrap ? ' nowrap' : '' - const align = column.align ? ` align="${column.align}"` : '' - const colspan = column.colspan ? ` colspan="${column.colspan}"` : '' - - output += `${column.name}` - } - output += '\r\n \r\n' - - output += ' \r\n' - for (const row of this.data) { - output += ' ' - for (const item of row) { - const nowrap = item.nowrap ? ' nowrap' : '' - const align = item.align ? ` align="${item.align}"` : '' - const colspan = item.colspan ? ` colspan="${item.colspan}"` : '' - - output += `${item.value}` - } - output += '\r\n' - } - output += ' \r\n' - - output += '
' - - return output - } -} +interface Column { + name: string + nowrap?: boolean + align?: string + colspan?: number +} + +type DataItem = { + value: string + nowrap?: boolean + align?: string + colspan?: number +}[] + +export class HTMLTable { + data: DataItem[] + columns: Column[] + + constructor(data: DataItem[], columns: Column[]) { + this.data = data + this.columns = columns + } + + toString() { + let output = '\r\n' + + output += ' \r\n ' + for (const column of this.columns) { + const nowrap = column.nowrap ? ' nowrap' : '' + const align = column.align ? ` align="${column.align}"` : '' + const colspan = column.colspan ? ` colspan="${column.colspan}"` : '' + + output += `${column.name}` + } + output += '\r\n \r\n' + + output += ' \r\n' + for (const row of this.data) { + output += ' ' + for (const item of row) { + const nowrap = item.nowrap ? ' nowrap' : '' + const align = item.align ? ` align="${item.align}"` : '' + const colspan = item.colspan ? ` colspan="${item.colspan}"` : '' + + output += `${item.value}` + } + output += '\r\n' + } + output += ' \r\n' + + output += '
' + + return output + } +} diff --git a/scripts/core/job.ts b/scripts/core/job.ts index 9dbf7308..db37ba15 100644 --- a/scripts/core/job.ts +++ b/scripts/core/job.ts @@ -1,34 +1,34 @@ -import { Logger } from '@freearhey/core' -import { Queue, Grabber, GuideManager } from '.' -import { GrabOptions } from '../commands/epg/grab' - -type JobProps = { - options: GrabOptions - logger: Logger - queue: Queue -} - -export class Job { - options: GrabOptions - logger: Logger - grabber: Grabber - - constructor({ queue, logger, options }: JobProps) { - this.options = options - this.logger = logger - this.grabber = new Grabber({ logger, queue, options }) - } - - async run() { - const { channels, programs } = await this.grabber.grab() - - const manager = new GuideManager({ - channels, - programs, - options: this.options, - logger: this.logger - }) - - await manager.createGuides() - } -} +import { Logger } from '@freearhey/core' +import { Queue, Grabber, GuideManager } from '.' +import { GrabOptions } from '../commands/epg/grab' + +interface JobProps { + options: GrabOptions + logger: Logger + queue: Queue +} + +export class Job { + options: GrabOptions + logger: Logger + grabber: Grabber + + constructor({ queue, logger, options }: JobProps) { + this.options = options + this.logger = logger + this.grabber = new Grabber({ logger, queue, options }) + } + + async run() { + const { channels, programs } = await this.grabber.grab() + + const manager = new GuideManager({ + channels, + programs, + options: this.options, + logger: this.logger + }) + + await manager.createGuides() + } +} diff --git a/scripts/core/proxyParser.ts b/scripts/core/proxyParser.ts index 3e316ab2..9cede1af 100644 --- a/scripts/core/proxyParser.ts +++ b/scripts/core/proxyParser.ts @@ -1,31 +1,31 @@ -import { URL } from 'node:url' - -type ProxyParserResult = { - protocol: string | null - auth?: { - username?: string - password?: string - } - host: string - port: number | null -} - -export class ProxyParser { - parse(_url: string): ProxyParserResult { - const parsed = new URL(_url) - - const result: ProxyParserResult = { - protocol: parsed.protocol.replace(':', '') || null, - host: parsed.hostname, - port: parsed.port ? parseInt(parsed.port) : null - } - - if (parsed.username || parsed.password) { - result.auth = {} - if (parsed.username) result.auth.username = parsed.username - if (parsed.password) result.auth.password = parsed.password - } - - return result - } -} +import { URL } from 'node:url' + +interface ProxyParserResult { + protocol: string | null + auth?: { + username?: string + password?: string + } + host: string + port: number | null +} + +export class ProxyParser { + parse(_url: string): ProxyParserResult { + const parsed = new URL(_url) + + const result: ProxyParserResult = { + protocol: parsed.protocol.replace(':', '') || null, + host: parsed.hostname, + port: parsed.port ? parseInt(parsed.port) : null + } + + if (parsed.username || parsed.password) { + result.auth = {} + if (parsed.username) result.auth.username = parsed.username + if (parsed.password) result.auth.password = parsed.password + } + + return result + } +} diff --git a/scripts/core/queue.ts b/scripts/core/queue.ts index 06ef3961..106c111e 100644 --- a/scripts/core/queue.ts +++ b/scripts/core/queue.ts @@ -1,45 +1,45 @@ -import { Dictionary } from '@freearhey/core' -import { SiteConfig, Channel } from 'epg-grabber' - -export type QueueItem = { - channel: Channel - date: string - config: SiteConfig - error: string | null -} - -export class Queue { - _data: Dictionary - - constructor() { - this._data = new Dictionary() - } - - missing(key: string): boolean { - return this._data.missing(key) - } - - add( - key: string, - { channel, config, date }: { channel: Channel; date: string | null; config: SiteConfig } - ) { - this._data.set(key, { - channel, - date, - config, - error: null - }) - } - - size(): number { - return Object.values(this._data.data()).length - } - - items(): QueueItem[] { - return Object.values(this._data.data()) as QueueItem[] - } - - isEmpty(): boolean { - return this.size() === 0 - } -} +import { Dictionary } from '@freearhey/core' +import { SiteConfig, Channel } from 'epg-grabber' + +export interface QueueItem { + channel: Channel + date: string + config: SiteConfig + error: string | null +} + +export class Queue { + _data: Dictionary + + constructor() { + this._data = new Dictionary() + } + + missing(key: string): boolean { + return this._data.missing(key) + } + + add( + key: string, + { channel, config, date }: { channel: Channel; date: string | null; config: SiteConfig } + ) { + this._data.set(key, { + channel, + date, + config, + error: null + }) + } + + size(): number { + return Object.values(this._data.data()).length + } + + items(): QueueItem[] { + return Object.values(this._data.data()) as QueueItem[] + } + + isEmpty(): boolean { + return this.size() === 0 + } +} diff --git a/scripts/core/queueCreator.ts b/scripts/core/queueCreator.ts index 71213630..56333dcb 100644 --- a/scripts/core/queueCreator.ts +++ b/scripts/core/queueCreator.ts @@ -1,63 +1,63 @@ -import { Storage, Collection, DateTime, Logger } from '@freearhey/core' -import { SITES_DIR, DATA_DIR } from '../constants' -import { GrabOptions } from '../commands/epg/grab' -import { ConfigLoader, Queue } from './' -import { SiteConfig } from 'epg-grabber' -import path from 'path' - -type QueueCreatorProps = { - logger: Logger - options: GrabOptions - channels: Collection -} - -export class QueueCreator { - configLoader: ConfigLoader - logger: Logger - sitesStorage: Storage - dataStorage: Storage - channels: Collection - options: GrabOptions - - constructor({ channels, logger, options }: QueueCreatorProps) { - this.channels = channels - this.logger = logger - this.sitesStorage = new Storage() - this.dataStorage = new Storage(DATA_DIR) - this.options = options - this.configLoader = new ConfigLoader() - } - - async create(): Promise { - let index = 0 - const queue = new Queue() - for (const channel of this.channels.all()) { - channel.index = index++ - if (!channel.site || !channel.site_id || !channel.name) continue - - const configPath = path.resolve(SITES_DIR, `${channel.site}/${channel.site}.config.js`) - const config: SiteConfig = await this.configLoader.load(configPath) - - if (!channel.xmltv_id) { - channel.xmltv_id = channel.site_id - } - - const days = this.options.days || config.days || 1 - const currDate = new DateTime(process.env.CURR_DATE || new Date().toISOString()) - const dates = Array.from({ length: days }, (_, day) => currDate.add(day, 'd')) - dates.forEach((date: DateTime) => { - const dateString = date.toJSON() - const key = `${channel.site}:${channel.lang}:${channel.xmltv_id}:${dateString}` - if (queue.missing(key)) { - queue.add(key, { - channel, - date: dateString, - config - }) - } - }) - } - - return queue - } -} +import { Storage, Collection, DateTime, Logger } from '@freearhey/core' +import { SITES_DIR, DATA_DIR } from '../constants' +import { GrabOptions } from '../commands/epg/grab' +import { ConfigLoader, Queue } from './' +import { SiteConfig } from 'epg-grabber' +import path from 'path' + +interface QueueCreatorProps { + logger: Logger + options: GrabOptions + channels: Collection +} + +export class QueueCreator { + configLoader: ConfigLoader + logger: Logger + sitesStorage: Storage + dataStorage: Storage + channels: Collection + options: GrabOptions + + constructor({ channels, logger, options }: QueueCreatorProps) { + this.channels = channels + this.logger = logger + this.sitesStorage = new Storage() + this.dataStorage = new Storage(DATA_DIR) + this.options = options + this.configLoader = new ConfigLoader() + } + + async create(): Promise { + let index = 0 + const queue = new Queue() + for (const channel of this.channels.all()) { + channel.index = index++ + if (!channel.site || !channel.site_id || !channel.name) continue + + const configPath = path.resolve(SITES_DIR, `${channel.site}/${channel.site}.config.js`) + const config: SiteConfig = await this.configLoader.load(configPath) + + if (!channel.xmltv_id) { + channel.xmltv_id = channel.site_id + } + + const days = this.options.days || config.days || 1 + const currDate = new DateTime(process.env.CURR_DATE || new Date().toISOString()) + const dates = Array.from({ length: days }, (_, day) => currDate.add(day, 'd')) + dates.forEach((date: DateTime) => { + const dateString = date.toJSON() + const key = `${channel.site}:${channel.lang}:${channel.xmltv_id}:${dateString}` + if (queue.missing(key)) { + queue.add(key, { + channel, + date: dateString, + config + }) + } + }) + } + + return queue + } +} diff --git a/scripts/functions/functions.ts b/scripts/functions/functions.ts index f97b84f8..f6e0bb63 100644 --- a/scripts/functions/functions.ts +++ b/scripts/functions/functions.ts @@ -1,77 +1,77 @@ -/** - * Sorts an array by the result of running each element through an iteratee function. - * Creates a shallow copy of the array before sorting to avoid mutating the original. - * - * @param {Array} arr - The array to sort - * @param {Function} fn - The iteratee function to compute sort values - * @returns {Array} A new sorted array - * - * @example - * const users = [{name: 'john', age: 30}, {name: 'jane', age: 25}]; - * sortBy(users, x => x.age); // [{name: 'jane', age: 25}, {name: 'john', age: 30}] - */ -export const sortBy = (arr: T[], fn: (item: T) => number | string): T[] => - [...arr].sort((a, b) => (fn(a) > fn(b) ? 1 : -1)) - -/** - * Sorts an array by multiple criteria with customizable sort orders. - * Supports ascending (default) and descending order for each criterion. - * - * @param {Array} arr - The array to sort - * @param {Array} fns - Array of iteratee functions to compute sort values - * @param {Array} orders - Array of sort orders ('asc' or 'desc'), defaults to all 'asc' - * @returns {Array} A new sorted array - * - * @example - * const users = [{name: 'john', age: 30}, {name: 'jane', age: 25}, {name: 'bob', age: 30}]; - * orderBy(users, [x => x.age, x => x.name], ['desc', 'asc']); - * // [{name: 'bob', age: 30}, {name: 'john', age: 30}, {name: 'jane', age: 25}] - */ -export const orderBy = ( - arr: Array, - fns: Array<(item: unknown) => string | number>, - orders: Array = [] -): Array => - [...arr].sort((a, b) => - fns.reduce( - (acc, fn, i) => - acc || - ((orders[i] === 'desc' ? fn(b) > fn(a) : fn(a) > fn(b)) ? 1 : fn(a) === fn(b) ? 0 : -1), - 0 - ) - ) - -/** - * Creates a duplicate-free version of an array using an iteratee function to generate - * the criterion by which uniqueness is computed. Only the first occurrence of each - * element is kept. - * - * @param {Array} arr - The array to inspect - * @param {Function} fn - The iteratee function to compute uniqueness criterion - * @returns {Array} A new duplicate-free array - * - * @example - * const users = [{id: 1, name: 'john'}, {id: 2, name: 'jane'}, {id: 1, name: 'john'}]; - * uniqBy(users, x => x.id); // [{id: 1, name: 'john'}, {id: 2, name: 'jane'}] - */ -export const uniqBy = (arr: T[], fn: (item: T) => unknown): T[] => - arr.filter((item, index) => arr.findIndex(x => fn(x) === fn(item)) === index) - -/** - * Converts a string to start case (capitalizes the first letter of each word). - * Handles camelCase, snake_case, kebab-case, and regular spaces. - * - * @param {string} str - The string to convert - * @returns {string} The start case string - * - * @example - * startCase('hello_world'); // "Hello World" - * startCase('helloWorld'); // "Hello World" - * startCase('hello-world'); // "Hello World" - * startCase('hello world'); // "Hello World" - */ -export const startCase = (str: string): string => - str - .replace(/([a-z])([A-Z])/g, '$1 $2') // Split camelCase - .replace(/[_-]/g, ' ') // Replace underscores and hyphens with spaces - .replace(/\b\w/g, c => c.toUpperCase()) // Capitalize first letter of each word +/** + * Sorts an array by the result of running each element through an iteratee function. + * Creates a shallow copy of the array before sorting to avoid mutating the original. + * + * @param {Array} arr - The array to sort + * @param {Function} fn - The iteratee function to compute sort values + * @returns {Array} A new sorted array + * + * @example + * const users = [{name: 'john', age: 30}, {name: 'jane', age: 25}]; + * sortBy(users, x => x.age); // [{name: 'jane', age: 25}, {name: 'john', age: 30}] + */ +export const sortBy = (arr: T[], fn: (item: T) => number | string): T[] => + [...arr].sort((a, b) => (fn(a) > fn(b) ? 1 : -1)) + +/** + * Sorts an array by multiple criteria with customizable sort orders. + * Supports ascending (default) and descending order for each criterion. + * + * @param {Array} arr - The array to sort + * @param {Array} fns - Array of iteratee functions to compute sort values + * @param {Array} orders - Array of sort orders ('asc' or 'desc'), defaults to all 'asc' + * @returns {Array} A new sorted array + * + * @example + * const users = [{name: 'john', age: 30}, {name: 'jane', age: 25}, {name: 'bob', age: 30}]; + * orderBy(users, [x => x.age, x => x.name], ['desc', 'asc']); + * // [{name: 'bob', age: 30}, {name: 'john', age: 30}, {name: 'jane', age: 25}] + */ +export const orderBy = ( + arr: unknown[], + fns: ((item: unknown) => string | number)[], + orders: string[] = [] +): unknown[] => + [...arr].sort((a, b) => + fns.reduce( + (acc, fn, i) => + acc || + ((orders[i] === 'desc' ? fn(b) > fn(a) : fn(a) > fn(b)) ? 1 : fn(a) === fn(b) ? 0 : -1), + 0 + ) + ) + +/** + * Creates a duplicate-free version of an array using an iteratee function to generate + * the criterion by which uniqueness is computed. Only the first occurrence of each + * element is kept. + * + * @param {Array} arr - The array to inspect + * @param {Function} fn - The iteratee function to compute uniqueness criterion + * @returns {Array} A new duplicate-free array + * + * @example + * const users = [{id: 1, name: 'john'}, {id: 2, name: 'jane'}, {id: 1, name: 'john'}]; + * uniqBy(users, x => x.id); // [{id: 1, name: 'john'}, {id: 2, name: 'jane'}] + */ +export const uniqBy = (arr: T[], fn: (item: T) => unknown): T[] => + arr.filter((item, index) => arr.findIndex(x => fn(x) === fn(item)) === index) + +/** + * Converts a string to start case (capitalizes the first letter of each word). + * Handles camelCase, snake_case, kebab-case, and regular spaces. + * + * @param {string} str - The string to convert + * @returns {string} The start case string + * + * @example + * startCase('hello_world'); // "Hello World" + * startCase('helloWorld'); // "Hello World" + * startCase('hello-world'); // "Hello World" + * startCase('hello world'); // "Hello World" + */ +export const startCase = (str: string): string => + str + .replace(/([a-z])([A-Z])/g, '$1 $2') // Split camelCase + .replace(/[_-]/g, ' ') // Replace underscores and hyphens with spaces + .replace(/\b\w/g, c => c.toUpperCase()) // Capitalize first letter of each word diff --git a/scripts/models/channel.ts b/scripts/models/channel.ts index fb62a3fc..e5bbde5e 100644 --- a/scripts/models/channel.ts +++ b/scripts/models/channel.ts @@ -1,164 +1,164 @@ -import { ChannelData, ChannelSearchableData } from '../types/channel' -import { Collection, Dictionary } from '@freearhey/core' -import { Stream, Feed, Logo, GuideChannel } from './' - -export class Channel { - id?: string - name?: string - altNames?: Collection - network?: string - owners?: Collection - countryCode?: string - subdivisionCode?: string - cityName?: string - categoryIds?: Collection - isNSFW: boolean = false - launched?: string - closed?: string - replacedBy?: string - website?: string - feeds?: Collection - logos: Collection = new Collection() - - constructor(data?: ChannelData) { - if (!data) return - - this.id = data.id - this.name = data.name - this.altNames = new Collection(data.alt_names) - this.network = data.network || undefined - this.owners = new Collection(data.owners) - this.countryCode = data.country - this.subdivisionCode = data.subdivision || undefined - this.cityName = data.city || undefined - this.categoryIds = new Collection(data.categories) - this.isNSFW = data.is_nsfw - this.launched = data.launched || undefined - this.closed = data.closed || undefined - this.replacedBy = data.replaced_by || undefined - this.website = data.website || undefined - } - - withFeeds(feedsGroupedByChannelId: Dictionary): this { - if (this.id) this.feeds = new Collection(feedsGroupedByChannelId.get(this.id)) - - return this - } - - withLogos(logosGroupedByChannelId: Dictionary): this { - if (this.id) this.logos = new Collection(logosGroupedByChannelId.get(this.id)) - - return this - } - - getFeeds(): Collection { - if (!this.feeds) return new Collection() - - return this.feeds - } - - getGuideChannels(): Collection { - let channels = new Collection() - - this.getFeeds().forEach((feed: Feed) => { - channels = channels.concat(feed.getGuideChannels()) - }) - - return channels - } - - getGuideChannelNames(): Collection { - return this.getGuideChannels() - .map((channel: GuideChannel) => channel.siteName) - .uniq() - } - - getStreams(): Collection { - let streams = new Collection() - - this.getFeeds().forEach((feed: Feed) => { - streams = streams.concat(feed.getStreams()) - }) - - return streams - } - - getStreamNames(): Collection { - return this.getStreams() - .map((stream: Stream) => stream.getName()) - .uniq() - } - - getFeedFullNames(): Collection { - return this.getFeeds() - .map((feed: Feed) => feed.getFullName()) - .uniq() - } - - getName(): string { - return this.name || '' - } - - getId(): string { - return this.id || '' - } - - getAltNames(): Collection { - return this.altNames || new Collection() - } - - getLogos(): Collection { - function feed(logo: Logo): number { - if (!logo.feed) return 1 - if (logo.feed.isMain) return 1 - - return 0 - } - - function format(logo: Logo): number { - const levelByFormat: { [key: string]: number } = { - SVG: 0, - PNG: 3, - APNG: 1, - WebP: 1, - AVIF: 1, - JPEG: 2, - GIF: 1 - } - - return logo.format ? levelByFormat[logo.format] : 0 - } - - function size(logo: Logo): number { - return Math.abs(512 - logo.width) + Math.abs(512 - logo.height) - } - - return this.logos.orderBy([feed, format, size], ['desc', 'desc', 'asc'], false) - } - - getLogo(): Logo | undefined { - return this.getLogos().first() - } - - hasLogo(): boolean { - return this.getLogos().notEmpty() - } - - getLogoUrl(): string { - const logo = this.getLogo() - if (!logo) return '' - - return logo.url || '' - } - - getSearchable(): ChannelSearchableData { - return { - id: this.getId(), - name: this.getName(), - altNames: this.getAltNames().all(), - guideNames: this.getGuideChannelNames().all(), - streamNames: this.getStreamNames().all(), - feedFullNames: this.getFeedFullNames().all() - } - } -} +import { ChannelData, ChannelSearchableData } from '../types/channel' +import { Collection, Dictionary } from '@freearhey/core' +import { Stream, Feed, Logo, GuideChannel } from './' + +export class Channel { + id?: string + name?: string + altNames?: Collection + network?: string + owners?: Collection + countryCode?: string + subdivisionCode?: string + cityName?: string + categoryIds?: Collection + isNSFW = false + launched?: string + closed?: string + replacedBy?: string + website?: string + feeds?: Collection + logos: Collection = new Collection() + + constructor(data?: ChannelData) { + if (!data) return + + this.id = data.id + this.name = data.name + this.altNames = new Collection(data.alt_names) + this.network = data.network || undefined + this.owners = new Collection(data.owners) + this.countryCode = data.country + this.subdivisionCode = data.subdivision || undefined + this.cityName = data.city || undefined + this.categoryIds = new Collection(data.categories) + this.isNSFW = data.is_nsfw + this.launched = data.launched || undefined + this.closed = data.closed || undefined + this.replacedBy = data.replaced_by || undefined + this.website = data.website || undefined + } + + withFeeds(feedsGroupedByChannelId: Dictionary): this { + if (this.id) this.feeds = new Collection(feedsGroupedByChannelId.get(this.id)) + + return this + } + + withLogos(logosGroupedByChannelId: Dictionary): this { + if (this.id) this.logos = new Collection(logosGroupedByChannelId.get(this.id)) + + return this + } + + getFeeds(): Collection { + if (!this.feeds) return new Collection() + + return this.feeds + } + + getGuideChannels(): Collection { + let channels = new Collection() + + this.getFeeds().forEach((feed: Feed) => { + channels = channels.concat(feed.getGuideChannels()) + }) + + return channels + } + + getGuideChannelNames(): Collection { + return this.getGuideChannels() + .map((channel: GuideChannel) => channel.siteName) + .uniq() + } + + getStreams(): Collection { + let streams = new Collection() + + this.getFeeds().forEach((feed: Feed) => { + streams = streams.concat(feed.getStreams()) + }) + + return streams + } + + getStreamNames(): Collection { + return this.getStreams() + .map((stream: Stream) => stream.getName()) + .uniq() + } + + getFeedFullNames(): Collection { + return this.getFeeds() + .map((feed: Feed) => feed.getFullName()) + .uniq() + } + + getName(): string { + return this.name || '' + } + + getId(): string { + return this.id || '' + } + + getAltNames(): Collection { + return this.altNames || new Collection() + } + + getLogos(): Collection { + function feed(logo: Logo): number { + if (!logo.feed) return 1 + if (logo.feed.isMain) return 1 + + return 0 + } + + function format(logo: Logo): number { + const levelByFormat: Record = { + SVG: 0, + PNG: 3, + APNG: 1, + WebP: 1, + AVIF: 1, + JPEG: 2, + GIF: 1 + } + + return logo.format ? levelByFormat[logo.format] : 0 + } + + function size(logo: Logo): number { + return Math.abs(512 - logo.width) + Math.abs(512 - logo.height) + } + + return this.logos.orderBy([feed, format, size], ['desc', 'desc', 'asc'], false) + } + + getLogo(): Logo | undefined { + return this.getLogos().first() + } + + hasLogo(): boolean { + return this.getLogos().notEmpty() + } + + getLogoUrl(): string { + const logo = this.getLogo() + if (!logo) return '' + + return logo.url || '' + } + + getSearchable(): ChannelSearchableData { + return { + id: this.getId(), + name: this.getName(), + altNames: this.getAltNames().all(), + guideNames: this.getGuideChannelNames().all(), + streamNames: this.getStreamNames().all(), + feedFullNames: this.getFeedFullNames().all() + } + } +} diff --git a/scripts/models/channelList.ts b/scripts/models/channelList.ts index d312e71c..951e0a90 100644 --- a/scripts/models/channelList.ts +++ b/scripts/models/channelList.ts @@ -1,77 +1,77 @@ -import { Collection } from '@freearhey/core' -import epgGrabber from 'epg-grabber' - -export class ChannelList { - channels: Collection = new Collection() - - constructor(data: { channels: epgGrabber.Channel[] }) { - this.channels = new Collection(data.channels) - } - - add(channel: epgGrabber.Channel): this { - this.channels.add(channel) - - return this - } - - get(siteId: string): epgGrabber.Channel | undefined { - return this.channels.find((channel: epgGrabber.Channel) => channel.site_id == siteId) - } - - sort(): this { - this.channels = this.channels.orderBy([ - (channel: epgGrabber.Channel) => channel.lang || '_', - (channel: epgGrabber.Channel) => (channel.xmltv_id ? channel.xmltv_id.toLowerCase() : '0'), - (channel: epgGrabber.Channel) => channel.site_id - ]) - - return this - } - - toString() { - function escapeString(value: string, defaultValue: string = '') { - if (!value) return defaultValue - - const regex = new RegExp( - '((?:[\0-\x08\x0B\f\x0E-\x1F\uFFFD\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))|([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|(?:\\uD83F[\\uDFFE\\uDFFF])|(?:\\uD87F[\\uDF' + - 'FE\\uDFFF])|(?:\\uD8BF[\\uDFFE\\uDFFF])|(?:\\uD8FF[\\uDFFE\\uDFFF])|(?:\\uD93F[\\uDFFE\\uD' + - 'FFF])|(?:\\uD97F[\\uDFFE\\uDFFF])|(?:\\uD9BF[\\uDFFE\\uDFFF])|(?:\\uD9FF[\\uDFFE\\uDFFF])' + - '|(?:\\uDA3F[\\uDFFE\\uDFFF])|(?:\\uDA7F[\\uDFFE\\uDFFF])|(?:\\uDABF[\\uDFFE\\uDFFF])|(?:\\' + - 'uDAFF[\\uDFFE\\uDFFF])|(?:\\uDB3F[\\uDFFE\\uDFFF])|(?:\\uDB7F[\\uDFFE\\uDFFF])|(?:\\uDBBF' + - '[\\uDFFE\\uDFFF])|(?:\\uDBFF[\\uDFFE\\uDFFF])(?:[\\0-\\t\\x0B\\f\\x0E-\\u2027\\u202A-\\uD7FF\\' + - 'uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|' + - '(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))', - 'g' - ) - - value = String(value || '').replace(regex, '') - - return value - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(/\n|\r/g, ' ') - .replace(/ +/g, ' ') - .trim() - } - - let output = '\r\n\r\n' - - this.channels.forEach((channel: epgGrabber.Channel) => { - const logo = channel.logo ? ` logo="${channel.logo}"` : '' - const xmltv_id = channel.xmltv_id ? escapeString(channel.xmltv_id) : '' - const lang = channel.lang || '' - const site_id = channel.site_id || '' - const site = channel.site || '' - const displayName = channel.name ? escapeString(channel.name) : '' - - output += ` ${displayName}\r\n` - }) - - output += '\r\n' - - return output - } -} +import { Collection } from '@freearhey/core' +import epgGrabber from 'epg-grabber' + +export class ChannelList { + channels: Collection = new Collection() + + constructor(data: { channels: epgGrabber.Channel[] }) { + this.channels = new Collection(data.channels) + } + + add(channel: epgGrabber.Channel): this { + this.channels.add(channel) + + return this + } + + get(siteId: string): epgGrabber.Channel | undefined { + return this.channels.find((channel: epgGrabber.Channel) => channel.site_id == siteId) + } + + sort(): this { + this.channels = this.channels.orderBy([ + (channel: epgGrabber.Channel) => channel.lang || '_', + (channel: epgGrabber.Channel) => (channel.xmltv_id ? channel.xmltv_id.toLowerCase() : '0'), + (channel: epgGrabber.Channel) => channel.site_id + ]) + + return this + } + + toString() { + function escapeString(value: string, defaultValue = '') { + if (!value) return defaultValue + + const regex = new RegExp( + '((?:[\0-\x08\x0B\f\x0E-\x1F\uFFFD\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))|([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|(?:\\uD83F[\\uDFFE\\uDFFF])|(?:\\uD87F[\\uDF' + + 'FE\\uDFFF])|(?:\\uD8BF[\\uDFFE\\uDFFF])|(?:\\uD8FF[\\uDFFE\\uDFFF])|(?:\\uD93F[\\uDFFE\\uD' + + 'FFF])|(?:\\uD97F[\\uDFFE\\uDFFF])|(?:\\uD9BF[\\uDFFE\\uDFFF])|(?:\\uD9FF[\\uDFFE\\uDFFF])' + + '|(?:\\uDA3F[\\uDFFE\\uDFFF])|(?:\\uDA7F[\\uDFFE\\uDFFF])|(?:\\uDABF[\\uDFFE\\uDFFF])|(?:\\' + + 'uDAFF[\\uDFFE\\uDFFF])|(?:\\uDB3F[\\uDFFE\\uDFFF])|(?:\\uDB7F[\\uDFFE\\uDFFF])|(?:\\uDBBF' + + '[\\uDFFE\\uDFFF])|(?:\\uDBFF[\\uDFFE\\uDFFF])(?:[\\0-\\t\\x0B\\f\\x0E-\\u2027\\u202A-\\uD7FF\\' + + 'uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|' + + '(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))', + 'g' + ) + + value = String(value || '').replace(regex, '') + + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/\n|\r/g, ' ') + .replace(/ +/g, ' ') + .trim() + } + + let output = '\r\n\r\n' + + this.channels.forEach((channel: epgGrabber.Channel) => { + const logo = channel.logo ? ` logo="${channel.logo}"` : '' + const xmltv_id = channel.xmltv_id ? escapeString(channel.xmltv_id) : '' + const lang = channel.lang || '' + const site_id = channel.site_id || '' + const site = channel.site || '' + const displayName = channel.name ? escapeString(channel.name) : '' + + output += ` ${displayName}\r\n` + }) + + output += '\r\n' + + return output + } +} diff --git a/scripts/models/feed.ts b/scripts/models/feed.ts index bb2c7020..7e91e305 100644 --- a/scripts/models/feed.ts +++ b/scripts/models/feed.ts @@ -1,124 +1,124 @@ -import { Collection, Dictionary } from '@freearhey/core' -import { FeedData } from '../types/feed' -import { Logo, Channel } from '.' - -export class Feed { - channelId: string - channel?: Channel - id: string - name: string - isMain: boolean - broadcastAreaCodes: Collection - languageCodes: Collection - timezoneIds: Collection - videoFormat: string - guideChannels?: Collection - streams?: Collection - logos: Collection = new Collection() - - constructor(data: FeedData) { - this.channelId = data.channel - this.id = data.id - this.name = data.name - this.isMain = data.is_main - this.broadcastAreaCodes = new Collection(data.broadcast_area) - this.languageCodes = new Collection(data.languages) - this.timezoneIds = new Collection(data.timezones) - this.videoFormat = data.video_format - } - - withChannel(channelsKeyById: Dictionary): this { - this.channel = channelsKeyById.get(this.channelId) - - return this - } - - withStreams(streamsGroupedById: Dictionary): this { - this.streams = new Collection(streamsGroupedById.get(`${this.channelId}@${this.id}`)) - - if (this.isMain) { - this.streams = this.streams.concat(new Collection(streamsGroupedById.get(this.channelId))) - } - - return this - } - - withGuideChannels(guideChannelsGroupedByStreamId: Dictionary): this { - this.guideChannels = new Collection( - guideChannelsGroupedByStreamId.get(`${this.channelId}@${this.id}`) - ) - - if (this.isMain) { - this.guideChannels = this.guideChannels.concat( - new Collection(guideChannelsGroupedByStreamId.get(this.channelId)) - ) - } - - return this - } - - withLogos(logosGroupedByStreamId: Dictionary): this { - this.logos = new Collection(logosGroupedByStreamId.get(this.getStreamId())) - - return this - } - - getGuideChannels(): Collection { - if (!this.guideChannels) return new Collection() - - return this.guideChannels - } - - getStreams(): Collection { - if (!this.streams) return new Collection() - - return this.streams - } - - getFullName(): string { - if (!this.channel) return '' - - return `${this.channel.name} ${this.name}` - } - - getStreamId(): string { - return `${this.channelId}@${this.id}` - } - - getLogos(): Collection { - function format(logo: Logo): number { - const levelByFormat: { [key: string]: number } = { - SVG: 0, - PNG: 3, - APNG: 1, - WebP: 1, - AVIF: 1, - JPEG: 2, - GIF: 1 - } - - return logo.format ? levelByFormat[logo.format] : 0 - } - - function size(logo: Logo): number { - return Math.abs(512 - logo.width) + Math.abs(512 - logo.height) - } - - return this.logos.orderBy([format, size], ['desc', 'asc'], false) - } - - getLogo(): Logo | undefined { - return this.getLogos().first() - } - - hasLogo(): boolean { - return this.getLogos().notEmpty() - } - - getLogoUrl(): string { - const logo = this.getLogo() - if (!logo) return '' - - return logo.url || '' - } -} +import { Collection, Dictionary } from '@freearhey/core' +import { FeedData } from '../types/feed' +import { Logo, Channel } from '.' + +export class Feed { + channelId: string + channel?: Channel + id: string + name: string + isMain: boolean + broadcastAreaCodes: Collection + languageCodes: Collection + timezoneIds: Collection + videoFormat: string + guideChannels?: Collection + streams?: Collection + logos: Collection = new Collection() + + constructor(data: FeedData) { + this.channelId = data.channel + this.id = data.id + this.name = data.name + this.isMain = data.is_main + this.broadcastAreaCodes = new Collection(data.broadcast_area) + this.languageCodes = new Collection(data.languages) + this.timezoneIds = new Collection(data.timezones) + this.videoFormat = data.video_format + } + + withChannel(channelsKeyById: Dictionary): this { + this.channel = channelsKeyById.get(this.channelId) + + return this + } + + withStreams(streamsGroupedById: Dictionary): this { + this.streams = new Collection(streamsGroupedById.get(`${this.channelId}@${this.id}`)) + + if (this.isMain) { + this.streams = this.streams.concat(new Collection(streamsGroupedById.get(this.channelId))) + } + + return this + } + + withGuideChannels(guideChannelsGroupedByStreamId: Dictionary): this { + this.guideChannels = new Collection( + guideChannelsGroupedByStreamId.get(`${this.channelId}@${this.id}`) + ) + + if (this.isMain) { + this.guideChannels = this.guideChannels.concat( + new Collection(guideChannelsGroupedByStreamId.get(this.channelId)) + ) + } + + return this + } + + withLogos(logosGroupedByStreamId: Dictionary): this { + this.logos = new Collection(logosGroupedByStreamId.get(this.getStreamId())) + + return this + } + + getGuideChannels(): Collection { + if (!this.guideChannels) return new Collection() + + return this.guideChannels + } + + getStreams(): Collection { + if (!this.streams) return new Collection() + + return this.streams + } + + getFullName(): string { + if (!this.channel) return '' + + return `${this.channel.name} ${this.name}` + } + + getStreamId(): string { + return `${this.channelId}@${this.id}` + } + + getLogos(): Collection { + function format(logo: Logo): number { + const levelByFormat: Record = { + SVG: 0, + PNG: 3, + APNG: 1, + WebP: 1, + AVIF: 1, + JPEG: 2, + GIF: 1 + } + + return logo.format ? levelByFormat[logo.format] : 0 + } + + function size(logo: Logo): number { + return Math.abs(512 - logo.width) + Math.abs(512 - logo.height) + } + + return this.logos.orderBy([format, size], ['desc', 'asc'], false) + } + + getLogo(): Logo | undefined { + return this.getLogos().first() + } + + hasLogo(): boolean { + return this.getLogos().notEmpty() + } + + getLogoUrl(): string { + const logo = this.getLogo() + if (!logo) return '' + + return logo.url || '' + } +} diff --git a/scripts/models/guide.ts b/scripts/models/guide.ts index b6026743..4072c8bc 100644 --- a/scripts/models/guide.ts +++ b/scripts/models/guide.ts @@ -1,35 +1,35 @@ -import { Collection, DateTime } from '@freearhey/core' -import { generateXMLTV } from 'epg-grabber' - -type GuideData = { - channels: Collection - programs: Collection - filepath: string - gzip: boolean -} - -export class Guide { - channels: Collection - programs: Collection - filepath: string - gzip: boolean - - constructor({ channels, programs, filepath, gzip }: GuideData) { - this.channels = channels - this.programs = programs - this.filepath = filepath - this.gzip = gzip || false - } - - toString() { - const currDate = new DateTime(process.env.CURR_DATE || new Date().toISOString(), { - timezone: 'UTC' - }) - - return generateXMLTV({ - channels: this.channels.all(), - programs: this.programs.all(), - date: currDate.toJSON() - }) - } -} +import { Collection, DateTime } from '@freearhey/core' +import { generateXMLTV } from 'epg-grabber' + +interface GuideData { + channels: Collection + programs: Collection + filepath: string + gzip: boolean +} + +export class Guide { + channels: Collection + programs: Collection + filepath: string + gzip: boolean + + constructor({ channels, programs, filepath, gzip }: GuideData) { + this.channels = channels + this.programs = programs + this.filepath = filepath + this.gzip = gzip || false + } + + toString() { + const currDate = new DateTime(process.env.CURR_DATE || new Date().toISOString(), { + timezone: 'UTC' + }) + + return generateXMLTV({ + channels: this.channels.all(), + programs: this.programs.all(), + date: currDate.toJSON() + }) + } +} diff --git a/scripts/models/issue.ts b/scripts/models/issue.ts index d9653a4f..a26e71ff 100644 --- a/scripts/models/issue.ts +++ b/scripts/models/issue.ts @@ -1,24 +1,24 @@ -import { Dictionary } from '@freearhey/core' -import { OWNER, REPO } from '../constants' - -type IssueProps = { - number: number - labels: string[] - data: Dictionary -} - -export class Issue { - number: number - labels: string[] - data: Dictionary - - constructor({ number, labels, data }: IssueProps) { - this.number = number - this.labels = labels - this.data = data - } - - getURL() { - return `https://github.com/${OWNER}/${REPO}/issues/${this.number}` - } -} +import { Dictionary } from '@freearhey/core' +import { OWNER, REPO } from '../constants' + +interface IssueProps { + number: number + labels: string[] + data: Dictionary +} + +export class Issue { + number: number + labels: string[] + data: Dictionary + + constructor({ number, labels, data }: IssueProps) { + this.number = number + this.labels = labels + this.data = data + } + + getURL() { + return `https://github.com/${OWNER}/${REPO}/issues/${this.number}` + } +} diff --git a/scripts/models/logo.ts b/scripts/models/logo.ts index d864a3fb..e08f443e 100644 --- a/scripts/models/logo.ts +++ b/scripts/models/logo.ts @@ -1,41 +1,41 @@ -import { Collection, type Dictionary } from '@freearhey/core' -import type { LogoData } from '../types/logo' -import { type Feed } from './feed' - -export class Logo { - channelId?: string - feedId?: string - feed?: Feed - tags: Collection = new Collection() - width: number = 0 - height: number = 0 - format?: string - url?: string - - constructor(data?: LogoData) { - if (!data) return - - this.channelId = data.channel - this.feedId = data.feed || undefined - this.tags = new Collection(data.tags) - this.width = data.width - this.height = data.height - this.format = data.format || undefined - this.url = data.url - } - - withFeed(feedsKeyByStreamId: Dictionary): this { - if (!this.feedId) return this - - this.feed = feedsKeyByStreamId.get(this.getStreamId()) - - return this - } - - getStreamId(): string { - if (!this.channelId) return '' - if (!this.feedId) return this.channelId - - return `${this.channelId}@${this.feedId}` - } -} +import { Collection, type Dictionary } from '@freearhey/core' +import type { LogoData } from '../types/logo' +import { type Feed } from './feed' + +export class Logo { + channelId?: string + feedId?: string + feed?: Feed + tags: Collection = new Collection() + width = 0 + height = 0 + format?: string + url?: string + + constructor(data?: LogoData) { + if (!data) return + + this.channelId = data.channel + this.feedId = data.feed || undefined + this.tags = new Collection(data.tags) + this.width = data.width + this.height = data.height + this.format = data.format || undefined + this.url = data.url + } + + withFeed(feedsKeyByStreamId: Dictionary): this { + if (!this.feedId) return this + + this.feed = feedsKeyByStreamId.get(this.getStreamId()) + + return this + } + + getStreamId(): string { + if (!this.channelId) return '' + if (!this.feedId) return this.channelId + + return `${this.channelId}@${this.feedId}` + } +} diff --git a/scripts/models/site.ts b/scripts/models/site.ts index fa95165f..d4ddfdaa 100644 --- a/scripts/models/site.ts +++ b/scripts/models/site.ts @@ -1,63 +1,63 @@ -import { Collection } from '@freearhey/core' -import { Issue } from './' - -enum StatusCode { - DOWN = 'down', - WARNING = 'warning', - OK = 'ok' -} - -type Status = { - code: StatusCode - emoji: string -} - -type SiteProps = { - domain: string - totalChannels?: number - markedChannels?: number - issues: Collection -} - -export class Site { - domain: string - totalChannels: number - markedChannels: number - issues: Collection - - constructor({ domain, totalChannels = 0, markedChannels = 0, issues }: SiteProps) { - this.domain = domain - this.totalChannels = totalChannels - this.markedChannels = markedChannels - this.issues = issues - } - - getStatus(): Status { - const issuesWithStatusDown = this.issues.filter((issue: Issue) => - issue.labels.find(label => label === 'status:down') - ) - if (issuesWithStatusDown.notEmpty()) - return { - code: StatusCode.DOWN, - emoji: '🔴' - } - - const issuesWithStatusWarning = this.issues.filter((issue: Issue) => - issue.labels.find(label => label === 'status:warning') - ) - if (issuesWithStatusWarning.notEmpty()) - return { - code: StatusCode.WARNING, - emoji: '🟡' - } - - return { - code: StatusCode.OK, - emoji: '🟢' - } - } - - getIssues(): Collection { - return this.issues.map((issue: Issue) => issue.getURL()) - } -} +import { Collection } from '@freearhey/core' +import { Issue } from './' + +enum StatusCode { + DOWN = 'down', + WARNING = 'warning', + OK = 'ok' +} + +interface Status { + code: StatusCode + emoji: string +} + +interface SiteProps { + domain: string + totalChannels?: number + markedChannels?: number + issues: Collection +} + +export class Site { + domain: string + totalChannels: number + markedChannels: number + issues: Collection + + constructor({ domain, totalChannels = 0, markedChannels = 0, issues }: SiteProps) { + this.domain = domain + this.totalChannels = totalChannels + this.markedChannels = markedChannels + this.issues = issues + } + + getStatus(): Status { + const issuesWithStatusDown = this.issues.filter((issue: Issue) => + issue.labels.find(label => label === 'status:down') + ) + if (issuesWithStatusDown.notEmpty()) + return { + code: StatusCode.DOWN, + emoji: '🔴' + } + + const issuesWithStatusWarning = this.issues.filter((issue: Issue) => + issue.labels.find(label => label === 'status:warning') + ) + if (issuesWithStatusWarning.notEmpty()) + return { + code: StatusCode.WARNING, + emoji: '🟡' + } + + return { + code: StatusCode.OK, + emoji: '🟢' + } + } + + getIssues(): Collection { + return this.issues.map((issue: Issue) => issue.getURL()) + } +} diff --git a/scripts/models/stream.ts b/scripts/models/stream.ts index 6ac1636b..c519bdfb 100644 --- a/scripts/models/stream.ts +++ b/scripts/models/stream.ts @@ -1,58 +1,58 @@ -import type { StreamData } from '../types/stream' -import { Feed, Channel } from './index' - -export class Stream { - name?: string - url: string - id?: string - channelId?: string - channel?: Channel - feedId?: string - feed?: Feed - filepath?: string - line?: number - label?: string - verticalResolution?: number - isInterlaced?: boolean - referrer?: string - userAgent?: string - groupTitle: string = 'Undefined' - removed: boolean = false - - constructor(data: StreamData) { - const id = data.channel && data.feed ? [data.channel, data.feed].join('@') : data.channel - const { verticalResolution, isInterlaced } = parseQuality(data.quality) - - this.id = id || undefined - this.channelId = data.channel || undefined - this.feedId = data.feed || undefined - this.name = data.name || undefined - this.url = data.url - this.referrer = data.referrer || undefined - this.userAgent = data.user_agent || undefined - this.verticalResolution = verticalResolution || undefined - this.isInterlaced = isInterlaced || undefined - this.label = data.label || undefined - } - - getId(): string { - return this.id || '' - } - - getName(): string { - return this.name || '' - } -} - -function parseQuality(quality: string | null): { - verticalResolution: number | null - isInterlaced: boolean | null -} { - if (!quality) return { verticalResolution: null, isInterlaced: null } - const [, verticalResolutionString] = quality.match(/^(\d+)/) || [null, undefined] - const isInterlaced = /i$/i.test(quality) - let verticalResolution = 0 - if (verticalResolutionString) verticalResolution = parseInt(verticalResolutionString) - - return { verticalResolution, isInterlaced } -} +import type { StreamData } from '../types/stream' +import { Feed, Channel } from './index' + +export class Stream { + name?: string + url: string + id?: string + channelId?: string + channel?: Channel + feedId?: string + feed?: Feed + filepath?: string + line?: number + label?: string + verticalResolution?: number + isInterlaced?: boolean + referrer?: string + userAgent?: string + groupTitle = 'Undefined' + removed = false + + constructor(data: StreamData) { + const id = data.channel && data.feed ? [data.channel, data.feed].join('@') : data.channel + const { verticalResolution, isInterlaced } = parseQuality(data.quality) + + this.id = id || undefined + this.channelId = data.channel || undefined + this.feedId = data.feed || undefined + this.name = data.name || undefined + this.url = data.url + this.referrer = data.referrer || undefined + this.userAgent = data.user_agent || undefined + this.verticalResolution = verticalResolution || undefined + this.isInterlaced = isInterlaced || undefined + this.label = data.label || undefined + } + + getId(): string { + return this.id || '' + } + + getName(): string { + return this.name || '' + } +} + +function parseQuality(quality: string | null): { + verticalResolution: number | null + isInterlaced: boolean | null +} { + if (!quality) return { verticalResolution: null, isInterlaced: null } + const [, verticalResolutionString] = quality.match(/^(\d+)/) || [null, undefined] + const isInterlaced = /i$/i.test(quality) + let verticalResolution = 0 + if (verticalResolutionString) verticalResolution = parseInt(verticalResolutionString) + + return { verticalResolution, isInterlaced } +} diff --git a/scripts/types/channel.d.ts b/scripts/types/channel.d.ts index b1d2237c..b2c709e1 100644 --- a/scripts/types/channel.d.ts +++ b/scripts/types/channel.d.ts @@ -1,27 +1,27 @@ -import { Collection } from '@freearhey/core' - -export type ChannelData = { - id: string - name: string - alt_names: string[] - network: string - owners: Collection - country: string - subdivision: string - city: string - categories: Collection - is_nsfw: boolean - launched: string - closed: string - replaced_by: string - website: string -} - -export type ChannelSearchableData = { - id: string - name: string - altNames: string[] - guideNames: string[] - streamNames: string[] - feedFullNames: string[] -} +import { Collection } from '@freearhey/core' + +export interface ChannelData { + id: string + name: string + alt_names: string[] + network: string + owners: Collection + country: string + subdivision: string + city: string + categories: Collection + is_nsfw: boolean + launched: string + closed: string + replaced_by: string + website: string +} + +export interface ChannelSearchableData { + id: string + name: string + altNames: string[] + guideNames: string[] + streamNames: string[] + feedFullNames: string[] +} diff --git a/scripts/types/dataLoader.d.ts b/scripts/types/dataLoader.d.ts index 135340e9..98d3d911 100644 --- a/scripts/types/dataLoader.d.ts +++ b/scripts/types/dataLoader.d.ts @@ -1,20 +1,20 @@ -import { Storage } from '@freearhey/core' - -export type DataLoaderProps = { - storage: Storage -} - -export type DataLoaderData = { - countries: object | object[] - regions: object | object[] - subdivisions: object | object[] - languages: object | object[] - categories: object | object[] - blocklist: object | object[] - channels: object | object[] - feeds: object | object[] - timezones: object | object[] - guides: object | object[] - streams: object | object[] - logos: object | object[] -} +import { Storage } from '@freearhey/core' + +export interface DataLoaderProps { + storage: Storage +} + +export interface DataLoaderData { + countries: object | object[] + regions: object | object[] + subdivisions: object | object[] + languages: object | object[] + categories: object | object[] + blocklist: object | object[] + channels: object | object[] + feeds: object | object[] + timezones: object | object[] + guides: object | object[] + streams: object | object[] + logos: object | object[] +} diff --git a/scripts/types/dataProcessor.d.ts b/scripts/types/dataProcessor.d.ts index f158f16e..e50915d1 100644 --- a/scripts/types/dataProcessor.d.ts +++ b/scripts/types/dataProcessor.d.ts @@ -1,16 +1,16 @@ -import { Collection, Dictionary } from '@freearhey/core' - -export type DataProcessorData = { - guideChannelsGroupedByStreamId: Dictionary - feedsGroupedByChannelId: Dictionary - logosGroupedByChannelId: Dictionary - logosGroupedByStreamId: Dictionary - feedsKeyByStreamId: Dictionary - streamsGroupedById: Dictionary - channelsKeyById: Dictionary - guideChannels: Collection - channels: Collection - streams: Collection - feeds: Collection - logos: Collection -} +import { Collection, Dictionary } from '@freearhey/core' + +export interface DataProcessorData { + guideChannelsGroupedByStreamId: Dictionary + feedsGroupedByChannelId: Dictionary + logosGroupedByChannelId: Dictionary + logosGroupedByStreamId: Dictionary + feedsKeyByStreamId: Dictionary + streamsGroupedById: Dictionary + channelsKeyById: Dictionary + guideChannels: Collection + channels: Collection + streams: Collection + feeds: Collection + logos: Collection +} diff --git a/scripts/types/feed.d.ts b/scripts/types/feed.d.ts index 00663a1b..00c49260 100644 --- a/scripts/types/feed.d.ts +++ b/scripts/types/feed.d.ts @@ -1,12 +1,12 @@ -import { Collection } from '@freearhey/core' - -export type FeedData = { - channel: string - id: string - name: string - is_main: boolean - broadcast_area: Collection - languages: Collection - timezones: Collection - video_format: string -} +import { Collection } from '@freearhey/core' + +export interface FeedData { + channel: string + id: string + name: string + is_main: boolean + broadcast_area: Collection + languages: Collection + timezones: Collection + video_format: string +} diff --git a/scripts/types/guide.d.ts b/scripts/types/guide.d.ts index 61ff6233..9fbe4da3 100644 --- a/scripts/types/guide.d.ts +++ b/scripts/types/guide.d.ts @@ -1,8 +1,8 @@ -export type GuideData = { - channel: string - feed: string - site: string - site_id: string - site_name: string - lang: string -} +export interface GuideData { + channel: string + feed: string + site: string + site_id: string + site_name: string + lang: string +} diff --git a/scripts/types/logo.d.ts b/scripts/types/logo.d.ts index c77f4799..d8c54b04 100644 --- a/scripts/types/logo.d.ts +++ b/scripts/types/logo.d.ts @@ -1,9 +1,9 @@ -export type LogoData = { - channel: string - feed: string | null - tags: string[] - width: number - height: number - format: string | null - url: string -} +export interface LogoData { + channel: string + feed: string | null + tags: string[] + width: number + height: number + format: string | null + url: string +} diff --git a/scripts/types/stream.d.ts b/scripts/types/stream.d.ts index adae13cf..c3365889 100644 --- a/scripts/types/stream.d.ts +++ b/scripts/types/stream.d.ts @@ -1,10 +1,10 @@ -export type StreamData = { - channel: string | null - feed: string | null - name?: string - url: string - referrer: string | null - user_agent: string | null - quality: string | null - label: string | null -} +export interface StreamData { + channel: string | null + feed: string | null + name?: string + url: string + referrer: string | null + user_agent: string | null + quality: string | null + label: string | null +} diff --git a/sites/tvim.tv/tvim.tv.test.js b/sites/tvim.tv/tvim.tv.test.js index b7c221cd..b819b777 100644 --- a/sites/tvim.tv/tvim.tv.test.js +++ b/sites/tvim.tv/tvim.tv.test.js @@ -1,41 +1,41 @@ -const { parser, url } = require('./tvim.tv.config.js') -const fs = require('fs') -const path = require('path') -const dayjs = require('dayjs') -const utc = require('dayjs/plugin/utc') -const customParseFormat = require('dayjs/plugin/customParseFormat') -dayjs.extend(customParseFormat) -dayjs.extend(utc) - -const date = dayjs.utc('2021-10-24', 'YYYY-MM-DD').startOf('d') -const channel = { site_id: 'T7', xmltv_id: 'T7.rs' } -const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json')) - -it('can generate valid url', () => { - const result = url({ date, channel }) - expect(result).toBe( - 'https://www.tvim.tv/script/program_epg?date=24.10.2021&prog=T7&server_time=true' - ) -}) - -it('can parse response', () => { - const result = parser({ date, channel, content }) - expect(result).toMatchObject([ - { - start: 'Sat, 23 Oct 2021 22:00:00 GMT', - stop: 'Sun, 24 Oct 2021 02:00:00 GMT', - title: 'Programi i T7', - description: 'Programi i T7', - category: 'test' - } - ]) -}) - -it('can handle empty guide', () => { - const result = parser({ - date, - channel, - content: fs.readFileSync(path.resolve(__dirname, '__data__/no_content.json')) - }) - expect(result).toMatchObject([]) -}) +const { parser, url } = require('./tvim.tv.config.js') +const fs = require('fs') +const path = require('path') +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +const customParseFormat = require('dayjs/plugin/customParseFormat') +dayjs.extend(customParseFormat) +dayjs.extend(utc) + +const date = dayjs.utc('2021-10-24', 'YYYY-MM-DD').startOf('d') +const channel = { site_id: 'T7', xmltv_id: 'T7.rs' } +const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json')) + +it('can generate valid url', () => { + const result = url({ date, channel }) + expect(result).toBe( + 'https://www.tvim.tv/script/program_epg?date=24.10.2021&prog=T7&server_time=true' + ) +}) + +it('can parse response', () => { + const result = parser({ date, channel, content }) + expect(result).toMatchObject([ + { + start: 'Sat, 23 Oct 2021 22:00:00 GMT', + stop: 'Sun, 24 Oct 2021 02:00:00 GMT', + title: 'Programi i T7', + description: 'Programi i T7', + category: 'test' + } + ]) +}) + +it('can handle empty guide', () => { + const result = parser({ + date, + channel, + content: fs.readFileSync(path.resolve(__dirname, '__data__/no_content.json')) + }) + expect(result).toMatchObject([]) +}) diff --git a/sites/tvinsider.com/tvinsider.com.config.js b/sites/tvinsider.com/tvinsider.com.config.js index 2ac33b16..9e43cb04 100644 --- a/sites/tvinsider.com/tvinsider.com.config.js +++ b/sites/tvinsider.com/tvinsider.com.config.js @@ -1,127 +1,127 @@ -const cheerio = require('cheerio') -const axios = require('axios') -const { DateTime } = require('luxon') - -module.exports = { - site: 'tvinsider.com', - days: 2, - url({ channel }) { - return `https://www.tvinsider.com/network/${channel.site_id}/schedule/` - }, - parser({ content, date }) { - const programs = [] - const items = parseItems(content, date) - items.forEach(item => { - const prev = programs[programs.length - 1] - const $item = cheerio.load(item) - const episodeInfo = parseEP($item) - let start = parseStart($item, date) - if (!start) return - if (prev) { - prev.stop = start - } - const stop = start.plus({ minute: 30 }) - - programs.push({ - title: parseTitle($item), - description: parseDescription($item), - category: parseCategory($item), - date: parseDate($item), - ...episodeInfo, - subTitles: parseSubtitle($item), - previouslyShown: parsePreviously($item), - start, - stop - }) - }) - - return programs - }, - async channels() { - const html = await axios - .get('https://www.tvinsider.com/network/5-star-max/') - .then(r => r.data) - .catch(console.log) - const $ = cheerio.load(html) - const items = $('body > main > section > select > option').toArray() - - const channels = [] - items.forEach(item => { - const name = $(item).text().trim() - const path = $(item).attr('value') - if (!path) return - const [, , site_id] = path.split('/') || [null, null, null] - if (!site_id) return - - channels.push({ - lang: 'en', - site_id, - name - }) - }) - - return channels - } -} - -function parseTitle($item) { - return $item('h3').text().trim() -} -function parseEP($item){ - const text = $item('h6').text().trim() - const match = text.match(/Season\s+(\d+)\s*•\s*Episode\s+(\d+)/i) - - if (!match) return {} // Return an empty object if no match, so properties are undefined later - - const season = parseInt(match[1], 10) - const episode = parseInt(match[2], 10) - - return { season, episode } // Return an object with season and episode -} - -function parseSubtitle($item) { - return $item('h5').text().trim() -} - -function parsePreviously($item){ - const h3Text = $item('h3').text().trim() - const isNewShow = /New$/.test(h3Text) - - if (isNewShow) { - return null - } else { - return {} - } -} - -function parseDescription($item) { - return $item('p').text().trim() -} - -function parseCategory($item) { - const [category] = $item('h4').text().trim().split(' • ') - - return category -} - -function parseDate($item) { - const [, date] = $item('h4').text().trim().split(' • ') - - return date -} - -function parseStart($item, date) { - let time = $item('time').text().trim() - time = `${date.format('YYYY-MM-DD')} ${time}` - - return DateTime.fromFormat(time, 'yyyy-MM-dd t', { zone: 'America/New_York' }).toUTC() -} - -function parseItems(content, date) { - const $ = cheerio.load(content) - - return $(`#${date.format('MM-DD-YYYY')}`) - .next() - .find('a') - .toArray() -} +const cheerio = require('cheerio') +const axios = require('axios') +const { DateTime } = require('luxon') + +module.exports = { + site: 'tvinsider.com', + days: 2, + url({ channel }) { + return `https://www.tvinsider.com/network/${channel.site_id}/schedule/` + }, + parser({ content, date }) { + const programs = [] + const items = parseItems(content, date) + items.forEach(item => { + const prev = programs[programs.length - 1] + const $item = cheerio.load(item) + const episodeInfo = parseEP($item) + let start = parseStart($item, date) + if (!start) return + if (prev) { + prev.stop = start + } + const stop = start.plus({ minute: 30 }) + + programs.push({ + title: parseTitle($item), + description: parseDescription($item), + category: parseCategory($item), + date: parseDate($item), + ...episodeInfo, + subTitles: parseSubtitle($item), + previouslyShown: parsePreviously($item), + start, + stop + }) + }) + + return programs + }, + async channels() { + const html = await axios + .get('https://www.tvinsider.com/network/5-star-max/') + .then(r => r.data) + .catch(console.log) + const $ = cheerio.load(html) + const items = $('body > main > section > select > option').toArray() + + const channels = [] + items.forEach(item => { + const name = $(item).text().trim() + const path = $(item).attr('value') + if (!path) return + const [, , site_id] = path.split('/') || [null, null, null] + if (!site_id) return + + channels.push({ + lang: 'en', + site_id, + name + }) + }) + + return channels + } +} + +function parseTitle($item) { + return $item('h3').text().trim() +} +function parseEP($item){ + const text = $item('h6').text().trim() + const match = text.match(/Season\s+(\d+)\s*•\s*Episode\s+(\d+)/i) + + if (!match) return {} // Return an empty object if no match, so properties are undefined later + + const season = parseInt(match[1], 10) + const episode = parseInt(match[2], 10) + + return { season, episode } // Return an object with season and episode +} + +function parseSubtitle($item) { + return $item('h5').text().trim() +} + +function parsePreviously($item){ + const h3Text = $item('h3').text().trim() + const isNewShow = /New$/.test(h3Text) + + if (isNewShow) { + return null + } else { + return {} + } +} + +function parseDescription($item) { + return $item('p').text().trim() +} + +function parseCategory($item) { + const [category] = $item('h4').text().trim().split(' • ') + + return category +} + +function parseDate($item) { + const [, date] = $item('h4').text().trim().split(' • ') + + return date +} + +function parseStart($item, date) { + let time = $item('time').text().trim() + time = `${date.format('YYYY-MM-DD')} ${time}` + + return DateTime.fromFormat(time, 'yyyy-MM-dd t', { zone: 'America/New_York' }).toUTC() +} + +function parseItems(content, date) { + const $ = cheerio.load(content) + + return $(`#${date.format('MM-DD-YYYY')}`) + .next() + .find('a') + .toArray() +} diff --git a/sites/tvireland.ie/tvireland.ie.config.js b/sites/tvireland.ie/tvireland.ie.config.js index be43fa9f..0ea0e349 100644 --- a/sites/tvireland.ie/tvireland.ie.config.js +++ b/sites/tvireland.ie/tvireland.ie.config.js @@ -1,99 +1,99 @@ -const cheerio = require('cheerio') -const dayjs = require('dayjs') -const utc = require('dayjs/plugin/utc') -const timezone = require('dayjs/plugin/timezone') -const customParseFormat = require('dayjs/plugin/customParseFormat') -const { uniqBy } = require('../../scripts/functions') - -dayjs.extend(utc) -dayjs.extend(timezone) -dayjs.extend(customParseFormat) - -module.exports = { - site: 'tvireland.ie', - days: 2, - url: function ({ date, channel }) { - return `https://www.tvireland.ie/tv/listings/channel/${channel.site_id}?dt=${date.format( - 'YYYY-MM-DD' - )}` - }, - parser: function ({ content, date, channel }) { - const programs = [] - const items = parseItems(content) - items.forEach(item => { - const prev = programs[programs.length - 1] - const $item = cheerio.load(item) - let start = parseStart($item, date, channel) - if (prev) { - if (start.isBefore(prev.start)) { - start = start.add(1, 'd') - date = date.add(1, 'd') - } - prev.stop = start - } - const stop = start.add(30, 'm') - programs.push({ - title: parseTitle($item), - start, - stop - }) - }) - - return programs - }, - async channels() { - const axios = require('axios') - - const providers = ['-9000019', '-8000019', '-1000019', '-2000019', '-7000019'] - - const channels = [] - for (let provider of providers) { - const data = await axios - .post('https://www.tvireland.ie/tv/schedule', null, { - params: { - provider, - region: 'Ireland', - TVperiod: 'Night', - date: dayjs().format('YYYY-MM-DD'), - st: 0, - u_time: 2027, - is_mobile: 1 - } - }) - .then(r => r.data) - .catch(console.log) - - const $ = cheerio.load(data) - $('.channelname').each((i, el) => { - const name = $(el).find('center > a:eq(1)').text() - const url = $(el).find('center > a:eq(1)').attr('href') - const [, number, slug] = url.match(/\/(\d+)\/(.*)\.html$/) - - channels.push({ - lang: 'en', - name, - site_id: `${number}/${slug}` - }) - }) - } - - return uniqBy(channels, x => x.site_id) - } -} - -function parseStart($item, date) { - const timeString = $item('td:eq(0)').text().trim() - const dateString = `${date.format('YYYY-MM-DD')} ${timeString}` - - return dayjs.tz(dateString, 'YYYY-MM-DD H:mm a', 'Europe/Dublin') -} - -function parseTitle($item) { - return $item('td:eq(1)').text().trim() -} - -function parseItems(content) { - const $ = cheerio.load(content) - - return $('table.table > tbody > tr').toArray() -} +const cheerio = require('cheerio') +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +const timezone = require('dayjs/plugin/timezone') +const customParseFormat = require('dayjs/plugin/customParseFormat') +const { uniqBy } = require('../../scripts/functions') + +dayjs.extend(utc) +dayjs.extend(timezone) +dayjs.extend(customParseFormat) + +module.exports = { + site: 'tvireland.ie', + days: 2, + url: function ({ date, channel }) { + return `https://www.tvireland.ie/tv/listings/channel/${channel.site_id}?dt=${date.format( + 'YYYY-MM-DD' + )}` + }, + parser: function ({ content, date, channel }) { + const programs = [] + const items = parseItems(content) + items.forEach(item => { + const prev = programs[programs.length - 1] + const $item = cheerio.load(item) + let start = parseStart($item, date, channel) + if (prev) { + if (start.isBefore(prev.start)) { + start = start.add(1, 'd') + date = date.add(1, 'd') + } + prev.stop = start + } + const stop = start.add(30, 'm') + programs.push({ + title: parseTitle($item), + start, + stop + }) + }) + + return programs + }, + async channels() { + const axios = require('axios') + + const providers = ['-9000019', '-8000019', '-1000019', '-2000019', '-7000019'] + + const channels = [] + for (let provider of providers) { + const data = await axios + .post('https://www.tvireland.ie/tv/schedule', null, { + params: { + provider, + region: 'Ireland', + TVperiod: 'Night', + date: dayjs().format('YYYY-MM-DD'), + st: 0, + u_time: 2027, + is_mobile: 1 + } + }) + .then(r => r.data) + .catch(console.log) + + const $ = cheerio.load(data) + $('.channelname').each((i, el) => { + const name = $(el).find('center > a:eq(1)').text() + const url = $(el).find('center > a:eq(1)').attr('href') + const [, number, slug] = url.match(/\/(\d+)\/(.*)\.html$/) + + channels.push({ + lang: 'en', + name, + site_id: `${number}/${slug}` + }) + }) + } + + return uniqBy(channels, x => x.site_id) + } +} + +function parseStart($item, date) { + const timeString = $item('td:eq(0)').text().trim() + const dateString = `${date.format('YYYY-MM-DD')} ${timeString}` + + return dayjs.tz(dateString, 'YYYY-MM-DD H:mm a', 'Europe/Dublin') +} + +function parseTitle($item) { + return $item('td:eq(1)').text().trim() +} + +function parseItems(content) { + const $ = cheerio.load(content) + + return $('table.table > tbody > tr').toArray() +} diff --git a/sites/tvmusor.hu/tvmusor.hu.config.js b/sites/tvmusor.hu/tvmusor.hu.config.js index ea420299..52ecb286 100644 --- a/sites/tvmusor.hu/tvmusor.hu.config.js +++ b/sites/tvmusor.hu/tvmusor.hu.config.js @@ -1,81 +1,81 @@ -const axios = require('axios') -const dayjs = require('dayjs') -const { uniqBy } = require('../../scripts/functions') - -module.exports = { - site: 'tvmusor.hu', - days: 2, - url: 'https://tvmusor.borsonline.hu/a/get-events/', - request: { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' - }, - data({ channel, date }) { - const params = new URLSearchParams() - params.append( - 'data', - JSON.stringify({ - blocks: [`${channel.site_id}|${date.format('YYYY-MM-DD')}`] - }) - ) - - return params - } - }, - parser({ content, channel, date }) { - let programs = [] - const items = parseItems(content, channel, date) - items.forEach(item => { - const prev = programs[programs.length - 1] - let start = dayjs(item.e) - let stop = dayjs(item.f) - if (prev) { - start = prev.stop - } - - programs.push({ - title: item.j, - category: item.h, - description: item.c, - image: parseImage(item), - start, - stop - }) - }) - - return programs - }, - async channels() { - const data = await axios - .get('https://tvmusor.borsonline.hu/most/') - .then(r => r.data) - .catch(console.log) - - const [, channelData] = data.match(/const CHANNEL_DATA = (.*);/) - const json = channelData.replace('},}', '}}').replace(/(\d+):/g, '"$1":') - const channels = JSON.parse(json) - - return Object.values(channels).map(item => { - return { - lang: 'hu', - site_id: item.id, - name: item.name - } - }) - } -} - -function parseImage(item) { - return item.z ? `https://tvmusor.borsonline.hu/images/events/408/${item.z}` : null -} - -function parseItems(content, channel, date) { - const data = JSON.parse(content) - if (!data || !data.data || !data.data.loadedBlocks) return [] - const blocks = data.data.loadedBlocks - const blockId = `${channel.site_id}_${date.format('YYYY-MM-DD')}` - if (!Array.isArray(blocks[blockId])) return [] - - return uniqBy(uniqBy(blocks[blockId], a => a.e), b => b.b) -} +const axios = require('axios') +const dayjs = require('dayjs') +const { uniqBy } = require('../../scripts/functions') + +module.exports = { + site: 'tvmusor.hu', + days: 2, + url: 'https://tvmusor.borsonline.hu/a/get-events/', + request: { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' + }, + data({ channel, date }) { + const params = new URLSearchParams() + params.append( + 'data', + JSON.stringify({ + blocks: [`${channel.site_id}|${date.format('YYYY-MM-DD')}`] + }) + ) + + return params + } + }, + parser({ content, channel, date }) { + let programs = [] + const items = parseItems(content, channel, date) + items.forEach(item => { + const prev = programs[programs.length - 1] + let start = dayjs(item.e) + let stop = dayjs(item.f) + if (prev) { + start = prev.stop + } + + programs.push({ + title: item.j, + category: item.h, + description: item.c, + image: parseImage(item), + start, + stop + }) + }) + + return programs + }, + async channels() { + const data = await axios + .get('https://tvmusor.borsonline.hu/most/') + .then(r => r.data) + .catch(console.log) + + const [, channelData] = data.match(/const CHANNEL_DATA = (.*);/) + const json = channelData.replace('},}', '}}').replace(/(\d+):/g, '"$1":') + const channels = JSON.parse(json) + + return Object.values(channels).map(item => { + return { + lang: 'hu', + site_id: item.id, + name: item.name + } + }) + } +} + +function parseImage(item) { + return item.z ? `https://tvmusor.borsonline.hu/images/events/408/${item.z}` : null +} + +function parseItems(content, channel, date) { + const data = JSON.parse(content) + if (!data || !data.data || !data.data.loadedBlocks) return [] + const blocks = data.data.loadedBlocks + const blockId = `${channel.site_id}_${date.format('YYYY-MM-DD')}` + if (!Array.isArray(blocks[blockId])) return [] + + return uniqBy(uniqBy(blocks[blockId], a => a.e), b => b.b) +} diff --git a/sites/tvprofil.com/tvprofil.com.channels.xml b/sites/tvprofil.com/tvprofil.com.channels.xml index bd09d7a7..0c154971 100644 --- a/sites/tvprofil.com/tvprofil.com.channels.xml +++ b/sites/tvprofil.com/tvprofil.com.channels.xml @@ -1,5839 +1,5839 @@ - - - Tring 3 Plus - 21 Mix - 360 TuneBox - ABC News Albania - Agro TV - Al Jazeera - Al Jazeera Balkans - Алсат М - AMC - Apollon TV - Arena Sport 5 RS - Arena Sport 6 RS - ARTE DE - ArtKino 1 - ArtKino 2 - ArtKino 3 - ATV Avrupa - ATV KS - ATV TR - AXN - AXN Spin - B92 - BabyTV - Balkanika TV - Bang Bang - BBC Earth - BBC World News - Beyaz TV - Radio Televizija BN - BN music - Boomerang - Bubble TV - Cartoon Network - Cartoonito CEE - CBS Reality - Cinemax - Cinemax 2 - CineStar Action&Thriller RS - CineStar TV Comedy Family - CineStar TV Fantasy - CineStar TV RS - Click TV - English Club TV - CNN Europe - Comedy Central DE - Crime & Investigation Channel - Cufo TV - Da Vinci Learning - Deutsche Welle English - Discovery Animal Planet - Discovery Channel - TLC - Disney Channel - DM SAT - DocuBox HD - Dorcel TV - Duck TV CZ - DuckTV - Elrodi - E! Entertainment - Epic Drama (CEE) - Eroxxx HD - Eurochannel - EuroNews - Euronews Albania - Explorer Histori - Explorer Natyra - Explorer Shkence - Extreme Sports Channel - FashionBox HD - Fast&FunBox HD - FAX News - FightBox HD - Film Aksion Digitalb - Film Drame Digitralb - Film Klub - Film Klub Extra - Film Thriller Digitalb - FilmBox Arthouse - FilmBox Extra RS - FilmBox Stars RS - FilmBox Premium RS - STAR Channel - STAR Crime - STAR Life - FOX Turkey - France24 - France 2 - Radio Televizija Federacije BIH - Gametoon HD - Habertürk - HappyTV - Hayat TV - HBO - HBO3 - HBO2 - The History Channel - History Channel 2 - HRT 1 - HRT 3 - HUSTLER TV - Investigation Discovery - JimJam - Tring Jolly HD - Junior TV - Kujtesa Sport 1 - Kujtesa Sport 2 - Kujtesa Sport 3 - Kujtesa Sport 4 - Kanal 6 - Kanal 7 - Kanal 10 - Kanal D - Kanali 7 - KitchenTV - Klan Kosova - Klan Plus - Kohavision - Kopliku TV - Living HD - Minimax - Motorvision HD RO - MTV Europe - MTV 00s - MTV Hits International - MTV Live HD - MTV 90s International - MUSE - My Music - NTV DE - National Geographic - Nat Geo Wild - NBA TV - News 24 - Nick Junior - Nickelodeon - Ora News - Pikaboo - RTV PINK - RED tv - Vesti - Pink Action - Pink Thriller - Pink Crime & Mystery - Pink Comedy - Pink Erotic 1 - Pink Erotic 2 - PINK Family - PINK Film - Pink Hits - Pink Kids - Pink LOL - Pink Romance - Pink SCI FI & Fantasy - Pink Music 1 - Pink and Roll - Pink Premium - Pink Reality - Pink Serije - Pink Super Kids - Pink Western - Pink World Cinema - Power TV - Power Türk TV - Brazzers TV (ex. Private Spice) - Private TV - ProSieben - ProSieben MAXX - Prva FILES - Prva KICK - Prva LIFE - Prva MAX - Prva Srpska TV - Prva World - RAI DUE - RAI TRE - RAI News 24 - Report TV - RT Documentary - RTK 1 - RTK 2 - RTK 4 - RTL - RTL 2 - RTL Zwei - RTL DE - RTRS - RTRS PLUS - RTS 1 - RTS 2 - RTS 3 - RTS Drama - RTS Kolo - RTS Muzika - RTS Poletarac - RTS SVET - RTS Trezor - RTS Život - RTV21 - RTV 21 Popullore - RTV Besa - Russia Today - Sat.1 - Sat.1 Gold - SciFi - Shenja TV - Show TV - Sky News - Tring Smile - SOS Plus - Tring Sport News - Star TV TR - Studio B - Super RTL - Superstar TV - Syri TV - Syri Vizion - Timeless Drama Channel - Tip TV - Top Channel - Travel Channel - Tring Bizarre - Tring Bunga Bunga - Tring Collection - Tring Comedy - Tring Desire - Tring History - Tring Kids - Tring Life - Tring Action - Tring Novelas - Tring Planet - Tring Shqip - Tring Super - Tring Tring - Tring World - TRT 1 - TRT 2 - TRT Spor - TRT Belgesel - TRT Çocuk - TRT Haber - TRT Müzik - TRT Turk - TRT World - TV5 Monde - TV1000 Balkan - TV 7 - TV 8 TR - Arena Sport 1 RS - Arena Sport 2 RS - Arena Sport 3 RS - Arena Sport 4 RS - TV Dukagjini - Телевизија Храм - Klan TV HD - RTV Most - DIVA (ex. Universal) - Vavoom - MTV 80s - Viasat Explore CEE - Viasat History - Viasat Nature CEE - Vizion Plus - RT Vojvodina 1 - RT Vojvodina 2 - VOX - Zico TV - Zjarr TV - 24 Kitchen - 360 TuneBox - Al Jazeera - Al Jazeera Balkans - AMC - Das Erste - ARTE FR - Auto Motor und Sport - BabyTV - Balkanika TV - BBC World News - BG-DNES - BHTV - Bloomberg TV - BN music - Body in Balance - Boomerang - BSTV BG - Cartoon Network - Cartoonito CEE - CBS Reality - CGTN - Первый - Cinemania BG - Cinemax 2 BG - Cinemax BG - Cinethronix RO - CNBC Europe - CNN Europe - Comedy Central BG - Nicktoons - Comedy Central Extra BG - Crime & Investigation Channel - Da Vinci Learning - Deluxe Music - Deutsche Welle English - Diema Sport 3 BG - Discovery Animal Planet - Discovery Channel - Discovery Science - TLC - Disney Junior BG - Stingray Djazz - DM SAT - DocuBox HD - Dorcel TV - Dorcel XXX - DSTV - DuckTV - Epic Drama (CEE) - Erox HD - Eroxxx HD - Eurochannel - EuroNews - Euronews FR - Eurosport 2 - Eurosport 1 BG - Extreme Sports Channel - F+ - Fashion TV - FashionBox HD - Fast&FunBox HD - FightBox HD - FilmBox Arthouse - FilmBox BG - FilmBox Extra BG - The Fishing and Hunting - The Fishing and Hunting RO - Fix & Foxi - France24 - France 2 - France 24 French - FunBox UHD - Gametoon HD - HBO 2 BG - HBO 3 BG - Home & Garden Television - The History Channel - History Channel 2 - HUSTLER TV - Investigation Discovery - Investigation Discovery BG - JimJam BG - K::CN 2 Music - КХЛ - KiKA - Love Nature - LUXE TV - MCM Top - Mezzo - Mezzo Live HD - Motorvision TV - MTV Europe - MTV 00s - Club MTV International - MTV Hits International - MTV Live HD - MTV 90s International - MyZen TV - Nasa TV US - Nick Junior - Nick Junior BG - Nickelodeon - Nickelodeon Commercial - Nickelodeon UK - Pickbox TV BG - Planeta TV BG - Playboy TV - Plovdivska Pravoslavna TV - Brazzers TV (ex. Private Spice) - ProSieben MAXX - RAI UNO - RAI News 24 - Reality Kings - RedLight HD - Ring TV - Россиᴙ 24 - RT Documentary - RTL Zwei - RTL DE - Russia Today - Sat.1 Gold - Sky News - Stingray iConcerts - Super RTL - SuperToons - Travel Channel - TRT Belgesel - TV5 Monde - TV5Monde Europe - TV1000 Balkan - TVE Internacional - Телевизия Стара Загора BG - MTV 80s - Viasat Explore CEE - Viasat History - Viasat Nature CEE - VOX - ZDF - 24Kitchen BG - AGRO TV BG - Alfa BG - AXN Black BG - AXN BG - AXN White BG - B1B Action TV BG - Barely Legal TV - Bloomberg TV BG - БНТ 1 - БНТ 2 - БНТ 3 - БНТ 4 - BOX TV BG - bTV BG - bTV Action - bTV Cinema - bTV Comedy - bTV Lady - Bulgaria on Air - City TV BG - Diema - Diema Family - Diema Sport 2 - Diema Sport - Disney Channel BG - EKids - Евроком - Фен Фолк ТВ - ФЕН ТВ - FilmBox Stars BG - HBO BG - Kino Nova - Magic TV BG - MAX Sport 1 BG - MAX Sport 2 BG - MAX Sport 3 BG - Max Sport 4 BG - Movie Star - National Geographic BG - Nat Geo Wild BG - Nova TV BG - Nova News - Nova Sport BG - Planeta Folk BG - Skat TV - Sport+ HD - STAR BG - STAR Crime BG - STAR Life BG - Travel TV BG - Travelxp - TV1 BG - TV Evropa BG - TV+ BG - Родина - Vivacom Arena - VTK BG - Wness TV - 24 Kitchen - 24 ВЕСТИ - 360 TuneBox - Adria TV - Adult Channel - Al Jazeera - Al Jazeera Arabic English - Al Jazeera Balkans - ALFA TV - AMC - Anixe HD Serie - ANIXE plus - Das Erste - Arena Esport - Arena Fight - Arena Sport 1 Premium - Arena Sport 1 Premium BiH - Arena Sport 1x2 - Arena Sport 2 BiH - Arena Sport 2 Premium - Arena Sport 2 Premium BiH - Arena Sport 3 BiH - Arena Sport 3 Premium - Arena Sport 3 Premium BiH - Arena Sport 4 BiH - Arena Sport 5 BiH - Arena Sport 6 RS - Arena Sport 6 BiH - Alternativna televizija Banja Luka - B92 - BabyTV - Balkan TV - Balkanika TV - BBC World News - BDC Televizija - Behar TV Sarajevo - Radio Televizija BIH - Bir TV - BlicTV - Bloomberg TV - Bloomberg Adria - Radio Televizija BN - BN music - Boomerang - Bravo Music - Cartoon Network - Cartoonito CEE - CBS Reality - CCTV 4 Europe - CGTN - Cinema TV - Cinemax - Cinemax 2 - City TV - English Club TV - Croatian Music Channel - CNBC Europe - CNN Europe - Nicktoons - Crime & Investigation Channel - Deutsche Welle English - Dexy TV - Digi 24 - Discovery Animal Planet - Discovery Channel - Discovery Science - TLC - Discovery Turbo Extra - Disney Channel - Disney Channel DE - DMAX DE - DM SAT - DocuBox HD - Dorcel TV - Dorcel XXX - DOX TV - Elta 1 HD - E! Entertainment - Erox HD - Eroxxx HD - Eska TV Extra - Etno TV RO - Eurochannel - EuroNews - Euronews FR - EuroNews Srbija - Eurosport - Eurosport 1 DE - Extreme Sports Channel - Fashion TV - FashionBox HD - Fast&FunBox HD - Favorit TV RO - FightBox HD - SK Fight - FilmBox Arthouse - FilmBox Extra RS - FilmBox Stars RS - FilmBox Premium RS - Food Network - STAR Channel - STAR Crime - STAR Life - STAR Movies - FOX NEWS - France24 - France 24 French - Radio Televizija Federacije BIH - GameHub HR - Gametoon HD - SK Golf - GP1 - Grand nostalgija - HappyTV - Hayat Folk - Hayat Plus - Hayat TV - HBO - HBO3 - HBO2 - Herceg TV - Historija TV - The History Channel - HIT TV - HSE - HRT 1 - HRT 3 - HUSTLER TV - Imperia TV - Insajder TV - Insta TV - Investigation Discovery - Izvorna TV - Otvorena televizija - JimJam - K1 TV - Kabel 1 - Kanal1 - Kanal 6 - Kazbuka - KiKA - Klape i Tambure TV - M1 Family - Maria Vision - Motorvision TV - MTV Europe - MTV 00s - Club MTV International - MTV Hits International - MTV Igman - MTV Live HD - MTV 90s International - MY TV - N1 RS - N24 Doku - Nasa TV US - National Geographic - National Geographic Channel HD - National Geographic RS - Nat Geo Wild - NBA TV - Neon TV - Nat Geo Wild HD - Nick Junior - Nick Music - Nickelodeon Commercial - NOVA TV - Nova Max - Nova Series - NTV 101 Sanski most - NTV IC Kakanj - O Kanal Music - O Kanal Plus - OBN - One - OSM TV - OTV Valentino - Pickbox TV RS - Pikaboo - RTV PINK - RED tv - Vesti - Pink Erotic 1 - Pink Erotic 2 - Pink Erotic 3 - Pink Erotic 4 - Pink Erotic 5 - Pink Erotic 6 - Pink Erotic 7 - Pink Erotic 8 - TV PINK EXTRA - PINK Film - Pink Folk 1 - Pink Hits 2 - Pink Kids - Pink Music 1 - Pink Parada - TV PINK PLUS - Pink Reality - Pink Timeout - Playboy TV - Poljoprivredna TV - Posavska Televizija - Premier League TV - Private TV - ProSieben - ProSieben MAXX - ProTV Tomislavgrad - Prva Srpska TV - QVC Deutschland - RAI UNO - RAI DUE - RAI TRE - RAI Education - RAI News 24 - Reality Kings - RT Documentary - RTL 2 - RTL Zwei - RTL DE - RTL Kockica - RTL Nitro - RTRS - RTS 1 - RTS Klasika - RTS Nauka - RTS Poletarac - RTS Život - RTSH 3 - RTSH 24 - RTSH Plus - RTSH Shkollë - RTV7 Tuzla - RTV BPK Goražde - RTV Herceg-Bosne - RTV HIT Brčko - RTV Lukavac - RTV Slon Tuzla - RTV Unsko-sanskog kantona - RTV Vogošća - RTV Zenica - RTV Tuzlanskog Kantona - Russia Today - Sat.1 - Sat.1 Gold - SciFi - Sevdah TV - SK1 BiH - SK esports - Sky News - Slobomir - Smart TV Tešanj - SOS Plus - Sport Klub 1 Srbija - Sport Klub 4 - Sport Klub 5 - Sport Klub 6 - Sport Klub 7 - Sport Klub 8 - Sport Klub 9 - Sport Klub 10 - Sport Klub HD - Sport Klub 1 Hrvatska - Sport Klub 3 - Sport Klub 2 Srbija - Superstar 2 - Super RTL - Supermedia Televizija - Tanjug Tačno - Tatabrada - TBN Polska - Timeless Drama Channel - Tele 5 DE - Televizija 5 - TLC DE - TNT Kids - Toxic Folk - Toxic Rap - Toxic TV - Travel Channel - Tropik TV - TRT 1 - TRT World - TV1 Mreža - TV Arena Bijeljina - Arena Sport 1 RS - Arena Sport 1 HR - Arena Sport 4 RS - Televizija Dalmacija - TV Duga + SAT - TV Istočno Sarajevo - TV Ras - TV Sarajevo - TV Vijesti - RTV Visoko - Televizija Crne Gore MNE - Televizija Doktor - TVR Cluj RO - TVR Craiova RO - TVR Iasi RO - TVR Tg-Mures RO - TVR Timisoara RO - UNA TV BiH - DIVA (ex. Universal) - Valentino Etno - Valentino Music HD - Vavoom - MTV 80s - Vikom - VOX - VOX up - Welt - ZDF - ZDFinfo - ZDFneo - 1-2-3.tv - 3SAT - 13th Street DE - A Spor - Al Jazeera - Animal Planet DE - Anixe HD Serie - ANIXE plus - Das Erste - ARD-alpha - ARTE DE - AstroTV - Alternativna televizija Banja Luka - ATV1 - ATV2 - Auto Motor und Sport - B92 - Bayerischen Fernsehen Nord - BBC World News - beIN Movies Premiere TR - Bergblick - BFM TV - Radio Televizija BIH - Bibel TV - Das Bild TV - Bloomberg TV - Blue Hustler - Radio Televizija BN - BN music - BonGusto - Boomerang DE - BR Fernsehen Süd - Cartoon Network DE - CCTV 4 Europe - CGTN - CGTN Documentary - Croatian Music Channel - CNBC Europe - CNews - CNN Europe - Comedy Central DE - Nicktoons - Crime & Investigation Channel - Crime & Investigation DE - Deluxe Music - Deutsche Welle English - Deutsches Musik Fernsehen - Deutsche Welle Deutsch - Discovery Channel DE - Disney Channel DE - DMAX DE - DM SAT - DocuBox HD - Dorcel TV - Dorcel XXX - DuckTV - Elta 1 HD - E! Entertainment - Erox HD - Euro Star - EuroNews - Eurosport - Eurosport 2 DE - Eurosport 1 DE - Extreme Sports Channel - Fashion TV - Fast&FunBox HD - Fight 24 - Fix & Foxi - Folx TV - France24 - France 24 French - FS1 AT - Radio Televizija Federacije BIH - Geo Television - Ginx Esports TV - Gute Laune TV - Habertürk - HappyTV - Hayat TV - Heimatkanal - HGTV DE - History Channel DE - HR Fernsehen - HSE - HSE24 Extra - HSE24 Trend - HRT 1 - HUSTLER TV - K-TV Katholisches Fernsehen - Kabel 1 - Kabel eins Österreich - Kabel Eins Classics - Kabel eins Doku - Kanal 7 - Kanal D TR - Kerrang! - KiKA - Kinowelt - KIT-TV - krone.tv - Love Nature - Marco Polo TV - MDR Fernsehen - MDR Sachsen-Anhalt - MDR Sachsen - MDR Thüringen - Melodie TV - Mezzo - Mezzo Live HD - Motorvision TV - MTV 00s - Club MTV International - MTV DE - MTV Hits International - MTV Live HD - MTV 90s International - N24 Doku - NTV DE - NatGeo Wild DE - National Geographic DE - The Nautical Channel - NDR Hamburg - NDR Mecklenburg-Vorpommern - NDR Niedersachsen - NDR Schleswig-Holstein - Nick Junior - Nick Music - Nick DE - Niederbayern TV Deggendorf-Straubing - NOVA TV - oe24.TV - One - ORF1 - ORF2 - ORF3 - ORF Sport Plus - OTV Valentino - Phoenix - TV PINK EXTRA - PINK Film - Pink Folk 1 - Pink Kids - Pink Music 1 - TV PINK PLUS - Pink Reality - Playboy TV - ProSieben - PRO 7 Österreich - ProSieben Fun - ProSieben MAXX - Prva Srpska TV - Puls 4 - QVC 2 DE - QVC Beauty - QVC Deutschland - QVC STYLE DE - RAI UNO - RAI DUE - RAI TRE - RAI Education - RAI News 24 - RAI Storia - RBB Fernsehen Brandenburg - RBB Fernsehen Berlin - RiC DE - Romance TV - RTL 2 - RTL Zwei - RTL Crime DE - RTL Croatia World - RTL DE - RTL Kockica - RTL Living DE - RTL Nitro - RTL Passion DE - RTLup - RTRS - RTS 1 - Russia Today - Sat.1 Emotions - Sat.1 - Sat.1 Österreich - Sat.1 Gold - Kurier TV - Schlager Deluxe - ServusTV - Show Türk - Sixx - Sixx AT - Sky 1 DE - Sky Atlantic DE - Sky Cinema Action DE - Sky Cinema Classics DE - Sky Cinema Family DE - Sky Krimi DE - Sky Cinema Thriller - Sky Sport 1 DE - Sky Sport 3 DE - Sky Sport 4 DE - Sky Sport 5 DE - Sky Sport 6 DE - Sky Sport 7 DE - Sky Sport 8 DE - Sky Sport 9 DE - Sky Sport 10 DE - Sky Bundesliga 1 - Sky Bundesliga 2 - Sky Bundesliga 3 - Sky Bundesliga 4 - Sky Bundesliga 5 - Sky Bundesliga 6 - Sky Bundesliga 7 - Sky Sport News DE - Sky Sports News - Sky News - sonnenklar.TV - Sony AXN - Sony Channel DE - Spiegel Geschichte - Curiosity Channel - Sport 1 plus DE - Šport TV 1 - Sportdigital Fußball - SR Fernsehen - SRF Info - SRF Zwei - Stingray Classica - Super RTL - SWR - SWR Baden-Württemberg - Syfy HD DE - tagesschau24 - Tele 5 DE - TLC DE - Warner TV Comedy DE - Warner TV Film DE - Warner TV Serie DE - TOGGO plus - TRT 1 - TRT Spor - TRT Belgesel - TRT Çocuk - TRT Müzik - TV 8 TR - Universal TV DE - MTV 80s - Vivid TV - VOX - W24 - WDR Fernsehen - WDR Fernsehen Köln - Welt - Welt der Wunder - ZDF - ZDFinfo - ZDFneo - 2M Monde - 3 Plus CH - 3SAT - 4 Plus - 4 Seven - 5 Plus - 5 Star - 6 plus - 6ter - 13th Street DE - 20 Mediaset - Action - Al Jazeera - Al Jazeera Arabic Arabic - Anixe HD Serie - ANIXE plus - Antena 3 - Das Erste - ARD-alpha - ARTE FR - ARTE DE - auftanken.TV - B1 TV - BBC1 - BBC2 - BBC3 - BBC4 - BBC News Channel - BBC Parliament - BBC World News - BFM Business - BFM TV - Bibel TV - Das Bild TV - Bloomberg TV - Bloomberg Quicktake - BN 2 HD - Boing - Boing Plus - Boomerang - Boomerang DE - BR Fernsehen Süd - C8 FR (ex. D8) - Canal 24H - Canal+ Kids FR - Canal J - Canal+ Cinéma(s) FR - Canal+ France - Canal Plus Sport FR - Canal+ Series FR - Canale 5 - CARAC4 - Cartoon Network DE - Cartoonito Italia - CBBC - Cbeebies - CCTV 4 Europe - CGTN - Challenge TV - Channel 4 - Channel 5 - Chérie 25 - cielo - Cine34 - Polar+ - Cine+ Premier FR - Children's ITV - Class TV Moda - English Club TV - Clubland TV - Croatian Music Channel - CNBC Europe - CNews - CNN Europe - CNN Türk TV - Comedy Central DE - Crime District - Crime & Investigation Channel - CStar FR - Dave - Deluxe Music - Deutsche Welle English - Deutsches Musik Fernsehen - Deutsche Welle Deutsch - Deutsche Welle Espanol - Discovery Channel DE - Discovery Channel IT - Disney Channel DE - DMAX IT - DMAX DE - DM SAT - Drama UK - Dream Türk - Sport 1 DE - Duna TV - Duna World - E4 - E! Entertainment - Euro D - Euro Star - EuroNews - Euronews FR - Eurosport - Eurosport 2 DE - Eurosport 2 FR - Eurosport 2 IT - Eurosport 1 DE - Eurosport FR - Eurosport IT - Fashion TV - Film4 - Fix & Foxi - Focus TV - Folx TV - Food Network Italia - Food Network UK - FOX NEWS - France24 - France 2 - France 3 - France 4 - France 5 - France 24 French - France Info - Frisbee - FunBox UHD - Giallo TV - Ginx Esports TV - Golf Channel Češka - Golf plus - Gulli - Habertürk - Halk TV - Hayat Folk - Hayat Music - Hayat Plus - Das Health TV - HGTV DE - HGTV IT - The History Channel - HR Fernsehen - HSE - HSE24 Extra - HSE24 Trend - HRT 1 - i24News FR - Iris - Italia 1 - Italia 2 - ITV1 - ITV2 - ITV3 - ITV4 - ITV Be - K2 - K-TV Katholisches Fernsehen - Kabel 1 - Kabel eins Doku - Kanal 9 TV - Kerrang! - KiKA - Kiss UK - Klan Kosova - Kohavision - L'Equipe - La Cinque - La7 - La7d - La Télé - La Chaîne Info - Magyar Televízió 1 - M2 Petőfi - M4 sport - m5 - M6 - Mangas - MCM FR - MDR Fernsehen - Mediaset Extra - Mediaset Italia - Mezzo - Mezzo Live HD - More4 - More Than Sports TV - Motorvision TV - Motorvision TV France - MTV DE - 5Select - N24 Doku - NTV DE - Nasa TV US - National Geographic DE - The Nautical Channel - NDR Hamburg - Nick DE - NOVE - Now 90s - NRJ12 - RMC Story - OBN - One - ORF1 - ORF2 - ORF3 - PBS America - Phoenix - Pick TV - TV PINK EXTRA - PINK Film - Pink Folk 1 - Pink Kids - Pink Koncert - Pink Music 1 - TV PINK PLUS - Pink Reality - Power Türk TV - ProSieben - ProSieben MAXX - Puls 8 - Radio Ticino Channel HD - RadioBremen - RAI UNO - RAI DUE - RAI TRE - RAI 4 - RAI 5 - RAI Education - RAI Gulp - RAI Movie - RAI News 24 - RAI Premium - RAI Sport 1 - RAI Storia - Rai Yoyo - RBB Fernsehen Berlin - real time - Rete 4 - RiC DE - RMC Découverte - Rocket Beans TV - Romance TV - CARAC1 - RSI La 1 - RSI La 2 - RTK 1 - RTL Zwei - RTL Crime DE - RTL DE - RTL Living DE - RTL Nitro - RTL Passion DE - RTLup - RTP3 - RTP Internacional - RTRS - RTS 2 Suisse - RTS SVET - RTS Un - Russia Today - S1 CH - S4C - Sat.1 - Sat.1 Gold - ServusTV - Show Türk - SIC - Sixx - Sky Atlantic - Sky Krimi DE - Sky Sport 1 DE - Sky Sports News - Sky TG24 HD - Sky News - SonLife - Spiegel Geschichte - Sport 1 plus DE - Sportitalia - SR Fernsehen - SRF 1 - SRF Info - SRF Zwei - Stingray Classica - Stingray iConcerts - Super! - Super RTL - Supertennis HD - K::CN 3 Svet Plus - Swiss1 TV - SWR - Syfy HD DE - tagesschau24 - TELE 1 - Tele 5 DE - TeleBärn - Tele Zürich - Télévision française 1 - TFX - TGCOM24 - TGRT HABER - TiJi - TLC DE - TMC - Warner TV Comedy DE - Warner TV Film DE - Warner TV Serie DE - TOGGO plus - Top Crime - Trace Urban - TRT Spor - TRT Kurdî - TRT Belgesel - TRT Çocuk - TRT Müzik - TRT Turk - TV5 Monde - TV5Monde Europe - TV8 IT - TV24 - TV25 - TV 8 TR - TV 2000 - TV Dukagjini - TVE Internacional - Televisión de Galicia - TV Internacional - TVM3 - Twenty Seven - DIVA (ex. Universal) - VH1 IT - Viaplay Xtra - VOX - VOX up - W9 - WDR Fernsehen - Welt - Welt der Wunder - Wetter - Yesterday - Zagrebačka Televizija - ZDF - ZDFinfo - ZDFneo - 1-2-3.tv - 3SAT - 13th Street DE - Al Jazeera - Al Jazeera Arabic English - Al Jazeera Balkans - Animal Planet DE - Anixe HD Serie - ANIXE plus - Das Erste - ARD-alpha - ARTE DE - AstroTV - Alternativna televizija Banja Luka - auftanken.TV - Baden TV - Balkanika TV - Bayerischen Fernsehen Nord - BBC World News - beIN iZ - beIN Movies Premiere TR - Bergblick - Bibel TV - Das Bild TV - Bloomberg TV - BonGusto - Boomerang DE - BR Fernsehen Süd - Canal 24H - Cartoon Network DE - CGTN - CGTN Documentary - Croatian Music Channel - CNBC Europe - CNN Europe - Comedy Central DE - Nicktoons - Crime & Investigation DE - DAZN 1 DE - DAZN 2 DE - Deluxe Music - Deutsche Welle English - Deutsches Musik Fernsehen - Deutsche Welle Deutsch - Discovery Channel DE - Disney Channel DE - DMAX DE - DM SAT - Sport 1 DE - Edge Sport - eSports 1 - Euro Star - EuroNews - Eurosport 2 DE - Eurosport 1 DE - EWTN - Extreme Sports Channel - Fashion TV - Fast&FunBox HD - Fight 24 - Fix & Foxi - Folx TV - France24 - France 2 - France 3 - France 4 - France 5 - France 24 French - Geo Television - Ginx Esports TV - Goldstar - Gute Laune TV - Habertürk - Halk TV - Hamburg 1 - Das Health TV - Heimatkanal - Home & Garden Television - HGTV DE - History Channel DE - HR Fernsehen - HSE - HSE24 Extra - HSE24 Trend - HRT 1 - Insight TV - Jukebox - K-TV Katholisches Fernsehen - Kabel 1 - Kabel Eins Classics - Kabel eins Doku - Kanal 7 - KiKA - Kinowelt - Klan Kosova - Kohavision - Marco Polo TV - MDR Fernsehen - MDR Sachsen-Anhalt - MDR Sachsen - MDR Thüringen - Mediaset Italia - Melodie TV - More Than Sports TV - Motorvision TV - MTV DE - MTV Live HD - münchen.tv - N24 Doku - NTV DE - NatGeo Wild DE - National Geographic DE - NDR Hamburg - NDR Mecklenburg-Vorpommern - NDR Niedersachsen - NDR Schleswig-Holstein - Nick Junior - Nick DE - Niederbayern TV Deggendorf-Straubing - One - ORF3 - ORF Sport Plus - Phoenix - TV PINK EXTRA - PINK Film - Pink Folk 1 - Pink Music 1 - TV PINK PLUS - Power Türk TV - ProSieben - ProSieben MAXX - QVC 2 DE - QVC Deutschland - RAI UNO - RAI DUE - RAI TRE - RAI News 24 - RAI Storia - RBB Fernsehen Brandenburg - RBB Fernsehen Berlin - RiC DE - Rhein Neckar Fernsehen - Rocket Beans TV - Romance TV - RTK 1 - RTL Zwei - RTL Crime DE - RTL DE - RTL Living DE - RTL Nitro - RTL Passion DE - RTLup - RTS SVET - Russia Today - Sat.1 Emotions - Sat.1 - Sat.1 Gold - Schlager Deluxe - ServusTV Deutschland - Show Türk - Silverline Movie Channel - Sixx - Sky 1 DE - Sky Atlantic DE - Sky Cinema Action DE - Sky Cinema Best Of DE - Sky Cinema Classics DE - Sky Cinema Comedy DE - Sky Cinema Family DE - Sky Krimi DE - Sky Cinema Premieren - Sky Sport 1 DE - Sky Sport 3 DE - Sky Sport 4 DE - Sky Sport 5 DE - Sky Sport 6 DE - Sky Sport 7 DE - Sky Sport 8 DE - Sky Sport 9 DE - Sky Sport 10 DE - Sky Bundesliga 1 - Sky Bundesliga 2 - Sky Bundesliga 3 - Sky Bundesliga 4 - Sky Bundesliga 5 - Sky Bundesliga 6 - Sky Bundesliga 7 - Sky Sport Mix DE - Sky Sport News DE - Sky Sport Premier League DE - Sky News - sonnenklar.TV - Sony AXN - Sony Channel DE - Spiegel Geschichte - Curiosity Channel - Sport 1 plus DE - Sportdigital Fußball - SR Fernsehen - Stingray Classica - Super RTL - SWR - SWR1 Baden-Württemberg - SWR Baden-Württemberg - Syfy HD DE - tagesschau24 - Tele 5 DE - TGRT EU - TLC DE - Warner TV Comedy DE - Warner TV Film DE - Warner TV Serie DE - TOGGO plus - TRT Turk - TV5 Monde - TV5Monde Europe - TV8 IT - TV Now DE - TVE Internacional - TVS - MTV 80s - VOX - VOX up - WDR Fernsehen - WDR Fernsehen Köln - Welt - Welt der Wunder - Wetter - Wir 24 - ZDF - ZDFinfo - ZDFneo - 4Music - 4 Seven - 5ACTION - 5 Star - 5 USA - Al Jazeera Arabic English - Alibi - AMC UK - Animal Planet UK - At The Races - BabyTV - BBC1 - BBC1 Northern Ireland - BBC One Scotland - BBC2 - BBC3 - BBC4 - BBC Alba - BBC Earth - BBC News Channel - BBC 1 Wales - BBC Parliament - BBC 2 Northern Ireland - BBC Two Wales - BBC World News - Boomerang - Boomerang UK - TNT Sports 1 - TNT Sports 2 - TNT Sports 4 - TNT Sports Europe - TNT Sports Ultimate - Cartoon Network - Cartoon Network UK - Cartoonito UK - CBBC - Cbeebies - CBS Drama UK - CBS Reality UK - Challenge TV - Channel 4 - Channel 4 +1 - Channel 5 - Channel S - Capital XTRA - Children's ITV - English Club TV - Clubland TV - Comedy Central Extra UK - Comedy Central UK - Create and Craft - Crime and Investigation UK - Dave - Deutsche Welle English - Discovery Channel UK - Discovery History UK - Discovery Science UK - Discovery Turbo UK - DMAX UK - Drama UK - E4 - E4 Extra - Eden UK - Edge Sport - BT Sport ESPN - EuroNews - Eurosport 2 UK - Eurosport 1 EMEA - Eurosport.com - Eurosport UK - Extreme Sports Channel - Film4 - Food Network UK - Gems TV - Ginx Esports TV - Great! romance - History 2 UK - History Channel UK - Home & Garden Television UK - Ideal Home Shopping - Inspiration TV - Investigation Discovery UK - ITV1 - ITV2 - ITV2+1 - ITV3 - ITV4 - ITV Be - Jewellery Channel - JML Direct - Kerrang! - Ketchup TV - Kiss UK - Pop Max - London Live - Love Nature - Magic - Manchester TV - More4 - MotorTrend - Movies 24 - MTV 80s UK - MTV 90s UK - MTV Hits UK - MTV Live HD - MTV Music UK - MTV UK - 5Select - Nat Geo Wild UK - National Geographic Channel UK - Nick Jr. Too UK - Nick Junior UK - Nick Music - Nickelodeon UK - Nicktoons UK - Now 70s - Now 80s - Now 90s - PBS America - Pick TV - Pop UK - Premier Sports 1 - Premier Sports 2 - Quest TV - Quest Red - QVC Beauty - QVC Style - Really UKTV - Revelation TV - S4C - Sky Arts - Sky Atlantic - Sky Cinema Drama - Sky Cinema Greats - Sky Cinema Hits - Sky Cinema Select - Sky Cinema SF Horror - Sky Crime - Sky Documentaries - Sky Kids - Sky Witness - Sky Max - Sky Cinema Action - Sky Cinema Comedy - Sky Cinema Thriller - Sky Family - Sky Cinema Premiere - Sky Nature UK - Sky Replay - Sky Showcase - Sky Sports Main Event - Sky Sports Cricket - Sky Sports Action - Sky Sports Golf - Sky Sports Premier League - Sky Sports Arena - Sky Sports F1 - Sky Sports Football - Sky Sports Mix - Sky Sports News - Sky Sports Racing - Sky News - Smithsonian Channel - SonLife - Sony Channel - Great! Movies - Great! Movies Action - Great! Movies Classic - Great! Movies +1 - STV UK - Sky Sci-Fi - Talking Pictures TV - TCM UK - That's TV - The Box - Trace Vault UK - Tiny Pop TV - TLC UK - Together - Trans World Radio - UK Gold - Ulster TV - Viaplay Xtra - W UK - Warner TV IT - Yesterday - 4Music - 4 Seven - 5 Star - Al Jazeera - Al Jazeera Arabic English - Alibi - Animal Planet UK - Arise News - At The Races - BBC1 - BBC1 Northern Ireland - BBC One Scotland - BBC2 - BBC3 - BBC4 - BBC Alba - BBC News Channel - BBC Parliament - Bloomberg TV - Boomerang - Boomerang UK - TNT Sports 1 - TNT Sports 2 - TNT Sports 4 - TNT Sports Europe - TNT Sports Ultimate - Cartoon Network - Cartoon Network UK - Cartoonito UK - CBBC - Cbeebies - CBS Drama UK - CBS Reality UK - CGTN - Challenge TV - Channel 4 - Channel 4 +1 - Channel 5 - Children's ITV - CNBC Europe - CNN Europe - Comedy Central Extra UK - Comedy Central UK - Crime and Investigation UK - Cúla4 - Dave - Daystar - Discovery Channel UK - Discovery History UK - Discovery Science UK - Discovery Turbo UK - DMAX UK - DocuBox HD - Drama UK - E4 - E4 Extra - Eden UK - EuroNews - Eurosport 2 UK - Eurosport UK - Extreme Sports Channel - Fashion TV - FashionBox HD - Fast&FunBox HD - Film4 - FilmBox Arthouse - Food Network UK - France24 - Gametoon HD - Gems TV - Ginx Esports TV - The History Channel - History Channel 2 - Home & Garden Television UK - Ideal Home Shopping - Inspiration TV - Investigation Discovery UK - ITV1 - ITV2 - ITV2+1 - ITV3 - ITV4 - ITV Be - JML Direct - Kerrang! - Kiss UK - Pop Max - Legend - Magic - More4 - Movies 24 - MTV 80s UK - MTV 90s UK - MTV Hits UK - MTV Music UK - MTV UK - 5Select - Nat Geo Wild UK - National Geographic Channel UK - Nick Junior UK - Nickelodeon UK - Nicktoons UK - Oireachtas TV - Paramount Network UK - PBS America - Pick TV - Pop UK - Premier Sports 1 - Premier Sports 2 - Quest TV - Quest Red - QVC Beauty - QVC Style - Really UKTV - Revelation TV - RTÉ One - RTÉ2 - RTÉ News - RTÉjr - Russia Today - S4C - Sky Arts - Sky Atlantic - Sky Crime - Sky Kids - Sky Witness - Sky Max - Sky Cinema Action - Sky Cinema Comedy - Sky Cinema Thriller - Sky Family - Sky Nature UK - Sky Showcase - Sky Sports Racing - Sky News - Smithsonian Channel - SonLife - Sony Channel - Great! TV - Great! Movies - Great! Movies Action - Great! Movies Classic - Great! Movies +1 - Sky Sci-Fi - Talking Pictures TV - TCM UK - TG4 Ireland - The Box - Tiny Pop TV - TLC UK - Together - Virgin Media One - UK Gold - Ulster TV - Viaplay Xtra - Virgin Media Four - Virgin Media More - Virgin Media Three - Virgin Media Two - W UK - WION - Yesterday - Tring 3 Plus - 3SAT - 4Fun Dance - 4Fun Kids - 24 Kitchen - 24 ВЕСТИ - 360 TuneBox - A2 CNN - ABC News Albania - Adria TV - Agro TV - Al Jazeera Balkans - AMC - Anixe HD Serie - Das Erste - Arena Esport - Arena Fight - Arena Sport 1 Premium - Arena Sport 1x2 - Arena Sport 2 Premium - Arena Sport 3 Premium - Arena Sport 5 RS - Arena Sport 6 RS - Arena Sport 7 RS - Arena Sport 8 RS - Arena Sport 9 RS - Arena Sport 10 RS - ARTE DE - AXN - AXN Spin - B92 - BabyTV - Balkan trip - Balkan TV - Bang Bang - BBC Earth - BBC World News - BlicTV - Bloomberg Adria - Radio Televizija BN - BN music - BN 2 HD - Boomerang - Brainz TV - Bravo Music - Cartoon Network - Cartoonito CEE - CBS Reality - CCTV 4 Europe - CGTN - CGTN Documentary - Cinemax - Cinemax 2 - CineStar Premiere 1 - CineStar Premiere 2 - CineStar TV2 - CineStar TV Comedy Family - CineStar TV Fantasy - Click TV - Croatian Music Channel - CNN Europe - Nicktoons - Crime & Investigation Channel - Cufo TV - Deutsche Welle English - DigitAlb T HD - Discovery Animal Planet - Discovery Channel - Discovery Science - TLC - Discovery Turbo Extra - Disney Channel - Disney Junior - DM SAT - DocuBox HD - Dorcel TV - Dorcel XXX - DOX TV - Dr. Fit HD - DuckTV - Elrodi - Elta 1 HD - E! Entertainment - Epic Drama (CEE) - Erox HD - Eroxxx HD - Eurochannel - EuroNews - Euronews Albania - EuroNews Srbija - Eurosport - Eurosport 2 - Explorer Histori - Explorer Natyra - Explorer Shkence - Extreme Sports Channel - FACE TV - Fashion TV - FashionBox HD - Fast&FunBox HD - FAX News - FightBox HD - SK Fight - Film Aksion Digitalb - Film Autor - Film Drame Digitralb - Film Klub - Film Thriller Digitalb - FilmBox Arthouse - FilmBox Extra RS - FilmBox Stars RS - FilmBox Premium RS - Food Network - STAR Channel - STAR Crime - STAR Life - STAR Movies - FOX NEWS - France24 - France 3 - France 24 French - Radio Televizija Federacije BIH - Gametoon HD - SK Golf - Golica TV - Grand Televizija - Grand nostalgija - HappyTV - Hayat Folk - Hayat Music - Hayat Plus - Hayat TV - Hayatovci - HBO - HBO3 - HBO2 - Home & Garden Television - The History Channel - History Channel 2 - HRT 1 - HRT 2 - HRT 3 - HRT 4 - HUSTLER TV - IDJ World - Insajder TV - Insta TV - Investigation Discovery - Tring Jolly HD - Jugoton TV - Junior TV - K1 TV - K::CN 2 Music - Kanal 3 Prnjavor - Kanal D - Kanali 7 - Kazbuka - KitchenTV - Klan Kosova - Kohavision - K::CN 1 Kopernikus - Kurir TV - Living HD - Lov i ribolov - MCN TV - Mediaset Italia - DigitAlb Melody TV - Minimax - MTV Europe - MTV 00s - Club MTV International - MTV Hits International - MTV Live HD - MTV 90s International - MUSE - My Music - MyZen TV - N1 RS - Наша ТВ - National Geographic - National Geographic Channel HD - Nat Geo Wild - NBA TV - News 24 - Nat Geo Wild HD - Nick Junior - Nickelodeon Commercial - Nova Max - Nova S - Nova Series - Nova Sport Srbija - RTV Novi Pazar - NTV IC Kakanj - O Kanal - OBN - Ora News - OTV Valentino - Pickbox TV RS - Pikaboo - RTV PINK - RED tv - Vesti - Pink Action - Pink Thriller - Pink Crime & Mystery - Pink BH - Pink Classic - Pink Comedy - Pink Erotic 1 - Pink Erotic 2 - Pink Erotic 3 - Pink Erotic 4 - Pink Erotic 5 - Pink Erotic 6 - Pink Erotic 7 - Pink Erotic 8 - TV PINK EXTRA - PINK Family - Pink Fashion - PINK Film - Pink Folk 1 - Pink Folk 2 - Pink Ha Ha - Pink Hits - Pink Hits 2 - Pink Horror - Pink Kids - Pink Koncert - Pink Kuvar - Pink LOL - Pink M - Pink Movies - Pink Romance - Pink SCI FI & Fantasy - Pink Music 1 - Pink and Roll - Pink Pedia - TV PINK PLUS - Pink Premium - Pink Reality - Pink Serije - Pink Show - Pink Soap - Pink Style - Pink Super Kids - Pink Western - PINK World - Pink World Cinema - PINK Zabava - Premier League TV - Brazzers TV (ex. Private Spice) - Private TV - ProSieben - Prva FILES - Prva KICK - Prva LIFE - Prva MAX - Prva Plus - Prva Srpska TV - Prva TV Crna Gora - Prva World - RAI UNO - RAI DUE - Reality Kings - Report TV - Россиᴙ 24 - RT Documentary - RTK 1 - RTL - RTL 2 - RTL Croatia World - RTL Kockica - RTL Living - RTRS - RTRS PLUS - RTS 1 - RTS 2 - RTS 3 - RTS Drama - RTS Klasika - RTS Kolo - RTS Muzika - RTS Nauka - RTS SVET - RTS Trezor - RTS Život - Radio Televizija Budva - Russia Today - Scan TV - SciFi - Sport Klub 1 Crna Gora - SK esports - Sky News - RTV Slovenija 1 - Tring Smile - SOS Plus - Sport Klub 1 Srbija - Sport Klub 4 - Sport Klub 5 - Sport Klub 6 - Sport Klub HD - Sport Klub 1 Slovenija - Sport Klub 3 - Sport Klub 2 Srbija - Superstar 2 - Stinet - Studio B - STV Folk - SuperSport 1 AL - Superstar TV - K::CN 3 Svet Plus - Syri TV - Televizioni 7 - Tanjug Tačno - Timeless Drama Channel - TGCOM24 - Tip TV - TOGGO plus - Top Channel - Top News - Toxic Folk - Toxic TV - Travel Channel - Tring Collection - Tring Comedy - Tring History - Tring Kids - Tring Life - Tring Action - Tring Novelas - Tring Planet - Tring Shqip - Tring Super - Tring Tring - Tring World - TV5Monde Europe - TV1000 Balkan - Televizija TV7 - Arena Sport 1 RS - Arena Sport 2 RS - Arena Sport 3 RS - Arena Sport 4 RS - TV Duga + SAT - TV Dukagjini - Телевизија Храм - RTV Most - Televizija Doktor - UNA TV - DIVA (ex. Universal) - Vavoom - MTV 80s - Viasat Explore CEE - Viasat History - Viasat Nature CEE - Vikom - Vizion Plus - RT Vojvodina 1 - RT Vojvodina 2 - Woman HD - ZDFinfo - ZDFneo - Zdrava televizija - Zico TV - BG Music Channel - Fuel TV - Passion XXX - The Voice BG - 7RM - 8 Andalucía - 8tv Catalunya - 3/24 - À Punt ES - AMC Break ES - Al Jazeera - AMC Crime ES - Antena 3 - Antena.nova - Aragón TV - Atreseries ES - AXN ES - AXN White ES - BabyTV ES - BBC World News - BE MAD ES - Betis TV ES - Bloomberg TV - Boing ES - BOM - Calle 13 - Canal 24H - Canal Cocina - Canal Decasa - Canal Extremadura - Canal Fútbol Replay - Odisea - Canal Panda - Canal Parlamento - Canal Sur - Castilla la Mancha TV - Caza y Pesca ES - Clan TVE - CNBC Europe - CNN Europe - Comedy Central ES - COSMO - Cuatro - DAZN 1 ES - DAZN 2 ES - DAZN F1 - DBike Channel - Deutsche Welle English - Deutsche Welle Espanol - Discovery Channel ES - Discovery MAX.es - Disney Channel ES - Disney Junior ES - Divinity - DKISS ES - El Toro TV - LEVANTE TV - Energy - Esport3 - EuroNews - Euronews FR - Eurosport 1 ES - Eurosport 2 ES - EWTN ES - Extreme Sports Channel - Fashion TV - Factoria de Ficción - Feel Good - Fight Time - FOX ES - France24 - HispanTV - Historia ES - HIT TV ES - Canal Hollywood - Iberalia HD CAZA - Iberalia HD PESCA - Iberalia TV - La 1 Cataluña - La dos - LA 8 MEDITERRANEO - La Otra ES - La primera - La Rioja - La sexta - Mega ES - Mezzo - Mezzo Live HD - MOTO ADV - Motorvision TV - Movistar Acción - Movistar Cine Español - Movistar Comedia - Movistar Deportes 1 - Movistar Deportes 2 - Movistar Drama - Movistar Estrenos - Movistar Estrenos 2 - Movistar Fórmula 1 - Movistar Golf - Movistar LaLiga - Movistar Liga de Campeones - Movistar Series - Movistar Seriesmania - MTV 00s - Club MTV International - MTV ES - MTV Hits International - MTV Live HD - MTV Music UK - MTV 90s International - MyZen TV - Nasa TV US - Nat Geo Wild ES - National Geographic ES - Nautica TV - Antena.neox - Nick Junior ES - Nickelodeon ES - Paramount Network ES - Paramount Comedy ES - Real Madrid TV - Russia Today ES - SYFY ES - Sevilla FC TV - Sky News - Stingray Classica - Sundance ES - Canal 33 - SX3 - TCM ES - Telecinco - TELE ELX - TeleDeporte - TeleMadrid - Ten ES - Warner TV ES - Toros TV - TV3 Catalunya - TV3 ES - TV5Monde Europe - TV Canaria - TVE Internacional - Televisión de Galicia - #Vamos - MTV 80s - 6ter - 360 TV - AB3 - Action - Al Arabiya - Al Jazeera - Antena 3 - Das Erste - ART Aflam 1 - ART Aflam 2 - ART Cinema - ARTE FR - ARTE DE - Atreseries ES - BabyTV - BBC Earth - BBC World News - beIN Drama Channel - beIN Movies Action - beIN Movies Drama - beIN Movies Family - beIN Movies Premiere - beIN Movies Premiere TR - beIN Series 1 - beIN Series 2 - beIN Sports 1 FR - beIN Sports 2 FR - beIN Sports 3 FR - beIN Sports MAX 5 FR - beIN Sports MAX 6 FR - beIN Sports MAX 7 FR - beIN Sports MAX 8 FR - beIN Sports MAX 9 FR - beIN Sports MAX 10 FR - beIN Sports MAX 4 FR - Benfica TV - BET FR - BFM Business - BFM TV - Bloomberg TV - Boing - Boomerang - Boomerang FR - Boomerang UK - C8 FR (ex. D8) - Canal 24H - Canal Cocina - Canal Decasa - CANAL+ DOCS - Canal+ Kids FR - CANAL+ GRAND ECRAN - Canal J - Canal+ Cinéma(s) FR - Canal+ France - Canal Plus Sport FR - Canal+ Series FR - Cartoon Network - Cartoon Network FR - CCTV 4 Europe - CGTN - CGTN Documentary - Первый - Chérie 25 - Ciné+ Classic - Ciné+ Club - Ciné+ Emotion - Ciné+ Famiz - Ciné+ Frisson - Polar+ - Cine+ Premier FR - English Club TV - CNBC Europe - CNews - CNN Europe - Comedie+ - Comedy Central FR - Comedy Central UK - Crime District - CStar FR - CStar Hits France - Daystar - Deutsche Welle English - Discovery Channel FR - Discovery Investigation FR - Disney Channel FR - Disney Junior FR - Stingray Djazz - Dorcel TV - Dorcel XXX - E! Entertainment - Euro Star - Eurochannel - Eurochannel FR - EuroNews - Euronews FR - Eurosport 2 FR - Eurosport FR - Fashion TV - FightBox HD - FOX NEWS - France24 - France 2 - France 3 - France 4 - France 5 - France24 Arabic - France 24 French - France Info - Game One - Ginx Esports TV - Golf Channel Češka - Golf Channel FR - Golf plus - Gulli - Habertürk - HUSTLER TV - i24News FR - Infosport+ - iTVN - iTVN Extra - J-One - Kabel 1 - Kanal 7 - KBS World HD - KiKA - L'Equipe - La Chaîne Info - LCP - M6 - Mangas - MBC Bollywood - MCM FR - MCM Top - Mediaset Italia - Mezzo - Mezzo Live HD - MGG TV - Motorvision TV - Motorvision TV France - MTV Europe - MTV 00s - MTV FR - MTV Hits FR - MTV Hits International - MTV Live HD - Museum TV - NTV DE - Nat Geo Wild FR - National Geographic FR - The Nautical Channel - Nickelodeon FR - Nickelodeon Junior FR - Nickelodeon Teen FR - Novelas TV FR - NRJ12 - RMC Story - OCS Geants - OCS Max - OCS Pulp - Olympia TV - OSN TV Movies Hollywood - OSN TV Movies Premiere - OSN TV Kids - OSN TV Movies Action - OSN TV Ya Hala Aflam - Paramount Channel FR - Paris premiere - TV PINK EXTRA - PINK Film - Pink Music 1 - TV PINK PLUS - Piwi+ - Planète+ Aventure - Planete+ Crime - Planète+ - Playboy TV - Power Türk TV - Brazzers TV (ex. Private Spice) - Private TV - ProSieben - RAI UNO - RAI DUE - RAI TRE - RAI Education - RAI News 24 - RAI Storia - Reality Kings - RMC Découverte - RMC Sport 1 - RMC Sport 2 - RMC Sport Live 4 - RMC Sport Live 5 - RMC Sport Live 6 - RMC Sport Live 7 - RMC Sport Live 8 - RMC Sport Live 9 - RMC Sport Live 10 - RMC Sport Live 11 - RMC Sport Live 12 - RMC Sport Live 13 - RMC Sport Live 14 - RMC Sport Live 15 - RMC Sport Live 16 - RMC Sport Live 17 - RMC Sport Live 3 - RT Documentary - RTL Zwei - RTL DE - RTL Nitro - RTP3 - RTS SVET - Russia Today - Sat.1 - Seasons - Show Türk - SIC Internacional - Sky News - Star Movies MENA - Star World MENA - Stingray CMusic - Stingray Classica - Stingray iConcerts - Super RTL - SWR - TCM UK - TCM Cinéma - Télétoon+ FR - Télévision française 1 - TFX - TGCOM24 - TiJi - TMC - Trace Urban - Travel Channel - TRT 1 - TRT Çocuk - TRT Turk - TRT World - TV3 Catalunya - TV5 Monde - TV5Monde Asia - TV5Monde Europe - TV5Monde Style - TV1000 Global Kino - TV Breizh - TVE Internacional - Televisión de Galicia - MTV 80s - Vivid TV - Vosges Télévision - VOX - W9 - Warner TV FR - Welt - World Fashion Channel - ZDF - ZDFinfo - XXL - 3SAT - 4Fun Dance - 24 Kitchen - 24 ВЕСТИ - 360 TuneBox - Adult Channel - Al Jazeera - Al Jazeera Balkans - ALFA TV - AMC - Das Erste - Arena Esport - Arena Fight - Arena Sport 4 HR - Arena Sport 6 HR - Arena Sport 8 HR - Arena Sport 9 HR - Arena Sport 10 HR - ARTE DE - Alternativna televizija Banja Luka - Aurora TV - AXN - AXN Spin - B1 TV - B92 - BabyTV - Balkan trip - Balkan TV - Balkanika TV - BBC Earth - BBC First - BBC World News - Radio Televizija BIH - Bloomberg TV - Bloomberg Adria - Blue Hustler - Radio Televizija BN - BN music - BN 2 HD - Body in Balance - Boomerang - Brainz TV - Cartoon Network - Cartoonito CEE - Cartoonito UK - CBS Reality - CCTV 4 Europe - CGTN - CGTN Documentary - Cinemax - Cinemax 2 - CineStar Action&Thriller - CineStar Premiere 1 - CineStar Premiere 2 - CineStar TV1 - CineStar TV2 - CineStar TV Comedy Family - CineStar TV Fantasy - English Club TV - Croatian Music Channel - CNBC Europe - CNN Europe - Comedy Central DE - Nicktoons - Crime & Investigation Channel - Da Vinci Learning - Deluxe Music - Deutsche Welle English - Diadora TV - Discovery Animal Planet - Discovery Channel - Discovery Science - TLC - Disney Channel - Stingray Djazz - DMAX DE - DMC televizija - DM SAT - DocuBox HD - DOKU TV - Doma TV - Dorcel TV - Dorcel XXX - DOX TV - Dr. Fit HD - Sport 1 DE - Dubrovačka Televizija - DuckTV - Duna World - E! Entertainment - Epic Drama (CEE) - Erox HD - Eroxxx HD - Eurochannel - EuroNews - Eurosport - Eurosport 2 - Eurosport 2 DE - Eurosport 1 EMEA - Eurosport.com - Eurosport 1 DE - ExtraTV - Extreme Sports Channel - FACE TV - Fashion TV - FashionBox HD - Fast&FunBox HD - FightBox HD - SK Fight - Film4 - FilmBox Arthouse - FilmBox Extra RS - FilmBox Stars RS - FilmBox Premium RS - Fireplace - Food Network - STAR Channel - STAR Crime - STAR Life - STAR Movies - FOX NEWS - France24 - France 24 French - Radio Televizija Federacije BIH - Fuel TV - FullTV - FunBox UHD - GameHub HR - Gametoon HD - Ginx Esports TV - SK Golf - GP1 - Grand Televizija - Grand nostalgija - HappyTV - Hayat Folk - Hayat TV - Hayatovci - HBO - HBO3 - HBO2 - Home & Garden Television - The History Channel - History Channel 2 - HIT TV - HSE - HRT 1 - HRT 2 - HRT 3 - HRT 4 - HRT Int. - HUSTLER TV - ICT Business - Insta TV - Otvorena televizija - JimJam - Jugoton TV - K::CN 2 Music - Kabel 1 - Kabel eins Österreich - Kabel eins Doku - Kanal Rijeka - KBS World HD - KiKA - KinoTV - KitchenTV - Pop Max - Klape i Tambure TV - KLASIK HR - KLASIK - K::CN 1 Kopernikus - Laudato TV - Legend - Libertas TV - Lov i ribolov - LUXE TV - M1 Family - M1 FILM - M1 Gold - M6 - Maria Vision - MAXSport 1 - MAXSport 2 - Mediaset Italia - Mezzo - Mezzo Live HD - Motorvision TV - MG Movie Generation - MTV Europe - MTV 00s - Club MTV International - MTV Hits International - MTV Live HD - MTV 90s International - MyZen TV - N1 HR - N24 Doku - NTV DE - National Geographic - National Geographic Channel HD - Nat Geo Wild - The Nautical Channel - MrežaZG - Nat Geo Wild HD - Nick Junior - Nick Music - Nickelodeon - NOVA TV - Nova BH - Nova Plus Family - Nova Sport Srbija - O Kanal - OBN - One - ORF1 - ORF2 - ORF Sport Plus - Osječka televizija - OTV Valentino - Phoenix - Pikaboo - Pikaboo 2 - RTV PINK - RED tv - Vesti - Pink BH - Pink Classic - TV PINK EXTRA - Pink Fashion - PINK Film - Pink Folk 1 - Pink Folk 2 - Pink Ha Ha - Pink Hits 2 - Pink Kids - Pink Koncert - Pink Kuvar - Pink LOL - Pink M - Pink Music 1 - Pink Pedia - TV PINK PLUS - Pink Reality - Pink Serije - Pink Show - Pink Style - Pink Super Kids - PINK World - Pink World Cinema - PINK Zabava - Planet Earth - Plava televizija - Playboy TV - Poljoprivredna TV - Posavska Televizija - TV Zelina - Brazzers TV (ex. Private Spice) - Private TV - ProSieben - ProSieben MAXX - Prva KICK - Prva Plus - Prva Srpska TV - Prva World - QVC Deutschland - RAI UNO - RAI DUE - RAI TRE - RAI Education - RAI News 24 - RAI Sport 1 - RAI Storia - Reality Kings - RedLight HD - Россиᴙ 24 - Radiotelevizija Banovina - RTL - RTL 2 - RTL Zwei - RTL Adria - RTL DE - RTL Kockica - RTL Living - RTL Nitro - RTLup - RTRS - RTRS PLUS - RTS 1 - RTS 2 - RTS SVET - RTV Herceg-Bosne - Russia Today - Saborska TV - Samobor TV - Sat.1 - Sat.1 Österreich - Sat.1 Gold - Slavonskobrodska Televizija - SciFi - ServusTV - SK 4K - SK esports - Sky News - TV Slavonije i Baranje - RTV Slovenija 1 - RTV Slovenija 2 - RTV Slovenija 3 - sonnenklar.TV - Sony Channel - Great! Movies Action - Great! Movies Classic - Great! Movies +1 - SOS Plus - Sport Klub 4 - Sport Klub 5 - Sport Klub 6 - Sport Klub 7 - Sport Klub 8 - Sport Klub 9 - Sport Klub 10 - Sport Klub HD - Sport Klub 1 Hrvatska - Sport Klub 2 Hrvatska - Sport Klub 3 - Sport Klub 2 Srbija - Sportska Televizija - Stars TV PL - Stingray CMusic - Stingray Classica - Stingray iConcerts - Studio B - Super RTL - Supertennis HD - K::CN 3 Svet Plus - Timeless Drama Channel - Telecinco - Televizija Alfa - Telma - TiJi - Tiny Pop TV - TOGGO plus - Toon kids - Toxic Folk - Toxic Rap - Toxic TV - Trace Urban - Travel Channel - Trend TV - TV5 Monde - TV5Monde Europe - TV1000 Balkan - Arena Sport 1 HR - Arena Sport 2 HR - Arena Sport 3 HR - Televizija Dalmacija - TV Duga + SAT - TV Jadran - TV Šibenik - TV Vijesti - Televizija Zapad Zaprešić - Televizija Crne Gore MNE - TVE Internacional - UNA TV - DIVA (ex. Universal) - Varaždinska Televizija - Vavoom - MTV 80s - Viasat Explore CEE - Viasat History - Viasat Nature CEE - Plava vinkovačka TV - Vivid Red - Vivid TV - Vizion Plus - RT Vojvodina 1 - VOX - Welt - Woman HD - Zagrebačka Televizija - ZDF - ZDFinfo - ZDFneo - Zdrava televizija - Tring 3 Plus - 4Fun Dance - 4Fun Kids - 24 Kitchen - 360 TuneBox - Agro TV - Televizija Alfa - Al Jazeera Balkans - Al Jazeera - Alpha TV - AMC HU - Antena Europe - Apostol TV - Arena4 HU - Arena Esport - Arena Fight - Arena Sport 1 BiH - Arena Sport 1 RS - Arena Sport 1 SI - Arena Sport 1 Premium - Arena Sport 1 Premium SI - Arena Sport 1x2 - Arena Sport 2 RS - Arena Sport 2 SI - Arena Sport 2 Premium - Arena Sport 3 RS - Arena Sport 3 SI - Arena Sport 3 Premium - Arena Sport 4 RS - Arena Sport 4 SI - Arena Sport 5 HR - Arena Sport 5 RS - Arena Sport 6 RS - Arena Sport 7 HR - Arena Sport 7 RS - Arena Sport 8 RS - ARTE DE - ATV Avrupa - AXN HU - AXN - AXN Spin - B1 TV - Balkanika TV - Balkan trip - BBC Earth - BBC News Channel - BBC World News - TV Belle Amie - BN 2 HD - BN music - Boomerang - Brainz TV - Brazzers TV (ex. Private Spice) - BRIO - Canale 5 - CGTN Documentary - Cinemania TV - CineStar TV1 - CineStar TV RS - CineStar TV2 - CineStar Action&Thriller - CineStar Action&Thriller RS - CineStar TV Comedy Family - CineStar TV Fantasy - CineStar Premiere 1 - CineStar Premiere 2 - CNN Europe - CNN Türk TV - Comedy Central HU - Comedy Central Family HU - CoolTV - Cufo TV - D1 TV HU - Das Erste - Da Vinci Learning - Dexy TV - Discovery Channel HU - Discovery Science - Disney Channel HU - DM SAT - DocuBox HD - DOKU TV - Doma TV - Dr. Fit HD - Deutsche Welle English - English Club TV - Epic Drama (CEE) - Erox HD - Eroxxx HD - ETV HD - Eurochannel - Euro D - EuroNews - Eurosport - Eurosport 2 - Explorer Histori - Explorer Natyra - Explorer Shkence - FACE TV - FashionBox HD - Fashion TV - Fast&FunBox HD - FEM3 - FightBox HD - Pink Fight Network - Film4 HU - Film Aksion Digitalb - FilmBox Arthouse - Filmbox Stars HU - Film Cafe HU - Film Drame Digitralb - Film Klub - Film Mania HU - Film+ HU - Film Thriller Digitalb - Food Network - STAR Crime - France24 Arabic - France24 - France 24 French - Galaxy4 - Gametoon HD - Ginx Esports TV - Golica TV - Grand Televizija - Pink Ha Ha - Hayat Folk - Hayat Music - Hayatovci - Hayat Plus - HBO HU - Home & Garden Television - Hír TV - History Channel 2 - HRT 2 - HRT 4 - HRT Int. - IDJ World - INTV AL - Investigation Discovery - Italia 1 - Izaura TV - JockyTV - Jugoton TV - Kanal 3 Prnjavor - Kanal A, SLO - Kanal D TR - Kazbuka - KINO - KinoTV - KitchenTV - Klan Kosova - Klan Macedonia - KLASIK - Kohavision - Kurir TV - La7 - Laudato TV - Life TV HU - Living HD - Pink LOL - Lov i ribolov - M1 FILM - M1 Gold - Mediaset Italia - Mezzo - Mezzo Live HD - Minimax - MiniTV - Mozi plusz TV - Moziverzum - МРТ 1 - МРТ 2 - MTV Europe HU - MTV Live HD - Muzsika TV - N1 BA - N1 HR - National Geographic HU - Nat Geo Wild HU - RTL Nitro - Nova 24 TV - Nova S - Nova Plus Cinema - Nova Sport Srbija - Nova BH - TV NOVA Pula - Nova M - Nova World - Novosadska TV - OBN - O Kanal - One - OTO - PΛX - Pickbox TV - Pink Action - Pink BH - Pink Classic - Pink Comedy - Pink Crime & Mystery - PINK Family - Pink Fashion - Pink Folk 2 - Pink Hits - Pink Horror - Pink Koncert - Pink Kuvar - Pink M - Pink Movies - Pink and Roll - Pink Pedia - Pink Premium - Pink Romance - Pink SCI FI & Fantasy - Pink Serije - Pink Show - Pink Soap - Pink Style - Pink Super Kids - Pink Thriller - Pink Western - PINK World - Pink World Cinema - PINK Zabava - Planeta TV BG - Planet Earth - Planet TV SI - Playboy TV - POP TV - Power Türk TV - Prime - ProSieben Fun - Prva FILES - Prva KICK - Prva LIFE - Prva MAX - Prva TV Crna Gora - Prva Plus - Prva World - QVC STYLE DE - QVC Style - RadioBremen - RAI UNO - RAI DUE - RAI TRE - RAI Gulp - RAI News 24 - RAI Storia - real time - Rete 4 - Russia Today - RTK 1 - RTK 2 - RTL - RTL HU - RTL Crime - RTL Gold - RTL Ketto - RTL Living - RTL Passion - Super RTL - RTRS PLUS - RTS 2 - RTS 3 - RTS Drama - RTS Kolo - RTS Muzika - RTS Poletarac - RTS SVET - RTS Trezor - RT Vojvodina 1 - RT Vojvodina 2 - RTV21 - Россиᴙ 24 - SonLife - Show Türk - Сител - Magyar Sláger TV - Sorozat+ - Spektrum TV - Spektrum Home HU - Spíler1 TV - Spíler2 TV - Sport 1 DE - Sport 1 HU - Sport 2 HU - Sport Klub 1 Srbija - Sport Klub 1 Slovenija - Sport Klub 2 Srbija - Sport Klub 2 Slovenija - Sport Klub 3 - Sport Klub 4 - Sport Klub 5 - Sport Klub 6 - SK esports - SK Golf - Sport Klub HD - Sportska Televizija - Sport TV1.pt - Šport TV 1 - Sport TV2 - Šport TV 2 - Stars TV PL - Stingray iConcerts - Story4 - Studio B - Superstar TV - Super TV2 - TGCOM24 - The Fishing and Hunting - TLC - TOGGO plus - Trace Urban - Travel Channel - TRT Arapça - TRT Avaz - TV2 HU - TV2 Comedy - TV2 Kids - TV2 Séf - TV 3 Medias - TV4 HU - TV Arena - Televizija Crne Gore 1 - Televizija Crne Gore 2 - Televizija Crne Gore MNE - TV Galaksija - Телевизија Храм - K::CN 1 Kopernikus - K::CN 2 Music - K::CN 3 Svet Plus - TV Koper - TVN24 - TVN - TV Paprika HU - TVP Polonia - RTV Slovenija 1 - RTV Slovenija 2 - RTV Slovenija 3 - ТВ Сонце - TV Vijesti - Ülke TV - Viasat3 - Viasat 6 - Viasat Explore CEE - Viasat History - TV1000 Global Kino - Viasat Nature CEE - TV1000 Balkan - VOX - Woman HD - World Fashion Channel - Zagrebačka Televizija - ZDF - Zenebutik - 360 TuneBox - Das Erste - ARD-alpha - ATV Spirit HU - BabyTV - BBC News Channel - BBC World News - Bloomberg TV - Boomerang - Cartoonito CEE - CBS Reality - CCTV 4 Europe - Cinemax 2 HU - Cinemax HU - English Club TV - CNN Europe - Da Vinci Learning - Deutsche Welle English - Discovery Turbo Extra - DocuBox HD - DuckTV - Duna TV - Duna World - E! Entertainment - Epic Drama (CEE) - Eroxxx HD - Extreme Sports Channel - FashionBox HD - Fast&FunBox HD - Fehérvár TV - FightBox HD - FilmBox Arthouse - Filmbox Extra HU - Filmbox Family HU - FilmBox HU - Filmbox Premium HU - Food Network - France24 - Gametoon HD - HBO - HBO 2 HU - HBO 3 HU - Home & Garden Television - The History Channel - History Channel 2 - History Channel HU - Home & Garden Television UK - HUSTLER TV - Investigation Discovery - Investigation Discovery UK - Jazz TV HU - JimJam - KiKA - Magyar Televízió 1 - M2 Petőfi - Magyar Televízió 3 - M4 sport - M4 Sport Plus - m5 - ATV HU - Magyar Mozi TV - MATCH4 - MAX4 - Mediaset Italia - Mezzo - Mezzo Live HD - Minimax - Minimax HU - MTV 00s - Club MTV International - MTV Hits International - MTV Live HD - MTV 90s International - MyZen TV - Nick Junior PL - Nickelodeon Commercial - Nicktoons PL - Ozone Network - Paramount Network HU - Polonia1 - Private TV - ProSieben - RAI UNO - RAI TRE - RedLight HD - RTL Zwei - RTL DE - RTL Három - Sat.1 - Sky News - Viasat Film HU - Stingray Classica - Stingray iConcerts - Super RTL - TeenNick - Travel Channel - TVE Internacional - MTV 80s - Viasat 2 - Viasat History - Viasat Nature CEE - VOX - ZDF - 7 Gold - 20 Mediaset - Alma TV - Boing - Boing Plus - Boomerang IT - Canale 5 - Canale 7 - Cartoon Network IT - Cartoonito Italia - cielo - Cine34 - Class TV Moda - Comedy Central IT - CI Crime+ Investigation - DAZN IT - DeA Junior - DeA Kids - Discovery Channel IT - Discovery MAX.es - DMAX IT - Eurosport 2 IT - Eurosport IT - Focus TV - Food Network Italia - Frisbee - Gambero Rosso Channel - Giallo TV - History Channel IT - Inter Channel - Iris - Italia 1 - Italia 2 - K2 - La Cinque - La7 - La7 AU - La7d - Lazio Style Channel - Marco Polo TV - Mediaset Extra - Mediaset Italia - Mediaset Italia AU - Milan TV - MotorTrend - MTV Hits International - MTV Italia - MTV Music UK - MTV Music IT - MTV 90s International - National Geographic - Nick Junior IT - Nickelodeon IT - NOVE - Parole di Vita - Radio Italia TV - Radiofreccia - RAI UNO - RAI DUE - RAI TRE - RAI 3 Bis - RAI 4 - RAI 5 - RAI Education - RAI Gulp - RAI Italia Australia - RAI Movie - RAI News 24 - RAI Premium - RAI Sport 1 - RAI Storia - RAI World Premium - Rai Yoyo - real time - Rete 4 - Sky Arte - Sky Atlantic IT - Sky Caccia e Pesca - Sky Cinema Action IT - Sky Cinema Collection IT - Sky Cinema Comedy IT - Sky Cinema Drama IT - Sky Cinema Due - Sky Cinema Family IT - Sky Cinema Romance IT - Sky Cinema Suspense IT - Sky Cinema Uno - Sky Documentaries IT - Sky Investigation - Sky Nature IT - Sky Pesca e Caccia - Sky Serie - Sky Sport24 HD - Sky Sport 1 IT - Sky Sport 2 IT - Sky Sport 3 IT - Sky Sport F1 IT - Sky Sport MotoGP IT - Sky Sport Plus IT - Sky TG24 HD - Sky Uno - Sportitalia - Super! - Supertennis HD - Telequattro - Teletutto - TGCOM24 - Top Calcio 24 - Top Crime - TV8 IT - TV 2000 - Twenty Seven - VH1 IT - Warner TV IT - Tring 3 Plus - 24 Kitchen - 24 ВЕСТИ - 360 TV - ABC News Albania - Agro TV - Al Jazeera - Al Jazeera Balkans - ALFA TV - Алсат М - AMC - Anixe HD Serie - Das Erste - Arena Esport - Arena Fight - Arena Sport 1 MK - Arena Sport 1 Premium - Arena Sport 2 Premium - Arena Sport 3 Premium - Arena Sport 5 RS - ARTE DE - Alternativna televizija Banja Luka - AXN - AXN Spin - Balkan trip - Balkanika TV - Bang Bang - BBC First - BBC World News - Bloomberg TV - Bloomberg Adria - Radio Televizija BN - BN music - BN 2 HD - Boomerang - Brainz TV - Cartoon Network - Cartoonito CEE - CBS Reality - Cinemania TV - Cinemax - Cinemax 2 - CineStar Premiere 1 - CineStar Premiere 2 - CineStar TV2 - Croatian Music Channel - CNBC Europe - CNN Europe - Nicktoons - Crime & Investigation Channel - Cufo TV - Da Vinci Learning - Deluxe Music - Deutsche Welle English - DigitAlb T HD - Discovery Animal Planet - Discovery Channel - Discovery Science - TLC - Disney Channel - Disney Junior - DM SAT - DocuBox HD - Sport 1 DE - Elta 1 HD - E! Entertainment - Epic Drama (CEE) - Erox HD - Eroxxx HD - Euro Star - EuroNews - Euronews Albania - Eurosport - Eurosport 2 - Explorer Histori - Explorer Natyra - Explorer Shkence - Extreme Sports Channel - FACE TV - Fashion TV - FashionBox HD - Fast&FunBox HD - FightBox HD - SK Fight - Film Autor - Film Drame Digitralb - Film Klub Extra - Film Thriller Digitalb - FilmBox Arthouse - FilmBox Extra RS - FilmBox Stars RS - The Fishing and Hunting - Food Network - STAR Channel - STAR Crime - STAR Life - STAR Movies - France24 - France 24 French - Radio Televizija Federacije BIH - Ginx Esports TV - SK Golf - Grand Televizija - HappyTV - Hayat Folk - Hayat Music - Hayat Plus - Hayat TV - Hayatovci - HBO - HBO3 - HBO2 - The History Channel - HRT 1 - HRT 3 - HRT 4 - HUSTLER TV - IDJ World - JimJam - Tring Jolly HD - Jugoton TV - Junior TV - K::CN 2 Music - Kabel 1 - Kanal1 - Канал 5 - Канал 8 - Kanal 10 - Kanal D - Kerrang! - KiKA - TV Kiss Menada - KitchenTV - Klan Macedonia - KLASIK - K::CN 1 Kopernikus - Living HD - Lov i ribolov - M1 Family - M1 Film MK - M1 Gold MK - DigitAlb Melody TV - Mezzo - Minimax - МРТ 1 - МРТ 3 - МРТ 4 - МРТ 5 - MTM Televizija - MTV Europe - MTV 00s - Club MTV International - MTV Hits International - MTV Live HD - MTV 90s International - MUSE - My Music - N1 RS - Наша ТВ - National Geographic - National Geographic Channel HD - Nat Geo Wild - News 24 - Nick Junior - Nickelodeon Commercial - Nova S - Nova Sport Srbija - RTV Novi Pazar - O Kanal - OBN - Ora News - Pickbox TV MK - Pikaboo - Pink Music 1 - Pink Serije - Pink Show - Playboy TV - Brazzers TV (ex. Private Spice) - Private TV - ProSieben - Prva FILES - Prva KICK - Prva LIFE - Prva MAX - Prva Plus - Prva Srpska TV - Prva World - RAI UNO - RAI DUE - RAI TRE - RAI Sport 1 - RAI Storia - RedLight HD - Report TV - Россиᴙ 24 - RT Documentary - RTK 1 - RTK 2 - RTK 4 - RTL - RTL 2 - RTL Zwei - RTL DE - RTL Kockica - RTL Living - RTRS - RTS 1 - RTS 2 - RTS 3 - RTS SVET - RTSH 1 - RTV 21 Popullore - RTV Besa - RTV Slon Tuzla - Russia Today - Sat.1 - Scan TV - SciFi - Shenja TV - Сител - SK esports - Sky News - RTV Slovenija 1 - RTV Slovenija 2 - RTV Slovenija 3 - Tring Smile - SOS Plus - Sport Klub 1 Srbija - Sport Klub 4 - Sport Klub 5 - Sport Klub 6 - Sport Klub 7 - Sport Klub 8 - Sport Klub 9 - Sport Klub 10 - Sport Klub HD - Sport Klub 1 Hrvatska - Sport Klub 2 Hrvatska - Sport Klub 3 - Sport Klub 2 Srbija - Superstar 2 - Stinet - Stingray CMusic - Studio B - STV Folk - Super RTL - Superstar TV - K::CN 3 Svet Plus - Syri TV - Televizioni 7 - Timeless Drama Channel - Telma - Tera TV - Tip TV - Top Channel - Top News - Toxic Folk - Toxic Rap - Toxic TV - Trace Urban - Travel Channel - Travelxp - Tring Bunga Bunga - Tring Comedy - Tring Desire - Tring History - Tring Kids - Tring Life - Tring Action - Tring Novelas - Tring Planet - Tring Shqip - Tring Super - Tring Tring - Tring World - TRT 1 - TRT Turk - TV5 Monde - TV1000 Balkan - Arena Sport 2 RS - Arena Sport 3 RS - Arena Sport 4 RS - TV Duga + SAT - TV Dukagjini - TV Edo - Klan TV HD - TVM Ohrid - TV Sarajevo - Televizija Crne Gore MNE - DIVA (ex. Universal) - Valentino Music HD - Vavoom - MTV 80s - Viasat Explore CEE - Viasat History - Viasat Nature CEE - Vikom - Vizion Plus - VOX - Welt - Wness TV - World Fashion Channel - ZDF - Zdrava televizija - 1-2-3.tv - 2X2 - 3SAT - 4Fun Dance - 4Fun Kids - 4FunTV - Telewizja 13 - 13 Ulica - 360 TuneBox - Active Family - Adult Channel - Adventure HD - Al Jazeera - Ale Kino+ - ALFA TVP - AMC PL - Animal Planet PL - Anixe HD Serie - Antena HD - Das Erste - ARD-alpha - ARTE FR - ARTE DE - AstroTV - AXN Black PL - AXN PL - AXN Spin PL - AXN White PL - BabyTV PL - BBC Brit PL - BBC Earth PL - BBC First PL - BBC Lifestyle PL - BBC News Channel - BBC World News - Belsat TV - BFM TV - Bibel TV - Biznes24 - Bloomberg TV - Blue Hustler - Bollywood PL - Boomerang - CANAL+ 4K Ultra HD - CANAL+ Dokument - CANAL+ Family PL - CANAL+ Film PL - CANAL+ Premium +1 PL - Canal+ Domo - CANAL+ Kuchnia - CANAL+ Premium PL - CANAL+ Seriale PL - CANAL+ Sport 2 - CANAL+ Sport 3 - CANAL+ Sport 4 - CANAL+ Sport 5 - CANAL+ Sport PL - Cartoon Network PL - Cartoonito CEE - Cartoonito UK - CBeebies PL - CBS Europa PL - CBS Reality PL - CGTN Documentary - Cinemax 2 PL - Cinemax PL - CNBC Europe - CNews - CNN Europe - Comedy Central DE - Comedy Central PL - COSMO - Crime+Investigation PL - ČT 1 - ČT 2 - ČT 24 - ČT :D - ČT Sport - Da Vinci Learning PL - Deluxe Music - Deutsche Welle English - Deutsche Welle Deutsch - Disco Polo Music PL - Discovery Channel PL - Discovery Historia - Discovery Life PL - Discovery Science PL - Disney Channel PL - Disney Junior Polska - Disney XD PL - DIZI PL - Stingray Djazz - DMAX DE - DocuBox HD - Dorcel TV - Dorcel XXX - Sport 1 DE - DTX PL - Duck TV Plus - DuckTV - E-Sport HD - Eleven Sports 1 PL - Eleven Sports 2 PL - Eleven Sports 3 PL - Eleven Sports 4 PL - E! Entertainment - Epic Drama (Poland) - Eska Rock TV - Eska TV - Eska TV Extra - Еспресо TV - Eurochannel - EuroNews - Euronews FR - Eurosport 1 PL - Eurosport 2 PL - EWTN - EWTN PL - EXTASY TV - Extreme Sports PL - Fashion TV - FashionBox HD - Fast&FunBox HD - Fight Klub HD - FightBox HD - Filmax - FilmBox Action PL - FilmBox Arthouse - FilmBox Extra PL - FilmBox Family PL - FilmBox Premium PL - Fokus TV - Food Network PL - FX Comedy PL - FX PL - France24 - France 2 - France 3 - France 4 - France 5 - France Info - FunBox UHD - Gametoon HD - Ginx Esports TV - Golf Channel PL - HBO 2 PL - HBO 3 PL - HBO PL - Das Health TV - HGTV PL - History 2 Polska - History Channel Polska - HR Fernsehen - HSE - HSE24 Extra - Hustler HD - HUSTLER TV - Insight TV - Investigation Discovery PL - Italia 2 - iTVN - iTVN Extra - JimJam PL - K-TV Katholisches Fernsehen - Kabel 1 - Kabel eins Österreich - Kabel eins Doku - KiKA - Kino Polska - Kino Polska Muzyka - KinoTV PL - La Chaîne Info - LCP - Leo TV - Love Nature - MDR Sachsen-Anhalt - MDR Sachsen - MDR Thüringen - Metro TV - Mezzo - Mezzo Live HD - Minimini+ - Motowizja - MTV Europe - MTV 00s - Club MTV International - MTV DE - MTV Hits International - MTV Live HD - MTV PL - MTV 90s International - münchen.tv - Music Box Polska - MyZen TV - N24 Doku - NTV DE - National Geographic Wild PL - National Geographic PL - National Geographic People PL - The Nautical Channel - NDR Hamburg - NDR Mecklenburg-Vorpommern - NDR Niedersachsen - NDR Schleswig-Holstein - News 24 - Nick Junior PL - Nick Music - Nick DE - Nickelodeon PL - Nickelodeon Ukraine Pluto - Nicktoons PL - Niederbayern TV Deggendorf-Straubing - Novela TV - Novelas+ - Nowa TV - NRJ12 - NUTA GOLD - NUTA.TV HD - oe24.TV - One - ORF2 - Paramount Network PL - Parole di Vita - Phoenix - Planete+ PL - Playboy TV - POLO TV - Polonia1 - TVP Polonia - Polsat - Polsat 1 - Polsat 2 - Polsat Cafe - Polsat Comedy Central Extra - Polsat Doku - Polsat Film - Polsat Games - Polsat Music - Polsat News - Polsat News 2 - Polsat Play - Polsat Rodzina - Polsat Seriale - Polsat Sport - Polsat Sport Extra - Polsat Sport Fight - Polsat Sport News - Polsat Sport Premium 1 - Polsat Sport Premium 2 - Polsat Sport Premium 3 PPV - Polsat Sport Premium 4 PPV - Polsat Sport Premium 5 PPV - Polsat Sport Premium 6 PPV - Polsat Viasat Explore - Polsat Viasat History - Polsat Viasat Nature - Power TV PL - Brazzers TV (ex. Private Spice) - Private TV - ProSieben - PRO 7 Österreich - Proart - ProSieben MAXX - QVC Deutschland - Radio Italia TV - Radiofreccia - RBB Fernsehen Brandenburg - RBB Fernsehen Berlin - Reality Kings - Red Carpet TV PL - RedLight HD - RiC DE - Romance TV PL - RT Documentary - RTL Zwei - RTL DE - RTL Nitro - Russia Today - Sat.1 - Sat.1 Österreich - Sat.1 Gold - Kurier TV - SciFi - ServusTV - Sky Sport News DE - Sky News - sonnenklar.TV - Sportklub PL - SR Fernsehen - Stars TV PL - Stingray CMusic - Stingray Classica - Stingray iConcerts - Stopklatka - Sundance TV PL - Super Polsat - Super RTL - SWR Baden-Württemberg - tagesschau24 - TBN Polska - TeenNick - Tele 5 PL - Tele 5 DE - teleTOON+ - TLC PL - TOGGO plus - Top Kids Jr. PL - Top Kids PL - Trace Urban - Travel Channel PL - Travelxp - TRT Arapça - TTV - TV5Monde Europe - TV6 PL - TV 4 - TV Puls 2 - TV Puls PL - TV Regionalna.pl - TV Republika - TV Silesia - Toya TV - TV Trwam - TVC PL - TVE Internacional - TVN - TVN24 - TVN24 BiS - TVN 7 - TVN Fabuła - TVN Style - TVN Turbo - TVP3 Białystok - TVP3 Bydgoszcz - TVP3 Gdańsk - TVP3 Katowice - TVP3 Kielce - TVP3 Kraków - TVP3 Łódź - TVP3 Lublin - TVP3 Olsztyn - TVP3 Opole - TVP3 Poznań - TVP3 Rzeszów - TVP3 Szczecin - TVP3 Warszawa - TVP3 Wrocław - TVP 1 - TVP 2 - TVP 3 - TVP ABC - TVP ABC 2 - TVP Dokument - TVP HD - TVP Historia - TVP Historia 2 - TVP Info - TVP Kobieta - TVP Kultura - TVP Kultura 2 - TVP Nauka - TVP Regionalna - TVP Rozrywka - TVP Seriale - TVP Sport - TVP Wilno - TVP World - TVR PL - TVS - TVT PL - MTV 80s - Viasat Explore CEE - Vivid Red - VOX - VOX Music TV PL - Warner TV FR - Warner TV PL - Water Planet - WDR Fernsehen Köln - Welt - Welt der Wunder - WP TV - wPolsce PL - Wydarzenia 24 - Xtreme TV - ZDFinfo - ZDFneo - Zoom TV PL - 3SAT - 24 Kitchen - 24Kitchen PT - AMC Break ES - Al Jazeera - AMC Break PT - AMC Crime PT - AMC PT - Antena 3 - ARD-alpha - ARTE FR - ARTV - AXN Movies PT - AXN PT - AXN White PT - BabyTV ES - BBC News Channel - BBC World News - Benfica TV - Biggs - Bloomberg TV - Canal 11 PT - Canal Hollywood PT - Canal Panda - Canal Panda PT - Cartoon Network PT - Cartoonito PT - Casa e Cozinha - Caza y Pesca ES - CBS Reality - CCTV 4 Europe - CGTN - Cinemundo - CMTV - CNBC Europe - CNN Europe - CNN PT - Comedy Central DE - Deutsche Welle English - Deutsche Welle Deutsch - Discovery Channel PT - Discovery Science - TLC PT - Disney Channel PT - Disney Junior PT - Stingray Djazz - DocuBox HD - Sport 1 DE - Eleven Sports 1 PT - Eleven Sports 2 PT - Eleven Sports 3 PT - Eleven Sports 4 PT - Eleven Sports 5 PT - Eleven Sports 6 PT - E! Entertainment - Eurochannel - EuroNews - Eurosport 1 PT - Eurosport 2 PT - Fashion TV - FashionBox HD - Fast&FunBox HD - FightBox HD - FilmBox Arthouse - Food Network - Food Network UK - FOX Comedy PT - FOX Crime PT - FOX Life PT - FOX Movies PT - FOX NEWS - FOX PT - France24 - France 24 French - Fuel TV - FunBox UHD - Gametoon HD - Ginx Esports TV - Canal HISTÓRIA PT - Canal Hollywood - Insight TV - Investigation Discovery - JimJam - KiKA - LUXE TV - M6 - MCM Top - Mezzo - Mezzo Live HD - Motorvision TV - MTV 00s - MTV ES - MTV Live HD - MTV PT - Museum TV - MyZen TV - Nat Geo Wild ES - National Geographic Portugal - The Nautical Channel - Nick Jr. PT - Nickelodeon PT - Nickelodeon Ukraine Pluto - Odisseia - Phoenix - Playboy TV - ProSieben - RAI UNO - RAI DUE - RT Documentary - RTL DE - RTP1 - RTP2 - RTP3 - RTP Açores - RTP Africa - RTP Madeira - RTP Memória - RTP Internacional - Russia Today - Russia Today ES - Sat.1 - SIC - SIC Caras - SIC Internacional - SIC K - SIC Mulher - SIC Noticias - SIC Radical - Sky News - Sport TV+ - Sport TV1.pt - Sport TV2 - Sport TV3 - Sport TV4 - Sport TV5 - Sport TV6 - Stingray CMusic - Stingray iConcerts - Super RTL - Syfy PT - Toros TV - Trace Urban - Travel Channel - TV5 Monde - TV5Monde Europe - TV Cine Action - TV Cine Edition - TV Cine Emotion - TV Cine Top - TVE Internacional - TV Internacional - TVI Ficcao - TVI Reality - VOX - ZDF - ZDFneo - AgroTV RO - Al Jazeera - Al Jazeera Arabic English - AMC RO - Antena1 RO - Antena 3 CNN - Antena Stars RO - ARTE FR - ATV Spirit HU - Auto Motor und Sport - AXN Black RO - AXN RO - AXN Spin RO - AXN White RO - B1 TV RO - BabyTV - Balkanika TV - BBC Earth - BBC First - BBC World News - Bloomberg TV - Bollywood-Classic RO - Bollywood HD RO - Bollywood Film RO - Boomerang - Bucuresti TV RO - Canal 33 RO - Cartoon Network RO - Cartoonito CEE - CBS Reality - CCTV 4 Europe - CGTN - CGTN Documentary - Cinemaraton RO - Cinemax 2 RO - Cinemax RO - Cinethronix RO - CNBC Europe - CNN Europe - Comedy Central Extra BG - Comedy Central Family HU - Comedy Central HU - Comedy Central RO - CoolTV - Credo TV - Crime & Investigation Channel - Da Vinci Learning - Deutsche Welle English - Digi 24 - Digi Animal World RO - Digi Life RO - TV Digi Sport 2 - TV Digi Sport 3 - TV Digi Sport 4 - Digi World RO - Discovery Animal Planet - Discovery Channel - Discovery Science - TLC - Discovery Turbo Extra - Disney Channel RO - Disney Junior - Diva Universal RO - DocuBox HD - Dorcel TV - Dorcel XXX - DuckTV - Duna TV - Duna World - E! Entertainment - Epic Drama (CEE) - Eroxxx HD - Etno TV RO - EuroNews - Eurosport - Eurosport 1 INT - Eurosport 2 INT - Extreme Sports Channel - Fashion TV - Fast&FunBox HD - Favorit TV RO - FEM3 - FightBox HD - Film Cafe RO - Film Now RO - Film+ HU - FilmBox Extra RO - FilmBox Family RO - FilmBox Plus RO - FilmBox Premium RO - FilmBox RO - FilmBox Stars BG - Filmbox Stars HU - The Fishing and Hunting RO - Focus TV - Food Network - Galaxy4 - H!T Music Channel RO - Happy Channel RO - HBO 2 RO - HBO 3 RO - HBO RO - Home & Garden Television - Hír TV - The History Channel - HUSTLER TV - IDA RO - Inedit TV RO - Investigation Discovery - Izaura TV - JimJam - Kanal D RO - Kiss TV RO - Linkpress TV RO - Love Nature - Magyar Televízió 1 - M2 Petőfi - M4 sport - Magic TV BG - ATV HU - Magyar Sláger TV - Mediaset Italia - Medika TV RO - Mezzo - Mezzo Live HD - Minimax HU - Minimax RO - Moldova TV - Mooz Dance - Mooz HD RO - Mooz Hits RO - Mooz Ro RO - Motorvision HD RO - Motorvision TV - MTV 00s - Club MTV International - MTV Europe HU - MTV Hits International - MTV Live HD - MTV Music UK - MTV 90s International - Museum HD RO - Music Channel 1 RO - Muzsika TV - MyZen TV - National 24 Plus RO - Nasul TV RO - National Geographic People RO - Nat Geo Wild RO - National Geographic RO - National TV RO - The Nautical Channel - Nick Junior PL - Nickelodeon Commercial - Nicktoons PL - TV Paprika RO - Polsat Sport Extra - Prima Sport 1 RO - Prima Sport 2 RO - Prima Sport 3 RO - Prima Sport 4 RO - Prima Sport 5 RO - Prima TV RO - Prime - Brazzers TV (ex. Private Spice) - Private TV - Mozi plusz TV - Acasă - ProSieben - Pro Cinema RO - Acasă Gold - PRO TV Internațional - PRO ARENA RO - Profit RO - ProTV - RAI UNO - RAI TRE - Realitatea Plus RO - Reality Kings - România TV - RTL DE - RTL Gold - RTL Ketto - RTL HU - RTLup - Sat.1 - Sky News - Sorozat+ - Speranta TV - Spíler1 TV - Stingray CMusic - Stingray Classica - Stingray iConcerts - Story4 - Super RTL - Super TV2 - Taraf Tv RO - Timeless Drama Channel - TeenNick - TV1000 Russian Kino RO - Orange Sport 1 - Orange Sport 2 - Orange Sport 3 - Orange Sport 4 - Trace Urban - Travel Channel - Travel Mix RO - Travelxp - Trinitas HD RO - TV2 Comedy - TV2 HU - TV2 Kids - TV2 Séf - TV4 HU - TV5Monde Europe - TV1000 Balkan - TV1000 Global Kino - TV Digi Sport 1 - TV Paprika HU - TV SudEst - TVE Internacional - Televiziunea Româna 1 - Televiziunea Româna 2 - TVR3 RO - TVR Cluj RO - TVR Craiova RO - TVR Iasi RO - TVR Tg-Mures RO - TVR Timisoara RO - Televiziunea Româna International - UTV RO - MTV 80s - Viasat Explore CEE - Viasat History - Viasat Nature CEE - VTV RO - Warner TV RO - Zenebutik - Zu TV - 3SAT - 24 Kitchen - Agro TV - Al Jazeera - Al Jazeera Balkans - ALFA TV - Алсат М - AMC SI - Anixe HD Serie - Das Erste - Arena Esport - Arena Fight - ARTE FR - ARTE DE - Alternativna televizija Banja Luka - AXN - AXN Spin - B92 - BabyTV - Balkan trip - Balkanika TV - BBC Earth - BBC First - BBC World News - Radio Televizija BIH - BK TV - Bloomberg TV - Bloomberg Adria - Radio Televizija BN - BN music - BN 2 HD - БНТ 2 - Boomerang - Canale 5 - Cartoon Network - Cartoon Network DE - Cartoonito CEE - CBS Reality - CCTV 4 Europe - CGTN - Cinemax - Cinemax 2 - CineStar Action&Thriller - CineStar Premiere 1 - CineStar Premiere 2 - CineStar TV1 - CineStar TV2 - CineStar TV Comedy Family - CineStar TV Fantasy - English Club TV - Croatian Music Channel - CNBC Europe - CNN Europe - Comedy Central DE - Nicktoons - Crime & Investigation Channel - Da Vinci Learning - Discovery Animal Planet - Discovery Channel - Discovery Science - TLC - Discovery Turbo Extra - Disney Channel - Disney Junior - DM SAT - DocuBox HD - Dorcel TV - Dorcel XXX - Dr. Fit HD - Sport 1 DE - DuckTV - Duna TV - Duna World - Elta 1 HD - E! Entertainment - Epic Drama (CEE) - Erox HD - Eroxxx HD - Eurochannel - EuroNews - Eurosport - Eurosport 2 - EWTN - Exodus TV - Extreme Sports Channel - Fashion TV - FashionBox HD - Fast&FunBox HD - FightBox HD - SK Fight - FilmBox Arthouse - FilmBox Extra RS - FilmBox Stars RS - The Fishing and Hunting - Focus TV - STAR Crime SI - STAR Life SI - STAR Movies SI - STAR SI - France24 - France 2 - France 24 French - Radio Televizija Federacije BIH - GEA TV - Ginx Esports TV - SK Golf - Golica TV - Gorenjska televizija - Grand Televizija - HappyTV - Hayat Folk - Hayat Music - Hayat Plus - Hayat TV - Hayatovci - HBO - HBO3 - HBO2 - Home & Garden Television - The History Channel - History Channel 2 - HIT TV - HRT 1 - HRT 2 - HRT 3 - HRT 4 - HUSTLER TV - IDJ World - Investigation Discovery - Italia 1 - Otvorena televizija - JimJam - Jugoton TV - K::CN 2 Music - Kabel 1 - Канал 5 - Kanal A, SLO - Kanal D - Kanal Rijeka - KiKA - Klape i Tambure TV - KLASIK - K::CN 1 Kopernikus - KTV Ormož - Living HD - Lov i ribolov - LUXE TV - M2 Petőfi - TV Maribor - Mediaset Italia - Mezzo - Mezzo Live HD - Minimax - Minimax SI - Motorvision TV - МРТ 1 - МРТ 2 - МРТ 3 - MTV Europe - MTV 00s - Club MTV International - MTV DE - MTV Hits International - MTV Live HD - MTV 90s International - MyZen TV - N1 BA - N1 HR - N1 RS - NTV DE - Nat Geo Wild SI - National Geographic - National Geographic Channel HD - Nat Geo Wild - The Nautical Channel - NBA TV - MrežaZG - Net TV - Nat Geo Wild HD - Nick Junior - Nickelodeon - Nickelodeon Commercial - NOVA TV - NTV IC Kakanj - O Kanal - OBN - ORF1 - ORF2 - OTV Valentino - Pickbox TV SI - Pikaboo 2 - RTV PINK - RED tv - TV PINK EXTRA - PINK Family - Pink Fashion - PINK Film - Pink Folk 1 - Pink Folk 2 - Pink Kids - Pink Movies - Pink Music 1 - TV PINK PLUS - Pink Reality - Pink Serije - Pink Show - PINK World - PINK Zabava - Planet 2 - Planet Earth - Planet TV SI - Playboy TV - POP TV - Brazzers TV (ex. Private Spice) - Private TV - ProSieben - Prva Srpska TV - Prva World - Ptujska televizija - RAI UNO - RAI DUE - RAI TRE - RAI 3 Bis - RAI Education - RAI Gulp - RAI News 24 - RAI Sport 1 - RAI Storia - Rai Yoyo - Reality Kings - RedLight HD - Rete 4 - Россиᴙ 24 - RTK 1 - RTL - RTL 2 - RTL Zwei - RTL DE - RTL Kockica - RTL Living - RTRS - RTS 1 - RTS 2 - RTS SVET - RTV International - RTV Unsko-sanskog kantona - RTV Tuzlanskog Kantona - Russia Today - Sat.1 - SciFi - ServusTV - Sexation TV - Televizija skupnih internih programov - Сител - Sixx - SK 4K - SK esports - Sky News - RTV Slovenija 1 - RTV Slovenija 2 - RTV Slovenija 3 - SOS Plus - Sport Klub 4 - Sport Klub 5 - Sport Klub 6 - Sport Klub HD - Sportitalia - Sport Klub 3 - Sport Klub 2 Srbija - Stingray iConcerts - ŠTV3 - Super RTL - K::CN 3 Svet Plus - Televizija Alfa - Televizija AS - Telma - Top TV - Toxic TV - Trace Urban - Travel Channel - Travelxp - TV3 - TV 3 Medias - TV5 Monde - TV1000 Balkan - TV ATM - TV Celje - TV Duga + SAT - TV Galeja - TV Idea - TV Jadran - TV Sarajevo - TV Veseljak - TV Vijesti - Televizija Crne Gore 1 - Televizija Crne Gore 2 - Televizija Crne Gore MNE - DIVA (ex. Universal) - Varaždinska Televizija - Vaš kanal - Vavoom - MTV 80s - Viasat Explore CEE - Viasat History - Viasat Nature CEE - Vikom - VOX - VTV Studio - Welt - Woman HD - XXL - Zagrebačka Televizija - ZDF - Zdrava televizija - 1-2-3.tv - 21 Mix - A2 CNN - A Spor - ABC News Albania - Apollon TV - ART Sport 1 - ART Sport 2 - ART Sport 3 - ART Sport 4 - ART Sport 5 - ART Sport 6 - ArtDoku 1 - ArtDoku 2 - ArtKino 1 - ArtKino 2 - ArtKino 3 - ATV TR - BabyTV - Bang Bang - Beyaz TV - Bubble TV - Cartoon Network - Cartoonito CEE - City TV - Click TV - CNBC Europe - CNN Türk TV - Comedy Central Extra UK - Deluxe Music - DigitAlb T HD - Discovery Animal Planet - Discovery Channel - Discovery Turbo UK - Disney Channel - DMAX DE - Elrodi - Euronews Albania - FAX News - Film Autor - FilmBox Extra RS - FilmBox Stars RS - STAR Channel - STAR Life - HSE24 Extra - HSE24 Trend - Info24 Albania - INTV AL - Junior TV - K-Sport 5 - Kabel 1 - Kabel eins Doku - Kanal 7 - Kanal 10 - Kanal D - Kanali 7 - KiKA - Klan Music - Klan Plus - Kopliku TV - MCN TV - DigitAlb Melody TV - My Music - N24 Doku - NTV DE - National Geographic - National Geographic Channel HD - Nat Geo Wild - Ndihma e Klientit - Nickelodeon - Premium Channel - QVC 2 DE - QVC Deutschland - RAI 4 - RAI 5 - RAI Movie - RAI Premium - Rai Yoyo - RTLup - RTS 2 - RTSH Agro - RTSH Femijë - RTSH Film - RTSH Gjirokastra - RTSH Korça - RTSH Kuvend - RTV 21 Popullore - RTV Besa - RTV Ora - Scan TV - Shenja TV - Show TV - Sixx - SuperSport 7 AL - Syri TV - Syri Vizion - Timeless Drama Channel - Tele 5 DE - TGRT Belgesel - Tring Bizarre - Tring Bunga Bunga - Tring Collection - Tring Desire - Tring Kanal 7 - Tring Novelas - Tring Sport 4 HD - Tring Sport 5 HD - TV 7 - TV Dukagjini - VOX up - Welt - ZDFneo - Zico TV - Zjarr TV - MUSE - News 24 - Ora News - Report TV - RTSH 1 - RTSH 2 - RTSH 3 - RTSH 24 - RTSH Plus - RTSH Shkollë - RTSH Shqip - RTSH Sport - Tring Smile - Stinet - STV Folk - SuperSport 1 AL - SuperSport 2 AL - SuperSport 3 AL - SuperSport 4 AL - SuperSport 5 AL - SuperSport 6 AL - Tip TV - Top Channel - Top News - Tring Action - Tring Comedy - Tring History - Tring Jolly HD - Tring Kids - Tring Life - Tring Planet - Tring Shqip - Tring Sport 3 HD - Tring Sport News - Tring Super - Tring Tring - Tring World - Klan TV HD - Vizion Plus - 3SAT - 4Fun Dance - 4Fun Kids - 4FunTV - 24 Kitchen - 24 ВЕСТИ - 360 TuneBox - Agro TV - Al Jazeera - Al Jazeera Balkans - ALFA TV - AMC - AMC HU - ANIXE plus - Das Erste - Arena Sport 9 RS - Arena Sport 10 RS - Aurora TV - AXN - AXN Spin - B1 TV - B92 - BabyTV - Balkan trip - Balkan TV - Balkanika TV - BBC Earth - BBC News Channel - BBC World News - Bit TV - BK TV - BlicTV - Bloomberg TV - Bloomberg Adria - Radio Televizija BN - BN music - BN 2 HD - Boomerang - Brainz TV - Bravo Music - Cartoon Network - Cartoonito CEE - Cartoonito UK - CBS Reality - CCTV 4 Europe - CGTN - CGTN Documentary - Первый - Cinemania TV - Cinemax - Cinemax 2 - Cinemax 2 HU - Cinemax HU - CineStar Action&Thriller RS - CineStar Premiere 1 - CineStar Premiere 2 - CineStar TV2 - CineStar TV Comedy Family - CineStar TV Fantasy - CineStar TV RS - City TV - Class TV Moda - Croatian Music Channel - CNBC Europe - CNN Europe - Nicktoons - Comedy Central HU - Comedy Central UK - CoolTV - Crime & Investigation Channel - Da Vinci Learning - Dajto - Deluxe Music - Deutsche Welle English - Dexy TV - Digi 24 - Discovery Animal Planet - Discovery Channel HU - Discovery Channel - Discovery Science - TLC - Discovery Turbo Extra - Disney Channel - Disney Channel DE - Disney Channel HU - Disney Junior - DMAX DE - DM SAT - DocuBox HD - Dorcel TV - Dorcel XXX - DOX TV - Dr. Fit HD - Sport 1 DE - DuckTV - Duna TV - Duna World - E! Entertainment - Epic Drama (CEE) - Erox HD - Eroxxx HD - Eska TV Extra - Etno TV RO - Eurochannel - EuroNews - Euronews FR - EuroNews Srbija - Eurosport - Eurosport 2 - Eurosport 1 DE - Extreme Sports Channel - FACE TV - Fashion TV - FashionBox HD - Fast&FunBox HD - Favorit TV RO - FEM3 - FightBox HD - SK Fight - Film4 HU - Film Klub - Film Klub Extra - FilmBox Arthouse - FilmBox Extra RS - Filmbox Extra HU - FilmBox Stars RS - FilmBox Premium RS - Filmbox Premium HU - Filmbox Stars HU - Folklorika SK - Food Network - STAR Channel - STAR Crime - STAR Life - STAR Movies - FOX NEWS - France24 - France 24 French - Radio Televizija Federacije BIH - Gametoon HD - Golica TV - Grand Televizija - Grand nostalgija - HappyTV - Hayat Folk - Hayat Music - Hayat Plus - Hayat TV - HBO - HBO 2 HU - HBO3 - HBO 3 HU - HBO2 - HBO HU - Home & Garden Television - Hír TV - The History Channel - History Channel 2 - HSE - HRT 1 - HRT 2 - HRT 3 - HRT 4 - HUSTLER TV - Hype TV - IDJ World - Info24 Albania - Insajder TV - Insta TV - Investigation Discovery - Izaura TV - JimJam - JOJ Plus - JOJ TV - K1 TV - K::CN 2 Music - K-Sport 5 - Kabel 1 - Kabel eins Doku - Kanal 9 TV - Kanal 25 - KiKA - KitchenTV - KLASIK - K::CN 1 Kopernikus - Kurir TV - Lala TV - LifeTV SK - Lov i ribolov - Magyar Televízió 1 - M2 Petőfi - M4 sport - M4 Sport Plus - m5 - Mediaset Italia - Mezzo - Minimax - Minimax HU - Moj Happy Život - Moja Happy Muzika - Moja Happy Zemlja - Moje Happy Društvo - MTV Europe - MTV 00s - Club MTV International - MTV Hits International - MTV Live HD - MTV 90s International - Museum TV - Muzsika TV - N1 HR - N1 RS - N24 Doku - Nasa TV US - National Geographic - National Geographic Channel HD - National Geographic HU - National Geographic RS - Nat Geo Wild - NBA TV - Nat Geo Wild HD - Nick Junior - Nick Junior PL - Nick Music - Nickelodeon Commercial - Nicktoons PL - NOVA TV - Nova Max - Nova S - Nova Series - Nova Sport Srbija - RTV Novi Pazar - Now 90s - NTV 101 Sanski most - O Kanal - OBN - Ozone Network - Pickbox TV RS - Pikaboo - RTV PINK - RED tv - Vesti - Pink Action - Pink Thriller - Pink Crime & Mystery - Pink BH - Pink Classic - Pink Comedy - Pink Erotic 1 - Pink Erotic 2 - Pink Erotic 3 - Pink Erotic 4 - Pink Erotic 5 - Pink Erotic 6 - Pink Erotic 7 - Pink Erotic 8 - TV PINK EXTRA - PINK Family - Pink Fashion - Pink Fight Network - PINK Film - Pink Folk 1 - Pink Folk 2 - Pink Ha Ha - Pink Hits - Pink Hits 2 - Pink Horror - Pink Kids - Pink Koncert - Pink Kuvar - Pink LOL - Pink M - Pink Movies - Pink Romance - Pink SCI FI & Fantasy - Pink Music 1 - Pink and Roll - Pink Parada - Pink Pedia - TV PINK PLUS - Pink Premium - Pink Reality - Pink Serije - Pink Show - Pink Soap - Pink Style - Pink Super Kids - Pink Timeout - Pink Western - PINK World - Pink World Cinema - PINK Zabava - Planet Earth - Planet TV SI - Playboy TV - Brazzers TV (ex. Private Spice) - Private TV - ProSieben - ProSieben MAXX - Prva FILES - Prva KICK - Prva LIFE - Prva MAX - Prva Plus - Prva Srpska TV - Prva World - QVC Deutschland - RAI UNO - RAI DUE - RAI TRE - RAI Education - RAI News 24 - RAI Storia - Reality Kings - Россиᴙ 24 - RT Documentary - RTL - RTL Croatia World - RTL Gold - RTL Három - RTL Nitro - RTLup - RTRS - RTRS PLUS - RTS 1 - RTS 2 - RTS 3 - RTS Drama - RTS Klasika - RTS Kolo - RTS Muzika - RTS Nauka - RTS Poletarac - RTS SVET - RTS Trezor - RTS Život - RTSH 3 - RTSH 24 - RTSH Plus - RTSH Shkollë - RTV HIT Brčko - RTV International - RTV Pančevo - RTVS Dvojka - RTVS Jednotka - Russia Today - Sat.1 - Sat.1 Gold - SAT TV - SciFi - Sixx - SK1 BiH - SK 4K - Sky News - RTV Slovenija 1 - RTV Slovenija 2 - RTV Slovenija 3 - Sorozat+ - SOS Plus - Spektrum Home HU - Sport Klub 7 - Sport Klub 8 - Sport Klub 9 - Sport Klub 10 - Sremska TV - Superstar 2 - Stars TV PL - Stingray Classica - Stingray iConcerts - Studio B - Super RTL - Super TV2 - SuperSat TV - Superstar TV - K::CN 3 Svet Plus - TA3 SK - Tanjug Tačno - TBN Polska - Timeless Drama Channel - Tele 5 DE - Televizija 5 - Televizija Alfa - TLC DE - TOGGO plus - Top TV - Toxic Folk - Toxic Rap - Toxic TV - Trace Urban - Travel Channel - Travelxp - TV2 Séf - TV4 HU - TV5 Monde - TV5Monde Europe - TV1000 Balkan - TV Doma - TV Duga + SAT - Телевизија Храм - TV K23 - TV Markíza SK - RTV Most - TV Paprika HU - TV Ras - TV Vijesti - Televizija Crne Gore MNE - Televizija Doktor - TVR Cluj RO - TVR Craiova RO - TVR Iasi RO - TVR Tg-Mures RO - TVR Timisoara RO - Televiziunea Româna International - UNA TV - DIVA (ex. Universal) - Vavoom - MTV 80s - Viasat Explore CEE - Viasat History - Viasat Nature CEE - RT Vojvodina 1 - RT Vojvodina 2 - VOX - VOX up - Woman HD - Zagrebačka Televizija - ZDF - ZDFinfo - ZDFneo - 24 Kitchen - 24Kitchen TR - 360 TV - A2TV TR - a Haber - a News - A Para - A Spor - Al Jazeera - Al Jazeera Arabic English - ATV TR - BabyTV TR - BBC First - BBC World News - BBN Türk - beIN Box Office 2 TR - beIN Box Office 3 TR - beIN Box Office 1 TR - beIN GURME - beIN HOME & ENTERTAINMENT - beIN iZ - beIN Movies Premiere 2 - beIN Movies Premiere TR - beIN Movies Stars - beIN Movies Turk - beIN Series 1 TR - beIN Series 2 TR - beIN Series 3 TR - beIN Series 4 TR - beIN Sports 1 TR - beIN Sports 2 TR - beIN Sports 3 TR - beIN Sports 4 TR - beIN Sports Haber - beIN Sports MAX 1 TR - beIN Sports MAX 2 TR - beIN TR - Beyaz TV - Bloomberg TV - Bloomberg HT - Boomerang - Boomerang TR - Cartoon Network TR - Cbeebies - CGTN - CGTN Documentary - CNBC Europe - CNN Europe - CNN Türk TV - Nicktoons - Da Vinci Learning - Da Vinci Learning TR - Deutsche Welle English - Discovery Channel TR - Discovery Channel - Discovery Science - TLC - Disney Junior - Dizi Smart Max - Dizi Smart Premium - DMAX TR - DocuBox HD - Dream Türk - Ekotürk - Epic Drama (CEE) - Euro D - Euro Star - EuroNews - Eurosport 2 - Fashion TV - Fast&FunBox HD - FENERBAHÇE TV - FilmBox TR - FOX Turkey - France24 - France 24 French - FX Turkey - Haber Global - Habertürk - Habitat TV - The History Channel - Insight TV - Kanal 7 - KANAL 24 TR - Kanal D - Kanal D TR - Kral Pop TV - KRT TV - Love Nature - MCM FR - MCM Top - Mezzo - MinikaGO TR - MovieSmart Classic - MovieSmart Türk - MTV 00s - MTV Hits International - MTV Live HD - National Geographic Wild TR - National Geographic Turkey - NBA TV - Nick Junior - Number One Türk - NTV TR - Power TV - Power Türk TV - S Sport - S Sport 2 - Show Türk - Show TV - SinemaTV 2 - SinemaTV 1001 - SinemaTV 1002 - SinemaTV Aile - SinemaTV Aile 2 - SinemaTV Aksiyon - SinemaTV Aksiyon 2 - SinemaTV Komedi - SinemaTV Komedi 2 - SinemaTV Yerli - SinemaTV Yerli 2 - SinemaTV - Spor Smart - Spor Smart 2 - Sports TV - Star TV TR - TAY TV - TELE 1 - teve2 - TGRT Belgesel - TGRT EU - TGRT HABER - Tivibu Spor - Tivibu Spor 2 - Tivibu Spor 3 - Tivibu Spor 4 - Tivibu Spor 5 - TLC TR - Trace Urban - TRT 1 - TRT 2 - TRT Spor - TRT 4K - TRT Kurdî - TRT Arapça - TRT Avaz - TRT Belgesel - TRT Çocuk - TRT Diyanet - TRT EBA TV İlkokul - TRT EBA TV Lise - TRT EBA TV Ortaokul - TRT Haber - TRT Müzik - TRT Spor Yıldız - TRT Turk - TRT World - TV5 - TV100 TR - TV 2 TR - TV 8 TR - TV 8.5 - TV Net - Uçankuş TV - Ülke TV - Viasat Explore CEE - Viasat History - Viasat Nature CEE - Yaban TV - + + + Tring 3 Plus + 21 Mix + 360 TuneBox + ABC News Albania + Agro TV + Al Jazeera + Al Jazeera Balkans + Алсат М + AMC + Apollon TV + Arena Sport 5 RS + Arena Sport 6 RS + ARTE DE + ArtKino 1 + ArtKino 2 + ArtKino 3 + ATV Avrupa + ATV KS + ATV TR + AXN + AXN Spin + B92 + BabyTV + Balkanika TV + Bang Bang + BBC Earth + BBC World News + Beyaz TV + Radio Televizija BN + BN music + Boomerang + Bubble TV + Cartoon Network + Cartoonito CEE + CBS Reality + Cinemax + Cinemax 2 + CineStar Action&Thriller RS + CineStar TV Comedy Family + CineStar TV Fantasy + CineStar TV RS + Click TV + English Club TV + CNN Europe + Comedy Central DE + Crime & Investigation Channel + Cufo TV + Da Vinci Learning + Deutsche Welle English + Discovery Animal Planet + Discovery Channel + TLC + Disney Channel + DM SAT + DocuBox HD + Dorcel TV + Duck TV CZ + DuckTV + Elrodi + E! Entertainment + Epic Drama (CEE) + Eroxxx HD + Eurochannel + EuroNews + Euronews Albania + Explorer Histori + Explorer Natyra + Explorer Shkence + Extreme Sports Channel + FashionBox HD + Fast&FunBox HD + FAX News + FightBox HD + Film Aksion Digitalb + Film Drame Digitralb + Film Klub + Film Klub Extra + Film Thriller Digitalb + FilmBox Arthouse + FilmBox Extra RS + FilmBox Stars RS + FilmBox Premium RS + STAR Channel + STAR Crime + STAR Life + FOX Turkey + France24 + France 2 + Radio Televizija Federacije BIH + Gametoon HD + Habertürk + HappyTV + Hayat TV + HBO + HBO3 + HBO2 + The History Channel + History Channel 2 + HRT 1 + HRT 3 + HUSTLER TV + Investigation Discovery + JimJam + Tring Jolly HD + Junior TV + Kujtesa Sport 1 + Kujtesa Sport 2 + Kujtesa Sport 3 + Kujtesa Sport 4 + Kanal 6 + Kanal 7 + Kanal 10 + Kanal D + Kanali 7 + KitchenTV + Klan Kosova + Klan Plus + Kohavision + Kopliku TV + Living HD + Minimax + Motorvision HD RO + MTV Europe + MTV 00s + MTV Hits International + MTV Live HD + MTV 90s International + MUSE + My Music + NTV DE + National Geographic + Nat Geo Wild + NBA TV + News 24 + Nick Junior + Nickelodeon + Ora News + Pikaboo + RTV PINK + RED tv + Vesti + Pink Action + Pink Thriller + Pink Crime & Mystery + Pink Comedy + Pink Erotic 1 + Pink Erotic 2 + PINK Family + PINK Film + Pink Hits + Pink Kids + Pink LOL + Pink Romance + Pink SCI FI & Fantasy + Pink Music 1 + Pink and Roll + Pink Premium + Pink Reality + Pink Serije + Pink Super Kids + Pink Western + Pink World Cinema + Power TV + Power Türk TV + Brazzers TV (ex. Private Spice) + Private TV + ProSieben + ProSieben MAXX + Prva FILES + Prva KICK + Prva LIFE + Prva MAX + Prva Srpska TV + Prva World + RAI DUE + RAI TRE + RAI News 24 + Report TV + RT Documentary + RTK 1 + RTK 2 + RTK 4 + RTL + RTL 2 + RTL Zwei + RTL DE + RTRS + RTRS PLUS + RTS 1 + RTS 2 + RTS 3 + RTS Drama + RTS Kolo + RTS Muzika + RTS Poletarac + RTS SVET + RTS Trezor + RTS Život + RTV21 + RTV 21 Popullore + RTV Besa + Russia Today + Sat.1 + Sat.1 Gold + SciFi + Shenja TV + Show TV + Sky News + Tring Smile + SOS Plus + Tring Sport News + Star TV TR + Studio B + Super RTL + Superstar TV + Syri TV + Syri Vizion + Timeless Drama Channel + Tip TV + Top Channel + Travel Channel + Tring Bizarre + Tring Bunga Bunga + Tring Collection + Tring Comedy + Tring Desire + Tring History + Tring Kids + Tring Life + Tring Action + Tring Novelas + Tring Planet + Tring Shqip + Tring Super + Tring Tring + Tring World + TRT 1 + TRT 2 + TRT Spor + TRT Belgesel + TRT Çocuk + TRT Haber + TRT Müzik + TRT Turk + TRT World + TV5 Monde + TV1000 Balkan + TV 7 + TV 8 TR + Arena Sport 1 RS + Arena Sport 2 RS + Arena Sport 3 RS + Arena Sport 4 RS + TV Dukagjini + Телевизија Храм + Klan TV HD + RTV Most + DIVA (ex. Universal) + Vavoom + MTV 80s + Viasat Explore CEE + Viasat History + Viasat Nature CEE + Vizion Plus + RT Vojvodina 1 + RT Vojvodina 2 + VOX + Zico TV + Zjarr TV + 24 Kitchen + 360 TuneBox + Al Jazeera + Al Jazeera Balkans + AMC + Das Erste + ARTE FR + Auto Motor und Sport + BabyTV + Balkanika TV + BBC World News + BG-DNES + BHTV + Bloomberg TV + BN music + Body in Balance + Boomerang + BSTV BG + Cartoon Network + Cartoonito CEE + CBS Reality + CGTN + Первый + Cinemania BG + Cinemax 2 BG + Cinemax BG + Cinethronix RO + CNBC Europe + CNN Europe + Comedy Central BG + Nicktoons + Comedy Central Extra BG + Crime & Investigation Channel + Da Vinci Learning + Deluxe Music + Deutsche Welle English + Diema Sport 3 BG + Discovery Animal Planet + Discovery Channel + Discovery Science + TLC + Disney Junior BG + Stingray Djazz + DM SAT + DocuBox HD + Dorcel TV + Dorcel XXX + DSTV + DuckTV + Epic Drama (CEE) + Erox HD + Eroxxx HD + Eurochannel + EuroNews + Euronews FR + Eurosport 2 + Eurosport 1 BG + Extreme Sports Channel + F+ + Fashion TV + FashionBox HD + Fast&FunBox HD + FightBox HD + FilmBox Arthouse + FilmBox BG + FilmBox Extra BG + The Fishing and Hunting + The Fishing and Hunting RO + Fix & Foxi + France24 + France 2 + France 24 French + FunBox UHD + Gametoon HD + HBO 2 BG + HBO 3 BG + Home & Garden Television + The History Channel + History Channel 2 + HUSTLER TV + Investigation Discovery + Investigation Discovery BG + JimJam BG + K::CN 2 Music + КХЛ + KiKA + Love Nature + LUXE TV + MCM Top + Mezzo + Mezzo Live HD + Motorvision TV + MTV Europe + MTV 00s + Club MTV International + MTV Hits International + MTV Live HD + MTV 90s International + MyZen TV + Nasa TV US + Nick Junior + Nick Junior BG + Nickelodeon + Nickelodeon Commercial + Nickelodeon UK + Pickbox TV BG + Planeta TV BG + Playboy TV + Plovdivska Pravoslavna TV + Brazzers TV (ex. Private Spice) + ProSieben MAXX + RAI UNO + RAI News 24 + Reality Kings + RedLight HD + Ring TV + Россиᴙ 24 + RT Documentary + RTL Zwei + RTL DE + Russia Today + Sat.1 Gold + Sky News + Stingray iConcerts + Super RTL + SuperToons + Travel Channel + TRT Belgesel + TV5 Monde + TV5Monde Europe + TV1000 Balkan + TVE Internacional + Телевизия Стара Загора BG + MTV 80s + Viasat Explore CEE + Viasat History + Viasat Nature CEE + VOX + ZDF + 24Kitchen BG + AGRO TV BG + Alfa BG + AXN Black BG + AXN BG + AXN White BG + B1B Action TV BG + Barely Legal TV + Bloomberg TV BG + БНТ 1 + БНТ 2 + БНТ 3 + БНТ 4 + BOX TV BG + bTV BG + bTV Action + bTV Cinema + bTV Comedy + bTV Lady + Bulgaria on Air + City TV BG + Diema + Diema Family + Diema Sport 2 + Diema Sport + Disney Channel BG + EKids + Евроком + Фен Фолк ТВ + ФЕН ТВ + FilmBox Stars BG + HBO BG + Kino Nova + Magic TV BG + MAX Sport 1 BG + MAX Sport 2 BG + MAX Sport 3 BG + Max Sport 4 BG + Movie Star + National Geographic BG + Nat Geo Wild BG + Nova TV BG + Nova News + Nova Sport BG + Planeta Folk BG + Skat TV + Sport+ HD + STAR BG + STAR Crime BG + STAR Life BG + Travel TV BG + Travelxp + TV1 BG + TV Evropa BG + TV+ BG + Родина + Vivacom Arena + VTK BG + Wness TV + 24 Kitchen + 24 ВЕСТИ + 360 TuneBox + Adria TV + Adult Channel + Al Jazeera + Al Jazeera Arabic English + Al Jazeera Balkans + ALFA TV + AMC + Anixe HD Serie + ANIXE plus + Das Erste + Arena Esport + Arena Fight + Arena Sport 1 Premium + Arena Sport 1 Premium BiH + Arena Sport 1x2 + Arena Sport 2 BiH + Arena Sport 2 Premium + Arena Sport 2 Premium BiH + Arena Sport 3 BiH + Arena Sport 3 Premium + Arena Sport 3 Premium BiH + Arena Sport 4 BiH + Arena Sport 5 BiH + Arena Sport 6 RS + Arena Sport 6 BiH + Alternativna televizija Banja Luka + B92 + BabyTV + Balkan TV + Balkanika TV + BBC World News + BDC Televizija + Behar TV Sarajevo + Radio Televizija BIH + Bir TV + BlicTV + Bloomberg TV + Bloomberg Adria + Radio Televizija BN + BN music + Boomerang + Bravo Music + Cartoon Network + Cartoonito CEE + CBS Reality + CCTV 4 Europe + CGTN + Cinema TV + Cinemax + Cinemax 2 + City TV + English Club TV + Croatian Music Channel + CNBC Europe + CNN Europe + Nicktoons + Crime & Investigation Channel + Deutsche Welle English + Dexy TV + Digi 24 + Discovery Animal Planet + Discovery Channel + Discovery Science + TLC + Discovery Turbo Extra + Disney Channel + Disney Channel DE + DMAX DE + DM SAT + DocuBox HD + Dorcel TV + Dorcel XXX + DOX TV + Elta 1 HD + E! Entertainment + Erox HD + Eroxxx HD + Eska TV Extra + Etno TV RO + Eurochannel + EuroNews + Euronews FR + EuroNews Srbija + Eurosport + Eurosport 1 DE + Extreme Sports Channel + Fashion TV + FashionBox HD + Fast&FunBox HD + Favorit TV RO + FightBox HD + SK Fight + FilmBox Arthouse + FilmBox Extra RS + FilmBox Stars RS + FilmBox Premium RS + Food Network + STAR Channel + STAR Crime + STAR Life + STAR Movies + FOX NEWS + France24 + France 24 French + Radio Televizija Federacije BIH + GameHub HR + Gametoon HD + SK Golf + GP1 + Grand nostalgija + HappyTV + Hayat Folk + Hayat Plus + Hayat TV + HBO + HBO3 + HBO2 + Herceg TV + Historija TV + The History Channel + HIT TV + HSE + HRT 1 + HRT 3 + HUSTLER TV + Imperia TV + Insajder TV + Insta TV + Investigation Discovery + Izvorna TV + Otvorena televizija + JimJam + K1 TV + Kabel 1 + Kanal1 + Kanal 6 + Kazbuka + KiKA + Klape i Tambure TV + M1 Family + Maria Vision + Motorvision TV + MTV Europe + MTV 00s + Club MTV International + MTV Hits International + MTV Igman + MTV Live HD + MTV 90s International + MY TV + N1 RS + N24 Doku + Nasa TV US + National Geographic + National Geographic Channel HD + National Geographic RS + Nat Geo Wild + NBA TV + Neon TV + Nat Geo Wild HD + Nick Junior + Nick Music + Nickelodeon Commercial + NOVA TV + Nova Max + Nova Series + NTV 101 Sanski most + NTV IC Kakanj + O Kanal Music + O Kanal Plus + OBN + One + OSM TV + OTV Valentino + Pickbox TV RS + Pikaboo + RTV PINK + RED tv + Vesti + Pink Erotic 1 + Pink Erotic 2 + Pink Erotic 3 + Pink Erotic 4 + Pink Erotic 5 + Pink Erotic 6 + Pink Erotic 7 + Pink Erotic 8 + TV PINK EXTRA + PINK Film + Pink Folk 1 + Pink Hits 2 + Pink Kids + Pink Music 1 + Pink Parada + TV PINK PLUS + Pink Reality + Pink Timeout + Playboy TV + Poljoprivredna TV + Posavska Televizija + Premier League TV + Private TV + ProSieben + ProSieben MAXX + ProTV Tomislavgrad + Prva Srpska TV + QVC Deutschland + RAI UNO + RAI DUE + RAI TRE + RAI Education + RAI News 24 + Reality Kings + RT Documentary + RTL 2 + RTL Zwei + RTL DE + RTL Kockica + RTL Nitro + RTRS + RTS 1 + RTS Klasika + RTS Nauka + RTS Poletarac + RTS Život + RTSH 3 + RTSH 24 + RTSH Plus + RTSH Shkollë + RTV7 Tuzla + RTV BPK Goražde + RTV Herceg-Bosne + RTV HIT Brčko + RTV Lukavac + RTV Slon Tuzla + RTV Unsko-sanskog kantona + RTV Vogošća + RTV Zenica + RTV Tuzlanskog Kantona + Russia Today + Sat.1 + Sat.1 Gold + SciFi + Sevdah TV + SK1 BiH + SK esports + Sky News + Slobomir + Smart TV Tešanj + SOS Plus + Sport Klub 1 Srbija + Sport Klub 4 + Sport Klub 5 + Sport Klub 6 + Sport Klub 7 + Sport Klub 8 + Sport Klub 9 + Sport Klub 10 + Sport Klub HD + Sport Klub 1 Hrvatska + Sport Klub 3 + Sport Klub 2 Srbija + Superstar 2 + Super RTL + Supermedia Televizija + Tanjug Tačno + Tatabrada + TBN Polska + Timeless Drama Channel + Tele 5 DE + Televizija 5 + TLC DE + TNT Kids + Toxic Folk + Toxic Rap + Toxic TV + Travel Channel + Tropik TV + TRT 1 + TRT World + TV1 Mreža + TV Arena Bijeljina + Arena Sport 1 RS + Arena Sport 1 HR + Arena Sport 4 RS + Televizija Dalmacija + TV Duga + SAT + TV Istočno Sarajevo + TV Ras + TV Sarajevo + TV Vijesti + RTV Visoko + Televizija Crne Gore MNE + Televizija Doktor + TVR Cluj RO + TVR Craiova RO + TVR Iasi RO + TVR Tg-Mures RO + TVR Timisoara RO + UNA TV BiH + DIVA (ex. Universal) + Valentino Etno + Valentino Music HD + Vavoom + MTV 80s + Vikom + VOX + VOX up + Welt + ZDF + ZDFinfo + ZDFneo + 1-2-3.tv + 3SAT + 13th Street DE + A Spor + Al Jazeera + Animal Planet DE + Anixe HD Serie + ANIXE plus + Das Erste + ARD-alpha + ARTE DE + AstroTV + Alternativna televizija Banja Luka + ATV1 + ATV2 + Auto Motor und Sport + B92 + Bayerischen Fernsehen Nord + BBC World News + beIN Movies Premiere TR + Bergblick + BFM TV + Radio Televizija BIH + Bibel TV + Das Bild TV + Bloomberg TV + Blue Hustler + Radio Televizija BN + BN music + BonGusto + Boomerang DE + BR Fernsehen Süd + Cartoon Network DE + CCTV 4 Europe + CGTN + CGTN Documentary + Croatian Music Channel + CNBC Europe + CNews + CNN Europe + Comedy Central DE + Nicktoons + Crime & Investigation Channel + Crime & Investigation DE + Deluxe Music + Deutsche Welle English + Deutsches Musik Fernsehen + Deutsche Welle Deutsch + Discovery Channel DE + Disney Channel DE + DMAX DE + DM SAT + DocuBox HD + Dorcel TV + Dorcel XXX + DuckTV + Elta 1 HD + E! Entertainment + Erox HD + Euro Star + EuroNews + Eurosport + Eurosport 2 DE + Eurosport 1 DE + Extreme Sports Channel + Fashion TV + Fast&FunBox HD + Fight 24 + Fix & Foxi + Folx TV + France24 + France 24 French + FS1 AT + Radio Televizija Federacije BIH + Geo Television + Ginx Esports TV + Gute Laune TV + Habertürk + HappyTV + Hayat TV + Heimatkanal + HGTV DE + History Channel DE + HR Fernsehen + HSE + HSE24 Extra + HSE24 Trend + HRT 1 + HUSTLER TV + K-TV Katholisches Fernsehen + Kabel 1 + Kabel eins Österreich + Kabel Eins Classics + Kabel eins Doku + Kanal 7 + Kanal D TR + Kerrang! + KiKA + Kinowelt + KIT-TV + krone.tv + Love Nature + Marco Polo TV + MDR Fernsehen + MDR Sachsen-Anhalt + MDR Sachsen + MDR Thüringen + Melodie TV + Mezzo + Mezzo Live HD + Motorvision TV + MTV 00s + Club MTV International + MTV DE + MTV Hits International + MTV Live HD + MTV 90s International + N24 Doku + NTV DE + NatGeo Wild DE + National Geographic DE + The Nautical Channel + NDR Hamburg + NDR Mecklenburg-Vorpommern + NDR Niedersachsen + NDR Schleswig-Holstein + Nick Junior + Nick Music + Nick DE + Niederbayern TV Deggendorf-Straubing + NOVA TV + oe24.TV + One + ORF1 + ORF2 + ORF3 + ORF Sport Plus + OTV Valentino + Phoenix + TV PINK EXTRA + PINK Film + Pink Folk 1 + Pink Kids + Pink Music 1 + TV PINK PLUS + Pink Reality + Playboy TV + ProSieben + PRO 7 Österreich + ProSieben Fun + ProSieben MAXX + Prva Srpska TV + Puls 4 + QVC 2 DE + QVC Beauty + QVC Deutschland + QVC STYLE DE + RAI UNO + RAI DUE + RAI TRE + RAI Education + RAI News 24 + RAI Storia + RBB Fernsehen Brandenburg + RBB Fernsehen Berlin + RiC DE + Romance TV + RTL 2 + RTL Zwei + RTL Crime DE + RTL Croatia World + RTL DE + RTL Kockica + RTL Living DE + RTL Nitro + RTL Passion DE + RTLup + RTRS + RTS 1 + Russia Today + Sat.1 Emotions + Sat.1 + Sat.1 Österreich + Sat.1 Gold + Kurier TV + Schlager Deluxe + ServusTV + Show Türk + Sixx + Sixx AT + Sky 1 DE + Sky Atlantic DE + Sky Cinema Action DE + Sky Cinema Classics DE + Sky Cinema Family DE + Sky Krimi DE + Sky Cinema Thriller + Sky Sport 1 DE + Sky Sport 3 DE + Sky Sport 4 DE + Sky Sport 5 DE + Sky Sport 6 DE + Sky Sport 7 DE + Sky Sport 8 DE + Sky Sport 9 DE + Sky Sport 10 DE + Sky Bundesliga 1 + Sky Bundesliga 2 + Sky Bundesliga 3 + Sky Bundesliga 4 + Sky Bundesliga 5 + Sky Bundesliga 6 + Sky Bundesliga 7 + Sky Sport News DE + Sky Sports News + Sky News + sonnenklar.TV + Sony AXN + Sony Channel DE + Spiegel Geschichte + Curiosity Channel + Sport 1 plus DE + Šport TV 1 + Sportdigital Fußball + SR Fernsehen + SRF Info + SRF Zwei + Stingray Classica + Super RTL + SWR + SWR Baden-Württemberg + Syfy HD DE + tagesschau24 + Tele 5 DE + TLC DE + Warner TV Comedy DE + Warner TV Film DE + Warner TV Serie DE + TOGGO plus + TRT 1 + TRT Spor + TRT Belgesel + TRT Çocuk + TRT Müzik + TV 8 TR + Universal TV DE + MTV 80s + Vivid TV + VOX + W24 + WDR Fernsehen + WDR Fernsehen Köln + Welt + Welt der Wunder + ZDF + ZDFinfo + ZDFneo + 2M Monde + 3 Plus CH + 3SAT + 4 Plus + 4 Seven + 5 Plus + 5 Star + 6 plus + 6ter + 13th Street DE + 20 Mediaset + Action + Al Jazeera + Al Jazeera Arabic Arabic + Anixe HD Serie + ANIXE plus + Antena 3 + Das Erste + ARD-alpha + ARTE FR + ARTE DE + auftanken.TV + B1 TV + BBC1 + BBC2 + BBC3 + BBC4 + BBC News Channel + BBC Parliament + BBC World News + BFM Business + BFM TV + Bibel TV + Das Bild TV + Bloomberg TV + Bloomberg Quicktake + BN 2 HD + Boing + Boing Plus + Boomerang + Boomerang DE + BR Fernsehen Süd + C8 FR (ex. D8) + Canal 24H + Canal+ Kids FR + Canal J + Canal+ Cinéma(s) FR + Canal+ France + Canal Plus Sport FR + Canal+ Series FR + Canale 5 + CARAC4 + Cartoon Network DE + Cartoonito Italia + CBBC + Cbeebies + CCTV 4 Europe + CGTN + Challenge TV + Channel 4 + Channel 5 + Chérie 25 + cielo + Cine34 + Polar+ + Cine+ Premier FR + Children's ITV + Class TV Moda + English Club TV + Clubland TV + Croatian Music Channel + CNBC Europe + CNews + CNN Europe + CNN Türk TV + Comedy Central DE + Crime District + Crime & Investigation Channel + CStar FR + Dave + Deluxe Music + Deutsche Welle English + Deutsches Musik Fernsehen + Deutsche Welle Deutsch + Deutsche Welle Espanol + Discovery Channel DE + Discovery Channel IT + Disney Channel DE + DMAX IT + DMAX DE + DM SAT + Drama UK + Dream Türk + Sport 1 DE + Duna TV + Duna World + E4 + E! Entertainment + Euro D + Euro Star + EuroNews + Euronews FR + Eurosport + Eurosport 2 DE + Eurosport 2 FR + Eurosport 2 IT + Eurosport 1 DE + Eurosport FR + Eurosport IT + Fashion TV + Film4 + Fix & Foxi + Focus TV + Folx TV + Food Network Italia + Food Network UK + FOX NEWS + France24 + France 2 + France 3 + France 4 + France 5 + France 24 French + France Info + Frisbee + FunBox UHD + Giallo TV + Ginx Esports TV + Golf Channel Češka + Golf plus + Gulli + Habertürk + Halk TV + Hayat Folk + Hayat Music + Hayat Plus + Das Health TV + HGTV DE + HGTV IT + The History Channel + HR Fernsehen + HSE + HSE24 Extra + HSE24 Trend + HRT 1 + i24News FR + Iris + Italia 1 + Italia 2 + ITV1 + ITV2 + ITV3 + ITV4 + ITV Be + K2 + K-TV Katholisches Fernsehen + Kabel 1 + Kabel eins Doku + Kanal 9 TV + Kerrang! + KiKA + Kiss UK + Klan Kosova + Kohavision + L'Equipe + La Cinque + La7 + La7d + La Télé + La Chaîne Info + Magyar Televízió 1 + M2 Petőfi + M4 sport + m5 + M6 + Mangas + MCM FR + MDR Fernsehen + Mediaset Extra + Mediaset Italia + Mezzo + Mezzo Live HD + More4 + More Than Sports TV + Motorvision TV + Motorvision TV France + MTV DE + 5Select + N24 Doku + NTV DE + Nasa TV US + National Geographic DE + The Nautical Channel + NDR Hamburg + Nick DE + NOVE + Now 90s + NRJ12 + RMC Story + OBN + One + ORF1 + ORF2 + ORF3 + PBS America + Phoenix + Pick TV + TV PINK EXTRA + PINK Film + Pink Folk 1 + Pink Kids + Pink Koncert + Pink Music 1 + TV PINK PLUS + Pink Reality + Power Türk TV + ProSieben + ProSieben MAXX + Puls 8 + Radio Ticino Channel HD + RadioBremen + RAI UNO + RAI DUE + RAI TRE + RAI 4 + RAI 5 + RAI Education + RAI Gulp + RAI Movie + RAI News 24 + RAI Premium + RAI Sport 1 + RAI Storia + Rai Yoyo + RBB Fernsehen Berlin + real time + Rete 4 + RiC DE + RMC Découverte + Rocket Beans TV + Romance TV + CARAC1 + RSI La 1 + RSI La 2 + RTK 1 + RTL Zwei + RTL Crime DE + RTL DE + RTL Living DE + RTL Nitro + RTL Passion DE + RTLup + RTP3 + RTP Internacional + RTRS + RTS 2 Suisse + RTS SVET + RTS Un + Russia Today + S1 CH + S4C + Sat.1 + Sat.1 Gold + ServusTV + Show Türk + SIC + Sixx + Sky Atlantic + Sky Krimi DE + Sky Sport 1 DE + Sky Sports News + Sky TG24 HD + Sky News + SonLife + Spiegel Geschichte + Sport 1 plus DE + Sportitalia + SR Fernsehen + SRF 1 + SRF Info + SRF Zwei + Stingray Classica + Stingray iConcerts + Super! + Super RTL + Supertennis HD + K::CN 3 Svet Plus + Swiss1 TV + SWR + Syfy HD DE + tagesschau24 + TELE 1 + Tele 5 DE + TeleBärn + Tele Zürich + Télévision française 1 + TFX + TGCOM24 + TGRT HABER + TiJi + TLC DE + TMC + Warner TV Comedy DE + Warner TV Film DE + Warner TV Serie DE + TOGGO plus + Top Crime + Trace Urban + TRT Spor + TRT Kurdî + TRT Belgesel + TRT Çocuk + TRT Müzik + TRT Turk + TV5 Monde + TV5Monde Europe + TV8 IT + TV24 + TV25 + TV 8 TR + TV 2000 + TV Dukagjini + TVE Internacional + Televisión de Galicia + TV Internacional + TVM3 + Twenty Seven + DIVA (ex. Universal) + VH1 IT + Viaplay Xtra + VOX + VOX up + W9 + WDR Fernsehen + Welt + Welt der Wunder + Wetter + Yesterday + Zagrebačka Televizija + ZDF + ZDFinfo + ZDFneo + 1-2-3.tv + 3SAT + 13th Street DE + Al Jazeera + Al Jazeera Arabic English + Al Jazeera Balkans + Animal Planet DE + Anixe HD Serie + ANIXE plus + Das Erste + ARD-alpha + ARTE DE + AstroTV + Alternativna televizija Banja Luka + auftanken.TV + Baden TV + Balkanika TV + Bayerischen Fernsehen Nord + BBC World News + beIN iZ + beIN Movies Premiere TR + Bergblick + Bibel TV + Das Bild TV + Bloomberg TV + BonGusto + Boomerang DE + BR Fernsehen Süd + Canal 24H + Cartoon Network DE + CGTN + CGTN Documentary + Croatian Music Channel + CNBC Europe + CNN Europe + Comedy Central DE + Nicktoons + Crime & Investigation DE + DAZN 1 DE + DAZN 2 DE + Deluxe Music + Deutsche Welle English + Deutsches Musik Fernsehen + Deutsche Welle Deutsch + Discovery Channel DE + Disney Channel DE + DMAX DE + DM SAT + Sport 1 DE + Edge Sport + eSports 1 + Euro Star + EuroNews + Eurosport 2 DE + Eurosport 1 DE + EWTN + Extreme Sports Channel + Fashion TV + Fast&FunBox HD + Fight 24 + Fix & Foxi + Folx TV + France24 + France 2 + France 3 + France 4 + France 5 + France 24 French + Geo Television + Ginx Esports TV + Goldstar + Gute Laune TV + Habertürk + Halk TV + Hamburg 1 + Das Health TV + Heimatkanal + Home & Garden Television + HGTV DE + History Channel DE + HR Fernsehen + HSE + HSE24 Extra + HSE24 Trend + HRT 1 + Insight TV + Jukebox + K-TV Katholisches Fernsehen + Kabel 1 + Kabel Eins Classics + Kabel eins Doku + Kanal 7 + KiKA + Kinowelt + Klan Kosova + Kohavision + Marco Polo TV + MDR Fernsehen + MDR Sachsen-Anhalt + MDR Sachsen + MDR Thüringen + Mediaset Italia + Melodie TV + More Than Sports TV + Motorvision TV + MTV DE + MTV Live HD + münchen.tv + N24 Doku + NTV DE + NatGeo Wild DE + National Geographic DE + NDR Hamburg + NDR Mecklenburg-Vorpommern + NDR Niedersachsen + NDR Schleswig-Holstein + Nick Junior + Nick DE + Niederbayern TV Deggendorf-Straubing + One + ORF3 + ORF Sport Plus + Phoenix + TV PINK EXTRA + PINK Film + Pink Folk 1 + Pink Music 1 + TV PINK PLUS + Power Türk TV + ProSieben + ProSieben MAXX + QVC 2 DE + QVC Deutschland + RAI UNO + RAI DUE + RAI TRE + RAI News 24 + RAI Storia + RBB Fernsehen Brandenburg + RBB Fernsehen Berlin + RiC DE + Rhein Neckar Fernsehen + Rocket Beans TV + Romance TV + RTK 1 + RTL Zwei + RTL Crime DE + RTL DE + RTL Living DE + RTL Nitro + RTL Passion DE + RTLup + RTS SVET + Russia Today + Sat.1 Emotions + Sat.1 + Sat.1 Gold + Schlager Deluxe + ServusTV Deutschland + Show Türk + Silverline Movie Channel + Sixx + Sky 1 DE + Sky Atlantic DE + Sky Cinema Action DE + Sky Cinema Best Of DE + Sky Cinema Classics DE + Sky Cinema Comedy DE + Sky Cinema Family DE + Sky Krimi DE + Sky Cinema Premieren + Sky Sport 1 DE + Sky Sport 3 DE + Sky Sport 4 DE + Sky Sport 5 DE + Sky Sport 6 DE + Sky Sport 7 DE + Sky Sport 8 DE + Sky Sport 9 DE + Sky Sport 10 DE + Sky Bundesliga 1 + Sky Bundesliga 2 + Sky Bundesliga 3 + Sky Bundesliga 4 + Sky Bundesliga 5 + Sky Bundesliga 6 + Sky Bundesliga 7 + Sky Sport Mix DE + Sky Sport News DE + Sky Sport Premier League DE + Sky News + sonnenklar.TV + Sony AXN + Sony Channel DE + Spiegel Geschichte + Curiosity Channel + Sport 1 plus DE + Sportdigital Fußball + SR Fernsehen + Stingray Classica + Super RTL + SWR + SWR1 Baden-Württemberg + SWR Baden-Württemberg + Syfy HD DE + tagesschau24 + Tele 5 DE + TGRT EU + TLC DE + Warner TV Comedy DE + Warner TV Film DE + Warner TV Serie DE + TOGGO plus + TRT Turk + TV5 Monde + TV5Monde Europe + TV8 IT + TV Now DE + TVE Internacional + TVS + MTV 80s + VOX + VOX up + WDR Fernsehen + WDR Fernsehen Köln + Welt + Welt der Wunder + Wetter + Wir 24 + ZDF + ZDFinfo + ZDFneo + 4Music + 4 Seven + 5ACTION + 5 Star + 5 USA + Al Jazeera Arabic English + Alibi + AMC UK + Animal Planet UK + At The Races + BabyTV + BBC1 + BBC1 Northern Ireland + BBC One Scotland + BBC2 + BBC3 + BBC4 + BBC Alba + BBC Earth + BBC News Channel + BBC 1 Wales + BBC Parliament + BBC 2 Northern Ireland + BBC Two Wales + BBC World News + Boomerang + Boomerang UK + TNT Sports 1 + TNT Sports 2 + TNT Sports 4 + TNT Sports Europe + TNT Sports Ultimate + Cartoon Network + Cartoon Network UK + Cartoonito UK + CBBC + Cbeebies + CBS Drama UK + CBS Reality UK + Challenge TV + Channel 4 + Channel 4 +1 + Channel 5 + Channel S + Capital XTRA + Children's ITV + English Club TV + Clubland TV + Comedy Central Extra UK + Comedy Central UK + Create and Craft + Crime and Investigation UK + Dave + Deutsche Welle English + Discovery Channel UK + Discovery History UK + Discovery Science UK + Discovery Turbo UK + DMAX UK + Drama UK + E4 + E4 Extra + Eden UK + Edge Sport + BT Sport ESPN + EuroNews + Eurosport 2 UK + Eurosport 1 EMEA + Eurosport.com + Eurosport UK + Extreme Sports Channel + Film4 + Food Network UK + Gems TV + Ginx Esports TV + Great! romance + History 2 UK + History Channel UK + Home & Garden Television UK + Ideal Home Shopping + Inspiration TV + Investigation Discovery UK + ITV1 + ITV2 + ITV2+1 + ITV3 + ITV4 + ITV Be + Jewellery Channel + JML Direct + Kerrang! + Ketchup TV + Kiss UK + Pop Max + London Live + Love Nature + Magic + Manchester TV + More4 + MotorTrend + Movies 24 + MTV 80s UK + MTV 90s UK + MTV Hits UK + MTV Live HD + MTV Music UK + MTV UK + 5Select + Nat Geo Wild UK + National Geographic Channel UK + Nick Jr. Too UK + Nick Junior UK + Nick Music + Nickelodeon UK + Nicktoons UK + Now 70s + Now 80s + Now 90s + PBS America + Pick TV + Pop UK + Premier Sports 1 + Premier Sports 2 + Quest TV + Quest Red + QVC Beauty + QVC Style + Really UKTV + Revelation TV + S4C + Sky Arts + Sky Atlantic + Sky Cinema Drama + Sky Cinema Greats + Sky Cinema Hits + Sky Cinema Select + Sky Cinema SF Horror + Sky Crime + Sky Documentaries + Sky Kids + Sky Witness + Sky Max + Sky Cinema Action + Sky Cinema Comedy + Sky Cinema Thriller + Sky Family + Sky Cinema Premiere + Sky Nature UK + Sky Replay + Sky Showcase + Sky Sports Main Event + Sky Sports Cricket + Sky Sports Action + Sky Sports Golf + Sky Sports Premier League + Sky Sports Arena + Sky Sports F1 + Sky Sports Football + Sky Sports Mix + Sky Sports News + Sky Sports Racing + Sky News + Smithsonian Channel + SonLife + Sony Channel + Great! Movies + Great! Movies Action + Great! Movies Classic + Great! Movies +1 + STV UK + Sky Sci-Fi + Talking Pictures TV + TCM UK + That's TV + The Box + Trace Vault UK + Tiny Pop TV + TLC UK + Together + Trans World Radio + UK Gold + Ulster TV + Viaplay Xtra + W UK + Warner TV IT + Yesterday + 4Music + 4 Seven + 5 Star + Al Jazeera + Al Jazeera Arabic English + Alibi + Animal Planet UK + Arise News + At The Races + BBC1 + BBC1 Northern Ireland + BBC One Scotland + BBC2 + BBC3 + BBC4 + BBC Alba + BBC News Channel + BBC Parliament + Bloomberg TV + Boomerang + Boomerang UK + TNT Sports 1 + TNT Sports 2 + TNT Sports 4 + TNT Sports Europe + TNT Sports Ultimate + Cartoon Network + Cartoon Network UK + Cartoonito UK + CBBC + Cbeebies + CBS Drama UK + CBS Reality UK + CGTN + Challenge TV + Channel 4 + Channel 4 +1 + Channel 5 + Children's ITV + CNBC Europe + CNN Europe + Comedy Central Extra UK + Comedy Central UK + Crime and Investigation UK + Cúla4 + Dave + Daystar + Discovery Channel UK + Discovery History UK + Discovery Science UK + Discovery Turbo UK + DMAX UK + DocuBox HD + Drama UK + E4 + E4 Extra + Eden UK + EuroNews + Eurosport 2 UK + Eurosport UK + Extreme Sports Channel + Fashion TV + FashionBox HD + Fast&FunBox HD + Film4 + FilmBox Arthouse + Food Network UK + France24 + Gametoon HD + Gems TV + Ginx Esports TV + The History Channel + History Channel 2 + Home & Garden Television UK + Ideal Home Shopping + Inspiration TV + Investigation Discovery UK + ITV1 + ITV2 + ITV2+1 + ITV3 + ITV4 + ITV Be + JML Direct + Kerrang! + Kiss UK + Pop Max + Legend + Magic + More4 + Movies 24 + MTV 80s UK + MTV 90s UK + MTV Hits UK + MTV Music UK + MTV UK + 5Select + Nat Geo Wild UK + National Geographic Channel UK + Nick Junior UK + Nickelodeon UK + Nicktoons UK + Oireachtas TV + Paramount Network UK + PBS America + Pick TV + Pop UK + Premier Sports 1 + Premier Sports 2 + Quest TV + Quest Red + QVC Beauty + QVC Style + Really UKTV + Revelation TV + RTÉ One + RTÉ2 + RTÉ News + RTÉjr + Russia Today + S4C + Sky Arts + Sky Atlantic + Sky Crime + Sky Kids + Sky Witness + Sky Max + Sky Cinema Action + Sky Cinema Comedy + Sky Cinema Thriller + Sky Family + Sky Nature UK + Sky Showcase + Sky Sports Racing + Sky News + Smithsonian Channel + SonLife + Sony Channel + Great! TV + Great! Movies + Great! Movies Action + Great! Movies Classic + Great! Movies +1 + Sky Sci-Fi + Talking Pictures TV + TCM UK + TG4 Ireland + The Box + Tiny Pop TV + TLC UK + Together + Virgin Media One + UK Gold + Ulster TV + Viaplay Xtra + Virgin Media Four + Virgin Media More + Virgin Media Three + Virgin Media Two + W UK + WION + Yesterday + Tring 3 Plus + 3SAT + 4Fun Dance + 4Fun Kids + 24 Kitchen + 24 ВЕСТИ + 360 TuneBox + A2 CNN + ABC News Albania + Adria TV + Agro TV + Al Jazeera Balkans + AMC + Anixe HD Serie + Das Erste + Arena Esport + Arena Fight + Arena Sport 1 Premium + Arena Sport 1x2 + Arena Sport 2 Premium + Arena Sport 3 Premium + Arena Sport 5 RS + Arena Sport 6 RS + Arena Sport 7 RS + Arena Sport 8 RS + Arena Sport 9 RS + Arena Sport 10 RS + ARTE DE + AXN + AXN Spin + B92 + BabyTV + Balkan trip + Balkan TV + Bang Bang + BBC Earth + BBC World News + BlicTV + Bloomberg Adria + Radio Televizija BN + BN music + BN 2 HD + Boomerang + Brainz TV + Bravo Music + Cartoon Network + Cartoonito CEE + CBS Reality + CCTV 4 Europe + CGTN + CGTN Documentary + Cinemax + Cinemax 2 + CineStar Premiere 1 + CineStar Premiere 2 + CineStar TV2 + CineStar TV Comedy Family + CineStar TV Fantasy + Click TV + Croatian Music Channel + CNN Europe + Nicktoons + Crime & Investigation Channel + Cufo TV + Deutsche Welle English + DigitAlb T HD + Discovery Animal Planet + Discovery Channel + Discovery Science + TLC + Discovery Turbo Extra + Disney Channel + Disney Junior + DM SAT + DocuBox HD + Dorcel TV + Dorcel XXX + DOX TV + Dr. Fit HD + DuckTV + Elrodi + Elta 1 HD + E! Entertainment + Epic Drama (CEE) + Erox HD + Eroxxx HD + Eurochannel + EuroNews + Euronews Albania + EuroNews Srbija + Eurosport + Eurosport 2 + Explorer Histori + Explorer Natyra + Explorer Shkence + Extreme Sports Channel + FACE TV + Fashion TV + FashionBox HD + Fast&FunBox HD + FAX News + FightBox HD + SK Fight + Film Aksion Digitalb + Film Autor + Film Drame Digitralb + Film Klub + Film Thriller Digitalb + FilmBox Arthouse + FilmBox Extra RS + FilmBox Stars RS + FilmBox Premium RS + Food Network + STAR Channel + STAR Crime + STAR Life + STAR Movies + FOX NEWS + France24 + France 3 + France 24 French + Radio Televizija Federacije BIH + Gametoon HD + SK Golf + Golica TV + Grand Televizija + Grand nostalgija + HappyTV + Hayat Folk + Hayat Music + Hayat Plus + Hayat TV + Hayatovci + HBO + HBO3 + HBO2 + Home & Garden Television + The History Channel + History Channel 2 + HRT 1 + HRT 2 + HRT 3 + HRT 4 + HUSTLER TV + IDJ World + Insajder TV + Insta TV + Investigation Discovery + Tring Jolly HD + Jugoton TV + Junior TV + K1 TV + K::CN 2 Music + Kanal 3 Prnjavor + Kanal D + Kanali 7 + Kazbuka + KitchenTV + Klan Kosova + Kohavision + K::CN 1 Kopernikus + Kurir TV + Living HD + Lov i ribolov + MCN TV + Mediaset Italia + DigitAlb Melody TV + Minimax + MTV Europe + MTV 00s + Club MTV International + MTV Hits International + MTV Live HD + MTV 90s International + MUSE + My Music + MyZen TV + N1 RS + Наша ТВ + National Geographic + National Geographic Channel HD + Nat Geo Wild + NBA TV + News 24 + Nat Geo Wild HD + Nick Junior + Nickelodeon Commercial + Nova Max + Nova S + Nova Series + Nova Sport Srbija + RTV Novi Pazar + NTV IC Kakanj + O Kanal + OBN + Ora News + OTV Valentino + Pickbox TV RS + Pikaboo + RTV PINK + RED tv + Vesti + Pink Action + Pink Thriller + Pink Crime & Mystery + Pink BH + Pink Classic + Pink Comedy + Pink Erotic 1 + Pink Erotic 2 + Pink Erotic 3 + Pink Erotic 4 + Pink Erotic 5 + Pink Erotic 6 + Pink Erotic 7 + Pink Erotic 8 + TV PINK EXTRA + PINK Family + Pink Fashion + PINK Film + Pink Folk 1 + Pink Folk 2 + Pink Ha Ha + Pink Hits + Pink Hits 2 + Pink Horror + Pink Kids + Pink Koncert + Pink Kuvar + Pink LOL + Pink M + Pink Movies + Pink Romance + Pink SCI FI & Fantasy + Pink Music 1 + Pink and Roll + Pink Pedia + TV PINK PLUS + Pink Premium + Pink Reality + Pink Serije + Pink Show + Pink Soap + Pink Style + Pink Super Kids + Pink Western + PINK World + Pink World Cinema + PINK Zabava + Premier League TV + Brazzers TV (ex. Private Spice) + Private TV + ProSieben + Prva FILES + Prva KICK + Prva LIFE + Prva MAX + Prva Plus + Prva Srpska TV + Prva TV Crna Gora + Prva World + RAI UNO + RAI DUE + Reality Kings + Report TV + Россиᴙ 24 + RT Documentary + RTK 1 + RTL + RTL 2 + RTL Croatia World + RTL Kockica + RTL Living + RTRS + RTRS PLUS + RTS 1 + RTS 2 + RTS 3 + RTS Drama + RTS Klasika + RTS Kolo + RTS Muzika + RTS Nauka + RTS SVET + RTS Trezor + RTS Život + Radio Televizija Budva + Russia Today + Scan TV + SciFi + Sport Klub 1 Crna Gora + SK esports + Sky News + RTV Slovenija 1 + Tring Smile + SOS Plus + Sport Klub 1 Srbija + Sport Klub 4 + Sport Klub 5 + Sport Klub 6 + Sport Klub HD + Sport Klub 1 Slovenija + Sport Klub 3 + Sport Klub 2 Srbija + Superstar 2 + Stinet + Studio B + STV Folk + SuperSport 1 AL + Superstar TV + K::CN 3 Svet Plus + Syri TV + Televizioni 7 + Tanjug Tačno + Timeless Drama Channel + TGCOM24 + Tip TV + TOGGO plus + Top Channel + Top News + Toxic Folk + Toxic TV + Travel Channel + Tring Collection + Tring Comedy + Tring History + Tring Kids + Tring Life + Tring Action + Tring Novelas + Tring Planet + Tring Shqip + Tring Super + Tring Tring + Tring World + TV5Monde Europe + TV1000 Balkan + Televizija TV7 + Arena Sport 1 RS + Arena Sport 2 RS + Arena Sport 3 RS + Arena Sport 4 RS + TV Duga + SAT + TV Dukagjini + Телевизија Храм + RTV Most + Televizija Doktor + UNA TV + DIVA (ex. Universal) + Vavoom + MTV 80s + Viasat Explore CEE + Viasat History + Viasat Nature CEE + Vikom + Vizion Plus + RT Vojvodina 1 + RT Vojvodina 2 + Woman HD + ZDFinfo + ZDFneo + Zdrava televizija + Zico TV + BG Music Channel + Fuel TV + Passion XXX + The Voice BG + 7RM + 8 Andalucía + 8tv Catalunya + 3/24 + À Punt ES + AMC Break ES + Al Jazeera + AMC Crime ES + Antena 3 + Antena.nova + Aragón TV + Atreseries ES + AXN ES + AXN White ES + BabyTV ES + BBC World News + BE MAD ES + Betis TV ES + Bloomberg TV + Boing ES + BOM + Calle 13 + Canal 24H + Canal Cocina + Canal Decasa + Canal Extremadura + Canal Fútbol Replay + Odisea + Canal Panda + Canal Parlamento + Canal Sur + Castilla la Mancha TV + Caza y Pesca ES + Clan TVE + CNBC Europe + CNN Europe + Comedy Central ES + COSMO + Cuatro + DAZN 1 ES + DAZN 2 ES + DAZN F1 + DBike Channel + Deutsche Welle English + Deutsche Welle Espanol + Discovery Channel ES + Discovery MAX.es + Disney Channel ES + Disney Junior ES + Divinity + DKISS ES + El Toro TV + LEVANTE TV + Energy + Esport3 + EuroNews + Euronews FR + Eurosport 1 ES + Eurosport 2 ES + EWTN ES + Extreme Sports Channel + Fashion TV + Factoria de Ficción + Feel Good + Fight Time + FOX ES + France24 + HispanTV + Historia ES + HIT TV ES + Canal Hollywood + Iberalia HD CAZA + Iberalia HD PESCA + Iberalia TV + La 1 Cataluña + La dos + LA 8 MEDITERRANEO + La Otra ES + La primera + La Rioja + La sexta + Mega ES + Mezzo + Mezzo Live HD + MOTO ADV + Motorvision TV + Movistar Acción + Movistar Cine Español + Movistar Comedia + Movistar Deportes 1 + Movistar Deportes 2 + Movistar Drama + Movistar Estrenos + Movistar Estrenos 2 + Movistar Fórmula 1 + Movistar Golf + Movistar LaLiga + Movistar Liga de Campeones + Movistar Series + Movistar Seriesmania + MTV 00s + Club MTV International + MTV ES + MTV Hits International + MTV Live HD + MTV Music UK + MTV 90s International + MyZen TV + Nasa TV US + Nat Geo Wild ES + National Geographic ES + Nautica TV + Antena.neox + Nick Junior ES + Nickelodeon ES + Paramount Network ES + Paramount Comedy ES + Real Madrid TV + Russia Today ES + SYFY ES + Sevilla FC TV + Sky News + Stingray Classica + Sundance ES + Canal 33 + SX3 + TCM ES + Telecinco + TELE ELX + TeleDeporte + TeleMadrid + Ten ES + Warner TV ES + Toros TV + TV3 Catalunya + TV3 ES + TV5Monde Europe + TV Canaria + TVE Internacional + Televisión de Galicia + #Vamos + MTV 80s + 6ter + 360 TV + AB3 + Action + Al Arabiya + Al Jazeera + Antena 3 + Das Erste + ART Aflam 1 + ART Aflam 2 + ART Cinema + ARTE FR + ARTE DE + Atreseries ES + BabyTV + BBC Earth + BBC World News + beIN Drama Channel + beIN Movies Action + beIN Movies Drama + beIN Movies Family + beIN Movies Premiere + beIN Movies Premiere TR + beIN Series 1 + beIN Series 2 + beIN Sports 1 FR + beIN Sports 2 FR + beIN Sports 3 FR + beIN Sports MAX 5 FR + beIN Sports MAX 6 FR + beIN Sports MAX 7 FR + beIN Sports MAX 8 FR + beIN Sports MAX 9 FR + beIN Sports MAX 10 FR + beIN Sports MAX 4 FR + Benfica TV + BET FR + BFM Business + BFM TV + Bloomberg TV + Boing + Boomerang + Boomerang FR + Boomerang UK + C8 FR (ex. D8) + Canal 24H + Canal Cocina + Canal Decasa + CANAL+ DOCS + Canal+ Kids FR + CANAL+ GRAND ECRAN + Canal J + Canal+ Cinéma(s) FR + Canal+ France + Canal Plus Sport FR + Canal+ Series FR + Cartoon Network + Cartoon Network FR + CCTV 4 Europe + CGTN + CGTN Documentary + Первый + Chérie 25 + Ciné+ Classic + Ciné+ Club + Ciné+ Emotion + Ciné+ Famiz + Ciné+ Frisson + Polar+ + Cine+ Premier FR + English Club TV + CNBC Europe + CNews + CNN Europe + Comedie+ + Comedy Central FR + Comedy Central UK + Crime District + CStar FR + CStar Hits France + Daystar + Deutsche Welle English + Discovery Channel FR + Discovery Investigation FR + Disney Channel FR + Disney Junior FR + Stingray Djazz + Dorcel TV + Dorcel XXX + E! Entertainment + Euro Star + Eurochannel + Eurochannel FR + EuroNews + Euronews FR + Eurosport 2 FR + Eurosport FR + Fashion TV + FightBox HD + FOX NEWS + France24 + France 2 + France 3 + France 4 + France 5 + France24 Arabic + France 24 French + France Info + Game One + Ginx Esports TV + Golf Channel Češka + Golf Channel FR + Golf plus + Gulli + Habertürk + HUSTLER TV + i24News FR + Infosport+ + iTVN + iTVN Extra + J-One + Kabel 1 + Kanal 7 + KBS World HD + KiKA + L'Equipe + La Chaîne Info + LCP + M6 + Mangas + MBC Bollywood + MCM FR + MCM Top + Mediaset Italia + Mezzo + Mezzo Live HD + MGG TV + Motorvision TV + Motorvision TV France + MTV Europe + MTV 00s + MTV FR + MTV Hits FR + MTV Hits International + MTV Live HD + Museum TV + NTV DE + Nat Geo Wild FR + National Geographic FR + The Nautical Channel + Nickelodeon FR + Nickelodeon Junior FR + Nickelodeon Teen FR + Novelas TV FR + NRJ12 + RMC Story + OCS Geants + OCS Max + OCS Pulp + Olympia TV + OSN TV Movies Hollywood + OSN TV Movies Premiere + OSN TV Kids + OSN TV Movies Action + OSN TV Ya Hala Aflam + Paramount Channel FR + Paris premiere + TV PINK EXTRA + PINK Film + Pink Music 1 + TV PINK PLUS + Piwi+ + Planète+ Aventure + Planete+ Crime + Planète+ + Playboy TV + Power Türk TV + Brazzers TV (ex. Private Spice) + Private TV + ProSieben + RAI UNO + RAI DUE + RAI TRE + RAI Education + RAI News 24 + RAI Storia + Reality Kings + RMC Découverte + RMC Sport 1 + RMC Sport 2 + RMC Sport Live 4 + RMC Sport Live 5 + RMC Sport Live 6 + RMC Sport Live 7 + RMC Sport Live 8 + RMC Sport Live 9 + RMC Sport Live 10 + RMC Sport Live 11 + RMC Sport Live 12 + RMC Sport Live 13 + RMC Sport Live 14 + RMC Sport Live 15 + RMC Sport Live 16 + RMC Sport Live 17 + RMC Sport Live 3 + RT Documentary + RTL Zwei + RTL DE + RTL Nitro + RTP3 + RTS SVET + Russia Today + Sat.1 + Seasons + Show Türk + SIC Internacional + Sky News + Star Movies MENA + Star World MENA + Stingray CMusic + Stingray Classica + Stingray iConcerts + Super RTL + SWR + TCM UK + TCM Cinéma + Télétoon+ FR + Télévision française 1 + TFX + TGCOM24 + TiJi + TMC + Trace Urban + Travel Channel + TRT 1 + TRT Çocuk + TRT Turk + TRT World + TV3 Catalunya + TV5 Monde + TV5Monde Asia + TV5Monde Europe + TV5Monde Style + TV1000 Global Kino + TV Breizh + TVE Internacional + Televisión de Galicia + MTV 80s + Vivid TV + Vosges Télévision + VOX + W9 + Warner TV FR + Welt + World Fashion Channel + ZDF + ZDFinfo + XXL + 3SAT + 4Fun Dance + 24 Kitchen + 24 ВЕСТИ + 360 TuneBox + Adult Channel + Al Jazeera + Al Jazeera Balkans + ALFA TV + AMC + Das Erste + Arena Esport + Arena Fight + Arena Sport 4 HR + Arena Sport 6 HR + Arena Sport 8 HR + Arena Sport 9 HR + Arena Sport 10 HR + ARTE DE + Alternativna televizija Banja Luka + Aurora TV + AXN + AXN Spin + B1 TV + B92 + BabyTV + Balkan trip + Balkan TV + Balkanika TV + BBC Earth + BBC First + BBC World News + Radio Televizija BIH + Bloomberg TV + Bloomberg Adria + Blue Hustler + Radio Televizija BN + BN music + BN 2 HD + Body in Balance + Boomerang + Brainz TV + Cartoon Network + Cartoonito CEE + Cartoonito UK + CBS Reality + CCTV 4 Europe + CGTN + CGTN Documentary + Cinemax + Cinemax 2 + CineStar Action&Thriller + CineStar Premiere 1 + CineStar Premiere 2 + CineStar TV1 + CineStar TV2 + CineStar TV Comedy Family + CineStar TV Fantasy + English Club TV + Croatian Music Channel + CNBC Europe + CNN Europe + Comedy Central DE + Nicktoons + Crime & Investigation Channel + Da Vinci Learning + Deluxe Music + Deutsche Welle English + Diadora TV + Discovery Animal Planet + Discovery Channel + Discovery Science + TLC + Disney Channel + Stingray Djazz + DMAX DE + DMC televizija + DM SAT + DocuBox HD + DOKU TV + Doma TV + Dorcel TV + Dorcel XXX + DOX TV + Dr. Fit HD + Sport 1 DE + Dubrovačka Televizija + DuckTV + Duna World + E! Entertainment + Epic Drama (CEE) + Erox HD + Eroxxx HD + Eurochannel + EuroNews + Eurosport + Eurosport 2 + Eurosport 2 DE + Eurosport 1 EMEA + Eurosport.com + Eurosport 1 DE + ExtraTV + Extreme Sports Channel + FACE TV + Fashion TV + FashionBox HD + Fast&FunBox HD + FightBox HD + SK Fight + Film4 + FilmBox Arthouse + FilmBox Extra RS + FilmBox Stars RS + FilmBox Premium RS + Fireplace + Food Network + STAR Channel + STAR Crime + STAR Life + STAR Movies + FOX NEWS + France24 + France 24 French + Radio Televizija Federacije BIH + Fuel TV + FullTV + FunBox UHD + GameHub HR + Gametoon HD + Ginx Esports TV + SK Golf + GP1 + Grand Televizija + Grand nostalgija + HappyTV + Hayat Folk + Hayat TV + Hayatovci + HBO + HBO3 + HBO2 + Home & Garden Television + The History Channel + History Channel 2 + HIT TV + HSE + HRT 1 + HRT 2 + HRT 3 + HRT 4 + HRT Int. + HUSTLER TV + ICT Business + Insta TV + Otvorena televizija + JimJam + Jugoton TV + K::CN 2 Music + Kabel 1 + Kabel eins Österreich + Kabel eins Doku + Kanal Rijeka + KBS World HD + KiKA + KinoTV + KitchenTV + Pop Max + Klape i Tambure TV + KLASIK HR + KLASIK + K::CN 1 Kopernikus + Laudato TV + Legend + Libertas TV + Lov i ribolov + LUXE TV + M1 Family + M1 FILM + M1 Gold + M6 + Maria Vision + MAXSport 1 + MAXSport 2 + Mediaset Italia + Mezzo + Mezzo Live HD + Motorvision TV + MG Movie Generation + MTV Europe + MTV 00s + Club MTV International + MTV Hits International + MTV Live HD + MTV 90s International + MyZen TV + N1 HR + N24 Doku + NTV DE + National Geographic + National Geographic Channel HD + Nat Geo Wild + The Nautical Channel + MrežaZG + Nat Geo Wild HD + Nick Junior + Nick Music + Nickelodeon + NOVA TV + Nova BH + Nova Plus Family + Nova Sport Srbija + O Kanal + OBN + One + ORF1 + ORF2 + ORF Sport Plus + Osječka televizija + OTV Valentino + Phoenix + Pikaboo + Pikaboo 2 + RTV PINK + RED tv + Vesti + Pink BH + Pink Classic + TV PINK EXTRA + Pink Fashion + PINK Film + Pink Folk 1 + Pink Folk 2 + Pink Ha Ha + Pink Hits 2 + Pink Kids + Pink Koncert + Pink Kuvar + Pink LOL + Pink M + Pink Music 1 + Pink Pedia + TV PINK PLUS + Pink Reality + Pink Serije + Pink Show + Pink Style + Pink Super Kids + PINK World + Pink World Cinema + PINK Zabava + Planet Earth + Plava televizija + Playboy TV + Poljoprivredna TV + Posavska Televizija + TV Zelina + Brazzers TV (ex. Private Spice) + Private TV + ProSieben + ProSieben MAXX + Prva KICK + Prva Plus + Prva Srpska TV + Prva World + QVC Deutschland + RAI UNO + RAI DUE + RAI TRE + RAI Education + RAI News 24 + RAI Sport 1 + RAI Storia + Reality Kings + RedLight HD + Россиᴙ 24 + Radiotelevizija Banovina + RTL + RTL 2 + RTL Zwei + RTL Adria + RTL DE + RTL Kockica + RTL Living + RTL Nitro + RTLup + RTRS + RTRS PLUS + RTS 1 + RTS 2 + RTS SVET + RTV Herceg-Bosne + Russia Today + Saborska TV + Samobor TV + Sat.1 + Sat.1 Österreich + Sat.1 Gold + Slavonskobrodska Televizija + SciFi + ServusTV + SK 4K + SK esports + Sky News + TV Slavonije i Baranje + RTV Slovenija 1 + RTV Slovenija 2 + RTV Slovenija 3 + sonnenklar.TV + Sony Channel + Great! Movies Action + Great! Movies Classic + Great! Movies +1 + SOS Plus + Sport Klub 4 + Sport Klub 5 + Sport Klub 6 + Sport Klub 7 + Sport Klub 8 + Sport Klub 9 + Sport Klub 10 + Sport Klub HD + Sport Klub 1 Hrvatska + Sport Klub 2 Hrvatska + Sport Klub 3 + Sport Klub 2 Srbija + Sportska Televizija + Stars TV PL + Stingray CMusic + Stingray Classica + Stingray iConcerts + Studio B + Super RTL + Supertennis HD + K::CN 3 Svet Plus + Timeless Drama Channel + Telecinco + Televizija Alfa + Telma + TiJi + Tiny Pop TV + TOGGO plus + Toon kids + Toxic Folk + Toxic Rap + Toxic TV + Trace Urban + Travel Channel + Trend TV + TV5 Monde + TV5Monde Europe + TV1000 Balkan + Arena Sport 1 HR + Arena Sport 2 HR + Arena Sport 3 HR + Televizija Dalmacija + TV Duga + SAT + TV Jadran + TV Šibenik + TV Vijesti + Televizija Zapad Zaprešić + Televizija Crne Gore MNE + TVE Internacional + UNA TV + DIVA (ex. Universal) + Varaždinska Televizija + Vavoom + MTV 80s + Viasat Explore CEE + Viasat History + Viasat Nature CEE + Plava vinkovačka TV + Vivid Red + Vivid TV + Vizion Plus + RT Vojvodina 1 + VOX + Welt + Woman HD + Zagrebačka Televizija + ZDF + ZDFinfo + ZDFneo + Zdrava televizija + Tring 3 Plus + 4Fun Dance + 4Fun Kids + 24 Kitchen + 360 TuneBox + Agro TV + Televizija Alfa + Al Jazeera Balkans + Al Jazeera + Alpha TV + AMC HU + Antena Europe + Apostol TV + Arena4 HU + Arena Esport + Arena Fight + Arena Sport 1 BiH + Arena Sport 1 RS + Arena Sport 1 SI + Arena Sport 1 Premium + Arena Sport 1 Premium SI + Arena Sport 1x2 + Arena Sport 2 RS + Arena Sport 2 SI + Arena Sport 2 Premium + Arena Sport 3 RS + Arena Sport 3 SI + Arena Sport 3 Premium + Arena Sport 4 RS + Arena Sport 4 SI + Arena Sport 5 HR + Arena Sport 5 RS + Arena Sport 6 RS + Arena Sport 7 HR + Arena Sport 7 RS + Arena Sport 8 RS + ARTE DE + ATV Avrupa + AXN HU + AXN + AXN Spin + B1 TV + Balkanika TV + Balkan trip + BBC Earth + BBC News Channel + BBC World News + TV Belle Amie + BN 2 HD + BN music + Boomerang + Brainz TV + Brazzers TV (ex. Private Spice) + BRIO + Canale 5 + CGTN Documentary + Cinemania TV + CineStar TV1 + CineStar TV RS + CineStar TV2 + CineStar Action&Thriller + CineStar Action&Thriller RS + CineStar TV Comedy Family + CineStar TV Fantasy + CineStar Premiere 1 + CineStar Premiere 2 + CNN Europe + CNN Türk TV + Comedy Central HU + Comedy Central Family HU + CoolTV + Cufo TV + D1 TV HU + Das Erste + Da Vinci Learning + Dexy TV + Discovery Channel HU + Discovery Science + Disney Channel HU + DM SAT + DocuBox HD + DOKU TV + Doma TV + Dr. Fit HD + Deutsche Welle English + English Club TV + Epic Drama (CEE) + Erox HD + Eroxxx HD + ETV HD + Eurochannel + Euro D + EuroNews + Eurosport + Eurosport 2 + Explorer Histori + Explorer Natyra + Explorer Shkence + FACE TV + FashionBox HD + Fashion TV + Fast&FunBox HD + FEM3 + FightBox HD + Pink Fight Network + Film4 HU + Film Aksion Digitalb + FilmBox Arthouse + Filmbox Stars HU + Film Cafe HU + Film Drame Digitralb + Film Klub + Film Mania HU + Film+ HU + Film Thriller Digitalb + Food Network + STAR Crime + France24 Arabic + France24 + France 24 French + Galaxy4 + Gametoon HD + Ginx Esports TV + Golica TV + Grand Televizija + Pink Ha Ha + Hayat Folk + Hayat Music + Hayatovci + Hayat Plus + HBO HU + Home & Garden Television + Hír TV + History Channel 2 + HRT 2 + HRT 4 + HRT Int. + IDJ World + INTV AL + Investigation Discovery + Italia 1 + Izaura TV + JockyTV + Jugoton TV + Kanal 3 Prnjavor + Kanal A, SLO + Kanal D TR + Kazbuka + KINO + KinoTV + KitchenTV + Klan Kosova + Klan Macedonia + KLASIK + Kohavision + Kurir TV + La7 + Laudato TV + Life TV HU + Living HD + Pink LOL + Lov i ribolov + M1 FILM + M1 Gold + Mediaset Italia + Mezzo + Mezzo Live HD + Minimax + MiniTV + Mozi plusz TV + Moziverzum + МРТ 1 + МРТ 2 + MTV Europe HU + MTV Live HD + Muzsika TV + N1 BA + N1 HR + National Geographic HU + Nat Geo Wild HU + RTL Nitro + Nova 24 TV + Nova S + Nova Plus Cinema + Nova Sport Srbija + Nova BH + TV NOVA Pula + Nova M + Nova World + Novosadska TV + OBN + O Kanal + One + OTO + PΛX + Pickbox TV + Pink Action + Pink BH + Pink Classic + Pink Comedy + Pink Crime & Mystery + PINK Family + Pink Fashion + Pink Folk 2 + Pink Hits + Pink Horror + Pink Koncert + Pink Kuvar + Pink M + Pink Movies + Pink and Roll + Pink Pedia + Pink Premium + Pink Romance + Pink SCI FI & Fantasy + Pink Serije + Pink Show + Pink Soap + Pink Style + Pink Super Kids + Pink Thriller + Pink Western + PINK World + Pink World Cinema + PINK Zabava + Planeta TV BG + Planet Earth + Planet TV SI + Playboy TV + POP TV + Power Türk TV + Prime + ProSieben Fun + Prva FILES + Prva KICK + Prva LIFE + Prva MAX + Prva TV Crna Gora + Prva Plus + Prva World + QVC STYLE DE + QVC Style + RadioBremen + RAI UNO + RAI DUE + RAI TRE + RAI Gulp + RAI News 24 + RAI Storia + real time + Rete 4 + Russia Today + RTK 1 + RTK 2 + RTL + RTL HU + RTL Crime + RTL Gold + RTL Ketto + RTL Living + RTL Passion + Super RTL + RTRS PLUS + RTS 2 + RTS 3 + RTS Drama + RTS Kolo + RTS Muzika + RTS Poletarac + RTS SVET + RTS Trezor + RT Vojvodina 1 + RT Vojvodina 2 + RTV21 + Россиᴙ 24 + SonLife + Show Türk + Сител + Magyar Sláger TV + Sorozat+ + Spektrum TV + Spektrum Home HU + Spíler1 TV + Spíler2 TV + Sport 1 DE + Sport 1 HU + Sport 2 HU + Sport Klub 1 Srbija + Sport Klub 1 Slovenija + Sport Klub 2 Srbija + Sport Klub 2 Slovenija + Sport Klub 3 + Sport Klub 4 + Sport Klub 5 + Sport Klub 6 + SK esports + SK Golf + Sport Klub HD + Sportska Televizija + Sport TV1.pt + Šport TV 1 + Sport TV2 + Šport TV 2 + Stars TV PL + Stingray iConcerts + Story4 + Studio B + Superstar TV + Super TV2 + TGCOM24 + The Fishing and Hunting + TLC + TOGGO plus + Trace Urban + Travel Channel + TRT Arapça + TRT Avaz + TV2 HU + TV2 Comedy + TV2 Kids + TV2 Séf + TV 3 Medias + TV4 HU + TV Arena + Televizija Crne Gore 1 + Televizija Crne Gore 2 + Televizija Crne Gore MNE + TV Galaksija + Телевизија Храм + K::CN 1 Kopernikus + K::CN 2 Music + K::CN 3 Svet Plus + TV Koper + TVN24 + TVN + TV Paprika HU + TVP Polonia + RTV Slovenija 1 + RTV Slovenija 2 + RTV Slovenija 3 + ТВ Сонце + TV Vijesti + Ülke TV + Viasat3 + Viasat 6 + Viasat Explore CEE + Viasat History + TV1000 Global Kino + Viasat Nature CEE + TV1000 Balkan + VOX + Woman HD + World Fashion Channel + Zagrebačka Televizija + ZDF + Zenebutik + 360 TuneBox + Das Erste + ARD-alpha + ATV Spirit HU + BabyTV + BBC News Channel + BBC World News + Bloomberg TV + Boomerang + Cartoonito CEE + CBS Reality + CCTV 4 Europe + Cinemax 2 HU + Cinemax HU + English Club TV + CNN Europe + Da Vinci Learning + Deutsche Welle English + Discovery Turbo Extra + DocuBox HD + DuckTV + Duna TV + Duna World + E! Entertainment + Epic Drama (CEE) + Eroxxx HD + Extreme Sports Channel + FashionBox HD + Fast&FunBox HD + Fehérvár TV + FightBox HD + FilmBox Arthouse + Filmbox Extra HU + Filmbox Family HU + FilmBox HU + Filmbox Premium HU + Food Network + France24 + Gametoon HD + HBO + HBO 2 HU + HBO 3 HU + Home & Garden Television + The History Channel + History Channel 2 + History Channel HU + Home & Garden Television UK + HUSTLER TV + Investigation Discovery + Investigation Discovery UK + Jazz TV HU + JimJam + KiKA + Magyar Televízió 1 + M2 Petőfi + Magyar Televízió 3 + M4 sport + M4 Sport Plus + m5 + ATV HU + Magyar Mozi TV + MATCH4 + MAX4 + Mediaset Italia + Mezzo + Mezzo Live HD + Minimax + Minimax HU + MTV 00s + Club MTV International + MTV Hits International + MTV Live HD + MTV 90s International + MyZen TV + Nick Junior PL + Nickelodeon Commercial + Nicktoons PL + Ozone Network + Paramount Network HU + Polonia1 + Private TV + ProSieben + RAI UNO + RAI TRE + RedLight HD + RTL Zwei + RTL DE + RTL Három + Sat.1 + Sky News + Viasat Film HU + Stingray Classica + Stingray iConcerts + Super RTL + TeenNick + Travel Channel + TVE Internacional + MTV 80s + Viasat 2 + Viasat History + Viasat Nature CEE + VOX + ZDF + 7 Gold + 20 Mediaset + Alma TV + Boing + Boing Plus + Boomerang IT + Canale 5 + Canale 7 + Cartoon Network IT + Cartoonito Italia + cielo + Cine34 + Class TV Moda + Comedy Central IT + CI Crime+ Investigation + DAZN IT + DeA Junior + DeA Kids + Discovery Channel IT + Discovery MAX.es + DMAX IT + Eurosport 2 IT + Eurosport IT + Focus TV + Food Network Italia + Frisbee + Gambero Rosso Channel + Giallo TV + History Channel IT + Inter Channel + Iris + Italia 1 + Italia 2 + K2 + La Cinque + La7 + La7 AU + La7d + Lazio Style Channel + Marco Polo TV + Mediaset Extra + Mediaset Italia + Mediaset Italia AU + Milan TV + MotorTrend + MTV Hits International + MTV Italia + MTV Music UK + MTV Music IT + MTV 90s International + National Geographic + Nick Junior IT + Nickelodeon IT + NOVE + Parole di Vita + Radio Italia TV + Radiofreccia + RAI UNO + RAI DUE + RAI TRE + RAI 3 Bis + RAI 4 + RAI 5 + RAI Education + RAI Gulp + RAI Italia Australia + RAI Movie + RAI News 24 + RAI Premium + RAI Sport 1 + RAI Storia + RAI World Premium + Rai Yoyo + real time + Rete 4 + Sky Arte + Sky Atlantic IT + Sky Caccia e Pesca + Sky Cinema Action IT + Sky Cinema Collection IT + Sky Cinema Comedy IT + Sky Cinema Drama IT + Sky Cinema Due + Sky Cinema Family IT + Sky Cinema Romance IT + Sky Cinema Suspense IT + Sky Cinema Uno + Sky Documentaries IT + Sky Investigation + Sky Nature IT + Sky Pesca e Caccia + Sky Serie + Sky Sport24 HD + Sky Sport 1 IT + Sky Sport 2 IT + Sky Sport 3 IT + Sky Sport F1 IT + Sky Sport MotoGP IT + Sky Sport Plus IT + Sky TG24 HD + Sky Uno + Sportitalia + Super! + Supertennis HD + Telequattro + Teletutto + TGCOM24 + Top Calcio 24 + Top Crime + TV8 IT + TV 2000 + Twenty Seven + VH1 IT + Warner TV IT + Tring 3 Plus + 24 Kitchen + 24 ВЕСТИ + 360 TV + ABC News Albania + Agro TV + Al Jazeera + Al Jazeera Balkans + ALFA TV + Алсат М + AMC + Anixe HD Serie + Das Erste + Arena Esport + Arena Fight + Arena Sport 1 MK + Arena Sport 1 Premium + Arena Sport 2 Premium + Arena Sport 3 Premium + Arena Sport 5 RS + ARTE DE + Alternativna televizija Banja Luka + AXN + AXN Spin + Balkan trip + Balkanika TV + Bang Bang + BBC First + BBC World News + Bloomberg TV + Bloomberg Adria + Radio Televizija BN + BN music + BN 2 HD + Boomerang + Brainz TV + Cartoon Network + Cartoonito CEE + CBS Reality + Cinemania TV + Cinemax + Cinemax 2 + CineStar Premiere 1 + CineStar Premiere 2 + CineStar TV2 + Croatian Music Channel + CNBC Europe + CNN Europe + Nicktoons + Crime & Investigation Channel + Cufo TV + Da Vinci Learning + Deluxe Music + Deutsche Welle English + DigitAlb T HD + Discovery Animal Planet + Discovery Channel + Discovery Science + TLC + Disney Channel + Disney Junior + DM SAT + DocuBox HD + Sport 1 DE + Elta 1 HD + E! Entertainment + Epic Drama (CEE) + Erox HD + Eroxxx HD + Euro Star + EuroNews + Euronews Albania + Eurosport + Eurosport 2 + Explorer Histori + Explorer Natyra + Explorer Shkence + Extreme Sports Channel + FACE TV + Fashion TV + FashionBox HD + Fast&FunBox HD + FightBox HD + SK Fight + Film Autor + Film Drame Digitralb + Film Klub Extra + Film Thriller Digitalb + FilmBox Arthouse + FilmBox Extra RS + FilmBox Stars RS + The Fishing and Hunting + Food Network + STAR Channel + STAR Crime + STAR Life + STAR Movies + France24 + France 24 French + Radio Televizija Federacije BIH + Ginx Esports TV + SK Golf + Grand Televizija + HappyTV + Hayat Folk + Hayat Music + Hayat Plus + Hayat TV + Hayatovci + HBO + HBO3 + HBO2 + The History Channel + HRT 1 + HRT 3 + HRT 4 + HUSTLER TV + IDJ World + JimJam + Tring Jolly HD + Jugoton TV + Junior TV + K::CN 2 Music + Kabel 1 + Kanal1 + Канал 5 + Канал 8 + Kanal 10 + Kanal D + Kerrang! + KiKA + TV Kiss Menada + KitchenTV + Klan Macedonia + KLASIK + K::CN 1 Kopernikus + Living HD + Lov i ribolov + M1 Family + M1 Film MK + M1 Gold MK + DigitAlb Melody TV + Mezzo + Minimax + МРТ 1 + МРТ 3 + МРТ 4 + МРТ 5 + MTM Televizija + MTV Europe + MTV 00s + Club MTV International + MTV Hits International + MTV Live HD + MTV 90s International + MUSE + My Music + N1 RS + Наша ТВ + National Geographic + National Geographic Channel HD + Nat Geo Wild + News 24 + Nick Junior + Nickelodeon Commercial + Nova S + Nova Sport Srbija + RTV Novi Pazar + O Kanal + OBN + Ora News + Pickbox TV MK + Pikaboo + Pink Music 1 + Pink Serije + Pink Show + Playboy TV + Brazzers TV (ex. Private Spice) + Private TV + ProSieben + Prva FILES + Prva KICK + Prva LIFE + Prva MAX + Prva Plus + Prva Srpska TV + Prva World + RAI UNO + RAI DUE + RAI TRE + RAI Sport 1 + RAI Storia + RedLight HD + Report TV + Россиᴙ 24 + RT Documentary + RTK 1 + RTK 2 + RTK 4 + RTL + RTL 2 + RTL Zwei + RTL DE + RTL Kockica + RTL Living + RTRS + RTS 1 + RTS 2 + RTS 3 + RTS SVET + RTSH 1 + RTV 21 Popullore + RTV Besa + RTV Slon Tuzla + Russia Today + Sat.1 + Scan TV + SciFi + Shenja TV + Сител + SK esports + Sky News + RTV Slovenija 1 + RTV Slovenija 2 + RTV Slovenija 3 + Tring Smile + SOS Plus + Sport Klub 1 Srbija + Sport Klub 4 + Sport Klub 5 + Sport Klub 6 + Sport Klub 7 + Sport Klub 8 + Sport Klub 9 + Sport Klub 10 + Sport Klub HD + Sport Klub 1 Hrvatska + Sport Klub 2 Hrvatska + Sport Klub 3 + Sport Klub 2 Srbija + Superstar 2 + Stinet + Stingray CMusic + Studio B + STV Folk + Super RTL + Superstar TV + K::CN 3 Svet Plus + Syri TV + Televizioni 7 + Timeless Drama Channel + Telma + Tera TV + Tip TV + Top Channel + Top News + Toxic Folk + Toxic Rap + Toxic TV + Trace Urban + Travel Channel + Travelxp + Tring Bunga Bunga + Tring Comedy + Tring Desire + Tring History + Tring Kids + Tring Life + Tring Action + Tring Novelas + Tring Planet + Tring Shqip + Tring Super + Tring Tring + Tring World + TRT 1 + TRT Turk + TV5 Monde + TV1000 Balkan + Arena Sport 2 RS + Arena Sport 3 RS + Arena Sport 4 RS + TV Duga + SAT + TV Dukagjini + TV Edo + Klan TV HD + TVM Ohrid + TV Sarajevo + Televizija Crne Gore MNE + DIVA (ex. Universal) + Valentino Music HD + Vavoom + MTV 80s + Viasat Explore CEE + Viasat History + Viasat Nature CEE + Vikom + Vizion Plus + VOX + Welt + Wness TV + World Fashion Channel + ZDF + Zdrava televizija + 1-2-3.tv + 2X2 + 3SAT + 4Fun Dance + 4Fun Kids + 4FunTV + Telewizja 13 + 13 Ulica + 360 TuneBox + Active Family + Adult Channel + Adventure HD + Al Jazeera + Ale Kino+ + ALFA TVP + AMC PL + Animal Planet PL + Anixe HD Serie + Antena HD + Das Erste + ARD-alpha + ARTE FR + ARTE DE + AstroTV + AXN Black PL + AXN PL + AXN Spin PL + AXN White PL + BabyTV PL + BBC Brit PL + BBC Earth PL + BBC First PL + BBC Lifestyle PL + BBC News Channel + BBC World News + Belsat TV + BFM TV + Bibel TV + Biznes24 + Bloomberg TV + Blue Hustler + Bollywood PL + Boomerang + CANAL+ 4K Ultra HD + CANAL+ Dokument + CANAL+ Family PL + CANAL+ Film PL + CANAL+ Premium +1 PL + Canal+ Domo + CANAL+ Kuchnia + CANAL+ Premium PL + CANAL+ Seriale PL + CANAL+ Sport 2 + CANAL+ Sport 3 + CANAL+ Sport 4 + CANAL+ Sport 5 + CANAL+ Sport PL + Cartoon Network PL + Cartoonito CEE + Cartoonito UK + CBeebies PL + CBS Europa PL + CBS Reality PL + CGTN Documentary + Cinemax 2 PL + Cinemax PL + CNBC Europe + CNews + CNN Europe + Comedy Central DE + Comedy Central PL + COSMO + Crime+Investigation PL + ČT 1 + ČT 2 + ČT 24 + ČT :D + ČT Sport + Da Vinci Learning PL + Deluxe Music + Deutsche Welle English + Deutsche Welle Deutsch + Disco Polo Music PL + Discovery Channel PL + Discovery Historia + Discovery Life PL + Discovery Science PL + Disney Channel PL + Disney Junior Polska + Disney XD PL + DIZI PL + Stingray Djazz + DMAX DE + DocuBox HD + Dorcel TV + Dorcel XXX + Sport 1 DE + DTX PL + Duck TV Plus + DuckTV + E-Sport HD + Eleven Sports 1 PL + Eleven Sports 2 PL + Eleven Sports 3 PL + Eleven Sports 4 PL + E! Entertainment + Epic Drama (Poland) + Eska Rock TV + Eska TV + Eska TV Extra + Еспресо TV + Eurochannel + EuroNews + Euronews FR + Eurosport 1 PL + Eurosport 2 PL + EWTN + EWTN PL + EXTASY TV + Extreme Sports PL + Fashion TV + FashionBox HD + Fast&FunBox HD + Fight Klub HD + FightBox HD + Filmax + FilmBox Action PL + FilmBox Arthouse + FilmBox Extra PL + FilmBox Family PL + FilmBox Premium PL + Fokus TV + Food Network PL + FX Comedy PL + FX PL + France24 + France 2 + France 3 + France 4 + France 5 + France Info + FunBox UHD + Gametoon HD + Ginx Esports TV + Golf Channel PL + HBO 2 PL + HBO 3 PL + HBO PL + Das Health TV + HGTV PL + History 2 Polska + History Channel Polska + HR Fernsehen + HSE + HSE24 Extra + Hustler HD + HUSTLER TV + Insight TV + Investigation Discovery PL + Italia 2 + iTVN + iTVN Extra + JimJam PL + K-TV Katholisches Fernsehen + Kabel 1 + Kabel eins Österreich + Kabel eins Doku + KiKA + Kino Polska + Kino Polska Muzyka + KinoTV PL + La Chaîne Info + LCP + Leo TV + Love Nature + MDR Sachsen-Anhalt + MDR Sachsen + MDR Thüringen + Metro TV + Mezzo + Mezzo Live HD + Minimini+ + Motowizja + MTV Europe + MTV 00s + Club MTV International + MTV DE + MTV Hits International + MTV Live HD + MTV PL + MTV 90s International + münchen.tv + Music Box Polska + MyZen TV + N24 Doku + NTV DE + National Geographic Wild PL + National Geographic PL + National Geographic People PL + The Nautical Channel + NDR Hamburg + NDR Mecklenburg-Vorpommern + NDR Niedersachsen + NDR Schleswig-Holstein + News 24 + Nick Junior PL + Nick Music + Nick DE + Nickelodeon PL + Nickelodeon Ukraine Pluto + Nicktoons PL + Niederbayern TV Deggendorf-Straubing + Novela TV + Novelas+ + Nowa TV + NRJ12 + NUTA GOLD + NUTA.TV HD + oe24.TV + One + ORF2 + Paramount Network PL + Parole di Vita + Phoenix + Planete+ PL + Playboy TV + POLO TV + Polonia1 + TVP Polonia + Polsat + Polsat 1 + Polsat 2 + Polsat Cafe + Polsat Comedy Central Extra + Polsat Doku + Polsat Film + Polsat Games + Polsat Music + Polsat News + Polsat News 2 + Polsat Play + Polsat Rodzina + Polsat Seriale + Polsat Sport + Polsat Sport Extra + Polsat Sport Fight + Polsat Sport News + Polsat Sport Premium 1 + Polsat Sport Premium 2 + Polsat Sport Premium 3 PPV + Polsat Sport Premium 4 PPV + Polsat Sport Premium 5 PPV + Polsat Sport Premium 6 PPV + Polsat Viasat Explore + Polsat Viasat History + Polsat Viasat Nature + Power TV PL + Brazzers TV (ex. Private Spice) + Private TV + ProSieben + PRO 7 Österreich + Proart + ProSieben MAXX + QVC Deutschland + Radio Italia TV + Radiofreccia + RBB Fernsehen Brandenburg + RBB Fernsehen Berlin + Reality Kings + Red Carpet TV PL + RedLight HD + RiC DE + Romance TV PL + RT Documentary + RTL Zwei + RTL DE + RTL Nitro + Russia Today + Sat.1 + Sat.1 Österreich + Sat.1 Gold + Kurier TV + SciFi + ServusTV + Sky Sport News DE + Sky News + sonnenklar.TV + Sportklub PL + SR Fernsehen + Stars TV PL + Stingray CMusic + Stingray Classica + Stingray iConcerts + Stopklatka + Sundance TV PL + Super Polsat + Super RTL + SWR Baden-Württemberg + tagesschau24 + TBN Polska + TeenNick + Tele 5 PL + Tele 5 DE + teleTOON+ + TLC PL + TOGGO plus + Top Kids Jr. PL + Top Kids PL + Trace Urban + Travel Channel PL + Travelxp + TRT Arapça + TTV + TV5Monde Europe + TV6 PL + TV 4 + TV Puls 2 + TV Puls PL + TV Regionalna.pl + TV Republika + TV Silesia + Toya TV + TV Trwam + TVC PL + TVE Internacional + TVN + TVN24 + TVN24 BiS + TVN 7 + TVN Fabuła + TVN Style + TVN Turbo + TVP3 Białystok + TVP3 Bydgoszcz + TVP3 Gdańsk + TVP3 Katowice + TVP3 Kielce + TVP3 Kraków + TVP3 Łódź + TVP3 Lublin + TVP3 Olsztyn + TVP3 Opole + TVP3 Poznań + TVP3 Rzeszów + TVP3 Szczecin + TVP3 Warszawa + TVP3 Wrocław + TVP 1 + TVP 2 + TVP 3 + TVP ABC + TVP ABC 2 + TVP Dokument + TVP HD + TVP Historia + TVP Historia 2 + TVP Info + TVP Kobieta + TVP Kultura + TVP Kultura 2 + TVP Nauka + TVP Regionalna + TVP Rozrywka + TVP Seriale + TVP Sport + TVP Wilno + TVP World + TVR PL + TVS + TVT PL + MTV 80s + Viasat Explore CEE + Vivid Red + VOX + VOX Music TV PL + Warner TV FR + Warner TV PL + Water Planet + WDR Fernsehen Köln + Welt + Welt der Wunder + WP TV + wPolsce PL + Wydarzenia 24 + Xtreme TV + ZDFinfo + ZDFneo + Zoom TV PL + 3SAT + 24 Kitchen + 24Kitchen PT + AMC Break ES + Al Jazeera + AMC Break PT + AMC Crime PT + AMC PT + Antena 3 + ARD-alpha + ARTE FR + ARTV + AXN Movies PT + AXN PT + AXN White PT + BabyTV ES + BBC News Channel + BBC World News + Benfica TV + Biggs + Bloomberg TV + Canal 11 PT + Canal Hollywood PT + Canal Panda + Canal Panda PT + Cartoon Network PT + Cartoonito PT + Casa e Cozinha + Caza y Pesca ES + CBS Reality + CCTV 4 Europe + CGTN + Cinemundo + CMTV + CNBC Europe + CNN Europe + CNN PT + Comedy Central DE + Deutsche Welle English + Deutsche Welle Deutsch + Discovery Channel PT + Discovery Science + TLC PT + Disney Channel PT + Disney Junior PT + Stingray Djazz + DocuBox HD + Sport 1 DE + Eleven Sports 1 PT + Eleven Sports 2 PT + Eleven Sports 3 PT + Eleven Sports 4 PT + Eleven Sports 5 PT + Eleven Sports 6 PT + E! Entertainment + Eurochannel + EuroNews + Eurosport 1 PT + Eurosport 2 PT + Fashion TV + FashionBox HD + Fast&FunBox HD + FightBox HD + FilmBox Arthouse + Food Network + Food Network UK + FOX Comedy PT + FOX Crime PT + FOX Life PT + FOX Movies PT + FOX NEWS + FOX PT + France24 + France 24 French + Fuel TV + FunBox UHD + Gametoon HD + Ginx Esports TV + Canal HISTÓRIA PT + Canal Hollywood + Insight TV + Investigation Discovery + JimJam + KiKA + LUXE TV + M6 + MCM Top + Mezzo + Mezzo Live HD + Motorvision TV + MTV 00s + MTV ES + MTV Live HD + MTV PT + Museum TV + MyZen TV + Nat Geo Wild ES + National Geographic Portugal + The Nautical Channel + Nick Jr. PT + Nickelodeon PT + Nickelodeon Ukraine Pluto + Odisseia + Phoenix + Playboy TV + ProSieben + RAI UNO + RAI DUE + RT Documentary + RTL DE + RTP1 + RTP2 + RTP3 + RTP Açores + RTP Africa + RTP Madeira + RTP Memória + RTP Internacional + Russia Today + Russia Today ES + Sat.1 + SIC + SIC Caras + SIC Internacional + SIC K + SIC Mulher + SIC Noticias + SIC Radical + Sky News + Sport TV+ + Sport TV1.pt + Sport TV2 + Sport TV3 + Sport TV4 + Sport TV5 + Sport TV6 + Stingray CMusic + Stingray iConcerts + Super RTL + Syfy PT + Toros TV + Trace Urban + Travel Channel + TV5 Monde + TV5Monde Europe + TV Cine Action + TV Cine Edition + TV Cine Emotion + TV Cine Top + TVE Internacional + TV Internacional + TVI Ficcao + TVI Reality + VOX + ZDF + ZDFneo + AgroTV RO + Al Jazeera + Al Jazeera Arabic English + AMC RO + Antena1 RO + Antena 3 CNN + Antena Stars RO + ARTE FR + ATV Spirit HU + Auto Motor und Sport + AXN Black RO + AXN RO + AXN Spin RO + AXN White RO + B1 TV RO + BabyTV + Balkanika TV + BBC Earth + BBC First + BBC World News + Bloomberg TV + Bollywood-Classic RO + Bollywood HD RO + Bollywood Film RO + Boomerang + Bucuresti TV RO + Canal 33 RO + Cartoon Network RO + Cartoonito CEE + CBS Reality + CCTV 4 Europe + CGTN + CGTN Documentary + Cinemaraton RO + Cinemax 2 RO + Cinemax RO + Cinethronix RO + CNBC Europe + CNN Europe + Comedy Central Extra BG + Comedy Central Family HU + Comedy Central HU + Comedy Central RO + CoolTV + Credo TV + Crime & Investigation Channel + Da Vinci Learning + Deutsche Welle English + Digi 24 + Digi Animal World RO + Digi Life RO + TV Digi Sport 2 + TV Digi Sport 3 + TV Digi Sport 4 + Digi World RO + Discovery Animal Planet + Discovery Channel + Discovery Science + TLC + Discovery Turbo Extra + Disney Channel RO + Disney Junior + Diva Universal RO + DocuBox HD + Dorcel TV + Dorcel XXX + DuckTV + Duna TV + Duna World + E! Entertainment + Epic Drama (CEE) + Eroxxx HD + Etno TV RO + EuroNews + Eurosport + Eurosport 1 INT + Eurosport 2 INT + Extreme Sports Channel + Fashion TV + Fast&FunBox HD + Favorit TV RO + FEM3 + FightBox HD + Film Cafe RO + Film Now RO + Film+ HU + FilmBox Extra RO + FilmBox Family RO + FilmBox Plus RO + FilmBox Premium RO + FilmBox RO + FilmBox Stars BG + Filmbox Stars HU + The Fishing and Hunting RO + Focus TV + Food Network + Galaxy4 + H!T Music Channel RO + Happy Channel RO + HBO 2 RO + HBO 3 RO + HBO RO + Home & Garden Television + Hír TV + The History Channel + HUSTLER TV + IDA RO + Inedit TV RO + Investigation Discovery + Izaura TV + JimJam + Kanal D RO + Kiss TV RO + Linkpress TV RO + Love Nature + Magyar Televízió 1 + M2 Petőfi + M4 sport + Magic TV BG + ATV HU + Magyar Sláger TV + Mediaset Italia + Medika TV RO + Mezzo + Mezzo Live HD + Minimax HU + Minimax RO + Moldova TV + Mooz Dance + Mooz HD RO + Mooz Hits RO + Mooz Ro RO + Motorvision HD RO + Motorvision TV + MTV 00s + Club MTV International + MTV Europe HU + MTV Hits International + MTV Live HD + MTV Music UK + MTV 90s International + Museum HD RO + Music Channel 1 RO + Muzsika TV + MyZen TV + National 24 Plus RO + Nasul TV RO + National Geographic People RO + Nat Geo Wild RO + National Geographic RO + National TV RO + The Nautical Channel + Nick Junior PL + Nickelodeon Commercial + Nicktoons PL + TV Paprika RO + Polsat Sport Extra + Prima Sport 1 RO + Prima Sport 2 RO + Prima Sport 3 RO + Prima Sport 4 RO + Prima Sport 5 RO + Prima TV RO + Prime + Brazzers TV (ex. Private Spice) + Private TV + Mozi plusz TV + Acasă + ProSieben + Pro Cinema RO + Acasă Gold + PRO TV Internațional + PRO ARENA RO + Profit RO + ProTV + RAI UNO + RAI TRE + Realitatea Plus RO + Reality Kings + România TV + RTL DE + RTL Gold + RTL Ketto + RTL HU + RTLup + Sat.1 + Sky News + Sorozat+ + Speranta TV + Spíler1 TV + Stingray CMusic + Stingray Classica + Stingray iConcerts + Story4 + Super RTL + Super TV2 + Taraf Tv RO + Timeless Drama Channel + TeenNick + TV1000 Russian Kino RO + Orange Sport 1 + Orange Sport 2 + Orange Sport 3 + Orange Sport 4 + Trace Urban + Travel Channel + Travel Mix RO + Travelxp + Trinitas HD RO + TV2 Comedy + TV2 HU + TV2 Kids + TV2 Séf + TV4 HU + TV5Monde Europe + TV1000 Balkan + TV1000 Global Kino + TV Digi Sport 1 + TV Paprika HU + TV SudEst + TVE Internacional + Televiziunea Româna 1 + Televiziunea Româna 2 + TVR3 RO + TVR Cluj RO + TVR Craiova RO + TVR Iasi RO + TVR Tg-Mures RO + TVR Timisoara RO + Televiziunea Româna International + UTV RO + MTV 80s + Viasat Explore CEE + Viasat History + Viasat Nature CEE + VTV RO + Warner TV RO + Zenebutik + Zu TV + 3SAT + 24 Kitchen + Agro TV + Al Jazeera + Al Jazeera Balkans + ALFA TV + Алсат М + AMC SI + Anixe HD Serie + Das Erste + Arena Esport + Arena Fight + ARTE FR + ARTE DE + Alternativna televizija Banja Luka + AXN + AXN Spin + B92 + BabyTV + Balkan trip + Balkanika TV + BBC Earth + BBC First + BBC World News + Radio Televizija BIH + BK TV + Bloomberg TV + Bloomberg Adria + Radio Televizija BN + BN music + BN 2 HD + БНТ 2 + Boomerang + Canale 5 + Cartoon Network + Cartoon Network DE + Cartoonito CEE + CBS Reality + CCTV 4 Europe + CGTN + Cinemax + Cinemax 2 + CineStar Action&Thriller + CineStar Premiere 1 + CineStar Premiere 2 + CineStar TV1 + CineStar TV2 + CineStar TV Comedy Family + CineStar TV Fantasy + English Club TV + Croatian Music Channel + CNBC Europe + CNN Europe + Comedy Central DE + Nicktoons + Crime & Investigation Channel + Da Vinci Learning + Discovery Animal Planet + Discovery Channel + Discovery Science + TLC + Discovery Turbo Extra + Disney Channel + Disney Junior + DM SAT + DocuBox HD + Dorcel TV + Dorcel XXX + Dr. Fit HD + Sport 1 DE + DuckTV + Duna TV + Duna World + Elta 1 HD + E! Entertainment + Epic Drama (CEE) + Erox HD + Eroxxx HD + Eurochannel + EuroNews + Eurosport + Eurosport 2 + EWTN + Exodus TV + Extreme Sports Channel + Fashion TV + FashionBox HD + Fast&FunBox HD + FightBox HD + SK Fight + FilmBox Arthouse + FilmBox Extra RS + FilmBox Stars RS + The Fishing and Hunting + Focus TV + STAR Crime SI + STAR Life SI + STAR Movies SI + STAR SI + France24 + France 2 + France 24 French + Radio Televizija Federacije BIH + GEA TV + Ginx Esports TV + SK Golf + Golica TV + Gorenjska televizija + Grand Televizija + HappyTV + Hayat Folk + Hayat Music + Hayat Plus + Hayat TV + Hayatovci + HBO + HBO3 + HBO2 + Home & Garden Television + The History Channel + History Channel 2 + HIT TV + HRT 1 + HRT 2 + HRT 3 + HRT 4 + HUSTLER TV + IDJ World + Investigation Discovery + Italia 1 + Otvorena televizija + JimJam + Jugoton TV + K::CN 2 Music + Kabel 1 + Канал 5 + Kanal A, SLO + Kanal D + Kanal Rijeka + KiKA + Klape i Tambure TV + KLASIK + K::CN 1 Kopernikus + KTV Ormož + Living HD + Lov i ribolov + LUXE TV + M2 Petőfi + TV Maribor + Mediaset Italia + Mezzo + Mezzo Live HD + Minimax + Minimax SI + Motorvision TV + МРТ 1 + МРТ 2 + МРТ 3 + MTV Europe + MTV 00s + Club MTV International + MTV DE + MTV Hits International + MTV Live HD + MTV 90s International + MyZen TV + N1 BA + N1 HR + N1 RS + NTV DE + Nat Geo Wild SI + National Geographic + National Geographic Channel HD + Nat Geo Wild + The Nautical Channel + NBA TV + MrežaZG + Net TV + Nat Geo Wild HD + Nick Junior + Nickelodeon + Nickelodeon Commercial + NOVA TV + NTV IC Kakanj + O Kanal + OBN + ORF1 + ORF2 + OTV Valentino + Pickbox TV SI + Pikaboo 2 + RTV PINK + RED tv + TV PINK EXTRA + PINK Family + Pink Fashion + PINK Film + Pink Folk 1 + Pink Folk 2 + Pink Kids + Pink Movies + Pink Music 1 + TV PINK PLUS + Pink Reality + Pink Serije + Pink Show + PINK World + PINK Zabava + Planet 2 + Planet Earth + Planet TV SI + Playboy TV + POP TV + Brazzers TV (ex. Private Spice) + Private TV + ProSieben + Prva Srpska TV + Prva World + Ptujska televizija + RAI UNO + RAI DUE + RAI TRE + RAI 3 Bis + RAI Education + RAI Gulp + RAI News 24 + RAI Sport 1 + RAI Storia + Rai Yoyo + Reality Kings + RedLight HD + Rete 4 + Россиᴙ 24 + RTK 1 + RTL + RTL 2 + RTL Zwei + RTL DE + RTL Kockica + RTL Living + RTRS + RTS 1 + RTS 2 + RTS SVET + RTV International + RTV Unsko-sanskog kantona + RTV Tuzlanskog Kantona + Russia Today + Sat.1 + SciFi + ServusTV + Sexation TV + Televizija skupnih internih programov + Сител + Sixx + SK 4K + SK esports + Sky News + RTV Slovenija 1 + RTV Slovenija 2 + RTV Slovenija 3 + SOS Plus + Sport Klub 4 + Sport Klub 5 + Sport Klub 6 + Sport Klub HD + Sportitalia + Sport Klub 3 + Sport Klub 2 Srbija + Stingray iConcerts + ŠTV3 + Super RTL + K::CN 3 Svet Plus + Televizija Alfa + Televizija AS + Telma + Top TV + Toxic TV + Trace Urban + Travel Channel + Travelxp + TV3 + TV 3 Medias + TV5 Monde + TV1000 Balkan + TV ATM + TV Celje + TV Duga + SAT + TV Galeja + TV Idea + TV Jadran + TV Sarajevo + TV Veseljak + TV Vijesti + Televizija Crne Gore 1 + Televizija Crne Gore 2 + Televizija Crne Gore MNE + DIVA (ex. Universal) + Varaždinska Televizija + Vaš kanal + Vavoom + MTV 80s + Viasat Explore CEE + Viasat History + Viasat Nature CEE + Vikom + VOX + VTV Studio + Welt + Woman HD + XXL + Zagrebačka Televizija + ZDF + Zdrava televizija + 1-2-3.tv + 21 Mix + A2 CNN + A Spor + ABC News Albania + Apollon TV + ART Sport 1 + ART Sport 2 + ART Sport 3 + ART Sport 4 + ART Sport 5 + ART Sport 6 + ArtDoku 1 + ArtDoku 2 + ArtKino 1 + ArtKino 2 + ArtKino 3 + ATV TR + BabyTV + Bang Bang + Beyaz TV + Bubble TV + Cartoon Network + Cartoonito CEE + City TV + Click TV + CNBC Europe + CNN Türk TV + Comedy Central Extra UK + Deluxe Music + DigitAlb T HD + Discovery Animal Planet + Discovery Channel + Discovery Turbo UK + Disney Channel + DMAX DE + Elrodi + Euronews Albania + FAX News + Film Autor + FilmBox Extra RS + FilmBox Stars RS + STAR Channel + STAR Life + HSE24 Extra + HSE24 Trend + Info24 Albania + INTV AL + Junior TV + K-Sport 5 + Kabel 1 + Kabel eins Doku + Kanal 7 + Kanal 10 + Kanal D + Kanali 7 + KiKA + Klan Music + Klan Plus + Kopliku TV + MCN TV + DigitAlb Melody TV + My Music + N24 Doku + NTV DE + National Geographic + National Geographic Channel HD + Nat Geo Wild + Ndihma e Klientit + Nickelodeon + Premium Channel + QVC 2 DE + QVC Deutschland + RAI 4 + RAI 5 + RAI Movie + RAI Premium + Rai Yoyo + RTLup + RTS 2 + RTSH Agro + RTSH Femijë + RTSH Film + RTSH Gjirokastra + RTSH Korça + RTSH Kuvend + RTV 21 Popullore + RTV Besa + RTV Ora + Scan TV + Shenja TV + Show TV + Sixx + SuperSport 7 AL + Syri TV + Syri Vizion + Timeless Drama Channel + Tele 5 DE + TGRT Belgesel + Tring Bizarre + Tring Bunga Bunga + Tring Collection + Tring Desire + Tring Kanal 7 + Tring Novelas + Tring Sport 4 HD + Tring Sport 5 HD + TV 7 + TV Dukagjini + VOX up + Welt + ZDFneo + Zico TV + Zjarr TV + MUSE + News 24 + Ora News + Report TV + RTSH 1 + RTSH 2 + RTSH 3 + RTSH 24 + RTSH Plus + RTSH Shkollë + RTSH Shqip + RTSH Sport + Tring Smile + Stinet + STV Folk + SuperSport 1 AL + SuperSport 2 AL + SuperSport 3 AL + SuperSport 4 AL + SuperSport 5 AL + SuperSport 6 AL + Tip TV + Top Channel + Top News + Tring Action + Tring Comedy + Tring History + Tring Jolly HD + Tring Kids + Tring Life + Tring Planet + Tring Shqip + Tring Sport 3 HD + Tring Sport News + Tring Super + Tring Tring + Tring World + Klan TV HD + Vizion Plus + 3SAT + 4Fun Dance + 4Fun Kids + 4FunTV + 24 Kitchen + 24 ВЕСТИ + 360 TuneBox + Agro TV + Al Jazeera + Al Jazeera Balkans + ALFA TV + AMC + AMC HU + ANIXE plus + Das Erste + Arena Sport 9 RS + Arena Sport 10 RS + Aurora TV + AXN + AXN Spin + B1 TV + B92 + BabyTV + Balkan trip + Balkan TV + Balkanika TV + BBC Earth + BBC News Channel + BBC World News + Bit TV + BK TV + BlicTV + Bloomberg TV + Bloomberg Adria + Radio Televizija BN + BN music + BN 2 HD + Boomerang + Brainz TV + Bravo Music + Cartoon Network + Cartoonito CEE + Cartoonito UK + CBS Reality + CCTV 4 Europe + CGTN + CGTN Documentary + Первый + Cinemania TV + Cinemax + Cinemax 2 + Cinemax 2 HU + Cinemax HU + CineStar Action&Thriller RS + CineStar Premiere 1 + CineStar Premiere 2 + CineStar TV2 + CineStar TV Comedy Family + CineStar TV Fantasy + CineStar TV RS + City TV + Class TV Moda + Croatian Music Channel + CNBC Europe + CNN Europe + Nicktoons + Comedy Central HU + Comedy Central UK + CoolTV + Crime & Investigation Channel + Da Vinci Learning + Dajto + Deluxe Music + Deutsche Welle English + Dexy TV + Digi 24 + Discovery Animal Planet + Discovery Channel HU + Discovery Channel + Discovery Science + TLC + Discovery Turbo Extra + Disney Channel + Disney Channel DE + Disney Channel HU + Disney Junior + DMAX DE + DM SAT + DocuBox HD + Dorcel TV + Dorcel XXX + DOX TV + Dr. Fit HD + Sport 1 DE + DuckTV + Duna TV + Duna World + E! Entertainment + Epic Drama (CEE) + Erox HD + Eroxxx HD + Eska TV Extra + Etno TV RO + Eurochannel + EuroNews + Euronews FR + EuroNews Srbija + Eurosport + Eurosport 2 + Eurosport 1 DE + Extreme Sports Channel + FACE TV + Fashion TV + FashionBox HD + Fast&FunBox HD + Favorit TV RO + FEM3 + FightBox HD + SK Fight + Film4 HU + Film Klub + Film Klub Extra + FilmBox Arthouse + FilmBox Extra RS + Filmbox Extra HU + FilmBox Stars RS + FilmBox Premium RS + Filmbox Premium HU + Filmbox Stars HU + Folklorika SK + Food Network + STAR Channel + STAR Crime + STAR Life + STAR Movies + FOX NEWS + France24 + France 24 French + Radio Televizija Federacije BIH + Gametoon HD + Golica TV + Grand Televizija + Grand nostalgija + HappyTV + Hayat Folk + Hayat Music + Hayat Plus + Hayat TV + HBO + HBO 2 HU + HBO3 + HBO 3 HU + HBO2 + HBO HU + Home & Garden Television + Hír TV + The History Channel + History Channel 2 + HSE + HRT 1 + HRT 2 + HRT 3 + HRT 4 + HUSTLER TV + Hype TV + IDJ World + Info24 Albania + Insajder TV + Insta TV + Investigation Discovery + Izaura TV + JimJam + JOJ Plus + JOJ TV + K1 TV + K::CN 2 Music + K-Sport 5 + Kabel 1 + Kabel eins Doku + Kanal 9 TV + Kanal 25 + KiKA + KitchenTV + KLASIK + K::CN 1 Kopernikus + Kurir TV + Lala TV + LifeTV SK + Lov i ribolov + Magyar Televízió 1 + M2 Petőfi + M4 sport + M4 Sport Plus + m5 + Mediaset Italia + Mezzo + Minimax + Minimax HU + Moj Happy Život + Moja Happy Muzika + Moja Happy Zemlja + Moje Happy Društvo + MTV Europe + MTV 00s + Club MTV International + MTV Hits International + MTV Live HD + MTV 90s International + Museum TV + Muzsika TV + N1 HR + N1 RS + N24 Doku + Nasa TV US + National Geographic + National Geographic Channel HD + National Geographic HU + National Geographic RS + Nat Geo Wild + NBA TV + Nat Geo Wild HD + Nick Junior + Nick Junior PL + Nick Music + Nickelodeon Commercial + Nicktoons PL + NOVA TV + Nova Max + Nova S + Nova Series + Nova Sport Srbija + RTV Novi Pazar + Now 90s + NTV 101 Sanski most + O Kanal + OBN + Ozone Network + Pickbox TV RS + Pikaboo + RTV PINK + RED tv + Vesti + Pink Action + Pink Thriller + Pink Crime & Mystery + Pink BH + Pink Classic + Pink Comedy + Pink Erotic 1 + Pink Erotic 2 + Pink Erotic 3 + Pink Erotic 4 + Pink Erotic 5 + Pink Erotic 6 + Pink Erotic 7 + Pink Erotic 8 + TV PINK EXTRA + PINK Family + Pink Fashion + Pink Fight Network + PINK Film + Pink Folk 1 + Pink Folk 2 + Pink Ha Ha + Pink Hits + Pink Hits 2 + Pink Horror + Pink Kids + Pink Koncert + Pink Kuvar + Pink LOL + Pink M + Pink Movies + Pink Romance + Pink SCI FI & Fantasy + Pink Music 1 + Pink and Roll + Pink Parada + Pink Pedia + TV PINK PLUS + Pink Premium + Pink Reality + Pink Serije + Pink Show + Pink Soap + Pink Style + Pink Super Kids + Pink Timeout + Pink Western + PINK World + Pink World Cinema + PINK Zabava + Planet Earth + Planet TV SI + Playboy TV + Brazzers TV (ex. Private Spice) + Private TV + ProSieben + ProSieben MAXX + Prva FILES + Prva KICK + Prva LIFE + Prva MAX + Prva Plus + Prva Srpska TV + Prva World + QVC Deutschland + RAI UNO + RAI DUE + RAI TRE + RAI Education + RAI News 24 + RAI Storia + Reality Kings + Россиᴙ 24 + RT Documentary + RTL + RTL Croatia World + RTL Gold + RTL Három + RTL Nitro + RTLup + RTRS + RTRS PLUS + RTS 1 + RTS 2 + RTS 3 + RTS Drama + RTS Klasika + RTS Kolo + RTS Muzika + RTS Nauka + RTS Poletarac + RTS SVET + RTS Trezor + RTS Život + RTSH 3 + RTSH 24 + RTSH Plus + RTSH Shkollë + RTV HIT Brčko + RTV International + RTV Pančevo + RTVS Dvojka + RTVS Jednotka + Russia Today + Sat.1 + Sat.1 Gold + SAT TV + SciFi + Sixx + SK1 BiH + SK 4K + Sky News + RTV Slovenija 1 + RTV Slovenija 2 + RTV Slovenija 3 + Sorozat+ + SOS Plus + Spektrum Home HU + Sport Klub 7 + Sport Klub 8 + Sport Klub 9 + Sport Klub 10 + Sremska TV + Superstar 2 + Stars TV PL + Stingray Classica + Stingray iConcerts + Studio B + Super RTL + Super TV2 + SuperSat TV + Superstar TV + K::CN 3 Svet Plus + TA3 SK + Tanjug Tačno + TBN Polska + Timeless Drama Channel + Tele 5 DE + Televizija 5 + Televizija Alfa + TLC DE + TOGGO plus + Top TV + Toxic Folk + Toxic Rap + Toxic TV + Trace Urban + Travel Channel + Travelxp + TV2 Séf + TV4 HU + TV5 Monde + TV5Monde Europe + TV1000 Balkan + TV Doma + TV Duga + SAT + Телевизија Храм + TV K23 + TV Markíza SK + RTV Most + TV Paprika HU + TV Ras + TV Vijesti + Televizija Crne Gore MNE + Televizija Doktor + TVR Cluj RO + TVR Craiova RO + TVR Iasi RO + TVR Tg-Mures RO + TVR Timisoara RO + Televiziunea Româna International + UNA TV + DIVA (ex. Universal) + Vavoom + MTV 80s + Viasat Explore CEE + Viasat History + Viasat Nature CEE + RT Vojvodina 1 + RT Vojvodina 2 + VOX + VOX up + Woman HD + Zagrebačka Televizija + ZDF + ZDFinfo + ZDFneo + 24 Kitchen + 24Kitchen TR + 360 TV + A2TV TR + a Haber + a News + A Para + A Spor + Al Jazeera + Al Jazeera Arabic English + ATV TR + BabyTV TR + BBC First + BBC World News + BBN Türk + beIN Box Office 2 TR + beIN Box Office 3 TR + beIN Box Office 1 TR + beIN GURME + beIN HOME & ENTERTAINMENT + beIN iZ + beIN Movies Premiere 2 + beIN Movies Premiere TR + beIN Movies Stars + beIN Movies Turk + beIN Series 1 TR + beIN Series 2 TR + beIN Series 3 TR + beIN Series 4 TR + beIN Sports 1 TR + beIN Sports 2 TR + beIN Sports 3 TR + beIN Sports 4 TR + beIN Sports Haber + beIN Sports MAX 1 TR + beIN Sports MAX 2 TR + beIN TR + Beyaz TV + Bloomberg TV + Bloomberg HT + Boomerang + Boomerang TR + Cartoon Network TR + Cbeebies + CGTN + CGTN Documentary + CNBC Europe + CNN Europe + CNN Türk TV + Nicktoons + Da Vinci Learning + Da Vinci Learning TR + Deutsche Welle English + Discovery Channel TR + Discovery Channel + Discovery Science + TLC + Disney Junior + Dizi Smart Max + Dizi Smart Premium + DMAX TR + DocuBox HD + Dream Türk + Ekotürk + Epic Drama (CEE) + Euro D + Euro Star + EuroNews + Eurosport 2 + Fashion TV + Fast&FunBox HD + FENERBAHÇE TV + FilmBox TR + FOX Turkey + France24 + France 24 French + FX Turkey + Haber Global + Habertürk + Habitat TV + The History Channel + Insight TV + Kanal 7 + KANAL 24 TR + Kanal D + Kanal D TR + Kral Pop TV + KRT TV + Love Nature + MCM FR + MCM Top + Mezzo + MinikaGO TR + MovieSmart Classic + MovieSmart Türk + MTV 00s + MTV Hits International + MTV Live HD + National Geographic Wild TR + National Geographic Turkey + NBA TV + Nick Junior + Number One Türk + NTV TR + Power TV + Power Türk TV + S Sport + S Sport 2 + Show Türk + Show TV + SinemaTV 2 + SinemaTV 1001 + SinemaTV 1002 + SinemaTV Aile + SinemaTV Aile 2 + SinemaTV Aksiyon + SinemaTV Aksiyon 2 + SinemaTV Komedi + SinemaTV Komedi 2 + SinemaTV Yerli + SinemaTV Yerli 2 + SinemaTV + Spor Smart + Spor Smart 2 + Sports TV + Star TV TR + TAY TV + TELE 1 + teve2 + TGRT Belgesel + TGRT EU + TGRT HABER + Tivibu Spor + Tivibu Spor 2 + Tivibu Spor 3 + Tivibu Spor 4 + Tivibu Spor 5 + TLC TR + Trace Urban + TRT 1 + TRT 2 + TRT Spor + TRT 4K + TRT Kurdî + TRT Arapça + TRT Avaz + TRT Belgesel + TRT Çocuk + TRT Diyanet + TRT EBA TV İlkokul + TRT EBA TV Lise + TRT EBA TV Ortaokul + TRT Haber + TRT Müzik + TRT Spor Yıldız + TRT Turk + TRT World + TV5 + TV100 TR + TV 2 TR + TV 8 TR + TV 8.5 + TV Net + Uçankuş TV + Ülke TV + Viasat Explore CEE + Viasat History + Viasat Nature CEE + Yaban TV + diff --git a/sites/web.magentatv.de/web.magentatv.de.config.js b/sites/web.magentatv.de/web.magentatv.de.config.js index 3a38685a..68864329 100644 --- a/sites/web.magentatv.de/web.magentatv.de.config.js +++ b/sites/web.magentatv.de/web.magentatv.de.config.js @@ -1,213 +1,213 @@ -const axios = require('axios') -const dayjs = require('dayjs') -const utc = require('dayjs/plugin/utc') -const customParseFormat = require('dayjs/plugin/customParseFormat') - -let X_CSRFTOKEN -let Cookie -const cookiesToExtract = ['JSESSIONID', 'CSESSIONID', 'CSRFSESSION'] - -dayjs.extend(utc) -dayjs.extend(customParseFormat) - -module.exports = { - site: 'web.magentatv.de', - days: 2, - url: 'https://api.prod.sngtv.magentatv.de/EPG/JSON/PlayBillList', - request: { - method: 'POST', - async headers() { - return await setHeaders() - }, - data({ channel, date }) { - return { - count: -1, - isFillProgram: 1, - offset: 0, - properties: [ - { - include: - 'endtime,genres,id,name,starttime,channelid,pictures,introduce,subName,seasonNum,subNum,cast,country,producedate,externalIds', - name: 'playbill' - } - ], - type: 2, - begintime: date.format('YYYYMMDD000000'), - channelid: channel.site_id, - endtime: date.add(1, 'd').format('YYYYMMDD000000') - } - } - }, - parser({ content }) { - const programs = [] - const items = parseItems(content) - items.forEach(item => { - programs.push({ - title: item.name, - description: item.introduce, - image: parseImage(item), - category: parseCategory(item), - start: parseStart(item), - stop: parseStop(item), - sub_title: item.subName, - season: item.seasonNum, - episode: item.subNum, - directors: parseDirectors(item), - producers: parseProducers(item), - adapters: parseAdapters(item), - country: item.country?.toUpperCase(), - date: item.producedate, - urls: parseUrls(item) - }) - }) - return programs - }, - async channels() { - const url = 'https://api.prod.sngtv.magentatv.de/EPG/JSON/AllChannel' - const body = { - channelNamespace: 2, - filterlist: [ - { - key: 'IsHide', - value: '-1' - } - ], - metaDataVer: 'Channel/1.1', - properties: [ - { - include: '/channellist/logicalChannel/contentId,/channellist/logicalChannel/name', - name: 'logicalChannel' - } - ], - returnSatChannel: 0 - } - const params = { - headers: await setHeaders() - } - - const data = await axios - .post(url, body, params) - .then(r => r.data) - .catch(console.log) - - return data.channellist.map(item => { - return { - lang: 'de', - site_id: item.contentId, - name: item.name - } - }) - } -} - -function parseCategory(item) { - return item.genres - ? item.genres - .replace('und', ',') - .split(',') - .map(i => i.trim()) - : [] -} - -function parseDirectors(item) { - if (!item.cast || !item.cast.director) return [] - return item.cast.director - .replace('und', ',') - .split(',') - .map(i => i.trim()) -} - -function parseProducers(item) { - if (!item.cast || !item.cast.producer) return [] - return item.cast.producer - .replace('und', ',') - .split(',') - .map(i => i.trim()) -} - -function parseAdapters(item) { - if (!item.cast || !item.cast.adaptor) return [] - return item.cast.adaptor - .replace('und', ',') - .split(',') - .map(i => i.trim()) -} - -function parseUrls(item) { - // currently only a imdb id is returned by the api, thus we can construct the url here - if (!item.externalIds) return [] - return JSON.parse(item.externalIds) - .filter(externalId => externalId.type === 'imdb' && externalId.id) - .map(externalId => ({ system: 'imdb', value: `https://www.imdb.com/title/${externalId.id}` })) -} - -function parseImage(item) { - if (!Array.isArray(item.pictures) || !item.pictures.length) return null - - return item.pictures[0].href -} - -function parseStart(item) { - return dayjs.utc(item.starttime, 'YYYY-MM-DD HH:mm:ss') -} - -function parseStop(item) { - return dayjs.utc(item.endtime, 'YYYY-MM-DD HH:mm:ss') -} - -function parseItems(content) { - const data = JSON.parse(content) - if (!data || !Array.isArray(data.playbilllist)) return [] - - return data.playbilllist -} - -async function fetchCookieAndToken() { - // Only fetch the cookies and csrfToken if they are not already set - if (X_CSRFTOKEN && Cookie) { - return - } - - try { - const response = await axios.request({ - url: 'https://api.prod.sngtv.magentatv.de/EPG/JSON/Authenticate', - params: { - SID: 'firstup', - T: 'Windows_chrome_118' - }, - method: 'POST', - data: '{"terminalid":"00:00:00:00:00:00","mac":"00:00:00:00:00:00","terminaltype":"WEBTV","utcEnable":1,"timezone":"Etc/GMT0","userType":3,"terminalvendor":"Unknown"}', - }) - - // Extract the cookies specified in cookiesToExtract - const setCookieHeader = response.headers['set-cookie'] || [] - const extractedCookies = [] - cookiesToExtract.forEach(cookieName => { - const regex = new RegExp(`${cookieName}=(.+?)(;|$)`) - const match = setCookieHeader.find(header => regex.test(header)) - - if (match) { - const cookieString = regex.exec(match)[0] - extractedCookies.push(cookieString) - } - }) - - // check if we recieved a csrfToken only then store the values - if (!response.data.csrfToken) { - console.log('csrfToken not found in the response.') - return - } - - X_CSRFTOKEN = response.data.csrfToken - Cookie = extractedCookies.join(' ') - - } catch(error) { - console.error(error) - } -} - -async function setHeaders() { - await fetchCookieAndToken() - - return { X_CSRFTOKEN, Cookie } -} +const axios = require('axios') +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +const customParseFormat = require('dayjs/plugin/customParseFormat') + +let X_CSRFTOKEN +let Cookie +const cookiesToExtract = ['JSESSIONID', 'CSESSIONID', 'CSRFSESSION'] + +dayjs.extend(utc) +dayjs.extend(customParseFormat) + +module.exports = { + site: 'web.magentatv.de', + days: 2, + url: 'https://api.prod.sngtv.magentatv.de/EPG/JSON/PlayBillList', + request: { + method: 'POST', + async headers() { + return await setHeaders() + }, + data({ channel, date }) { + return { + count: -1, + isFillProgram: 1, + offset: 0, + properties: [ + { + include: + 'endtime,genres,id,name,starttime,channelid,pictures,introduce,subName,seasonNum,subNum,cast,country,producedate,externalIds', + name: 'playbill' + } + ], + type: 2, + begintime: date.format('YYYYMMDD000000'), + channelid: channel.site_id, + endtime: date.add(1, 'd').format('YYYYMMDD000000') + } + } + }, + parser({ content }) { + const programs = [] + const items = parseItems(content) + items.forEach(item => { + programs.push({ + title: item.name, + description: item.introduce, + image: parseImage(item), + category: parseCategory(item), + start: parseStart(item), + stop: parseStop(item), + sub_title: item.subName, + season: item.seasonNum, + episode: item.subNum, + directors: parseDirectors(item), + producers: parseProducers(item), + adapters: parseAdapters(item), + country: item.country?.toUpperCase(), + date: item.producedate, + urls: parseUrls(item) + }) + }) + return programs + }, + async channels() { + const url = 'https://api.prod.sngtv.magentatv.de/EPG/JSON/AllChannel' + const body = { + channelNamespace: 2, + filterlist: [ + { + key: 'IsHide', + value: '-1' + } + ], + metaDataVer: 'Channel/1.1', + properties: [ + { + include: '/channellist/logicalChannel/contentId,/channellist/logicalChannel/name', + name: 'logicalChannel' + } + ], + returnSatChannel: 0 + } + const params = { + headers: await setHeaders() + } + + const data = await axios + .post(url, body, params) + .then(r => r.data) + .catch(console.log) + + return data.channellist.map(item => { + return { + lang: 'de', + site_id: item.contentId, + name: item.name + } + }) + } +} + +function parseCategory(item) { + return item.genres + ? item.genres + .replace('und', ',') + .split(',') + .map(i => i.trim()) + : [] +} + +function parseDirectors(item) { + if (!item.cast || !item.cast.director) return [] + return item.cast.director + .replace('und', ',') + .split(',') + .map(i => i.trim()) +} + +function parseProducers(item) { + if (!item.cast || !item.cast.producer) return [] + return item.cast.producer + .replace('und', ',') + .split(',') + .map(i => i.trim()) +} + +function parseAdapters(item) { + if (!item.cast || !item.cast.adaptor) return [] + return item.cast.adaptor + .replace('und', ',') + .split(',') + .map(i => i.trim()) +} + +function parseUrls(item) { + // currently only a imdb id is returned by the api, thus we can construct the url here + if (!item.externalIds) return [] + return JSON.parse(item.externalIds) + .filter(externalId => externalId.type === 'imdb' && externalId.id) + .map(externalId => ({ system: 'imdb', value: `https://www.imdb.com/title/${externalId.id}` })) +} + +function parseImage(item) { + if (!Array.isArray(item.pictures) || !item.pictures.length) return null + + return item.pictures[0].href +} + +function parseStart(item) { + return dayjs.utc(item.starttime, 'YYYY-MM-DD HH:mm:ss') +} + +function parseStop(item) { + return dayjs.utc(item.endtime, 'YYYY-MM-DD HH:mm:ss') +} + +function parseItems(content) { + const data = JSON.parse(content) + if (!data || !Array.isArray(data.playbilllist)) return [] + + return data.playbilllist +} + +async function fetchCookieAndToken() { + // Only fetch the cookies and csrfToken if they are not already set + if (X_CSRFTOKEN && Cookie) { + return + } + + try { + const response = await axios.request({ + url: 'https://api.prod.sngtv.magentatv.de/EPG/JSON/Authenticate', + params: { + SID: 'firstup', + T: 'Windows_chrome_118' + }, + method: 'POST', + data: '{"terminalid":"00:00:00:00:00:00","mac":"00:00:00:00:00:00","terminaltype":"WEBTV","utcEnable":1,"timezone":"Etc/GMT0","userType":3,"terminalvendor":"Unknown"}', + }) + + // Extract the cookies specified in cookiesToExtract + const setCookieHeader = response.headers['set-cookie'] || [] + const extractedCookies = [] + cookiesToExtract.forEach(cookieName => { + const regex = new RegExp(`${cookieName}=(.+?)(;|$)`) + const match = setCookieHeader.find(header => regex.test(header)) + + if (match) { + const cookieString = regex.exec(match)[0] + extractedCookies.push(cookieString) + } + }) + + // check if we recieved a csrfToken only then store the values + if (!response.data.csrfToken) { + console.log('csrfToken not found in the response.') + return + } + + X_CSRFTOKEN = response.data.csrfToken + Cookie = extractedCookies.join(' ') + + } catch(error) { + console.error(error) + } +} + +async function setHeaders() { + await fetchCookieAndToken() + + return { X_CSRFTOKEN, Cookie } +} diff --git a/tests/commands/channels/lint.test.ts b/tests/commands/channels/lint.test.ts index 61b9f53b..38b2ba6b 100644 --- a/tests/commands/channels/lint.test.ts +++ b/tests/commands/channels/lint.test.ts @@ -1,83 +1,83 @@ -import { execSync } from 'child_process' - -type ExecError = { - status: number - stdout: string -} - -describe('channels:lint', () => { - it('will show a message if the file contains a syntax error', () => { - try { - const cmd = 'npm run channels:lint --- tests/__data__/input/channels_lint/error.channels.xml' - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - process.exit(1) - } catch (error) { - expect((error as ExecError).status).toBe(1) - expect((error as ExecError).stdout).toContain( - "error.channels.xml\n 3:0 Element 'channel': The attribute 'lang' is required but missing.\n\n1 error(s)\n" - ) - } - }) - - it('will show a message if an error occurred while parsing an xml file', () => { - try { - const cmd = - 'npm run channels:lint --- tests/__data__/input/channels_lint/invalid.channels.xml' - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - process.exit(1) - } catch (error) { - expect((error as ExecError).status).toBe(1) - expect((error as ExecError).stdout).toContain( - 'invalid.channels.xml\n 2:6 XML declaration allowed only at the start of the document\n' - ) - } - }) - - it('can test multiple files at ones', () => { - try { - const cmd = - 'npm run channels:lint --- tests/__data__/input/channels_lint/error.channels.xml tests/__data__/input/channels_lint/invalid.channels.xml' - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - process.exit(1) - } catch (error) { - expect((error as ExecError).status).toBe(1) - expect((error as ExecError).stdout).toContain( - "error.channels.xml\n 3:0 Element 'channel': The attribute 'lang' is required but missing.\n" - ) - expect((error as ExecError).stdout).toContain( - 'invalid.channels.xml\n 2:6 XML declaration allowed only at the start of the document\n' - ) - expect((error as ExecError).stdout).toContain('2 error(s)') - } - }) - - it('will show a message if the file contains single quotes', () => { - try { - const cmd = - 'npm run channels:lint --- tests/__data__/input/channels_lint/single_quotes.channels.xml' - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - process.exit(1) - } catch (error) { - expect((error as ExecError).status).toBe(1) - expect((error as ExecError).stdout).toContain('single_quotes.channels.xml') - expect((error as ExecError).stdout).toContain( - '1:14 Single quotes cannot be used in attributes' - ) - } - }) - - it('does not display errors if there are none', () => { - try { - const cmd = 'npm run channels:lint --- tests/__data__/input/channels_lint/valid.channels.xml' - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - } catch (error) { - if (process.env.DEBUG === 'true') console.log((error as ExecError).stdout) - process.exit(1) - } - }) -}) +import { execSync } from 'child_process' + +interface ExecError { + status: number + stdout: string +} + +describe('channels:lint', () => { + it('will show a message if the file contains a syntax error', () => { + try { + const cmd = 'npm run channels:lint --- tests/__data__/input/channels_lint/error.channels.xml' + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + process.exit(1) + } catch (error) { + expect((error as ExecError).status).toBe(1) + expect((error as ExecError).stdout).toContain( + "error.channels.xml\n 3:0 Element 'channel': The attribute 'lang' is required but missing.\n\n1 error(s)\n" + ) + } + }) + + it('will show a message if an error occurred while parsing an xml file', () => { + try { + const cmd = + 'npm run channels:lint --- tests/__data__/input/channels_lint/invalid.channels.xml' + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + process.exit(1) + } catch (error) { + expect((error as ExecError).status).toBe(1) + expect((error as ExecError).stdout).toContain( + 'invalid.channels.xml\n 2:6 XML declaration allowed only at the start of the document\n' + ) + } + }) + + it('can test multiple files at ones', () => { + try { + const cmd = + 'npm run channels:lint --- tests/__data__/input/channels_lint/error.channels.xml tests/__data__/input/channels_lint/invalid.channels.xml' + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + process.exit(1) + } catch (error) { + expect((error as ExecError).status).toBe(1) + expect((error as ExecError).stdout).toContain( + "error.channels.xml\n 3:0 Element 'channel': The attribute 'lang' is required but missing.\n" + ) + expect((error as ExecError).stdout).toContain( + 'invalid.channels.xml\n 2:6 XML declaration allowed only at the start of the document\n' + ) + expect((error as ExecError).stdout).toContain('2 error(s)') + } + }) + + it('will show a message if the file contains single quotes', () => { + try { + const cmd = + 'npm run channels:lint --- tests/__data__/input/channels_lint/single_quotes.channels.xml' + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + process.exit(1) + } catch (error) { + expect((error as ExecError).status).toBe(1) + expect((error as ExecError).stdout).toContain('single_quotes.channels.xml') + expect((error as ExecError).stdout).toContain( + '1:14 Single quotes cannot be used in attributes' + ) + } + }) + + it('does not display errors if there are none', () => { + try { + const cmd = 'npm run channels:lint --- tests/__data__/input/channels_lint/valid.channels.xml' + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + } catch (error) { + if (process.env.DEBUG === 'true') console.log((error as ExecError).stdout) + process.exit(1) + } + }) +}) diff --git a/tests/commands/channels/validate.test.ts b/tests/commands/channels/validate.test.ts index 4dd18b37..3a1527c3 100644 --- a/tests/commands/channels/validate.test.ts +++ b/tests/commands/channels/validate.test.ts @@ -1,70 +1,70 @@ -import { execSync } from 'child_process' - -type ExecError = { - status: number - stdout: string -} - -const ENV_VAR = 'cross-env DATA_DIR=tests/__data__/input/__data__' - -describe('channels:validate', () => { - it('will show a message if the file contains a duplicate', () => { - try { - const cmd = `${ENV_VAR} npm run channels:validate --- tests/__data__/input/channels_validate/duplicate.channels.xml` - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - process.exit(1) - } catch (error) { - expect((error as ExecError).status).toBe(1) - expect((error as ExecError).stdout).toContain(` -┌─────────┬─────────────┬──────┬─────────────────┬─────────┬─────────┐ -│ (index) │ type │ lang │ xmltv_id │ site_id │ name │ -├─────────┼─────────────┼──────┼─────────────────┼─────────┼─────────┤ -│ 0 │ 'duplicate' │ 'en' │ 'Bravo.us@East' │ '140' │ 'Bravo' │ -└─────────┴─────────────┴──────┴─────────────────┴─────────┴─────────┘ - -1 error(s) in 1 file(s) -`) - } - }) - - it('will show a message if the file contains a channel with wrong channel id', () => { - try { - const cmd = `${ENV_VAR} npm run channels:validate --- tests/__data__/input/channels_validate/wrong_channel_id.channels.xml` - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - process.exit(1) - } catch (error) { - expect((error as ExecError).status).toBe(1) - expect((error as ExecError).stdout).toContain(` -┌─────────┬────────────────────┬──────┬────────────────────┬─────────┬─────────────────────┐ -│ (index) │ type │ lang │ xmltv_id │ site_id │ name │ -├─────────┼────────────────────┼──────┼────────────────────┼─────────┼─────────────────────┤ -│ 0 │ 'wrong_channel_id' │ 'en' │ 'CNNInternational' │ '140' │ 'CNN International' │ -└─────────┴────────────────────┴──────┴────────────────────┴─────────┴─────────────────────┘ - -1 error(s) in 1 file(s) -`) - } - }) - - it('will show a message if the file contains a channel with wrong feed id', () => { - try { - const cmd = `${ENV_VAR} npm run channels:validate --- tests/__data__/input/channels_validate/wrong_feed_id.channels.xml` - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - process.exit(1) - } catch (error) { - expect((error as ExecError).status).toBe(1) - expect((error as ExecError).stdout).toContain(` -┌─────────┬─────────────────┬──────┬─────────────────┬─────────┬─────────┐ -│ (index) │ type │ lang │ xmltv_id │ site_id │ name │ -├─────────┼─────────────────┼──────┼─────────────────┼─────────┼─────────┤ -│ 0 │ 'wrong_feed_id' │ 'en' │ 'Bravo.us@West' │ '150' │ 'Bravo' │ -└─────────┴─────────────────┴──────┴─────────────────┴─────────┴─────────┘ - -1 error(s) in 1 file(s) -`) - } - }) -}) +import { execSync } from 'child_process' + +interface ExecError { + status: number + stdout: string +} + +const ENV_VAR = 'cross-env DATA_DIR=tests/__data__/input/__data__' + +describe('channels:validate', () => { + it('will show a message if the file contains a duplicate', () => { + try { + const cmd = `${ENV_VAR} npm run channels:validate --- tests/__data__/input/channels_validate/duplicate.channels.xml` + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + process.exit(1) + } catch (error) { + expect((error as ExecError).status).toBe(1) + expect((error as ExecError).stdout).toContain(` +┌─────────┬─────────────┬──────┬─────────────────┬─────────┬─────────┐ +│ (index) │ type │ lang │ xmltv_id │ site_id │ name │ +├─────────┼─────────────┼──────┼─────────────────┼─────────┼─────────┤ +│ 0 │ 'duplicate' │ 'en' │ 'Bravo.us@East' │ '140' │ 'Bravo' │ +└─────────┴─────────────┴──────┴─────────────────┴─────────┴─────────┘ + +1 error(s) in 1 file(s) +`) + } + }) + + it('will show a message if the file contains a channel with wrong channel id', () => { + try { + const cmd = `${ENV_VAR} npm run channels:validate --- tests/__data__/input/channels_validate/wrong_channel_id.channels.xml` + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + process.exit(1) + } catch (error) { + expect((error as ExecError).status).toBe(1) + expect((error as ExecError).stdout).toContain(` +┌─────────┬────────────────────┬──────┬────────────────────┬─────────┬─────────────────────┐ +│ (index) │ type │ lang │ xmltv_id │ site_id │ name │ +├─────────┼────────────────────┼──────┼────────────────────┼─────────┼─────────────────────┤ +│ 0 │ 'wrong_channel_id' │ 'en' │ 'CNNInternational' │ '140' │ 'CNN International' │ +└─────────┴────────────────────┴──────┴────────────────────┴─────────┴─────────────────────┘ + +1 error(s) in 1 file(s) +`) + } + }) + + it('will show a message if the file contains a channel with wrong feed id', () => { + try { + const cmd = `${ENV_VAR} npm run channels:validate --- tests/__data__/input/channels_validate/wrong_feed_id.channels.xml` + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + process.exit(1) + } catch (error) { + expect((error as ExecError).status).toBe(1) + expect((error as ExecError).stdout).toContain(` +┌─────────┬─────────────────┬──────┬─────────────────┬─────────┬─────────┐ +│ (index) │ type │ lang │ xmltv_id │ site_id │ name │ +├─────────┼─────────────────┼──────┼─────────────────┼─────────┼─────────┤ +│ 0 │ 'wrong_feed_id' │ 'en' │ 'Bravo.us@West' │ '150' │ 'Bravo' │ +└─────────┴─────────────────┴──────┴─────────────────┴─────────┴─────────┘ + +1 error(s) in 1 file(s) +`) + } + }) +})