mirror of
https://github.com/Arrowar/StreamingCommunity.git
synced 2025-06-01 17:10:10 +00:00
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
This commit is contained in:
parent
32197a3c5d
commit
faf83765d0
329
.github/.site/css/style.css
vendored
Normal file
329
.github/.site/css/style.css
vendored
Normal file
@ -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;
|
||||
}
|
74
.github/.site/index.html
vendored
Normal file
74
.github/.site/index.html
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Streaming Directory</title>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<section class="container">
|
||||
<div class="sites-container">
|
||||
<div id="site-list" class="site-grid">
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="footer-content">
|
||||
<div class="footer-section">
|
||||
<h3 class="footer-title">Repository</h3>
|
||||
<ul class="footer-links">
|
||||
<li>
|
||||
<a href="https://github.com/Arrowar/StreamingCommunity" target="_blank" rel="noopener noreferrer">
|
||||
<i class="fab fa-github"></i>
|
||||
Project GitHub
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="footer-description">
|
||||
An updated collection of streaming sites. Contribute to the project on GitHub!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="footer-section">
|
||||
<h3 class="footer-title">Author</h3>
|
||||
<ul class="footer-links">
|
||||
<li>
|
||||
<a href="https://github.com/Arrowar" target="_blank" rel="noopener noreferrer">
|
||||
<i class="fas fa-user-tie"></i>
|
||||
Arrowar Profile
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="footer-description">
|
||||
Developer of the project.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="footer-section">
|
||||
<h3 class="footer-title">Info</h3>
|
||||
<ul class="footer-links">
|
||||
<li>
|
||||
<span class="update-note">
|
||||
<i class="fas fa-sync-alt"></i>
|
||||
Domains updated once every hour
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="footer-description">
|
||||
All domains are automatically updated once every hour.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="js/script.js"></script>
|
||||
</body>
|
||||
</html>
|
88
.github/.site/js/script.js
vendored
Normal file
88
.github/.site/js/script.js
vendored
Normal file
@ -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,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="%238c52ff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>';
|
||||
};
|
||||
|
||||
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 = `<span class="label">Previous domain:</span> ${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 = `<span class="label">Updated:</span> ${dateString}`;
|
||||
siteContent.appendChild(timeChange);
|
||||
}
|
||||
|
||||
const siteLink = document.createElement('a');
|
||||
siteLink.href = site.full_url;
|
||||
siteLink.target = '_blank';
|
||||
siteLink.innerHTML = 'Visit <i class="fas fa-external-link-alt"></i>';
|
||||
siteLink.rel = 'noopener noreferrer';
|
||||
|
||||
siteContent.appendChild(siteTitle);
|
||||
siteContent.appendChild(siteLink);
|
||||
siteItem.appendChild(siteIcon);
|
||||
siteItem.appendChild(siteContent);
|
||||
siteList.appendChild(siteItem);
|
||||
}
|
||||
} else {
|
||||
siteList.innerHTML = '<div class="no-sites">No sites available</div>';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Errore:', error);
|
||||
siteList.innerHTML = `
|
||||
<div class="error-message">
|
||||
<p>Errore nel caricamento</p>
|
||||
<button onclick="loadSiteData()" class="retry-button">Riprova</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', loadSiteData);
|
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -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 }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
45
.github/workflows/pages.yml
vendored
Normal file
45
.github/workflows/pages.yml
vendored
Normal file
@ -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
|
@ -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()
|
||||
self.client.close()
|
||||
|
@ -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()
|
||||
return media_search_manager.get_length()
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
time.sleep(4)
|
@ -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):
|
||||
|
@ -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]")
|
||||
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]")
|
||||
|
@ -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)
|
||||
TelegramSession.deleteScriptId(script_id)
|
||||
|
@ -6,9 +6,10 @@ m3u8
|
||||
certifi
|
||||
psutil
|
||||
unidecode
|
||||
dnspython
|
||||
jsbeautifier
|
||||
pathvalidate
|
||||
pycryptodomex
|
||||
ua-generator
|
||||
qbittorrent-api
|
||||
pyTelegramBotAPI
|
||||
pyTelegramBotAPI
|
||||
|
Loading…
x
Reference in New Issue
Block a user