StreamingCommunity 2.5.2__py3-none-any.whl → 2.5.6__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/Api/Player/Helper/Vixcloud/js_parser.py +143 -143
- StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +136 -136
- StreamingCommunity/Api/Player/ddl.py +89 -89
- StreamingCommunity/Api/Player/maxstream.py +151 -151
- StreamingCommunity/Api/Player/supervideo.py +193 -193
- StreamingCommunity/Api/Player/vixcloud.py +272 -272
- StreamingCommunity/Api/Site/1337xx/__init__.py +51 -50
- StreamingCommunity/Api/Site/1337xx/costant.py +14 -14
- StreamingCommunity/Api/Site/1337xx/site.py +87 -89
- StreamingCommunity/Api/Site/1337xx/title.py +63 -64
- StreamingCommunity/Api/Site/altadefinizionegratis/__init__.py +74 -50
- StreamingCommunity/Api/Site/altadefinizionegratis/costant.py +21 -19
- StreamingCommunity/Api/Site/altadefinizionegratis/film.py +81 -72
- StreamingCommunity/Api/Site/altadefinizionegratis/site.py +116 -94
- StreamingCommunity/Api/Site/animeunity/__init__.py +75 -50
- StreamingCommunity/Api/Site/animeunity/costant.py +21 -19
- StreamingCommunity/Api/Site/animeunity/film_serie.py +172 -134
- StreamingCommunity/Api/Site/animeunity/site.py +191 -174
- StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +97 -97
- StreamingCommunity/Api/Site/cb01new/__init__.py +51 -51
- StreamingCommunity/Api/Site/cb01new/costant.py +19 -19
- StreamingCommunity/Api/Site/cb01new/film.py +61 -71
- StreamingCommunity/Api/Site/cb01new/site.py +82 -82
- StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +55 -55
- StreamingCommunity/Api/Site/ddlstreamitaly/costant.py +20 -20
- StreamingCommunity/Api/Site/ddlstreamitaly/series.py +150 -145
- StreamingCommunity/Api/Site/ddlstreamitaly/site.py +98 -98
- StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +84 -84
- StreamingCommunity/Api/Site/guardaserie/__init__.py +50 -50
- StreamingCommunity/Api/Site/guardaserie/costant.py +19 -19
- StreamingCommunity/Api/Site/guardaserie/series.py +200 -198
- StreamingCommunity/Api/Site/guardaserie/site.py +89 -89
- StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +110 -110
- StreamingCommunity/Api/Site/ilcorsaronero/__init__.py +51 -51
- StreamingCommunity/Api/Site/ilcorsaronero/costant.py +18 -18
- StreamingCommunity/Api/Site/ilcorsaronero/site.py +71 -71
- StreamingCommunity/Api/Site/ilcorsaronero/title.py +44 -44
- StreamingCommunity/Api/Site/ilcorsaronero/util/ilCorsarScraper.py +149 -149
- StreamingCommunity/Api/Site/mostraguarda/__init__.py +48 -48
- StreamingCommunity/Api/Site/mostraguarda/costant.py +18 -18
- StreamingCommunity/Api/Site/mostraguarda/film.py +90 -101
- StreamingCommunity/Api/Site/streamingcommunity/__init__.py +79 -55
- StreamingCommunity/Api/Site/streamingcommunity/costant.py +21 -19
- StreamingCommunity/Api/Site/streamingcommunity/film.py +86 -75
- StreamingCommunity/Api/Site/streamingcommunity/series.py +260 -207
- StreamingCommunity/Api/Site/streamingcommunity/site.py +156 -142
- StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +124 -124
- StreamingCommunity/Api/Template/Class/SearchType.py +101 -101
- StreamingCommunity/Api/Template/Util/__init__.py +4 -4
- StreamingCommunity/Api/Template/Util/get_domain.py +201 -201
- StreamingCommunity/Api/Template/Util/manage_ep.py +178 -178
- StreamingCommunity/Api/Template/Util/recall_search.py +37 -37
- StreamingCommunity/Api/Template/__init__.py +2 -2
- StreamingCommunity/Api/Template/site.py +87 -87
- StreamingCommunity/Lib/Downloader/HLS/downloader.py +529 -1008
- StreamingCommunity/Lib/Downloader/HLS/proxyes.py +110 -110
- StreamingCommunity/Lib/Downloader/HLS/segments.py +446 -573
- StreamingCommunity/Lib/Downloader/MP4/downloader.py +181 -155
- StreamingCommunity/Lib/Downloader/TOR/downloader.py +297 -295
- StreamingCommunity/Lib/Downloader/__init__.py +4 -4
- StreamingCommunity/Lib/FFmpeg/__init__.py +4 -4
- StreamingCommunity/Lib/FFmpeg/capture.py +170 -170
- StreamingCommunity/Lib/FFmpeg/command.py +264 -296
- StreamingCommunity/Lib/FFmpeg/util.py +248 -248
- StreamingCommunity/Lib/M3U8/__init__.py +5 -5
- StreamingCommunity/Lib/M3U8/decryptor.py +164 -164
- StreamingCommunity/Lib/M3U8/estimator.py +146 -228
- StreamingCommunity/Lib/M3U8/parser.py +666 -666
- StreamingCommunity/Lib/M3U8/url_fixer.py +57 -57
- StreamingCommunity/Lib/TMBD/__init__.py +1 -1
- StreamingCommunity/Lib/TMBD/obj_tmbd.py +39 -39
- StreamingCommunity/Lib/TMBD/tmdb.py +345 -345
- StreamingCommunity/TelegramHelp/__init__.py +0 -0
- StreamingCommunity/TelegramHelp/request_manager.py +82 -0
- StreamingCommunity/TelegramHelp/session.py +56 -0
- StreamingCommunity/TelegramHelp/telegram_bot.py +561 -0
- StreamingCommunity/Upload/update.py +75 -67
- StreamingCommunity/Upload/version.py +5 -5
- StreamingCommunity/Util/_jsonConfig.py +227 -228
- StreamingCommunity/Util/call_stack.py +42 -42
- StreamingCommunity/Util/color.py +20 -20
- StreamingCommunity/Util/console.py +12 -12
- StreamingCommunity/Util/ffmpeg_installer.py +342 -370
- StreamingCommunity/Util/headers.py +159 -159
- StreamingCommunity/Util/logger.py +61 -61
- StreamingCommunity/Util/message.py +36 -64
- StreamingCommunity/Util/os.py +500 -507
- StreamingCommunity/Util/table.py +271 -228
- StreamingCommunity/run.py +352 -245
- {StreamingCommunity-2.5.2.dist-info → StreamingCommunity-2.5.6.dist-info}/LICENSE +674 -674
- {StreamingCommunity-2.5.2.dist-info → StreamingCommunity-2.5.6.dist-info}/METADATA +601 -543
- StreamingCommunity-2.5.6.dist-info/RECORD +96 -0
- {StreamingCommunity-2.5.2.dist-info → StreamingCommunity-2.5.6.dist-info}/entry_points.txt +0 -1
- StreamingCommunity/Api/Player/Helper/Vixcloud/__pycache__/js_parser.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Player/Helper/Vixcloud/__pycache__/js_parser.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Player/Helper/Vixcloud/__pycache__/util.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Player/Helper/Vixcloud/__pycache__/util.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Player/__pycache__/ddl.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Player/__pycache__/ddl.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Player/__pycache__/maxstream.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Player/__pycache__/maxstream.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Player/__pycache__/supervideo.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Player/__pycache__/supervideo.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Player/__pycache__/vixcloud.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Player/__pycache__/vixcloud.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/1337xx/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/1337xx/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/1337xx/__pycache__/costant.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/1337xx/__pycache__/costant.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/1337xx/__pycache__/site.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/1337xx/__pycache__/site.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/1337xx/__pycache__/title.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/1337xx/__pycache__/title.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/costant.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/costant.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/film.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/film.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/site.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/site.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/animeunity/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/animeunity/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/animeunity/__pycache__/costant.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/animeunity/__pycache__/costant.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/animeunity/__pycache__/film_serie.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/animeunity/__pycache__/film_serie.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/animeunity/__pycache__/site.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/animeunity/__pycache__/site.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/animeunity/util/__pycache__/ScrapeSerie.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/animeunity/util/__pycache__/ScrapeSerie.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/cb01new/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/cb01new/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/cb01new/__pycache__/costant.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/cb01new/__pycache__/costant.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/cb01new/__pycache__/film.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/cb01new/__pycache__/film.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/cb01new/__pycache__/site.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/cb01new/__pycache__/site.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/costant.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/costant.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/series.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/series.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/site.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/site.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/ddlstreamitaly/util/__pycache__/ScrapeSerie.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/ddlstreamitaly/util/__pycache__/ScrapeSerie.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/guardaserie/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/guardaserie/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/guardaserie/__pycache__/costant.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/guardaserie/__pycache__/costant.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/guardaserie/__pycache__/series.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/guardaserie/__pycache__/series.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/guardaserie/__pycache__/site.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/guardaserie/__pycache__/site.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/guardaserie/util/__pycache__/ScrapeSerie.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/guardaserie/util/__pycache__/ScrapeSerie.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/costant.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/costant.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/site.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/site.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/title.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/title.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/ilcorsaronero/util/__pycache__/ilCorsarScraper.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/ilcorsaronero/util/__pycache__/ilCorsarScraper.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/mostraguarda/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/mostraguarda/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/mostraguarda/__pycache__/costant.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/mostraguarda/__pycache__/costant.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/mostraguarda/__pycache__/film.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/mostraguarda/__pycache__/film.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/__pycache__/costant.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/__pycache__/costant.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/__pycache__/film.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/__pycache__/film.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/__pycache__/series.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/__pycache__/series.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/__pycache__/site.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/__pycache__/site.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/util/__pycache__/ScrapeSerie.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Site/streamingcommunity/util/__pycache__/ScrapeSerie.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Template/Class/__pycache__/SearchType.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Template/Class/__pycache__/SearchType.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Template/Util/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Template/Util/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Template/Util/__pycache__/get_domain.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Template/Util/__pycache__/get_domain.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Template/Util/__pycache__/manage_ep.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Template/Util/__pycache__/manage_ep.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Template/Util/__pycache__/recall_search.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Template/Util/__pycache__/recall_search.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Template/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Template/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Api/Template/__pycache__/site.cpython-313.pyc +0 -0
- StreamingCommunity/Api/Template/__pycache__/site.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/Downloader/HLS/__pycache__/downloader.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/Downloader/HLS/__pycache__/downloader.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/Downloader/HLS/__pycache__/proxyes.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/Downloader/HLS/__pycache__/proxyes.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/Downloader/HLS/__pycache__/segments.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/Downloader/HLS/__pycache__/segments.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/Downloader/MP4/__pycache__/downloader.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/Downloader/MP4/__pycache__/downloader.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/Downloader/TOR/__pycache__/downloader.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/Downloader/TOR/__pycache__/downloader.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/Downloader/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/Downloader/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/FFmpeg/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/FFmpeg/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/FFmpeg/__pycache__/capture.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/FFmpeg/__pycache__/capture.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/FFmpeg/__pycache__/command.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/FFmpeg/__pycache__/command.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/FFmpeg/__pycache__/util.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/FFmpeg/__pycache__/util.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/M3U8/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/M3U8/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/M3U8/__pycache__/decryptor.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/M3U8/__pycache__/decryptor.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/M3U8/__pycache__/estimator.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/M3U8/__pycache__/estimator.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/M3U8/__pycache__/parser.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/M3U8/__pycache__/parser.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/M3U8/__pycache__/url_fixer.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/M3U8/__pycache__/url_fixer.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/TMBD/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/TMBD/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/TMBD/__pycache__/obj_tmbd.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/TMBD/__pycache__/obj_tmbd.cpython-39.pyc +0 -0
- StreamingCommunity/Lib/TMBD/__pycache__/tmdb.cpython-313.pyc +0 -0
- StreamingCommunity/Lib/TMBD/__pycache__/tmdb.cpython-39.pyc +0 -0
- StreamingCommunity/Upload/__pycache__/update.cpython-313.pyc +0 -0
- StreamingCommunity/Upload/__pycache__/update.cpython-39.pyc +0 -0
- StreamingCommunity/Upload/__pycache__/version.cpython-313.pyc +0 -0
- StreamingCommunity/Upload/__pycache__/version.cpython-39.pyc +0 -0
- StreamingCommunity/Util/__pycache__/_jsonConfig.cpython-313.pyc +0 -0
- StreamingCommunity/Util/__pycache__/_jsonConfig.cpython-39.pyc +0 -0
- StreamingCommunity/Util/__pycache__/call_stack.cpython-313.pyc +0 -0
- StreamingCommunity/Util/__pycache__/call_stack.cpython-39.pyc +0 -0
- StreamingCommunity/Util/__pycache__/color.cpython-313.pyc +0 -0
- StreamingCommunity/Util/__pycache__/color.cpython-39.pyc +0 -0
- StreamingCommunity/Util/__pycache__/console.cpython-313.pyc +0 -0
- StreamingCommunity/Util/__pycache__/console.cpython-39.pyc +0 -0
- StreamingCommunity/Util/__pycache__/ffmpeg_installer.cpython-313.pyc +0 -0
- StreamingCommunity/Util/__pycache__/ffmpeg_installer.cpython-39.pyc +0 -0
- StreamingCommunity/Util/__pycache__/headers.cpython-313.pyc +0 -0
- StreamingCommunity/Util/__pycache__/headers.cpython-39.pyc +0 -0
- StreamingCommunity/Util/__pycache__/logger.cpython-313.pyc +0 -0
- StreamingCommunity/Util/__pycache__/logger.cpython-39.pyc +0 -0
- StreamingCommunity/Util/__pycache__/message.cpython-313.pyc +0 -0
- StreamingCommunity/Util/__pycache__/message.cpython-39.pyc +0 -0
- StreamingCommunity/Util/__pycache__/os.cpython-313.pyc +0 -0
- StreamingCommunity/Util/__pycache__/os.cpython-39.pyc +0 -0
- StreamingCommunity/Util/__pycache__/table.cpython-313.pyc +0 -0
- StreamingCommunity/Util/__pycache__/table.cpython-39.pyc +0 -0
- StreamingCommunity/__pycache__/__init__.cpython-313.pyc +0 -0
- StreamingCommunity/__pycache__/__init__.cpython-39.pyc +0 -0
- StreamingCommunity/__pycache__/run.cpython-313.pyc +0 -0
- StreamingCommunity/__pycache__/run.cpython-39.pyc +0 -0
- StreamingCommunity-2.5.2.dist-info/RECORD +0 -264
- {StreamingCommunity-2.5.2.dist-info → StreamingCommunity-2.5.6.dist-info}/WHEEL +0 -0
- {StreamingCommunity-2.5.2.dist-info → StreamingCommunity-2.5.6.dist-info}/top_level.txt +0 -0
|
@@ -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, dynamic_format_number
|
|
@@ -1,202 +1,202 @@
|
|
|
1
|
-
# 18.06.24
|
|
2
|
-
|
|
3
|
-
import ssl
|
|
4
|
-
import time
|
|
5
|
-
from urllib.parse import urlparse, unquote
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
# External libraries
|
|
9
|
-
import httpx
|
|
10
|
-
from googlesearch import search
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# Internal utilities
|
|
14
|
-
from StreamingCommunity.Util.headers import get_headers
|
|
15
|
-
from StreamingCommunity.Util.console import console, msg
|
|
16
|
-
from StreamingCommunity.Util._jsonConfig import config_manager
|
|
17
|
-
|
|
18
|
-
base_headers = {
|
|
19
|
-
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
|
20
|
-
'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
|
|
21
|
-
'dnt': '1',
|
|
22
|
-
'priority': 'u=0, i',
|
|
23
|
-
'referer': '',
|
|
24
|
-
'sec-ch-ua-mobile': '?0',
|
|
25
|
-
'sec-ch-ua-platform': '"Windows"',
|
|
26
|
-
'sec-fetch-dest': 'document',
|
|
27
|
-
'sec-fetch-mode': 'navigate',
|
|
28
|
-
'sec-fetch-site': 'same-origin',
|
|
29
|
-
'sec-fetch-user': '?1',
|
|
30
|
-
'upgrade-insecure-requests': '1',
|
|
31
|
-
'user-agent': ''
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def get_tld(url_str):
|
|
36
|
-
"""Extract the TLD (Top-Level Domain) from the URL."""
|
|
37
|
-
try:
|
|
38
|
-
url_str = unquote(url_str)
|
|
39
|
-
parsed = urlparse(url_str)
|
|
40
|
-
domain = parsed.netloc.lower()
|
|
41
|
-
|
|
42
|
-
if domain.startswith('www.'):
|
|
43
|
-
domain = domain[4:]
|
|
44
|
-
parts = domain.split('.')
|
|
45
|
-
|
|
46
|
-
return parts[-1] if len(parts) >= 2 else None
|
|
47
|
-
|
|
48
|
-
except Exception:
|
|
49
|
-
return None
|
|
50
|
-
|
|
51
|
-
def get_base_domain(url_str):
|
|
52
|
-
"""Extract base domain without protocol, www and path."""
|
|
53
|
-
try:
|
|
54
|
-
parsed = urlparse(url_str)
|
|
55
|
-
domain = parsed.netloc.lower()
|
|
56
|
-
if domain.startswith('www.'):
|
|
57
|
-
domain = domain[4:]
|
|
58
|
-
|
|
59
|
-
# Check if domain has multiple parts separated by dots
|
|
60
|
-
parts = domain.split('.')
|
|
61
|
-
if len(parts) > 2: # Handle subdomains
|
|
62
|
-
return '.'.join(parts[:-1]) # Return everything except TLD
|
|
63
|
-
|
|
64
|
-
return parts[0] # Return base domain
|
|
65
|
-
|
|
66
|
-
except Exception:
|
|
67
|
-
return None
|
|
68
|
-
|
|
69
|
-
def get_base_url(url_str):
|
|
70
|
-
"""Extract base URL including protocol and domain, removing path and query parameters."""
|
|
71
|
-
try:
|
|
72
|
-
parsed = urlparse(url_str)
|
|
73
|
-
return f"{parsed.scheme}://{parsed.netloc}"
|
|
74
|
-
|
|
75
|
-
except Exception:
|
|
76
|
-
return None
|
|
77
|
-
|
|
78
|
-
def validate_url(url, base_url, max_timeout, max_retries=2, sleep=1):
|
|
79
|
-
"""Validate if URL is accessible and matches expected base domain."""
|
|
80
|
-
console.print(f"\n[cyan]Starting validation for URL[white]: [yellow]{url}")
|
|
81
|
-
|
|
82
|
-
# Verify URL structure matches base_url structure
|
|
83
|
-
base_domain = get_base_domain(base_url)
|
|
84
|
-
url_domain = get_base_domain(url)
|
|
85
|
-
|
|
86
|
-
base_headers['referer'] = url
|
|
87
|
-
base_headers['user-agent'] = get_headers()
|
|
88
|
-
|
|
89
|
-
if base_domain != url_domain:
|
|
90
|
-
console.print(f"[red]Domain structure mismatch: {url_domain} != {base_domain}")
|
|
91
|
-
return False, None
|
|
92
|
-
|
|
93
|
-
# Count dots to ensure we don't have extra subdomains
|
|
94
|
-
base_dots = base_url.count('.')
|
|
95
|
-
url_dots = url.count('.')
|
|
96
|
-
if url_dots > base_dots + 1: # Allow for one extra dot for TLD change
|
|
97
|
-
console.print(f"[red]Too many subdomains in URL")
|
|
98
|
-
return False, None
|
|
99
|
-
|
|
100
|
-
client = httpx.Client(
|
|
101
|
-
verify=False,
|
|
102
|
-
headers=base_headers,
|
|
103
|
-
timeout=max_timeout
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
for retry in range(max_retries):
|
|
107
|
-
try:
|
|
108
|
-
time.sleep(sleep)
|
|
109
|
-
|
|
110
|
-
# Initial check without redirects
|
|
111
|
-
response = client.get(url, follow_redirects=False)
|
|
112
|
-
if response.status_code == 403:
|
|
113
|
-
console.print(f"[red]Check failed (403) - Attempt {retry + 1}/{max_retries}")
|
|
114
|
-
continue
|
|
115
|
-
|
|
116
|
-
if response.status_code >= 400:
|
|
117
|
-
console.print(f"[red]Check failed: HTTP {response.status_code}")
|
|
118
|
-
return False, None
|
|
119
|
-
|
|
120
|
-
# Follow redirects and verify final domain
|
|
121
|
-
final_response = client.get(url, follow_redirects=True)
|
|
122
|
-
final_domain = get_base_domain(str(final_response.url))
|
|
123
|
-
console.print(f"[cyan]Redirect url: [red]{final_response.url}")
|
|
124
|
-
|
|
125
|
-
if final_domain != base_domain:
|
|
126
|
-
console.print(f"[red]Final domain mismatch: {final_domain} != {base_domain}")
|
|
127
|
-
return False, None
|
|
128
|
-
|
|
129
|
-
new_tld = get_tld(str(final_response.url))
|
|
130
|
-
if new_tld != get_tld(url):
|
|
131
|
-
return True, new_tld
|
|
132
|
-
|
|
133
|
-
return True, None
|
|
134
|
-
|
|
135
|
-
except (httpx.RequestError, ssl.SSLError) as e:
|
|
136
|
-
console.print(f"[red]Connection error: {str(e)}")
|
|
137
|
-
time.sleep(sleep)
|
|
138
|
-
continue
|
|
139
|
-
|
|
140
|
-
return False, None
|
|
141
|
-
|
|
142
|
-
def search_domain(site_name: str, base_url: str, get_first: bool = False):
|
|
143
|
-
"""Search for valid domain matching site name and base URL."""
|
|
144
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
145
|
-
domain = str(config_manager.get_dict("SITE", site_name)['domain'])
|
|
146
|
-
|
|
147
|
-
# Test initial URL
|
|
148
|
-
try:
|
|
149
|
-
is_correct, redirect_tld = validate_url(base_url, base_url, max_timeout)
|
|
150
|
-
|
|
151
|
-
if is_correct:
|
|
152
|
-
tld = redirect_tld or get_tld(base_url)
|
|
153
|
-
config_manager.config['SITE'][site_name]['domain'] = tld
|
|
154
|
-
config_manager.write_config()
|
|
155
|
-
console.print(f"[green]Successfully validated initial URL")
|
|
156
|
-
return tld, base_url
|
|
157
|
-
|
|
158
|
-
except Exception as e:
|
|
159
|
-
console.print(f"[red]Error testing initial URL: {str(e)}")
|
|
160
|
-
|
|
161
|
-
# Google search phase
|
|
162
|
-
base_domain = get_base_domain(base_url)
|
|
163
|
-
console.print(f"\n[cyan]Searching for alternate domains for[white]: [yellow]{base_domain}")
|
|
164
|
-
|
|
165
|
-
try:
|
|
166
|
-
search_results = list(search(base_domain, num_results=20, lang="it"))
|
|
167
|
-
|
|
168
|
-
base_urls = set()
|
|
169
|
-
for url in search_results:
|
|
170
|
-
element_url = get_base_url(url)
|
|
171
|
-
if element_url:
|
|
172
|
-
base_urls.add(element_url)
|
|
173
|
-
|
|
174
|
-
# Filter URLs based on domain matching and subdomain count
|
|
175
|
-
filtered_results = [
|
|
176
|
-
url for url in base_urls
|
|
177
|
-
if get_base_domain(url) == base_domain
|
|
178
|
-
and url.count('.') <= base_url.count('.') + 1
|
|
179
|
-
]
|
|
180
|
-
|
|
181
|
-
for idx, result_url in enumerate(filtered_results, 1):
|
|
182
|
-
console.print(f"\n[cyan]Checking result {idx}/{len(filtered_results)}[white]: [yellow]{result_url}")
|
|
183
|
-
|
|
184
|
-
is_valid, new_tld = validate_url(result_url, base_url, max_timeout)
|
|
185
|
-
if is_valid:
|
|
186
|
-
final_tld = new_tld or get_tld(result_url)
|
|
187
|
-
|
|
188
|
-
if get_first or msg.ask(
|
|
189
|
-
f"\n[cyan]Update site[white] [red]'{site_name}'[cyan] with domain[white] [red]'{final_tld}'",
|
|
190
|
-
choices=["y", "n"],
|
|
191
|
-
default="y"
|
|
192
|
-
).lower() == "y":
|
|
193
|
-
|
|
194
|
-
config_manager.config['SITE'][site_name]['domain'] = final_tld
|
|
195
|
-
config_manager.write_config()
|
|
196
|
-
return final_tld, f"{base_url}.{final_tld}"
|
|
197
|
-
|
|
198
|
-
except Exception as e:
|
|
199
|
-
console.print(f"[red]Error during search: {str(e)}")
|
|
200
|
-
|
|
201
|
-
console.print("[bold red]No valid URLs found matching the base URL.")
|
|
1
|
+
# 18.06.24
|
|
2
|
+
|
|
3
|
+
import ssl
|
|
4
|
+
import time
|
|
5
|
+
from urllib.parse import urlparse, unquote
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# External libraries
|
|
9
|
+
import httpx
|
|
10
|
+
from googlesearch import search
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Internal utilities
|
|
14
|
+
from StreamingCommunity.Util.headers import get_headers
|
|
15
|
+
from StreamingCommunity.Util.console import console, msg
|
|
16
|
+
from StreamingCommunity.Util._jsonConfig import config_manager
|
|
17
|
+
|
|
18
|
+
base_headers = {
|
|
19
|
+
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
|
20
|
+
'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
|
|
21
|
+
'dnt': '1',
|
|
22
|
+
'priority': 'u=0, i',
|
|
23
|
+
'referer': '',
|
|
24
|
+
'sec-ch-ua-mobile': '?0',
|
|
25
|
+
'sec-ch-ua-platform': '"Windows"',
|
|
26
|
+
'sec-fetch-dest': 'document',
|
|
27
|
+
'sec-fetch-mode': 'navigate',
|
|
28
|
+
'sec-fetch-site': 'same-origin',
|
|
29
|
+
'sec-fetch-user': '?1',
|
|
30
|
+
'upgrade-insecure-requests': '1',
|
|
31
|
+
'user-agent': ''
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_tld(url_str):
|
|
36
|
+
"""Extract the TLD (Top-Level Domain) from the URL."""
|
|
37
|
+
try:
|
|
38
|
+
url_str = unquote(url_str)
|
|
39
|
+
parsed = urlparse(url_str)
|
|
40
|
+
domain = parsed.netloc.lower()
|
|
41
|
+
|
|
42
|
+
if domain.startswith('www.'):
|
|
43
|
+
domain = domain[4:]
|
|
44
|
+
parts = domain.split('.')
|
|
45
|
+
|
|
46
|
+
return parts[-1] if len(parts) >= 2 else None
|
|
47
|
+
|
|
48
|
+
except Exception:
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
def get_base_domain(url_str):
|
|
52
|
+
"""Extract base domain without protocol, www and path."""
|
|
53
|
+
try:
|
|
54
|
+
parsed = urlparse(url_str)
|
|
55
|
+
domain = parsed.netloc.lower()
|
|
56
|
+
if domain.startswith('www.'):
|
|
57
|
+
domain = domain[4:]
|
|
58
|
+
|
|
59
|
+
# Check if domain has multiple parts separated by dots
|
|
60
|
+
parts = domain.split('.')
|
|
61
|
+
if len(parts) > 2: # Handle subdomains
|
|
62
|
+
return '.'.join(parts[:-1]) # Return everything except TLD
|
|
63
|
+
|
|
64
|
+
return parts[0] # Return base domain
|
|
65
|
+
|
|
66
|
+
except Exception:
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
def get_base_url(url_str):
|
|
70
|
+
"""Extract base URL including protocol and domain, removing path and query parameters."""
|
|
71
|
+
try:
|
|
72
|
+
parsed = urlparse(url_str)
|
|
73
|
+
return f"{parsed.scheme}://{parsed.netloc}"
|
|
74
|
+
|
|
75
|
+
except Exception:
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
def validate_url(url, base_url, max_timeout, max_retries=2, sleep=1):
|
|
79
|
+
"""Validate if URL is accessible and matches expected base domain."""
|
|
80
|
+
console.print(f"\n[cyan]Starting validation for URL[white]: [yellow]{url}")
|
|
81
|
+
|
|
82
|
+
# Verify URL structure matches base_url structure
|
|
83
|
+
base_domain = get_base_domain(base_url)
|
|
84
|
+
url_domain = get_base_domain(url)
|
|
85
|
+
|
|
86
|
+
base_headers['referer'] = url
|
|
87
|
+
base_headers['user-agent'] = get_headers()
|
|
88
|
+
|
|
89
|
+
if base_domain != url_domain:
|
|
90
|
+
console.print(f"[red]Domain structure mismatch: {url_domain} != {base_domain}")
|
|
91
|
+
return False, None
|
|
92
|
+
|
|
93
|
+
# Count dots to ensure we don't have extra subdomains
|
|
94
|
+
base_dots = base_url.count('.')
|
|
95
|
+
url_dots = url.count('.')
|
|
96
|
+
if url_dots > base_dots + 1: # Allow for one extra dot for TLD change
|
|
97
|
+
console.print(f"[red]Too many subdomains in URL")
|
|
98
|
+
return False, None
|
|
99
|
+
|
|
100
|
+
client = httpx.Client(
|
|
101
|
+
verify=False,
|
|
102
|
+
headers=base_headers,
|
|
103
|
+
timeout=max_timeout
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
for retry in range(max_retries):
|
|
107
|
+
try:
|
|
108
|
+
time.sleep(sleep)
|
|
109
|
+
|
|
110
|
+
# Initial check without redirects
|
|
111
|
+
response = client.get(url, follow_redirects=False)
|
|
112
|
+
if response.status_code == 403:
|
|
113
|
+
console.print(f"[red]Check failed (403) - Attempt {retry + 1}/{max_retries}")
|
|
114
|
+
continue
|
|
115
|
+
|
|
116
|
+
if response.status_code >= 400:
|
|
117
|
+
console.print(f"[red]Check failed: HTTP {response.status_code}")
|
|
118
|
+
return False, None
|
|
119
|
+
|
|
120
|
+
# Follow redirects and verify final domain
|
|
121
|
+
final_response = client.get(url, follow_redirects=True)
|
|
122
|
+
final_domain = get_base_domain(str(final_response.url))
|
|
123
|
+
console.print(f"[cyan]Redirect url: [red]{final_response.url}")
|
|
124
|
+
|
|
125
|
+
if final_domain != base_domain:
|
|
126
|
+
console.print(f"[red]Final domain mismatch: {final_domain} != {base_domain}")
|
|
127
|
+
return False, None
|
|
128
|
+
|
|
129
|
+
new_tld = get_tld(str(final_response.url))
|
|
130
|
+
if new_tld != get_tld(url):
|
|
131
|
+
return True, new_tld
|
|
132
|
+
|
|
133
|
+
return True, None
|
|
134
|
+
|
|
135
|
+
except (httpx.RequestError, ssl.SSLError) as e:
|
|
136
|
+
console.print(f"[red]Connection error: {str(e)}")
|
|
137
|
+
time.sleep(sleep)
|
|
138
|
+
continue
|
|
139
|
+
|
|
140
|
+
return False, None
|
|
141
|
+
|
|
142
|
+
def search_domain(site_name: str, base_url: str, get_first: bool = False):
|
|
143
|
+
"""Search for valid domain matching site name and base URL."""
|
|
144
|
+
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
145
|
+
domain = str(config_manager.get_dict("SITE", site_name)['domain'])
|
|
146
|
+
|
|
147
|
+
# Test initial URL
|
|
148
|
+
try:
|
|
149
|
+
is_correct, redirect_tld = validate_url(base_url, base_url, max_timeout)
|
|
150
|
+
|
|
151
|
+
if is_correct:
|
|
152
|
+
tld = redirect_tld or get_tld(base_url)
|
|
153
|
+
config_manager.config['SITE'][site_name]['domain'] = tld
|
|
154
|
+
config_manager.write_config()
|
|
155
|
+
console.print(f"[green]Successfully validated initial URL")
|
|
156
|
+
return tld, base_url
|
|
157
|
+
|
|
158
|
+
except Exception as e:
|
|
159
|
+
console.print(f"[red]Error testing initial URL: {str(e)}")
|
|
160
|
+
|
|
161
|
+
# Google search phase
|
|
162
|
+
base_domain = get_base_domain(base_url)
|
|
163
|
+
console.print(f"\n[cyan]Searching for alternate domains for[white]: [yellow]{base_domain}")
|
|
164
|
+
|
|
165
|
+
try:
|
|
166
|
+
search_results = list(search(base_domain, num_results=20, lang="it"))
|
|
167
|
+
|
|
168
|
+
base_urls = set()
|
|
169
|
+
for url in search_results:
|
|
170
|
+
element_url = get_base_url(url)
|
|
171
|
+
if element_url:
|
|
172
|
+
base_urls.add(element_url)
|
|
173
|
+
|
|
174
|
+
# Filter URLs based on domain matching and subdomain count
|
|
175
|
+
filtered_results = [
|
|
176
|
+
url for url in base_urls
|
|
177
|
+
if get_base_domain(url) == base_domain
|
|
178
|
+
and url.count('.') <= base_url.count('.') + 1
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
for idx, result_url in enumerate(filtered_results, 1):
|
|
182
|
+
console.print(f"\n[cyan]Checking result {idx}/{len(filtered_results)}[white]: [yellow]{result_url}")
|
|
183
|
+
|
|
184
|
+
is_valid, new_tld = validate_url(result_url, base_url, max_timeout)
|
|
185
|
+
if is_valid:
|
|
186
|
+
final_tld = new_tld or get_tld(result_url)
|
|
187
|
+
|
|
188
|
+
if get_first or msg.ask(
|
|
189
|
+
f"\n[cyan]Update site[white] [red]'{site_name}'[cyan] with domain[white] [red]'{final_tld}'",
|
|
190
|
+
choices=["y", "n"],
|
|
191
|
+
default="y"
|
|
192
|
+
).lower() == "y":
|
|
193
|
+
|
|
194
|
+
config_manager.config['SITE'][site_name]['domain'] = final_tld
|
|
195
|
+
config_manager.write_config()
|
|
196
|
+
return final_tld, f"{base_url}.{final_tld}"
|
|
197
|
+
|
|
198
|
+
except Exception as e:
|
|
199
|
+
console.print(f"[red]Error during search: {str(e)}")
|
|
200
|
+
|
|
201
|
+
console.print("[bold red]No valid URLs found matching the base URL.")
|
|
202
202
|
return domain, f"{base_url}.{domain}"
|