From 468f3cf96698b050e42444f941bc1881669e0b92 Mon Sep 17 00:00:00 2001 From: Lovi <62809003+Lovi-0@users.noreply.github.com> Date: Thu, 6 Feb 2025 14:29:48 +0100 Subject: [PATCH] Fix cb01 --- .github/workflows/build.yml | 48 ++++++++++++++++++ .github/workflows/update-loc-badge.yml | 4 +- .gitignore | 2 - MANIFEST.in | 3 ++ README.md | 4 +- StreamingCommunity/Api/Site/cb01new/film.py | 1 - .../Lib/Downloader/HLS/downloader.py | 2 +- .../Lib/Downloader/HLS/segments.py | 12 ++--- StreamingCommunity/Upload/update.py | 24 +++++++-- StreamingCommunity/Util/message.py | 12 ++--- StreamingCommunity/Util/os.py | 22 -------- Test/Media/62809003.ico | Bin 0 -> 4474 bytes Test/{Util => Media}/loc-badge.json | 0 config.json | 2 +- setup.py | 32 ++++++++++++ 15 files changed, 120 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 MANIFEST.in create mode 100644 Test/Media/62809003.ico rename Test/{Util => Media}/loc-badge.json (100%) create mode 100644 setup.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..089c5cb --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,48 @@ +name: Build and Release with PyInstaller + +on: + workflow_dispatch: + +jobs: + build: + runs-on: windows-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Cache Python dependencies + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install fake-useragent==1.1.3 + + - name: Build executable with PyInstaller + run: | + pyinstaller --onefile --hidden-import=pycryptodomex --hidden-import=fake_useragent --hidden-import=qbittorrentapi --hidden-import=qbittorrent --hidden-import=googlesearch --hidden-import=bs4 --hidden-import=httpx --hidden-import=rich --hidden-import=tqdm --hidden-import=m3u8 --hidden-import=psutil --hidden-import=unidecode --hidden-import=jsbeautifier --hidden-import=pathvalidate --hidden-import=Cryptodome.Cipher --hidden-import=Cryptodome.Cipher.AES --hidden-import=Cryptodome.Util --hidden-import=Cryptodome.Util.Padding --hidden-import=Cryptodome.Random --hidden-import=Pillow --hidden-import=pyTelegramBotAPI --additional-hooks-dir=pyinstaller/hooks --add-data "StreamingCommunity;StreamingCommunity" --name=StreamingCommunity --icon="StreamingCommunity/Test/Media/62809003.ico" test_run.py + + - name: Upload executable as artifact + uses: actions/upload-artifact@v3 + with: + name: StreamingCommunity + path: dist/StreamingCommunity.exe + + - name: Create or update GitHub release + uses: softprops/action-gh-release@v1 + with: + files: dist/StreamingCommunity.exe + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/update-loc-badge.yml b/.github/workflows/update-loc-badge.yml index ab23e14..eadfba5 100644 --- a/.github/workflows/update-loc-badge.yml +++ b/.github/workflows/update-loc-badge.yml @@ -18,12 +18,12 @@ jobs: - name: Count Lines of Code run: | LOC=$(cloc . --json | jq '.SUM.code') - echo "{\"schemaVersion\": 1, \"label\": \"Lines of Code\", \"message\": \"$LOC\", \"color\": \"green\"}" > Test/Util/loc-badge.json + echo "{\"schemaVersion\": 1, \"label\": \"Lines of Code\", \"message\": \"$LOC\", \"color\": \"green\"}" > Test/Media/loc-badge.json - name: Commit and Push LOC Badge run: | git config --local user.name "GitHub Actions" git config --local user.email "actions@github.com" - git add Test/Util/loc-badge.json + git add Test/Media/loc-badge.json git commit -m "Update lines of code badge" || echo "No changes to commit" git push \ No newline at end of file diff --git a/.gitignore b/.gitignore index 231113a..d7cc0b7 100644 --- a/.gitignore +++ b/.gitignore @@ -23,8 +23,6 @@ share/python-wheels/ # PyInstaller *.manifest *.spec -setup.py -MANIFEST.in # Installer logs pip-log.txt diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..e02a32e --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +recursive-include StreamingCommunity * +recursive-include StreamingCommunity/Api * +recursive-include StreamingCommunity/Lib * \ No newline at end of file diff --git a/README.md b/README.md index 0381241..88c0e0a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- Project Logo + Project Logo

@@ -25,7 +25,7 @@ PyPI Downloads - Lines of Code + Lines of Code

