StreamingCommunity 3.0.6__tar.gz → 3.0.7__tar.gz

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.
Files changed (106) hide show
  1. {streamingcommunity-3.0.6/StreamingCommunity.egg-info → streamingcommunity-3.0.7}/PKG-INFO +30 -12
  2. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/README.md +29 -11
  3. streamingcommunity-3.0.7/StreamingCommunity/Api/Player/maxstream.py +141 -0
  4. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Player/vixcloud.py +5 -3
  5. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/1337xx/__init__.py +2 -2
  6. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/altadefinizione/__init__.py +2 -2
  7. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/altadefinizione/film.py +15 -35
  8. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/animeunity/__init__.py +1 -1
  9. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +21 -23
  10. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/animeworld/__init__.py +1 -1
  11. streamingcommunity-3.0.7/StreamingCommunity/Api/Site/cb01new/__init__.py +72 -0
  12. streamingcommunity-3.0.7/StreamingCommunity/Api/Site/cb01new/film.py +62 -0
  13. streamingcommunity-3.0.7/StreamingCommunity/Api/Site/cb01new/site.py +78 -0
  14. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/guardaserie/__init__.py +1 -1
  15. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/raiplay/__init__.py +1 -1
  16. streamingcommunity-3.0.7/StreamingCommunity/Api/Site/streamingcommunity/__init__.py +164 -0
  17. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/streamingcommunity/film.py +2 -2
  18. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/streamingcommunity/series.py +4 -4
  19. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/streamingcommunity/site.py +7 -4
  20. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +6 -3
  21. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/streamingwatch/__init__.py +10 -4
  22. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/streamingwatch/site.py +12 -5
  23. streamingcommunity-3.0.7/StreamingCommunity/Api/Template/site.py +129 -0
  24. streamingcommunity-3.0.7/StreamingCommunity/Lib/Proxies/proxy.py +72 -0
  25. streamingcommunity-3.0.7/StreamingCommunity/TelegramHelp/config.json +62 -0
  26. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/TelegramHelp/telegram_bot.py +4 -0
  27. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Upload/version.py +1 -1
  28. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/run.py +2 -2
  29. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7/StreamingCommunity.egg-info}/PKG-INFO +30 -12
  30. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity.egg-info/SOURCES.txt +5 -0
  31. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/setup.py +1 -1
  32. streamingcommunity-3.0.6/StreamingCommunity/Api/Site/streamingcommunity/__init__.py +0 -130
  33. streamingcommunity-3.0.6/StreamingCommunity/Api/Template/site.py +0 -84
  34. streamingcommunity-3.0.6/StreamingCommunity/Lib/Proxies/proxy.py +0 -232
  35. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/LICENSE +0 -0
  36. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/MANIFEST.in +0 -0
  37. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Player/Helper/Vixcloud/js_parser.py +0 -0
  38. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +0 -0
  39. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Player/ddl.py +0 -0
  40. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Player/hdplayer.py +0 -0
  41. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Player/mediapolisvod.py +0 -0
  42. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Player/mixdrop.py +0 -0
  43. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Player/supervideo.py +0 -0
  44. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Player/sweetpixel.py +0 -0
  45. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/1337xx/site.py +0 -0
  46. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/1337xx/title.py +0 -0
  47. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/altadefinizione/series.py +0 -0
  48. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/altadefinizione/site.py +0 -0
  49. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py +0 -0
  50. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/animeunity/film.py +0 -0
  51. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/animeunity/serie.py +0 -0
  52. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/animeunity/site.py +0 -0
  53. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/animeworld/film.py +0 -0
  54. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/animeworld/serie.py +0 -0
  55. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/animeworld/site.py +0 -0
  56. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py +0 -0
  57. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/guardaserie/series.py +0 -0
  58. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/guardaserie/site.py +0 -0
  59. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +0 -0
  60. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/raiplay/film.py +0 -0
  61. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/raiplay/series.py +0 -0
  62. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/raiplay/site.py +0 -0
  63. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +0 -0
  64. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/streamingwatch/film.py +0 -0
  65. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/streamingwatch/series.py +0 -0
  66. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Site/streamingwatch/util/ScrapeSerie.py +0 -0
  67. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Template/Class/SearchType.py +0 -0
  68. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Template/Util/__init__.py +0 -0
  69. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Template/Util/manage_ep.py +0 -0
  70. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Template/__init__.py +0 -0
  71. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Api/Template/config_loader.py +0 -0
  72. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/Downloader/HLS/downloader.py +0 -0
  73. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/Downloader/HLS/segments.py +0 -0
  74. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/Downloader/MP4/downloader.py +0 -0
  75. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/Downloader/TOR/downloader.py +0 -0
  76. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/Downloader/__init__.py +0 -0
  77. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/FFmpeg/__init__.py +0 -0
  78. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/FFmpeg/capture.py +0 -0
  79. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/FFmpeg/command.py +0 -0
  80. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/FFmpeg/util.py +0 -0
  81. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/M3U8/__init__.py +0 -0
  82. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/M3U8/decryptor.py +0 -0
  83. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/M3U8/estimator.py +0 -0
  84. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/M3U8/parser.py +0 -0
  85. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/M3U8/url_fixer.py +0 -0
  86. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/TMBD/__init__.py +0 -0
  87. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/TMBD/obj_tmbd.py +0 -0
  88. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Lib/TMBD/tmdb.py +0 -0
  89. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/TelegramHelp/__init__.py +0 -0
  90. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Upload/update.py +0 -0
  91. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Util/color.py +0 -0
  92. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Util/config_json.py +0 -0
  93. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Util/ffmpeg_installer.py +0 -0
  94. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Util/headers.py +0 -0
  95. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Util/logger.py +0 -0
  96. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Util/message.py +0 -0
  97. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Util/os.py +0 -0
  98. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/Util/table.py +0 -0
  99. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/__init__.py +0 -0
  100. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity/global_search.py +0 -0
  101. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity.egg-info/dependency_links.txt +0 -0
  102. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity.egg-info/entry_points.txt +0 -0
  103. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity.egg-info/requires.txt +0 -0
  104. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/StreamingCommunity.egg-info/top_level.txt +0 -0
  105. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/requirements.txt +0 -0
  106. {streamingcommunity-3.0.6 → streamingcommunity-3.0.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: StreamingCommunity
3
- Version: 3.0.6
3
+ Version: 3.0.7
4
4
  Home-page: https://github.com/Lovi-0/StreamingCommunity
5
5
  Author: Lovi-0
6
6
  Project-URL: Bug Reports, https://github.com/Lovi-0/StreamingCommunity/issues
@@ -506,7 +506,11 @@ To enable qBittorrent integration, follow the setup guide [here](https://github.
506
506
  "REQUESTS": {
507
507
  "verify": false,
508
508
  "timeout": 20,
509
- "max_retry": 8
509
+ "max_retry": 8,
510
+ "proxy": {
511
+ "http": "http://username:password@host:port",
512
+ "https": "https://username:password@host:port"
513
+ }
510
514
  }
511
515
  }
512
516
  ```
@@ -514,6 +518,22 @@ To enable qBittorrent integration, follow the setup guide [here](https://github.
514
518
  - `verify`: Verifies SSL certificates
515
519
  - `timeout`: Maximum timeout (in seconds) for each request
516
520
  - `max_retry`: Number of retry attempts per segment during M3U8 index download
521
+ - `proxy`: Proxy configuration for HTTP/HTTPS requests
522
+ * Set to empty string `""` to disable proxies (default)
523
+ * Example with authentication:
524
+ ```json
525
+ "proxy": {
526
+ "http": "http://username:password@host:port",
527
+ "https": "https://username:password@host:port"
528
+ }
529
+ ```
530
+ * Example without authentication:
531
+ ```json
532
+ "proxy": {
533
+ "http": "http://host:port",
534
+ "https": "https://host:port"
535
+ }
536
+ ```
517
537
  </details>
518
538
 
519
539
  <details>
@@ -764,26 +784,24 @@ The `run-container` command mounts also the `config.json` file, so any change to
764
784
  The bot was created to replace terminal commands and allow interaction via Telegram. Each download runs within a screen session, enabling multiple downloads to run simultaneously.
765
785
 
766
786
  To run the bot in the background, simply start it inside a screen session and then press Ctrl + A, followed by D, to detach from the session without stopping the bot.
767
- </details>
768
-
769
- <details>
770
- <summary>🤖 Bot Commands</summary>
771
787
 
772
788
  Command Functions:
773
789
 
774
790
  🔹 /start – Starts a new search for a download. This command performs the same operations as manually running the script in the terminal with test_run.py.
775
791
 
776
792
  🔹 /list – Displays the status of active downloads, with options to:
777
- - Stop an incorrect download using /stop <ID>
778
- - View the real-time output of a download using /screen <ID>
793
+
794
+ Stop an incorrect download using /stop <ID>.
795
+
796
+ View the real-time output of a download using /screen <ID>.
779
797
 
780
798
  ⚠ Warning: If a download is interrupted, incomplete files may remain in the folder specified in config.json. These files must be deleted manually to avoid storage or management issues.
781
- </details>
782
799
 
783
- <details>
784
- <summary>🔧 Environment Setup</summary>
800
+ 🛠 Configuration: Currently, the bot's settings are stored in the config.json file, which is located in the same directory as the telegram_bot.py script.
801
+
802
+ ## .env Example:
785
803
 
786
- Create an `.env` file with:
804
+ You need to create an .env file and enter your Telegram token and user ID to authorize only one user to use it
787
805
 
788
806
  ```
789
807
  TOKEN_TELEGRAM=IlTuo2131TOKEN$12D3Telegram
@@ -470,7 +470,11 @@ To enable qBittorrent integration, follow the setup guide [here](https://github.
470
470
  "REQUESTS": {
471
471
  "verify": false,
472
472
  "timeout": 20,
473
- "max_retry": 8
473
+ "max_retry": 8,
474
+ "proxy": {
475
+ "http": "http://username:password@host:port",
476
+ "https": "https://username:password@host:port"
477
+ }
474
478
  }
475
479
  }
476
480
  ```
@@ -478,6 +482,22 @@ To enable qBittorrent integration, follow the setup guide [here](https://github.
478
482
  - `verify`: Verifies SSL certificates
479
483
  - `timeout`: Maximum timeout (in seconds) for each request
480
484
  - `max_retry`: Number of retry attempts per segment during M3U8 index download
485
+ - `proxy`: Proxy configuration for HTTP/HTTPS requests
486
+ * Set to empty string `""` to disable proxies (default)
487
+ * Example with authentication:
488
+ ```json
489
+ "proxy": {
490
+ "http": "http://username:password@host:port",
491
+ "https": "https://username:password@host:port"
492
+ }
493
+ ```
494
+ * Example without authentication:
495
+ ```json
496
+ "proxy": {
497
+ "http": "http://host:port",
498
+ "https": "https://host:port"
499
+ }
500
+ ```
481
501
  </details>
482
502
 
483
503
  <details>
@@ -728,26 +748,24 @@ The `run-container` command mounts also the `config.json` file, so any change to
728
748
  The bot was created to replace terminal commands and allow interaction via Telegram. Each download runs within a screen session, enabling multiple downloads to run simultaneously.
729
749
 
730
750
  To run the bot in the background, simply start it inside a screen session and then press Ctrl + A, followed by D, to detach from the session without stopping the bot.
731
- </details>
732
-
733
- <details>
734
- <summary>🤖 Bot Commands</summary>
735
751
 
736
752
  Command Functions:
737
753
 
738
754
  🔹 /start – Starts a new search for a download. This command performs the same operations as manually running the script in the terminal with test_run.py.
739
755
 
740
756
  🔹 /list – Displays the status of active downloads, with options to:
741
- - Stop an incorrect download using /stop <ID>
742
- - View the real-time output of a download using /screen <ID>
757
+
758
+ Stop an incorrect download using /stop <ID>.
759
+
760
+ View the real-time output of a download using /screen <ID>.
743
761
 
744
762
  ⚠ Warning: If a download is interrupted, incomplete files may remain in the folder specified in config.json. These files must be deleted manually to avoid storage or management issues.
745
- </details>
746
763
 
747
- <details>
748
- <summary>🔧 Environment Setup</summary>
764
+ 🛠 Configuration: Currently, the bot's settings are stored in the config.json file, which is located in the same directory as the telegram_bot.py script.
765
+
766
+ ## .env Example:
749
767
 
750
- Create an `.env` file with:
768
+ You need to create an .env file and enter your Telegram token and user ID to authorize only one user to use it
751
769
 
752
770
  ```
753
771
  TOKEN_TELEGRAM=IlTuo2131TOKEN$12D3Telegram
@@ -0,0 +1,141 @@
1
+ # 05.07.24
2
+ # NOTE: NOT USED
3
+
4
+ import re
5
+ import logging
6
+
7
+
8
+ # External libraries
9
+ import httpx
10
+ import jsbeautifier
11
+ from bs4 import BeautifulSoup
12
+
13
+
14
+ # Internal utilities
15
+ from StreamingCommunity.Util.config_json import config_manager
16
+ from StreamingCommunity.Util.headers import get_userAgent
17
+
18
+
19
+ # Variable
20
+ MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
21
+
22
+
23
+ class VideoSource:
24
+ def __init__(self, url: str):
25
+ """
26
+ Sets up the video source with the provided URL.
27
+
28
+ Parameters:
29
+ - url (str): The URL of the video.
30
+ """
31
+ self.url = url
32
+ self.redirect_url = None
33
+ self.maxstream_url = None
34
+ self.m3u8_url = None
35
+ self.headers = {'user-agent': get_userAgent()}
36
+
37
+ def get_redirect_url(self):
38
+ """
39
+ Sends a request to the initial URL and extracts the redirect URL.
40
+ """
41
+ try:
42
+ response = httpx.get(self.url, headers=self.headers, follow_redirects=True, timeout=MAX_TIMEOUT)
43
+ response.raise_for_status()
44
+
45
+ # Extract the redirect URL from the HTML
46
+ soup = BeautifulSoup(response.text, "html.parser")
47
+ self.redirect_url = soup.find("div", id="iframen1").get("data-src")
48
+ logging.info(f"Redirect URL: {self.redirect_url}")
49
+
50
+ return self.redirect_url
51
+
52
+ except Exception as e:
53
+ logging.error(f"Error parsing HTML: {e}")
54
+ raise
55
+
56
+ def get_maxstream_url(self):
57
+ """
58
+ Sends a request to the redirect URL and extracts the Maxstream URL.
59
+ """
60
+ try:
61
+ response = httpx.get(self.redirect_url, headers=self.headers, follow_redirects=True, timeout=MAX_TIMEOUT)
62
+ response.raise_for_status()
63
+
64
+ # Extract the Maxstream URL from the HTML
65
+ soup = BeautifulSoup(response.text, "html.parser")
66
+ maxstream_url = soup.find("a")
67
+
68
+ if maxstream_url is None:
69
+
70
+ # If no anchor tag is found, try the alternative method
71
+ logging.warning("Anchor tag not found. Trying the alternative method.")
72
+ headers = {
73
+ 'origin': 'https://stayonline.pro',
74
+ 'user-agent': get_userAgent(),
75
+ 'x-requested-with': 'XMLHttpRequest',
76
+ }
77
+
78
+ # Make request to stayonline api
79
+ data = {'id': self.redirect_url.split("/")[-2], 'ref': ''}
80
+ response = httpx.post('https://stayonline.pro/ajax/linkEmbedView.php', headers=headers, data=data)
81
+ response.raise_for_status()
82
+ uprot_url = response.json()['data']['value']
83
+
84
+ # Retry getting maxtstream url
85
+ response = httpx.get(uprot_url, headers=self.headers, follow_redirects=True, timeout=MAX_TIMEOUT)
86
+ response.raise_for_status()
87
+ soup = BeautifulSoup(response.text, "html.parser")
88
+ maxstream_url = soup.find("a").get("href")
89
+
90
+ else:
91
+ maxstream_url = maxstream_url.get("href")
92
+
93
+ self.maxstream_url = maxstream_url
94
+ logging.info(f"Maxstream URL: {self.maxstream_url}")
95
+
96
+ return self.maxstream_url
97
+
98
+ except Exception as e:
99
+ logging.error(f"Error during the request: {e}")
100
+ raise
101
+
102
+ def get_m3u8_url(self):
103
+ """
104
+ Sends a request to the Maxstream URL and extracts the .m3u8 file URL.
105
+ """
106
+ try:
107
+ response = httpx.get(self.maxstream_url, headers=self.headers, follow_redirects=True, timeout=MAX_TIMEOUT)
108
+ response.raise_for_status()
109
+ soup = BeautifulSoup(response.text, "html.parser")
110
+
111
+ # Iterate over all script tags in the HTML
112
+ for script in soup.find_all("script"):
113
+ if "eval(function(p,a,c,k,e,d)" in script.text:
114
+
115
+ # Execute the script using
116
+ data_js = jsbeautifier.beautify(script.text)
117
+
118
+ # Extract the .m3u8 URL from the script's output
119
+ match = re.search(r'sources:\s*\[\{\s*src:\s*"([^"]+)"', data_js)
120
+
121
+ if match:
122
+ self.m3u8_url = match.group(1)
123
+ logging.info(f"M3U8 URL: {self.m3u8_url}")
124
+ break
125
+
126
+ else:
127
+ logging.error("Failed to find M3U8 URL: No match found")
128
+
129
+ return self.m3u8_url
130
+
131
+ except Exception as e:
132
+ logging.error(f"Error executing the Node.js script: {e}")
133
+ raise
134
+
135
+ def get_playlist(self):
136
+ """
137
+ Executes the entire flow to obtain the final .m3u8 file URL.
138
+ """
139
+ self.get_redirect_url()
140
+ self.get_maxstream_url()
141
+ return self.get_m3u8_url()
@@ -1,6 +1,6 @@
1
1
  # 01.03.24
2
2
 
3
- import sys
3
+ import time
4
4
  import logging
5
5
  from urllib.parse import urlparse, parse_qs, urlencode, urlunparse
6
6
 
@@ -24,7 +24,7 @@ console = Console()
24
24
 
25
25
 
26
26
  class VideoSource:
27
- def __init__(self, url: str, is_series: bool, media_id: int = None):
27
+ def __init__(self, url: str, is_series: bool, media_id: int = None, proxy: str = None):
28
28
  """
29
29
  Initialize video source for streaming site.
30
30
 
@@ -35,6 +35,7 @@ class VideoSource:
35
35
  """
36
36
  self.headers = {'user-agent': get_userAgent()}
37
37
  self.url = url
38
+ self.proxy = proxy
38
39
  self.is_series = is_series
39
40
  self.media_id = media_id
40
41
  self.iframe_src = None
@@ -55,7 +56,7 @@ class VideoSource:
55
56
  }
