Mythus commited on
Commit
5b63e44
·
verified ·
1 Parent(s): 3dda5ff

Upload 42 files

Browse files
Files changed (42) hide show
  1. Dockerfile +15 -0
  2. Dockerfiles/Dockerfile-auto-update +23 -0
  3. Dockerfiles/Dockerfile-auto-update-no-config +21 -0
  4. Src/API/__pycache__/animeworld.cpython-311.pyc +0 -0
  5. Src/API/__pycache__/cool.cpython-311.pyc +0 -0
  6. Src/API/__pycache__/ddlstream.cpython-311.pyc +0 -0
  7. Src/API/__pycache__/epg.cpython-311.pyc +0 -0
  8. Src/API/__pycache__/filmpertutti.cpython-311.pyc +0 -0
  9. Src/API/__pycache__/lordchannel.cpython-311.pyc +0 -0
  10. Src/API/__pycache__/okru.cpython-311.pyc +0 -0
  11. Src/API/__pycache__/streamingcommunity.cpython-311.pyc +0 -0
  12. Src/API/__pycache__/streamingwatch.cpython-311.pyc +0 -0
  13. Src/API/__pycache__/tantifilm.cpython-311.pyc +0 -0
  14. Src/API/__pycache__/webru.cpython-311.pyc +0 -0
  15. Src/API/animeworld.py +163 -0
  16. Src/API/cool.py +146 -0
  17. Src/API/ddlstream.py +137 -0
  18. Src/API/epg.py +225 -0
  19. Src/API/filmpertutti.py +180 -0
  20. Src/API/lordchannel.py +111 -0
  21. Src/API/okru.py +18 -0
  22. Src/API/streamingcommunity.py +259 -0
  23. Src/API/streamingwatch.py +98 -0
  24. Src/API/tantifilm.py +287 -0
  25. Src/API/webru.py +47 -0
  26. Src/Utilities/__pycache__/config.cpython-311.pyc +0 -0
  27. Src/Utilities/__pycache__/convert.cpython-311.pyc +0 -0
  28. Src/Utilities/__pycache__/convert_date.cpython-311.pyc +0 -0
  29. Src/Utilities/__pycache__/dictionaries.cpython-311.pyc +0 -0
  30. Src/Utilities/__pycache__/info.cpython-311.pyc +0 -0
  31. Src/Utilities/__pycache__/loadenv.cpython-311.pyc +0 -0
  32. Src/Utilities/config.py +25 -0
  33. Src/Utilities/convert.py +14 -0
  34. Src/Utilities/convert_date.py +39 -0
  35. Src/Utilities/dictionaries.py +846 -0
  36. Src/Utilities/info.py +160 -0
  37. Src/Utilities/loadenv.py +22 -0
  38. config.json +34 -0
  39. requirements.txt +11 -0
  40. run.py +269 -0
  41. static/__pycache__/static.cpython-311.pyc +0 -0
  42. static/static.py +273 -0
Dockerfile ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use an official Python runtime as a parent image
2
+ FROM python:3.10-slim-buster
3
+ # Set the working directory in the container to /app
4
+ WORKDIR /app
5
+
6
+ # Copy the current directory contents into the container at /app
7
+ # (including run.py, filmpertutti.py, and requirements.txt)
8
+ ADD . /app
9
+ # Install any needed packages specified in requirements.txt
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
+ #EXPOSE the port, for now default is 8080 cause it's the only one really allowed by HuggingFace
12
+ EXPOSE 8080
13
+
14
+ # Run run.py when the container launches
15
+ CMD ["python", "run.py"]
Dockerfiles/Dockerfile-auto-update ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Use an official Python runtime as a parent image
2
+ FROM python:3.10-slim-buster
3
+
4
+ # Set the working directory in the container to /app
5
+ WORKDIR /app
6
+
7
+ # Install git
8
+ RUN apt-get update && apt-get install -y git
9
+
10
+ # Clone the repository
11
+ RUN git clone https://github.com/UrloMythus/MammaMia.git .
12
+
13
+ # Copy the local config.json file to the container
14
+ COPY config.json /app/config.json
15
+
16
+ # Install any needed packages specified in requirements.txt
17
+ RUN pip install --no-cache-dir -r requirements.txt
18
+
19
+ # Expose the port, for now default is 8080 cause it's the only one really allowed by HuggingFace
20
+ EXPOSE 8080
21
+
22
+ # Run run.py when the container launches
23
+ CMD ["python", "run.py"]
Dockerfiles/Dockerfile-auto-update-no-config ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Use an official Python runtime as a parent image
2
+ FROM python:3.10-slim-buster
3
+
4
+ # Set the working directory in the container to /app
5
+ WORKDIR /app
6
+
7
+ # Install git
8
+ RUN apt-get update && apt-get install -y git
9
+
10
+ # Clone the repository
11
+ RUN git clone https://github.com/UrloMythus/MammaMia.git .
12
+
13
+
14
+ # Install any needed packages specified in requirements.txt
15
+ RUN pip install --no-cache-dir -r requirements.txt
16
+
17
+ # Expose the port, for now default is 8080 cause it's the only one really allowed by HuggingFace
18
+ EXPOSE 8080
19
+
20
+ # Run run.py when the container launches
21
+ CMD ["python", "run.py"]
Src/API/__pycache__/animeworld.cpython-311.pyc ADDED
Binary file (8.4 kB). View file
 
Src/API/__pycache__/cool.cpython-311.pyc ADDED
Binary file (6.99 kB). View file
 
Src/API/__pycache__/ddlstream.cpython-311.pyc ADDED
Binary file (7.07 kB). View file
 
Src/API/__pycache__/epg.cpython-311.pyc ADDED
Binary file (8.03 kB). View file
 
Src/API/__pycache__/filmpertutti.cpython-311.pyc ADDED
Binary file (8.05 kB). View file
 
Src/API/__pycache__/lordchannel.cpython-311.pyc ADDED
Binary file (5.32 kB). View file
 
Src/API/__pycache__/okru.cpython-311.pyc ADDED
Binary file (1.35 kB). View file
 
Src/API/__pycache__/streamingcommunity.cpython-311.pyc ADDED
Binary file (13.5 kB). View file
 
Src/API/__pycache__/streamingwatch.cpython-311.pyc ADDED
Binary file (5.9 kB). View file
 
Src/API/__pycache__/tantifilm.cpython-311.pyc ADDED
Binary file (13.4 kB). View file
 
Src/API/__pycache__/webru.cpython-311.pyc ADDED
Binary file (3 kB). View file
 
