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 @@
-
+
@@ -25,7 +25,7 @@
-
+
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 0000000..ff16d28
Binary files /dev/null and b/Test/Media/62809003.ico differ
diff --git a/Test/Util/loc-badge.json b/Test/Media/loc-badge.json
similarity index 100%
rename from Test/Util/loc-badge.json
rename to Test/Media/loc-badge.json
diff --git a/config.json b/config.json
index 98c88a8..11a0a66 100644
--- a/config.json
+++ b/config.json
@@ -28,7 +28,7 @@
"proxy_start_max": 0.5
},
"M3U8_DOWNLOAD": {
- "tqdm_delay": 0.05,
+ "tqdm_delay": 0.01,
"default_video_workser": 12,
"default_audio_workser": 12,
"download_audio": true,
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..abfd3b2
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,32 @@
+from setuptools import setup, find_packages
+
+def read_readme():
+ with open("README.md", "r", encoding="utf-8") as fh:
+ return fh.read()
+
+with open("requirements.txt", "r", encoding="utf-8-sig") as f:
+ required_packages = f.read().splitlines()
+ print(required_packages)
+
+setup(
+ name="StreamingCommunity",
+ version="2.5.2",
+ long_description=read_readme(),
+ long_description_content_type="text/markdown",
+ author="Lovi-0",
+ url="https://github.com/Lovi-0/StreamingCommunity",
+ packages=find_packages(include=["StreamingCommunity", "StreamingCommunity.*"]),
+ install_requires=required_packages,
+ python_requires='>=3.8',
+ entry_points={
+ "console_scripts": [
+ "streamingcommunity=StreamingCommunity.run:main",
+ ],
+ },
+ include_package_data=True,
+ keywords="streaming community",
+ project_urls={
+ "Bug Reports": "https://github.com/Lovi-0/StreamingCommunity/issues",
+ "Source": "https://github.com/Lovi-0/StreamingCommunity",
+ }
+)