56
57
 
57
58
  try:
58
- response = httpx.get(f"{self.url}/iframe/{self.media_id}", params=params, timeout=MAX_TIMEOUT)
59
+ response = httpx.get(f"{self.url}/iframe/{self.media_id}", headers=self.headers, params=params, timeout=MAX_TIMEOUT, proxy=self.proxy)
59
60
  response.raise_for_status()
60
61
 
61
62
  # Parse response with BeautifulSoup to get iframe source
@@ -81,6 +82,7 @@ class VideoSource:
81
82
  self.window_video = WindowVideo(converter.get('video'))
82
83
  self.window_streams = StreamsCollection(converter.get('streams'))
83
84
  self.window_parameter = WindowParameter(converter.get('masterPlaylist'))
85
+ time.sleep(0.5)
84
86
 
85
87
  except Exception as e:
86
88
  logging.error(f"Error parsing script: {e}")
@@ -24,7 +24,7 @@ indice = 3
24
24
  _useFor = "Torrent"
25
25
  _priority = 0
26
26
  _engineDownload = "Torrent"
27
- _deprecate = False
27
+ _deprecate = True
28
28
 
29
29
  console = Console()
30
30
  msg = Prompt()
@@ -62,7 +62,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
62
62
  return media_search_manager
63
63
 