Src/API/animeworld.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from bs4 import BeautifulSoup
3
+ import datetime
4
+ import json
5
+ from Src.Utilities.info import get_info_kitsu
6
+ import Src.Utilities.config as config
7
+ import re
8
+ AW_DOMAIN = config.AW_DOMAIN
9
+ months = {
10
+ "Gennaio": "January", "Febbraio": "February", "Marzo": "March",
11
+ "Aprile": "April", "Maggio": "May", "Giugno": "June",
12
+ "Luglio": "July", "Agosto": "August", "Settembre": "September",
13
+ "Ottobre": "October", "Novembre": "November", "Dicembre": "December"
14
+ }
15
+ showname_replace = {
16
+ "Attack on Titan": "L'attacco dei Giganti",
17
+ "Season": "",
18
+ " ": " ",
19
+ "Shippuuden": "Shippuden",
20
+ " ": "+",
21
+ }
22
+
23
+ async def get_mp4(anime_url,ismovie,episode,client):
24
+ response = await client.get(anime_url,allow_redirects=True, impersonate = "chrome120")
25
+ soup = BeautifulSoup(response.text,'lxml')
26
+ episode_page = soup.find('a', {'data-episode-num':episode })
27
+ if episode_page is None:
28
+ return None
29
+ episode_page = f'https://animeworld.{AW_DOMAIN}{episode_page["href"]}'
30
+ response = await client.get(episode_page,allow_redirects=True, impersonate = "chrome120")
31
+ soup = BeautifulSoup(response.text,'lxml')
32
+ a_tag = soup.find('a', {'id': 'alternativeDownloadLink', 'class': 'm-1 btn btn-sm btn-primary'})
33
+ url = a_tag['href']
34
+ response = await client.head(url)
35
+ if response.status_code == 404:
36
+ url = None
37
+ return url
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+ async def old_search(showname,date,ismovie,episode,client):
46
+ cookies = {
47
+ 'sessionId': 's%3AtGSRfYcsIoaeV0nqFJgN69Zxixb_-uJU.fcNz%2FsJBiiP8v8TwthMN9%2FmynWFciI5gezZuz8CltyQ',
48
+ }
49
+
50
+ headers = {
51
+ 'authority': f'www.animeworld.{AW_DOMAIN}',
52
+ 'accept': 'application/json, text/javascript, */*; q=0.01',
53
+ 'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
54
+ # 'content-length': '0',
55
+ # 'cookie': 'sessionId=s%3AtGSRfYcsIoaeV0nqFJgN69Zxixb_-uJU.fcNz%2FsJBiiP8v8TwthMN9%2FmynWFciI5gezZuz8CltyQ',
56
+ 'csrf-token': 'oKFK43s4-BzfqPX27RlAORUd-iyiAfXyfDAo',
57
+ 'origin': f'https://www.animeworld.{AW_DOMAIN}',
58
+ 'referer': f'https://www.animeworld.{AW_DOMAIN}/',
59
+ 'sec-ch-ua': '"Not-A.Brand";v="99", "Chromium";v="124"',
60
+ 'sec-ch-ua-mobile': '?0',
61
+ 'sec-ch-ua-platform': '"Android"',
62
+ 'sec-fetch-dest': 'empty',
63
+ 'sec-fetch-mode': 'cors',
64
+ 'sec-fetch-site': 'same-origin',
65
+ 'user-agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
66
+ 'x-requested-with': 'XMLHttpRequest',
67
+ }
68
+
69
+ params = {
70
+ 'keyword': showname,
71
+ }
72
+
73
+ response = await client.post(f'https://www.animeworld.{AW_DOMAIN}/api/search/v2', params=params, cookies=cookies, headers=headers,allow_redirects=True, impersonate = "chrome120")
74
+
75
+ data = json.loads(response.text)
76
+ final_urls = []
77
+ for anime in data["animes"]:
78
+ release_date = anime["release"]
79
+ for ita, eng in months.items():
80
+ release_date = release_date.replace(ita, eng)
81
+ release_date = datetime.datetime.strptime(release_date, "%d %B %Y")
82
+ release_date = release_date.strftime("%Y-%m-%d")
83
+ if release_date == date:
84
+ identifier = anime["identifier"]
85
+ link = anime["link"]
86
+ anime_url = f'https://animeworld.{AW_DOMAIN}/play/{link}.{identifier}'
87
+ final_url = await get_mp4(anime_url,ismovie,episode,client)
88
+ final_urls.append(final_url)
89
+ break
90
+ showname = showname + " (ITA)"
91
+ params = {
92
+ 'keyword': showname,
93
+ }
94
+ response = await client.post(f'https://www.animeworld.{AW_DOMAIN}/api/search/v2', params=params, cookies=cookies, headers=headers, allow_redirects=True, impersonate = "chrome120")
95
+ data = json.loads(response.text)
96
+ for anime in data["animes"]:
97
+ release_date = anime["release"]
98
+ for ita, eng in months.items():
99
+ release_date = release_date.replace(ita, eng)
100
+ release_date = datetime.datetime.strptime(release_date, "%d %B %Y")
101
+ release_date = release_date.strftime("%Y-%m-%d")
102
+ if release_date == date:
103
+ identifier = anime["identifier"]
104
+ link = anime["link"]
105
+ anime_url = f'https://animeworld.{AW_DOMAIN}/play/{link}.{identifier}'
106
+ final_url = await get_mp4(anime_url,ismovie,episode,client)
107
+ final_urls.append(final_url)
108
+ break
109
+ return final_urls
110
+
111
+ async def search(showname,date,ismovie,episode,client):
112
+ search_year = date[:4]
113
+ response = await client.get(f'https://www.animeworld.so/filter?year={search_year}&sort=2&keyword={showname}',allow_redirects=True, impersonate = "chrome120")
114
+ soup = BeautifulSoup(response.text,'lxml')
115
+ anime_list = soup.find_all('a', class_=['poster', 'tooltipstered'])
116
+ final_urls = []
117
+ for anime in anime_list:
118
+ anime_info_url = f'https://www.animeworld.{AW_DOMAIN}/{anime["data-tip"]}'
119
+ response = await client.get(anime_info_url,allow_redirects=True, impersonate = "chrome120")
120
+ pattern = r'<label>Data di uscita:</label>\s*<span>\s*(.*?)\s*</span>'
121
+ match = re.search(pattern, response.text, re.S)
122
+ release_date = match.group(1).strip()
123
+ for ita, eng in months.items():
124
+ release_date = release_date.replace(ita, eng)
125
+ release_date = datetime.datetime.strptime(release_date, "%d %B %Y")
126
+ release_date = release_date.strftime("%Y-%m-%d")
127
+ if release_date == date:
128
+ anime_url = f'https://www.animeworld.{AW_DOMAIN}{anime["href"]}'
129
+ final_url = await get_mp4(anime_url,ismovie,episode,client)
130
+ if final_url:
131
+ final_urls.append(final_url)
132
+
133
+ return final_urls
134
+
135
+ async def animeworld(id,client):
136
+ try:
137
+ print(id)
138
+ kitsu_id = id.split(":")[1]
139
+ episode = id.split(":")[2]
140
+ ismovie = 1 if len(id.split(":")) == 2 else 0
141
+ showname,date = await get_info_kitsu(kitsu_id,client)
142
+ for key in showname_replace:
143
+ if key in showname: # Check if the key is a substring of showname
144
+ showname = showname.replace(key, showname_replace[key])
145
+ if "Naruto:" in showname:
146
+ showname = showname.replace(":", "")
147
+ final_urls = await search(showname,date,ismovie,episode,client)
148
+ return final_urls
149
+ except:
150
+ print("Animeworld failed")
151
+ return None
152
+
153
+ #async def test_animeworld():
154
+ async with httpx.AsyncClient() as client:
155
+ # Replace with actual id, for example 'anime_id:episode' format
156
+ test_id = "kitsu:1555:1" # This is an example ID format
157
+ results = await animeworld(test_id, client)
158
+ print(results)
159
+
160
+ #if __name__ == "__main__":
161
+ import httpx
162
+ import asyncio
163
+ asyncio.run(test_animeworld())
Src/API/cool.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from Src.Utilities.info import get_info_tmdb,is_movie
3
+ from Src.Utilities.convert import get_TMDb_id_from_IMDb_id
4
+ from Src.Utilities.loadenv import load_env
5
+ env_vars = load_env()
6
+ MYSTERIUS_KEY = env_vars.get('MYSTERIUS_KEY')
7
+ async def get_links(slug,season,episode,ismovie,client):
8
+ try:
9
+ headers = {
10
+ "x-api-key": MYSTERIUS_KEY
11
+ }
12
+ response = await client.get("https://mammamia-urlo-ulala12431.hf.space/api/cookie", headers=headers)
13
+ Auths = response.json()
14
+ Bearer = Auths.get('cookie')
15
+ ap_session = Auths.get('auth')
16
+
17
+ cookies = {'ap_session': ap_session}
18
+
19
+ headers = {
20
+ 'accept': 'application/json, text/plain, */*',
21
+ 'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
22
+ 'authorization': f'Bearer {Bearer}',
23
+ 'referer': f'https://altadefinizione-originale.com/play/{slug}',
24
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 OPR/111.0.0.0',
25
+ 'x-requested-with': 'XMLHttpRequest',
26
+ }
27
+ if ismovie == 1:
28
+
29
+ response = await client.get(f'https://altadefinizione-originale.com/api/post/urls/stream/{slug}',cookies=cookies,headers=headers)
30
+ elif ismovie == 0:
31
+ print("HERE SEASON",season)
32
+ print("HERE EPISODE",episode)
33
+ request_url =f'https://altadefinizione-originale.com/api/post/urls/stream/{slug}/{season}/{episode}'
34
+ print(request_url)
35
+ response = await client.get(request_url,cookies=cookies,headers=headers)
36
+ try:
37
+ video_data = response.json() # Assuming this is the JSON response containing video streams
38
+ if 'streams' not in video_data:
39
+ print("Invalid JSON format: 'streams' key not found or incorrect structure")
40
+ return None
41
+
42
+ streams = video_data['streams']
43
+
44
+ resolutions = {}
45
+
46
+ for stream in streams:
47
+ resolution_name = stream['resolution']['name'].lower() # Convert resolution name to lowercase
48
+ url = stream['url']
49
+
50
+ # Remove everything after '.mp4' in the URL
51
+ mp4_index = url.find('.mp4')
52
+ if mp4_index != -1:
53
+ url = url[:mp4_index + 4] # +4 to include '.mp4' in the substring
54
+
55
+ resolutions[resolution_name] = url
56
+
57
+ return resolutions
58
+
59
+ except KeyError as e:
60
+ print(f"KeyError: {e}")
61
+ return None
62
+ except json.JSONDecodeError as e:
63
+ print(f"JSONDecodeError: {e}")
64
+ return None
65
+
66
+ except client.RequestException as e:
67
+ print(f"Request error: {e}")
68
+ return None
69
+
70
+
71
+ # Example usage: Fetch video links
72
+
73
+
74
+ # Print the dictionary
75
+
76
+
77
+
78
+
79
+
80
+ async def search_imdb(showname,tmdba,client):
81
+ showname = showname.replace(" ","%20")
82
+ tmdba = str(tmdba)
83
+ query = f'https://altadefinizione-originale.com/api/search?search={showname}&page=1'
84
+ response = await client.get(query,allow_redirects=True, impersonate = "chrome120")
85
+ if response.status_code == 200:
86
+ data = response.json()
87
+ if 'data' in data:
88
+ for item in data['data']:
89
+ tmdb_id = item.get('tmdb_id')
90
+ tmdb_id = ''.join(char for char in tmdb_id if char.isdigit())
91
+ if tmdb_id == tmdba:
92
+ slug = item.get('slug')
93
+ print(slug)
94
+ return slug
95
+
96
+
97
+
98
+ def parse_links(resolution_links):
99
+ results = {}
100
+ if resolution_links:
101
+ print("Video links:")
102
+ for resolution, link in resolution_links.items():
103
+ if "cdn.altadefinizione-originale.com" in link:
104
+ link = link.replace("cdn.altadefinizione-originale.com","protectlinknt.b-cdn.net")
105
+ print(f"{resolution}: {link}")
106
+ results[resolution] = link
107
+ return results
108
+ else:
109
+ print("Failed to fetch video links")
110
+
111
+
112
+ async def cool(imdb,client):
113
+ try:
114
+ type = "Cool"
115
+ general = is_movie(imdb)
116
+ ismovie = general[0]
117
+ imdb_id = general[1]
118
+ if ismovie == 0 :
119
+ season = int(general[2])
120
+ episode = int(general[3])
121
+
122
+ if "tt" in imdb:
123
+ #Get showname
124
+ tmdba = await get_TMDb_id_from_IMDb_id(imdb_id,client)
125
+ else:
126
+ tmdba = imdb_id.replace("tmdb:","")
127
+
128
+ showname = get_info_tmdb(tmdba,ismovie,type)
129
+
130
+
131
+ slug = await search_imdb(showname,tmdba,client)
132
+ if ismovie == 1:
133
+ season = None
134
+ episode = None
135
+ resolution_links = await get_links(slug,episode,season,ismovie,client)
136
+ results = parse_links(resolution_links)
137
+ return results
138
+ elif ismovie == 0:
139
+ season = season -1
140
+ episode = episode - 1
141
+ resolution_links = await get_links(slug,season,episode,ismovie,client)
142
+ results = parse_links(resolution_links)
143
+ return results
144
+ except Exception as e:
145
+ print("Cool Error",e)
146
+ return None
Src/API/ddlstream.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import re
3
+ from bs4 import BeautifulSoup, SoupStrainer
4
+ from Src.Utilities.info import get_info_imdb, is_movie, get_info_tmdb
5
+
6
+ Cookies = {
7
+ "ips4_member_id": "4029329",
8
+ "ips4_device_key": "b6f084be79c28bb53ecfc556fd7a2a70",
9
+ "ips4_login_key": "1725525639",
10
+ "ips4_IPSSessionFront": "1fe0cb08a08c5689a9ac93b94faf769e",
11
+ }
12
+
13
+ async def search_series(client,id,season,episode):
14
+ season = 5
15
+ response = await client.get("https://ddlstreamitaly.co/search/?&q=La%20casa%20di%20carta%203%20Streaming&type=videobox_video&quick=1&nodes=11&search_and_or=and&search_in=titles&sortby=relevancy")
16
+ soup = BeautifulSoup(response.text, 'lxml',parse_only=SoupStrainer('a'))
17
+ a_tags = soup.find_all('a', {'data-linktype': 'link'})
18
+ for a in a_tags:
19
+ href = a['href']
20
+ response = await client.get(href, cookies = Cookies)
21
+ soup = BeautifulSoup(response.text, 'lxml')
22
+ movie_ids = soup.find_all('a',{'rel':'external nofollow'})
23
+ for database in movie_ids:
24
+ link = database['href']
25
+ real_id = link.split('/')[4]
26
+ if real_id == id:
27
+ meta_description = soup.find('meta',{'name':'description'})
28
+ content = meta_description['content']
29
+ if f"Stagione {season}" in content:
30
+ return href
31
+ else:
32
+ continue
33
+ else:
34
+ continue
35
+
36
+ async def get_episode(client,link,episode):
37
+ Cookies = {
38
+ "ips4_member_id": "4029329",
39
+ "ips4_device_key": "b6f084be79c28bb53ecfc556fd7a2a70",
40
+ "ips4_login_key": "1725525639",
41
+ "ips4_IPSSessionFront": "1fe0cb08a08c5689a9ac93b94faf769e"
42
+ }
43
+ episode = "6"
44
+ link = link + "?area=online"
45
+ response = await client.get(link, cookies = Cookies,impersonate="chrome120")
46
+ pattern = rf'<a\s+href="([^"]+)"[^>]*>\s*(Part\s+{episode})\s*</a>'
47
+ match = re.search(pattern, response.text)
48
+ mp4_link = match.group(1)
49
+ mp4_link = mp4_link.replace("&amp","")
50
+ mp4_link = mp4_link.replace(";","&")
51
+ return mp4_link
52
+
53
+ async def search_movie():
54
+ link = "https://ddlstreamitaly.co/search/?&q=%20Noi%2C%20i%20ragazzi%20dello%20zoo%20di%20Berlino%20Streaming&type=videobox_video&quick=1&nodes=11&search_and_or=and&sortby=relevancy"
55
+ response = requests.get(link,impersonate = "chrome120")
56
+ soup = BeautifulSoup(response.text, 'lxml',parse_only=SoupStrainer('a'))
57
+ a_tags = soup.find_all('a', {'data-linktype': 'link'})
58
+ for a in a_tags:
59
+ href = a['href']
60
+ response = requests.get(href, cookies = Cookies)
61
+ soup = BeautifulSoup(response.text, 'lxml', parse_only=SoupStrainer('a'))
62
+ movie_ids = soup.find_all('a',{'rel':'external nofollow'})
63
+ for database in movie_ids:
64
+ link = database['href']
65
+ real_id = link.split('/')[4]
66
+ if real_id == id:
67
+ return href
68
+ else:
69
+ continue
70
+ return
71
+
72
+
73
+
74
+ async def get_mp4(client,link):
75
+ response = await client.get(link, cookies = Cookies)
76
+ soup = BeautifulSoup(response.text,'lxml',parse_only=SoupStrainer('source'))
77
+ source_tag = soup.find('source')
78
+ final_url = source_tag['src']
79
+ res = source_tag.get('res')
80
+ return final_url,res
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+ async def ddlstream(imdb,client):
96
+ try:
97
+ general = is_movie(imdb)
98
+ ismovie = general[0]
99
+ id = general[1]
100
+ type = "DDLStream"
101
+ if "tt" in imdb:
102
+ showname = await get_info_imdb(id,ismovie,type,client)
103
+ print(showname)
104
+ else:
105
+ showname = get_info_tmdb(id,ismovie,type)
106
+ if ismovie == 0:
107
+ season = general[2]
108
+ episode = general[3]
109
+ page_link = await search_series(client,id,season,episode)
110
+ mp4_link = await get_episode(client,page_link,episode)
111
+ final_url = await get_mp4(client,mp4_link)
112
+ print(final_url)
113
+ else:
114
+ page_link = await search_movie()
115
+ mp4_link = page_link + "?area=online"
116
+ final_url = await get_mp4(client,mp4_link)
117
+ print(final_url)
118
+
119
+ except Exception as e:
120
+ print(f"MammaMia: DDLStream Failed {e}")
121
+ return None,None
122
+
123
+ '''
124
+ async def test_animeworld():
125
+ from curl_cffi.requests import AsyncSession
126
+ async with AsyncSession() as client:
127
+ test_id = "tt6468322:5:1" # This is an example ID format
128
+ results = await ddlstream(test_id, client)
129
+ print(results)
130
+
131
+ if __name__ == "__main__":
132
+ import asyncio
133
+ asyncio.run(test_animeworld())
134
+
135
+
136
+ #python3 -m Src.API.ddlstream
137
+ '''
Src/API/epg.py ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from bs4 import BeautifulSoup
2
+
3
+ tivu = {
4
+ "dazn-zona-a": "801",
5
+ }
6
+ """
7
+ "rai-1": "3401",
8
+ "rai-2": "3402",
9
+ "rai-3": "3403",
10
+ "rete-4": "123",
11
+ "canale-5": "122",
12
+ "italia-1": "121",
13
+ "la7": "79",
14
+ "tv8": "7260",
15
+ "nove": "4323",
16
+ "rai-4": "3405",
17
+ "rai-movie": "3406",
18
+ "rai-premium": "8522",
19
+ "mediaset-extra": "129",
20
+ "cielo": "4120",
21
+ "rai-sport": "17714",
22
+ "rai-news": "17711",
23
+ "dmax": "15202",
24
+ "real-time": "15201",
25
+ "focus": "134",
26
+ "giallo": "4322",
27
+ "topcrime": "132",
28
+ "boing": "126",
29
+ "cartoonito": "133",
30
+ "k2": "15204",
31
+ "foodnetwork": "15203",
32
+ "hgtv": "4334",
33
+ "solocalcio": "4996" ,
34
+ "euronews": "2017",
35
+ "rai-4k": "3407",
36
+ """
37
+ convert_bho_1 = {
38
+ "euronews": "PlutoEuronews.it",
39
+ "cartoonito": "cartoonito",
40
+ "sky-tg-24": "skytg24",
41
+ "frisbee": "frisbee",
42
+ "hgtv": "hgtv",
43
+ "k2": "k2",
44
+ "supertennis": "supertennis",
45
+ "solocalcio": "sportitaliasolocalcio",
46
+ "sportitalia": "sportitalia",
47
+ "sportitalia24": "RakutenSportItalia.it",
48
+ "rsi-la-2": "rsila2",
49
+ "baby-shark-tv": "RakutenBabySharkTv.it",
50
+ "adrenaline-movies": "RakutenFullMoon.it",
51
+ "adrenaline-movies": "RakutenBizzarroMovies.it",
52
+ "cinema-italiano": "RakutenCinemaItalianoRakutenTv.it",
53
+ "le-vite-degli-altri": "RakutenLeViteDegliAltri.it",
54
+ "dark-matter": "RakutenDarkMatterItNew.it",
55
+ "cine-western": "RakutenWesternEPeplum.it",
56
+ "serie-crime": "RakutenCrimeSeriesItRakutenTv.it",
57
+ "filmrise-sci-fi": "RakutenFuelTvNew.it",
58
+ "doctor-who": "RakutenBbcDoctorWho.it",
59
+ "bbc-drama": "RakutenBbcDrama.it",
60
+ "documentari": "RakutenDocumentaries.it",
61
+ "house-of-docs": "RakutenHouseOfDocs.it",
62
+ "the-asylum": "PlutoTheAsylum.it",
63
+ "western": "PlutoTvWestern.it",
64
+ "consulenze-illegali": "PlutoConsulenzeIllegaliItPlus.it"
65
+
66
+ }
67
+
68
+
69
+ convert_bho_2 = {
70
+ "rai-1": "Rai%201",
71
+ "rai-2": "Rai 2",
72
+ "rai-3": "Rai 3",
73
+ "rai-4": "Rai 4",
74
+ "rai-premium": "Rai Premium",
75
+ "rai-movie": "Rai Movie",
76
+ "rai-sport": "Rai Sport",
77
+ "rete-4": "Rete 4",
78
+ "canale-5": "Canale 5",
79
+ "italia-1": "Italia 1",
80
+ "topcrime": "Top Crime",
81
+ "mediaset-extra": "Mediaset Extra",
82
+ "focus": "Focus",
83
+ "boing": "Boing",
84
+ "history": "History",
85
+ "comedy-central": "Comedy Central",
86
+ "tv8": "TV 8",
87
+ "cielo": "Cielo",
88
+ "sky-cinema-action": "Sky Cinema Action",
89
+ "sky-arte": "Sky Arte FHD",
90
+ "sky-atlantic": "Sky Atlantic",
91
+ "sky-cinema-collection": "Sky Cinema Collection",
92
+ "sky-cinema-comedy": "Sky Cinema Comedy",
93
+ "sky-cinema-drama": "Sky Cinema Drama",
94
+ "sky-cinema-due": "Sky Cinema Due",
95
+ "sky-cinema-family": "Sky Cinema Family",
96
+ "sky-cinema-romance": "Sky Cinema Romance",
97
+ "sky-cinema-suspence": "Sky Cinema Suspence",
98
+ "sky-cinema-uno": "Sky Cinema Uno",
99
+ "sky-uno": "Sky Uno",
100
+ "sky-sport-24": "Sky Sport",
101
+ "sky-sport-uno": "Sky Sport Uno",
102
+ "sky-sport-f1": "Sky Sport F1",
103
+ "sky-sport-motogp": "Sky Sport MotoGP",
104
+ "sky-sport-arena": "Sky Sport Arena",
105
+ "sky-sport-nba": "Sky Sport NBA",
106
+ "eurosport-1": "Eurosport 1",
107
+ "eurosport-2": "Eurosport 2",
108
+ "dmax": "Dmax",
109
+ "foodnetwork": "Food Network",
110
+ "giallo": "Giallo",
111
+ "nove": "Nove",
112
+ "realtime": "Real Time",
113
+ }
114
+ convert_bho_3 = {
115
+ "la7": "La7",
116
+ "rai-news": "Rai News DTT",
117
+ "sky-crime": "Sky CrimeInvestigation",
118
+ "sky-documentaries": "Sky Documentaries HD",
119
+ "sky-investigation": "Sky Investigation HD",
120
+ "sky-nature": "Sky Nature HD",
121
+ "sky-serie": "Sky Serie HD",
122
+ "sky-sport-golf": "Sky Sport Golf",
123
+ "sky-sport-251": "Sky Sport 251 HD",
124
+ "sky-sport-252": "Sky Sport 252 HD",
125
+ "sky-sport-253": "Sky Sport 253 HD",
126
+ "sky-sport-254": "Sky Sport 254 HD",
127
+ "sky-sport-255": "Sky Sport 255 HD",
128
+ "sky-sport-256": "Sky Sport 256 HD",
129
+ "sky-sport-257": "Sky Sport 257 HD",
130
+ "sky-sport-258": "Sky Sport 258 HD",
131
+ "sky-sport-259": "Sky Sport 259 HD",
132
+ "sky-sport-260": "Sky Sport 260 HD",
133
+ "sky-sport-261": "Sky Sport 261 HD",
134
+ "sky-sport-max": "Sky Sport Max",
135
+ "sky-sport-calcio": "Sky Sport Calcio HD",
136
+ "sky-sport-tennis": "Sky Sport Tennis HD",
137
+ }
138
+
139
+
140
+ async def tivu_get(id,client):
141
+ try:
142
+ cookies = {
143
+ 'ASP.NET_SessionId': 'p2fk5silp5mjgtx0j5chjrh3',
144
+ }
145
+ ik = tivu[id]
146
+ headers = {
147
+ 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0',
148
+ 'Accept': '*/*',
149
+ 'Accept-Language': 'en-US,en;q=0.5',
150
+ # 'Accept-Encoding': 'gzip, deflate, br, zstd',
151
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
152
+ 'X-Requested-With': 'XMLHttpRequest',
153
+ 'Origin': 'https://www.tivu.tv',
154
+ 'DNT': '1',
155
+ 'Sec-GPC': '1',
156
+ 'Connection': 'keep-alive',
157
+ 'Referer': 'https://www.tivu.tv/schedasat-rai1.html',
158
+ # 'Cookie': 'ASP.NET_SessionId=p2fk5silp5mjgtx0j5chjrh3',
159
+ 'Sec-Fetch-Dest': 'empty',
160
+ 'Sec-Fetch-Mode': 'cors',
161
+ 'Sec-Fetch-Site': 'same-origin',
162
+ 'Pragma': 'no-cache',
163
+ 'Cache-Control': 'no-cache',
164
+ }
165
+
166
+ data = {
167
+ 'ik': ik
168
+ }
169
+ response = await client.post('https://www.tivu.tv/getPrograms.ashx', cookies=cookies, headers=headers, data=data)
170
+ soup = BeautifulSoup(response.text,'lxml')
171
+ tr_element = soup.find('tr', class_='in_onda')
172
+ hour_range = tr_element.find_all('td')[0].text.strip()
173
+ program_name = tr_element.find_all('td')[1].text.strip()
174
+ description = hour_range + " " + program_name
175
+ return description
176
+ except Exception as e:
177
+ print(e)
178
+ description = f'Watch {id}'
179
+ return description
180
+
181
+
182
+
183
+ async def epg_guide(id,client):
184
+ try:
185
+ if id in convert_bho_1:
186
+ new_id = convert_bho_1[id]
187
+ new_id = new_id.replace(" ","%20")
188
+ response = await client.get(f"https://lorempizza-boh.hf.space/{new_id}/now")
189
+ elif id in convert_bho_2:
190
+ new_id = convert_bho_2[id]
191
+ new_id = new_id.replace(" ","%20")
192
+ response = await client.get(f"https://mammamia-urlo-boh2.hf.space/{new_id}/now")
193
+ elif id in convert_bho_3:
194
+ new_id = convert_bho_3[id]
195
+ new_id = new_id.replace(" ","%20")
196
+ response = await client.get(f"https://mammamia-urlo-boh3.hf.space/{new_id}/now")
197
+ data = response.json()
198
+ description = data['description'].replace("- EPG by epg-guide.com","").replace("No description","")
199
+ title = data['title']
200
+ print("MammaMia: EPG FOUND")
201
+ return description,title
202
+ except Exception as e:
203
+ print(e)
204
+ description = f'Watch {id}'
205
+ title = ""
206
+ return description,title
207
+
208
+
209
+
210
+
211
+ #async def test_animeworld():
212
+ async with httpx.AsyncClient() as client:
213
+ test_id = "rai-news" # Replace with actual ID
214
+ try:
215
+ results = await epg_guide(test_id, client)
216
+ print(results)
217
+ except httpx.HTTPStatusError as e:
218
+ print(f"HTTP error occurred: {e}")
219
+ except Exception as e:
220
+ print(f"An error occurred: {e}")
221
+
222
+ #if __name__ == "__main__":
223
+ import httpx
224
+ import asyncio
225
+ asyncio.run(test_animeworld())
Src/API/filmpertutti.py ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from tmdbv3api import TMDb, Movie, TV
3
+ from bs4 import BeautifulSoup,SoupStrainer
4
+ import string
5
+ import re
6
+ import dateparser
7
+ from Src.Utilities.convert import get_TMDb_id_from_IMDb_id
8
+ from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
9
+ from Src.Utilities.convert_date import convert_US_date
10
+ import Src.Utilities.config as config
11
+ FT_DOMAIN = config.FT_DOMAIN
12
+ WOA = 0
13
+ #Some basic headers
14
+ headers = {
15
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.10; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
16
+ 'Accept-Language': 'en-US,en;q=0.5'
17
+ }
18
+ #Map months to check if date = date
19
+ month_mapping = {
20
+ 'Jan': 'Gennaio', 'Feb': 'Febbraio', 'Mar': 'Marzo', 'Apr': 'Aprile',
21
+ 'May': 'Maggio', 'Jun': 'Giugno', 'Jul': 'Luglio', 'Aug': 'Agosto',
22
+ 'Sep': 'Settembre', 'Oct': 'Ottobre', 'Nov': 'Novembre', 'Dec': 'Dicembre'
23
+ }
24
+
25
+ async def search(query,date,client,season,ismovie):
26
+ response = await client.get(query)
27
+ response = response.json()
28
+ #Get link tid of every item and then open the link to see if the date = date
29
+ for json in response:
30
+ link = json['link']
31
+ tid = json['id']
32
+ series_response = await client.get(link, headers=headers, allow_redirects=True, timeout = 30)
33
+ series_soup = BeautifulSoup(series_response.text, 'lxml')
34
+ release_span = series_soup.find('span', class_='released')
35
+ if release_span:
36
+ if release_span.text != "Data di uscita: N/A":
37
+ date_string = release_span.text.split(': ')[-1] # Get the date part
38
+ release_date = date_string[-4:]
39
+ if WOA:
40
+ for eng, ita in month_mapping.items():
41
+ date_string = re.sub(rf'\b{eng}\b', ita, date_string)
42
+
43
+ # Swap to YY-MM-DD formatting using dateparser
44
+ release_date = dateparser.parse(date_string, languages=['it']).strftime("%Y-%m-%d")
45
+ if release_date == date:
46
+ url = link
47
+ tid = tid
48
+ if ismovie == 0:
49
+ Seasons = series_soup.find_all('span', class_="season-name")
50
+ i = 0
51
+ for item in Seasons:
52
+ season_text = item.text.strip()
53
+ if season in season_text and "SUB" not in season_text:
54
+ actual_season = i
55
+ return url, tid, actual_season
56
+ else:
57
+ i = i + 1
58
+ continue
59
+ else:
60
+ actual_season = None
61
+ return url, tid, actual_season
62
+ else:
63
+ print("")
64
+
65
+ def get_episode_link(actual_season,episode,tid,url):
66
+ #Get the link from where we have to obtain mixdrop link
67
+ tlink = f'{url}?show_video=true&post_id={tid}&season_id={actual_season}&episode_id={episode-1}'
68
+ return tlink
69
+
70
+
71
+ def get_film(url):
72
+ #Get the link from where we have to obtain mixdrop link
73
+ tlink = url + "?show_video=true"
74
+ return tlink
75
+
76
+ async def get_real_link(tlink,client):
77
+ #Some basic code to get the mixdrop link
78
+ page = await client.get(tlink, headers=headers, allow_redirects=True)
79
+ soup = BeautifulSoup(page.content, features="lxml",parse_only=SoupStrainer('iframe'))
80
+ iframe_src = soup.find('iframe')['src']
81
+ iframe_page = await client.get(iframe_src, headers=headers, allow_redirects=True, timeout = 30)
82
+ iframe_soup = BeautifulSoup(iframe_page.content, features="lxml")
83
+
84
+ mega_button = iframe_soup.find('div', attrs={'class': 'megaButton', 'rel': 'nofollow'}, string='MIXDROP')
85
+ if mega_button:
86
+ real_link = mega_button.get('meta-link')
87
+ return real_link
88
+
89
+ async def get_true_link(real_link,client):
90
+ response = await client.get(real_link, headers=headers, allow_redirects=True,timeout = 30)
91
+ [s1, s2] = re.search(r"\}\('(.+)',.+,'(.+)'\.split", response.text).group(1, 2)
92
+ schema = s1.split(";")[2][5:-1]
93
+ terms = s2.split("|")
94
+ charset = string.digits + string.ascii_letters
95
+ d = dict()
96
+ for i in range(len(terms)):
97
+ d[charset[i]] = terms[i] or charset[i]
98
+ s = 'https:'
99
+ for c in schema:
100
+ s += d[c] if c in d else c
101
+ return s
102
+
103
+ async def filmpertutti(imdb,client):
104
+ general = is_movie(imdb)
105
+ ismovie = general[0]
106
+ imdb_id = general[1]
107
+ type = "Filmpertutti"
108
+ if ismovie == 0 :
109
+ season = general[2]
110
+ episode = int(general[3])
111
+ if "tt" in imdb:
112
+ if ismovie == 0:
113
+ #Get showname and date
114
+ showname,date = await get_info_imdb(imdb_id,ismovie,type,client)
115
+ else:
116
+ #THIS IS needed cause the only way to get all releases dates is by giving a tmdb ID not a IMDB
117
+ showname,date = await get_info_imdb(imdb_id,ismovie,type, client)
118
+ season = None
119
+
120
+ elif "tmdb" in imdb:
121
+ #Get showname and date
122
+ tmdba = imdb_id.replace("tmdb:","")
123
+ showname,date = get_info_tmdb(tmdba,ismovie,type)
124
+ showname = showname.replace(" ", "+").replace("–", "+").replace("—","+")
125
+ #Build the query
126
+ query = f'https://filmpertutti.{FT_DOMAIN}/wp-json/wp/v2/posts?search={showname}&page=1&_fields=link,id'
127
+ try:
128
+ url,tid,actual_season = await search(query,date,client,season,ismovie)
129
+ except:
130
+ print("MammaMia: No results found for Filmpertutti")
131
+ return None
132
+ if ismovie == 0:
133
+ episode_link = get_episode_link(actual_season,episode,tid,url)
134
+ #Let's get mixdrop link
135
+ real_link = await get_real_link(episode_link,client)
136
+ #let's get delivery link, streaming link
137
+ streaming_link = await get_true_link(real_link,client)
138
+ return streaming_link
139
+ elif ismovie == 1:
140
+ film_link = get_film(url)
141
+ #Let's get mixdrop link
142
+ real_link = await get_real_link(film_link,client)
143
+ #let's get delivery link, streaming link
144
+ streaming_link = await get_true_link(real_link,client)
145
+ return streaming_link
146
+
147
+
148
+ '''
149
+ async def test_animeworld():
150
+ from curl_cffi.requests import AsyncSession
151
+ async with AsyncSession() as client:
152
+ # Replace with actual id, for example 'anime_id:episode' format
153
+ test_id = "tt4655480:1:1" # This is an example ID format
154
+ results = await filmpertutti(test_id, client)
155
+
156
+ if __name__ == "__main__":
157
+ import asyncio
158
+ asyncio.run(test_animeworld())
159
+ '''
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+ '''
169
+ series_response = await client.get(link, headers=headers, follow_redirects=True)
170
+ series_soup = BeautifulSoup(series_response.text, 'lxml')
171
+ release_span = series_soup.find('span', class_='released')
172
+ if release_span:
173
+ if release_span.text != "Data di uscita: N/A":
174
+ date_string = release_span.text.split(': ')[-1] # Get the date part
175
+ for eng, ita in month_mapping.items():
176
+ date_string = re.sub(rf'\b{eng}\b', ita, date_string)
177
+
178
+ # Swap to YY-MM-DD formatting using dateparser
179
+ release_date = dateparser.parse(date_string, languages=['it']).strftime("%Y-%m-%d")
180
+ '''
Src/API/lordchannel.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from tmdbv3api import TMDb, Movie, TV
2
+ from bs4 import BeautifulSoup,SoupStrainer
3
+ from Src.Utilities.convert import get_TMDb_id_from_IMDb_id
4
+ from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
5
+ import Src.Utilities.config as config
6
+ import re
7
+ import json
8
+ LC_DOMAIN = config.LC_DOMAIN
9
+ async def search(showname,date,season,episode,ismovie,client):
10
+ cookies = {
11
+ 'csrftoken': '7lvc502CZe8Zbx7iSX1xkZOBA1NbDxJZ',
12
+ }
13
+
14
+ headers = {
15
+ 'authority': f'lordchannel.{LC_DOMAIN}',
16
+ 'accept': '*/*',
17
+ 'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
18
+ # 'cookie': 'csrftoken=7lvc502CZe8Zbx7iSX1xkZOBA1NbDxJZ',
19
+ 'referer': f'https://lordchannel.{LC_DOMAIN}/anime/anime-ita/',
20
+ 'sec-ch-ua': '"Not-A.Brand";v="99", "Chromium";v="124"',
21
+ 'sec-ch-ua-mobile': '?0',
22
+ 'sec-ch-ua-platform': '"Android"',
23
+ 'sec-fetch-dest': 'empty',
24
+ 'sec-fetch-mode': 'cors',
25
+ 'sec-fetch-site': 'same-origin',
26
+ 'user-agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
27
+ 'x-requested-with': 'XMLHttpRequest',
28
+ }
29
+
30
+ params = {
31
+ 'media': showname,
32
+ '_': '1724421723999',
33
+ }
34
+ response = await client.get(f'https://lordchannel.{LC_DOMAIN}/live_search/', params=params, cookies=cookies, headers=headers, allow_redirects=True, impersonate = "chrome120")
35
+ data = json.loads(response.text)
36
+ for entry in data['data']:
37
+ if entry is not None: # check if the a_tag exists
38
+ href = entry['url']
39
+ quality = entry['qualit\u00e0_video']
40
+ link = f'https://lordchannel.{LC_DOMAIN}{href}'
41
+ response = await client.get(link, allow_redirects=True, impersonate = "chrome120")
42
+ soup2 = BeautifulSoup(response.text,'lxml')
43
+ li_tag = soup2.select_one("ul.card__meta li:nth-of-type(2)")
44
+ if li_tag is not None: # check if the li_tag exists
45
+ card_date = li_tag.text[-4:]
46
+ if card_date == date:
47
+ if ismovie == 1:
48
+ video_url = soup2.find('a', class_="btn-streaming streaming_btn")
49
+ video_url = video_url['href']
50
+ return video_url,quality
51
+ elif ismovie == 0:
52
+ div = soup2.find('div', id=f'collapse{season}')
53
+ episode = episode -1 #Index start from 0 so I need to subtract 1
54
+ episode = div.select('tr')[2] # index is 2 because we want the correct element
55
+ video_url = episode.find('a').get('href')
56
+ return video_url,quality
57
+ else:
58
+ print("")
59
+ continue
60
+
61
+ async def get_m3u8(video_url,client):
62
+ response = await client.get(video_url, allow_redirects=True, impersonate = "chrome120")
63
+ pattern = r'const\s+videoData\s*=\s*\[(.*?)\];'
64
+ match = re.search(pattern, response.text)
65
+ if match:
66
+ video_data = match.group(1).strip().split(', ')
67
+ url = video_data[0]
68
+ return url
69
+
70
+ async def lordchannel(imdb,client):
71
+ try:
72
+ general = is_movie(imdb)
73
+ ismovie = general[0]
74
+ imdb_id = general[1]
75
+ type = "LordChannel"
76
+ if ismovie == 0:
77
+ season = int(general[2])
78
+ episode = int(general[3])
79
+ if "tt" in imdb:
80
+ tmdba = await get_TMDb_id_from_IMDb_id(imdb_id,client)
81
+ else:
82
+ tmdba = imdb_id
83
+ else:
84
+ season = None
85
+ episode = None
86
+ if "tt" in imdb:
87
+ tmdba = await get_TMDb_id_from_IMDb_id(imdb_id,client)
88
+ else:
89
+ tmdba = imdb_id
90
+ showname,date = get_info_tmdb(tmdba,ismovie,type)
91
+ video_url,quality = await search(showname,date,season,episode,ismovie,client)
92
+ url = await get_m3u8(video_url,client)
93
+ url = url.replace('"','')
94
+ print("MammaMia: Found results for LordChannel")
95
+ return url,quality
96
+ except:
97
+ print("MammaMia: Lordchannel Failed")
98
+ return None,None
99
+
100
+
101
+ '''
102
+ async def test_animeworld():
103
+ async with httpx.AsyncClient() as client:
104
+ results = await lordchannel("tt14134334:1:1",client)
105
+ print(results)
106
+
107
+ if __name__ == "__main__":
108
+ import httpx
109
+ import asyncio
110
+ asyncio.run(test_animeworld())
111
+ '''
Src/API/okru.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from bs4 import BeautifulSoup
2
+ import json
3
+ from Src.Utilities.dictionaries import okru
4
+
5
+
6
+
7
+ async def okru_get_url(id,client):
8
+ embed_link = okru[id]
9
+ print(embed_link)
10
+ response = await client.get(embed_link, allow_redirects=True, impersonate = "chrome120")
11
+ soup = BeautifulSoup(response.text, 'lxml')
12
+ div = soup.find('div', {'data-module': 'OKVideo'})
13
+ data_options = div.get('data-options')
14
+ data = json.loads(data_options)
15
+ metadata = json.loads(data['flashvars']['metadata'])
16
+ m3u8_link = metadata['hlsMasterPlaylistUrl']
17
+ print("MammaMia: Found results for Okru")
18
+ return m3u8_link
Src/API/streamingcommunity.py ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from bs4 import BeautifulSoup
2
+ from Src.Utilities.convert import get_TMDb_id_from_IMDb_id
3
+ from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
4
+ import Src.Utilities.config as config
5
+ import json
6
+ import random
7
+ import re
8
+ from urllib.parse import urlparse, parse_qs
9
+ from fake_headers import Headers
10
+ from Src.Utilities.loadenv import load_env
11
+ env_vars = load_env()
12
+ #Get domain
13
+ SC_DOMAIN = config.SC_DOMAIN
14
+ Public_Instance = config.Public_Instance
15
+ Alternative_Link = env_vars.get('ALTERNATIVE_LINK')
16
+
17
+ headers = Headers()
18
+ #GET VERSION OF STREAMING COMMUNITY:
19
+ async def get_version(client):
20
+ #Extract the version from the main page of the site
21
+
22
+
23
+ try:
24
+ random_headers = headers.generate()
25
+ random_headers['Referer'] = "https://streamingcommunity.buzz/"
26
+ random_headers['Origin'] = "https://streamingcommunity.buzz"
27
+ base_url = f'https://streamingcommunity.{SC_DOMAIN}/richiedi-un-titolo'
28
+ response = await client.get(base_url, headers=random_headers, allow_redirects = True, impersonate="chrome120")
29
+ #Soup the response
30
+ soup = BeautifulSoup(response.text, "lxml")
31
+
32
+ # Extract version
33
+ version = json.loads(soup.find("div", {"id": "app"}).get("data-page"))['version']
34
+ return version
35
+ except Exception as e:
36
+ print("Couldn't find the version",e)
37
+ version = "65e52dcf34d64173542cd2dc6b8bb75b"
38
+ return version
39
+
40
+ async def search(query,date,ismovie, client,SC_FAST_SEARCH):
41
+ random_headers = headers.generate()
42
+ random_headers['Referer'] = "https://streamingcommunity.buzz/"
43
+ random_headers['Origin'] = "https://streamingcommunity.buzz"
44
+ #Do a request to get the ID of serie/move and it's slug in the URL
45
+ response = await client.get(query, headers = random_headers, allow_redirects=True,impersonate = "chrome120")
46
+ print(response)
47
+ response = response.json()
48
+
49
+ for item in response['data']:
50
+ tid = item['id']
51
+ slug = item['slug']
52
+ type = item['type']
53
+ if type == "tv":
54
+ type = 0
55
+ elif type == "movie":
56
+ type = 1
57
+ if type == ismovie:
58
+ #Added a Check to see if the result is what it is supposed to be
59
+ if SC_FAST_SEARCH == "0":
60
+ random_headers = headers.generate()
61
+ random_headers['Referer'] = "https://streamingcommunity.buzz/"
62
+ random_headers['Origin'] = "https://streamingcommunity.buzz"
63
+ response = await client.get ( f'https://streamingcommunity.{SC_DOMAIN}/titles/{tid}-{slug}', headers = random_headers, allow_redirects=True,impersonate = "chrome120")
64
+ pattern = r'<div[^>]*class="features"[^>]*>.*?<span[^>]*>(.*?)<\/span>'
65
+ match = re.search(pattern, response.text)
66
+ print(match.group(1).split("-")[0])
67
+ first_air_year = match.group(1).split("-")[0]
68
+ date = int(date)
69
+ first_air_year = int(first_air_year)
70
+ if first_air_year == date:
71
+ return tid,slug
72
+ elif SC_FAST_SEARCH == "1":
73
+ return tid,slug
74
+ else:
75
+ print("Couldn't find anything")
76
+
77
+
78
+ async def get_film(tid,version,client):
79
+ random_headers = headers.generate()
80
+ random_headers['Referer'] = "https://streamingcommunity.buzz/"
81
+ random_headers['Origin'] = "https://streamingcommunity.buzz"
82
+ random_headers['x-inertia'] = "true"
83
+ random_headers['x-inertia-version'] = version
84
+ #Access the iframe
85
+ url = f'https://streamingcommunity.{SC_DOMAIN}/iframe/{tid}'
86
+ response = await client.get(url, headers=random_headers, allow_redirects=True,impersonate = "chrome120")
87
+ iframe = BeautifulSoup(response.text, 'lxml')
88
+ #Get the link of iframe
89
+ iframe = iframe.find('iframe').get("src")
90
+ #Get the ID containted in the src of iframe
91
+ vixid = iframe.split("/embed/")[1].split("?")[0]
92
+ parsed_url = urlparse(iframe)
93
+ query_params = parse_qs(parsed_url.query)
94
+ random_headers = headers.generate()
95
+ random_headers['Referer'] = "https://streamingcommunity.buzz/"
96
+ random_headers['Origin'] = "https://streamingcommunity.buzz"
97
+ random_headers['x-inertia'] = "true"
98
+ random_headers['x-inertia-version'] = version
99
+ #Get real token and expires by looking at the page in the iframe, vixcloud/embed
100
+ resp = await client.get(iframe, headers = random_headers, allow_redirects=True,impersonate= "chrome120")
101
+ soup= BeautifulSoup(resp.text, "lxml")
102
+ script = soup.find("body").find("script").text
103
+ token = re.search(r"'token':\s*'(\w+)'", script).group(1)
104
+ expires = re.search(r"'expires':\s*'(\d+)'", script).group(1)
105
+ quality = re.search(r'"quality":(\d+)', script).group(1)
106
+ #Example url https://vixcloud.co/playlist/231315?b=1&token=bce060eec3dc9d1965a5d258dc78c964&expires=1728995040&rendition=1080p
107
+ url = f'https://vixcloud.co/playlist/{vixid}?token={token}&expires={expires}'
108
+ if 'canPlayFHD' in query_params:
109
+ canPlayFHD = 'h=1'
110
+ url += "&h=1"
111
+ if 'b' in query_params:
112
+ b = 'b=1'
113
+ url += "&b=1"
114
+ url720 = f'https://vixcloud.co/playlist/{vixid}'
115
+ return url,url720,quality,
116
+
117
+ async def get_season_episode_id(tid,slug,season,episode,version,client):
118
+ random_headers = headers.generate()
119
+ random_headers['Referer'] = "https://streamingcommunity.buzz/"
120
+ random_headers['Origin'] = "https://streamingcommunity.buzz"
121
+ random_headers['x-inertia'] = "true"
122
+ random_headers['x-inertia-version'] = version
123
+ #Set some basic headers for the request
124
+ #Get episode ID
125
+ response = await client.get(f'https://streamingcommunity.{SC_DOMAIN}/titles/{tid}-{slug}/stagione-{season}', headers=random_headers, allow_redirects=True, impersonate = "chrome120")
126
+ # Print the json got
127
+ json_response = response.json().get('props', {}).get('loadedSeason', {}).get('episodes', [])
128
+ for dict_episode in json_response:
129
+ if dict_episode['number'] == episode:
130
+ return dict_episode['id']
131
+
132
+ async def get_episode_link(episode_id,tid,version,client):
133
+ #The parameters for the request
134
+ random_headers = headers.generate()
135
+ random_headers['Referer'] = "https://streamingcommunity.buzz/"
136
+ random_headers['Origin'] = "https://streamingcommunity.buzz"
137
+ params = {
138
+ 'episode_id': episode_id,
139
+ 'next_episode': '1'
140
+ }
141
+ #Let's try to get the link from iframe source
142
+ # Make a request to get iframe source
143
+ response = await client.get(f"https://streamingcommunity.{SC_DOMAIN}/iframe/{tid}", params=params, headers = random_headers, allow_redirects=True, impersonate = "chrome120")
144
+
145
+ # Parse response with BeautifulSoup to get iframe source
146
+ soup = BeautifulSoup(response.text, "lxml")
147
+ iframe = soup.find("iframe").get("src")
148
+ vixid = iframe.split("/embed/")[1].split("?")[0]
149
+ random_headers = headers.generate()
150
+ random_headers['Referer'] = "https://streamingcommunity.buzz/"
151
+ random_headers['Origin'] = "https://streamingcommunity.buzz"
152
+ random_headers['x-inertia'] = "true"
153
+ random_headers['x-inertia-version'] = version
154
+ parsed_url = urlparse(iframe)
155
+ query_params = parse_qs(parsed_url.query)
156
+ #Get real token and expires by looking at the page in the iframe, vixcloud/embed
157
+ resp = await client.get(iframe, headers = random_headers, allow_redirects=True, impersonate = "chrome120")
158
+ soup= BeautifulSoup(resp.text, "lxml")
159
+ script = soup.find("body").find("script").text
160
+ token = re.search(r"'token':\s*'(\w+)'", script).group(1)
161
+ expires = re.search(r"'expires':\s*'(\d+)'", script).group(1)
162
+ quality = re.search(r'"quality":(\d+)', script).group(1)
163
+ #Example url https://vixcloud.co/playlist/231315?b=1&token=bce060eec3dc9d1965a5d258dc78c964&expires=1728995040&rendition=1080p
164
+ url = f'https://vixcloud.co/playlist/{vixid}?token={token}&expires={expires}'
165
+ if 'canPlayFHD' in query_params:
166
+ canPlayFHD = 'h=1'
167
+ url += "&h=1"
168
+ if 'b' in query_params:
169
+ b = 'b=1'
170
+ url += "&b=1"
171
+ url720 = f'https://vixcloud.co/playlist/{vixid}'
172
+ return url,url720,quality
173
+
174
+
175
+ async def streaming_community(imdb,client,SC_FAST_SEARCH):
176
+ try:
177
+ if Public_Instance == "1":
178
+ Weird_Link = json.loads(Alternative_Link)
179
+ link_post = random.choice(Weird_Link)
180
+ response = await client.get(f"{link_post}fetch-data/{imdb}")
181
+ url_streaming_community = response.headers.get('x-url-streaming-community')
182
+ url_720_streaming_community = response.headers.get('x-url-720-streaming-community')
183
+ quality_sc = response.headers.get('x-quality-sc')
184
+ print(quality_sc,url_streaming_community)
185
+ return url_streaming_community,url_720_streaming_community,quality_sc
186
+ general = is_movie(imdb)
187
+ ismovie = general[0]
188
+ imdb_id = general[1]
189
+ if ismovie == 0 :
190
+ season = int(general[2])
191
+ episode = int(general[3])
192
+ #Check if fast search is enabled or disabled
193
+ if SC_FAST_SEARCH == "1":
194
+ type = "StreamingCommunityFS"
195
+ if "tt" in imdb:
196
+ #Get showname
197
+ showname = await get_info_imdb(imdb_id,ismovie,type,client)
198
+ date = None
199
+ else:
200
+ #I just set n season to None to avoid bugs, but it is not needed if Fast search is enabled
201
+ date = None
202
+ #else just equals them
203
+ tmdba = imdb_id.replace("tmdb:","")
204
+ showname = get_info_tmdb(tmdba,ismovie,type)
205
+ elif SC_FAST_SEARCH == "0":
206
+ type = "StreamingCommunity"
207
+ tmdba = await get_TMDb_id_from_IMDb_id(imdb_id,client)
208
+ showname,date = get_info_tmdb(tmdba,ismovie,type)
209
+ #HERE THE CASE IF IT IS A MOVIE
210
+ else:
211
+ if SC_FAST_SEARCH == "1":
212
+ type = "StreamingCommunityFS"
213
+ if "tt" in imdb:
214
+ #Get showname
215
+ date = None
216
+ showname = await get_info_imdb(imdb_id,ismovie,type,client)
217
+ else:
218
+ date = None
219
+ tmdba = imdb_id.replace("tmdb:","")
220
+ showname = get_info_tmdb(tmdba,ismovie,type)
221
+ elif SC_FAST_SEARCH == "0":
222
+ type = "StreamingCommunity"
223
+ if "tt" in imdb:
224
+ #Get showname
225
+ showname,date = await get_info_imdb(imdb_id,ismovie,type,client)
226
+ else:
227
+ tmdba = imdb_id.replace("tmdb:","")
228
+ showname,date = get_info_tmdb(tmdba,ismovie,type)
229
+
230
+ showname = showname.replace(" ", "+").replace("–", "+").replace("—","+")
231
+ query = f'https://streamingcommunity.{SC_DOMAIN}/api/search?q={showname}'
232
+ version = await get_version(client)
233
+ tid,slug = await search(query,date,ismovie,client,SC_FAST_SEARCH)
234
+ if ismovie == 1:
235
+ #TID means temporaly ID
236
+ url,url720,quality = await get_film(tid,version,client)
237
+ print("MammaMia found results for StreamingCommunity")
238
+ return url,url720,quality
239
+ if ismovie == 0:
240
+ #Uid = URL ID
241
+ episode_id = await get_season_episode_id(tid,slug,season,episode,version,client)
242
+ url,url720,quality = await get_episode_link(episode_id,tid,version,client)
243
+ print("MammaMia found results for StreamingCommunity")
244
+ return url,url720,quality
245
+ except Exception as e:
246
+ print("MammaMia: StreamingCommunity failed",e)
247
+ return None,None,None
248
+ '''
249
+ async def test_animeworld():
250
+ from curl_cffi.requests import AsyncSession
251
+ async with AsyncSession() as client:
252
+ # Replace with actual id, for example 'anime_id:episode' format
253
+ test_id = "tt16288804:1:1" # This is an example ID format
254
+ results = await streaming_community(test_id, client,"0")
255
+
256
+ if __name__ == "__main__":
257
+ import asyncio
258
+ asyncio.run(test_animeworld())
259
+ '''
Src/API/streamingwatch.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from bs4 import BeautifulSoup,SoupStrainer
2
+ from Src.Utilities.convert import get_TMDb_id_from_IMDb_id
3
+ from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
4
+ import Src.Utilities.config as config
5
+ import re
6
+ import json
7
+ SW_DOMAIN = config.SW_DOMAIN
8
+ async def search(showname,season,episode,date,ismovie,client):
9
+ if ismovie == 1:
10
+ query = f'https://www.streamingwatch.{SW_DOMAIN}/wp-admin/admin-ajax.php'
11
+ headers = {
12
+ 'authority': f'www.streamingwatch.{SW_DOMAIN}',
13
+ 'accept': '*/*',
14
+ 'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
15
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
16
+ # 'cookie': 'wordpress_test_cookie=WP%20Cookie%20check',
17
+ 'origin': f'https://www.streamingwatch.{SW_DOMAIN}',
18
+ 'referer': f'https://www.streamingwatch.{SW_DOMAIN}',
19
+ 'sec-ch-ua': '"Not-A.Brand";v="99", "Chromium";v="124"',
20
+ 'sec-ch-ua-mobile': '?0',
21
+ 'sec-ch-ua-platform': '"Android"',
22
+ 'sec-fetch-dest': 'empty',
23
+ 'sec-fetch-mode': 'cors',
24
+ 'sec-fetch-site': 'same-origin',
25
+ 'user-agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
26
+ 'x-requested-with': 'XMLHttpRequest',
27
+ }
28
+ data = {
29
+ 'action': 'data_fetch',
30
+ 'keyword': showname,
31
+ '_wpnonce': '648328b831',
32
+ }
33
+ cookies = {
34
+ 'wordpress_test_cookie': 'WP%20Cookie%20check',
35
+ }
36
+ response = await client.post(query,cookies=cookies, headers=headers, data=data)
37
+ soup = BeautifulSoup(response.content,'lxml')
38
+ page_date = soup.find(id = 'search-cat-year').text.strip()
39
+ if page_date == date:
40
+ href = soup.find('a')['href']
41
+ response = await client.get(href, allow_redirects=True, impersonate = "chrome120")
42
+ soup = BeautifulSoup(response.text,'lxml',parse_only=SoupStrainer('iframe'))
43
+ iframe = soup.find('iframe')
44
+ hdplayer = iframe.get('data-lazy-src')
45
+
46
+ return hdplayer
47
+ elif ismovie == 0:
48
+ #Some series have the name in english so we first search with the categories option and then we use the obtained ID to get all the episodes
49
+ id_response = await client.get(f'https://streamingwatch.{SW_DOMAIN}/wp-json/wp/v2/categories?search={showname}&_fields=id', allow_redirects=True, impersonate = "chrome120")
50
+ data = json.loads(id_response.text)
51
+ category_id = data[0]['id']
52
+ query = f'https://streamingwatch.{SW_DOMAIN}/wp-json/wp/v2/posts?categories={category_id}&per_page=100'
53
+ response = await client.get(query, allow_redirects=True, impersonate = "chrome120")
54
+ data_json = response.text
55
+ data = json.loads(data_json)
56
+ for entry in data:
57
+ if f"stagione-{season}-episodio-{episode}" in entry["slug"]:
58
+ content = entry["content"]["rendered"]
59
+ #"content":{
60
+ # "rendered":"<p><!--baslik:PRO--><iframe loading=\"lazy\" src=\"https:\/\/hdplayer.gives\/embed\/YErLVq64uNTZRNz\" frameborder=\"0\" width=\"700\" height=\"400\" allowfullscreen><\/iframe><\/p>\n","protected":false}
61
+ start = content.find('src="') + len('src="') #start of url
62
+ end = content.find('"', start) #end of url
63
+ hdplayer = content[start:end]
64
+ return hdplayer
65
+ async def hls_url(hdplayer,client):
66
+ response = await client.get(hdplayer, allow_redirects=True, impersonate = "chrome120")
67
+ match = re.search(r'sources:\s*\[\s*\{\s*file\s*:\s*"([^"]*)"', response.text)
68
+ url = match.group(1)
69
+ return url
70
+ async def streamingwatch(imdb,client):
71
+ try:
72
+ general = is_movie(imdb)
73
+ ismovie = general[0]
74
+ imdb_id = general[1]
75
+ type = "StreamingWatch"
76
+ if ismovie == 0:
77
+ season = int(general[2])
78
+ episode = int(general[3])
79
+ if "tt" in imdb:
80
+ tmdba = await get_TMDb_id_from_IMDb_id(imdb_id,client)
81
+ else:
82
+ tmdba = imdb_id
83
+ else:
84
+ season = None
85
+ episode = None
86
+ if "tt" in imdb:
87
+ tmdba = await get_TMDb_id_from_IMDb_id(imdb_id,client)
88
+ else:
89
+ tmdba = imdb_id
90
+ showname,date = get_info_tmdb(tmdba,ismovie,type)
91
+ showname = showname.replace(" ", "+").replace("–", "+").replace("—","+")
92
+ hdplayer = await search(showname,season,episode,date,ismovie,client)
93
+ url = await hls_url(hdplayer,client)
94
+ print("MammaMia: StreamingWatch found results for StreamingCommunity")
95
+ return url
96
+ except:
97
+ print("MammaMia: StreamingWatch Failed")
98
+ return None
Src/API/tantifilm.py ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from bs4 import BeautifulSoup,SoupStrainer
2
+ import re
3
+ import time
4
+ from Src.Utilities.info import is_movie,get_info_imdb,get_info_tmdb
5
+ import Src.Utilities.config as config
6
+ from Src.Utilities.loadenv import load_env
7
+ HF = config.HF
8
+ env_vars = load_env()
9
+ PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
10
+ TF_DOMAIN = config.TF_DOMAIN
11
+
12
+ async def search(showname,ismovie,date,client):
13
+ showname = showname.replace(" ","%20")
14
+ url = f'https://www.tanti.bond/ajax/posts?q={showname}'
15
+ response = await client.post(url, allow_redirects=True, impersonate = "chrome120")
16
+ response = response.json()['data']
17
+ if ismovie == 1:
18
+ for link in response:
19
+ url = link['url']
20
+ response = client.get(url, allow_redirects=True, impersonate = "chrome120")
21
+ pattern = r'Data di rilascio\s*</div>\s*<div class="text">\s*(\d{4})\s*</div>'
22
+ found_date = re.search(pattern, response.text)
23
+ release_date = str(found_date.group(1))
24
+ if release_date == date:
25
+ tid= url.split('-')[-1]
26
+ #Return URL and even the soup so I can use it later
27
+ #I try to get doodstream link inside this function so I do not have to get again the response
28
+ return tid,url
29
+ elif ismovie == 0:
30
+ for link in response:
31
+ base_url = link['url']
32
+ url = f'{base_url}-1-season-1-episode'
33
+ response = await client.get(url, allow_redirects=True, impersonate = "chrome120")
34
+ pattern = r'Data di rilascio\s*</div>\s*<div class="text">\s*(\d{4})\s*</div>'
35
+ found_date = re.search(pattern, response.text)
36
+ release_date = str(found_date.group(1))
37
+ if release_date == date:
38
+ tid= url.split('-')[1]
39
+ soup = BeautifulSoup(response.text, 'lxml')
40
+ a_tag = soup.find('a', class_='dropdown-toggle btn-service selected')
41
+ embed_id = a_tag['data-embed']
42
+ #I try to get doodstream link inside this function so I do not have to get again the response
43
+ return url,embed_id
44
+
45
+ async def fast_search(showname,ismovie,client):
46
+ showname = showname.replace(" ","%20")
47
+ url = f'https://www.tanti.{TF_DOMAIN}/search/{showname}'
48
+ response = await client.get(url, allow_redirects=True, impersonate = "chrome120")
49
+ soup = BeautifulSoup(response.text, "lxml")
50
+ if ismovie == 1:
51
+ first_link = soup.select_one('#movies .col .list-media')
52
+ url = first_link['href']
53
+ tid= url.split('-')[1]
54
+ return tid,url
55
+ elif ismovie == 0:
56
+ first_link = soup.select_one('#series .col .list-media')
57
+ base_url = first_link['href']
58
+ url = f'{base_url}-1-season-1-episode'
59
+ response = await client.get(url, allow_redirects=True, impersonate = "chrome120")
60
+ soup = BeautifulSoup(response.text, 'lxml')
61
+ a_tag = soup.find('a', class_='dropdown-toggle btn-service selected')
62
+ embed_id = a_tag['data-embed']
63
+ return url,embed_id
64
+
65
+
66
+
67
+ async def get_protect_link(id,url,client):
68
+ #Get the link where the Iframe is located, which contains the doodstream url kind of.
69
+ response = await client.get(f"https://p.hdplayer.casa/myadmin/play.php?id={id}", allow_redirects=True, impersonate = "chrome120")
70
+ soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer('iframe'))
71
+ protect_link = soup.iframe['src']
72
+ if "protect" in protect_link:
73
+ return protect_link
74
+ else:
75
+ #DO this in case the movie has a 3D version etc
76
+ response = await client.get(url, allow_redirects=True, impersonate = "chrome120")
77
+ soup = BeautifulSoup(response.text, 'lxml')
78
+ a_tag = soup.find('a', class_='dropdown-toggle btn-service selected')
79
+ embed_id = a_tag['data-embed']
80
+ headers = {
81
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
82
+ 'Referer': url
83
+ }
84
+ #Parameters needed is the embed ID
85
+ data = {
86
+ 'id': embed_id
87
+ }
88
+ ajax_url = f"https://www.tanti.{TF_DOMAIN}/ajax/embed"
89
+ response = await client.post(ajax_url, headers=headers, data=data)
90
+ hdplayer = response.text[43:-27]
91
+ response = await client.get(hdplayer, allow_redirects=True, impersonate = "chrome120")
92
+ soup = BeautifulSoup(response.text, 'lxml')
93
+ links_dict = {}
94
+ li_tags = soup.select('ul.nav.navbar-nav li.dropdown')
95
+ for li_tag in li_tags:
96
+ a_tag = li_tag.find('a')
97
+ if a_tag:
98
+ title = a_tag.text.strip()
99
+ #Since tantifilm player is broken I just skip it
100
+ if title == "1" or "Tantifilm" in title:
101
+ continue # Get the text of the <a> tag
102
+ href = a_tag['href']
103
+ response = await client.get(href, allow_redirects=True, impersonate = "chrome120")
104
+ soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer('iframe'))
105
+ protect_link = soup.iframe['src']
106
+ if "protect" in protect_link:
107
+ url = true_url(protect_link)
108
+ links_dict[title] = url
109
+ return links_dict
110
+ # Get the value of the href attribute
111
+
112
+
113
+ async def get_nuovo_indirizzo_and_protect_link(url,embed_id,season,episode,client):
114
+ headers = {
115
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
116
+ 'Referer': url
117
+ }
118
+ #Parameters needed is the embed ID
119
+ data = {
120
+ 'id': embed_id
121
+ }
122
+ ajax_url = f"https://www.tanti.{TF_DOMAIN}/ajax/embed"
123
+ response = await client.post(ajax_url, headers=headers, data=data)
124
+ nuovo_indirizzo = response.text[43:-27]
125
+ response = await client.get(nuovo_indirizzo, allow_redirects=True, impersonate = "chrome120")
126
+ soup = BeautifulSoup(response.text, 'lxml')
127
+ #Get season
128
+ season = season - 1
129
+ li_tags = soup.select('ul.nav.navbar-nav > li.dropdown')
130
+ if len(li_tags) != 1:
131
+ link = li_tags[season].find('a')['href']
132
+ response = await client.get(link, allow_redirects=True, impersonate = "chrome120")
133
+ soup = BeautifulSoup(response.text, 'lxml')
134
+ option_tag = soup.select(f'select[name="ep_select"] > option:nth-of-type({episode})')[0]
135
+ link = option_tag['value']
136
+ #Let's find protect link now
137
+ response = await client.get(link, allow_redirects=True, impersonate = "chrome120")
138
+ soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer('iframe'))
139
+ protect_link = soup.iframe['src']
140
+ return protect_link
141
+
142
+ else:
143
+ #If there is only one season than
144
+ option_tag = soup.select('select.dynamic_select > option')[episode]
145
+ link = option_tag['value']
146
+ #Let's find protect link now
147
+ response = await client.get(link, allow_redirects=True, impersonate = "chrome120")
148
+ soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer('iframe'))
149
+ protect_link = soup.iframe['src']
150
+ return protect_link
151
+
152
+
153
+ async def true_url(protect_link,client):
154
+ # Define headers
155
+ headers = {
156
+ "Range": "bytes=0-",
157
+ "Referer": "https://d000d.com/",
158
+ }
159
+ if HF == "1":
160
+ import random
161
+ import json
162
+ proxy_list = PROXY_CREDENTIALS
163
+ proxy = random.choice(proxy_list)
164
+ proxies = {
165
+ "http": proxy,
166
+ "https": proxy
167
+ }
168
+ response = await client.get(protect_link, proxies=proxies, allow_redirects=True, impersonate = "chrome120")
169
+ else:
170
+ response = await client.get(protect_link, allow_redirects=True, impersonate = "chrome120")
171
+
172
+
173
+ if response.status_code == 200:
174
+ # Get unique timestamp for the request
175
+ real_time = str(int(time.time()))
176
+
177
+ # Regular Expression Pattern for the match
178
+ pattern = r"(\/pass_md5\/.*?)'.*(\?token=.*?expiry=)"
179
+
180
+ # Find the match
181
+ match = re.search(pattern, response.text, re.DOTALL)
182
+
183
+ # If a match was found
184
+ if match:
185
+ # Create real link (match[0] includes all matched elements)
186
+ url =f'https://d000d.com{match[1]}'
187
+ if "HF" == "1" :
188
+ rebobo = await client.get(url, headers=headers, allow_redirects=True, impersonate = "chrome120",proxies= proxies)
189
+ else:
190
+ rebobo = await client.get(url, headers=headers, allow_redirects=True, impersonate = "chrome120")
191
+ real_url = f'{rebobo.text}123456789{match[2]}{real_time}'
192
+ print("MammaMia: Found results for Tantifilm")
193
+ return real_url
194
+ else:
195
+ print("No match found in the text.")
196
+ return None
197
+
198
+ print("Error: Could not get the response.")
199
+ return None
200
+
201
+
202
+
203
+ #Get temporaly ID
204
+ async def tantifilm(imdb,client,TF_FAST_SEARCH):
205
+ urls = None
206
+ try:
207
+ general = is_movie(imdb)
208
+ ismovie = general[0]
209
+ imdb_id = general[1]
210
+ if ismovie == 0 :
211
+ season = int(general[2])
212
+ episode = int(general[3])
213
+ if "tt" in imdb:
214
+ if TF_FAST_SEARCH == "0":
215
+ type = "Tantifilm"
216
+ showname,date = await get_info_imdb(imdb_id,ismovie,type,client)
217
+ url,embed_id = await search(showname,ismovie,date,client)
218
+ elif TF_FAST_SEARCH == "1":
219
+ type = "TantifilmFS"
220
+ showname = await get_info_imdb(imdb_id,ismovie,type,client)
221
+ url,embed_id = await fast_search(showname,ismovie,client)
222
+ else:
223
+ #else just equals them
224
+ tmdba = imdb_id.replace("tmdb:","")
225
+ if TF_FAST_SEARCH == "0":
226
+ type = "Tantifilm"
227
+ showname,date = get_info_tmdb(tmdba,ismovie,type)
228
+ url,embed_id = await search(showname,ismovie,date,client)
229
+ elif TF_FAST_SEARCH == "1":
230
+ type = "TantifilmFS"
231
+ showname= get_info_tmdb(tmdba,ismovie,type)
232
+ url,embed_id = await fast_search(showname,ismovie,client)
233
+ protect_link = await get_nuovo_indirizzo_and_protect_link(url,embed_id,season,episode,client)
234
+ url = await true_url(protect_link,client)
235
+ return url
236
+ elif ismovie == 1:
237
+ if "tt" in imdb:
238
+ #Get showname
239
+ if TF_FAST_SEARCH == "0":
240
+ type = "Tantifilm"
241
+ showname,date = await get_info_imdb(imdb_id,ismovie,type,client)
242
+ tid,url = await search(showname,ismovie,date,client)
243
+ elif TF_FAST_SEARCH == "1":
244
+ type = "TantifilmFS"
245
+ showname = await get_info_imdb(imdb_id,ismovie,type,client)
246
+ date = None
247
+ tid,url = await fast_search(showname,ismovie,client)
248
+ else:
249
+ if TF_FAST_SEARCH == "0":
250
+ type = "Tantifilm"
251
+ showname,date = get_info_tmdb(imdb,ismovie,type)
252
+ tid,url = await search(showname,ismovie,date,client)
253
+ elif TF_FAST_SEARCH == "1":
254
+ type = "TantifilmFS"
255
+ showname = get_info_tmdb(imdb,ismovie,type)
256
+ tid,url = await fast_search(showname,ismovie,client)
257
+ protect_link = await get_protect_link(tid,url,client)
258
+ if not isinstance(protect_link, str):
259
+ urls = protect_link
260
+ if urls:
261
+ return urls
262
+ else:
263
+ print("Tantifilm Error v2")
264
+ else:
265
+ url = await true_url(protect_link,client)
266
+ if url:
267
+ return url
268
+
269
+ except Exception as e:
270
+ print("Tantifilm Error: ", e)
271
+ return None
272
+
273
+
274
+ '''
275
+ async def test_animeworld():
276
+ from curl_cffi.requests import AsyncSession
277
+ async with AsyncSession() as client:
278
+ # Replace with actual id, for example 'anime_id:episode' format
279
+ test_id = "tt6468322:1:1" # This is an example ID format
280
+ results = await tantifilm(test_id, client,"0")
281
+
282
+ if __name__ == "__main__":
283
+ import asyncio
284
+ asyncio.run(test_animeworld())
285
+
286
+ '''
287
+
Src/API/webru.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ import Src.Utilities.config as config
3
+ from Src.Utilities.dictionaries import webru_vary,webru_dlhd
4
+ from Src.Utilities.loadenv import load_env
5
+ env_vars = load_env()
6
+ MEDIAFLOW_PASS = env_vars.get('MEDIAFLOW_PASS')
7
+ Referer = "https://ilovetoplay.xyz/"
8
+ Origin = "https://ilovetoplay.xyz"
9
+ headers = {
10
+ "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0",
11
+ "Accept": "*/*",
12
+ "Accept-Language": "en-US,en;q=0.5",
13
+ "Accept-Encoding": "gzip, deflate, br, zstd",
14
+ "Origin": Origin,
15
+ "DNT": "1",
16
+ "Sec-GPC": "1",
17
+ "Connection": "keep-alive",
18
+ "Referer": Referer,
19
+ "Sec-Fetch-Dest": "empty",
20
+ "Sec-Fetch-Mode": "cors",
21
+ "Sec-Fetch-Site": "cross-site",
22
+ "Pragma": "no-cache",
23
+ "Cache-Control": "no-cache",
24
+ }
25
+ medialink = config.MediaProxy
26
+ async def get_stream_link(id,site,client):
27
+ try:
28
+ if site == "dlhd":
29
+ m3u8_url = webru_dlhd[id]
30
+ elif site == "vary":
31
+ m3u8_url = webru_vary[id]
32
+ response = await client.get(m3u8_url, headers=headers, allow_redirects=False, impersonate = "chrome120")
33
+ if response.status_code == 301:
34
+ stream_url = response.headers.get("Location", "")
35
+ return stream_url,Referer,Origin
36
+ except Exception as e:
37
+ return None
38
+ async def webru(id,site,client):
39
+ try:
40
+ stream_url, Referer,Origin = await get_stream_link(id,site,client)
41
+ mediaproxy = config.MediaProxy
42
+ medialink = random.choice(mediaproxy)
43
+ new_stream_url = f'{medialink}proxy/hls?key_url=https%3A%2F%2Fkey.mizhls.ru%2F&api_password={MEDIAFLOW_PASS}&d={stream_url}&h_Referer={Referer}&h_Origin={Origin}&h_User-Agent=Mozilla%2F5.0%20(Windows%20NT%2010.0%3B%20Win64%3B%20x64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F58.0.3029.110%20Safari%2F537.3'
44
+ return new_stream_url
45
+ except Exception as e:
46
+ print("WebRu failed",e)
47
+ return None
Src/Utilities/__pycache__/config.cpython-311.pyc ADDED
Binary file (1.29 kB). View file
 
