StreamingCommunity 2.5.0__py3-none-any.whl → 2.5.2__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.

Files changed (263) hide show
  1. StreamingCommunity/Api/Player/Helper/Vixcloud/__pycache__/js_parser.cpython-313.pyc +0 -0
  2. StreamingCommunity/Api/Player/Helper/Vixcloud/__pycache__/js_parser.cpython-39.pyc +0 -0
  3. StreamingCommunity/Api/Player/Helper/Vixcloud/__pycache__/util.cpython-313.pyc +0 -0
  4. StreamingCommunity/Api/Player/Helper/Vixcloud/__pycache__/util.cpython-39.pyc +0 -0
  5. StreamingCommunity/Api/Player/Helper/Vixcloud/js_parser.py +143 -0
  6. StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +136 -0
  7. StreamingCommunity/Api/Player/__pycache__/ddl.cpython-313.pyc +0 -0
  8. StreamingCommunity/Api/Player/__pycache__/ddl.cpython-39.pyc +0 -0
  9. StreamingCommunity/Api/Player/__pycache__/maxstream.cpython-313.pyc +0 -0
  10. StreamingCommunity/Api/Player/__pycache__/maxstream.cpython-39.pyc +0 -0
  11. StreamingCommunity/Api/Player/__pycache__/supervideo.cpython-313.pyc +0 -0
  12. StreamingCommunity/Api/Player/__pycache__/supervideo.cpython-39.pyc +0 -0
  13. StreamingCommunity/Api/Player/__pycache__/vixcloud.cpython-313.pyc +0 -0
  14. StreamingCommunity/Api/Player/__pycache__/vixcloud.cpython-39.pyc +0 -0
  15. StreamingCommunity/Api/Player/ddl.py +89 -0
  16. StreamingCommunity/Api/Player/maxstream.py +151 -0
  17. StreamingCommunity/Api/Player/supervideo.py +194 -0
  18. StreamingCommunity/Api/Player/vixcloud.py +273 -0
  19. StreamingCommunity/Api/Site/1337xx/__init__.py +51 -0
  20. StreamingCommunity/Api/Site/1337xx/__pycache__/__init__.cpython-313.pyc +0 -0
  21. StreamingCommunity/Api/Site/1337xx/__pycache__/__init__.cpython-39.pyc +0 -0
  22. StreamingCommunity/Api/Site/1337xx/__pycache__/costant.cpython-313.pyc +0 -0
  23. StreamingCommunity/Api/Site/1337xx/__pycache__/costant.cpython-39.pyc +0 -0
  24. StreamingCommunity/Api/Site/1337xx/__pycache__/site.cpython-313.pyc +0 -0
  25. StreamingCommunity/Api/Site/1337xx/__pycache__/site.cpython-39.pyc +0 -0
  26. StreamingCommunity/Api/Site/1337xx/__pycache__/title.cpython-313.pyc +0 -0
  27. StreamingCommunity/Api/Site/1337xx/__pycache__/title.cpython-39.pyc +0 -0
  28. StreamingCommunity/Api/Site/1337xx/costant.py +15 -0
  29. StreamingCommunity/Api/Site/1337xx/site.py +89 -0
  30. StreamingCommunity/Api/Site/1337xx/title.py +64 -0
  31. StreamingCommunity/Api/Site/altadefinizionegratis/__init__.py +51 -0
  32. StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/__init__.cpython-313.pyc +0 -0
  33. StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/__init__.cpython-39.pyc +0 -0
  34. StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/costant.cpython-313.pyc +0 -0
  35. StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/costant.cpython-39.pyc +0 -0
  36. StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/film.cpython-313.pyc +0 -0
  37. StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/film.cpython-39.pyc +0 -0
  38. StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/site.cpython-313.pyc +0 -0
  39. StreamingCommunity/Api/Site/altadefinizionegratis/__pycache__/site.cpython-39.pyc +0 -0
  40. StreamingCommunity/Api/Site/altadefinizionegratis/costant.py +19 -0
  41. StreamingCommunity/Api/Site/altadefinizionegratis/film.py +72 -0
  42. StreamingCommunity/Api/Site/altadefinizionegratis/site.py +95 -0
  43. StreamingCommunity/Api/Site/animeunity/__init__.py +51 -0
  44. StreamingCommunity/Api/Site/animeunity/__pycache__/__init__.cpython-313.pyc +0 -0
  45. StreamingCommunity/Api/Site/animeunity/__pycache__/__init__.cpython-39.pyc +0 -0
  46. StreamingCommunity/Api/Site/animeunity/__pycache__/costant.cpython-313.pyc +0 -0
  47. StreamingCommunity/Api/Site/animeunity/__pycache__/costant.cpython-39.pyc +0 -0
  48. StreamingCommunity/Api/Site/animeunity/__pycache__/film_serie.cpython-313.pyc +0 -0
  49. StreamingCommunity/Api/Site/animeunity/__pycache__/film_serie.cpython-39.pyc +0 -0
  50. StreamingCommunity/Api/Site/animeunity/__pycache__/site.cpython-313.pyc +0 -0
  51. StreamingCommunity/Api/Site/animeunity/__pycache__/site.cpython-39.pyc +0 -0
  52. StreamingCommunity/Api/Site/animeunity/costant.py +19 -0
  53. StreamingCommunity/Api/Site/animeunity/film_serie.py +135 -0
  54. StreamingCommunity/Api/Site/animeunity/site.py +175 -0
  55. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +97 -0
  56. StreamingCommunity/Api/Site/animeunity/util/__pycache__/ScrapeSerie.cpython-313.pyc +0 -0
  57. StreamingCommunity/Api/Site/animeunity/util/__pycache__/ScrapeSerie.cpython-39.pyc +0 -0
  58. StreamingCommunity/Api/Site/cb01new/__init__.py +52 -0
  59. StreamingCommunity/Api/Site/cb01new/__pycache__/__init__.cpython-313.pyc +0 -0
  60. StreamingCommunity/Api/Site/cb01new/__pycache__/__init__.cpython-39.pyc +0 -0
  61. StreamingCommunity/Api/Site/cb01new/__pycache__/costant.cpython-313.pyc +0 -0
  62. StreamingCommunity/Api/Site/cb01new/__pycache__/costant.cpython-39.pyc +0 -0
  63. StreamingCommunity/Api/Site/cb01new/__pycache__/film.cpython-313.pyc +0 -0
  64. StreamingCommunity/Api/Site/cb01new/__pycache__/film.cpython-39.pyc +0 -0
  65. StreamingCommunity/Api/Site/cb01new/__pycache__/site.cpython-313.pyc +0 -0
  66. StreamingCommunity/Api/Site/cb01new/__pycache__/site.cpython-39.pyc +0 -0
  67. StreamingCommunity/Api/Site/cb01new/costant.py +19 -0
  68. StreamingCommunity/Api/Site/cb01new/film.py +71 -0
  69. StreamingCommunity/Api/Site/cb01new/site.py +83 -0
  70. StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +56 -0
  71. StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/__init__.cpython-313.pyc +0 -0
  72. StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/__init__.cpython-39.pyc +0 -0
  73. StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/costant.cpython-313.pyc +0 -0
  74. StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/costant.cpython-39.pyc +0 -0
  75. StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/series.cpython-313.pyc +0 -0
  76. StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/series.cpython-39.pyc +0 -0
  77. StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/site.cpython-313.pyc +0 -0
  78. StreamingCommunity/Api/Site/ddlstreamitaly/__pycache__/site.cpython-39.pyc +0 -0
  79. StreamingCommunity/Api/Site/ddlstreamitaly/costant.py +20 -0
  80. StreamingCommunity/Api/Site/ddlstreamitaly/series.py +145 -0
  81. StreamingCommunity/Api/Site/ddlstreamitaly/site.py +99 -0
  82. StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +85 -0
  83. StreamingCommunity/Api/Site/ddlstreamitaly/util/__pycache__/ScrapeSerie.cpython-313.pyc +0 -0
  84. StreamingCommunity/Api/Site/ddlstreamitaly/util/__pycache__/ScrapeSerie.cpython-39.pyc +0 -0
  85. StreamingCommunity/Api/Site/guardaserie/__init__.py +51 -0
  86. StreamingCommunity/Api/Site/guardaserie/__pycache__/__init__.cpython-313.pyc +0 -0
  87. StreamingCommunity/Api/Site/guardaserie/__pycache__/__init__.cpython-39.pyc +0 -0
  88. StreamingCommunity/Api/Site/guardaserie/__pycache__/costant.cpython-313.pyc +0 -0
  89. StreamingCommunity/Api/Site/guardaserie/__pycache__/costant.cpython-39.pyc +0 -0
  90. StreamingCommunity/Api/Site/guardaserie/__pycache__/series.cpython-313.pyc +0 -0
  91. StreamingCommunity/Api/Site/guardaserie/__pycache__/series.cpython-39.pyc +0 -0
  92. StreamingCommunity/Api/Site/guardaserie/__pycache__/site.cpython-313.pyc +0 -0
  93. StreamingCommunity/Api/Site/guardaserie/__pycache__/site.cpython-39.pyc +0 -0
  94. StreamingCommunity/Api/Site/guardaserie/costant.py +19 -0
  95. StreamingCommunity/Api/Site/guardaserie/series.py +198 -0
  96. StreamingCommunity/Api/Site/guardaserie/site.py +90 -0
  97. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +110 -0
  98. StreamingCommunity/Api/Site/guardaserie/util/__pycache__/ScrapeSerie.cpython-313.pyc +0 -0
  99. StreamingCommunity/Api/Site/guardaserie/util/__pycache__/ScrapeSerie.cpython-39.pyc +0 -0
  100. StreamingCommunity/Api/Site/ilcorsaronero/__init__.py +52 -0
  101. StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/__init__.cpython-313.pyc +0 -0
  102. StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/__init__.cpython-39.pyc +0 -0
  103. StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/costant.cpython-313.pyc +0 -0
  104. StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/costant.cpython-39.pyc +0 -0
  105. StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/site.cpython-313.pyc +0 -0
  106. StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/site.cpython-39.pyc +0 -0
  107. StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/title.cpython-313.pyc +0 -0
  108. StreamingCommunity/Api/Site/ilcorsaronero/__pycache__/title.cpython-39.pyc +0 -0
  109. StreamingCommunity/Api/Site/ilcorsaronero/costant.py +19 -0
  110. StreamingCommunity/Api/Site/ilcorsaronero/site.py +72 -0
  111. StreamingCommunity/Api/Site/ilcorsaronero/title.py +44 -0
  112. StreamingCommunity/Api/Site/ilcorsaronero/util/__pycache__/ilCorsarScraper.cpython-313.pyc +0 -0
  113. StreamingCommunity/Api/Site/ilcorsaronero/util/__pycache__/ilCorsarScraper.cpython-39.pyc +0 -0
  114. StreamingCommunity/Api/Site/ilcorsaronero/util/ilCorsarScraper.py +149 -0
  115. StreamingCommunity/Api/Site/mostraguarda/__init__.py +49 -0
  116. StreamingCommunity/Api/Site/mostraguarda/__pycache__/__init__.cpython-313.pyc +0 -0
  117. StreamingCommunity/Api/Site/mostraguarda/__pycache__/__init__.cpython-39.pyc +0 -0
  118. StreamingCommunity/Api/Site/mostraguarda/__pycache__/costant.cpython-313.pyc +0 -0
  119. StreamingCommunity/Api/Site/mostraguarda/__pycache__/costant.cpython-39.pyc +0 -0
  120. StreamingCommunity/Api/Site/mostraguarda/__pycache__/film.cpython-313.pyc +0 -0
  121. StreamingCommunity/Api/Site/mostraguarda/__pycache__/film.cpython-39.pyc +0 -0
  122. StreamingCommunity/Api/Site/mostraguarda/costant.py +19 -0
  123. StreamingCommunity/Api/Site/mostraguarda/film.py +101 -0
  124. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +56 -0
  125. StreamingCommunity/Api/Site/streamingcommunity/__pycache__/__init__.cpython-313.pyc +0 -0
  126. StreamingCommunity/Api/Site/streamingcommunity/__pycache__/__init__.cpython-39.pyc +0 -0
  127. StreamingCommunity/Api/Site/streamingcommunity/__pycache__/costant.cpython-313.pyc +0 -0
  128. StreamingCommunity/Api/Site/streamingcommunity/__pycache__/costant.cpython-39.pyc +0 -0
  129. StreamingCommunity/Api/Site/streamingcommunity/__pycache__/film.cpython-313.pyc +0 -0
  130. StreamingCommunity/Api/Site/streamingcommunity/__pycache__/film.cpython-39.pyc +0 -0
  131. StreamingCommunity/Api/Site/streamingcommunity/__pycache__/series.cpython-313.pyc +0 -0
  132. StreamingCommunity/Api/Site/streamingcommunity/__pycache__/series.cpython-39.pyc +0 -0
  133. StreamingCommunity/Api/Site/streamingcommunity/__pycache__/site.cpython-313.pyc +0 -0
  134. StreamingCommunity/Api/Site/streamingcommunity/__pycache__/site.cpython-39.pyc +0 -0
  135. StreamingCommunity/Api/Site/streamingcommunity/costant.py +19 -0
  136. StreamingCommunity/Api/Site/streamingcommunity/film.py +75 -0
  137. StreamingCommunity/Api/Site/streamingcommunity/series.py +207 -0
  138. StreamingCommunity/Api/Site/streamingcommunity/site.py +143 -0
  139. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +124 -0
  140. StreamingCommunity/Api/Site/streamingcommunity/util/__pycache__/ScrapeSerie.cpython-313.pyc +0 -0
  141. StreamingCommunity/Api/Site/streamingcommunity/util/__pycache__/ScrapeSerie.cpython-39.pyc +0 -0
  142. StreamingCommunity/Api/Template/Class/SearchType.py +101 -0
  143. StreamingCommunity/Api/Template/Class/__pycache__/SearchType.cpython-313.pyc +0 -0
  144. StreamingCommunity/Api/Template/Class/__pycache__/SearchType.cpython-39.pyc +0 -0
  145. StreamingCommunity/Api/Template/Util/__init__.py +5 -0
  146. StreamingCommunity/Api/Template/Util/__pycache__/__init__.cpython-313.pyc +0 -0
  147. StreamingCommunity/Api/Template/Util/__pycache__/__init__.cpython-39.pyc +0 -0
  148. StreamingCommunity/Api/Template/Util/__pycache__/get_domain.cpython-313.pyc +0 -0
  149. StreamingCommunity/Api/Template/Util/__pycache__/get_domain.cpython-39.pyc +0 -0
  150. StreamingCommunity/Api/Template/Util/__pycache__/manage_ep.cpython-313.pyc +0 -0
  151. StreamingCommunity/Api/Template/Util/__pycache__/manage_ep.cpython-39.pyc +0 -0
  152. StreamingCommunity/Api/Template/Util/__pycache__/recall_search.cpython-313.pyc +0 -0
  153. StreamingCommunity/Api/Template/Util/__pycache__/recall_search.cpython-39.pyc +0 -0
  154. StreamingCommunity/Api/Template/Util/get_domain.py +202 -0
  155. StreamingCommunity/Api/Template/Util/manage_ep.py +179 -0
  156. StreamingCommunity/Api/Template/Util/recall_search.py +37 -0
  157. StreamingCommunity/Api/Template/__init__.py +3 -0
  158. StreamingCommunity/Api/Template/__pycache__/__init__.cpython-313.pyc +0 -0
  159. StreamingCommunity/Api/Template/__pycache__/__init__.cpython-39.pyc +0 -0
  160. StreamingCommunity/Api/Template/__pycache__/site.cpython-313.pyc +0 -0
  161. StreamingCommunity/Api/Template/__pycache__/site.cpython-39.pyc +0 -0
  162. StreamingCommunity/Api/Template/site.py +87 -0
  163. StreamingCommunity/Lib/Downloader/HLS/__pycache__/downloader.cpython-313.pyc +0 -0
  164. StreamingCommunity/Lib/Downloader/HLS/__pycache__/downloader.cpython-39.pyc +0 -0
  165. StreamingCommunity/Lib/Downloader/HLS/__pycache__/proxyes.cpython-313.pyc +0 -0
  166. StreamingCommunity/Lib/Downloader/HLS/__pycache__/proxyes.cpython-39.pyc +0 -0
  167. StreamingCommunity/Lib/Downloader/HLS/__pycache__/segments.cpython-313.pyc +0 -0
  168. StreamingCommunity/Lib/Downloader/HLS/__pycache__/segments.cpython-39.pyc +0 -0
  169. StreamingCommunity/Lib/Downloader/HLS/downloader.py +1008 -0
  170. StreamingCommunity/Lib/Downloader/HLS/proxyes.py +110 -0
  171. StreamingCommunity/Lib/Downloader/HLS/segments.py +573 -0
  172. StreamingCommunity/Lib/Downloader/MP4/__pycache__/downloader.cpython-313.pyc +0 -0
  173. StreamingCommunity/Lib/Downloader/MP4/__pycache__/downloader.cpython-39.pyc +0 -0
  174. StreamingCommunity/Lib/Downloader/MP4/downloader.py +155 -0
  175. StreamingCommunity/Lib/Downloader/TOR/__pycache__/downloader.cpython-313.pyc +0 -0
  176. StreamingCommunity/Lib/Downloader/TOR/__pycache__/downloader.cpython-39.pyc +0 -0
  177. StreamingCommunity/Lib/Downloader/TOR/downloader.py +296 -0
  178. StreamingCommunity/Lib/Downloader/__init__.py +5 -0
  179. StreamingCommunity/Lib/Downloader/__pycache__/__init__.cpython-313.pyc +0 -0
  180. StreamingCommunity/Lib/Downloader/__pycache__/__init__.cpython-39.pyc +0 -0
  181. StreamingCommunity/Lib/FFmpeg/__init__.py +4 -0
  182. StreamingCommunity/Lib/FFmpeg/__pycache__/__init__.cpython-313.pyc +0 -0
  183. StreamingCommunity/Lib/FFmpeg/__pycache__/__init__.cpython-39.pyc +0 -0
  184. StreamingCommunity/Lib/FFmpeg/__pycache__/capture.cpython-313.pyc +0 -0
  185. StreamingCommunity/Lib/FFmpeg/__pycache__/capture.cpython-39.pyc +0 -0
  186. StreamingCommunity/Lib/FFmpeg/__pycache__/command.cpython-313.pyc +0 -0
  187. StreamingCommunity/Lib/FFmpeg/__pycache__/command.cpython-39.pyc +0 -0
  188. StreamingCommunity/Lib/FFmpeg/__pycache__/util.cpython-313.pyc +0 -0
  189. StreamingCommunity/Lib/FFmpeg/__pycache__/util.cpython-39.pyc +0 -0
  190. StreamingCommunity/Lib/FFmpeg/capture.py +170 -0
  191. StreamingCommunity/Lib/FFmpeg/command.py +296 -0
  192. StreamingCommunity/Lib/FFmpeg/util.py +249 -0
  193. StreamingCommunity/Lib/M3U8/__init__.py +6 -0
  194. StreamingCommunity/Lib/M3U8/__pycache__/__init__.cpython-313.pyc +0 -0
  195. StreamingCommunity/Lib/M3U8/__pycache__/__init__.cpython-39.pyc +0 -0
  196. StreamingCommunity/Lib/M3U8/__pycache__/decryptor.cpython-313.pyc +0 -0
  197. StreamingCommunity/Lib/M3U8/__pycache__/decryptor.cpython-39.pyc +0 -0
  198. StreamingCommunity/Lib/M3U8/__pycache__/estimator.cpython-313.pyc +0 -0
  199. StreamingCommunity/Lib/M3U8/__pycache__/estimator.cpython-39.pyc +0 -0
  200. StreamingCommunity/Lib/M3U8/__pycache__/parser.cpython-313.pyc +0 -0
  201. StreamingCommunity/Lib/M3U8/__pycache__/parser.cpython-39.pyc +0 -0
  202. StreamingCommunity/Lib/M3U8/__pycache__/url_fixer.cpython-313.pyc +0 -0
  203. StreamingCommunity/Lib/M3U8/__pycache__/url_fixer.cpython-39.pyc +0 -0
  204. StreamingCommunity/Lib/M3U8/decryptor.py +165 -0
  205. StreamingCommunity/Lib/M3U8/estimator.py +229 -0
  206. StreamingCommunity/Lib/M3U8/parser.py +666 -0
  207. StreamingCommunity/Lib/M3U8/url_fixer.py +58 -0
  208. StreamingCommunity/Lib/TMBD/__init__.py +2 -0
  209. StreamingCommunity/Lib/TMBD/__pycache__/__init__.cpython-313.pyc +0 -0
  210. StreamingCommunity/Lib/TMBD/__pycache__/__init__.cpython-39.pyc +0 -0
  211. StreamingCommunity/Lib/TMBD/__pycache__/obj_tmbd.cpython-313.pyc +0 -0
  212. StreamingCommunity/Lib/TMBD/__pycache__/obj_tmbd.cpython-39.pyc +0 -0
  213. StreamingCommunity/Lib/TMBD/__pycache__/tmdb.cpython-313.pyc +0 -0
  214. StreamingCommunity/Lib/TMBD/__pycache__/tmdb.cpython-39.pyc +0 -0
  215. StreamingCommunity/Lib/TMBD/obj_tmbd.py +39 -0
  216. StreamingCommunity/Lib/TMBD/tmdb.py +346 -0
  217. StreamingCommunity/Upload/__pycache__/update.cpython-313.pyc +0 -0
  218. StreamingCommunity/Upload/__pycache__/update.cpython-39.pyc +0 -0
  219. StreamingCommunity/Upload/__pycache__/version.cpython-313.pyc +0 -0
  220. StreamingCommunity/Upload/__pycache__/version.cpython-39.pyc +0 -0
  221. StreamingCommunity/Upload/update.py +67 -0
  222. StreamingCommunity/Upload/version.py +5 -0
  223. StreamingCommunity/Util/__pycache__/_jsonConfig.cpython-313.pyc +0 -0
  224. StreamingCommunity/Util/__pycache__/_jsonConfig.cpython-39.pyc +0 -0
  225. StreamingCommunity/Util/__pycache__/call_stack.cpython-313.pyc +0 -0
  226. StreamingCommunity/Util/__pycache__/call_stack.cpython-39.pyc +0 -0
  227. StreamingCommunity/Util/__pycache__/color.cpython-313.pyc +0 -0
  228. StreamingCommunity/Util/__pycache__/color.cpython-39.pyc +0 -0
  229. StreamingCommunity/Util/__pycache__/console.cpython-313.pyc +0 -0
  230. StreamingCommunity/Util/__pycache__/console.cpython-39.pyc +0 -0
  231. StreamingCommunity/Util/__pycache__/ffmpeg_installer.cpython-313.pyc +0 -0
  232. StreamingCommunity/Util/__pycache__/ffmpeg_installer.cpython-39.pyc +0 -0
  233. StreamingCommunity/Util/__pycache__/headers.cpython-313.pyc +0 -0
  234. StreamingCommunity/Util/__pycache__/headers.cpython-39.pyc +0 -0
  235. StreamingCommunity/Util/__pycache__/logger.cpython-313.pyc +0 -0
  236. StreamingCommunity/Util/__pycache__/logger.cpython-39.pyc +0 -0
  237. StreamingCommunity/Util/__pycache__/message.cpython-313.pyc +0 -0
  238. StreamingCommunity/Util/__pycache__/message.cpython-39.pyc +0 -0
  239. StreamingCommunity/Util/__pycache__/os.cpython-313.pyc +0 -0
  240. StreamingCommunity/Util/__pycache__/os.cpython-39.pyc +0 -0
  241. StreamingCommunity/Util/__pycache__/table.cpython-313.pyc +0 -0
  242. StreamingCommunity/Util/__pycache__/table.cpython-39.pyc +0 -0
  243. StreamingCommunity/Util/_jsonConfig.py +228 -0
  244. StreamingCommunity/Util/call_stack.py +42 -0
  245. StreamingCommunity/Util/color.py +20 -0
  246. StreamingCommunity/Util/console.py +12 -0
  247. StreamingCommunity/Util/ffmpeg_installer.py +371 -0
  248. StreamingCommunity/Util/headers.py +160 -0
  249. StreamingCommunity/Util/logger.py +62 -0
  250. StreamingCommunity/Util/message.py +64 -0
  251. StreamingCommunity/Util/os.py +507 -0
  252. StreamingCommunity/Util/table.py +229 -0
  253. StreamingCommunity/__pycache__/__init__.cpython-313.pyc +0 -0
  254. StreamingCommunity/__pycache__/__init__.cpython-39.pyc +0 -0
  255. StreamingCommunity/__pycache__/run.cpython-313.pyc +0 -0
  256. StreamingCommunity/__pycache__/run.cpython-39.pyc +0 -0
  257. {StreamingCommunity-2.5.0.dist-info → StreamingCommunity-2.5.2.dist-info}/METADATA +1 -1
  258. StreamingCommunity-2.5.2.dist-info/RECORD +264 -0
  259. StreamingCommunity-2.5.0.dist-info/RECORD +0 -8
  260. {StreamingCommunity-2.5.0.dist-info → StreamingCommunity-2.5.2.dist-info}/LICENSE +0 -0
  261. {StreamingCommunity-2.5.0.dist-info → StreamingCommunity-2.5.2.dist-info}/WHEEL +0 -0
  262. {StreamingCommunity-2.5.0.dist-info → StreamingCommunity-2.5.2.dist-info}/entry_points.txt +0 -0
  263. {StreamingCommunity-2.5.0.dist-info → StreamingCommunity-2.5.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,124 @@
1
+ # 01.03.24
2
+
3
+ import json
4
+ import logging
5
+
6
+
7
+ # External libraries
8
+ import httpx
9
+ from bs4 import BeautifulSoup
10
+
11
+
12
+ # Internal utilities
13
+ from StreamingCommunity.Util.headers import get_headers
14
+ from StreamingCommunity.Util._jsonConfig import config_manager
15
+ from StreamingCommunity.Api.Player.Helper.Vixcloud.util import Season, EpisodeManager
16
+
17
+
18
+ # Variable
19
+ max_timeout = config_manager.get_int("REQUESTS", "timeout")
20
+
21
+
22
+ class ScrapeSerie:
23
+ def __init__(self, site_name: str):
24
+ """
25
+ Initialize the ScrapeSerie class for scraping TV series information.
26
+
27
+ Args:
28
+ site_name (str): Name of the streaming site to scrape from
29
+ """
30
+ self.is_series = False
31
+ self.headers = {'user-agent': get_headers()}
32
+ self.base_name = site_name
33
+ self.domain = config_manager.get_dict('SITE', self.base_name)['domain']
34
+
35
+ def setup(self, version: str = None, media_id: int = None, series_name: str = None):
36
+ """
37
+ Set up the scraper with specific media details.
38
+
39
+ Args:
40
+ version (str, optional): Site version for request headers
41
+ media_id (int, optional): Unique identifier for the media
42
+ series_name (str, optional): Name of the TV series
43
+ """
44
+ self.version = version
45
+ self.media_id = media_id
46
+
47
+ # If series name is provided, initialize series-specific managers
48
+ if series_name is not None:
49
+ self.is_series = True
50
+ self.series_name = series_name
51
+ self.season_manager = None
52
+ self.episode_manager: EpisodeManager = EpisodeManager()
53
+
54
+ def collect_info_title(self) -> None:
55
+ """
56
+ Retrieve season information for a TV series from the streaming site.
57
+
58
+ Raises:
59
+ Exception: If there's an error fetching season information
60
+ """
61
+ try:
62
+ response = httpx.get(
63
+ url=f"https://{self.base_name}.{self.domain}/titles/{self.media_id}-{self.series_name}",
64
+ headers=self.headers,
65
+ timeout=max_timeout
66
+ )
67
+ response.raise_for_status()
68
+
69
+ # Extract seasons from JSON response
70
+ soup = BeautifulSoup(response.text, "html.parser")
71
+ json_response = json.loads(soup.find("div", {"id": "app"}).get("data-page"))
72
+ self.version = json_response['version']
73
+
74
+ """
75
+ response = httpx.post(
76
+ url=f'https://{self.base_name}.{self.domain}/api/titles/preview/{self.media_id}',
77
+ headers={'User-Agent': get_headers()}
78
+ )
79
+ response.raise_for_status()
80
+
81
+
82
+ # Extract seasons from JSON response
83
+ json_response = response.json()
84
+ """
85
+
86
+ # Collect info about season
87
+ self.season_manager = Season(json_response.get("props").get("title"))
88
+
89
+ except Exception as e:
90
+ logging.error(f"Error collecting season info: {e}")
91
+ raise
92
+
93
+ def collect_info_season(self, number_season: int) -> None:
94
+ """
95
+ Retrieve episode information for a specific season.
96
+
97
+ Args:
98
+ number_season (int): Season number to fetch episodes for
99
+
100
+ Raises:
101
+ Exception: If there's an error fetching episode information
102
+ """
103
+ try:
104
+ response = httpx.get(
105
+ url=f'https://{self.base_name}.{self.domain}/titles/{self.media_id}-{self.series_name}/stagione-{number_season}',
106
+ headers={
107
+ 'User-Agent': get_headers(),
108
+ 'x-inertia': 'true',
109
+ 'x-inertia-version': self.version,
110
+ },
111
+ timeout=max_timeout
112
+ )
113
+ response.raise_for_status()
114
+
115
+ # Extract episodes from JSON response
116
+ json_response = response.json().get('props').get('loadedSeason').get('episodes')
117
+
118
+ # Add each episode to the episode manager
119
+ for dict_episode in json_response:
120
+ self.episode_manager.add(dict_episode)
121
+
122
+ except Exception as e:
123
+ logging.error(f"Error collecting title season info: {e}")
124
+ raise
@@ -0,0 +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)})"
@@ -0,0 +1,5 @@
1
+ # 23.11.24
2
+
3
+ from .recall_search import execute_search
4
+ from .get_domain import search_domain
5
+ from .manage_ep import manage_selection, map_episode_title, validate_episode_selection, validate_selection, dynamic_format_number
@@ -0,0 +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.")
202
+ return domain, f"{base_url}.{domain}"
@@ -0,0 +1,179 @@
1
+ # 19.06.24
2
+
3
+ import logging
4
+ from typing import List
5
+
6
+
7
+ # Internal utilities
8
+ from StreamingCommunity.Util._jsonConfig import config_manager
9
+ from StreamingCommunity.Util.os import os_manager
10
+
11
+
12
+ # Config
13
+ MAP_EPISODE = config_manager.get('DEFAULT', 'map_episode_name')
14
+
15
+
16
+ def dynamic_format_number(n: int) -> str:
17
+ """
18
+ Formats a number by adding a leading zero if it is less than 9.
19
+ The width of the resulting string is dynamic, calculated as the number of digits in the number plus one
20
+ for numbers less than 9, otherwise the width remains the same.
21
+
22
+ Parameters:
23
+ - n (int): The number to format.
24
+
25
+ Returns:
26
+ - str: The formatted number as a string with a leading zero if the number is less than 9.
27
+ """
28
+ if n < 10:
29
+ width = len(str(n)) + 1
30
+ else:
31
+ width = len(str(n))
32
+
33
+ return str(n).zfill(width)
34
+
35
+
36
+ def manage_selection(cmd_insert: str, max_count: int) -> List[int]:
37
+ """
38
+ Manage user selection for seasons or episodes to download.
39
+
40
+ Parameters:
41
+ - cmd_insert (str): User input for selection.
42
+ - max_count (int): Maximum count available.
43
+
44
+ Returns:
45
+ list_selection (List[int]): List of selected items.
46
+ """
47
+ list_selection = []
48
+ logging.info(f"Command insert: {cmd_insert}, end index: {max_count + 1}")
49
+
50
+ # For a single number (e.g., '5')
51
+ if cmd_insert.isnumeric():
52
+ list_selection.append(int(cmd_insert))
53
+
54
+ # For a range (e.g., '5-12')
55
+ elif "-" in cmd_insert:
56
+ start, end = map(str.strip, cmd_insert.split('-'))
57
+ start = int(start)
58
+ end = int(end) if end.isnumeric() else max_count
59
+
60
+ list_selection = list(range(start, end + 1))
61
+
62
+ # For all items ('*')
63
+ elif cmd_insert == "*":
64
+ list_selection = list(range(1, max_count + 1))
65
+
66
+ else:
67
+ raise ValueError("Invalid input format")
68
+
69
+ logging.info(f"List return: {list_selection}")
70
+ return list_selection
71
+
72
+
73
+ def map_episode_title(tv_name: str, number_season: int, episode_number: int, episode_name: str) -> str:
74
+ """
75
+ Maps the episode title to a specific format.
76
+
77
+ Parameters:
78
+ tv_name (str): The name of the TV show.
79
+ number_season (int): The season number.
80
+ episode_number (int): The episode number.
81
+ episode_name (str): The original name of the episode.
82
+
83
+ Returns:
84
+ str: The mapped episode title.
85
+ """
86
+ map_episode_temp = MAP_EPISODE
87
+
88
+ if tv_name != None:
89
+ map_episode_temp = map_episode_temp.replace("%(tv_name)", os_manager.get_sanitize_file(tv_name))
90
+
91
+ if number_season != None:
92
+ map_episode_temp = map_episode_temp.replace("%(season)", number_season)
93
+ else:
94
+ map_episode_temp = map_episode_temp.replace("%(season)", dynamic_format_number(0))
95
+
96
+ if episode_number != None:
97
+ map_episode_temp = map_episode_temp.replace("%(episode)", dynamic_format_number(episode_number))
98
+ else:
99
+ map_episode_temp = map_episode_temp.replace("%(episode)", dynamic_format_number(0))
100
+
101
+ if episode_name != None:
102
+ map_episode_temp = map_episode_temp.replace("%(episode_name)", os_manager.get_sanitize_file(episode_name))
103
+
104
+ logging.info(f"Map episode string return: {map_episode_temp}")
105
+ return map_episode_temp
106
+
107
+
108
+ # --> for season
109
+ def validate_selection(list_season_select: List[int], seasons_count: int) -> List[int]:
110
+ """
111
+ Validates and adjusts the selected seasons based on the available seasons.
112
+
113
+ Parameters:
114
+ - list_season_select (List[int]): List of seasons selected by the user.
115
+ - seasons_count (int): Total number of available seasons.
116
+
117
+ Returns:
118
+ - List[int]: Adjusted list of valid season numbers.
119
+ """
120
+ while True:
121
+ try:
122
+
123
+ # Remove any seasons greater than the available seasons
124
+ valid_seasons = [season for season in list_season_select if 1 <= season <= seasons_count]
125
+
126
+ # If the list is empty, the input was completely invalid
127
+ if not valid_seasons:
128
+ logging.error(f"Invalid selection: The selected seasons are outside the available range (1-{seasons_count}). Please try again.")
129
+
130
+ # Re-prompt for valid input
131
+ input_seasons = input(f"Enter valid season numbers (1-{seasons_count}): ")
132
+ list_season_select = list(map(int, input_seasons.split(',')))
133
+ continue # Re-prompt the user if the selection is invalid
134
+
135
+ return valid_seasons # Return the valid seasons if the input is correct
136
+
137
+ except ValueError:
138
+ logging.error("Error: Please enter valid integers separated by commas.")
139
+
140
+ # Prompt the user for valid input again
141
+ input_seasons = input(f"Enter valid season numbers (1-{seasons_count}): ")
142
+ list_season_select = list(map(int, input_seasons.split(',')))
143
+
144
+
145
+ # --> for episode
146
+ def validate_episode_selection(list_episode_select: List[int], episodes_count: int) -> List[int]:
147
+ """
148
+ Validates and adjusts the selected episodes based on the available episodes.
149
+
150
+ Parameters:
151
+ - list_episode_select (List[int]): List of episodes selected by the user.
152
+ - episodes_count (int): Total number of available episodes in the season.
153
+
154
+ Returns:
155
+ - List[int]: Adjusted list of valid episode numbers.
156
+ """
157
+ while True:
158
+ try:
159
+
160
+ # Remove any episodes greater than the available episodes
161
+ valid_episodes = [episode for episode in list_episode_select if 1 <= episode <= episodes_count]
162
+
163
+ # If the list is empty, the input was completely invalid
164
+ if not valid_episodes:
165
+ logging.error(f"Invalid selection: The selected episodes are outside the available range (1-{episodes_count}). Please try again.")
166
+
167
+ # Re-prompt for valid input
168
+ input_episodes = input(f"Enter valid episode numbers (1-{episodes_count}): ")
169
+ list_episode_select = list(map(int, input_episodes.split(',')))
170
+ continue # Re-prompt the user if the selection is invalid
171
+
172
+ return valid_episodes
173
+
174
+ except ValueError:
175
+ logging.error("Error: Please enter valid integers separated by commas.")
176
+
177
+ # Prompt the user for valid input again
178
+ input_episodes = input(f"Enter valid episode numbers (1-{episodes_count}): ")
179
+ list_episode_select = list(map(int, input_episodes.split(',')))
@@ -0,0 +1,37 @@
1
+ # 19.10.24
2
+
3
+ import os
4
+ import sys
5
+
6
+ def execute_search(info):
7
+ """
8
+ Dynamically imports and executes a specified function from a module defined in the info dictionary.
9
+
10
+ Parameters:
11
+ info (dict): A dictionary containing the function name, folder, and module information.
12
+ """
13
+
14
+ # Define the project path using the folder from the info dictionary
15
+ project_path = os.path.dirname(info['folder']) # Get the base path for the project
16
+
17
+ # Add the project path to sys.path
18
+ if project_path not in sys.path:
19
+ sys.path.append(project_path)
20
+
21
+ # Attempt to import the specified function from the module
22
+ try:
23
+ # Construct the import statement dynamically
24
+ module_path = f"StreamingCommunity.Api.Site{info['folder_base']}"
25
+ exec(f"from {module_path} import {info['function']}")
26
+
27
+ # Call the specified function
28
+ eval(info['function'])() # Calls the search function
29
+
30
+ except ModuleNotFoundError as e:
31
+ print(f"ModuleNotFoundError: {e}")
32
+
33
+ except ImportError as e:
34
+ print(f"ImportError: {e}")
35
+
36
+ except Exception as e:
37
+ print(f"An error occurred: {e}")
@@ -0,0 +1,3 @@
1
+ # 19.06.24
2
+
3
+ from .site import get_select_title