64
64
  if len_database > 0:
65
- select_title = get_select_title(table_show_manager, media_search_manager)
65
+ select_title = get_select_title(table_show_manager, media_search_manager, len_database)
66
66
  download_title(select_title)
67
67
 
68
68
  else:
@@ -27,7 +27,7 @@ indice = 2
27
27
  _useFor = "Film_&_Serie"
28
28
  _priority = 0
29
29
  _engineDownload = "hls"
30
- _deprecate = True
30
+ _deprecate = False
31
31
 
32
32
  msg = Prompt()
33
33
  console = Console()
@@ -110,7 +110,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
110
110
  bot = get_bot_instance()
111
111
 
112
112
  if len_database > 0:
113
- select_title = get_select_title(table_show_manager, media_search_manager)
113
+ select_title = get_select_title(table_show_manager, media_search_manager, len_database)
114
114
  process_search_result(select_title, selections)
115
115
 
116
116
  else:
@@ -1,6 +1,7 @@
1
1
  # 16.03.25
2
2
 
3
3
  import os
4
+ import re
4
5
 
5
6
 
6
7
  # External library
@@ -56,51 +57,30 @@ def download_film(select_title: MediaItem) -> str:
56
57
 
57
58
  start_message()
58
59
  console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n")
59
-
60
- # Extract mostraguarda link
60
+
61
+ # Extract mostraguarda URL
61
62
  try:
