Перекладка и апгрейд проекта под расширение

This commit is contained in:
2024-12-08 16:38:04 +08:00
parent faec083397
commit 0df4578e09
54 changed files with 1255 additions and 1245 deletions

0
src/cache/.gitkeep vendored
View File

File diff suppressed because it is too large Load Diff

77
src/scripts/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://github.com/anthonyaxenov/iptv/blob/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
src/scripts/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://github.com/anthonyaxenov/iptv/blob/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
src/scripts/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://github.com/anthonyaxenov/iptv/blob/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: 'tools/downloaded' directory does not exist. Run tools/download-all.sh" && exit 1
[ ! "$(ls -A "$DL_DIR")" ] && echo "Error: 'tools/downloaded' directory is empty. Run tools/download-all.sh" && exit 2
for file in $TOOLS_DIR/downloaded/*; do
$TOOLS_DIR/find-in-pls.sh "$1" "$file"
done

84
src/scripts/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://github.com/anthonyaxenov/iptv/blob/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
src/scripts/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://github.com/anthonyaxenov/iptv/blob/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: 'tools/downloaded' directory does not exist. Run tools/download-all.sh" && exit 1
[ ! "$(ls -A "$DL_DIR")" ] && echo "Error: 'tools/downloaded' directory is empty. Run tools/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://github.com/anthonyaxenov/iptv"
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

10
src/svc-main/.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
vendor/
cache/
views/custom.twig
playlists.ini
commit
*.log
.env
!/**/.gitkeep

View File

@@ -1,6 +1,6 @@
{
"require": {
"php": "^8.2",
"php": "^8.4",
"ext-json": "*",
"ext-curl": "*",
"ext-fileinfo": "*",
@@ -10,10 +10,12 @@
},
"autoload": {
"psr-4": {
"App\\": "app/"
"Core\\": "core/",
"Controllers\\": "controllers/",
"Exceptions\\": "exceptions/"
},
"files": [
"app/helpers.php"
"helpers.php"
]
},
"scripts": {

View File

@@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3cbd8253b2f0790d682e38f308df6e7f",
"content-hash": "1aaea4609092e8a88074f050dab42323",
"packages": [
{
"name": "mikecao/flight",
"version": "v3.12.0",
"version": "v3.13.0",
"source": {
"type": "git",
"url": "https://github.com/flightphp/core.git",
"reference": "63fbf9b0316969e8aa6c318f8479d1ed0578f9b4"
"reference": "1307e8a39d89fadba69d0c2dad53b6e0da83fd96"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/flightphp/core/zipball/63fbf9b0316969e8aa6c318f8479d1ed0578f9b4",
"reference": "63fbf9b0316969e8aa6c318f8479d1ed0578f9b4",
"url": "https://api.github.com/repos/flightphp/core/zipball/1307e8a39d89fadba69d0c2dad53b6e0da83fd96",
"reference": "1307e8a39d89fadba69d0c2dad53b6e0da83fd96",
"shasum": ""
},
"require": {
@@ -26,7 +26,7 @@
},
"require-dev": {
"ext-pdo_sqlite": "*",
"flightphp/runway": "^0.2.0",
"flightphp/runway": "^0.2.3 || ^1.0",
"league/container": "^4.2",
"level-2/dice": "^4.0",
"phpstan/extension-installer": "^1.3",
@@ -73,22 +73,22 @@
"homepage": "http://flightphp.com",
"support": {
"issues": "https://github.com/flightphp/core/issues",
"source": "https://github.com/flightphp/core/tree/v3.12.0"
"source": "https://github.com/flightphp/core/tree/v3.13.0"
},
"time": "2024-08-22T17:05:34+00:00"
"time": "2024-10-30T19:52:23+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.5.0",
"version": "v3.5.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"shasum": ""
},
"require": {
@@ -126,7 +126,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0"
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
},
"funding": [
{
@@ -142,20 +142,20 @@
"type": "tidelift"
}
],
"time": "2024-04-18T09:32:20+00:00"
"time": "2024-09-25T14:20:29+00:00"
},
{
"name": "symfony/dotenv",
"version": "v7.1.5",
"version": "v7.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/dotenv.git",
"reference": "6d966200b399fa59759286f3fc7c919f0677c449"
"reference": "28347a897771d0c28e99b75166dd2689099f3045"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dotenv/zipball/6d966200b399fa59759286f3fc7c919f0677c449",
"reference": "6d966200b399fa59759286f3fc7c919f0677c449",
"url": "https://api.github.com/repos/symfony/dotenv/zipball/28347a897771d0c28e99b75166dd2689099f3045",
"reference": "28347a897771d0c28e99b75166dd2689099f3045",
"shasum": ""
},
"require": {
@@ -200,7 +200,7 @@
"environment"
],
"support": {
"source": "https://github.com/symfony/dotenv/tree/v7.1.5"
"source": "https://github.com/symfony/dotenv/tree/v7.2.0"
},
"funding": [
{
@@ -216,7 +216,7 @@
"type": "tidelift"
}
],
"time": "2024-09-17T09:16:35+00:00"
"time": "2024-11-27T11:18:42+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -455,16 +455,16 @@
},
{
"name": "twig/twig",
"version": "v3.14.0",
"version": "v3.16.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72"
"reference": "475ad2dc97d65d8631393e721e7e44fb544f0561"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/126b2c97818dbff0cdf3fbfc881aedb3d40aae72",
"reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/475ad2dc97d65d8631393e721e7e44fb544f0561",
"reference": "475ad2dc97d65d8631393e721e7e44fb544f0561",
"shasum": ""
},
"require": {
@@ -475,6 +475,7 @@
"symfony/polyfill-php81": "^1.29"
},
"require-dev": {
"phpstan/phpstan": "^2.0",
"psr/container": "^1.0|^2.0",
"symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0"
},
@@ -518,7 +519,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.14.0"
"source": "https://github.com/twigphp/Twig/tree/v3.16.0"
},
"funding": [
{
@@ -530,20 +531,21 @@
"type": "tidelift"
}
],
"time": "2024-09-09T17:55:12+00:00"
"time": "2024-11-29T08:27:05+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "^8.2",
"ext-json": "*",
"ext-curl": "*"
"ext-curl": "*",
"ext-fileinfo": "*"
},
"platform-dev": [],
"platform-dev": {},
"plugin-api-version": "2.6.0"
}

