StreamingCommunity 1.7.6__py3-none-any.whl → 1.9.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of StreamingCommunity might be problematic. Click here for more details.
- StreamingCommunity/{Src/Api → Api}/Player/Helper/Vixcloud/js_parser.py +4 -1
- StreamingCommunity/{Src/Api → Api}/Player/Helper/Vixcloud/util.py +166 -166
- StreamingCommunity/{Src/Api → Api}/Player/ddl.py +89 -89
- StreamingCommunity/{Src/Api → Api}/Player/maxstream.py +151 -151
- StreamingCommunity/{Src/Api → Api}/Player/supervideo.py +193 -193
- StreamingCommunity/{Src/Api → Api}/Player/vixcloud.py +224 -212
- StreamingCommunity/{Src/Api → Api}/Site/1337xx/__init__.py +50 -50
- StreamingCommunity/{Src/Api → Api}/Site/1337xx/costant.py +15 -15
- StreamingCommunity/{Src/Api → Api}/Site/1337xx/site.py +83 -83
- StreamingCommunity/{Src/Api → Api}/Site/1337xx/title.py +66 -66
- StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/__init__.py +50 -50
- StreamingCommunity/{Src/Api/Site/mostraguarda → Api/Site/altadefinizione}/costant.py +15 -15
- StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/film.py +69 -69
- StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/site.py +86 -86
- StreamingCommunity/{Src/Api → Api}/Site/animeunity/__init__.py +50 -50
- StreamingCommunity/{Src/Api/Site/altadefinizione → Api/Site/animeunity}/costant.py +15 -15
- StreamingCommunity/{Src/Api → Api}/Site/animeunity/film_serie.py +130 -131
- StreamingCommunity/{Src/Api → Api}/Site/animeunity/site.py +164 -164
- StreamingCommunity/{Src/Api → Api}/Site/animeunity/util/ScrapeSerie.py +3 -3
- StreamingCommunity/{Src/Api → Api}/Site/bitsearch/__init__.py +51 -51
- StreamingCommunity/{Src/Api → Api}/Site/bitsearch/costant.py +15 -15
- StreamingCommunity/{Src/Api → Api}/Site/bitsearch/site.py +84 -84
- StreamingCommunity/{Src/Api → Api}/Site/bitsearch/title.py +47 -47
- StreamingCommunity/{Src/Api → Api}/Site/cb01new/__init__.py +51 -51
- StreamingCommunity/{Src/Api → Api}/Site/cb01new/costant.py +15 -15
- StreamingCommunity/{Src/Api → Api}/Site/cb01new/film.py +69 -69
- StreamingCommunity/{Src/Api → Api}/Site/cb01new/site.py +74 -74
- StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/__init__.py +57 -57
- StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/costant.py +16 -16
- StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/series.py +141 -142
- StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/site.py +92 -92
- StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/util/ScrapeSerie.py +84 -82
- StreamingCommunity/{Src/Api → Api}/Site/guardaserie/__init__.py +52 -52
- StreamingCommunity/{Src/Api/Site/piratebays → Api/Site/guardaserie}/costant.py +15 -15
- StreamingCommunity/{Src/Api → Api}/Site/guardaserie/series.py +195 -195
- StreamingCommunity/{Src/Api → Api}/Site/guardaserie/site.py +84 -84
- StreamingCommunity/{Src/Api → Api}/Site/guardaserie/util/ScrapeSerie.py +110 -110
- StreamingCommunity/{Src/Api → Api}/Site/mostraguarda/__init__.py +48 -48
- StreamingCommunity/{Src/Api/Site/animeunity → Api/Site/mostraguarda}/costant.py +15 -15
- StreamingCommunity/{Src/Api → Api}/Site/mostraguarda/film.py +94 -94
- StreamingCommunity/{Src/Api → Api}/Site/piratebays/__init__.py +50 -50
- StreamingCommunity/{Src/Api/Site/guardaserie → Api/Site/piratebays}/costant.py +15 -15
- StreamingCommunity/{Src/Api → Api}/Site/piratebays/site.py +88 -88
- StreamingCommunity/{Src/Api → Api}/Site/piratebays/title.py +45 -45
- StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/__init__.py +55 -55
- StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/costant.py +15 -15
- StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/film.py +70 -70
- StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/series.py +205 -203
- StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/site.py +125 -125
- StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/util/ScrapeSerie.py +3 -3
- StreamingCommunity/{Src/Api → Api}/Template/Class/SearchType.py +101 -101
- StreamingCommunity/{Src/Api → Api}/Template/Util/__init__.py +4 -4
- StreamingCommunity/{Src/Api → Api}/Template/Util/get_domain.py +137 -137
- StreamingCommunity/{Src/Api → Api}/Template/Util/manage_ep.py +153 -153
- StreamingCommunity/{Src/Api → Api}/Template/Util/recall_search.py +37 -37
- StreamingCommunity/Api/Template/__init__.py +3 -0
- StreamingCommunity/{Src/Api → Api}/Template/site.py +87 -87
- StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/downloader.py +968 -968
- StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/proxyes.py +110 -110
- StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/segments.py +538 -540
- StreamingCommunity/{Src/Lib → Lib}/Downloader/MP4/downloader.py +156 -156
- StreamingCommunity/{Src/Lib → Lib}/Downloader/TOR/downloader.py +222 -222
- StreamingCommunity/{Src/Lib → Lib}/Downloader/__init__.py +4 -4
- StreamingCommunity/{Src/Lib → Lib}/Driver/driver_1.py +76 -76
- StreamingCommunity/{Src/Lib → Lib}/FFmpeg/__init__.py +4 -4
- StreamingCommunity/{Src/Lib → Lib}/FFmpeg/capture.py +170 -170
- StreamingCommunity/{Src/Lib → Lib}/FFmpeg/command.py +292 -292
- StreamingCommunity/{Src/Lib → Lib}/FFmpeg/util.py +241 -241
- StreamingCommunity/{Src/Lib → Lib}/M3U8/__init__.py +5 -5
- StreamingCommunity/{Src/Lib → Lib}/M3U8/decryptor.py +164 -129
- StreamingCommunity/{Src/Lib → Lib}/M3U8/estimator.py +175 -172
- StreamingCommunity/{Src/Lib → Lib}/M3U8/parser.py +666 -666
- StreamingCommunity/{Src/Lib → Lib}/M3U8/url_fixer.py +51 -51
- StreamingCommunity/Lib/TMBD/__init__.py +2 -0
- StreamingCommunity/{Src/Lib → Lib}/TMBD/obj_tmbd.py +39 -39
- StreamingCommunity/{Src/Lib → Lib}/TMBD/tmdb.py +345 -345
- StreamingCommunity/{Src/Upload → Upload}/update.py +68 -64
- StreamingCommunity/{Src/Upload → Upload}/version.py +5 -5
- StreamingCommunity/{Src/Util → Util}/_jsonConfig.py +204 -204
- StreamingCommunity/{Src/Util → Util}/call_stack.py +42 -42
- StreamingCommunity/{Src/Util → Util}/color.py +20 -20
- StreamingCommunity/{Src/Util → Util}/console.py +12 -12
- StreamingCommunity/Util/ffmpeg_installer.py +275 -0
- StreamingCommunity/{Src/Util → Util}/headers.py +147 -147
- StreamingCommunity/{Src/Util → Util}/logger.py +53 -53
- StreamingCommunity/{Src/Util → Util}/message.py +46 -46
- StreamingCommunity/{Src/Util → Util}/os.py +514 -417
- StreamingCommunity/{Src/Util → Util}/table.py +163 -163
- StreamingCommunity/run.py +202 -196
- {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/METADATA +126 -60
- StreamingCommunity-1.9.1.dist-info/RECORD +95 -0
- {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/WHEEL +1 -1
- StreamingCommunity/Src/Api/Site/animeunity/anime.py +0 -126
- StreamingCommunity/Src/Api/Site/ddlstreamitaly/Player/ScrapeSerie.py +0 -83
- StreamingCommunity/Src/Api/Site/guardaserie/Player/ScrapeSerie.py +0 -110
- StreamingCommunity/Src/Api/Template/__init__.py +0 -3
- StreamingCommunity/Src/Lib/TMBD/__init__.py +0 -2
- StreamingCommunity-1.7.6.dist-info/RECORD +0 -97
- {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/LICENSE +0 -0
- {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/entry_points.txt +0 -0
- {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/top_level.txt +0 -0
|
@@ -8,9 +8,9 @@ import httpx
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
# Internal utilities
|
|
11
|
-
from StreamingCommunity.
|
|
12
|
-
from StreamingCommunity.
|
|
13
|
-
from StreamingCommunity.
|
|
11
|
+
from StreamingCommunity.Util.headers import get_headers
|
|
12
|
+
from StreamingCommunity.Util._jsonConfig import config_manager
|
|
13
|
+
from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager, EpisodeManager
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
# Variable
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
# 07.07.24
|
|
2
|
-
|
|
3
|
-
from typing import List, TypedDict
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class MediaItemData(TypedDict, total=False):
|
|
7
|
-
id: int # GENERAL
|
|
8
|
-
name: str # GENERAL
|
|
9
|
-
type: str # GENERAL
|
|
10
|
-
url: str # GENERAL
|
|
11
|
-
size: str # GENERAL
|
|
12
|
-
score: str # GENERAL
|
|
13
|
-
date: str # GENERAL
|
|
14
|
-
desc: str # GENERAL
|
|
15
|
-
|
|
16
|
-
seeder: int # TOR
|
|
17
|
-
leecher: int # TOR
|
|
18
|
-
|
|
19
|
-
slug: str # SC
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class MediaItemMeta(type):
|
|
24
|
-
def __new__(cls, name, bases, dct):
|
|
25
|
-
def init(self, **kwargs):
|
|
26
|
-
for key, value in kwargs.items():
|
|
27
|
-
setattr(self, key, value)
|
|
28
|
-
|
|
29
|
-
dct['__init__'] = init
|
|
30
|
-
|
|
31
|
-
def get_attr(self, item):
|
|
32
|
-
return self.__dict__.get(item, None)
|
|
33
|
-
|
|
34
|
-
dct['__getattr__'] = get_attr
|
|
35
|
-
|
|
36
|
-
def set_attr(self, key, value):
|
|
37
|
-
self.__dict__[key] = value
|
|
38
|
-
|
|
39
|
-
dct['__setattr__'] = set_attr
|
|
40
|
-
|
|
41
|
-
return super().__new__(cls, name, bases, dct)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class MediaItem(metaclass=MediaItemMeta):
|
|
45
|
-
id: int # GENERAL
|
|
46
|
-
name: str # GENERAL
|
|
47
|
-
type: str # GENERAL
|
|
48
|
-
url: str # GENERAL
|
|
49
|
-
size: str # GENERAL
|
|
50
|
-
score: str # GENERAL
|
|
51
|
-
date: str # GENERAL
|
|
52
|
-
desc: str # GENERAL
|
|
53
|
-
|
|
54
|
-
seeder: int # TOR
|
|
55
|
-
leecher: int # TOR
|
|
56
|
-
|
|
57
|
-
slug: str # SC
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
class MediaManager:
|
|
61
|
-
def __init__(self):
|
|
62
|
-
self.media_list: List[MediaItem] = []
|
|
63
|
-
|
|
64
|
-
def add_media(self, data: dict) -> None:
|
|
65
|
-
"""
|
|
66
|
-
Add media to the list.
|
|
67
|
-
|
|
68
|
-
Args:
|
|
69
|
-
data (dict): Media data to add.
|
|
70
|
-
"""
|
|
71
|
-
self.media_list.append(MediaItem(**data))
|
|
72
|
-
|
|
73
|
-
def get(self, index: int) -> MediaItem:
|
|
74
|
-
"""
|
|
75
|
-
Get a media item from the list by index.
|
|
76
|
-
|
|
77
|
-
Args:
|
|
78
|
-
index (int): The index of the media item to retrieve.
|
|
79
|
-
|
|
80
|
-
Returns:
|
|
81
|
-
MediaItem: The media item at the specified index.
|
|
82
|
-
"""
|
|
83
|
-
return self.media_list[index]
|
|
84
|
-
|
|
85
|
-
def get_length(self) -> int:
|
|
86
|
-
"""
|
|
87
|
-
Get the number of media items in the list.
|
|
88
|
-
|
|
89
|
-
Returns:
|
|
90
|
-
int: Number of media items.
|
|
91
|
-
"""
|
|
92
|
-
return len(self.media_list)
|
|
93
|
-
|
|
94
|
-
def clear(self) -> None:
|
|
95
|
-
"""
|
|
96
|
-
This method clears the media list.
|
|
97
|
-
"""
|
|
98
|
-
self.media_list.clear()
|
|
99
|
-
|
|
100
|
-
def __str__(self):
|
|
101
|
-
return f"MediaManager(num_media={len(self.media_list)})"
|
|
1
|
+
# 07.07.24
|
|
2
|
+
|
|
3
|
+
from typing import List, TypedDict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MediaItemData(TypedDict, total=False):
|
|
7
|
+
id: int # GENERAL
|
|
8
|
+
name: str # GENERAL
|
|
9
|
+
type: str # GENERAL
|
|
10
|
+
url: str # GENERAL
|
|
11
|
+
size: str # GENERAL
|
|
12
|
+
score: str # GENERAL
|
|
13
|
+
date: str # GENERAL
|
|
14
|
+
desc: str # GENERAL
|
|
15
|
+
|
|
16
|
+
seeder: int # TOR
|
|
17
|
+
leecher: int # TOR
|
|
18
|
+
|
|
19
|
+
slug: str # SC
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class MediaItemMeta(type):
|
|
24
|
+
def __new__(cls, name, bases, dct):
|
|
25
|
+
def init(self, **kwargs):
|
|
26
|
+
for key, value in kwargs.items():
|
|
27
|
+
setattr(self, key, value)
|
|
28
|
+
|
|
29
|
+
dct['__init__'] = init
|
|
30
|
+
|
|
31
|
+
def get_attr(self, item):
|
|
32
|
+
return self.__dict__.get(item, None)
|
|
33
|
+
|
|
34
|
+
dct['__getattr__'] = get_attr
|
|
35
|
+
|
|
36
|
+
def set_attr(self, key, value):
|
|
37
|
+
self.__dict__[key] = value
|
|
38
|
+
|
|
39
|
+
dct['__setattr__'] = set_attr
|
|
40
|
+
|
|
41
|
+
return super().__new__(cls, name, bases, dct)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class MediaItem(metaclass=MediaItemMeta):
|
|
45
|
+
id: int # GENERAL
|
|
46
|
+
name: str # GENERAL
|
|
47
|
+
type: str # GENERAL
|
|
48
|
+
url: str # GENERAL
|
|
49
|
+
size: str # GENERAL
|
|
50
|
+
score: str # GENERAL
|
|
51
|
+
date: str # GENERAL
|
|
52
|
+
desc: str # GENERAL
|
|
53
|
+
|
|
54
|
+
seeder: int # TOR
|
|
55
|
+
leecher: int # TOR
|
|
56
|
+
|
|
57
|
+
slug: str # SC
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class MediaManager:
|
|
61
|
+
def __init__(self):
|
|
62
|
+
self.media_list: List[MediaItem] = []
|
|
63
|
+
|
|
64
|
+
def add_media(self, data: dict) -> None:
|
|
65
|
+
"""
|
|
66
|
+
Add media to the list.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
data (dict): Media data to add.
|
|
70
|
+
"""
|
|
71
|
+
self.media_list.append(MediaItem(**data))
|
|
72
|
+
|
|
73
|
+
def get(self, index: int) -> MediaItem:
|
|
74
|
+
"""
|
|
75
|
+
Get a media item from the list by index.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
index (int): The index of the media item to retrieve.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
MediaItem: The media item at the specified index.
|
|
82
|
+
"""
|
|
83
|
+
return self.media_list[index]
|
|
84
|
+
|
|
85
|
+
def get_length(self) -> int:
|
|
86
|
+
"""
|
|
87
|
+
Get the number of media items in the list.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
int: Number of media items.
|
|
91
|
+
"""
|
|
92
|
+
return len(self.media_list)
|
|
93
|
+
|
|
94
|
+
def clear(self) -> None:
|
|
95
|
+
"""
|
|
96
|
+
This method clears the media list.
|
|
97
|
+
"""
|
|
98
|
+
self.media_list.clear()
|
|
99
|
+
|
|
100
|
+
def __str__(self):
|
|
101
|
+
return f"MediaManager(num_media={len(self.media_list)})"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
# 23.11.24
|
|
2
|
-
|
|
3
|
-
from .recall_search import execute_search
|
|
4
|
-
from .get_domain import search_domain
|
|
1
|
+
# 23.11.24
|
|
2
|
+
|
|
3
|
+
from .recall_search import execute_search
|
|
4
|
+
from .get_domain import search_domain
|
|
5
5
|
from .manage_ep import manage_selection, map_episode_title, validate_episode_selection, validate_selection
|
|
@@ -1,137 +1,137 @@
|
|
|
1
|
-
# 18.06.24
|
|
2
|
-
|
|
3
|
-
import sys
|
|
4
|
-
from urllib.parse import urlparse
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# External libraries
|
|
8
|
-
import httpx
|
|
9
|
-
from googlesearch import search
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# Internal utilities
|
|
13
|
-
from StreamingCommunity.
|
|
14
|
-
from StreamingCommunity.
|
|
15
|
-
from StreamingCommunity.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def google_search(query):
|
|
19
|
-
"""
|
|
20
|
-
Perform a Google search and return the first result.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
query (str): The search query to execute on Google.
|
|
24
|
-
|
|
25
|
-
Returns:
|
|
26
|
-
str: The first URL result from the search, or None if no result is found.
|
|
27
|
-
"""
|
|
28
|
-
# Perform the search on Google and limit to 1 result
|
|
29
|
-
search_results = search(query, num_results=1)
|
|
30
|
-
|
|
31
|
-
# Extract the first result
|
|
32
|
-
first_result = next(search_results, None)
|
|
33
|
-
|
|
34
|
-
if not first_result:
|
|
35
|
-
console.print("[red]No results found.[/red]")
|
|
36
|
-
|
|
37
|
-
return first_result
|
|
38
|
-
|
|
39
|
-
def get_final_redirect_url(initial_url, max_timeout):
|
|
40
|
-
"""
|
|
41
|
-
Follow redirects from the initial URL and return the final URL after all redirects.
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
initial_url (str): The URL to start with and follow redirects.
|
|
45
|
-
|
|
46
|
-
Returns:
|
|
47
|
-
str: The final URL after all redirects are followed.
|
|
48
|
-
"""
|
|
49
|
-
|
|
50
|
-
# Create a client with redirects enabled
|
|
51
|
-
try:
|
|
52
|
-
with httpx.Client(follow_redirects=True, timeout=max_timeout, headers={'user-agent': get_headers()}) as client:
|
|
53
|
-
response = client.get(initial_url)
|
|
54
|
-
response.raise_for_status()
|
|
55
|
-
|
|
56
|
-
# Capture the final URL after all redirects
|
|
57
|
-
final_url = response.url
|
|
58
|
-
|
|
59
|
-
return final_url
|
|
60
|
-
|
|
61
|
-
except Exception as e:
|
|
62
|
-
console.print(f"[cyan]Test url[white]: [red]{initial_url}, [cyan]error[white]: [red]{e}")
|
|
63
|
-
return None
|
|
64
|
-
|
|
65
|
-
def search_domain(site_name: str, base_url: str):
|
|
66
|
-
"""
|
|
67
|
-
Search for a valid domain for the given site name and base URL.
|
|
68
|
-
|
|
69
|
-
Parameters:
|
|
70
|
-
- site_name (str): The name of the site to search the domain for.
|
|
71
|
-
- base_url (str): The base URL to construct complete URLs.
|
|
72
|
-
- follow_redirects (bool): To follow redirect url or not.
|
|
73
|
-
|
|
74
|
-
Returns:
|
|
75
|
-
tuple: The found domain and the complete URL.
|
|
76
|
-
"""
|
|
77
|
-
|
|
78
|
-
# Extract config domain
|
|
79
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
80
|
-
domain = str(config_manager.get_dict("SITE", site_name)['domain'])
|
|
81
|
-
|
|
82
|
-
try:
|
|
83
|
-
|
|
84
|
-
# Test the current domain
|
|
85
|
-
response_follow = httpx.get(f"{base_url}.{domain}", headers={'user-agent': get_headers()}, timeout=max_timeout, follow_redirects=True)
|
|
86
|
-
response_follow.raise_for_status()
|
|
87
|
-
|
|
88
|
-
except Exception as e:
|
|
89
|
-
|
|
90
|
-
query = base_url.split("/")[-1]
|
|
91
|
-
first_url = google_search(query)
|
|
92
|
-
console.print(f"[green]First url from google seach[white]: [red]{first_url}")
|
|
93
|
-
|
|
94
|
-
if first_url:
|
|
95
|
-
final_url = get_final_redirect_url(first_url, max_timeout)
|
|
96
|
-
|
|
97
|
-
if final_url != None:
|
|
98
|
-
console.print(f"\n[bold yellow]Suggestion:[/bold yellow] [white](Experimental)\n"
|
|
99
|
-
f"[cyan]New final URL[white]: [green]{final_url}")
|
|
100
|
-
|
|
101
|
-
def extract_domain(url):
|
|
102
|
-
parsed_url = urlparse(url)
|
|
103
|
-
domain = parsed_url.netloc
|
|
104
|
-
return domain.split(".")[-1]
|
|
105
|
-
|
|
106
|
-
new_domain_extract = extract_domain(str(final_url))
|
|
107
|
-
|
|
108
|
-
if msg.ask(f"[red]Do you want to auto update config.json - '[green]{site_name}[red]' with domain: [green]{new_domain_extract}", choices=["y", "n"], default="y").lower() == "y":
|
|
109
|
-
|
|
110
|
-
# Update domain in config.json
|
|
111
|
-
config_manager.config['SITE'][site_name]['domain'] = new_domain_extract
|
|
112
|
-
config_manager.write_config()
|
|
113
|
-
|
|
114
|
-
# Return config domain
|
|
115
|
-
#console.print(f"[cyan]Return domain: [red]{new_domain_extract} \n")
|
|
116
|
-
return new_domain_extract, f"{base_url}.{new_domain_extract}"
|
|
117
|
-
|
|
118
|
-
else:
|
|
119
|
-
console.print("[bold red]\nManually change the domain in the JSON file.[/bold red]")
|
|
120
|
-
raise
|
|
121
|
-
|
|
122
|
-
else:
|
|
123
|
-
console.print("[bold red]No valid URL to follow redirects.[/bold red]")
|
|
124
|
-
|
|
125
|
-
# Ensure the URL is in string format before parsing
|
|
126
|
-
parsed_url = urlparse(str(response_follow.url))
|
|
127
|
-
parse_domain = parsed_url.netloc
|
|
128
|
-
tld = parse_domain.split('.')[-1]
|
|
129
|
-
|
|
130
|
-
if tld is not None:
|
|
131
|
-
|
|
132
|
-
# Update domain in config.json
|
|
133
|
-
config_manager.config['SITE'][site_name]['domain'] = tld
|
|
134
|
-
config_manager.write_config()
|
|
135
|
-
|
|
136
|
-
# Return config domain
|
|
137
|
-
return tld, f"{base_url}.{tld}"
|
|
1
|
+
# 18.06.24
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from urllib.parse import urlparse
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# External libraries
|
|
8
|
+
import httpx
|
|
9
|
+
from googlesearch import search
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Internal utilities
|
|
13
|
+
from StreamingCommunity.Util.headers import get_headers
|
|
14
|
+
from StreamingCommunity.Util.console import console, msg
|
|
15
|
+
from StreamingCommunity.Util._jsonConfig import config_manager
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def google_search(query):
|
|
19
|
+
"""
|
|
20
|
+
Perform a Google search and return the first result.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
query (str): The search query to execute on Google.
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
str: The first URL result from the search, or None if no result is found.
|
|
27
|
+
"""
|
|
28
|
+
# Perform the search on Google and limit to 1 result
|
|
29
|
+
search_results = search(query, num_results=1)
|
|
30
|
+
|
|
31
|
+
# Extract the first result
|
|
32
|
+
first_result = next(search_results, None)
|
|
33
|
+
|
|
34
|
+
if not first_result:
|
|
35
|
+
console.print("[red]No results found.[/red]")
|
|
36
|
+
|
|
37
|
+
return first_result
|
|
38
|
+
|
|
39
|
+
def get_final_redirect_url(initial_url, max_timeout):
|
|
40
|
+
"""
|
|
41
|
+
Follow redirects from the initial URL and return the final URL after all redirects.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
initial_url (str): The URL to start with and follow redirects.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
str: The final URL after all redirects are followed.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
# Create a client with redirects enabled
|
|
51
|
+
try:
|
|
52
|
+
with httpx.Client(follow_redirects=True, timeout=max_timeout, headers={'user-agent': get_headers()}) as client:
|
|
53
|
+
response = client.get(initial_url)
|
|
54
|
+
response.raise_for_status()
|
|
55
|
+
|
|
56
|
+
# Capture the final URL after all redirects
|
|
57
|
+
final_url = response.url
|
|
58
|
+
|
|
59
|
+
return final_url
|
|
60
|
+
|
|
61
|
+
except Exception as e:
|
|
62
|
+
console.print(f"[cyan]Test url[white]: [red]{initial_url}, [cyan]error[white]: [red]{e}")
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
def search_domain(site_name: str, base_url: str):
|
|
66
|
+
"""
|
|
67
|
+
Search for a valid domain for the given site name and base URL.
|
|
68
|
+
|
|
69
|
+
Parameters:
|
|
70
|
+
- site_name (str): The name of the site to search the domain for.
|
|
71
|
+
- base_url (str): The base URL to construct complete URLs.
|
|
72
|
+
- follow_redirects (bool): To follow redirect url or not.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
tuple: The found domain and the complete URL.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
# Extract config domain
|
|
79
|
+
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
80
|
+
domain = str(config_manager.get_dict("SITE", site_name)['domain'])
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
|
|
84
|
+
# Test the current domain
|
|
85
|
+
response_follow = httpx.get(f"{base_url}.{domain}", headers={'user-agent': get_headers()}, timeout=max_timeout, follow_redirects=True)
|
|
86
|
+
response_follow.raise_for_status()
|
|
87
|
+
|
|
88
|
+
except Exception as e:
|
|
89
|
+
|
|
90
|
+
query = base_url.split("/")[-1]
|
|
91
|
+
first_url = google_search(query)
|
|
92
|
+
console.print(f"[green]First url from google seach[white]: [red]{first_url}")
|
|
93
|
+
|
|
94
|
+
if first_url:
|
|
95
|
+
final_url = get_final_redirect_url(first_url, max_timeout)
|
|
96
|
+
|
|
97
|
+
if final_url != None:
|
|
98
|
+
console.print(f"\n[bold yellow]Suggestion:[/bold yellow] [white](Experimental)\n"
|
|
99
|
+
f"[cyan]New final URL[white]: [green]{final_url}")
|
|
100
|
+
|
|
101
|
+
def extract_domain(url):
|
|
102
|
+
parsed_url = urlparse(url)
|
|
103
|
+
domain = parsed_url.netloc
|
|
104
|
+
return domain.split(".")[-1]
|
|
105
|
+
|
|
106
|
+
new_domain_extract = extract_domain(str(final_url))
|
|
107
|
+
|
|
108
|
+
if msg.ask(f"[red]Do you want to auto update config.json - '[green]{site_name}[red]' with domain: [green]{new_domain_extract}", choices=["y", "n"], default="y").lower() == "y":
|
|
109
|
+
|
|
110
|
+
# Update domain in config.json
|
|
111
|
+
config_manager.config['SITE'][site_name]['domain'] = new_domain_extract
|
|
112
|
+
config_manager.write_config()
|
|
113
|
+
|
|
114
|
+
# Return config domain
|
|
115
|
+
#console.print(f"[cyan]Return domain: [red]{new_domain_extract} \n")
|
|
116
|
+
return new_domain_extract, f"{base_url}.{new_domain_extract}"
|
|
117
|
+
|
|
118
|
+
else:
|
|
119
|
+
console.print("[bold red]\nManually change the domain in the JSON file.[/bold red]")
|
|
120
|
+
raise
|
|
121
|
+
|
|
122
|
+
else:
|
|
123
|
+
console.print("[bold red]No valid URL to follow redirects.[/bold red]")
|
|
124
|
+
|
|
125
|
+
# Ensure the URL is in string format before parsing
|
|
126
|
+
parsed_url = urlparse(str(response_follow.url))
|
|
127
|
+
parse_domain = parsed_url.netloc
|
|
128
|
+
tld = parse_domain.split('.')[-1]
|
|
129
|
+
|
|
130
|
+
if tld is not None:
|
|
131
|
+
|
|
132
|
+
# Update domain in config.json
|
|
133
|
+
config_manager.config['SITE'][site_name]['domain'] = tld
|
|
134
|
+
config_manager.write_config()
|
|
135
|
+
|
|
136
|
+
# Return config domain
|
|
137
|
+
return tld, f"{base_url}.{tld}"
|