Initial commit

This commit is contained in:
Anthony Axenov 2025-03-05 00:20:33 +08:00
commit 6fd8998245
Signed by: anthony
GPG Key ID: EA9EC32FF7CCD4EC
8 changed files with 377 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/downloaded
playlists.ini
*.m3u
*.m3u8

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Антон Аксенов (Anthony Axenov)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

80
README.md Normal file
View File

@ -0,0 +1,80 @@
# Инструменты для работы с IPTV-плейлистами
Проект, содержащий в себе скрипты для работы с IPTV-плейлистами.
Для начала работы необходимо скачать файл [playlists.ini](https://git.axenov.dev/IPTV/playlists/raw/branch/master/playlists.ini).
- [Инструменты для работы с IPTV-плейлистами](#инструменты-для-работы-с-iptv-плейлистами)
- [Скачать все плейлисты](#скачать-все-плейлисты)
- [Проверить каналы плейлиста](#проверить-каналы-плейлиста)
- [Поиск каналов в одном плейлисте](#поиск-каналов-в-одном-плейлисте)
- [Поиск каналов во всех плейлистах](#поиск-каналов-во-всех-плейлистах)
- [Создать плейлист из нужных каналов](#создать-плейлист-из-нужных-каналов)
- [Как создать свой собственный плейлист?](#как-создать-свой-собственный-плейлист)
- [Лицензия](#лицензия)
## Скачать все плейлисты
Команда: `./download-all.sh`
Скачивает все плейлисты из `playlists.ini` в локальную директорию `./downloaded/`.
## Проверить каналы плейлиста
Команда: `./check-pls.sh`
Проверяет каждый канал в плейлисте на доступность и выводит результат проверки.
Поддерживаются `*.m3u` и `*.m3u8`; как локальные файлы, так по прямым ссылкам.
Коды ошибок доступны [здесь](https://everything.curl.dev/usingcurl/returns).
## Поиск каналов в одном плейлисте
Команда: `./find-in-pls.sh`
Находит каналы по заданному регулярному выражению в одном указанном плейлисте.
Поддерживаются `*.m3u` и `*.m3u8`; как локальные файлы, так по прямым ссылкам.
## Поиск каналов во всех плейлистах
Команда: `./find-in-all.sh`
Находит каналы по заданному регулярному выражению во всех плейлистах, скачанных через `download-all.sh`.
## Создать плейлист из нужных каналов
Команда: `./make-pls.sh`
Находит каналы по заданному регулярному выражению во всех плейлистах, скачанных через `download-all.sh`.
Отличается от `find-in-all.sh` тем, что тот выводит результат в человекочитаемом формате, а этот -- в готовом m3u
формате для сохранения в файл.
Для сохранения в файл следует добавить `> myfile.m3u` или `>> myfile.m3u` в конец команды.
## Как создать свой собственный плейлист?
1. Скачать все плейлисты, указанные в `playlists.ini`:
```
$ ./download-all.sh
```
2. Вытащить из них нужные каналы и сохранить в отдельный файл:
```
$ ./make-pls.sh "(fox|disney)" > my.m3u8
```
Так в плейлисте `./my.m3u8` окажутся все каналы из скачанных плейлистов, в названиях которых встретились `fox`
или `disney`.
3. Проверить доступность каналов в полученном плейлисте:
```
$ ./check-pls.sh my.m3u8
```
> Результат `ОК` не означает, что канал действительно работает и отдаёт видео/аудио потоки.
> Результат `ERROR` с любыми кодами ошибок гарантированно означает, что канал не работает.
4. Вручную: удалить нерабочие, мусорные и продублировавшиеся (по ссылкам) каналы.
5. Вручную: добавить плейлист в IPTV-плеер и перепроверить результат.
## Лицензия
[The MIT License](LICENSE)

77
check-pls.sh Executable file
View File

@ -0,0 +1,77 @@
#!/bin/bash
#################################################
#
# IPTV Playlist check tool
#
# Usage:
# ./check-pls.sh local/pls.m3u
# ./check-pls.sh https://example.com/pls.m3u
#
# 1st argument is playlist file name or URL.
# If it is an URL it will be saved in /tmp and
# checked as local file.
#
# Both *.m3u and *.m3u8 are supported.
#
# Anthony Axenov (c) 2022
# The MIT License:
# https://git.axenov.dev/IPTV/tools/src/branch/master/LICENSE
#
#################################################
awk '
BEGIN {
total_count=0
success_count=0
fail_count=0
print "\033[20m\033[97mPlaylist:\033[0m " ARGV[1]
if (ARGV[1] ~ /^http(s)?:\/\/.*/) {
parts_count = split(ARGV[1], parts, "/")
file_name = parts[parts_count]
code = system("wget " ARGV[1] " -qO /tmp/" file_name " > /dev/null")
if (code == 0) {
print "Saved in /tmp/" file_name
} else {
print "ERROR: cannot download playlist: " ARGV[1]
exit 1
}
ARGV[1] = "/tmp/" file_name
}
print ""
print "\033[20m\033[97mNote 1:\033[0m operation may take some time, press CTRL+C to stop."
print "\033[20m\033[97mNote 2:\033[0m results may be inaccurate, you should use proper IPTV software to re-check."
print "\033[20m\033[97mNote 3:\033[0m error codes listed here - https://everything.curl.dev/usingcurl/returns"
print "--------------------"
}
{
sub("\r$", "", $0) # crlf -> lf
if ($0 ~ /^#EXTINF:.+,/) {
total_count++
channel_name = substr($0, index($0, ",") + 1, length($0))
print "\n[" total_count "] " channel_name
}
if ($0 ~ /^http(s)?:\/\/.*/) {
url = sprintf("%c%s%c", 34, $0, 34) # 34 is "
cmd = "curl -fs --max-time 5 -w \"%{http_code}\" --max-filesize 5000 -o /dev/null " url
cmd | getline http_code
code = close(cmd)
if (http_code == "000") {
http_code = "-"
}
if (code == 0 || code == 63) {
print "\033[32mOK:\033[0m " url
success_count++
} else {
print "\033[91mERROR\033[0m " code " (" http_code "): " url
fail_count++
}
}
}
END {
print "--------------------"
print "\033[20m\033[97mPlaylist:\033[0m " ARGV[1]
print "- Success:\t\033[32m" success_count "\033[0m/" total_count
print "- Failed: \t\033[91m" fail_count "\033[0m/" total_count
}
' $1

31
download-all.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/bash
#################################################
#
# IPTV Playlist download tool
#
# Usage:
# ./download-all.sh
#
# All playlists from playlists.ini will be
# downloaded in ./downloaded directory
#
# Anthony Axenov (c) 2022
# The MIT License:
# https://git.axenov.dev/IPTV/tools/src/branch/master/LICENSE
#
#################################################
TOOLS_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )";
DL_DIR="$TOOLS_DIR/downloaded"
INI_FILE="$(dirname "$TOOLS_DIR")/playlists.ini"
rm -rf "$DL_DIR" && \
mkdir -p "$DL_DIR" && \
cd "$DL_DIR" && \
cat "$INI_FILE" \
| grep -P "pls\s*=\s*'(.*)'" \
| sed "s#^pls\s*=\s*##g" \
| sed "s#'##g" \
| tr -d '\r' \
| xargs wget

25
find-in-all.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
#################################################
#
# IPTV channel finder (all playlists)
#
# Usage:
# ./download-all.sh
# ./find-in-all.sh "(disney|atv)"
#
# 1st argument is channel name pattern.
#
# Anthony Axenov (c) 2022
# The MIT License:
# https://git.axenov.dev/IPTV/tools/src/branch/master/LICENSE
#
#################################################
TOOLS_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )";
DL_DIR="$TOOLS_DIR/downloaded"
[ ! -d "$DL_DIR" ] && echo "Error: '$DL_DIR' directory does not exist. Run ./download-all.sh" && exit 1
[ ! "$(ls -A "$DL_DIR")" ] && echo "Error: '$DL_DIR' directory is empty. Run ./download-all.sh" && exit 2
for file in $TOOLS_DIR/downloaded/*; do
$TOOLS_DIR/find-in-pls.sh "$1" "$file"
done

84
find-in-pls.sh Executable file
View File

@ -0,0 +1,84 @@
#!/bin/bash
#################################################
#
# IPTV channel finder (one playlist)
#
# Usage:
# ./find-in-pls.sh "disney" local/pls.m3u
# ./find-in-pls.sh "disney" https://example.com/pls.m3u
#
# 1st argument is channel name pattern.
#
# 2nd argument is playlist file name or URL.
# If it is an URL it will be saved in /tmp and
# checked as local file.
#
# Both *.m3u and *.m3u8 are supported.
#
# Anthony Axenov (c) 2022
# The MIT License:
# https://git.axenov.dev/IPTV/tools/src/branch/master/LICENSE
#
#################################################
channel="$1"
playlist="$2"
playlist_url="$playlist"
regex_ch="^#extinf:\s*-?[01]\s*.*,(.*${channel,,}.*)"
regex_url="^https?:\/\/.*$"
is_downloaded=0
download_dir="/tmp/$(date '+%s%N')"
found_count=0
found_last=0
line_count=1
if [[ "$playlist" =~ $regex_url ]]; then
mkdir -p "$download_dir"
cd "$download_dir"
wget "$playlist" -q > /dev/null
if [ $? -eq 0 ]; then
is_downloaded=1
playlist="$download_dir/$(ls -1 "$download_dir")"
cd - > /dev/null
else
echo "ERROR: cannot download playlist: $playlist"
exit 1
fi
fi
echo "--------------------"
echo -e "\033[20m\033[97mChannel:\033[0m $channel"
echo -e "\033[20m\033[97mPlaylist:\033[0m $playlist_url"
echo -e "\033[20m\033[97mRegex:\033[0m $regex_ch"
echo "--------------------"
while read line; do
if [[ "${line,,}" =~ $regex_ch ]]; then
echo -e "\n\033[32m$line_count FOUND:\033[0m\t$line"
((found_count += 1))
found_last=$found_count
fi
if [ $found_last -gt 0 ]; then
if [[ "${line,,}" =~ $regex_url ]]; then
echo -e "\t\t$line"
found_last=0
fi
fi
((line_count += 1))
done < $playlist
if [ $found_count -eq 0 ]; then
echo -e "\033[91mNothing found\033[0m"
else
echo "--------------------"
echo -e "\033[20m\033[97mChannel:\033[0m $channel"
echo -e "\033[20m\033[97mPlaylist:\033[0m $playlist_url"
echo -e "\033[20m\033[97mFound:\033[0m\033[32m $found_count\033[0m"
fi
if [ $is_downloaded -eq 1 ]; then
rm -rf "$download_dir"
fi

55
make-pls.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/bash
#################################################
#
# IPTV channel maker (all playlists)
#
# Usage:
# ./download-all.sh
# ./make-pls.sh "disney"
#
# 1st argument is channel name pattern.
#
# To save output in file use redirection:
# ./make-pls.sh "disney" > disney.m3u8
#
# Anthony Axenov (c) 2022
# The MIT License:
# https://git.axenov.dev/IPTV/tools/src/branch/master/LICENSE
#
#################################################
TOOLS_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )";
DL_DIR="$TOOLS_DIR/downloaded"
[ ! -d "$DL_DIR" ] && echo "Error: '$DL_DIR' directory does not exist. Run ./download-all.sh" && exit 1
[ ! "$(ls -A "$DL_DIR")" ] && echo "Error: '$DL_DIR' directory is empty. Run ./download-all.sh" && exit 2
channel="$1"
playlist="$2"
regex_ch="^#extinf:\s*-?[01]\s*.*,(.*${channel,,}.*)"
regex_url="^https?:\/\/.*$"
found_count=0
found_last=0
echo "#EXTM3U"
echo "# Autogenerated at `date +%d.%m.%Y`"
echo "# https://git.axenov.dev/IPTV/tools"
echo
for file in ./downloaded/*; do
while read line; do
if [[ "${line,,}" =~ $regex_ch ]]; then
echo -e "$line"
((found_count += 1))
found_last=$found_count
fi
if [ $found_last -gt 0 ]; then
if [[ "${line,,}" =~ $regex_url ]]; then
echo -e "$line\n"
found_last=0
fi
fi
done < $file
done