View File

@@ -2,12 +2,12 @@
declare(strict_types=1);
namespace App\Controllers;
namespace Controllers;
use App\Core\IniFile;
use App\Core\Playlist;
use App\Exceptions\PlaylistNotFoundException;
use Core\IniFile;
use Core\Playlist;
use Exception;
use Exceptions\PlaylistNotFoundException;
use Flight;
use Random\RandomException;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\Controllers;
namespace Controllers;
use Exception;
use Flight;

View File

@@ -2,11 +2,11 @@
declare(strict_types=1);
namespace App\Controllers;
namespace Controllers;
use App\Core\ChannelLogo;
use App\Exceptions\PlaylistNotFoundException;
use Core\ChannelLogo;
use Exception;
use Exceptions\PlaylistNotFoundException;
use Flight;
/**

View File

@@ -2,9 +2,8 @@
declare(strict_types=1);
namespace App\Core;
namespace Core;
use App\Extensions\TwigFunctions;
use Flight;
use Twig\Environment;
use Twig\Extension\DebugExtension;
@@ -22,7 +21,7 @@ final class Bootstrapper
*/
public static function bootSettings(): void
{
$config = require_once config_path('app.php');
$config = require_once root_path('config.php');
foreach ($config as $key => $value) {
Flight::set($key, $value);
}
@@ -67,7 +66,7 @@ final class Bootstrapper
*/
public static function bootRoutes(): void
{
$routes = require_once config_path('routes.php');
$routes = require_once root_path('routes.php');
foreach ($routes as $route => $handler) {
Flight::route($route, $handler);
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\Core;
namespace Core;
class ChannelLogo implements \Stringable
{

View File

@@ -2,10 +2,10 @@
declare(strict_types=1);
namespace App\Core;
namespace Core;
use App\Exceptions\PlaylistNotFoundException;
use Exception;
use Exceptions\PlaylistNotFoundException;
/**
* Класс для работы с ini-файлом плейлистов
@@ -40,7 +40,7 @@ class IniFile
*/
public function load(): void
{
$filepath = config_path('playlists.ini');
$filepath = root_path('playlists.ini');
$this->updated_at = date('d.m.Y h:i', filemtime($filepath));
$this->rawIni = parse_ini_file($filepath, true);

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\Core;
namespace Core;
use Exception;
use Random\RandomException;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\Extensions;
namespace Core;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\Exceptions;
namespace Exceptions;
use Exception;

View File

@@ -17,17 +17,6 @@ function root_path(string $path = ''): string
return rtrim(sprintf('%s/%s', dirname($_SERVER['DOCUMENT_ROOT']), $path), '/');
}
/**
* Return path to application configuration directory
*
* @param string $path
* @return string
*/
function config_path(string $path = ''): string
{
return root_path("config/$path");
}
/**
* Returns path to app cache
*

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
use App\Core\Bootstrapper;
use Core\Bootstrapper;
use Symfony\Component\Dotenv\Dotenv;
/*

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -2,8 +2,8 @@
declare(strict_types=1);
use App\Controllers\HomeController;
use App\Controllers\PlaylistController;
use Controllers\HomeController;
use Controllers\PlaylistController;
return [
'GET /' => [HomeController::class, 'index'],