From faf83765d0d580c51020f053da89453bf7460e38 Mon Sep 17 00:00:00 2001
From: None <62809003+Arrowar@users.noreply.github.com>
Date: Sat, 10 May 2025 09:17:37 +0200
Subject: [PATCH] Dev (#311)
* Update build.yml
* Update site.py
* Update requirements.txt
* Update os.py
* Update run.py
* Update global_search.py
* Update hdplayer.py
* Create index.html
* Create script.js
* Create style.css
* Create pages.yml
* Some fix
---
.github/.site/css/style.css | 329 ++++++++++++++++++
.github/.site/index.html | 74 ++++
.github/.site/js/script.js | 88 +++++
.github/workflows/build.yml | 3 +-
.github/workflows/pages.yml | 45 +++
StreamingCommunity/Api/Player/hdplayer.py | 24 +-
.../Api/Site/animeworld/site.py | 8 +-
StreamingCommunity/Lib/Proxies/proxy.py | 2 +-
StreamingCommunity/Upload/update.py | 45 +--
StreamingCommunity/Util/os.py | 38 ++
StreamingCommunity/global_search.py | 20 +-
StreamingCommunity/run.py | 13 +-
requirements.txt | 3 +-
13 files changed, 647 insertions(+), 45 deletions(-)
create mode 100644 .github/.site/css/style.css
create mode 100644 .github/.site/index.html
create mode 100644 .github/.site/js/script.js
create mode 100644 .github/workflows/pages.yml
diff --git a/.github/.site/css/style.css b/.github/.site/css/style.css
new file mode 100644
index 0000000..ee47051
--- /dev/null
+++ b/.github/.site/css/style.css
@@ -0,0 +1,329 @@
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
+
+:root {
+ --primary-color: #8c52ff;
+ --secondary-color: #6930c3;
+ --accent-color: #00e5ff;
+ --background-color: #121212;
+ --card-background: #1e1e1e;
+ --text-color: #f8f9fa;
+ --shadow-color: rgba(0, 0, 0, 0.25);
+ --card-hover: #2a2a2a;
+ --border-color: #333333;
+ --header-bg: rgba(18, 18, 18, 0.95);
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ transition: all 0.2s ease;
+}
+
+body {
+ font-family: 'Inter', 'Segoe UI', sans-serif;
+ background-color: var(--background-color);
+ color: var(--text-color);
+ line-height: 1.6;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+
+header {
+ background-color: var(--header-bg);
+ backdrop-filter: blur(10px);
+ position: fixed;
+ width: 100%;
+ padding: 15px 0;
+ z-index: 1000;
+ box-shadow: 0 2px 12px var(--shadow-color);
+}
+
+.container {
+ max-width: 1400px;
+ margin: 0 auto;
+ padding: 20px;
+ flex: 1;
+}
+
+.site-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+ gap: 24px;
+ padding: 2rem 0;
+}
+
+.site-item {
+ min-height: 280px;
+ background-color: var(--card-background);
+ border-radius: 16px;
+ padding: 30px;
+ box-shadow: 0 6px 20px var(--shadow-color);
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ border: 1px solid var(--border-color);
+ position: relative;
+ overflow: hidden;
+}
+
+.site-item::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 4px;
+ background: linear-gradient(90deg, var(--primary-color), var(--accent-color));
+}
+
+.site-item:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 12px 30px var(--shadow-color);
+}
+
+.site-item img {
+ width: 80px;
+ height: 80px;
+ margin-bottom: 1.5rem;
+ border-radius: 16px;
+ object-fit: cover;
+ border: 2px solid var(--border-color);
+}
+
+.site-content {
+ text-align: center;
+ width: 100%;
+}
+
+.site-item h3 {
+ font-size: 1.4rem;
+ font-weight: 600;
+ margin-bottom: 0.5rem;
+ color: var(--primary-color);
+}
+
+.domain {
+ color: var(--text-color);
+ opacity: 0.8;
+ font-size: 0.9rem;
+ margin-bottom: 1.5rem;
+ word-break: break-all;
+}
+
+.site-item a {
+ margin-top: 1rem;
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
+ color: white;
+ text-decoration: none;
+ font-weight: 500;
+ padding: 12px 28px;
+ border-radius: 8px;
+ width: fit-content;
+ margin: 0 auto;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.site-item a:hover {
+ opacity: 0.9;
+ transform: translateY(-2px);
+}
+
+footer {
+ background: var(--card-background);
+ border-top: 1px solid var(--border-color);
+ margin-top: auto;
+ padding: 40px 20px;
+ position: relative;
+}
+
+.footer-content {
+ max-width: 1200px;
+ margin: 0 auto;
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 30px;
+ position: relative;
+ padding: 10px 0;
+}
+
+.footer-section {
+ padding: 20px;
+ border-radius: 12px;
+ transition: transform 0.3s ease, background-color 0.3s ease;
+ background-color: var(--card-background);
+ border: 1px solid var(--border-color);
+}
+
+.footer-section:hover {
+ transform: translateY(-5px);
+ background-color: var(--card-hover);
+}
+
+.footer-title {
+ color: var(--accent-color);
+ font-size: 1.3rem;
+ margin-bottom: 1.5rem;
+ padding-bottom: 0.5rem;
+ position: relative;
+ letter-spacing: 0.5px;
+}
+
+.footer-title::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 60px;
+ height: 3px;
+ border-radius: 2px;
+ background: linear-gradient(90deg, var(--primary-color), var(--accent-color));
+}
+
+.footer-links {
+ list-style: none;
+}
+
+.footer-links li {
+ margin-bottom: 0.8rem;
+}
+
+.footer-links a {
+ color: var(--text-color);
+ text-decoration: none;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ opacity: 0.8;
+ transition: all 0.3s ease;
+ padding: 8px 12px;
+ border-radius: 8px;
+ background-color: transparent;
+}
+
+.footer-links a:hover {
+ opacity: 1;
+ color: var(--accent-color);
+ transform: translateX(8px);
+ background-color: rgba(140, 82, 255, 0.1);
+}
+
+.footer-links i {
+ width: 20px;
+ text-align: center;
+ font-size: 1.2rem;
+ color: var(--primary-color);
+ transition: transform 0.3s ease;
+}
+
+.footer-links a:hover i {
+ transform: scale(1.2);
+}
+
+.github-stats {
+ display: flex;
+ gap: 10px;
+ margin-top: 10px;
+ font-size: 0.8rem;
+}
+
+.github-badge {
+ background-color: var(--background-color);
+ padding: 4px 8px;
+ border-radius: 4px;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+}
+
+.github-badge i {
+ color: var(--accent-color);
+}
+
+.footer-description {
+ margin-top: 15px;
+ font-size: 0.9rem;
+ color: var(--text-color);
+ opacity: 0.8;
+ line-height: 1.5;
+}
+
+.update-info {
+ text-align: center;
+ margin-top: 30px;
+ padding-top: 30px;
+ border-top: 1px solid var(--border-color);
+}
+
+.update-note {
+ color: var(--accent-color);
+ font-size: 0.9rem;
+ opacity: 0.9;
+}
+
+@media (max-width: 768px) {
+ .footer-content {
+ grid-template-columns: 1fr;
+ text-align: center;
+ }
+
+ .footer-title::after {
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ .footer-links a {
+ justify-content: center;
+ }
+
+ .footer-links a:hover {
+ transform: translateY(-5px);
+ }
+
+ .footer-section {
+ margin-bottom: 20px;
+ }
+}
+
+.loader {
+ border: 3px solid var(--border-color);
+ border-top: 3px solid var(--primary-color);
+ border-right: 3px solid var(--accent-color);
+ border-radius: 50%;
+ width: 50px;
+ height: 50px;
+ animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+@media (max-width: 768px) {
+ .site-item {
+ padding: 25px;
+ }
+
+ .site-item img {
+ width: 70px;
+ height: 70px;
+ }
+}
+
+.old-domain, .time-change {
+ color: var(--text-color);
+ opacity: 0.7;
+ font-size: 0.85rem;
+ margin-bottom: 0.5rem;
+ word-break: break-all;
+}
+
+.label {
+ color: var(--accent-color);
+ font-weight: 500;
+}
diff --git a/.github/.site/index.html b/.github/.site/index.html
new file mode 100644
index 0000000..a9ac6d0
--- /dev/null
+++ b/.github/.site/index.html
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+ Streaming Directory
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.github/.site/js/script.js b/.github/.site/js/script.js
new file mode 100644
index 0000000..a79d13f
--- /dev/null
+++ b/.github/.site/js/script.js
@@ -0,0 +1,88 @@
+const supabaseUrl = 'https://zvfngpoxwrgswnzytadh.supabase.co';
+const supabaseKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inp2Zm5ncG94d3Jnc3duenl0YWRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDAxNTIxNjMsImV4cCI6MjA1NTcyODE2M30.FNTCCMwi0QaKjOu8gtZsT5yQttUW8QiDDGXmzkn89QE';
+
+async function loadSiteData() {
+ try {
+ const siteList = document.getElementById('site-list');
+ const headers = {
+ 'apikey': supabaseKey,
+ 'Authorization': `Bearer ${supabaseKey}`,
+ 'Content-Type': 'application/json'
+ };
+
+ const response = await fetch(`${supabaseUrl}/rest/v1/public`, {
+ method: 'GET',
+ headers: headers
+ });
+
+ if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
+
+ const data = await response.json();
+
+ siteList.innerHTML = '';
+
+ if (data && data.length > 0) {
+ const configSite = data[0].data;
+
+ for (const siteName in configSite) {
+ const site = configSite[siteName];
+ const siteItem = document.createElement('div');
+ siteItem.className = 'site-item';
+
+ const siteIcon = document.createElement('img');
+ siteIcon.src = `https://t2.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=${site.full_url}&size=128`;
+ siteIcon.alt = `${siteName} icon`;
+ siteIcon.onerror = function() {
+ this.src = 'data:image/svg+xml;utf8,';
+ };
+
+ const siteContent = document.createElement('div');
+ siteContent.className = 'site-content';
+
+ const siteTitle = document.createElement('h3');
+ siteTitle.textContent = siteName;
+
+ if (site.old_domain) {
+ const oldDomain = document.createElement('p');
+ oldDomain.className = 'old-domain';
+ oldDomain.innerHTML = `Previous domain: ${site.old_domain.replace(/^https?:\/\//, '')}`;
+ siteContent.appendChild(oldDomain);
+ }
+
+ if (site.time_change) {
+ const timeChange = document.createElement('p');
+ timeChange.className = 'time-change';
+
+ const changeDate = new Date(site.time_change);
+ const dateString = isNaN(changeDate) ? site.time_change : changeDate.toLocaleDateString();
+ timeChange.innerHTML = `Updated: ${dateString}`;
+ siteContent.appendChild(timeChange);
+ }
+
+ const siteLink = document.createElement('a');
+ siteLink.href = site.full_url;
+ siteLink.target = '_blank';
+ siteLink.innerHTML = 'Visit ';
+ siteLink.rel = 'noopener noreferrer';
+
+ siteContent.appendChild(siteTitle);
+ siteContent.appendChild(siteLink);
+ siteItem.appendChild(siteIcon);
+ siteItem.appendChild(siteContent);
+ siteList.appendChild(siteItem);
+ }
+ } else {
+ siteList.innerHTML = 'No sites available
';
+ }
+ } catch (error) {
+ console.error('Errore:', error);
+ siteList.innerHTML = `
+
+
Errore nel caricamento
+
+
+ `;
+ }
+}
+
+document.addEventListener('DOMContentLoaded', loadSiteData);
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 408e9b7..c15ccf3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -98,6 +98,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
+ python -m pip install --upgrade certifi
python -m pip install -r requirements.txt
python -m pip install pyinstaller
@@ -137,4 +138,4 @@ jobs:
tag_name: ${{ env.latest_tag }}
files: dist/${{ matrix.executable }}
env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
new file mode 100644
index 0000000..a0aa6f7
--- /dev/null
+++ b/.github/workflows/pages.yml
@@ -0,0 +1,45 @@
+on:
+ push:
+ branches: ["main"]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Pages
+ uses: actions/configure-pages@v5
+
+ - name: Copy site files
+ run: |
+ mkdir -p _site
+ cp -r .site/* _site/
+ ls -la _site/
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: _site
+
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/StreamingCommunity/Api/Player/hdplayer.py b/StreamingCommunity/Api/Player/hdplayer.py
index 124f7f5..f4cae0a 100644
--- a/StreamingCommunity/Api/Player/hdplayer.py
+++ b/StreamingCommunity/Api/Player/hdplayer.py
@@ -2,14 +2,13 @@
import re
-
# External library
import httpx
from bs4 import BeautifulSoup
# Internal utilities
-from StreamingCommunity.Util.headers import get_headers
+from StreamingCommunity.Util.headers import get_userAgent
from StreamingCommunity.Util.config_json import config_manager
@@ -19,7 +18,7 @@ MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
class VideoSource:
def __init__(self, proxy=None):
- self.client = httpx.Client(headers=get_headers(), timeout=MAX_TIMEOUT, proxy=proxy)
+ self.client = httpx.Client(headers={'user-agent': get_userAgent()}, timeout=MAX_TIMEOUT, proxy=proxy)
def extractLinkHdPlayer(self, response):
"""Extract iframe source from the page."""
@@ -34,6 +33,9 @@ class VideoSource:
Extract m3u8 URL from hdPlayer page.
"""
try:
+ base_domain = re.match(r'https?://(?:www\.)?([^/]+)', page_url).group(0)
+ self.client.headers.update({'referer': base_domain})
+
# Get the page content
response = self.client.get(page_url)
@@ -41,19 +43,17 @@ class VideoSource:
iframe_url = self.extractLinkHdPlayer(response)
if not iframe_url:
return None
-
+
# Get HDPlayer page content
response_hdplayer = self.client.get(iframe_url)
if response_hdplayer.status_code != 200:
return None
+
+ sources_pattern = r'file:"([^"]+)"'
+ match = re.search(sources_pattern, response_hdplayer.text)
- soup = BeautifulSoup(response_hdplayer.text, 'html.parser')
-
- # Find m3u8 URL in scripts
- for script in soup.find_all("script"):
- match = re.search(r'sources:\s*\[\{\s*file:\s*"([^"]+)"', script.text)
- if match:
- return match.group(1)
+ if match:
+ return match.group(1)
return None
@@ -62,4 +62,4 @@ class VideoSource:
return None
finally:
- self.client.close()
\ No newline at end of file
+ self.client.close()
diff --git a/StreamingCommunity/Api/Site/animeworld/site.py b/StreamingCommunity/Api/Site/animeworld/site.py
index e154c24..79d6aa8 100644
--- a/StreamingCommunity/Api/Site/animeworld/site.py
+++ b/StreamingCommunity/Api/Site/animeworld/site.py
@@ -31,7 +31,11 @@ def get_session_and_csrf() -> dict:
Get the session ID and CSRF token from the website's cookies and HTML meta data.
"""
# Send an initial GET request to the website
- response = httpx.get(site_constant.FULL_URL, headers=get_headers())
+ response = httpx.get(
+ site_constant.FULL_URL,
+ headers=get_headers(),
+ verify=False
+ )
# Extract the sessionId from the cookies
session_id = response.cookies.get('sessionId')
@@ -114,4 +118,4 @@ def title_search(query: str) -> int:
print(f"Error parsing a film entry: {e}")
# Return the length of media search manager
- return media_search_manager.get_length()
\ No newline at end of file
+ return media_search_manager.get_length()
diff --git a/StreamingCommunity/Lib/Proxies/proxy.py b/StreamingCommunity/Lib/Proxies/proxy.py
index f345ef6..1f108e7 100644
--- a/StreamingCommunity/Lib/Proxies/proxy.py
+++ b/StreamingCommunity/Lib/Proxies/proxy.py
@@ -103,7 +103,7 @@ class ProxyFinder:
return proxies
def fetch_proxies_from_sources(self) -> list:
- print("[cyan]Fetching proxies from sources...[/cyan]")
+ #print("[cyan]Fetching proxies from sources...[/cyan]")
with ThreadPoolExecutor(max_workers=3) as executor:
proxyscrape_future = executor.submit(self.fetch_proxyscrape)
geonode_future = executor.submit(self.fetch_geonode)
diff --git a/StreamingCommunity/Upload/update.py b/StreamingCommunity/Upload/update.py
index 031ba56..ee9fbb0 100644
--- a/StreamingCommunity/Upload/update.py
+++ b/StreamingCommunity/Upload/update.py
@@ -3,7 +3,7 @@
import os
import sys
import time
-
+import asyncio
# External library
import httpx
@@ -24,32 +24,33 @@ else:
base_path = os.path.dirname(__file__)
console = Console()
+async def fetch_github_data(client, url):
+ """Helper function to fetch data from GitHub API"""
+ response = await client.get(
+ url=url,
+ headers={'user-agent': get_userAgent()},
+ timeout=config_manager.get_int("REQUESTS", "timeout"),
+ follow_redirects=True
+ )
+ return response.json()
+
+async def async_github_requests():
+ """Make concurrent GitHub API requests"""
+ async with httpx.AsyncClient() as client:
+ tasks = [
+ fetch_github_data(client, f"https://api.github.com/repos/{__author__}/{__title__}"),
+ fetch_github_data(client, f"https://api.github.com/repos/{__author__}/{__title__}/releases"),
+ fetch_github_data(client, f"https://api.github.com/repos/{__author__}/{__title__}/commits")
+ ]
+ return await asyncio.gather(*tasks)
def update():
"""
Check for updates on GitHub and display relevant information.
"""
try:
- response_reposity = httpx.get(
- url=f"https://api.github.com/repos/{__author__}/{__title__}",
- headers={'user-agent': get_userAgent()},
- 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_userAgent()},
- timeout=config_manager.get_int("REQUESTS", "timeout"),
- follow_redirects=True
- ).json()
-
- response_commits = httpx.get(
- url=f"https://api.github.com/repos/{__author__}/{__title__}/commits",
- headers={'user-agent': get_userAgent()},
- timeout=config_manager.get_int("REQUESTS", "timeout"),
- follow_redirects=True
- ).json()
+ # Run async requests concurrently
+ response_reposity, response_releases, response_commits = asyncio.run(async_github_requests())
except Exception as e:
console.print(f"[red]Error accessing GitHub API: {e}")
@@ -92,4 +93,4 @@ def update():
console.print(f"\n[red]{__title__} has been downloaded [yellow]{total_download_count} [red]times, but only [yellow]{percentual_stars}% [red]of users have starred it.\n\
[cyan]Help the repository grow today by leaving a [yellow]star [cyan]and [yellow]sharing [cyan]it with others online!")
- time.sleep(3)
\ No newline at end of file
+ time.sleep(4)
\ No newline at end of file
diff --git a/StreamingCommunity/Util/os.py b/StreamingCommunity/Util/os.py
index 4b43eeb..8da5de1 100644
--- a/StreamingCommunity/Util/os.py
+++ b/StreamingCommunity/Util/os.py
@@ -19,6 +19,7 @@ from unidecode import unidecode
from rich.console import Console
from rich.prompt import Prompt
from pathvalidate import sanitize_filename, sanitize_filepath
+from dns.resolver import dns
# Internal utilities
@@ -282,6 +283,43 @@ class InternManager():
else:
return f"{bytes / (1024 * 1024):.2f} MB/s"
+ def check_dns_provider(self):
+ """
+ Check if the system's current DNS server matches any known DNS providers.
+
+ Returns:
+ bool: True if the current DNS server matches a known provider,
+ False if no match is found or in case of errors
+ """
+ dns_providers = {
+ "Cloudflare": ["1.1.1.1", "1.0.0.1"],
+ "Google": ["8.8.8.8", "8.8.4.4"],
+ "OpenDNS": ["208.67.222.222", "208.67.220.220"],
+ "Quad9": ["9.9.9.9", "149.112.112.112"],
+ "AdGuard": ["94.140.14.14", "94.140.15.15"],
+ "Comodo": ["8.26.56.26", "8.20.247.20"],
+ "Level3": ["209.244.0.3", "209.244.0.4"],
+ "Norton": ["199.85.126.10", "199.85.127.10"],
+ "CleanBrowsing": ["185.228.168.9", "185.228.169.9"],
+ "Yandex": ["77.88.8.8", "77.88.8.1"]
+ }
+
+ try:
+ resolver = dns.resolver.Resolver()
+ nameservers = resolver.nameservers
+
+ if not nameservers:
+ return False
+
+ for server in nameservers:
+ for provider, ips in dns_providers.items():
+ if server in ips:
+ return True
+ return False
+
+ except Exception:
+ return False
+
class OsSummary:
def __init__(self):
diff --git a/StreamingCommunity/global_search.py b/StreamingCommunity/global_search.py
index 3b65a18..968ec98 100644
--- a/StreamingCommunity/global_search.py
+++ b/StreamingCommunity/global_search.py
@@ -58,7 +58,10 @@ def load_search_functions():
# Get 'indice' from the module
indice = getattr(mod, 'indice', 0)
use_for = getattr(mod, '_useFor', 'other')
- modules.append((module_name, indice, use_for))
+ priority = getattr(mod, '_priority', 0)
+
+ if priority == 0:
+ modules.append((module_name, indice, use_for))
except Exception as e:
console.print(f"[red]Failed to import module {module_name}: {str(e)}")
@@ -296,17 +299,26 @@ def process_selected_item(selected_item, search_functions):
console.print(f"\n[bold green]Processing selection from:[/bold green] {selected_item.get('source')}")
# Extract necessary information to pass to the site's search function
- item_id = selected_item.get('id', selected_item.get('media_id'))
+ item_id = None
+ for id_field in ['id', 'media_id', 'ID', 'item_id', 'url']:
+ item_id = selected_item.get(id_field)
+ if item_id:
+ break
+
item_type = selected_item.get('type', selected_item.get('media_type', 'unknown'))
item_title = selected_item.get('title', selected_item.get('name', 'Unknown'))
if item_id:
console.print(f"[bold green]Selected item:[/bold green] {item_title} (ID: {item_id}, Type: {item_type})")
- # Call the site's search function with direct_item parameter to process download
try:
func(direct_item=selected_item)
+
except Exception as e:
console.print(f"[bold red]Error processing download:[/bold red] {str(e)}")
+ logging.exception("Download processing error")
+
else:
- console.print("[bold red]Error: Item ID not found.[/bold red]")
\ No newline at end of file
+ console.print("[bold red]Error: Item ID not found. Available fields:[/bold red]")
+ for key in selected_item.keys():
+ console.print(f"[yellow]- {key}: {selected_item[key]}[/yellow]")
diff --git a/StreamingCommunity/run.py b/StreamingCommunity/run.py
index 4c7446b..62855e4 100644
--- a/StreamingCommunity/run.py
+++ b/StreamingCommunity/run.py
@@ -21,7 +21,7 @@ from rich.prompt import Prompt
from .global_search import global_search
from StreamingCommunity.Util.message import start_message
from StreamingCommunity.Util.config_json import config_manager
-from StreamingCommunity.Util.os import os_summary
+from StreamingCommunity.Util.os import os_summary, internet_manager
from StreamingCommunity.Util.logger import Logger
from StreamingCommunity.Upload.update import update as git_update
from StreamingCommunity.Lib.TMBD import tmdb
@@ -200,6 +200,15 @@ def main(script_id = 0):
# Create logger
log_not = Logger()
initialize()
+
+ if not internet_manager.check_dns_provider():
+ console.print("[red]❌ ERROR: DNS configuration is required!")
+ console.print("[red]The program cannot function correctly without proper DNS settings.")
+ console.print("[yellow]Please configure one of these DNS servers:")
+ console.print("[blue]• Cloudflare (1.1.1.1)")
+ console.print("[blue]• Quad9 (9.9.9.9)")
+ console.print("\n[yellow]⚠️ The program will not work until you configure your DNS settings.")
+ input("[yellow]Press Enter to exit...")
# Load search functions
search_functions = load_search_functions()
@@ -381,4 +390,4 @@ def main(script_id = 0):
# Delete script_id
script_id = TelegramSession.get_session()
if script_id != "unknown":
- TelegramSession.deleteScriptId(script_id)
\ No newline at end of file
+ TelegramSession.deleteScriptId(script_id)
diff --git a/requirements.txt b/requirements.txt
index 0dca602..3790b61 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,9 +6,10 @@ m3u8
certifi
psutil
unidecode
+dnspython
jsbeautifier
pathvalidate
pycryptodomex
ua-generator
qbittorrent-api
-pyTelegramBotAPI
\ No newline at end of file
+pyTelegramBotAPI