62
63
  response = httpx.get(select_title.url, headers=get_headers(), timeout=10)
63
- response.raise_for_status()
64
-
65
- except Exception as e:
66
- console.print(f"[red]Error fetching the page: {e}")
67
-
68
- if site_constant.TELEGRAM_BOT:
69
- bot.send_message(f"ERRORE\n\nErrore durante il recupero della pagina.\n\n{e}", None)
70
- return None
64
+ soup = BeautifulSoup(response.text, 'html.parser')
65
+ iframes = soup.find_all('iframe')
66
+ mostraguarda = iframes[0]['src']
71
67
 
72
- # Create mostraguarda url
73
- soup = BeautifulSoup(response.text, "html.parser")
74
- iframe_tag = soup.find_all("iframe")
75
- url_mostraGuarda = iframe_tag[0].get('data-src')
76
- if not url_mostraGuarda:
77
- console.print("Error: data-src attribute not found in iframe.")
78
- if site_constant.TELEGRAM_BOT:
79
- bot.send_message(f"ERRORE\n\nErrore: attributo data-src non trovato nell'iframe", None)
68
+ except Exception as e:
69
+ console.print(f"[red]Site: {site_constant.SITE_NAME}, request error: {e}, get mostraguarda")
80
70
 
81
71
  # Extract supervideo URL