Src/Utilities/__pycache__/convert.cpython-311.pyc ADDED
Binary file (1.08 kB). View file
 
Src/Utilities/__pycache__/convert_date.cpython-311.pyc ADDED
Binary file (3.95 kB). View file
 
Src/Utilities/__pycache__/dictionaries.cpython-311.pyc ADDED
Binary file (31.3 kB). View file
 
Src/Utilities/__pycache__/info.cpython-311.pyc ADDED
Binary file (6.86 kB). View file
 
Src/Utilities/__pycache__/loadenv.cpython-311.pyc ADDED
Binary file (1.18 kB). View file
 
Src/Utilities/config.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #LOAD THE CONFIG
2
+ import json
3
+
4
+ # Open the configuration file
5
+ with open('config.json') as f:
6
+ # Load JSON data from file
7
+ config = json.load(f)
8
+
9
+ # Accessing SC_DOMAIN
10
+ SITE = config["Siti"]
11
+ FT_DOMAIN = SITE["Filmpertutti"]['domain']
12
+ SC_DOMAIN = SITE["StreamingCommunity"]['domain']
13
+ TF_DOMAIN = SITE["Tantifilm"]['domain']
14
+ LC_DOMAIN = SITE["LordChannel"]['domain']
15
+ SW_DOMAIN = SITE["StreamingWatch"]['domain']
16
+ AW_DOMAIN = SITE['AnimeWorld']['domain']
17
+ MYSTERIUS = SITE['Mysterius']['enabled']
18
+ #General
19
+ GENERAL = config['General']
20
+ dotenv = GENERAL["load_env"]
21
+ HOST = GENERAL["HOST"]
22
+ PORT = GENERAL["PORT"]
23
+ HF = GENERAL["HF"]
24
+ Public_Instance = GENERAL["Public_Instance"]
25
+ MediaProxy = GENERAL["MediaProxy"]
Src/Utilities/convert.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from Src.Utilities.loadenv import load_env
2
+ env_vars = load_env()
3
+
4
+ TMDB_KEY = env_vars.get('TMDB_KEY')
5
+ async def get_TMDb_id_from_IMDb_id(imdb_id,client):
6
+ response = await client.get(f'https://api.themoviedb.org/3/find/{imdb_id}',
7
+ params={'external_source': 'imdb_id', 'api_key': f'{TMDB_KEY}'})
8
+ tmbda = response.json()
9
+ if tmbda['movie_results']:
10
+ return tmbda['movie_results'][0]['id']
11
+ elif tmbda['tv_results']:
12
+ return tmbda['tv_results'][0]['id']
13
+ else:
14
+ return None
Src/Utilities/convert_date.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ def convert_US_date(date):
3
+ us_data = next((country_data for country_data in date['results'] if country_data["iso_3166_1"] == "US"), None)
4
+ if us_data:
5
+ us_release_dates_type_3 = [rd for rd in us_data['release_dates'] if rd['type'] == 3]
6
+ # Sort the list of release dates and get the latest
7
+ us_release_dates_type_3.sort(key = lambda x: x['release_date'], reverse=True)
8
+ if len(us_release_dates_type_3) > 0:
9
+ latest_release_date = us_release_dates_type_3[0]['release_date']
10
+ date = latest_release_date.split('T')[0]
11
+ print('Latest US theatrical release date:', date)
12
+ return date
13
+ else:
14
+ us_release_dates_type_4 = [rd for rd in us_data['release_dates'] if rd['type'] == 4]
15
+ us_release_dates_type_4.sort(key = lambda x: x['release_date'], reverse=True)
16
+ if len(us_release_dates_type_4) > 0:
17
+ latest_release_date = us_release_dates_type_4[0]['release_date']
18
+ date = latest_release_date.split('T')[0]
19
+ print('Latest US theatrical release date (type 4):', date)
20
+ return date
21
+ def convert_IT_date(date):
22
+ it_data = next((country_data for country_data in date['results'] if country_data["iso_3166_1"] == "IT"), None)
23
+ if it_data:
24
+ it_release_dates_type_3 = [rd for rd in it_data['release_dates'] if rd['type'] == 3]
25
+ # Sort the list of release dates and get the latest
26
+ it_release_dates_type_3.sort(key = lambda x: x['release_date'], reverse=True)
27
+ if len(it_release_dates_type_3) > 0:
28
+ latest_release_date = it_release_dates_type_3[0]['release_date']
29
+ date = latest_release_date.split('T')[0]
30
+ print('Latest IT theatrical release date:', date)
31
+ return date
32
+ else:
33
+ it_release_dates_type_4 = [rd for rd in it_data['release_dates'] if rd['type'] == 4]
34
+ it_release_dates_type_4.sort(key = lambda x: x['release_date'], reverse=True)
35
+ if len(it_release_dates_type_4) > 0:
36
+ latest_release_date = it_release_dates_type_4[0]['release_date']
37
+ date = latest_release_date.split('T')[0]
38
+ print('Latest IT theatrical release date (type 4):', date)
39
+ return date
Src/Utilities/dictionaries.py ADDED
@@ -0,0 +1,846 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ okru = {
2
+ "rai-1": "https://ok.ru/videoembed/7703488765552?nochat=1",
3
+ "rai-2": "https://ok.ru/videoembed/7805618364016?nochat=1",
4
+ "canale-5": "https://ok.ru/videoembed/7789978328688?nochat=1",
5
+ "italia-1": "https://ok.ru/videoembed/7393558339184?nochat=1",
6
+ "rai-premium": "https://ok.ru/videoembed/7363152715376?nochat=1",
7
+ "rai-movie": "https://ok.ru/videoembed/7384012693104?nochat=1",
8
+ "tv8": "https://ok.ru/videoembed/7681651777136?nochat=1",
9
+ "rsi-la-2": "https://ok.ru/videoembed/7681648107120?nochat=1"
10
+ }
11
+
12
+ STREAM = {
13
+ "channels": [
14
+ {
15
+ "id": "la7",
16
+ "title": "LA7",
17
+ "name": "HD/FHD",
18
+ "genres": ["La7"],
19
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/LA7_-_Logo_2011.svg/1280px-LA7_-_Logo_2011.svg.png",
20
+ "url": "https://d3749synfikwkv.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-74ylxpgd78bpb/Live.m3u8"
21
+ },
22
+ {
23
+ "id": "rai-1",
24
+ "title": "Rai 1",
25
+ "name": "Full HD",
26
+ "genres": ["Rai"],
27
+ "poster": "https://i.imgur.com/OPV9jJD.png",
28
+ "url": "http://173.208.52.200/rai1/index.m3u8"
29
+ },
30
+ {
31
+ "id": "rai-2",
32
+ "title": "Rai 2",
33
+ "name": "Full HD",
34
+ "genres": ["Rai"],
35
+ "poster": "https://i.imgur.com/uHtYy8w.png",
36
+ "url": "http://173.208.52.200/rai2/index.m3u8"
37
+ },
38
+ {
39
+ "id": "rai-3",
40
+ "title": "Rai 3",
41
+ "name": "Full HD",
42
+ "genres": ["Rai"],
43
+ "poster": "https://i.imgur.com/iXst6me.png",
44
+ "url": "http://173.208.52.200/rai3/index.m3u8"
45
+ },
46
+ {
47
+ "id": "rai-4",
48
+ "title": "Rai 4",
49
+ "name": "Full HD",
50
+ "genres": ["Rai"],
51
+ "poster": "https://i.imgur.com/KGg3hvr.png",
52
+ "url": "http://173.208.52.200/rai4/index.m3u8"
53
+ },
54
+ {
55
+ "id": "rai-premium",
56
+ "title": "Rai Premium",
57
+ "name": "Full HD",
58
+ "genres": ["Rai"],
59
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/rai-premium_c.png",
60
+ "url": "https://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=746992"
61
+ },
62
+ {
63
+ "id": "rai-4k",
64
+ "title": "Rai 4K",
65
+ "name": "4K",
66
+ "genres": ["Rai"],
67
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Rai_4K_-_Logo_2016.svg/1920px-Rai_4K_-_Logo_2016.svg.png",
68
+ "url": "https://raievent10-elem-live.akamaized.net/hls/live/619189/raievent10/raievent10/playlist.m3u8"
69
+
70
+ },
71
+ {
72
+ "id": "rai-news",
73
+ "title": "Rai News",
74
+ "name": "",
75
+ "genres": ["Rai"],
76
+ "poster": "https://is1-ssl.mzstatic.com/image/thumb/Purple221/v4/31/05/eb/3105eb24-a953-7bb9-876d-0fcfb0a19055/AppIcon-0-0-1x_U007epad-0-10-0-0-85-220.png/1200x630wa.png",
77
+ "url": "https://streamcdnb4-8e7439fdb1694c8da3a0fd63e4dda518.msvdn.net/rainews1/hls/playlist_mo.m3u8"
78
+ },
79
+ {
80
+ "id": "rai-movie",
81
+ "title": "Rai Movie",
82
+ "name": "",
83
+ "genres": ["Rai"],
84
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/rai-movie_c.png",
85
+ "url": "https://m3u.iranvids.com/rai-movie/output.m3u8"
86
+ },
87
+ {
88
+ "id": "rai-sport",
89
+ "title": "Rai Sport",
90
+ "name": "",
91
+ "genres": ["Rai"],
92
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/rai-sport_c.png",
93
+ "url": "https://m3u.iranvids.com/rai-sport01/output.m3u8"
94
+ },
95
+ {
96
+ "id": "rete-4",
97
+ "title": "Rete 4",
98
+ "name": "Full HD",
99
+ "genres": ["Mediaset"],
100
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5f/Rete_4_2018.svg/1024px-Rete_4_2018.svg.png",
101
+ "url": "http://173.208.52.200/rete4/index.m3u8"
102
+ },
103
+ {
104
+ "id": "euronews",
105
+ "title": "Euronews",
106
+ "name": "720p",
107
+ "genres": ["Euronews"],
108
+ "poster": "https://yt3.googleusercontent.com/t3slq37NYJRuP2UoEZDoPKyMClKyQULG8-j2DEfzL1XXcBvFpR6z6HD7rtc0wDn8Mqt0OtpU=s900-c-k-c0x00ffffff-no-rj",
109
+ "url": "https://rakuten-euronews-3-it.samsung.wurl.tv/manifest/playlist.m3u8"
110
+ },
111
+ {
112
+ "id": "canale-5",
113
+ "title": "Canale 5",
114
+ "name": "Full HD",
115
+ "genres": ["Mediaset"],
116
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/canale-5_c.png",
117
+ "url": "http://173.208.52.200/canale5/index.m3u8"
118
+ },
119
+ {
120
+ "id": "italia-1",
121
+ "title": "Italia 1",
122
+ "name": "Full HD",
123
+ "genres": ["Mediaset"],
124
+ "poster": "https://upload.wikimedia.org/wikipedia/en/thumb/e/e2/Italia_1.svg/1024px-Italia_1.svg.png",
125
+ "url": "http://173.208.52.200/italia1/index.m3u8"
126
+ },
127
+ {
128
+ "id": "topcrime",
129
+ "title": "Top Crime",
130
+ "name": "HD/FHD",
131
+ "genres": ["Mediaset"],
132
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/top-crime_c.png",
133
+ "url": "https://live02-seg.msf.cdn.mediaset.net/live/ch-lt/lt-clr.isml/index.m3u8"
134
+ },
135
+ {
136
+ "id": "mediaset-extra",
137
+ "title": "Mediaset Extra",
138
+ "name": "HD/FHD",
139
+ "genres": ["Mediaset"],
140
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/mediaset-extra_c.png",
141
+ "url": "https://live02-seg.msf.cdn.mediaset.net/live/ch-kq/kq-clr.isml/index.m3u8"
142
+ },
143
+ {
144
+ "id": "focus",
145
+ "title": "Focus",
146
+ "name": "HD/FHD",
147
+ "genres": ["Mediaset"],
148
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/d/d0/Focus_channel.png",
149
+ "url": "https://live02-seg.msf.cdn.mediaset.net/live/ch-fu/fu-clr.isml/index.m3u8"
150
+ },
151
+ {
152
+ "id": "boing",
153
+ "title": "Boing",
154
+ "name": "HD/FHD",
155
+ "genres": ["Mediaset"],
156
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/8/8c/Logo_Boing.png",
157
+ "url": "https://live02-seg.msf.cdn.mediaset.net/live/ch-kb/kb-clr.isml/index.m3u8"
158
+ },
159
+ {
160
+ "id": "cartoonito",
161
+ "title": "Cartoonito",
162
+ "name": "HD/FHD",
163
+ "genres": ["Mediaset"],
164
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Cartoonito_-_Logo_2021.svg/1920px-Cartoonito_-_Logo_2021.svg.png",
165
+ "url": "https://live02-seg.msf.cdn.mediaset.net/live/ch-la/la-clr.isml/index.m3u8"
166
+ },
167
+ {
168
+ "id": "history",
169
+ "title": "History",
170
+ "name": "",
171
+ "genres": ["A+E"],
172
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/history_c.png"
173
+ },
174
+ {
175
+ "id": "comedy-central",
176
+ "title": "Comedy Central",
177
+ "name": "",
178
+ "genres": ["Paramount"],
179
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/comedy-central_c.png"
180
+ },
181
+ {
182
+ "id": "sky-tg-24",
183
+ "title": "Sky TG24",
184
+ "name": "",
185
+ "genres": ["Sky"],
186
+ "poster": "https://images-na.ssl-images-amazon.com/images/I/512j1jeZaHL.png",
187
+ "url": "https://hlslive-web-gcdn-skycdn-it.akamaized.net/TACT/12221/web/master.m3u8?hdnts=st=1701861650~exp=1765449000~acl=/*~hmac=84c9f3f71e57b13c3a67afa8b29a8591ea9ed84bf786524399545d94be1ec04d"
188
+ },
189
+ {
190
+ "id": "tv8",
191
+ "title": "TV8",
192
+ "name": "SD",
193
+ "genres": ["Sky"],
194
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/9/9a/TV8_logo.png",
195
+ "url": "https://hlslive-web-gcdn-skycdn-it.akamaized.net/TACT/11223/tv8web/master.m3u8?hdnea=st=1701861650~exp=1765449000~acl=/*~hmac=84c9f3f71e57b13c3a67afa8b29a8591ea9ed84bf786524399545d94be1ec04d"
196
+ },
197
+ {
198
+ "id": "cielo",
199
+ "title": "Cielo",
200
+ "name": "SD",
201
+ "genres": ["Sky"],
202
+ "poster": "https://static.sky.it/static_clientlibs/skycielo/clientlibs/clientlib-site/resources/images/facebook.jpg",
203
+ "url": "https://hlslive-web-gcdn-skycdn-it.akamaized.net/TACT/11219/cieloweb/master.m3u8?hdnea=st=1701861650~exp=1765449000~acl=/*~hmac=84c9f3f71e57b13c3a67afa8b29a8591ea9ed84bf786524399545d94be1ec04d"
204
+ },
205
+ {
206
+ "id": "sky-cinema-action",
207
+ "title": "Sky Cinema Action",
208
+ "name": "",
209
+ "genres": ["Sky"],
210
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-action_c.png"
211
+ },
212
+ {
213
+ "id": "sky-arte",
214
+ "title": "Sky Arte",
215
+ "name": "",
216
+ "genres": ["Sky"],
217
+ "poster": "https://www.davinciface.com/wp-content/uploads/2022/07/sky_arte_logo-270x270.jpg"
218
+ },
219
+ {
220
+ "id": "sky-atlantic",
221
+ "title": "Sky Atlantic",
222
+ "name": "",
223
+ "genres": ["Sky"],
224
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-atlantic_c.png"
225
+ },
226
+ {
227
+ "id": "sky-cinema-collection",
228
+ "title": "Sky Cinema Collection",
229
+ "name": "",
230
+ "genres": ["Sky"],
231
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-collection_c.png"
232
+ },
233
+ {
234
+ "id": "sky-cinema-comedy",
235
+ "title": "Sky Cinema Comedy",
236
+ "name": "",
237
+ "genres": ["Sky"],
238
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-comedy_c.png"
239
+ },
240
+ {
241
+ "id": "sky-cinema-drama",
242
+ "title": "Sky Cinema Drama",
243
+ "name": "",
244
+ "genres": ["Sky"],
245
+ "poster":"https://i.imgur.com/Z8hr5aR.png"
246
+ },
247
+ {
248
+ "id": "sky-cinema-due",
249
+ "title": "Sky Cinema Due",
250
+ "name": "",
251
+ "genres": ["Sky"],
252
+ "poster": "https://i.imgur.com/xfbZiXs.png"
253
+ },
254
+ {
255
+ "id": "sky-cinema-family",
256
+ "title": "Sky Cinema Family",
257
+ "name": "",
258
+ "genres": ["Sky"],
259
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-family_c.png"
260
+ },
261
+ {
262
+ "id": "sky-cinema-romance",
263
+ "title": "Sky Cinema Romance",
264
+ "name": "",
265
+ "genres": ["Sky"],
266
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-romance_c.png"
267
+ },
268
+ {
269
+ "id": "sky-cinema-suspence",
270
+ "title": "Sky Cinema Suspence",
271
+ "name": "",
272
+ "genres": ["Sky"],
273
+ "poster": "https://i.imgur.com/vS97bNg.png"
274
+ },
275
+ {
276
+ "id": "sky-cinema-uno",
277
+ "title": "Sky Cinema Uno",
278
+ "name": "",
279
+ "genres": ["Sky"],
280
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-1_c.png"
281
+ },
282
+ {
283
+ "id": "sky-crime",
284
+ "title": "Sky Crime",
285
+ "name": "",
286
+ "genres": ["Sky"],
287
+ "poster": "https://i.imgur.com/j2JdQaH.png"
288
+ },
289
+ {
290
+ "id": "sky-documentaries",
291
+ "title": "Sky Documentaries",
292
+ "name": "",
293
+ "genres": ["Sky"],
294
+ "poster": "https://artworks.thetvdb.com/banners/posters/117551-3.jpg"
295
+ },
296
+ {
297
+ "id": "sky-investigation",
298
+ "title": "Sky Investigation",
299
+ "name": "",
300
+ "genres": ["Sky"],
301
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-investigation_c.png"
302
+ },
303
+ {
304
+ "id": "sky-nature",
305
+ "title": "Sky Nature",
306
+ "name": "",
307
+ "genres": ["Sky"],
308
+ "poster":"https://search.bus-hit.me/image_proxy?url=https%3A%2F%2Fstatic.wikia.nocookie.net%2Flogosfake%2Fimages%2Fa%2Fad%2FSky_Nature_Generic_ID_2020.png%2Frevision%2Flatest%2Fscale-to-width-down%2F1200%3Fcb%3D20200725184630&h=71ab69ffa3abfe2ce6c20912b44f862adff4f10b9d4d761c18d292b7ffa3e9a9"
309
+ },
310
+ {
311
+ "id": "sky-serie",
312
+ "title": "Sky Serie",
313
+ "name": "",
314
+ "genres": ["Sky"],
315
+ "poster": "https://i.imgur.com/FYvSq5T.png"
316
+ },
317
+ {
318
+ "id": "sky-uno",
319
+ "title": "Sky Uno",
320
+ "name": "",
321
+ "genres": ["Sky"],
322
+ "poster": "https://www.miotvonline.com/wp-content/uploads/2020/09/sky-uno-straming-live-miotv.jpg"
323
+ },
324
+ {
325
+ "id": "sky-sport-24",
326
+ "title": "Sky Sport 24",
327
+ "name": "",
328
+ "genres": ["Sky"],
329
+ "poster": "https://img2.sport-tv-guide.live/images/tv-station-sky-sport24-it-356.png"
330
+
331
+ },
332
+ {
333
+ "id": "sky-sport-golf",
334
+ "title": "Sky Sport Golf",
335
+ "name": "",
336
+ "genres": ["Sky"],
337
+ "poster": "https://search.bus-hit.me/image_proxy?url=https%3A%2F%2Fencrypted-tbn0.gstatic.com%2Fimages%3Fq%3Dtbn%3AANd9GcRQoDZOK798-OYz0E_NAahzde_JW-hLcHK-PjLm0rCXyVVcj_Y%26s&h=4b1b7a276442b52778daf26f745d06f57ff6c0cf401f4d7f3e371a566247f3ef"
338
+ },
339
+ {
340
+ "id": "sky-sport-251",
341
+ "title": "Sky Sport 251",
342
+ "name": "",
343
+ "genres": ["Sky"],
344
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
345
+ },
346
+ {
347
+ "id": "sky-sport-252",
348
+ "title": "Sky Sport 252",
349
+ "name": "",
350
+ "genres": ["Sky"],
351
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
352
+ },
353
+ {
354
+ "id": "sky-sport-253",
355
+ "title": "Sky Sport 253",
356
+ "name": "",
357
+ "genres": ["Sky"],
358
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
359
+ },
360
+ {
361
+ "id": "sky-sport-254",
362
+ "title": "Sky Sport 254",
363
+ "name": "",
364
+ "genres": ["Sky"],
365
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
366
+ },
367
+ {
368
+ "id": "sky-sport-255",
369
+ "title": "Sky Sport 255",
370
+ "name": "",
371
+ "genres": ["Sky"],
372
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
373
+ },
374
+ {
375
+ "id": "sky-sport-256",
376
+ "title": "Sky Sport 256",
377
+ "name": "",
378
+ "genres": ["Sky"],
379
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
380
+ },
381
+ {
382
+ "id": "sky-sport-257",
383
+ "title": "Sky Sport 257",
384
+ "name": "",
385
+ "genres": ["Sky"],
386
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
387
+ },
388
+ {
389
+ "id": "sky-sport-258",
390
+ "title": "Sky Sport 258",
391
+ "name": "",
392
+ "genres": ["Sky"],
393
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
394
+ },
395
+ {
396
+ "id": "sky-sport-259",
397
+ "title": "Sky Sport 259",
398
+ "name": "",
399
+ "genres": ["Sky"],
400
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
401
+ },
402
+ {
403
+ "id": "sky-sport-260",
404
+ "title": "Sky Sport 260",
405
+ "name": "",
406
+ "genres": ["Sky"],
407
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
408
+ },
409
+ {
410
+ "id": "sky-sport-261",
411
+ "title": "Sky Sport 261",
412
+ "name": "",
413
+ "genres": ["Sky"],
414
+ "poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
415
+ },
416
+ {
417
+ "id": "sky-sport-max",
418
+ "title": "Sky Sport Max",
419
+ "name": "",
420
+ "genres": ["Sky"],
421
+ "poster": "https://i.imgur.com/TWl58VI.png"
422
+ },
423
+ {
424
+ "id": "sky-sport-uno",
425
+ "title": "Sky Sport Uno",
426
+ "name": "",
427
+ "genres": ["Sky"],
428
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-sport-1_c.png"
429
+ },
430
+ {
431
+ "id": "sky-sport-f1",
432
+ "title": "Sky Sport F1",
433
+ "name": "",
434
+ "genres": ["Sky"],
435
+ "poster": "https://i1.wp.com/cache.pressmailing.net/thumbnail/story_hires/395b1e2f-a1c6-4cf6-9869-02155da4021f/Sky_F1_Logo.jpg.jpg"
436
+ },
437
+ {
438
+ "id": "sky-sport-motogp",
439
+ "title": "Sky Sport MotoGP",
440
+ "name": "",
441
+ "genres": ["Sky"],
442
+ "poster": "https://img2.sport-tv-guide.live/images/tv-station-sky-sport-motogp-360.png"
443
+ },
444
+ {
445
+ "id": "sky-sport-calcio",
446
+ "title": "Sky Sport Calcio",
447
+ "name": "",
448
+ "genres": ["Sky"],
449
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-sport-2_c.png"
450
+ },
451
+ {
452
+ "id": "sky-sport-arena",
453
+ "title": "Sky Sport Arena",
454
+ "name": "",
455
+ "genres": ["Sky"],
456
+ "poster": "https://img2.sport-tv-guide.live/images/tv-station-sky-sport-arena-354.png"
457
+ },
458
+ {
459
+ "id": "sky-sport-tennis",
460
+ "title": "Sky Sport Tennis",
461
+ "name": "",
462
+ "genres": ["Sky"],
463
+ "poster": "https://pbs.twimg.com/profile_images/1752313472325431296/jr-YrkR6_400x400.png"
464
+ },
465
+ {
466
+ "id": "sky-sport-nba",
467
+ "title": "Sky Sport NBA",
468
+ "name": "",
469
+ "genres": ["Sky"],
470
+ "poster": "https://www.nbareligion.com/wp-content/uploads/2019/09/sky-sport-nba.jpg"
471
+ },
472
+ {
473
+ "id": "dazn-zona-a",
474
+ "title": "DAZN Zona A",
475
+ "name": "",
476
+ "genres": ["DAZN"],
477
+ "poster": "https://i.ytimg.com/vi/0cEfGLq-tz4/maxresdefault.jpg"
478
+ },
479
+ {
480
+ "id": "eurosport-1",
481
+ "title": "Eurosport 1",
482
+ "name": "",
483
+ "genres": ["Warner Bros"],
484
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/eurosport-1_c.png"
485
+ },
486
+ {
487
+ "id": "eurosport-2",
488
+ "title": "Eurosport 2",
489
+ "name": "",
490
+ "genres": ["Warner Bros"],
491
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/eurosport-2_c.png"
492
+ },
493
+ {
494
+ "id": "dmax",
495
+ "title": "DMAX",
496
+ "name": "",
497
+ "genres": ["Warner Bros"],
498
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/d-max_c.png",
499
+ "url": "https://amg16146-wbdi-amg16146c8-samsung-it-1841.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-dmax-samsungit/playlist.m3u8"
500
+ },
501
+ {
502
+ "id": "foodnetwork",
503
+ "title": "Food Network",
504
+ "name": "",
505
+ "genres": ["Warner Bros"],
506
+ "poster":"https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Food_Network_logo.svg/1024px-Food_Network_logo.svg.png",
507
+ "url": "https://amg16146-wbdi-amg16146c3-samsung-it-1836.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-foodnetwork-samsungit/playlist.m3u8"
508
+ },
509
+ {
510
+ "id": "frisbee",
511
+ "title": "Frisbee",
512
+ "name": "",
513
+ "genres": ["Warner Bros"],
514
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/FRISBEE_LOGO_2015.png/1280px-FRISBEE_LOGO_2015.png",
515
+ "url": "https://amg16146-wbdi-amg16146c7-samsung-it-1840.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-frisbee-samsungit/playlist.m3u8"
516
+ },
517
+ {
518
+ "id": "giallo",
519
+ "title": "Giallo",
520
+ "name": "",
521
+ "genres": ["Warner Bros"],
522
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/giallo_c.png",
523
+ "url": "https://amg16146-wbdi-amg16146c5-samsung-it-1838.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-giallo-samsungit/playlist.m3u8"
524
+ },
525
+ {
526
+ "id": "hgtv",
527
+ "title": "HGTV",
528
+ "name": "",
529
+ "genres": ["Warner Bros"],
530
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/HGTV_2010.svg/1920px-HGTV_2010.svg.png",
531
+ "url": "https://amg16146-wbdi-amg16146c9-samsung-it-1842.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-hgtv-samsungit/playlist.m3u8"
532
+ },
533
+ {
534
+ "id": "k2",
535
+ "title": "K2",
536
+ "name": "",
537
+ "genres": ["Warner Bros"],
538
+ "poster": "https://upload.wikimedia.org/wikipedia/it/thumb/7/70/K2_logo_%282013%29.svg/800px-K2_logo_%282013%29.svg.png",
539
+ "url": "https://amg16146-wbdi-amg16146c6-samsung-it-1839.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-k2-samsungit/playlist.m3u8"
540
+ },
541
+ {
542
+ "id": "nove",
543
+ "title": "Nove",
544
+ "name": "",
545
+ "genres": ["Warner Bros"],
546
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/nove_c.png",
547
+ "url": "https://amg16146-wbdi-amg16146c1-samsung-it-1831.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-nove-samsungit/playlist.m3u8"
548
+ },
549
+
550
+ {
551
+ "id": "realtime",
552
+ "title": "Real Time",
553
+ "name": "",
554
+ "genres": ["Warner Bros"],
555
+ "poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/real-time_c.png",
556
+ "url": "https://amg16146-wbdi-amg16146c2-samsung-it-1835.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-realtime-samsungit/playlist.m3u8"
557
+ },
558
+ {
559
+ "id": "supertennis",
560
+ "title": "Super Tennis",
561
+ "name": "",
562
+ "genres": ["FIT"],
563
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/0/02/SUPERTENNIS_HD.png",
564
+ "url": "https://live-embed.supertennix.hiway.media/restreamer/supertennix_client/gpu-a-c0-16/restreamer/rtmp/hls/h24_supertennix/manifest.m3u8"
565
+ },
566
+ {
567
+ "id": "solocalcio",
568
+ "title": "Solo Calcio",
569
+ "name": "",
570
+ "genres": ["Sportitalia"],
571
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/SI_Live_24_logo_%282019%29.svg/1280px-SI_Live_24_logo_%282019%29.svg.png",
572
+ "url": "https://di-kzbhv8pw.vo.lswcdn.net/sportitalia/sisolocalcio/playlist.m3u8"
573
+ },
574
+ {
575
+ "id": "sportitalia",
576
+ "title": ["Sportitalia"],
577
+ "name": "",
578
+ "genres": ["Sportitalia"],
579
+ "poster": "https://upload.wikimedia.org/wikipedia/en/5/55/Sportitalia.jpg",
580
+ "url": "https://di-kzbhv8pw.vo.lswcdn.net/sportitalia/sihd/playlist.m3u8"
581
+ },
582
+ {
583
+ "id": "sportitalia24",
584
+ "title": "Sportitalia 24",
585
+ "name": "",
586
+ "genres": ["Sportitalia"],
587
+ "poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/SI_Live_24_logo_%282019%29.svg/1280px-SI_Live_24_logo_%282019%29.svg.png",
588
+ "url": "https://di-kzbhv8pw.vo.lswcdn.net/sportitalia/sihd/playlist.m3u8"
589
+ },
590
+ {
591
+ "id": "rsi-la-2",
592
+ "title": "RSI LA 2",
593
+ "name": "",
594
+ "genres": ["RSI"],
595
+ "poster": "https://livehere.one/img/rsi.png"
596
+ },
597
+ {
598
+ "id": "baby-shark-tv",
599
+ "title": "Baby Shark TV",
600
+ "name": "",
601
+ "genres": ["Rakuten"],
602
+ "poster": "https://flxt.tmsimg.com/assets/p19459897_b_v13_aa.jpg",
603
+ "url": "https://c0c65b821b3542c3a4dca92702f59944.mediatailor.us-east-1.amazonaws.com/v1/master/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_BabySharkTV/playlist.m3u8?ads.content_classification=6&ads.device_lmt=1&ads.device_make=&ads.device_model=&ads.device_type=web&ads.device_year=&ads.env=prod&ads.gdpr_consent=&ads.market=it&ads.player_height=&ads.player_width=&ads.pod_type=playerpage_midroll&ads.ppid=&ads.rtv_content_id=3623&ads.rtv_content_language=eng&ads.rtvid=271861&ads.streaming_id=17ded124-30eb-47bc-ab57-ddfce3a16599&ads.user_type=visitor&ads.wurl_channel=696"
604
+ },
605
+ {
606
+ "id": "adrenaline-movies",
607
+ "title": "Rakuten Adrenaline Movies",
608
+ "name": "",
609
+ "genres": ["Rakuten"],
610
+ "poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBC11000050E_20231213T033148SQUARE.png_20231213033148.png",
611
+ "url": "https://minerva-fullmoon-1-eu.plex.wurl.tv/4300.m3u8"
612
+ },
613
+ {
614
+ "id": "bizzarro-movies",
615
+ "title": "Bizzarro Movies",
616
+ "name": "",
617
+ "genres": ["Rakuten"],
618
+ "poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBA3300024IU_20240214T034959SQUARE.png_20240214034959.png",
619
+ "url": "https://minerva-bizzarromovies-1-eu.plex.wurl.tv/4300.m3u8"
620
+ },
621
+ {
622
+ "id": "cinema-italiano",
623
+ "title": "Cinema Italiano",
624
+ "name": "",
625
+ "genres": ["Rakuten"],
626
+ "poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBA33000238E_20240313T074122SQUARE.png",
627
+ "url": "https://minerva-cinemasegreto-1-eu.plex.wurl.tv/4300.m3u8"
628
+ },
629
+ {
630
+ "id": "le-vite-degli-altri",
631
+ "title": "Le Vite Degli Altri",
632
+ "name": "",
633
+ "genres": ["Rakuten"],
634
+ "poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBD3200002DU_20230913T031625SQUARE.png_20230913031625.png",
635
+ "url": "https://amg02512-nexodigital-amg02512c2-wedotv-eu-869.playouts.now.amagi.tv/playlist/amg02512-nexodigital-levitedeglialtri-wedotveu/playlist.m3u8"
636
+ },
637
+ {
638
+ "id": "dark-matter",
639
+ "title": "Dark Matter",
640
+ "name": "",
641
+ "genres": ["Rakuten"],
642
+ "poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBC400001LX_20220404T005859SQUARE.png_20220404005901.png",
643
+ "url": "https://d39g1vxj2ef6in.cloudfront.net/v1/master/3fec3e5cac39a52b2132f9c66c83dae043dc17d4/prod-rakuten-stitched/master.m3u8?ads.xumo_channelId=88883020&ads.xumo_contentId=3480"
644
+ },
645
+ {
646
+ "id": "cine-western",
647
+ "title": "Cine Western",
648
+ "name": "",
649
+ "genres": ["Rakuten"],
650
+ "poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBB20000072M_20240214T035001SQUARE.png_20240214035002.png",
651
+ "url": "https://minerva-wp-1-eu.plex.wurl.tv/4300.m3u8"
652
+ },
653
+ {
654
+ "id": "serie-crime",
655
+ "title": "Serie Crime",
656
+ "name": "",
657
+ "genres": ["Rakuten"],
658
+ "poster": "https://images-2.rakuten.tv/storage/global-live-channel/translation/artwork-negative/0e0a6638-7c4c-4065-82d7-a34d818388ee-width500.png",
659
+ "url": "https://rakuten-seriecrime-6-it.xiaomi.wurl.tv/4300.m3u8"
660
+ },
661
+ {
662
+ "id": "filmrise-sci-fi",
663
+ "title": "Filmrise Sci-Fi",
664
+ "name": "",
665
+ "genres": ["Rakuten"],
666
+ "poster": "https://images-3.rakuten.tv/storage/global-live-channel/translation/artwork_negative/ba0fa0a9-7e17-497e-abcc-9405dbb3a7f5-filmrise-sci-fi-1643623368-quality100.png",
667
+ "url": "https://d39g1vxj2ef6in.cloudfront.net/v1/master/3fec3e5cac39a52b2132f9c66c83dae043dc17d4/prod-rakuten-stitched/master.m3u8?ads.xumo_channelId=9991764"
668
+ },
669
+ {
670
+ "id": "doctor-who",
671
+ "title": "Doctor Who",
672
+ "name": "",
673
+ "genres": ["Rakuten"],
674
+ "poster": "https://images.pluto.tv/channels/62e7f8db27ce19000732d1aa/colorLogoPNG.png",
675
+ "url": "https://bbceu-doctorwho-1-it.rakuten.wurl.tv/3000.m3u8"
676
+ },
677
+ {
678
+ "id": "bbc-drama",
679
+ "title": "BBC Drama",
680
+ "name": "",
681
+ "genres": ["Rakuten"],
682
+ "poster": "https://images.pluto.tv/channels/62e7fa5ab5062e0007dcf97d/colorLogoPNG.png",
683
+ "url": "https://bbceu-bbcdrama-2-it.rakuten.wurl.tv/3000.m3u8"
684
+ },
685
+ {
686
+ "id": "documentari",
687
+ "title": "Documentari (Grandi Documentari)",
688
+ "name": "",
689
+ "genres": ["Rakuten"],
690
+ "poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBC35000016T_20230208T013151SQUARE.png_20230208013152.png",
691
+ "url": "https://videosolutions-wedobigstories-rakuten.amagi.tv/playlist1080p.m3u8"
692
+ },
693
+ {
694
+ "id": "house-of-docs",
695
+ "title": "House of Docs",
696
+ "name": "",
697
+ "genres": ["Rakuten"],
698
+ "poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBD1100001B7_20230412T042554SQUARE.png_20230412042554.png",
699
+ "url": "https://amg02512-nexodigital-amg02512c1-wedotv-eu-871.playouts.now.amagi.tv/playlist/amg02512-nexodigital-houseofdocs-wedotveu/playlist.m3u8"
700
+ },
701
+ {
702
+ "id": "pluto-matrimoni",
703
+ "title": "Pluto TV Matrimoni",
704
+ "name": "",
705
+ "genres": ["Pluto"],
706
+ "poster": "https://images.pluto.tv/channels/661f8f2506839f0008b864e9/colorLogoPNG.png",
707
+ "url": "http://stitcher.pluto.tv/v1/stitch/embed/hls/channel/661f8f2506839f0008b864e9/master.m3u8?deviceId=0&deviceModel=samsung&deviceVersion=0&appVersion=0&deviceType=samsung&deviceMake=samsung&deviceDNT=true"
708
+ },
709
+ {
710
+ "id": "the-asylum",
711
+ "title": "The Asylum",
712
+ "name": "",
713
+ "genres": ["Pluto"],
714
+ "poster": "https://images.pluto.tv/channels/62e8d5369e48940007fc1dc1/colorLogoPNG.png",
715
+ "url": "http://stitcher.pluto.tv/v1/stitch/embed/hls/channel/62e8d5369e48940007fc1dc1/master.m3u8?deviceType=samsung-tvplus&deviceMake=samsung&deviceModel=samsung&deviceVersion=unknown&appVersion=unknown&deviceLat=0&deviceLon=0&deviceDNT=%7BTARGETOPT%7D&deviceId=%7BPSID%7D&advertisingId=%7BPSID%7D&us_privacy=1YNY&samsung_app_domain=%7BAPP_DOMAIN%7D&samsung_app_name=%7BAPP_NAME%7D&profileLimit=&profileFloor=&embedPartner=samsung-tvplus"
716
+ },
717
+ {
718
+ "id": "western",
719
+ "title": "Western",
720
+ "name": "",
721
+ "genres": ["Pluto"],
722
+ "poster": "https://images.pluto.tv/channels/62e7fb67478a5b0007e6c50c/colorLogoPNG.png",
723
+ "url": "http://stitcher.pluto.tv/v1/stitch/embed/hls/channel/62e7fb67478a5b0007e6c50c/master.m3u8?deviceType=samsung-tvplus&deviceMake=samsung&deviceModel=samsung&deviceVersion=unknown&appVersion=unknown&deviceLat=0&deviceLon=0&deviceDNT=%7BTARGETOPT%7D&deviceId=%7BPSID%7D&advertisingId=%7BPSID%7D&us_privacy=1YNY&samsung_app_domain=%7BAPP_DOMAIN%7D&samsung_app_name=%7BAPP_NAME%7D&profileLimit=&profileFloor=&embedPartner=samsung-tvplus"
724
+ },
725
+ {
726
+ "id": "consulenze-illegali",
727
+ "title": "Consulenze Illegali",
728
+ "name": "",
729
+ "genres": ["Pluto"],
730
+ "poster": "https://images.pluto.tv/channels/60b9dc99521a1400079bdfba/colorLogoPNG.png",
731
+ "url": "http://stitcher.pluto.tv/v1/stitch/embed/hls/channel/60b9dc99521a1400079bdfba/master.m3u8?deviceType=samsung-tvplus&deviceMake=samsung&deviceModel=samsung&deviceVersion=unknown&appVersion=unknown&deviceLat=0&deviceLon=0&deviceDNT=%7BTARGETOPT%7D&deviceId=%7BPSID%7D&advertisingId=%7BPSID%7D&us_privacy=1YNY&samsung_app_domain=%7BAPP_DOMAIN%7D&samsung_app_name=%7BAPP_NAME%7D&profileLimit=&profileFloor=&embedPartner=samsung-tvplus"
732
+ }
733
+ ]
734
+ }
735
+
736
+
737
+
738
+
739
+ webru_vary = {
740
+ "sky-cinema-action": "https://webuit.mizhls.ru/lb/calcioXac/index.m3u8",
741
+ "comedy-central": "https://webuit.mizhls.ru/lb/calcioXcomedycentral/index.m3u8",
742
+ "history": "https://webuit.mizhls.ru/lb/calcioXhistory/index.m3u8",
743
+ "sky-arte": "https://webuit.mizhls.ru/lb/calcioXskyarte/index.m3u8",
744
+ "sky-atlantic": "https://webuit.mizhls.ru/lb/calcioXskyatlantic/index.m3u8",
745
+ "sky-cinema-collection": "https://webuit.mizhls.ru/lb/calcioXskycinemacollection/index.m3u8",
746
+ "sky-cinema-comedy": "https://webuit.mizhls.ru/lb/calcioXskycinemacomedy/index.m3u8",
747
+ "sky-cinema-drama": "https://webuit.mizhls.ru/lb/calcioXskycinemadrama/index.m3u8",
748
+ "sky-cinema-due": "https://webuit.mizhls.ru/lb/calcioXskycinemadue/index.m3u8",
749
+ "sky-cinema-family": "https://webuit.mizhls.ru/lb/calcioXskycinemafamily/index.m3u8",
750
+ "sky-cinema-romance": "https://webuit.mizhls.ru/lb/calcioXskycinemaromance/index.m3u8",
751
+ "sky-cinema-suspence": "https://webuit.mizhls.ru/lb/calcioXskycinemasuspence/index.m3u8",
752
+ "sky-cinema-uno": "https://webuit.mizhls.ru/lb/calcioXskycinemauno/index.m3u8",
753
+ "sky-crime": "https://webuit.mizhls.ru/lb/calcioXskycrime/index.m3u8",
754
+ "sky-documentaries": "https://webuit.mizhls.ru/lb/calcioXskydocumentaries/index.m3u8",
755
+ "sky-investigation": "https://webuit.mizhls.ru/lb/calcioXskyinvestigation/index.m3u8",
756
+ "sky-nature": "https://webuit.mizhls.ru/lb/calcioXskynature/index.m3u8",
757
+ "sky-serie": "https://webuit.mizhls.ru/lb/calcioXskyserie/index.m3u8",
758
+ "sky-uno": "https://webuit.mizhls.ru/lb/calcioXskyuno/index.m3u8",
759
+ "sky-sport-24": "https://webuit.mizhls.ru/lb/calcioXskysport24/index.m3u8",
760
+ "sky-sport-golf": "https://webuit.mizhls.ru/lb/calcioXskysportgolf/index.m3u8",
761
+ "sky-sport-251": "https://webuit.mizhls.ru/lb/calcioXskysport251/index.m3u8",
762
+ "sky-sport-253": "https://webuit.mizhls.ru/lb/calcioXskysport253/index.m3u8",
763
+ "sky-sport-max": "https://webuit.mizhls.ru/lb/calcioXskysportmax/index.m3u8",
764
+ "sky-sport-255": "https://webuit.mizhls.ru/lb/calcioXskysport255/index.m3u8",
765
+ "sky-sport-259": "https://webuit.mizhls.ru/lb/calcioXsky259/index.m3u8",
766
+ "sky-sport-252": "https://webuit.mizhls.ru/lb/calcioXskysport252/index.m3u8",
767
+ "sky-sport-254": "https://webuit.mizhls.ru/lb/calcioXskysport254/index.m3u8",
768
+ "sky-sport-256": "https://webuit.mizhls.ru/lb/calcioXskysport256/index.m3u8",
769
+ "sky-sport-257": "https://webuit.mizhls.ru/lb/calcioXskysport257/index.m3u8",
770
+ "sky-sport-258": "https://webuit.mizhls.ru/lb/calcioXsky258/index.m3u8",
771
+ "sky-sport-259": "https://webuit.mizhls.ru/lb/calcioXsky259/index.m3u8",
772
+ "sky-sport-260": "https://webuit.mizhls.ru/lb/calcioXsky260/index.m3u8",
773
+ "sky-sport-261": "https://webuit.mizhls.ru/lb/calcioXsky261/index.m3u8",
774
+ "eurosport-1": "https://webuit.mizhls.ru/lb/calcioXeurosport1/index.m3u8",
775
+ "eurosport-2": "https://webuit.mizhls.ru/lb/calcioXeurosport2/index.m3u8",
776
+ "sky-sport-uno": "https://webuit.mizhls.ru/lb/calcioXskysportuno/index.m3u8",
777
+ "sky-sport-f1": "https://webuit.mizhls.ru/lb/calcioXskysportf1/index.m3u8",
778
+ "sky-sport-motogp": "https://webuit.mizhls.ru/lb/calcioXskysportmotogp/index.m3u8",
779
+ "sky-sport-calcio": "https://webuit.mizhls.ru/lb/calcioXskysportcalcio/index.m3u8",
780
+ "sky-sport-arena": "https://webuit.mizhls.ru/lb/calcioXskysportarena/index.m3u8",
781
+ "sky-sport-tennis": "https://webuit.mizhls.ru/lb/calcioXskysporttennis/index.m3u8",
782
+ "sky-sport-nba": "https://webuit.mizhls.ru/lb/calcioXskysportnba/index.m3u8",
783
+ "dazn-zona-a": "https://webuit.mizhls.ru/lb/calcioXzona/index.m3u8"
784
+ }
785
+
786
+
787
+ webru_dlhd = {
788
+ "sky-sport-tennis": "https://webhdrunns.mizhls.ru/lb/premium576/index.m3u8",
789
+ "sky-sport-uno": "https://webhdrunns.mizhls.ru/lb/premium461/index.m3u8",
790
+ "sky-cinema-collection": "https://webhdrunns.mizhls.ru/lb/premium859/index.m3u8",
791
+ "sky-cinema-romance": "https://webhdrunns.mizhls.ru/lb/premium864/index.m3u8",
792
+ "sky-sport-24": "https://webhdrunns.mizhls.ru/lb/premium869/index.m3u8",
793
+ "sky-sport-254": "https://webhdrunns.mizhls.ru/lb/premium874/index.m3u8",
794
+ "sky-sport-f1": "https://webhdrunns.mizhls.ru/lb/premium577/index.m3u8",
795
+ "sky-sport-arena": "https://webhdrunns.mizhls.ru/lb/premium462/index.m3u8",
796
+ "sky-cinema-uno": "https://webhdrunns.mizhls.ru/lb/premium860/index.m3u8",
797
+ "sky-cinema-family": "https://webhdrunns.mizhls.ru/lb/premium865/index.m3u8",
798
+ "sky-sport-calcio": "https://webhdrunns.mizhls.ru/lb/premium870/index.m3u8",
799
+ "sky-sport-255": "https://webhdrunns.mizhls.ru/lb/premium875/index.m3u8",
800
+ "sky-cinema-action": "https://webhdrunns.mizhls.ru/lb/premium861/index.m3u8",
801
+ "sky-cinema-due": "https://webhdrunns.mizhls.ru/lb/premium866/index.m3u8",
802
+ "sky-sport-251": "https://webhdrunns.mizhls.ru/lb/premium871/index.m3u8",
803
+ "sky-sport-256": "https://webhdrunns.mizhls.ru/lb/premium876/index.m3u8",
804
+ "sky-sport-golf": "https://webhdrunns.mizhls.ru/lb/premium574/index.m3u8",
805
+ "sky-uno": "https://webhdrunns.mizhls.ru/lb/premium881/index.m3u8",
806
+ "sky-cinema-comedy": "https://webhdrunns.mizhls.ru/lb/premium862/index.m3u8",
807
+ "sky-cinema-drama": "https://webhdrunns.mizhls.ru/lb/premium867/index.m3u8",
808
+ "sky-sport-252": "https://webhdrunns.mizhls.ru/lb/premium872/index.m3u8",
809
+ "sky-sport-257": "https://webhdrunns.mizhls.ru/lb/premium877/index.m3u8",
810
+ "sky-sport-motogp": "https://webhdrunns.mizhls.ru/lb/premium575/index.m3u8",
811
+ "sky-sport-football": "https://webhdrunns.mizhls.ru/lb/premium460/index.m3u8",
812
+ "sky-cinema-uno-24": "https://webhdrunns.mizhls.ru/lb/premium863/index.m3u8",
813
+ "sky-cinema-suspence": "https://webhdrunns.mizhls.ru/lb/premium868/index.m3u8",
814
+ "sky-sport-253": "https://webhdrunns.mizhls.ru/lb/premium873/index.m3u8",
815
+ "sky-serie": "https://webhdrunns.mizhls.ru/lb/premium880/index.m3u8"
816
+ }
817
+ extra_sources = {
818
+ "rai-1": ["https://m3u.iranvids.com/rai01/output.m3u8"],
819
+ "rai-2": ["https://m3u.iranvids.com/rai02/output.m3u8"],
820
+ "rai-3": ["https://dash2.antik.sk/live/test_rai_tre_tizen/playlist.m3u8","https://wzstreaming.rai.it/TVlive/liveStream/playlist.m3u8","https://list.iptvcat.com/my_list/s/1f22856f68f2fba4a993c47f47c78a64.m3u8","https://list.iptvcat.com/my_list/s/a372048a4fb440e752aec141aa02885f.m3u8","https://list.iptvcat.com/my_list/s/c7efe17aa0dc8096561967bfb828d4f3.m3u8","https://list.iptvcat.com/my_list/s/2d1f14bbb3370d263d8d3f0d9f5128e0.m3u8"],
821
+ "rete-4":["http://tvit.leicaflorianrobert.dev/mediaset/rete-4/stream.m3u8","https://live02-seg.msf.cdn.mediaset.net/live/ch-r4/r4-clr.isml/index.m3u8"],
822
+ "canale-5":["https://live02-seg.msf.cdn.mediaset.net/live/ch-c5/c5-clr.isml/index.m3u8","http://tvit.leicaflorianrobert.dev/mediaset/canale-5/stream.m3u8"],
823
+ "italia-1":["https://tvit.leicaflorianrobert.dev/mediaset/italia-1/stream.m3u8","https://live02-seg.msf.cdn.mediaset.net/live/ch-i1/i1-clr.isml/index.m3u8"],
824
+ "rai-4k": ["https://list.iptvcat.com/my_list/s/fbf04fbd9694eee71b5af9f12e49538d.m3u8"],
825
+ "rai-news":["https://8e7439fdb1694c8da3a0fd63e4dda518.msvdn.net/rainews1/hls/playlist_mo.m3u8"],
826
+ "topcrime": ["https://tvit.leicaflorianrobert.dev/mediaset/top-crime/stream.m3u8"],
827
+ "mediaset-extra": ["https://tvit.leicaflorianrobert.dev/mediaset/mediaset-extra/stream.m3u8"],
828
+ "focus": ["https://tvit.leicaflorianrobert.dev/mediaset/focus/stream.m3u8"],
829
+ "boing": ["https://tvit.leicaflorianrobert.dev/mediaset/boing/stream.m3u8"],
830
+ "cartoonito": ["https://tvit.leicaflorianrobert.dev/mediaset/cartoonito/stream.m3u8"],
831
+ "tv8": ["https://tvit.leicaflorianrobert.dev/sky/tv8/stream.m3u8"],
832
+ "cielo": ["https://tvit.leicaflorianrobert.dev/sky/cielo/stream.m3u8"],
833
+ "dmax": ["https://tvit.leicaflorianrobert.dev/discovery/dmax/stream.m3u8"],
834
+ "nove": ["https://tvit.leicaflorianrobert.dev/discovery/nove/stream.m3u8"]
835
+ }
836
+
837
+ provider_map = {
838
+ 'SC': 'STREAMINGCOMMUNITY',
839
+ 'SC_FS': 'SC_FAST_SEARCH',
840
+ 'LC': 'LORDCHANNEL',
841
+ 'SW': 'STREAMINGWATCH',
842
+ 'TF_FS': 'TF_FAST_SEARCH',
843
+ 'TF': 'TANTIFILM', # Assuming 'TF' should also be handled
844
+ 'FT': 'FILMPERTUTTI',
845
+ 'AW': 'ANIMEWORLD'
846
+ }
Src/Utilities/info.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from Src.Utilities.loadenv import load_env
2
+ from tmdbv3api import TMDb, Movie, TV
3
+ from Src.Utilities.convert_date import convert_US_date, convert_IT_date
4
+ import Src.Utilities.config as config
5
+ import json
6
+ env_vars = load_env()
7
+ TMDB_KEY = env_vars.get('TMDB_KEY')
8
+
9
+
10
+ def get_info_tmdb(tmbda,ismovie,type):
11
+ tmdb = TMDb()
12
+ tmdb.api_key = f'{TMDB_KEY}'
13
+ tmdb.language = 'it'
14
+ if ismovie == 0:
15
+ tv = TV()
16
+ show= tv.details(tmbda)
17
+ showname = show.name
18
+ if type == "Filmpertutti":
19
+ date= show.first_air_date
20
+ date = date.split("-")[0]
21
+ print("Real date",date)
22
+ return showname,date
23
+ elif type == "StreamingCommunity":
24
+ full_date = show.first_air_date
25
+ date = full_date.split("-")[0]
26
+ print(date)
27
+ return showname,date
28
+ elif type == "StreamingCommunityFS":
29
+ return showname
30
+ elif type == "Tantifilm":
31
+ date = show.first_air_date
32
+ date = date.split("-")[0]
33
+ print("Real date",date)
34
+ return showname,date
35
+ elif type == "TantifilmFS":
36
+ return showname
37
+ elif type == "Cool":
38
+ return showname
39
+ elif type == "LordChannel":
40
+ date = show.first_air_date
41
+ date = date.split("-")[0]
42
+ print("Real date",date)
43
+ return showname,date
44
+ elif type == "StreamingWatch":
45
+ date = show.first_air_date
46
+ date = date.split("-")[0]
47
+ print("Real date",date)
48
+ return showname,date
49
+ elif type == "DDLStream":
50
+ return showname
51
+
52
+ elif ismovie == 1:
53
+ movie = Movie()
54
+ show= movie.details(tmbda)
55
+ showname= show.title
56
+ #Get all release dates
57
+ if type == "Filmpertutti":
58
+ date = show.release_dates
59
+ date = date.split("-")[0]
60
+ #GET US RELEASE DATE because filmpertutti somewhy uses US release date
61
+ return showname,date
62
+ elif type == "StreamingCommunity":
63
+ date = show.release_dates
64
+ date = date.split("-")[0]
65
+ return showname
66
+ elif type == "StreamingCommunityFS":
67
+ return showname
68
+ elif type == "Tantifilm":
69
+ date = show.release_date
70
+ date = date.split("-")[0]
71
+ print("Real date",date)
72
+ return showname,date
73
+ elif type == "TantifilmFS":
74
+ return showname
75
+ elif type == "Cool":
76
+ return showname
77
+ elif type == "LordChannel":
78
+ date = show.release_date
79
+ date = date.split("-")[0]
80
+ print("Real date",date)
81
+ return showname,date
82
+ elif type == "StreamingWatch":
83
+ date = show.release_date
84
+ date = date.split("-")[0]
85
+ print("Real date",date)
86
+ return showname,date
87
+ elif type == "DDLStream":
88
+ return showname
89
+
90
+ async def get_info_imdb(imdb_id, ismovie, type,client):
91
+ resp = await client.get(f'https://api.themoviedb.org/3/find/{imdb_id}?api_key={TMDB_KEY}&language=it&external_source=imdb_id')
92
+ data = resp.json()
93
+ if ismovie == 0:
94
+ showname = data['tv_results'][0]['name']
95
+ if type == "Filmpertutti":
96
+ date= data['tv_results'][0]['first_air_date']
97
+ date = date.split("-")[0]
98
+ print("Real date",date)
99
+ return showname, date
100
+ elif type == "StreamingCommunity":
101
+ date = data['tv_results'][0]['first_air_date']
102
+ date = date.split("-")[0]
103
+ return showname,date
104
+ elif type == "StreamingCommunityFS":
105
+ return showname
106
+ elif type == "Tantifilm":
107
+ date = data['tv_results'][0]['first_air_date']
108
+ date = date.split("-")[0]
109
+ return showname,date
110
+ elif type == "TantifilmFS":
111
+ return showname
112
+ elif type == "Cool":
113
+ return showname
114
+ elif type == "DDLStream":
115
+ return showname
116
+
117
+ elif ismovie == 1:
118
+ showname= data['movie_results'][0]['title']
119
+ if type == "Filmpertutti":
120
+ date = data['movie_results'][0]['release_date']
121
+ date = date.split("-")[0]
122
+ return showname,date
123
+ elif type == "StreamingCommunity":
124
+ date = data['movie_results'][0]['release_date']
125
+ date = date.split("-")[0]
126
+ return showname,date
127
+ elif type == "StreamingCommunityFS":
128
+ return showname
129
+ elif type == "Tantifilm":
130
+ date = data['movie_results'][0]['release_date']
131
+ date = date.split("-")[0]
132
+ return showname,date
133
+ elif type == "Cool":
134
+ return showname
135
+ elif type == "DDLStream":
136
+ return showname
137
+
138
+ async def get_info_kitsu(kitsu_id,client):
139
+ api_url = f'https://kitsu.io/api/edge/anime/{kitsu_id}'
140
+ response = await client.get(api_url)
141
+ data = json.loads(response.text)
142
+ showname = data['data']['attributes']['canonicalTitle']
143
+ date = data['data']['attributes']['startDate']
144
+ return showname,date
145
+
146
+
147
+
148
+
149
+ def is_movie(imdb_id):
150
+ if "tmdb:" in imdb_id:
151
+ imdb_id = imdb_id.replace("tmdb:","")
152
+ if ":" in imdb_id:
153
+ season = imdb_id.split(":")[1]
154
+ episode = imdb_id.split(":")[-1]
155
+ ismovie = 0
156
+ imdb_id = imdb_id.split(":")[0]
157
+ return ismovie,imdb_id,season,episode
158
+ else:
159
+ ismovie = 1
160
+ return ismovie,imdb_id
Src/Utilities/loadenv.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import Src.Utilities.config as config
3
+ MYSTERIUS = config.MYSTERIUS
4
+ dotenv = config.dotenv
5
+ HF = config.HF
6
+ Public_Instance = config.Public_Instance
7
+ #You need to keep dotenv disabled on remote servers
8
+ if dotenv == "1":
9
+ from dotenv import load_dotenv
10
+ load_dotenv(".env")
11
+
12
+
13
+ def load_env():
14
+ env_vars = {}
15
+ env_vars['TMDB_KEY'] = os.getenv('TMDB_KEY')
16
+ if MYSTERIUS == "1":
17
+ env_vars['MYSTERIUS_KEY'] = os.getenv('MYSTERIUS_KEY')
18
+ env_vars['PROXY_CREDENTIALS'] = os.getenv('PROXY')
19
+ env_vars['MEDIAFLOW_PASS'] = os.getenv('MEDIAFLOW_PASS')
20
+ if Public_Instance == "1":
21
+ env_vars['ALTERNATIVE_LINK'] = os.getenv('ALTERNATIVE_LINK')
22
+ return env_vars
config.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "Siti": {
3
+ "StreamingCommunity": {
4
+ "domain": "buzz"
5
+ },
6
+ "Filmpertutti": {
7
+ "domain": "diy"
8
+ },
9
+ "Tantifilm":{
10
+ "domain": "bond"
11
+ },
12
+ "Mysterius":{
13
+ "enabled": "0"
14
+ },
15
+ "LordChannel":{
16
+ "domain":"com"
17
+ },
18
+ "StreamingWatch":{
19
+ "domain":"org"
20
+ },
21
+ "AnimeWorld":{
22
+ "domain":"so"
23
+ }
24
+ },
25
+ "General":{
26
+ "load_env": "1",
27
+ "HOST": "0.0.0.0",
28
+ "PORT": "8080",
29
+ "HF": "0",
30
+ "Public_Instance": "0",
31
+ "MediaProxy": ["https://putinputout-newmediaflow-proxy.hf.space/"]
32
+ }
33
+ }
34
+
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ bs4
2
+ tmdbv3api
3
+ dateparser
4
+ python-dotenv
5
+ fastapi
6
+ uvicorn
7
+ tzdata
8
+ lxml
9
+ slowapi
10
+ curl_cffi
11
+ fake-headers
run.py ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException,Request
2
+ from fastapi.responses import JSONResponse,RedirectResponse,HTMLResponse
3
+ from Src.API.filmpertutti import filmpertutti
4
+ from Src.API.streamingcommunity import streaming_community
5
+ from Src.API.tantifilm import tantifilm
6
+ from Src.API.lordchannel import lordchannel
7
+ from Src.API.streamingwatch import streamingwatch
8
+ import Src.Utilities.config as config
9
+ import logging
10
+ from Src.API.okru import okru_get_url
11
+ from Src.API.animeworld import animeworld
12
+ from Src.Utilities.dictionaries import okru,STREAM,extra_sources,webru_vary,webru_dlhd,provider_map
13
+ from Src.API.epg import tivu, tivu_get,epg_guide,convert_bho_1,convert_bho_2,convert_bho_3
14
+ from Src.API.webru import webru
15
+ from curl_cffi.requests import AsyncSession
16
+ from slowapi import Limiter
17
+ from slowapi.util import get_remote_address
18
+ from slowapi.middleware import SlowAPIMiddleware
19
+ from static.static import HTML
20
+ # Configure logging
21
+ MYSTERIUS = config.MYSTERIUS
22
+ HOST = config.HOST
23
+ PORT = int(config.PORT)
24
+ HF = config.HF
25
+ if HF == "1":
26
+ HF = "🤗️"
27
+ #Cool code to set the hugging face if the service is hosted there.
28
+ else:
29
+ HF = ""
30
+ if MYSTERIUS == "1":
31
+ from Src.API.cool import cool
32
+
33
+ app = FastAPI()
34
+ limiter = Limiter(key_func=get_remote_address)
35
+ app.state.limiter = limiter
36
+ app.add_middleware(SlowAPIMiddleware)
37
+ MANIFEST = {
38
+ "id": "org.stremio.mammamia",
39
+ "version": "1.1.0",
40
+ "catalogs": [
41
+ {
42
+ "type": "tv",
43
+ "id": "tv_channels",
44
+ "name": "TV Channels",
45
+ "behaviorHints": {
46
+ "configurable": True,
47
+ "configurationRequired": True
48
+ },
49
+ "extra": [
50
+ {
51
+ "name": "genre",
52
+ "isRequired": False,
53
+ "options": ["Rai", "Mediaset", "Sky", "Euronews", "La7", "Warner Bros", "FIT", "Sportitalia","RSI","DAZN", "Rakuten", "Pluto", "A+E", "Paramount", "Chill"]
54
+ }
55
+ ]
56
+ }
57
+ ],
58
+ "resources": ["stream", "catalog", "meta"],
59
+ "types": ["movie", "series", "tv"],
60
+ "name": "Mamma Mia",
61
+ "description": "Addon providing HTTPS Streams for Italian Movies, Series, and Live TV! Note that you need to have Kitsu Addon installed in order to watch Anime",
62
+ "logo": "https://creazilla-store.fra1.digitaloceanspaces.com/emojis/49647/pizza-emoji-clipart-md.png"
63
+ }
64
+
65
+
66
+ def respond_with(data):
67
+ resp = JSONResponse(data)
68
+ resp.headers['Access-Control-Allow-Origin'] = '*'
69
+ resp.headers['Access-Control-Allow-Headers'] = '*'
70
+ return resp
71
+
72
+ @app.get('/config')
73
+ def config():
74
+ return RedirectResponse(url="/")
75
+ @app.get('/{config}/manifest.json')
76
+ def addon_manifest():
77
+ return respond_with(MANIFEST)
78
+
79
+ @app.get('/', response_class=HTMLResponse)
80
+ def root(request: Request):
81
+ forwarded_proto = request.headers.get("x-forwarded-proto")
82
+ scheme = forwarded_proto if forwarded_proto else request.url.scheme
83
+ instance_url = f"{scheme}://{request.url.netloc}"
84
+ html_content = HTML.replace("{instance_url}", instance_url)
85
+ return html_content
86
+ async def addon_catalog(type: str, id: str, genre: str = None):
87
+ print(f"Received genre parameter: {genre}")
88
+ if type != "tv":
89
+ raise HTTPException(status_code=404)
90
+
91
+ catalogs = {"metas": []}
92
+
93
+ for channel in STREAM["channels"]:
94
+ if genre and genre not in channel.get("genres", []):
95
+ continue # Skip channels that don't match the selected genre
96
+
97
+ description = f'Watch {channel["title"]}'
98
+ catalogs["metas"].append({
99
+ "id": channel["id"],
100
+ "type": "tv",
101
+ "name": channel["title"],
102
+ "poster": channel["poster"], # Add poster URL if available
103
+ "description": description,
104
+ "genres": channel.get("genres", [])
105
+ })
106
+
107
+ return catalogs
108
+ @app.get('/{config}/catalog/{type}/{id}.json')
109
+ @limiter.limit("5/second")
110
+ async def first_catalog(request: Request,type: str, id: str, genre: str = None):
111
+ catalogs = await addon_catalog(type, id,genre)
112
+ return respond_with(catalogs)
113
+
114
+ @app.get('/{config}/catalog/{type}/{id}/genre={genre}.json')
115
+ async def first_catalog(type: str, id: str, genre: str = None):
116
+ catalogs = await addon_catalog(type, id,genre)
117
+ return respond_with(catalogs)
118
+
119
+ @app.get('/{config}/meta/tv/{id}.json')
120
+ @limiter.limit("20/second")
121
+ async def addon_meta(request: Request,id: str):
122
+ # Find the channel by ID
123
+ channel = next((ch for ch in STREAM['channels'] if ch['id'] == id), None)
124
+
125
+ if not channel:
126
+ raise HTTPException(status_code=404, detail="Channel not found")
127
+ async with AsyncSession() as client:
128
+ if channel["id"] in convert_bho_1 or channel["id"] in convert_bho_2 or channel["id"] in convert_bho_3:
129
+ description,title = await epg_guide(channel["id"],client)
130
+ elif channel["id"] in tivu:
131
+ description = await tivu_get(channel["id"],client)
132
+ print(description)
133
+ title = ""
134
+ else:
135
+ description = f'Watch {channel["title"]}'
136
+ title = ""
137
+ meta = {
138
+ 'meta': {
139
+ 'id': channel['id'],
140
+ 'type': 'tv',
141
+ 'name': channel['name'],
142
+ 'poster': channel['poster'],
143
+ 'posterShape': 'landscape',
144
+ 'description': title + "\n" + description,
145
+ # Additional fields can be added here
146
+ 'background': channel['poster'], # Example of using the same poster as background
147
+ 'logo': channel['poster'],
148
+ 'genres': channel.get('genres', []), # Example of using the same poster as logo
149
+ }
150
+ }
151
+ if 'url' in channel:
152
+ meta['meta']['url'] = channel['url'] # Using the stream URL as a website link
153
+ return respond_with(meta)
154
+
155
+
156
+ @app.get('/{config}/stream/{type}/{id}.json')
157
+ @limiter.limit("5/second")
158
+ async def addon_stream(request: Request,config, type, id,):
159
+ if type not in MANIFEST['types']:
160
+ raise HTTPException(status_code=404)
161
+ streams = {'streams': []}
162
+ config_providers = config.split('|')
163
+ provider_maps = {name: "0" for name in provider_map.values()}
164
+ for provider in config_providers:
165
+ if provider in provider_map:
166
+ provider_name = provider_map[provider]
167
+ provider_maps[provider_name] = "1"
168
+
169
+ async with AsyncSession() as client:
170
+ if type == "tv":
171
+ for channel in STREAM["channels"]:
172
+ if channel["id"] == id:
173
+ i = 0
174
+ if 'url' in channel:
175
+ i = i+1
176
+ streams['streams'].append({
177
+ 'title': f"Server {i} " + f" "+ channel['name'] + " " + channel['title'] ,
178
+ 'url': channel['url']
179
+ })
180
+ if id in okru:
181
+ i = i+1
182
+ channel_url = await okru_get_url(id,client)
183
+ streams['streams'].append({
184
+ 'title': f"Server {i} " + channel['title'] + " OKRU",
185
+ 'url': channel_url
186
+ })
187
+ if id in extra_sources:
188
+ list_sources = extra_sources[id]
189
+ for item in list_sources:
190
+ i = i+1
191
+ streams['streams'].append({'title':f"Server {i} " + channel['title'],'url': item})
192
+ if id in webru_vary:
193
+ i = i+1
194
+ webru_url = await webru(id,"vary",client)
195
+ streams['streams'].append({'title': f"Server {i} " + channel['title'],'url': webru_url})
196
+ if not streams['streams']:
197
+ raise HTTPException(status_code=404)
198
+ return respond_with(streams)
199
+ elif "tt" in id or "tmdb" in id or "kitsu" in id:
200
+ print(f"Handling movie or series: {id}")
201
+ if "kitsu" in id:
202
+ if provider_maps['ANIMEWORLD'] == "1":
203
+ animeworld_urls = await animeworld(id,client)
204
+ if animeworld_urls:
205
+ print(f"AnimeWorld Found Results for {id}")
206
+ i = 0
207
+ for url in animeworld_urls:
208
+ if url:
209
+ if i == 0:
210
+ title = "Original"
211
+ elif i == 1:
212
+ title = "Italian"
213
+ streams['streams'].append({'title': f'{HF}Animeworld {title}', 'url': url})
214
+ i+=1
215
+ else:
216
+ if MYSTERIUS == "1":
217
+ results = await cool(id,client)
218
+ if results:
219
+ print(f"Mysterius Found Results for {id}")
220
+ for resolution, link in results.items():
221
+ streams['streams'].append({'title': f'{HF}Mysterious {resolution}', 'url': link})
222
+ print(provider_maps['STREAMINGCOMMUNITY'])
223
+ if provider_maps['STREAMINGCOMMUNITY'] == "1":
224
+ SC_FAST_SEARCH = provider_maps['SC_FAST_SEARCH']
225
+ url_streaming_community,url_720_streaming_community,quality_sc = await streaming_community(id,client,SC_FAST_SEARCH)
226
+ if url_streaming_community is not None:
227
+ print(f"StreamingCommunity Found Results for {id}")
228
+ if quality_sc == "1080":
229
+ streams['streams'].append({'title': f'{HF}StreamingCommunity 1080p Max', 'url': url_streaming_community})
230
+ streams['streams'].append({'title': f'{HF}StreamingCommunity 720p Max', 'url': url_720_streaming_community})
231
+ else:
232
+ streams['streams'].append({'title': f'{HF}StreamingCommunity 720p Max', 'url': url_streaming_community})
233
+ if provider_maps['LORDCHANNEL'] == "1":
234
+ url_lordchannel,quality_lordchannel = await lordchannel(id,client)
235
+ if quality_lordchannel == "FULL HD" and url_lordchannel != None:
236
+ print(f"LordChannel Found Results for {id}")
237
+ streams['streams'].append({'title': f'{HF}LordChannel 1080p', 'url': url_lordchannel})
238
+ elif url_lordchannel != None:
239
+ print(f"LordChannel Found Results for {id}")
240
+ streams['streams'].append({'title': f'{HF}LordChannel 720p', 'url': url_lordchannel})
241
+ if provider_maps['FILMPERTUTTI'] == "1":
242
+ url_filmpertutti = await filmpertutti(id,client)
243
+ if url_filmpertutti is not None:
244
+ print(f"Filmpertutti Found Results for {id}")
245
+ streams['streams'].append({'title': 'Filmpertutti', 'url': url_filmpertutti})
246
+ if provider_maps['TANTIFILM'] == "1":
247
+ TF_FAST_SEARCH = provider_maps['TF_FAST_SEARCH']
248
+ url_tantifilm = await tantifilm(id,client,TF_FAST_SEARCH)
249
+ if url_tantifilm:
250
+ print(f"TantiFilm Found Results for {id}")
251
+ if not isinstance(url_tantifilm, str):
252
+ for title, url in url_tantifilm.items():
253
+ streams['streams'].append({'title': f'{HF}Tantifilm {title}', 'url': url, 'behaviorHints': {'proxyHeaders': {"request": {"Referer": "https://d000d.com/"}}, 'notWebReady': True}})
254
+ else:
255
+ streams['streams'].append({'title': f'{HF}Tantifilm', 'url': url_tantifilm, 'behaviorHints': {'proxyHeaders': {"request": {"Referer": "https://d000d.com/"}}, 'notWebReady': True}})
256
+ if provider_maps['STREAMINGWATCH'] == "1":
257
+ url_streamingwatch = await streamingwatch(id,client)
258
+ if url_streamingwatch:
259
+ print(f"Streaming Watch Found Results for {id}")
260
+ streams['streams'].append({'title': f'{HF}StreamingWatch 720p', 'url': url_streamingwatch})
261
+ if not streams['streams']:
262
+ raise HTTPException(status_code=404)
263
+
264
+ return respond_with(streams)
265
+
266
+
267
+ if __name__ == '__main__':
268
+ import uvicorn
269
+ uvicorn.run("run:app", host=HOST, port=PORT, log_level="info")
static/__pycache__/static.cpython-311.pyc ADDED
Binary file (9.68 kB). View file
 