diff --git a/StreamingCommunity/Api/Site/cb01new/film.py b/StreamingCommunity/Api/Site/cb01new/film.py index 249329d..392612b 100644 --- a/StreamingCommunity/Api/Site/cb01new/film.py +++ b/StreamingCommunity/Api/Site/cb01new/film.py @@ -37,7 +37,6 @@ def download_film(select_title: MediaItem) -> str: console.print(f"[cyan]You can safely stop the download with [bold]Ctrl+c[bold] [cyan] \n") # Setup api manger - print(select_title.url) video_source = VideoSource(select_title.url) # Define output path diff --git a/StreamingCommunity/Lib/Downloader/HLS/downloader.py b/StreamingCommunity/Lib/Downloader/HLS/downloader.py index 4fbb583..e3e124c 100644 --- a/StreamingCommunity/Lib/Downloader/HLS/downloader.py +++ b/StreamingCommunity/Lib/Downloader/HLS/downloader.py @@ -506,8 +506,8 @@ class HLS_Downloader: file_size = internet_manager.format_file_size(os.path.getsize(self.path_manager.output_path)) duration = print_duration_table(self.path_manager.output_path, description=False, return_string=True) + print() panel_content = ( - f"[bold green]Download completed![/bold green]\n" f"[cyan]File size: [bold red]{file_size}[/bold red]\n" f"[cyan]Duration: [bold]{duration}[/bold]\n" f"[cyan]Output: [bold]{os.path.abspath(self.path_manager.output_path)}[/bold]" diff --git a/StreamingCommunity/Lib/Downloader/HLS/segments.py b/StreamingCommunity/Lib/Downloader/HLS/segments.py index b17b453..cfc0da5 100644 --- a/StreamingCommunity/Lib/Downloader/HLS/segments.py +++ b/StreamingCommunity/Lib/Downloader/HLS/segments.py @@ -87,6 +87,7 @@ class M3U8_Segments: self.info_maxRetry = 0 self.info_nRetry = 0 self.info_nFailed = 0 + self.active_retries = 0 self.active_retries_lock = threading.Lock() @@ -170,7 +171,8 @@ class M3U8_Segments: client_params = { 'headers': random_headers(self.key_base_url) if hasattr(self, 'key_base_url') else {'User-Agent': get_headers()}, 'timeout': MAX_TIMEOOUT, - 'follow_redirects': True + 'follow_redirects': True, + 'http2': False } if THERE_IS_PROXY_LIST and index is not None and hasattr(self, 'valid_proxy'): @@ -178,7 +180,7 @@ class M3U8_Segments: return httpx.Client(**client_params) - def download_segment(self, ts_url: str, index: int, progress_bar: tqdm, backoff_factor: float = 1.3) -> None: + def download_segment(self, ts_url: str, index: int, progress_bar: tqdm, backoff_factor: float = 1.1) -> None: """ Downloads a TS segment and adds it to the segment queue with retry logic. @@ -186,7 +188,6 @@ class M3U8_Segments: - ts_url (str): The URL of the TS segment. - index (int): The index of the segment. - progress_bar (tqdm): Progress counter for tracking download progress. - - retries (int): The number of times to retry on failure (default is 3). - backoff_factor (float): The backoff factor for exponential backoff (default is 1.5 seconds). """ for attempt in range(REQUEST_MAX_RETRY): @@ -289,7 +290,7 @@ class M3U8_Segments: buffer[index] = segment_content except queue.Empty: - self.current_timeout = min(MAX_TIMEOOUT, self.current_timeout * 1.25) + self.current_timeout = min(MAX_TIMEOOUT, self.current_timeout * 1.1) if self.stop_event.is_set(): break @@ -323,7 +324,7 @@ class M3U8_Segments: # Configure workers and delay max_workers = self._get_worker_count(type) delay = max(PROXY_START_MIN, min(PROXY_START_MAX, 1 / (len(self.valid_proxy) + 1))) if THERE_IS_PROXY_LIST else TQDM_DELAY_WORKER - + # Download segments with completion verification with ThreadPoolExecutor(max_workers=max_workers) as executor: futures = [] @@ -373,7 +374,6 @@ class M3U8_Segments: return self._generate_results(type) - def _get_bar_format(self, description: str) -> str: """ Generate platform-appropriate progress bar format. diff --git a/StreamingCommunity/Upload/update.py b/StreamingCommunity/Upload/update.py index 39fd94b..566c355 100644 --- a/StreamingCommunity/Upload/update.py +++ b/StreamingCommunity/Upload/update.py @@ -5,14 +5,17 @@ import sys import time +# External library +import httpx + + # Internal utilities from .version import __version__, __author__, __title__ from StreamingCommunity.Util.console import console +from StreamingCommunity.Util._jsonConfig import config_manager +from StreamingCommunity.Util.headers import get_headers -# External library -import httpx - # Variable if getattr(sys, 'frozen', False): # Modalità PyInstaller @@ -26,8 +29,19 @@ def update(): Check for updates on GitHub and display relevant information. """ try: - response_reposity = httpx.get(f"https://api.github.com/repos/{__author__}/{__title__}").json() - response_releases = httpx.get(f"https://api.github.com/repos/{__author__}/{__title__}/releases").json() + response_reposity = httpx.get( + url=f"https://api.github.com/repos/{__author__}/{__title__}", + headers={'user-agent': get_headers()}, + timeout=config_manager.get_int("REQUESTS", "timeout"), + follow_redirects=True + ).json() + + response_releases = httpx.get( + url=f"https://api.github.com/repos/{__author__}/{__title__}/releases", + headers={'user-agent': get_headers()}, + timeout=config_manager.get_int("REQUESTS", "timeout"), + follow_redirects=True + ).json() except Exception as e: console.print(f"[red]Error accessing GitHub API: {e}") diff --git a/StreamingCommunity/Util/message.py b/StreamingCommunity/Util/message.py index 804541c..96aee0a 100644 --- a/StreamingCommunity/Util/message.py +++ b/StreamingCommunity/Util/message.py @@ -17,12 +17,12 @@ def start_message(): """Display a stylized start message in the console.""" msg = r''' - __ __ _ _____ __ _ - / //_/(_)________ ____ _ __ / ___// /_________ ____ _____ ___ (_)___ ____ _ - / ,< / / ___/ __ \/ __ \ | |/_/ \__ \/ __/ ___/ _ \/ __ `/ __ `__ \/ / __ \/ __ `/ - / /| |/ / / / /_/ / / / / _> < ___/ / /_/ / / __/ /_/ / / / / / / / / / / /_/ / -/_/ |_/_/_/ \____/_/ /_/ /_/|_| /____/\__/_/ \___/\__,_/_/ /_/ /_/_/_/ /_/\__, / - /____/ + ___ _____ __ _ + / | ______________ _ ______ ______ _ __ / ___// /_________ ____ _____ ___ (_)___ ____ _ + / /| | / ___/ ___/ __ \ | /| / / __ `/ ___/ | |/_/ \__ \/ __/ ___/ _ \/ __ `/ __ `__ \/ / __ \/ __ `/ + / ___ |/ / / / / /_/ / |/ |/ / /_/ / / _> < ___/ / /_/ / / __/ /_/ / / / / / / / / / / /_/ / +/_/ |_/_/ /_/ \____/|__/|__/\__,_/_/ /_/|_| /____/\__/_/ \___/\__,_/_/ /_/ /_/_/_/ /_/\__, / + /____/ '''.rstrip() if CLEAN: diff --git a/StreamingCommunity/Util/os.py b/StreamingCommunity/Util/os.py index fb8479c..90216d0 100644 --- a/StreamingCommunity/Util/os.py +++ b/StreamingCommunity/Util/os.py @@ -307,24 +307,6 @@ class OsSummary: else: # linux return os.path.join(home, '.local', 'bin', 'binary') - def get_executable_version(self, command: list): - """ - Get the version of a given command-line executable. - - Args: - command (list): The command to run, e.g., `['ffmpeg', '-version']`. - - Returns: - str: The version string of the executable. - """ - try: - version_output = subprocess.check_output(command, stderr=subprocess.STDOUT).decode().split('\n')[0] - return version_output.split(" ")[2] - - except (FileNotFoundError, subprocess.CalledProcessError): - console.print(f"{command[0]} not found", style="bold red") - sys.exit(0) - def check_ffmpeg_location(self, command: list) -> str: """ Check if a specific executable (ffmpeg or ffprobe) is located using the given command. @@ -464,11 +446,7 @@ class OsSummary: console.log("[red]Can't locate ffmpeg or ffprobe") sys.exit(0) - ffmpeg_version = self.get_executable_version([self.ffmpeg_path, '-version']) - ffprobe_version = self.get_executable_version([self.ffprobe_path, '-version']) - console.print(f"[cyan]Path[white]: [red]ffmpeg [bold yellow]'{self.ffmpeg_path}'[/bold yellow][white], [red]ffprobe '[bold yellow]{self.ffprobe_path}'[/bold yellow]") - console.print(f"[cyan]Exe versions[white]: [bold red]ffmpeg {ffmpeg_version}, ffprobe {ffprobe_version}[/bold red]") # Handle requirements.txt if not getattr(sys, 'frozen', False): diff --git a/Test/Media/62809003.ico b/Test/Media/62809003.ico new file mode 100644 index 0000000000000000000000000000000000000000..ff16d28d891275f2a8d05aac771ad2b040a7da04 GIT binary patch literal 4474 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