82
72
  try:
83
- response = httpx.get(url_mostraGuarda, headers=get_headers(), timeout=10)
84
- response.raise_for_status()
73
+ response = httpx.get(mostraguarda, headers=get_headers(), timeout=10)
74
+ soup = BeautifulSoup(response.text, 'html.parser')
75
+ pattern = r'//supervideo\.[^/]+/[a-z]/[a-zA-Z0-9]+'
76
+ supervideo_match = re.search(pattern, response.text)
77
+ supervideo_url = 'https:' + supervideo_match.group(0)
85
78
 
86
79
  except Exception as e:
87
- console.print(f"[red]Error fetching mostraguarda link: {e}")
88
- console.print("[yellow]Missing access credentials. This part of the code is still under development.")
89
- if site_constant.TELEGRAM_BOT:
90
- bot.send_message(f"ERRORE\n\nErrore durante il recupero del link mostra/guarda.\n\n{e}", None)
91
- bot.send_message(f"ERRORE\n\nCredenziali di accesso mancanti.\nQuesta parte del codice è ancora in fase di sviluppo.", None)
92
- return None
93
-
94
- # Create supervio URL
95
- soup = BeautifulSoup(response.text, "html.parser")
96
- player_links = soup.find("ul", class_="_player-mirrors")
97
- player_items = player_links.find_all("li")
98
- supervideo_url = "https:" + player_items[0].get("data-link")
99
- if not supervideo_url:
100
- return None
80
+ console.print(f"[red]Site: {site_constant.SITE_NAME}, request error: {e}, get supervideo URL")
101
81
 
