mirror of
https://github.com/anthonyaxenov/iptv.git
synced 2025-01-24 02:06:09 +00:00
Большое обновление
- проект переписан на flight + twig, laravel-like хелперы - docker-окружение - новая страница с подробностями о плейлисте - улучшен json о плейлисте - нормальный роутинг - нормальная статусная система - попытка перекодировки при не utf-8 + предупреждение об этом - дополнены FAQ + README
This commit is contained in:
parent
649ab85d79
commit
c43439b9cc
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,7 +1,12 @@
|
||||
/.idea
|
||||
/.vscode
|
||||
/downloaded
|
||||
/src/cache/*
|
||||
/src/vendor
|
||||
*.log
|
||||
.env
|
||||
*.m3u
|
||||
*.m3u.*
|
||||
*.m3u8
|
||||
*.m3u8.*
|
||||
!/**/.gitkeep
|
||||
|
245
README.md
245
README.md
@ -1,97 +1,200 @@
|
||||
# Список самообновляемых плейлистов для IPTV
|
||||
# Автообновляемые IPTV-плейлисты
|
||||
|
||||
- [Список самообновляемых плейлистов для IPTV](#список-самообновляемых-плейлистов-для-iptv)
|
||||
- [Как использовать этот список?](#как-использовать-этот-список)
|
||||
- [Как добавить плейлист в этот список?](#как-добавить-плейлист-в-этот-список)
|
||||
- [API](#api)
|
||||
- [Формат `playlists.ini`](#формат-playlistsini)
|
||||
- [Дополнительные инструменты (`./tools`)](#дополнительные-инструменты-tools)
|
||||
- [Как создать свой собственный плейлист](#как-создать-свой-собственный-плейлист)
|
||||
- [Лицензия](#лицензия)
|
||||
> **Web-версия**: [https://iptv.axenov.dev/](https://iptv.axenov.dev/)
|
||||
> **FAQ**: [https://iptv.axenov.dev/faq](https://iptv.axenov.dev/faq)
|
||||
> **Зеркало репозитория**: https://git.axenov.dev/anthony/iptv
|
||||
|
||||
Проект, содержащий в себе инструменты для работы с IPTV-плейлистами:
|
||||
|
||||
* список автообновляемых плейлистов, которые найдены в открытых источниках;
|
||||
* скрипты для поиска каналов в этом списке, создания своего плейлиста;
|
||||
* веб-сервис, предоставляющий короткие ссылки на эти плейлисты и отображающий список каналов.
|
||||
|
||||
Плейлисты подбираются преимущественно для РФ и любых стран бывшего СНГ, но этими странами список не ограничивается.
|
||||
|
||||
Поддержкой этих плейлистов занимаются сервисы и ресурсы, указанные как источник.
|
||||
Вопросы работоспособности плейлистов адресуйте тем, кто несёт за них ответственность.
|
||||
|
||||
Они бесплатны для использования.
|
||||
Список проверяется и обновляется мной вручную.
|
||||
Гарантию работоспособности никто не даёт.
|
||||
|
||||
## English description
|
||||
|
||||
> **Mirrored repo**: https://git.axenov.dev/anthony/iptv
|
||||
|
||||
This repo contains IPTV-playlists free to use with your media-player.
|
||||
|
||||
Most of them are in russian or CIS languages but you can find something interesting here for yourself.
|
||||
|
||||
Also there are some handy tools to make your own playlist or find channels you want in playlists listed here.
|
||||
|
||||
You can use this repo according to [LICENSE](LICENSE) conditions.
|
||||
|
||||
I'm too lazy to translate and support the whole project in ru and en, sorry, guys.
|
||||
|
||||
---
|
||||
|
||||
> **[Перейти на актуальную сраницу](https://iptv.axenov.dev/)**
|
||||
## Содержание
|
||||
|
||||
Здесь собраны ссылки на IPTV-плейлисты, которые находятся в открытом доступе.
|
||||
- [Как использовать этот список?](#howtouse)
|
||||
- [Формат playlists.ini](#iniformat)
|
||||
- [API](#api)
|
||||
- [Развёртывание проекта](#deploy)
|
||||
- [Дополнительные инструменты](#tools)
|
||||
- [Как создать свой собственный плейлист](#howtomake)
|
||||
- [Использованный стек](#stack)
|
||||
- [Лицензия](#license)
|
||||
|
||||
Они бесплатны для использования. Список проверяется и обновляется мной вручную.
|
||||
---
|
||||
|
||||
Поддержкой этих плейлистов занимаются сервисы и ресурсы, указанные как источник.
|
||||
|
||||
Вопросы работоспособности плейлистов адресуйте тем, кто несёт за них ответственность.
|
||||
<a id="howtouse"></a>
|
||||
|
||||
## Как использовать этот список?
|
||||
|
||||
Чтобы подключить плейлист, нужно в настройках IPTV-плеера указать ссылку в следующем формате:
|
||||
Чтобы подключить плейлист, нужно в настройках медиаплеера указать ссылку в следующем формате:
|
||||
|
||||
```
|
||||
iptv.axenov.dev?ID
|
||||
iptv.axenov.dev/<ID>
|
||||
iptv.axenov.dev?<ID> (устаревший формат)
|
||||
iptv.axenov.dev/?<ID> (устаревший формат)
|
||||
```
|
||||
|
||||
где `ID` - один из идентификаторов, указанных в [`playlists.ini`](playlists.ini) в квадратных скобках.
|
||||
|
||||
## Как добавить плейлист в этот список?
|
||||
|
||||
1) Склонировать себе репозиторий, создать ветку
|
||||
2) Внести изменения в файл [`playlists.ini`](playlists.ini) как описано ниже
|
||||
3) Сделать коммит, отправить изменения в свой репозиторий и создать merge-request
|
||||
где `<ID>` - один из идентификаторов, указанных в [`playlists.ini`](playlists.ini) в квадратных скобках.
|
||||
|
||||
Либо провернуть всё то же самое через браузер.
|
||||
|
||||
<a id="iniformat"></a>
|
||||
|
||||
## Формат `playlists.ini`
|
||||
|
||||
```ini
|
||||
# В квадратных скобках - ID плейлиста в рамках этого
|
||||
# конфига (обязателен). Для удобства ввода с пульта,
|
||||
# для ID рекомендуется число или короткая строка без
|
||||
# пробелов и др. спецсимволов.
|
||||
[1]
|
||||
|
||||
# Название плейлиста (необязательно)
|
||||
name = 'Рабочий и актуальный IPTV плейлист M3U'
|
||||
|
||||
# Краткое описание из источника или от себя (необязательно)
|
||||
desc = 'В этом IPTV плейлисте вы найдете очень много каналов в HD качестве'
|
||||
|
||||
# Прямая ссылка на m3u/m3u8 плейлист (обязательно)
|
||||
pls = 'https://example.com/pls.m3u'
|
||||
|
||||
# Ссылка на источник, откуда взят плейлист (необязательно)
|
||||
src = 'https://example.com/super-duper-playlist'
|
||||
|
||||
[2]
|
||||
|
||||
# ID другого плейлиста в этом списке, на который
|
||||
# произойдёт редирект. Нужен для мягкой смены ID.
|
||||
redirect = 1
|
||||
```
|
||||
|
||||
В описании плейлиста обязательны:
|
||||
|
||||
* любой желаемый ID в квадратных скобках;
|
||||
* либо `pls`, либо `redirect` (если указаны оба, то `redirect` приоритетен).
|
||||
|
||||
Плейлистов с редиректами может быть сколько угодно, но они не должны быть цикличными.
|
||||
|
||||
<a id="api"></a>
|
||||
|
||||
## API
|
||||
|
||||
Можно получать состояние плейлистов из этого сборника при помощи метода:
|
||||
|
||||
```
|
||||
GET https://iptv.axenov.dev/?getinfo=<ID>
|
||||
GET https://iptv.axenov.dev/<ID>/json
|
||||
```
|
||||
|
||||
где `ID` - один из идентификаторов, указанных в [`playlists.ini`](playlists.ini) в квадратных скобках.
|
||||
где `ID` -- один из идентификаторов, указанных в [`playlists.ini`](playlists.ini) в квадратных скобках.
|
||||
|
||||
Ответом может быть JSON следующего содержания:
|
||||
В случае успеха вернётся JSON следующего содержания:
|
||||
|
||||
```json
|
||||
{
|
||||
"is_online": true,
|
||||
"count": 123,
|
||||
"channels": [ ... ]
|
||||
"id": "p1",
|
||||
"url": "localhost:8080/p1",
|
||||
"name": "Каналы в SD и HD качестве (smarttvnews.ru)",
|
||||
"desc": "Рабочий и актуальный IPTV плейлист M3U — на июнь 2022 года",
|
||||
"pls": "https://smarttvnews.ru/apps/iptvchannels.m3u",
|
||||
"src": "https://smarttvnews.ru/rabochiy-i-aktualnyiy-iptv-pleylist-m3u-kanalyi-v-sd-i-hd-kachestve/",
|
||||
"status": "online",
|
||||
"encoding": {
|
||||
"name": "UTF-8",
|
||||
"alert": false
|
||||
},
|
||||
"channels": [
|
||||
"Channel1",
|
||||
"Channel2",
|
||||
"ChannelX"
|
||||
],
|
||||
"count": 3
|
||||
}
|
||||
```
|
||||
|
||||
где:
|
||||
* `is_online` - `bool`, доступность плейлиста
|
||||
* `count` - `uint|char[1]`, количество каналов >=0 либо `'-'` при `is_online === false`
|
||||
* `channels` - `string[]`, массив строк с названиями каналов, может быть пустым.
|
||||
|
||||
Также ответ может быть пустым (вообще пустым, даже не `null`).
|
||||
Такое я встречал с одним конкретном плейлисте с поехавшей кодировкой.
|
||||
Лень разбираться, пофиг.
|
||||
* `id` -- название плейлиста
|
||||
* `name` -- краткое описание из источника или от себя
|
||||
* `url` -- короткая ссылка, которую можно использовать для добавления плейлиста в плеер
|
||||
* `desc` -- подробное описание плейлиста
|
||||
* `pls` -- прямая ссылка на m3u/m3u8 плейлист
|
||||
* `src` -- ссылка на источник, откуда взят плейлист
|
||||
* `status` -- признак доступности плейлиста (`online`, `timeout`, `offline`, `unknown`)
|
||||
* `encoding` -- данные о кодировке файла плейлиста
|
||||
* `name` -- название кодировки (на данный момент определяются только `UTF-8` или `Windows-1251`)
|
||||
* `alert` -- признак отличия кодировки от `UTF-8`, названия каналов сконвертированы в `UTF-8`
|
||||
* `channels` -- массив названий каналов
|
||||
* `count` -- количество каналов >= 0
|
||||
|
||||
## Формат `playlists.ini`
|
||||
> Название кодировки `encoding.name` может определяться неточно!
|
||||
|
||||
```ini
|
||||
; В квадратных скобках - ID плейлиста в рамках этого
|
||||
; конфига (обязателен). Для удобства ввода с пульта,
|
||||
; для ID рекомендуется число или короткая строка без
|
||||
; пробелов и др. спецсимволов.
|
||||
[p1]
|
||||
; Название плейлиста (необязательно)
|
||||
name='webarmen.com 18+'
|
||||
; Краткое описание из источника или от себя (необязательно)
|
||||
desc=''
|
||||
; Прямая ссылка на m3u/m3u8 плейлист (обязательно)
|
||||
pls='https://webarmen.com/my/iptv/auto.xxx.m3u'
|
||||
; Ссылка на источник, откуда взят плейлист (необязательно)
|
||||
src='https://webarmen.com/my/iptv/xxx.php'
|
||||
В случае ошибки вернётся JSON в следующем формате:
|
||||
|
||||
[p2]
|
||||
; ID другого плейлиста в этом списке, на который
|
||||
; произойдёт редирект (нужно для мягкой смены ID).
|
||||
; Необязателен, но если указан, то приоритетнее, чем pls.
|
||||
redirect=p1
|
||||
```json
|
||||
{
|
||||
"id": "p1",
|
||||
"url": "localhost:8080/p1",
|
||||
"name": "Каналы в SD и HD качестве (smarttvnews.ru)",
|
||||
"desc": "Рабочий и актуальный IPTV плейлист M3U — на июнь 2022 года",
|
||||
"pls": "https://smarttvnews.ru/apps/iptvchannels.m3u",
|
||||
"src": "https://smarttvnews.ru/rabochiy-i-aktualnyiy-iptv-pleylist-m3u-kanalyi-v-sd-i-hd-kachestve/",
|
||||
"status": "offline",
|
||||
"error": {
|
||||
"code": 22,
|
||||
"message": "The requested URL returned error: 404 Not Found"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
где:
|
||||
|
||||
* `id` -- название плейлиста
|
||||
* `name` -- краткое описание из источника или от себя
|
||||
* `url` -- короткая ссылка, которую можно использовать для добавления плейлиста в плеер
|
||||
* `desc` -- подробное описание плейлиста
|
||||
* `pls` -- прямая ссылка на m3u/m3u8 плейлист
|
||||
* `src` -- ссылка на источник, откуда взят плейлист
|
||||
* `status` -- признак доступности плейлиста (`online`, `timeout`, `offline`, `error`)
|
||||
* `error` -- данные о кодировке файла плейлиста
|
||||
* `code` -- [код ошибки curl](https://curl.se/libcurl/c/libcurl-errors.html)
|
||||
* `message` -- текст ошибки curl
|
||||
|
||||
<a id="deploy"></a>
|
||||
|
||||
## Развёртывание проекта
|
||||
|
||||
1. Выполнить `cp .env.example .env`, установить необходимые параметры
|
||||
2. Выполнить `docker compose up -d --build`
|
||||
3. Открыть `https://<APP_URL>:8080`
|
||||
|
||||
<a id="tools"></a>
|
||||
|
||||
## Дополнительные инструменты (`./tools`)
|
||||
|
||||
### `download-all.sh`
|
||||
@ -102,7 +205,7 @@ redirect=p1
|
||||
|
||||
Проверяет каждый канал в плейлисте на доступность и выводит результат проверки.
|
||||
|
||||
Поддерживаются \*.m3u и \*.m3u8; как локальные файлы, так по прямым ссылкам.
|
||||
Поддерживаются `*.m3u` и `*.m3u8`; как локальные файлы, так по прямым ссылкам.
|
||||
|
||||
Коды ошибок доступны [здесь](https://everything.curl.dev/usingcurl/returns).
|
||||
|
||||
@ -139,9 +242,9 @@ Check stats
|
||||
|
||||
### `find-in-pls.sh`
|
||||
|
||||
Находит каналы по заданному регулярному выражению в указанном плейлисте.
|
||||
Находит каналы по заданному регулярному выражению в одном указанном плейлисте.
|
||||
|
||||
Поддерживаются \*.m3u и \*.m3u8; как локальные файлы, так по прямым ссылкам.
|
||||
Поддерживаются `*.m3u` и `*.m3u8`; как локальные файлы, так по прямым ссылкам.
|
||||
|
||||
Пример:
|
||||
|
||||
@ -165,7 +268,7 @@ Found: 2
|
||||
|
||||
### `find-in-all.sh`
|
||||
|
||||
Находит каналы по заданному регулярному выражению в плейлистах, скачанных через `download-all.sh`.
|
||||
Находит каналы по заданному регулярному выражению во всех плейлистах, скачанных через `download-all.sh`.
|
||||
|
||||
Пример:
|
||||
|
||||
@ -199,9 +302,10 @@ Nothing found
|
||||
|
||||
### `make-pls.sh`
|
||||
|
||||
Находит каналы по заданному регулярному выражению в плейлистах, скачанных через `download-all.sh`.
|
||||
Находит каналы по заданному регулярному выражению во всех плейлистах, скачанных через `download-all.sh`.
|
||||
|
||||
Отличается от `find-in-all.sh` тем, что тот выводит результат в человекочитаемом формате, а этот -- в готовом m3u формате для сохранения в файл.
|
||||
Отличается от `find-in-all.sh` тем, что тот выводит результат в человекочитаемом формате, а этот -- в готовом m3u
|
||||
формате для сохранения в файл.
|
||||
|
||||
Пример:
|
||||
|
||||
@ -222,6 +326,7 @@ http://live02-cdn.tv.ti.ru:80/dtv/id376_NBN_SG--Fox_HD/04/plst.m3u8
|
||||
...
|
||||
```
|
||||
|
||||
<a id="howtomake"></a>
|
||||
## Как создать свой собственный плейлист?
|
||||
|
||||
1. Скачать все плейлисты, указанные в [`playlists.ini`](playlists.ini):
|
||||
@ -232,7 +337,8 @@ http://live02-cdn.tv.ti.ru:80/dtv/id376_NBN_SG--Fox_HD/04/plst.m3u8
|
||||
```
|
||||
$ ./tools/make-pls.sh "(fox|disney)" > my.m3u8
|
||||
```
|
||||
Так в плейлисте `./my.m3u8` окажутся все каналы из скачанных плейлистов, в названиях которых встрелись `fox` или `disney`.
|
||||
Так в плейлисте `./my.m3u8` окажутся все каналы из скачанных плейлистов, в названиях которых встретились `fox`
|
||||
или `disney`.
|
||||
3. Проверить доступность каналов в полученном плейлисте:
|
||||
```
|
||||
$ ./tools/check-pls.sh my.m3u8
|
||||
@ -242,6 +348,19 @@ http://live02-cdn.tv.ti.ru:80/dtv/id376_NBN_SG--Fox_HD/04/plst.m3u8
|
||||
4. Вручную: удалить нерабочие, мусорные и продублировавшиеся (по ссылкам) каналы.
|
||||
5. Вручную: добавить плейлист в IPTV-плеер и перепроверить результат.
|
||||
|
||||
<a id="stack"></a>
|
||||
|
||||
## Использованный стек
|
||||
|
||||
* [docker compose](https://docs.docker.com/compose/)
|
||||
* [php8.1-fpm](https://www.php.net/releases/8.1/en.php)
|
||||
* [FlightPHP](https://flightphp.com/learn)
|
||||
* [Bootstrap 5](https://getbootstrap.com/docs/5.0/getting-started/introduction/)
|
||||
* [nginx](https://nginx.org/ru/)
|
||||
* bash
|
||||
|
||||
<a id="license"></a>
|
||||
|
||||
## Лицензия
|
||||
|
||||
[The MIT License](LICENSE)
|
||||
|
39
docker-compose.yml
Normal file
39
docker-compose.yml
Normal file
@ -0,0 +1,39 @@
|
||||
version: '3'
|
||||
|
||||
networks:
|
||||
iptv:
|
||||
driver: bridge
|
||||
|
||||
services:
|
||||
|
||||
php:
|
||||
container_name: iptv-php
|
||||
build: 'docker/php'
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- iptv
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf:ro
|
||||
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/php.ini:ro
|
||||
- ./log/php:/var/log/php:rw
|
||||
- ./src:/var/www:rw
|
||||
- ./playlists.ini:/var/www/config/playlists.ini:ro
|
||||
|
||||
nginx:
|
||||
container_name: iptv-nginx
|
||||
image: nginx:latest
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- iptv
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./docker/nginx/vhost.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./log/nginx:/var/log/nginx:rw
|
||||
- ./src:/var/www:ro
|
||||
ports:
|
||||
- 8080:80
|
||||
links:
|
||||
- php
|
||||
depends_on:
|
||||
- php
|
30
docker/nginx/vhost.conf
Normal file
30
docker/nginx/vhost.conf
Normal file
@ -0,0 +1,30 @@
|
||||
server {
|
||||
server_name iptv.local;
|
||||
listen 80;
|
||||
root /var/www/public;
|
||||
index index.php;
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
|
||||
access_log off;
|
||||
expires max;
|
||||
log_not_found off;
|
||||
}
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
}
|
||||
location ~ \.php$ {
|
||||
try_files $uri /index.php =404;
|
||||
fastcgi_pass php:9000;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
include fastcgi_params;
|
||||
}
|
||||
}
|
16
docker/php/dockerfile
Normal file
16
docker/php/dockerfile
Normal file
@ -0,0 +1,16 @@
|
||||
FROM php:8.1-fpm
|
||||
|
||||
RUN apt update && \
|
||||
apt upgrade -y && \
|
||||
apt install -y git && \
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# https://pecl.php.net/package/xdebug
|
||||
RUN pecl channel-update pecl.php.net && \
|
||||
pecl install xdebug-3.1.5 && \
|
||||
mkdir -p /var/log/php
|
||||
|
||||
EXPOSE 9000
|
||||
WORKDIR /var/www
|
||||
CMD composer install
|
||||
CMD php-fpm
|
27
docker/php/php.ini
Normal file
27
docker/php/php.ini
Normal file
@ -0,0 +1,27 @@
|
||||
[PHP]
|
||||
file_uploads = Off
|
||||
; upload_max_filesize=256M
|
||||
; post_max_size=256M
|
||||
error_reporting = E_ALL
|
||||
;& ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE & ~E_WARNING
|
||||
|
||||
[opcache]
|
||||
opcache.enable = 1
|
||||
opcache.enable_cli = 1
|
||||
opcache.memory_consumption = 128
|
||||
opcache.max_accelerated_files = 30000
|
||||
opcache.revalidate_freq = 0
|
||||
opcache.jit_buffer_size = 64M
|
||||
opcache.jit = tracing
|
||||
|
||||
[xdebug]
|
||||
; https://xdebug.org/docs/all_settings
|
||||
zend_extension = xdebug.so
|
||||
xdebug.mode = develop,debug
|
||||
xdebug.REQUEST = *
|
||||
xdebug.SESSION = *
|
||||
xdebug.SERVER = *
|
||||
xdebug.client_host = 172.17.0.1
|
||||
;xdebug.start_with_request=yes
|
||||
xdebug.start_with_request = trigger
|
||||
xdebug.trigger_value = go
|
21
docker/php/www.conf
Normal file
21
docker/php/www.conf
Normal file
@ -0,0 +1,21 @@
|
||||
[www]
|
||||
user = www-data
|
||||
group = www-data
|
||||
listen = 127.0.0.1:9000
|
||||
pm = dynamic
|
||||
pm.max_children = 5
|
||||
pm.start_servers = 2
|
||||
pm.min_spare_servers = 1
|
||||
pm.max_spare_servers = 3
|
||||
pm.max_requests = 50
|
||||
pm.status_path = /status
|
||||
ping.path = /ping
|
||||
ping.response = pong
|
||||
access.log = /var/log/php/$pool.access.log
|
||||
;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{milli}d %{kilo}M %C%%"
|
||||
; chroot = /var/www
|
||||
; chdir = /var/www
|
||||
php_flag[display_errors] = on
|
||||
php_admin_value[error_log] = /var/log/php/www.error.log
|
||||
php_admin_flag[log_errors] = on
|
||||
php_admin_value[memory_limit] = 32M
|
345
index.php
345
index.php
@ -1,345 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Anthony Axenov (c) 2022
|
||||
* The MIT License:
|
||||
* https://github.com/anthonyaxenov/iptv/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
//ini_set('display_errors', 1);
|
||||
//ini_set('display_startup_errors', 1);
|
||||
//error_reporting(E_ALL);
|
||||
|
||||
function response(array $content): void
|
||||
{
|
||||
header("Content-Type: application/json; charset=utf-8");
|
||||
die(json_encode($content));
|
||||
}
|
||||
|
||||
$updated_at = date('d.m.Y h:i', filemtime('playlists.ini'));
|
||||
$my_url = $_SERVER['SERVER_NAME'] . '?';
|
||||
$ini = parse_ini_file('playlists.ini', true);
|
||||
|
||||
// get playlist info (ajax)
|
||||
if (!empty($_GET['getinfo'])) {
|
||||
$pls = $ini[$_GET['getinfo']];
|
||||
if (!empty($pls['redirect'])) {
|
||||
$pls = $ini[$pls['redirect']];
|
||||
}
|
||||
unset($ini);
|
||||
if (empty($pls)) { // no playlist in ini
|
||||
response([
|
||||
'is_online' => false,
|
||||
'count' => 0,
|
||||
'channels' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $pls['pls']);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 5);
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
$response = curl_exec($curl);
|
||||
$code = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
|
||||
curl_close($curl);
|
||||
unset($curl);
|
||||
if ($response === false) { // timed out
|
||||
response([
|
||||
'is_online' => false,
|
||||
'count' => '-',
|
||||
'channels' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
$matches = [];
|
||||
preg_match_all("/^#EXTINF:-?\d.*,\s*(.*)/m", $response, $matches);
|
||||
$channels = array_map('trim', $matches[1]);
|
||||
unset($response, $matches);
|
||||
response([
|
||||
'is_online' => $is_online = $code < 400,
|
||||
'count' => $is_online ? count($channels) : '-',
|
||||
'channels' => $channels,
|
||||
]);
|
||||
}
|
||||
|
||||
// redirect to playlist
|
||||
if (array_intersect(array_keys($_GET), array_keys($ini))) {
|
||||
$id = array_keys($_GET)[0];
|
||||
if (!empty($ini[$id]['redirect'])) {
|
||||
header('Location: ' . $ini[$ini[$id]['redirect']]['pls']);
|
||||
die;
|
||||
} elseif (!empty($ini[$id]['pls'])) {
|
||||
header('Location: ' . $ini[$id]['pls']);
|
||||
die;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>IPTV Playlists</title>
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>.cursor-pointer {cursor: pointer} </style>
|
||||
<script src="js/bootstrap.bundle.min.js"></script>
|
||||
</head>
|
||||
<body class="bg-dark text-light">
|
||||
<div class="col-lg-8 mx-auto p-3 py-md-5">
|
||||
<header class="pb-3 mb-3">
|
||||
<a href="/" class="text-light text-decoration-none">
|
||||
<h1>Самообновляемые плейлисты IPTV</h1>
|
||||
</a>
|
||||
<p class="small text-muted">
|
||||
<a href="https://github.com/anthonyaxenov/iptv">GitHub</a> | <a href="https://axenov.dev">axenov.dev</a><br/>
|
||||
Обновлено: <?=$updated_at?>МСК<br/>
|
||||
Плейлистов в списке: <strong><?=count($ini)?></strong>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="list-tab" data-bs-toggle="tab" data-bs-target="#list" type="button"
|
||||
role="tab" aria-controls="list" aria-selected="true">Список</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="faq-tab" data-bs-toggle="tab" data-bs-target="#faq" type="button"
|
||||
role="tab" aria-controls="faq" aria-selected="false">FAQ</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active pt-5" id="list" role="tabpanel" aria-labelledby="list-tab">
|
||||
<table class="table table-dark table-hover small">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Информация о плейлисте</th>
|
||||
<th>Каналов</th>
|
||||
<th title="Нажми на ссылку, чтобы скопировать её в буфер обмена">Ссылка</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ($ini as $id => $element) {
|
||||
if (empty($element['pls'])) {
|
||||
continue;
|
||||
}
|
||||
?>
|
||||
<tr class="pls" data-playlist-id="<?=$id?>">
|
||||
<td class="text-center id">
|
||||
<strong><?=$id?></strong>
|
||||
</td>
|
||||
<td class="info">
|
||||
<strong><?=$element['name'] ?: "Плейлист #" . $id?></strong>
|
||||
<span class="badge small bg-warning text-dark status">?</span>
|
||||
<div class="small">
|
||||
<a href="<?=$element['pls']?>"
|
||||
target="_blank"
|
||||
rel="noopener nofollow">M3U</a>
|
||||
<?php
|
||||
if (!empty($element['src'])) { ?>
|
||||
| <a href="<?=$element['src']?>"
|
||||
target="_blank"
|
||||
rel="noopener nofollow">Источник</a>
|
||||
<?php
|
||||
} ?>
|
||||
<?php
|
||||
if (!empty($element['desc'])) { ?>
|
||||
<br/><p class="my-1"><?=$element['desc']?></p>
|
||||
<?php
|
||||
} ?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center count">
|
||||
<div class="spinner-border text-success" role="status">
|
||||
<span class="visually-hidden">загрузка...</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="col-3">
|
||||
<span onclick="prompt('Скопируй адрес плейлиста', '<?=$my_url?><?=$id?>')"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
|
||||
class="font-monospace cursor-pointer">
|
||||
<?=$my_url?><?=$id?>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
} ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="tab-pane fade p-3 pt-5" id="faq" role="tabpanel" aria-labelledby="profile-tab">
|
||||
<h2>Что здесь происходит?</h2>
|
||||
<p>
|
||||
На этой странице собраны ссылки на IPTV-плейлисты, которые находятся в открытом доступе.
|
||||
Они отбираются мной вручную и проверяются здесь автоматически.
|
||||
</p>
|
||||
<p>
|
||||
Ресурс <?=$_SERVER['SERVER_NAME']?> не занимается трансляцией видео- и аудиопотоков,
|
||||
администрированием конечных плейлистов и программ телепередач или хранением всего указанного.
|
||||
Подобными вопросами занимаются администраторы ресурсов, указанные как источник, и те, с чьих ресурсов
|
||||
ведётся трансляция.
|
||||
</p>
|
||||
<p class="mb-5">
|
||||
Ресурс <?=$_SERVER['SERVER_NAME']?> предоставляет только информацию об активности плейлистов, найденных
|
||||
в открытом доступе, и короткие ссылки на них для удобства ввода с пульта на телевизоре.
|
||||
Вопросы работоспособности плейлистов и каналов адресуйте тем, кто несёт за них ответственность.
|
||||
</p>
|
||||
|
||||
<h2>Что означают статусы плейлистов?</h2>
|
||||
<ul class="mb-5">
|
||||
<li>
|
||||
<span class="badge small bg-warning text-dark">?</span> Загрузка данных, нужно немного подождать.
|
||||
</li>
|
||||
<li>
|
||||
<span class="badge small text-dark bg-success">online</span> Плейлист, возможно, активен.
|
||||
</li>
|
||||
<li>
|
||||
<span class="badge small text-dark bg-secondary">unknown</span> Состояние неизвестно.
|
||||
Возможно, плейлист активен, но корректно его проверить не удалось.
|
||||
</li>
|
||||
<li>
|
||||
<span class="badge small text-dark bg-secondary">timeout</span> Не удалось вовремя проверить плейлист.
|
||||
</li>
|
||||
<li>
|
||||
<span class="badge small text-dark bg-danger">offline</span> Плейлист неактивен.
|
||||
</li>
|
||||
<li>
|
||||
<span class="badge small text-dark bg-danger">error</span> Ошибка при проверке плейлиста.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Почему нельзя доверять результатам проверки?</h2>
|
||||
<p>
|
||||
Я не гарантирую корректность и актуальность информации, которую ты увидишь здесь.
|
||||
Хотя я и стараюсь улучшать качество проверок, но всё же рекомендую проверять желаемые
|
||||
плейлисты самостоятельно вручную, ибо нет никаких гарантий:
|
||||
</p>
|
||||
<ul class="mb-5">
|
||||
<li>
|
||||
что это вообще плейлисты, а не чьи-то архивы с мокрыми кисками;
|
||||
</li>
|
||||
<li>
|
||||
что плейлисты по разным ссылкам не дублируют друг друга и отличаются каналами хотя бы на четверть;
|
||||
</li>
|
||||
<li>
|
||||
что плейлист работоспособен (каналы работают, корректно названы, имеют аудио, etc.);
|
||||
</li>
|
||||
<li>
|
||||
что подгрузится корректное количество каналов и их список (хотя на это я ещё могу влиять и
|
||||
стараюсь как-то улучшить).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Эти плейлисты и каналы в них -- бесплатны?</h2>
|
||||
<p class="mb-5">Возможно. По крайней мере, так утверждают источники.</p>
|
||||
|
||||
<h2>Как подключить плейлист?</h2>
|
||||
<p class="mb-5">
|
||||
<a href="https://www.google.com/search?q=%D0%BA%D0%B0%D0%BA%20%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%20iptv%20%D0%BF%D0%BB%D0%B5%D0%B9%D0%BB%D0%B8%D1%81%D1%82%20%D0%BF%D0%BE%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B5">
|
||||
Добавь в свой IPTV-плеер</a> ссылку из последней колонки.
|
||||
</p>
|
||||
|
||||
<h2>Какова гарантия, что я добавлю себе плейлист отсюда и он работать хоть сколько-нибудь долго?</h2>
|
||||
<p class="mb-5">
|
||||
Никакова.
|
||||
Мёртвые плейлисты я периодически вычищаю, реже -- добавляю новые.
|
||||
ID плейлистов могут меняться, поэтому вполне может произойти внезапная подмена одного другим, однако намеренно я так не делаю.
|
||||
Если один плейлист переезжает на новый адрес, то я ставлю временное перенаправление со старого ID на новый.
|
||||
Плюс читай выше про доверие результатам проверки (проблема может быть не на этой стороне).
|
||||
</p>
|
||||
|
||||
<h2>Где взять программу передач (EPG)?</h2>
|
||||
<ul class="mb-5">
|
||||
<li><b>https://iptvx.one/viewtopic.php?f=12&t=4</b></li>
|
||||
<li>https://iptvmaster.ru/epg-for-iptv</li>
|
||||
<li>https://google.com</li>
|
||||
</ul>
|
||||
|
||||
<h2>Как часто обновляется этот список?</h2>
|
||||
<p>
|
||||
Время от времени.
|
||||
Иногда я захожу сюда и проверяю всё ли на месте, иногда занимаюсь какими-то доработками.
|
||||
</p>
|
||||
<p class="mb-5">
|
||||
Если есть кандидаты на добавление, то читай ниже.
|
||||
</p>
|
||||
|
||||
<h2>Как часто обновляются сами плейлисты (каналы)?</h2>
|
||||
<p class="mb-5">
|
||||
Зависит от источника. Я этим не занимаюсь.
|
||||
</p>
|
||||
|
||||
<h2>Как пополнить этот список?</h2>
|
||||
<p class="mb-5">
|
||||
Сделать pull-request в <a href="https://github.com/anthonyaxenov/iptv">репозиторий</a>.
|
||||
Я проверю плейлист и добавлю его в общий список, если всё ок.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="py-4 text-center">
|
||||
<a href="https://github.com/anthonyaxenov/iptv">GitHub</a> | <a href="https://axenov.dev">axenov.dev</a>
|
||||
</footer>
|
||||
</div>
|
||||
<script>
|
||||
document.querySelectorAll('tr.pls').forEach((tr) => {
|
||||
const id = tr.attributes['data-playlist-id'].value
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.responseType = 'json'
|
||||
xhr.timeout = 60000 // ms = 1 min
|
||||
let st_el = tr.querySelector('span.status')
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
console.log('[' + id + '] DONE', xhr.response)
|
||||
st_el.classList.remove('bg-warning')
|
||||
if (xhr.response) {
|
||||
tr.querySelector('td.count').innerHTML = xhr.response.count
|
||||
if (xhr.response.is_online === true) {
|
||||
st_el.innerHTML = 'online'
|
||||
st_el.classList.add('bg-success')
|
||||
if (xhr.response.channels.length > 0) {
|
||||
tr.querySelector('td.info').innerHTML += '<a class="small cursor-pointer" ' +
|
||||
'data-bs-toggle="collapse" data-bs-target="#channels-' + id + '" aria-expanded="false" ' +
|
||||
'aria-controls="channels-' + id + '">Список каналов</a><div class="collapse" id="channels-' + id +
|
||||
'"><p class="card card-body bg-dark small" style="max-height:250px;overflow-y:auto;">' +
|
||||
xhr.response.channels.join('<br />') + '</p></div>'
|
||||
}
|
||||
} else {
|
||||
st_el.innerHTML = 'offline'
|
||||
st_el.classList.add('bg-danger')
|
||||
}
|
||||
} else {
|
||||
tr.querySelector('td.count').innerHTML = '-'
|
||||
st_el.classList.add('bg-secondary')
|
||||
st_el.innerHTML = 'unknown'
|
||||
}
|
||||
}
|
||||
}
|
||||
xhr.onerror = () => {
|
||||
console.log('[' + id + '] ERROR', xhr.response)
|
||||
st_el.classList.add('bg-danger')
|
||||
st_el.innerHTML = 'error'
|
||||
tr.querySelector('td.count').innerHTML = '-'
|
||||
}
|
||||
xhr.onabort = () => {
|
||||
console.log('[' + id + '] ABORTED', xhr.response)
|
||||
st_el.classList.add('bg-secondary')
|
||||
tr.querySelector('td.count').innerHTML = '-'
|
||||
}
|
||||
xhr.ontimeout = () => {
|
||||
console.log('[' + id + '] TIMEOUT', xhr.response)
|
||||
st_el.classList.add('bg-secondary')
|
||||
st_el.innerHTML = 'timeout'
|
||||
tr.querySelector('td.count').innerHTML = '-'
|
||||
}
|
||||
xhr.open('GET', '/?getinfo=' + id)
|
||||
xhr.send()
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
0
log/nginx/.gitkeep
Normal file
0
log/nginx/.gitkeep
Normal file
0
log/php/.gitkeep
Normal file
0
log/php/.gitkeep
Normal file
452
playlists.ini
452
playlists.ini
@ -1,452 +0,0 @@
|
||||
[1]
|
||||
name='Рабочий и актуальный IPTV плейлист M3U (smarttvapp.ru)'
|
||||
desc='В этом IPTV плейлисте формата m3u вы найдете очень много каналов в HD качестве. Познавательные: Discovery HD, Discovery Science, Nat Geo, Nat Geo WILD, TLC HD. Детские: Nickelodeon HD. Спортивные, много каналов с фильмами: Дом Кино Премиум HD, Кинопремьера HD. Плейлист актуален на: 3.02.22'
|
||||
pls='https://smarttvapp.ru/app/iptvfull.m3u'
|
||||
src='https://smarttvapp.ru/aktualnyiy-i-rabochiy-iptv-pleylist-m3u/'
|
||||
|
||||
[2]
|
||||
name='Самообновляемый IPTV плейлист — июнь 2022 (prodigtv.ru)'
|
||||
desc='Возможно, доублирует какой-то от smarttvnews'
|
||||
pls='https://prodigtv.ru/play/iptv.m3u'
|
||||
src='https://prodigtv.ru/iptv/playlist/samoobnovlyaemyj'
|
||||
|
||||
[3]
|
||||
name='IPTV каналы плейлист m3u без тормозов (poiskpmr)'
|
||||
desc='Самые популярные и актуальные жанры iptv каналов m3u в 2022 году'
|
||||
pls='https://iptvmaster.ru/december.m3u'
|
||||
src='https://poiskpmr.ru/blog/ip-kanaly-plejlist-m3u-bez-tormozov-b256'
|
||||
|
||||
[4]
|
||||
name='Самообновляемый IPTV плейлист 2022 на июнь (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/iptv-playlist.m3u'
|
||||
src='https://iptv-russia.ru/playlists/iptv-playlist/'
|
||||
|
||||
[5]
|
||||
name='IPTV плейлист с миксом ТВ каналов 2022 на июнь (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/mix.m3u'
|
||||
src='https://iptv-russia.ru/playlists/mix/'
|
||||
|
||||
[p1]
|
||||
name='Каналы в SD и HD качестве (smarttvnews.ru)'
|
||||
desc='Рабочий и актуальный IPTV плейлист M3U — на июнь 2022 года'
|
||||
pls='https://smarttvnews.ru/apps/iptvchannels.m3u'
|
||||
src='https://smarttvnews.ru/rabochiy-i-aktualnyiy-iptv-pleylist-m3u-kanalyi-v-sd-i-hd-kachestve/'
|
||||
|
||||
[p2]
|
||||
name='Самообновляемый iptv плейлист 2022 июнь (smarttvnews.ru)'
|
||||
desc='Лучший самообновляемый IPTV плейлист в 2022 году'
|
||||
pls='https://smarttvnews.ru/apps/freeiptv.m3u'
|
||||
src='https://smarttvnews.ru/samoobnovlyaemyj-iptv-plejlist/'
|
||||
|
||||
[p4]
|
||||
name='IPTV плейлист на июль 2020 (iptvm3u.ru)'
|
||||
desc='Плейлист содержит 1200+ ТВ каналов всех категорий (музыка, спорт, детские, образовательные, взрослые). Так же в файле есть каналы Украины, Белоруссии, Молдовы. Для удобства каналы других стран расположены в низу списка.'
|
||||
pls='https://iptvm3u.ru/0720.m3u'
|
||||
src='https://iptvm3u.ru/iptv-plejlist-na-ijul-2/'
|
||||
|
||||
[p5]
|
||||
name='Плейлист 2020 от iptv-playlisty.ru'
|
||||
desc='Трансляции для детей и подростков. Сериалы и Премьеры кино. Каналы для женщин и мужских развлечений. Документалистика и исторические лента о событиях прошлого.'
|
||||
pls='https://iptv-playlisty.ru/wp-content/uploads/m3u/2020.m3u'
|
||||
src='https://iptv-playlisty.ru/collection/samyj-svezheobnovlennyj-plejlist-iptv-na-2020-god/'
|
||||
|
||||
[p6]
|
||||
redirect='p1'
|
||||
|
||||
[kid1]
|
||||
name='Детский IPTV «Kids»'
|
||||
desc=''
|
||||
pls='https://webhalpme.ru/kids.m3u'
|
||||
src='https://webhalpme.ru/samoobnovljaemye-plejlisty-iptv-2019/'
|
||||
|
||||
[kid2]
|
||||
name='Плейлист детских каналов iptvmaster.ru'
|
||||
desc='02.08.2020 Среди детских каналов есть и отечественные, и зарубежные, большинство из них в HD.'
|
||||
pls='https://iptvmaster.ru/kids-all.m3u'
|
||||
src='https://iptvmaster.ru/detskie-kanaly-playlist/'
|
||||
|
||||
[np]
|
||||
name='Плейлист newplay (iptv-playlisty.ru)'
|
||||
desc='Общефедеральные. Каналы фильмов. Все на русском. Имеются с зарубежными лентами. Спортивные. Как трансляции, так и кино данной тематики. Детские. Мультфильмы и передачи.'
|
||||
pls='https://iptv-playlisty.ru/wp-content/uploads/m3u/newplay.m3u'
|
||||
src='https://iptv-playlisty.ru/collection/besplatnyj-iptv-plejlist-formata-m3u/'
|
||||
|
||||
[his]
|
||||
name='IPTV плейлист телеканала History (iptv-playlisty.ru)'
|
||||
desc=
|
||||
pls='https://iptv-playlisty.ru/wp-content/uploads/m3u/history.m3u'
|
||||
src='https://iptv-playlisty.ru/iptv-kanaly/iptv-plejlist-telekanala-history/'
|
||||
|
||||
[dis]
|
||||
name='IPTV плейлист телеканала Discovery (iptv-playlisty.ru)'
|
||||
desc=
|
||||
pls='https://iptv-playlisty.ru/wp-content/uploads/m3u/discovery.m3u'
|
||||
src='https://iptv-playlisty.ru/iptv-kanaly/iptv-plejlist-telekanala-discovery/'
|
||||
|
||||
[ngeo]
|
||||
name='IPTV плейлист канала national geographic (iptv-playlisty.ru)'
|
||||
desc=
|
||||
pls='https://iptv-playlisty.ru/wp-content/uploads/m3u/ngeografik.m3u'
|
||||
src='https://iptv-playlisty.ru/iptv-kanaly/iptv-plejlist-kanala-national-geographic/'
|
||||
|
||||
[news]
|
||||
name='Новости'
|
||||
desc=
|
||||
pls='https://iptvmaster.ru/news.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[mus]
|
||||
name='Музыкальные 1'
|
||||
desc=
|
||||
pls='https://iptvmaster.ru/music.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[mus1]
|
||||
name='Музыкальные 2 (smarttvnews.ru)'
|
||||
desc='IPTV плейлист музыкальных каналов 2022'
|
||||
pls='https://smarttvnews.ru/apps/music.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[mus2]
|
||||
name='IPTV плейлист с музыкальными каналами (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/music.m3u'
|
||||
src='https://iptv-russia.ru/playlists/music/'
|
||||
|
||||
[ser]
|
||||
name='Сериалы'
|
||||
desc=
|
||||
pls='http://bluecrabstv.do.am/serial.m3u'
|
||||
src='https://iptvsensei.ru/samoobnovlyayemyye-pleylisty-iptv'
|
||||
|
||||
[kino1]
|
||||
name='Фильмы 1'
|
||||
desc=
|
||||
pls='https://smarttvnews.ru/apps/Films.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[kino2]
|
||||
name='Фильмы 2'
|
||||
desc=
|
||||
pls='http://iptvm3u.ru/500newFilms.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[kino3]
|
||||
name='Фильмы 3'
|
||||
desc=
|
||||
pls='http://iptvm3u.ru/film1.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[kino4]
|
||||
name='Фильмы 4'
|
||||
desc=
|
||||
pls='http://iptvm3u.ru/film4.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[kino5]
|
||||
name='Фильмы 5'
|
||||
desc=
|
||||
pls='https://pastebin.com/raw/jLaRge54'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[kino6]
|
||||
name='IPTV плейлист с кино, сериалами и мультфильмами 2022 на июнь (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/cinematic.m3u'
|
||||
src='https://iptv-russia.ru/playlists/cinematic/'
|
||||
|
||||
[ru1]
|
||||
name='Русские 1'
|
||||
desc=
|
||||
pls='https://webhalpme.ru/RussiaIPTV.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[ru3]
|
||||
name='Русские 3'
|
||||
desc=
|
||||
pls='https://getsapp.ru/IPTV/Auto_IPTV.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[ru4]
|
||||
name='Русские 4'
|
||||
desc=
|
||||
pls='https://iptvm3u.ru/list2511.m3u8'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[ru5]
|
||||
name='Русские 5'
|
||||
desc=
|
||||
pls='https://avdmono.do.am/film/natgeo.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[ru6]
|
||||
name='Русские 6'
|
||||
desc=
|
||||
pls='http://iptv.ktkru.ru/playlist.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[ru7]
|
||||
name='IPTV плейлист с ТВ каналами России 2022 на июнь (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/ru-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/ru-all/'
|
||||
|
||||
[reg]
|
||||
name='IPTV Плейлист — Региональные каналы России (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/ru-regional.m3u'
|
||||
src='https://iptv-russia.ru/playlists/ru-regional/'
|
||||
|
||||
[ua1]
|
||||
name='Украинские IPTV каналы (smarttvnews.ru)'
|
||||
desc=''
|
||||
pls='https://smarttvnews.ru/apps/ukraine.m3u'
|
||||
src='https://smarttvnews.ru/iptv-plejlist-ukrainskih-kanalov/'
|
||||
|
||||
[ua2]
|
||||
name='Украинские 2'
|
||||
desc=''
|
||||
pls='https://iptvmaster.ru/ukraine.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[ua3]
|
||||
name='IPTV плейлист с ТВ каналами Украины 2022 (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/ua-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/ua-all/'
|
||||
|
||||
[ua4]
|
||||
name='IPTV m3u плейлист Украина самообновляемый 2022 (tva.org.ua)'
|
||||
desc='IPTV плейлист m3u бесплатных украинских каналов на 29 мая 2022 року'
|
||||
pls='https://tva.org.ua/ip/u/iptv_ukr.m3u'
|
||||
src='https://tva.org.ua/iptv-m3u-plejlist-ukraina-samoobnovlyaemyj.html'
|
||||
|
||||
[by]
|
||||
name='IPTV плейлист с ТВ каналами Беларуси 2022 (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/by-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/by-all/'
|
||||
|
||||
[arm]
|
||||
name='IPTV плейлист с ТВ каналами Армении 2022 (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/arm-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/all-arm/'
|
||||
|
||||
[uz]
|
||||
name='IPTV плейлист с ТВ каналами Узбекистана 2022 (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/uz-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/uz-all/'
|
||||
|
||||
[uz]
|
||||
name='IPTV плейлист с ТВ каналами Казахстана 2022 (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/kz-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/kz-all/'
|
||||
|
||||
[tr]
|
||||
name='IPTV плейлист с ТВ каналами Турции и Азербайджана 2022 (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/tr-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/tr-all/'
|
||||
|
||||
[usa]
|
||||
name='IPTV плейлист с ТВ каналами США 2022 (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/usa-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/usa-all/'
|
||||
|
||||
[ita]
|
||||
name='IPTV плейлист с ТВ каналами Италии 2022 (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/ita-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/ita-all/'
|
||||
|
||||
[m2]
|
||||
name='Мультфильмы 2'
|
||||
desc=
|
||||
pls='https://iptvmaster.ru/kids.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[m3]
|
||||
name='Мультфильмы 3'
|
||||
desc=
|
||||
pls='https://iptvmaster.ru/multfilm.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[m4]
|
||||
name='Мультфильмы 4'
|
||||
desc=
|
||||
pls='https://iptvmaster.ru/kids-all.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[m5]
|
||||
name='Мультфильмы 5'
|
||||
desc=
|
||||
pls='https://smarttvnews.ru/apps/Films.m3u'
|
||||
src='https://iptvsensei.ru/samoobnovlyayemyye-pleylisty-iptv'
|
||||
|
||||
[m6]
|
||||
name='Мультфильмы 6'
|
||||
desc=
|
||||
pls='http://iptvm3u.ru/film4.m3u'
|
||||
src='https://iptvsensei.ru/samoobnovlyayemyye-pleylisty-iptv'
|
||||
|
||||
[m7]
|
||||
name='Мультфильмы 7'
|
||||
desc=
|
||||
pls='http://iptvm3u.ru/film2.m3u'
|
||||
src='https://iptvsensei.ru/samoobnovlyayemyye-pleylisty-iptv'
|
||||
|
||||
[m8]
|
||||
name='Мультфильмы 8'
|
||||
desc=
|
||||
pls='http://iptvm3u.ru/film1.m3u'
|
||||
src='https://iptvsensei.ru/samoobnovlyayemyye-pleylisty-iptv'
|
||||
|
||||
[m9]
|
||||
name='Мультфильмы 9'
|
||||
desc=
|
||||
pls='http://iptvm3u.ru/500newFilms.m3u'
|
||||
src='https://iptvsensei.ru/samoobnovlyayemyye-pleylisty-iptv'
|
||||
|
||||
[m10]
|
||||
name='Детский Iptv плейлист с каналами и мультфильмами (smarttvnews.ru)'
|
||||
desc=''
|
||||
pls='https://smarttvnews.ru/apps/mult.m3u'
|
||||
src='https://smarttvnews.ru/samoobnovlyaemyie-iptv-pleylistyi/'
|
||||
|
||||
[sci]
|
||||
name='Познавательные'
|
||||
desc=''
|
||||
pls='https://iptvmaster.ru/poznavatelnoe.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sci2]
|
||||
name='IPTV плейлист с познавательными ТВ каналами 2022 на июнь (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/sci-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/sci-all/'
|
||||
|
||||
[sp]
|
||||
name='IPTV плейлист со спортивными каналами 2022 на июнь (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/sport-all.m3u'
|
||||
src='https://iptv-russia.ru/playlists/sports-all/'
|
||||
|
||||
[cam]
|
||||
name='IPTV плейлист с вебкамерами России и мира 2022 на июнь (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/webcams.m3u'
|
||||
src='https://iptv-russia.ru/playlists/webcams/'
|
||||
|
||||
[cam2]
|
||||
name='Веб камеры онлайн всего мира m3u (tva.org.ua)'
|
||||
desc='Веб камеры со всего мира онлайн в формате m3u плейлиста iptv.'
|
||||
pls='https://tva.org.ua/ip/web/web-kam-14.12.2021.m3u'
|
||||
src='https://tva.org.ua/veb-kamery-onlayn-vsego-mira-m3u.html'
|
||||
|
||||
[r1]
|
||||
name='Радио каналы 1'
|
||||
desc=
|
||||
pls='http://lradio.c1.biz/ltradio.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[r3]
|
||||
name='Радио каналы 3'
|
||||
desc=
|
||||
pls='https://iptvmaster.ru/radio.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng1]
|
||||
name='Каналы СНГ 1'
|
||||
desc=
|
||||
pls='https://iptvm3u.ru/iptv1218.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng2]
|
||||
name='Каналы СНГ 2'
|
||||
desc=
|
||||
pls='https://iptvm3u.ru/0119.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng3]
|
||||
name='Каналы СНГ 3'
|
||||
desc=
|
||||
pls='https://iptvm3u.ru/0219.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng4]
|
||||
name='Каналы СНГ 4'
|
||||
desc=
|
||||
pls='http://iptvm3u.ru/iptv082018.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng5]
|
||||
name='Каналы СНГ 5'
|
||||
desc=
|
||||
pls='https://iptvm3u.ru/0919.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng6]
|
||||
name='Каналы СНГ 6'
|
||||
desc=
|
||||
pls='https://iptvm3u.ru/0819.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng7]
|
||||
name='Каналы СНГ 7'
|
||||
desc=
|
||||
pls='https://iptvm3u.ru/1019.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng8]
|
||||
name='Каналы СНГ 8'
|
||||
desc=
|
||||
pls='https://iptvm3u.ru/1119.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng10]
|
||||
name='Каналы СНГ 10'
|
||||
desc=
|
||||
pls='https://webhalpme.ru/donwhm.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng11]
|
||||
name='Каналы СНГ 11'
|
||||
desc=
|
||||
pls='https://iptvmaster.ru/hd.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng12]
|
||||
name='Каналы СНГ 12'
|
||||
desc=
|
||||
pls='https://iptvmaster.ru/armenia.m3u'
|
||||
src='https://iptvsensei.ru/novye-samoobnovlyaemye-plejlisty'
|
||||
|
||||
[sng13]
|
||||
name='Каналы СНГ 13'
|
||||
desc=
|
||||
pls='https://dl.dropboxusercontent.com/s/iw9v57cln6dfkpu/Vinnitsa.m3u'
|
||||
src='https://iptvsensei.ru/samoobnovlyayemyye-pleylisty-iptv'
|
||||
|
||||
[sng14]
|
||||
name='Каналы СНГ 14'
|
||||
desc=
|
||||
pls='http://gorod.tv/iptv.m3u'
|
||||
src='https://iptvsensei.ru/samoobnovlyayemyye-pleylisty-iptv'
|
||||
|
||||
[x]
|
||||
name='IPTV плейлист для взрослых 2022 (smarttvnews.ru)'
|
||||
desc='Рабочий IPTV плейлист с каналами и фильмами для взрослых'
|
||||
pls='https://smarttvnews.ru/apps/xxx.m3u'
|
||||
src='https://smarttvnews.ru/iptv-plejlist-dlya-vzroslyh/'
|
||||
|
||||
[x2]
|
||||
name='IPTV плейлист для взрослых 2022 (iptv-russia.ru)'
|
||||
desc=''
|
||||
pls='https://iptv-russia.ru/list/xxx.m3u'
|
||||
src='https://iptv-russia.ru/playlists/xxx/'
|
1
playlists.ini
Symbolic link
1
playlists.ini
Symbolic link
@ -0,0 +1 @@
|
||||
src/config/playlists.ini
|
7
src/.env.example
Normal file
7
src/.env.example
Normal file
@ -0,0 +1,7 @@
|
||||
APP_TITLE=
|
||||
APP_URL=
|
||||
TWIG_CACHE=1
|
||||
TWIG_DEBUG=0
|
||||
FLIGHT_CASE_SENSITIVE=0
|
||||
FLIGHT_HANDLE_ERRORS=1
|
||||
FLIGHT_LOG_ERRORS=1
|
9
src/app/Controllers/Controller.php
Normal file
9
src/app/Controllers/Controller.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
abstract class Controller
|
||||
{
|
||||
}
|
76
src/app/Controllers/HomeController.php
Normal file
76
src/app/Controllers/HomeController.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Core\PlaylistProcessor;
|
||||
use App\Core\RedirectedPlaylist;
|
||||
use Exception;
|
||||
use Flight;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
protected PlaylistProcessor $ini;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ini = new PlaylistProcessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if (Flight::request()->query->count() > 0) {
|
||||
$id = Flight::request()->query->keys()[0];
|
||||
Flight::redirect(base_url("$id"));
|
||||
die;
|
||||
}
|
||||
view('list', [
|
||||
'updated_at' => $this->ini->updatedAt(),
|
||||
'count' => $this->ini->playlists->count(),
|
||||
'playlists' => $this->ini->playlists->where('redirect_id', null)->toArray(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function faq()
|
||||
{
|
||||
view('faq');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function details(string $id): void
|
||||
{
|
||||
$playlist = $this->ini->playlist($id);
|
||||
if ($playlist instanceof RedirectedPlaylist) {
|
||||
Flight::redirect(base_url($playlist->redirect_id . '/info'));
|
||||
}
|
||||
view('details', [
|
||||
'id' => $id,
|
||||
'playlist' => $playlist->toArray(),
|
||||
'info' => $this->ini->parse($id),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function ajax(string $id): void
|
||||
{
|
||||
$playlist = $this->ini->playlist($id);
|
||||
if ($playlist instanceof RedirectedPlaylist) {
|
||||
Flight::redirect(base_url($playlist->redirect_id . '/getInfo'));
|
||||
}
|
||||
Flight::json([
|
||||
'playlist' => $playlist->toArray(),
|
||||
'info' => $this->ini->parse($id),
|
||||
]);
|
||||
}
|
||||
}
|
65
src/app/Controllers/PlaylistController.php
Normal file
65
src/app/Controllers/PlaylistController.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Core\PlaylistProcessor;
|
||||
use App\Core\RedirectedPlaylist;
|
||||
use Exception;
|
||||
use Flight;
|
||||
|
||||
class PlaylistController extends Controller
|
||||
{
|
||||
protected PlaylistProcessor $ini;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ini = new PlaylistProcessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function download($id)
|
||||
{
|
||||
$playlist = $this->ini->playlist($id);
|
||||
if ($playlist instanceof RedirectedPlaylist) {
|
||||
Flight::redirect(base_url($playlist->redirect_id));
|
||||
die;
|
||||
}
|
||||
Flight::redirect($playlist->pls);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function details(string $id): void
|
||||
{
|
||||
$playlist = $this->ini->playlist($id);
|
||||
if ($playlist instanceof RedirectedPlaylist) {
|
||||
Flight::redirect(base_url($playlist->redirect_id . '/details'));
|
||||
die;
|
||||
}
|
||||
view('details', [
|
||||
...$playlist->toArray(),
|
||||
...$this->ini->parse($id),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function json(string $id): void
|
||||
{
|
||||
$playlist = $this->ini->playlist($id);
|
||||
if ($playlist instanceof RedirectedPlaylist) {
|
||||
Flight::redirect(base_url($playlist->redirect_id . '/json'));
|
||||
die;
|
||||
}
|
||||
Flight::json([
|
||||
...$playlist->toArray(),
|
||||
...$this->ini->parse($id),
|
||||
]);
|
||||
}
|
||||
}
|
17
src/app/Core/BasicPlaylist.php
Normal file
17
src/app/Core/BasicPlaylist.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace App\Core;
|
||||
|
||||