static/static.py ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # static.py
2
+
3
+ HTML = """
4
+ <!DOCTYPE html>
5
+ <html>
6
+ <head>
7
+ <meta charset="utf-8">
8
+ <title>Mamma Mia</title>
9
+ <link rel="icon" href="https://creazilla-store.fra1.digitaloceanspaces.com/emojis/49647/pizza-emoji-clipart-md.png" type="image/x-icon">
10
+ <title>Fast Search Example</title>
11
+ <style>
12
+ * {
13
+ box-sizing: border-box;
14
+ }
15
+ body, html {
16
+ margin: 0;
17
+ padding: 0;
18
+ width: 100%;
19
+ height: 100%;
20
+ font-size: 2.2vh;
21
+ font-family: 'Open Sans', Arial, sans-serif;
22
+ color: white;
23
+ background: url('https://i.postimg.cc/m2ZqvpZj/italian-seamless-free-vector-pattern3.png') center center repeat;
24
+ background-size: cover;
25
+ display: flex;
26
+ align-items: flex-start;
27
+ justify-content: center;
28
+ overflow-y: auto;
29
+ }
30
+ #addon {
31
+ background: rgba(0, 0, 0, 0.8);
32
+ padding: 0.5vh;
33
+ border-radius: 10px;
34
+ width: 65vh;
35
+ max-width: 100%;
36
+ text-align: center;
37
+ margin-top: 10vh;
38
+ }
39
+ .logo {
40
+ width: 12vh;
41
+ margin: 0 auto;
42
+ margin-bottom: 3vh;
43
+ margin-top: -3vh;
44
+ }
45
+ .logo img {
46
+ width: 100%;
47
+ height: auto;
48
+ }
49
+ h1, h2, h3 {
50
+ margin: 0;
51
+ text-shadow: 0 0 1vh rgba(0, 0, 0, 0.15);
52
+ }
53
+ h1 {
54
+ font-size: 4.5vh;
55
+ font-weight: 700;
56
+ }
57
+ h2 {
58
+ font-size: 2vh;
59
+ font-weight: normal;
60
+ font-style: italic;
61
+ opacity: 0.8;
62
+ margin-bottom: 20px;
63
+ }
64
+ h3 {
65
+ font-size: 2.2vh;
66
+ margin-bottom: 10px;
67
+ }
68
+ .provider-group {
69
+ display: flex;
70
+ align-items: center; /* Vertically align items */
71
+ justify-content: space-between; /* Spread items across the available space */
72
+ margin-bottom: 2vh;
73
+ background: rgba(255, 255, 255, 0.1);
74
+ padding: 1.5vh;
75
+ border-radius: 5px;
76
+ overflow: hidden;
77
+ width: 100%;
78
+ }
79
+ .provider-group label {
80
+ display: flex;
81
+ align-items: center; /* Align items within label vertically centered */
82
+ white-space: nowrap;
83
+ overflow: hidden;
84
+ text-overflow: ellipsis;
85
+ flex-grow: 1; /* Let the label take as much space as possible */
86
+ font-size: 2.2vh;
87
+ }
88
+ .fast-search {
89
+ display: flex;
90
+ align-items: center; /* Align the Fast Search checkbox vertically centered */
91
+ margin-left: 10px; /* Space between provider and Fast Search */
92
+ }
93
+ .fast-search input[type="checkbox"] {
94
+ margin-right: 0.5vh; /* Space between the checkbox and label */
95
+ width: 3vh;
96
+ height: 3vh;
97
+ }
98
+ .provider-group input[type="checkbox"] {
99
+ margin-right: 1.5vh;
100
+ width: 4vh;
101
+ height: 4vh;
102
+ }
103
+ .parent-container {
104
+ display: flex;
105
+ align-items: center;
106
+ justify-content: space-between;
107
+ width: 100%;
108
+ }
109
+ .contact {
110
+ position: absolute;
111
+ left: 0;
112
+ bottom: 4vh;
113
+ width: 100%;
114
+ text-align: center;
115
+ }
116
+ .contact a {
117
+ font-size: 1.4vh;
118
+ font-style: italic;
119
+ }
120
+ button {
121
+ border: 0;
122
+ outline: 0;
123
+ color: white;
124
+ background: #8A5AAB;
125
+ padding: 1.2vh 3.5vh;
126
+ text-align: center;
127
+ font-family: 'Open Sans', Arial, sans-serif;
128
+ font-size: 2.2vh;
129
+ font-weight: 600;
130
+ cursor: pointer;
131
+ display: block;
132
+ box-shadow: 0 0.5vh 1vh rgba(0, 0, 0, 0.2);
133
+ transition: box-shadow 0.1s ease-in-out;
134
+ width: 80%;
135
+ max-width: 35vh;
136
+ margin: 1vh auto;
137
+ }
138
+ button:hover {
139
+ box-shadow: none;
140
+ }
141
+ button:active {
142
+ box-shadow: 0 0 0 0.5vh white inset;
143
+ }
144
+ #manifestBox {
145
+ margin-top: 2vh;
146
+ padding: 2vh;
147
+ background: rgba(255, 255, 255, 0.2);
148
+ border-radius: 5px;
149
+ display: none;
150
+ text-align: left;
151
+ white-space: pre-wrap;
152
+ }
153
+ #generateManifestButton {
154
+ background: #4CAF50;
155
+ }
156
+ #installButton {
157
+ background: #FF5722;
158
+ }
159
+ #installButton a {
160
+ color: white;
161
+ text-decoration: none;
162
+ }
163
+ #additionalText {
164
+ margin-top: 2vh;
165
+ font-size: 1.8vh;
166
+ text-align: left;
167
+ }
168
+ /* Responsive adjustments for smaller screens */
169
+ @media (max-width: 600px) {
170
+ .provider-group label {
171
+ font-size: 2vh;
172
+ white-space: nowrap;
173
+ }
174
+ }
175
+ </style>
176
+ </head>
177
+ <body>
178
+ <div id="addon">
179
+ <div class="logo">
180
+ <img src="https://creazilla-store.fra1.digitaloceanspaces.com/emojis/49647/pizza-emoji-clipart-md.png" alt="Logo">
181
+ </div>
182
+ <h1 class="name">Mamma Mia</h1>
183
+ <h2 class="version">v1.1.0</h2>
184
+ <div id="additionalText">
185
+ <h2>This addon provides Movie, Series, Anime, and Live TV HTTPS Streams.<br> https://github.com/UrloMythus/MammaMia/</h2>
186
+ </div>
187
+ <p class="description">Configure your providers: Note that if you enable Fast Search results will be less accurate but faster. <br> Filmpertutti and Tantifilm won't work if you are not using a local (on your PC) instance.</p>
188
+ <h3 class="gives">Select Providers:</h3>
189
+ <form class="pure-form" id="provider-form">
190
+ <div class="provider-group">
191
+ <label for="streamingcommunity" class="provider-label">
192
+ <input type="checkbox" id="streamingcommunity"> StreamingCommunity
193
+ </label>
194
+ <span class="fast-search">
195
+ <label for="fast_search_sc">
196
+ <input type="checkbox" id="fast_search_sc"> Fast Search
197
+ </label>
198
+ </span>
199
+ </div>
200
+ <div class="provider-group">
201
+ <label for="lordchannel" class="provider-label">
202
+ <input type="checkbox" id="lordchannel"> LordChannel
203
+ </label>
204
+ </div>
205
+ <div class="provider-group">
206
+ <label for="streamingwatch" class="provider-label">
207
+ <input type="checkbox" id="streamingwatch"> StreamingWatch
208
+ </label>
209
+ </div>
210
+ <div class="provider-group">
211
+ <label for="tantifilm" class="provider-label">
212
+ <input type="checkbox" id="tantifilm"> Tantifilm
213
+ </label>
214
+ <span class="fast-search">
215
+ <label for="fast_search_tf">
216
+ <input type="checkbox" id="fast_search_tf"> Fast Search
217
+ </label>
218
+ </span>
219
+ </div>
220
+ <div class="provider-group">
221
+ <label for="filmpertutti" class="provider-label">
222
+ <input type="checkbox" id="filmpertutti"> Filmpertutti
223
+ </label>
224
+ </div>
225
+ <div class="provider-group">
226
+ <label for="animeworld" class="provider-label">
227
+ <input type="checkbox" id="animeworld"> Animeworld
228
+ </label>
229
+ </div>
230
+ </form>
231
+ <button id="generateManifestButton">Generate Link</button>
232
+ <button id="installButton">INSTALL</button>
233
+ <div id="manifestBox"></div>
234
+ </div>
235
+ <script>
236
+ function generateManifest() {
237
+ let manifest = "|";
238
+ const providers = {
239
+ "streamingcommunity": "SC",
240
+ "fast_search_sc": "SC_FS",
241
+ "lordchannel": "LC",
242
+ "streamingwatch": "SW",
243
+ "tantifilm": "TF",
244
+ "fast_search_tf": "TF_FS",
245
+ "filmpertutti": "FT",
246
+ "animeworld": "AW"
247
+ };
248
+
249
+ for (const id in providers) {
250
+ if (document.getElementById(id).checked) {
251
+ manifest += providers[id] + "|";
252
+ }
253
+ }
254
+ const instanceUrl = "{instance_url}"; // Keep http in the URL
255
+ const manifestUrl = instanceUrl + "/" + manifest + "/" + "manifest.json";
256
+ return manifestUrl;
257
+ }
258
+ document.getElementById('generateManifestButton').addEventListener('click', function() {
259
+ const manifestUrl = generateManifest();
260
+ document.getElementById("manifestBox").style.display = "block";
261
+ document.getElementById("manifestBox").innerText = manifestUrl;
262
+ });
263
+ document.getElementById('installButton').addEventListener('click', function() {
264
+ let manifestUrl = generateManifest();
265
+ manifestUrl = manifestUrl.replace("http://", "");
266
+ manifestUrl = manifestUrl.replace("https://", "");
267
+ const stremioUrl = "stremio://" + manifestUrl;
268
+ window.location.href = stremioUrl;
269
+ });
270
+ </script>
271
+ </body>
272
+ </html>
273
+ """