102
82
  # Init class
103
- video_source = VideoSource(url=supervideo_url)
83
+ video_source = VideoSource(supervideo_url)
104
84
  master_playlist = video_source.get_playlist()
105
85
 
106
86
  # Define the filename and path for the downloaded film
@@ -109,7 +109,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
109
109
  bot = get_bot_instance()
110
110
 
111
111
  if len_database > 0:
112
- select_title = get_select_title(table_show_manager, media_search_manager)
112
+ select_title = get_select_title(table_show_manager, media_search_manager,len_database)
113
113
  process_search_result(select_title, selections)
114
114
 
115
115
  else:
@@ -43,40 +43,38 @@ class ScrapeSerieAnime:
43
43
  def get_count_episodes(self):
44
44
  """
45
45
  Retrieve total number of episodes for the selected media.
46
+ This includes partial episodes (like episode 6.5).
46
47
 
47
48
  Returns:
48
- int: Total episode count
49
+ int: Total episode count including partial episodes
49
50
  """
50
- try:
51
-
52
- response = httpx.get(
53
- url=f"{self.url}/info_api/{self.media_id}/",
54
- headers=self.headers,
55
- timeout=max_timeout
56
- )
57
- response.raise_for_status()
58
-
59
- # Parse JSON response and return episode count
60
- return response.json()["episodes_count"]
61
-
62
- except Exception as e:
63
- logging.error(f"Error fetching episode count: {e}")
64
- return None
51
+ if self.episodes_cache is None:
52
+ self._fetch_all_episodes()
53
+
54
+ if self.episodes_cache:
55
+ return len(self.episodes_cache)
56
+ return None
65
57
 
66
58
  def _fetch_all_episodes(self):
67
59
  """
68
60
  Fetch all episodes data at once and cache it
69
61
  """
70
62
  try:
71
- all_episodes = []
72
- count = self.get_count_episodes()
73
- if not count:
74
- return
63
+ # Get initial episode count
64
+ response = httpx.get(
65
+ url=f"{self.url}/info_api/{self.media_id}/",
66
+ headers=self.headers,
67
+ timeout=max_timeout
68
+ )
69
+ response.raise_for_status()
70
+ initial_count = response.json()["episodes_count"]
75
71
 
76
- # Fetch episodes
72
+ all_episodes = []
77
73
  start_range = 1
78
- while start_range <= count:
79
- end_range = min(start_range + 119, count)
74
+
75
+ # Fetch episodes in chunks
76
+ while start_range <= initial_count:
77
+ end_range = min(start_range + 119, initial_count)
80
78
 
81
79
  response = httpx.get(
82
80
  url=f"{self.url}/info_api/{self.media_id}/1",
@@ -75,7 +75,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
75
75
  return media_search_manager
76
76
 
77
77
  if len_database > 0:
78
- select_title = get_select_title(table_show_manager, media_search_manager)
78
+ select_title = get_select_title(table_show_manager, media_search_manager,len_database)
79
79
  process_search_result(select_title, selections)
80
80
 
81
81
  else:
@@ -0,0 +1,72 @@
1
+ # 09.06.24
2
+
3
+ from urllib.parse import quote_plus
4
+
5
+
6
+ # External library
7
+ from rich.console import Console
8
+ from rich.prompt import Prompt
9
+
10
+
11
+ # Internal utilities
12
+ from StreamingCommunity.Api.Template import get_select_title
13
+ from StreamingCommunity.Api.Template.config_loader import site_constant
14
+ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
15
+
16
+
17
+ # Logic class
18
+ from .site import title_search, media_search_manager, table_show_manager
19
+ from .film import download_film
20
+
21
+
22
+ # Variable
23
+ indice = -1
24
+ _useFor = "Film"
25
+ _priority = 0
26
+ _engineDownload = "mp4"
27
+ _deprecate = True
28
+
29
+ msg = Prompt()
30
+ console = Console()
31
+
32
+
33
+ def process_search_result(select_title):
34
+ """
35
+ Handles the search result and initiates the download for either a film or series.
36
+ """
37
+ # !!! ADD TYPE DONT WORK FOR SERIE
38
+ download_film(select_title)
39
+
40
+ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
41
+ """
42
+ Main function of the application for search.
43
+
44
+ Parameters:
45
+ string_to_search (str, optional): String to search for
46
+ get_onylDatabase (bool, optional): If True, return only the database object
47
+ direct_item (dict, optional): Direct item to process (bypass search)
48
+ """
49
+ if direct_item:
50
+ select_title = MediaItem(**direct_item)
51
+ process_search_result(select_title)
52
+ return
53
+
54
+ if string_to_search is None:
55
+ string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
56
+
57
+ # Search on database
58
+ len_database = title_search(quote_plus(string_to_search))
59
+
60
+ ## If only the database is needed, return the manager
61
+ if get_onlyDatabase:
62
+ return media_search_manager
63
+
64
+ if len_database > 0:
65
+ select_title = get_select_title(table_show_manager, media_search_manager,len_database)
66
+ process_search_result(select_title)
67
+
68
+ else:
69
+
70
+ # If no results are found, ask again
71
+ console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
72
+ search()
@@ -0,0 +1,62 @@
1
+ # 03.07.24
2
+
3
+ import os
4
+
5
+
6
+ # External library
7
+ from rich.console import Console
8
+
9
+
10
+ # Internal utilities
11
+ from StreamingCommunity.Util.os import os_manager
12
+ from StreamingCommunity.Util.message import start_message
13
+ from StreamingCommunity.Lib.Downloader import HLS_Downloader
14
+
15
+
16
+ # Logic class
17
+ from StreamingCommunity.Api.Template.config_loader import site_constant
18
+ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
19
+
20
+
21
+ # Player
22
+ from StreamingCommunity.Api.Player.maxstream import VideoSource
23
+
24
+
25
+ # Variable
26
+ console = Console()
27
+
28
+
29
+ def download_film(select_title: MediaItem) -> str:
30
+ """
31
+ Downloads a film using the provided obj.
32
+
33
+ Parameters:
34
+ - select_title (MediaItem): The media item to be downloaded. This should be an instance of the MediaItem class, containing attributes like `name` and `url`.
35
+
36
+ Return:
37
+ - str: output path
38
+ """
39
+ start_message()
40
+ console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n")
41
+
42
+ # Setup api manger
43
+ video_source = VideoSource(select_title.url)
44
+
45
+ # Define output path
46
+ title_name = os_manager.get_sanitize_file(select_title.name) +".mp4"
47
+ mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(".mp4", ""))
48
+
49
+ # Get m3u8 master playlist
50
+ master_playlist = video_source.get_playlist()
51
+
52
+ # Download the film using the m3u8 playlist, and output filename
53
+ r_proc = HLS_Downloader(
54
+ m3u8_url=master_playlist,
55
+ output_path=os.path.join(mp4_path, title_name)
56
+ ).start()
57
+
58
+ if r_proc['error'] is not None:
59
+ try: os.remove(r_proc['path'])
60
+ except: pass
61
+
62
+ return r_proc['path']