379 Commits
71 changed files with 5869 additions and 1872 deletions
+121
View File
@@ -0,0 +1,121 @@
name: Conditional Sync Upstream, Build, and Push Docker Image
on:
schedule:
- cron: '0 * * * *' # ogni ora
workflow_dispatch:
push:
branches: [main]
jobs:
sync-build-push:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Backup files and force sync upstream
id: sync
run: |
git config user.name "github-actions"
git config user.email "[email protected]"
git remote get-url upstream || git remote add upstream https://github.com/UrloMythus/MammaMia.git
git fetch upstream
# Controlla se ci sono differenze PRIMA del reset
if git diff --quiet HEAD upstream/main; then
echo "Repository already up to date"
echo "no_change=true" >> $GITHUB_OUTPUT
else
echo "Changes detected, proceeding with sync and build"
backup_dir=".git/backup_files"
mkdir -p "$backup_dir/.github/workflows"
mkdir -p "$backup_dir/Dockerfiles"
if [ -f config.json ]; then
cp config.json "$backup_dir/config.json"
else
echo "⚠️ config.json non trovato, skipping backup"
fi
if [ -f update_domains.py ]; then
cp update_domains.py "$backup_dir/update_domains.py"
else
echo "⚠️ update_domains.py non trovato, skipping backup"
fi
if [ -d .github/workflows ]; then
cp -r .github/workflows/* "$backup_dir/.github/workflows/" || echo "⚠️ No workflows to backup"
else
echo "⚠️ Cartella .github/workflows non trovata, skipping backup"
fi
if [ -d Dockerfiles ]; then
cp -r Dockerfiles/* "$backup_dir/Dockerfiles/" || echo "⚠️ No Dockerfiles to backup"
else
echo "⚠️ Cartella Dockerfiles non trovata, skipping backup"
fi
git checkout main || git checkout -b main
git reset --hard upstream/main
if [ -f "$backup_dir/config.json" ]; then
cp "$backup_dir/config.json" config.json
else
echo "⚠️ File config.json non trovato nel backup, skipping restore"
fi
if [ -f "$backup_dir/update_domains.py" ]; then
cp "$backup_dir/update_domains.py" update_domains.py
else
echo "⚠️ File update_domains.py non trovato nel backup, skipping restore"
fi
mkdir -p .github/workflows
if [ -d "$backup_dir/.github/workflows" ]; then
cp -r "$backup_dir/.github/workflows/"* .github/workflows/ || echo "⚠️ No workflows to restore"
else
echo "⚠️ Backup workflows folder mancante, skipping restore"
fi
mkdir -p Dockerfiles
if [ -d "$backup_dir/Dockerfiles" ]; then
cp -r "$backup_dir/Dockerfiles/"* Dockerfiles/ || echo "⚠️ No Dockerfiles to restore"
else
echo "⚠️ Backup Dockerfiles folder mancante, skipping restore"
fi
git add .
git commit -m "Restore files after forced sync" || echo "No changes needed"
git push origin main --force
echo "no_change=false" >> $GITHUB_OUTPUT
rm -rf "$backup_dir"
fi
- name: Check if build is needed
run: echo "Changes detected, proceed with build."
if: steps.sync.outputs.no_change == 'false'
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
if: steps.sync.outputs.no_change == 'false'
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
if: steps.sync.outputs.no_change == 'false'
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: dula117/mammamia:latest
if: steps.sync.outputs.no_change == 'false'
+37
View File
@@ -0,0 +1,37 @@
name: Update Domains
on:
schedule:
- cron: "0 20 * * *" # Esegui alle 20:00 ogni giorno
workflow_dispatch: # Permette di avviare manualmente il workflow
jobs:
update-domains:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install requests
- name: Update domains in config.json
run: |
python update_domains.py
- name: Commit and push changes
run: |
git config --global user.email "[email protected]"
git config --global user.name "Your Name"
git add config.json
git commit -m "Aggiornamento domini in config.json"
git push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+2
View File
@@ -1,2 +1,4 @@
.env
__pycache__/
.vercel
beamup.json
+10 -8
View File
@@ -1,15 +1,17 @@
# Use an official Python runtime as a parent image
FROM python:3.10-slim-buster
# Set the working directory in the container to /app
FROM python:3.11-slim-bullseye
WORKDIR /app
# Copy the current directory contents into the container at /app
# (including run.py, filmpertutti.py, and requirements.txt)
ADD . /app
# Install any needed packages specified in requirements.txt
RUN apt-get update && \
apt-get install -y tesseract-ocr libtesseract-dev && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir -r requirements.txt
#EXPOSE the port, for now default is 8080 cause it's the only one really allowed by HuggingFace
RUN pip install --no-cache-dir pytesseract
EXPOSE 8080
# Run run.py when the container launches
CMD ["python", "run.py"]
ENTRYPOINT ["python","run.py"]
+2 -10
View File
@@ -1,23 +1,15 @@
Use an official Python runtime as a parent image
FROM python:3.10-slim-buster
FROM python:3.11-slim-bullseye
# Set the working directory in the container to /app
WORKDIR /app
# Install git
RUN apt-get update && apt-get install -y git
# Clone the repository
RUN git clone https://github.com/UrloMythus/MammaMia.git .
# Copy the local config.json file to the container
COPY config.json /app/config.json
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# Expose the port, for now default is 8080 cause it's the only one really allowed by HuggingFace
EXPOSE 8080
# Run run.py when the container launches
CMD ["python", "run.py"]
ENTRYPOINT ["python", "run.py"]
+2 -9
View File
@@ -1,21 +1,14 @@
Use an official Python runtime as a parent image
FROM python:3.10-slim-buster
FROM python:3.11-slim-bullseye
# Set the working directory in the container to /app
WORKDIR /app
# Install git
RUN apt-get update && apt-get install -y git
# Clone the repository
RUN git clone https://github.com/UrloMythus/MammaMia.git .
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# Expose the port, for now default is 8080 cause it's the only one really allowed by HuggingFace
EXPOSE 8080
# Run run.py when the container launches
CMD ["python", "run.py"]
ENTRYPOINT ["python", "run.py"]
+18
View File
@@ -0,0 +1,18 @@
FROM python:3.11-slim-bullseye
WORKDIR /app
RUN apt-get update && \
apt-get install -y git tesseract-ocr libtesseract-dev && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN git clone https://github.com/vitouchiha/MammaMia.git .
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install --no-cache-dir pytesseract
EXPOSE 8080
ENTRYPOINT ["python", "run.py"]
+1
View File
@@ -0,0 +1 @@
web: uvicorn run:app --host=0.0.0.0 --port=$PORT --workers 2
+100 -120
View File
@@ -13,7 +13,7 @@
A Stremio Addon for high quality HTTPS Streams in Italian
A Stremio Addon for HTTPS Streams in Italian
Movies, Series, Anime and Live TV are supported.
@@ -25,23 +25,6 @@ Movies, Series, Anime and Live TV are supported.
While hosting, this project, remember that Filmpertutti uses Mixdrop. Mixdrop only allows seeing the videos from the same IP where they were generated so, if you want to scrape filmpertutti, you will have to host this project locally. Else, you can only scrape other providers.
Hosting your own instance is suggested, but you can use the public instance [linked](https://mammamia-urlo-mammamia.hf.space/) in the About Page of the repo.
# Installation
@@ -69,13 +52,28 @@ Hosting your own instance is suggested, but you can use the public instance [lin
``pip install -r requirements.txt ``
2. Create a .env file and fill it (look at example.env)
2. If you want to use Eurostreaming install those packages:
- Linux (Debian/Ubuntu):
``sudo apt install tesseract-ocr libtesseract-dev ``
- Windows: Install the following library from this [link](https://github.com/UB-Mannheim/tesseract/wiki)
- MacOS: ```brew install tesseract```
Then install the following Python package:
``pip install pytesseract ``
3. Create a .env file and fill it (look at example.env)
4. Modify the config.json as you wish
3. Then to start the Fast API app server just execute:
4. Then to start the Fast API app server just execute:
@@ -97,7 +95,7 @@ Hosting your own instance is suggested, but you can use the public instance [lin
To host this project with Hugging Face, go to the [linked](https://huggingface.co/spaces/MammaMia-Urlo/CloneThisSpace/) page and follow these steps:
To host this project with Hugging Face you will need a Github Account, a Hugging Face account and a [TMDB KEY](https://www.educative.io/courses/movie-database-api-python/set-up-the-credentials).
@@ -107,75 +105,56 @@ To host this project with Hugging Face, go to the [linked](https://huggingface.c
1. Create an Hugging Face Account [here](https://huggingface.co/join)
1. Fork this project and give it a random name.
[!WARNING] The name must not be related to Mamma Mia or mediaflowproxy. Just use a random name
2. Go on the Github of the [Repo](https://github.com/UrloMythus/MammaMia/), click on Fork -> Create New Fork -> Create One.
3. Click on static directory and then click on static.py. Remove the whole content and put:
```
HTML = """
Whatever you want
"""
```
4. Change ```Whatever you want``` with a random phrase (the longer it is, the better it is). If you are too lazy go to this [link](https://www.thewordfinder.com/random-sentence-generator/) and generate it.
5. Click Commit Changes
[!WARNING] Since the main page doesn't exist anymore, you will need to configure MammaMia from /configure endpoint
6. Go to [linked](https://huggingface.co/login?next=%2Fnew-space) page and create a new Public Docker Space.
[!WARNING] The Space must be Public or else you won't be able to access it
7. Go to Settings and in ```Variables and secrets``` section click New Secret. As ```Name``` put TMDB_KEY and as ```Value`` put your TMDB Key
8. Go to Files and click Contribute -> Create a new file
9. In ```Name your file``` field put ```Dockerfile``` . Inside the text box put the content of the Dockerfile called ```Dockerfile-auto-update-no-config``` which you will find inside the /Dockerfiles directory of your Github Fork.
10. Where there is "YourUsername" put your Github username and where there is "YourRepoName" insert the name of the fork.
[!WARNING] Don't remove the final . or it won't work
11. When you are done click Commit Changes to main
12. Go to the README.md in the Files section of your HuggingFace's space and click on it. After that click on edit. After ```pinned: false``` insert this ```app_port: 8080```
13. When you are done click Commit Changes to main
14. You are done!
2. Go to [linked](https://huggingface.co/spaces/MammaMia-Urlo/CloneThisSpace) page and click on three dots on the top (right) part of the screen
3. Click Duplicate this Space
4. Insert TMDB Key and set visibility to Public
5. Clone the Project
6. Go into settings and click on Factory Rebuild.
7. You are done!
8. To install it on Stremio altought, you will need the Direct URL. It can be found on three dots --> Embed This Space --> Direct URL
15. To install it on Stremio you will need the Direct URL. It can be found on three dots --> Embed This Space --> Direct URL
If you do not find it it means your space is Private. To fix so go to Settings and click Set Visibility to Public.
9. How do I handle updates? To update the addon you will have to Factory Rebuild your space (in Settings) and, if there are any changes to config.json, copy them from [here](https://github.com/UrloMythus/MammaMia/blob/main/config.json) to the config.json in your Space, under Files.
10. How can I use Live TV? For now it won't work on public instances. Wait until next update.
Technical Details:
On Hugging Face you are forced to use the 8080 port because it is the only one allowed to send/get network requests. Moreover, remember that load_env and Public Instance need to be disabled in the config.json (it should be by default if you clone the project from HF)
16. How to handle updates: First of all you will need to go to your GitHub Repo and click Sync Changes (without discarding commits). Then go into your HuggingFace Space ---> Settings ---> Factory Reset
@@ -192,6 +171,7 @@ On Hugging Face you are forced to use the 8080 port because it is the only one a
To install this project on [Render](https://render.com/) follow these steps:
[!WARNING] Render might ban your account. Modify the static.py file might help with that
@@ -222,7 +202,7 @@ To install this project on [Render](https://render.com/) follow these steps:
4. Among the other environment variables, put PORT = 8080. This is needed because Render needs the Port given as an environment variable. Remember to put TMDB_KEY as an enviroment variable.
4. Aside from usual enviroment variables you will need to put PORT = 8080.
@@ -244,7 +224,13 @@ To install this project on [Render](https://render.com/) follow these steps:
Remember, load_env and Public Instance needs to be disabled in the config.json
Remember, load_env needs to be disabled in the config.json
# Vercel
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FUrloMythus%2FMammaMia&env=PORT,TMDB_KEY&envDescription=PORT%20(8080)%20and%20API%20KEY%20of%20TMDB&envLink=https%3A%2F%2Fgithub.com%2FUrloMythus%2FMammaMia%2Fblob%2Fmain%2Fexample.env)
@@ -256,21 +242,6 @@ Remember, load_env and Public Instance needs to be disabled in the config.json
# How to add to Stremio
Open your instance URL and configure MammaMia. Once you are done you can click on INSTALL Button. If it doesn't work click on Generate Manifest and copy it. Then paste it in Stremio Search Bar. If you are on Mac or on Web go to addons, click Add an Addon, and paste it there.
# Enviroment Variables
@@ -285,14 +256,12 @@ Open your instance URL and configure MammaMia. Once you are done you can click o
| Enviroment Variable | Value |
|-------------------------|---|
|TMDB_KEY|INSERT YOUR API KEY HERE|
|FORWARDPROXY| "YOURFORWARDPROXY/" |
|PROXY | ["PROXY1","PROXY2"]|
Here is [linked](https://www.themoviedb.org/settings/api) a tutorial about how to get a TMDB KEY
Tutorial to get the TMDB Key: [Tutorial](https://www.themoviedb.org/settings/api)
@@ -306,7 +275,9 @@ Here is [linked](https://www.themoviedb.org/settings/api) a tutorial about how t
In the repo there is a config.json that you can modify to change some aspects of the addon like the domains of the sites. Down here all explained:
In the repo there is a config.json that you can modify to change some aspects of the addon like the domains of the sites. "1" means True, "0" means False
Down here all explained:
@@ -315,17 +286,15 @@ In the repo there is a config.json that you can modify to change some aspects of
| Config | Value |
|-------------------------|---|
| Domain | The domain of the site, must be a string |
|enabled | If the site is enabled or not. "1" means true. "0" means false. Remember, there is no point in enabling filmpertutti on a remote server since it's IP-LOCKED|
|fast_search|"1" for enabled, "0" for disabled. It enables a faster search for supported providers but it is less accurate|
|load_env|Put "1" if enabled, "0" if disabled. It needs to be enabled if you need to load a .env file. On remote hosting services, like Hugging Face or Render, it needs to be disabled. |
|enabled | If the site is enabled or not. This will override user-preference in the configuration|
|**_ForwardProxy| Whether or not to use the ForwardProxy for the specific site.|
|**_Proxy| Whether or not to use the Proxies for the specific site.|
|load_env|It needs to be enabled if you need to load a .env file. On remote hosting services, like Hugging Face or Render, it needs to be disabled. |
|HOST| The host for the Fast API APP|
|PORT| The port for the Fast API APP. Default: 8080 |
For now Mysterius must be kept disabled if you do not know what you are doing.
For now Tantifilm, even if its player is not IP-Locked, does not work on Hugging Face.
|PORT| The port for the Fast API APP. Default: 8080
|level| The level for the logging module. Default: info
|Icon| The Icon for the Add-On.|
|Global_Proxy| Whatever to enable a Global Proxy which will be valid for every request in the add-on.
@@ -333,7 +302,6 @@ Check those links to get the new Domain for the providers.
[FILMPERTUTTI](https://filmpertuttiiii.nuovo.live/)
@@ -341,7 +309,6 @@ Check those links to get the new Domain for the providers.
[TANTIFILM](https://tantinuovo.com/tantifilm-nuovo-indirizzo/)
@@ -349,20 +316,33 @@ Check those links to get the new Domain for the providers.
[LORDCHANNEL](https://t.me/+5MQwrb3eqb81NGI0)
[ANIMEWORLD](https://t.me/AnimeWorldITA2)
[CB01](https://cb01.uno/)
[GUARDAFLIX](https://guardoserie.it/)
[GUARDOSERIE](https://guardoserie.it/)
[EUROSTREAMING](https://eurostreaming-nuovo-indirizzo.online/)
## Mediaflow Proxy
This project uses Mediaflow-Proxy to bypass some protections. You can find instructions about how to install it [here](https://github.com/mhdzumair/mediaflow-proxy/).
## Credits
- Big thanks to [Lovi0](https://github.com/Lovi-0), the creator of StreamingCommunity downloader, for helping me with some aspects of this project.
- This project uses [MediaFlowProxy](https://github.com/mhdzumair/mediaflow-proxy/) in order to be able to play some Live TV channels. Big thanks to his creator, [mhdzumair](https://github.com/mhdzumair)
- This project uses [MediaFlowProxy](https://github.com/mhdzumair/mediaflow-proxy/) in order to be able to play some Live TV channels and to proxy some streams. Big thanks to his creator, [mhdzumair](https://github.com/mhdzumair)
## Disclaimer
This project does not host any illegal content on his servers, if you want any content to be taken down, please contact the actual owners of those sites.
The Live TV sources are taken from online sites, avaiable on the web and indixed by Google.
We hereby issue this notice to inform you that this Add-On just function like an ordinary browser (like your browser) that fetch video files from internet, and do not violate the provisions of the Digital Millennium Copyright Act (DMCA). The Content these extensions may access is not hosted or made avaiable by us or the Stremio application but the websites they are browsing in their autonomous mode. It is sole responsibility of the user and his/her countries' or states' law. If you think they are violating any intellectual property then please contact the actual file hosts not the owners of this repository or the Stremio app.
Thank You.
+155 -69
View File
@@ -1,10 +1,43 @@
from bs4 import BeautifulSoup
import datetime
import logging
import json
from Src.Utilities.info import get_info_kitsu
import Src.Utilities.config as config
import re
from fake_headers import Headers
import Src.Utilities.config as config
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
Icon = config.Icon
Name = config.Name
random_headers = Headers()
proxies = {}
from Src.Utilities.loadenv import load_env
env_vars = load_env()
AW_PROXY = config.AW_PROXY
AW_ForwardProxy = config.AW_ForwardProxy
if AW_PROXY == "1":
import random
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
if AW_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
AW_DOMAIN = config.AW_DOMAIN
months = {
"Gennaio": "January", "Febbraio": "February", "Marzo": "March",
@@ -18,25 +51,136 @@ showname_replace = {
" ": " ",
"Shippuuden": "Shippuden",
" ": "+",
"Solo+Leveling+2": "Solo+Leveling+2:",
"Case+Book": "Casebook",
"-": ""
}
async def get_mp4(anime_url,ismovie,episode,client):
response = await client.get(anime_url,allow_redirects=True, impersonate = "chrome120")
async def security_cookie (response):
match = re.search(r'SecurityAW-([A-Za-z0-9]{2})=([^;]+)', response.text)
if match:
unknown_chars = match.group(1).strip()
Security_Cookie = match.group(2).strip()
cookies = {
f"SecurityAW-{unknown_chars}": Security_Cookie
}
return cookies
async def get_mp4(anime_url,ismovie,episode,client,i,streams):
cookies = {}
if ForwardProxy != "":
response = await client.get(ForwardProxy + anime_url,allow_redirects=True,impersonate = "chrome124",proxies=proxies)
anime_url = f'{AW_DOMAIN}/{response.url.replace(ForwardProxy,"")}?d=1'
response = await client.get(ForwardProxy + anime_url, allow_redirects=True, cookies = cookies,impersonate = "chrome124",proxies=proxies)
cookies = await security_cookie(response)
response = await client.get(ForwardProxy + anime_url, allow_redirects=True, cookies = cookies,impersonate = "chrome124",proxies=proxies)
else:
response = await client.get(ForwardProxy + anime_url, allow_redirects=True, cookies = cookies,impersonate = "chrome124",proxies=proxies)
soup = BeautifulSoup(response.text,'lxml')
if ismovie == 0:
episode_page = soup.find('a', {'data-episode-num':episode })
if episode_page is None:
return None
episode_page = f'https://animeworld.{AW_DOMAIN}{episode_page["href"]}'
response = await client.get(episode_page,allow_redirects=True, impersonate = "chrome120")
return streams
episode_page = f'{AW_DOMAIN}/api/episode/serverPlayerAnimeWorld?id={episode_page["href"].split("/")[-1]}'
response = await client.get(ForwardProxy + episode_page,allow_redirects=True, cookies = cookies,impersonate = "chrome124", proxies=proxies)
if response.status_code == 202:
cookies = await security_cookie(response)
response = await client.get(ForwardProxy + episode_page,allow_redirects=True, cookies = cookies,impersonate = "chrome124", proxies=proxies)
soup = BeautifulSoup(response.text,'lxml')
a_tag = soup.find('a', {'id': 'alternativeDownloadLink', 'class': 'm-1 btn btn-sm btn-primary'})
url = a_tag['href']
a_tag = soup.find('source')
url = a_tag['src']
response = await client.head(url)
if response.status_code == 404:
url = None
return url
if url:
if i == 0:
language = "Original"
elif i == 1:
language = "Italian"
streams['streams'].append({'title': f'{Icon}Animeworld {language}', 'url': url,'behaviorHints': {'bingeGroup': 'animeworld'}})
return streams
async def search(showname,date,ismovie,episode,client,streams):
search_year = date[:4]
headers = random_headers.generate()
link = f'{AW_DOMAIN}/filter?year={search_year}&sort=2&keyword={showname}'
response = await client.get(ForwardProxy + link,allow_redirects=True, impersonate = "chrome124", headers = headers, proxies = proxies)
if response.status_code == 202:
cookies = await security_cookie(response)
response = await client.get(ForwardProxy + link,allow_redirects=True, impersonate = "chrome124", proxies = proxies, headers = headers, cookies = cookies)
else:
cookies = {}
soup = BeautifulSoup(response.text,'lxml')
anime_list = soup.find_all('a', class_=['poster', 'tooltipstered'])
i = 0
for anime in anime_list:
anime_info_url = f'{AW_DOMAIN}/{anime["data-tip"]}'
response = await client.get(ForwardProxy + anime_info_url,allow_redirects=True, impersonate = "chrome124", cookies = cookies, proxies = proxies)
if response.status_code == 202:
cookies = await security_cookie(response)
response = await client.get(ForwardProxy + anime_info_url,allow_redirects=True, impersonate = "chrome124", cookies = cookies, proxies = proxies)
pattern = r'<label>Data di uscita:</label>\s*<span>\s*(.*?)\s*</span>'
match = re.search(pattern, response.text, re.S)
release_date = match.group(1).strip()
for ita, eng in months.items():
release_date = release_date.replace(ita, eng)
release_date_object = datetime.datetime.strptime(release_date, "%d %B %Y")
date_object = datetime.datetime.strptime(date, "%Y-%m-%d")
release_date = release_date_object.strftime("%Y-%m-%d")
if (release_date == date or
release_date == (datetime.datetime.strptime(date, "%Y-%m-%d") + datetime.timedelta(days=1)).strftime("%Y-%m-%d") or
release_date == (datetime.datetime.strptime(date, "%Y-%m-%d") - datetime.timedelta(days=1)).strftime("%Y-%m-%d")):
anime_url = f'{AW_DOMAIN}{anime["href"]}'
streams = await get_mp4(anime_url,ismovie,episode,client,i,streams)
i+=1
logger.info(f"AnimeWorld Found Results for current ID")
return streams
async def animeworld(streams,id,client):
try:
kitsu_id = id.split(":")[1]
ismovie = 1 if len(id.split(":")) == 2 else 0
if ismovie == 1:
episode = None
else:
episode = id.split(":")[2]
showname,date = await get_info_kitsu(kitsu_id,client)
#Format Showname
for key in showname_replace:
if key in showname: # Check if the key is a substring of showname
showname = showname.replace(key, showname_replace[key])
if "Naruto:" in showname:
showname = showname.replace(":", "")
if "’" in showname:
showname = showname.split("’")[0]
if ":" in showname:
showname = showname.split(":")[0]
streams = await search(showname,date,ismovie,episode,client,streams)
return streams
except Exception as e:
logger.warning(f"Animeworld failed {e}")
return streams
async def test_animeworld():
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "kitsu:12:1" # This is an example ID format
results = await animeworld({'streams': []},test_id, client)
print(results)
if __name__ == "__main__":
from curl_cffi.requests import AsyncSession
import asyncio
asyncio.run(test_animeworld())
@@ -72,7 +216,7 @@ async def old_search(showname,date,ismovie,episode,client):
'keyword': showname,
}
response = await client.post(f'https://www.animeworld.{AW_DOMAIN}/api/search/v2', params=params, cookies=cookies, headers=headers,allow_redirects=True, impersonate = "chrome120")
response = await client.post(f'https://www.animeworld.{AW_DOMAIN}/api/search/v2', params=params, cookies=cookies, headers=headers,allow_redirects=True)
data = json.loads(response.text)
final_urls = []
@@ -93,7 +237,7 @@ async def old_search(showname,date,ismovie,episode,client):
params = {
'keyword': showname,
}
response = await client.post(f'https://www.animeworld.{AW_DOMAIN}/api/search/v2', params=params, cookies=cookies, headers=headers, allow_redirects=True, impersonate = "chrome120")
response = await client.post(ForwardProxy + f'https://www.animeworld.{AW_DOMAIN}/api/search/v2', params=params, cookies=cookies, headers=headers, allow_redirects=True, proxies = proxies)
data = json.loads(response.text)
for anime in data["animes"]:
release_date = anime["release"]
@@ -109,61 +253,3 @@ async def old_search(showname,date,ismovie,episode,client):
final_urls.append(final_url)
break
return final_urls
async def search(showname,date,ismovie,episode,client):
search_year = date[:4]
response = await client.get(f'https://www.animeworld.so/filter?year={search_year}&sort=2&keyword={showname}',allow_redirects=True, impersonate = "chrome120")
soup = BeautifulSoup(response.text,'lxml')
anime_list = soup.find_all('a', class_=['poster', 'tooltipstered'])
final_urls = []
for anime in anime_list:
anime_info_url = f'https://www.animeworld.{AW_DOMAIN}/{anime["data-tip"]}'
response = await client.get(anime_info_url,allow_redirects=True, impersonate = "chrome120")
pattern = r'<label>Data di uscita:</label>\s*<span>\s*(.*?)\s*</span>'
match = re.search(pattern, response.text, re.S)
release_date = match.group(1).strip()
for ita, eng in months.items():
release_date = release_date.replace(ita, eng)
release_date = datetime.datetime.strptime(release_date, "%d %B %Y")
release_date = release_date.strftime("%Y-%m-%d")
if release_date == date:
anime_url = f'https://www.animeworld.{AW_DOMAIN}{anime["href"]}'
final_url = await get_mp4(anime_url,ismovie,episode,client)
if final_url:
final_urls.append(final_url)
return final_urls
async def animeworld(id,client):
try:
print(id)
kitsu_id = id.split(":")[1]
ismovie = 1 if len(id.split(":")) == 2 else 0
if ismovie == 1:
episode = None
else:
episode = id.split(":")[2]
showname,date = await get_info_kitsu(kitsu_id,client)
for key in showname_replace:
if key in showname: # Check if the key is a substring of showname
showname = showname.replace(key, showname_replace[key])
if "Naruto:" in showname:
showname = showname.replace(":", "")
final_urls = await search(showname,date,ismovie,episode,client)
return final_urls
except:
print("Animeworld failed")
return None
'''
async def test_animeworld():
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "kitsu:11407" # This is an example ID format
results = await animeworld(test_id, client)
print(results)
if __name__ == "__main__":
from curl_cffi.requests import AsyncSession
import asyncio
asyncio.run(test_animeworld())
'''
+147 -147
View File
@@ -4,8 +4,63 @@ from Src.Utilities.info import is_movie,get_info_tmdb,get_info_imdb
from Src.Utilities.convert import get_TMDb_id_from_IMDb_id
from fake_headers import Headers
import Src.Utilities.config as config
ForwardProxy_list = config.ForwardProxy
ForwardProxy = ForwardProxy_list[0]
from Src.Utilities.loadenv import load_env
from Src.API.extractors.mixdrop import mixdrop
from Src.API.extractors.maxstream import maxstream
from Src.API.extractors.uprot import bypass_uprot
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
CB_DOMAIN = config.CB_DOMAIN
CB_PROXY = config.CB_PROXY
MX_PROXY = config.MX_PROXY
Icon = config.Icon
Name = config.Name
proxies = {}
proxies2 = {}
env_vars = load_env()
import random
import json
from Src.Utilities.mfp import build_mfp
if MX_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies2 = {}
else:
proxies2 = {
"http": proxy,
"https": proxy
}
if CB_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
proxies2 = proxies
CB_ForwardProxy = config.CB_ForwardProxy
MX_ForwardProxy = config.MX_ForwardProxy
if CB_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
ForwardProxy2 = ForwardProxy
if MX_ForwardProxy == "1":
ForwardProxy2 = ForwardProxy
elif MX_ForwardProxy == "1":
ForwardProxy2 = env_vars.get('ForwardProxy')
else:
ForwardProxy2 = ""
ForwardProxy = ""
fake_headers = Headers()
async def get_stayonline(link,client):
@@ -15,85 +70,34 @@ async def get_stayonline(link,client):
'x-requested-with': 'XMLHttpRequest',
}
data = {'id': link.split("/")[-2], 'ref': ''}
response = await client.post('https://stayonline.pro/ajax/linkEmbedView.php', headers=headers, data=data)
response = await client.post('https://stayonline.pro/ajax/linkEmbedView.php', headers=headers, data=data, proxies = proxies2)
real_url = response.json()['data']['value']
print(real_url)
return real_url
async def get_uprot(link,client):
if "msf" in link:
link = link.replace("msf","mse")
headers = fake_headers.generate()
response = await client.get(link, headers=headers, allow_redirects=True, timeout=10)
soup = BeautifulSoup(response.text, "lxml")
maxstream_url = soup.find("a")
maxstream_url = maxstream_url.get("href")
return maxstream_url
async def get_true_link_mixdrop(real_link,client):
try:
import string
headers = fake_headers.generate()
response = await client.get(real_link, headers=headers, allow_redirects=True,timeout = 30)
[s1, s2] = re.search(r"\}\('(.+)',.+,'(.+)'\.split", response.text).group(1, 2)
schema = s1.split(";")[2][5:-1]
terms = s2.split("|")
charset = string.digits + string.ascii_letters
d = dict()
for i in range(len(terms)):
d[charset[i]] = terms[i] or charset[i]
s = 'https:'
for c in schema:
s += d[c] if c in d else c
print(s)
return s
except Exception as e:
return None
async def get_true_link_maxstream(maxstream_url,client):
headers = fake_headers.generate()
# Send a GET request to the Maxstream URL
response = await client.get(maxstream_url, headers=headers, allow_redirects=True, timeout=10)
[s1, s2] = re.search(r"\}\('(.+)',.+,'(.+)'\.split", response.text).group(1, 2)
terms = s2.split("|")
urlset_index = terms.index('urlset')
hls_index = terms.index('hls')
sources_index = terms.index('sources')
result = terms[urlset_index + 1 : hls_index]
reversed_elements = result[::-1]
first_part = terms[hls_index +1 : sources_index]
reversed_first_part = first_part[::-1]
first_url_part = ""
for first_part in reversed_first_part:
if "0" in first_part:
first_url_part += first_part
async def get_maxstream(link,streams,client):
if 'stayonline' in link:
uprot_link = await get_stayonline(link,client)
else:
first_url_part += first_part + "-"
base_url = f"https://{first_url_part}.host-cdn.net/hls/"
if len(reversed_elements) == 1:
final_url = base_url + "," + reversed_elements[0] + ".urlset/master.m3u8"
lenght = len(reversed_elements)
i = 1
for element in reversed_elements:
base_url += element + ","
if lenght == i:
base_url += ".urlset/master.m3u8"
uprot_link = link
maxstream_link = await bypass_uprot(client,uprot_link)
if maxstream_link:
streams = await maxstream(maxstream_link,client,streams,'CB01','',proxies2,ForwardProxy)
else:
i += 1
final_url = base_url
return final_url
if maxstream_link == False:
return streams
else:
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}CB01\n▶️ Please do the captcha at /uprot in order to be able to play this content! \n Remember to refresh the sources!\nIf you recently did the captcha then dont worry, just refresh the sources', 'url': 'https://github.com/UrloMythus/MammaMia', 'behaviorHints': { 'bingeGroup': 'cb01'}})
return streams
async def search_movie(showname,date,client):
try:
showname = showname.replace(" ","+")
showname = showname.replace(" ","+").replace("ò","o").replace("è","e").replace("à","a").replace("ù","u").replace("ì","i")
headers = fake_headers.generate()
headers['Referer'] = 'https://cb01.technology/'
query = f'https://cb01.technology/?s={showname}'
response = await client.get(query,headers=headers)
headers['Referer'] = f'{CB_DOMAIN}/'
query = f'{CB_DOMAIN}/?s={showname}'
response = await client.get(ForwardProxy + query,headers=headers, proxies = proxies)
if response.status_code != 200:
logger.warning(f"CB01 Failed to fetch search results: {response.status_code}")
soup = BeautifulSoup(response.text, 'lxml',parse_only=SoupStrainer('div', class_='card-content'))
cards = soup.find_all('div', class_='card-content')
year_pattern = re.compile(r'(19|20)\d{2}')
@@ -101,29 +105,28 @@ async def search_movie(showname,date,client):
# Find the link inside the current card
link_tag = card.find('h3', class_='card-title').find('a')
href = link_tag['href']
# Find the date span and extract possible years
date_span = card.find('span', style=re.compile('color'))
if date_span:
date_text = date_span.text
date_text = href.split("/")[-2]
# Search for the first occurrence of a year (starting with 19 or 20)
match = year_pattern.search(date_text)
if match:
year = match.group(0)
if year == date : # Check if the year is 2011
print(f"Link: {href}")
if year == date :
return href
except Exception as e:
print(f'MammaMia: Error in search_series cb01: {e}')
logger.warning(f'MammaMia: Error in search_series cb01: {e}')
async def search_series(showname,date,client):
try:
showname = showname.replace(" ","+")
headers = fake_headers.generate()
headers['Referer'] = 'https://cb01.technology/serietv/'
query = f'https://cb01.technology/serietv/?s={showname}'
response = await client.get(query,headers=headers)
headers['Referer'] = f'{CB_DOMAIN}/serietv/'
query = f'{CB_DOMAIN}/serietv/?s={showname}'
response = await client.get(ForwardProxy + query,headers=headers, proxies = proxies)
if response.status_code != 200:
logger.warning(f"CB01 Failed to fetch search results: {response.status_code}")
soup = BeautifulSoup(response.text, 'lxml',parse_only=SoupStrainer('div', class_='card-content'))
cards = soup.find_all('div', class_='card-content')
year_pattern = re.compile(r'(19|20)\d{2}')
@@ -131,7 +134,6 @@ async def search_series(showname,date,client):
# Find the link inside the current card
link_tag = card.find('h3', class_='card-title').find('a')
href = link_tag['href']
# Find the date span and extract possible years
date_span = card.find('span', style=re.compile('color'))
if date_span:
@@ -140,78 +142,75 @@ async def search_series(showname,date,client):
match = year_pattern.search(date_text)
if match:
year = match.group(0)
if year == date : # Check if the year is 2011
print(f"Link: {href}")
if (int(year) - int(date)) == 0 or (int(year)-int(date)) == 1 or (int(year)-int(date)) == -1 : # Check if the year is 2011
return href
except Exception as e:
print(f'MammaMia: Error in search_series cb01: {e}')
logger.warning(f'MammaMia: Error in search_series cb01: {e}')
async def movie_redirect_url(link,client):
async def movie_redirect_url(link,client,MFP,MFP_CREDENTIALS,streams):
headers = fake_headers.generate()
response = client.get(link, headers=headers, allow_redirects=True, timeout=10)
response = await client.get(ForwardProxy + link, headers=headers, allow_redirects=True, timeout=10, proxies = proxies)
# Extract the redirect URL from the HTML
soup = BeautifulSoup(response.text, "lxml",parse_only=SoupStrainer('div', id='iframen1'))
redirect_url = soup.find("div", id="iframen1").get("data-src")
return redirect_url
async def series_redirect_url(link,season,episode,client):
if len(episode) == 1:
episode = f'0{episode}'
soup = BeautifulSoup(response.text, "lxml",parse_only=SoupStrainer('div'))
redirect_url = soup.find("div", id="iframen2").get("data-src")
redirect_url_2 = soup.find("div", id="iframen1").get("data-src")
if "stayonline" in redirect_url:
mixdrop_real_link = await get_stayonline(redirect_url,client)
streams,status = await mixdrop(mixdrop_real_link,client,MFP,MFP_CREDENTIALS,streams,"CB01",proxies,ForwardProxy,"")
if status == False:
streams = await get_maxstream(redirect_url_2,streams,client)
return streams
async def series_search_streams(text,search_text,response_text,headers,season,episode,client,MFP,MFP_CREDENTIALS,streams):
if "A" in text:
captcha = re.search(rf'{search_text}.*?href="([^"]+)',response_text,re.DOTALL)
if captcha:
response = await client.get(ForwardProxy + captcha.group(1), headers = headers, allow_redirects = True, proxies = proxies)
season = season.zfill(2)
match = re.search(rf"(S{season}E{episode}|{season}x{episode}).+?href='([^']+)",response.text)
print(match.group(2))
if match:
streams = await get_maxstream(match.group(2),streams,client)
else:
match = re.search(rf'{season}&#215;{episode}\s*&#8211;\s*<a[^>]*href="[^"]*"[^>]*>[^<]*</a>\s&#8211; <a[^>]*href="[^"]*.*</a>',response_text)
if match:
links = match.group(0)
soup = BeautifulSoup(links,'lxml',parse_only=SoupStrainer('a'))
host_links = soup.find_all('a')
mixdrop_real_link = await get_stayonline(host_links[1]['href'],client)
status = False
streams,status = await mixdrop(mixdrop_real_link,client,MFP,MFP_CREDENTIALS,streams,"CB01",proxies,ForwardProxy,"")
if status == False:
streams = await get_maxstream(host_links[0]['href'],streams,client)
return streams
async def series_redirect_url(link,season,episode,client,MFP,MFP_CREDENTIALS,streams):
episode = episode.zfill(2)
headers = fake_headers.generate()
response = await client.get(link, headers=headers, allow_redirects=True, timeout=10)
response = await client.get(ForwardProxy + link, headers=headers, allow_redirects=True, timeout=10, proxies = proxies)
soup = BeautifulSoup(response.text, "lxml")
seasons_text = soup.find_all('div', class_='sp-head')
for season_text in seasons_text:
text = season_text.text
search_text = season_text.text
if f'STAGIONE' in text and f'{season}' in text:
text = text.replace("STAGIONE","").replace("ITA", "")
if "A" in text:
if len(season) == 1:
season = f'0{season}'
sp_body = season_text.find_next('div', class_='sp-body')
link_tag = sp_body.find('a')
uprot_long = link_tag.get('href')
response = await client.get(uprot_long, headers=headers, allow_redirects=True, timeout=10)
season = "01"
episode = "04"
pattern1 = rf"(?i)\S*?\.{season}x{episode}\S*?\.mkv.*?href=['\"](.*?)['\"]"
pattern2 = rf"\S*\.S{season}E{episode}\S*?\.mkv.*?href=['\"](.*?)['\"]"
match = re.search(pattern1, response.text)
if match:
maxstream_link = match.group(1)
else:
match = re.search(pattern2, response.text)
if match:
maxstream_link = match.group(1)
print(maxstream_link)
if "stayonline" in maxstream_link:
maxstream_link =await get_stayonline(maxstream_link,client)
maxstream_real_link = await get_uprot(maxstream_link,client)
final_url = await get_true_link_maxstream(maxstream_real_link,client)
print(final_url)
else:
pattern = re.compile(r'4&#215;03\s*&#8211;.*?<a href="(.*?)".*?>Maxstream</a>\s*&#8211;.*?<a href="(.*?)".*?>Mixdrop</a>', re.DOTALL)
match = pattern.search(response.text)
maxstream_link = match.group(1)
mixdrop_link = match.group(2)
print(f"Maxstream: {maxstream_link}")
print(f"Mixdrop: {mixdrop_link}")
mixdrop_real_link = await get_stayonline(mixdrop_link,client)
final_url = await get_true_link_mixdrop(mixdrop_real_link,client)
if final_url == None:
if "stayonline" in maxstream_link:
maxstream_link =await get_stayonline(maxstream_link,client)
maxstream_real_link = await get_uprot(maxstream_link,client)
final_url = await get_true_link_maxstream(maxstream_real_link,client)
print(final_url)
streams = await series_search_streams(text,search_text,response.text,headers,season,episode,client,MFP,MFP_CREDENTIALS,streams)
elif f'STAGIONE' in text and 'A' in text.replace("STAGIONE","").replace("ITA", ""):
parts = text.split('STAGIONE ')[1].split(' A ')
num1 = int(parts[0])
num2 = int(parts[1][0])
if int(season) in range(num1,num2):
streams = await series_search_streams(text,search_text,response.text,headers,season,episode,client,MFP,MFP_CREDENTIALS,streams)
return streams
async def cb01(id,client):
async def cb01(streams,id,MFP,MFP_CREDENTIALS,client):
try:
general = is_movie(id)
general = await is_movie(id)
ismovie = general[0]
real_id = general[1]
type = "Cb01"
@@ -223,15 +222,18 @@ async def cb01(id,client):
season = general[2]
episode = general[3]
link = await search_series(showname,date,client)
redirect_url = await series_redirect_url(link,season,episode,client)
streams = await series_redirect_url(link,season,episode,client,MFP,MFP_CREDENTIALS,streams)
return streams
elif ismovie == 1:
season = None
episode = None
link = await search_movie(showname,date,client)
redirect_url = await movie_redirect_url(link,client)
streams = await movie_redirect_url(link,client,MFP,MFP_CREDENTIALS,streams)
return streams
except Exception as e:
print(f'MammaMia: Error in cb01: {e}')
return None
logger.warning(f'MammaMia: Error in cb01: {e}')
return streams
@@ -250,16 +252,14 @@ async def cb01(id,client):
'''
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "tt0158552:1:1" # This is an example ID format
results = await cb01(test_id, client)
test_id = "tt11378946" # This is an example ID format
MFP = "0"
results = await cb01({'streams': []},test_id,MFP,['test','test'],client)
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_animeworld())
'''
+1
View File
@@ -0,0 +1 @@
{}
+15 -10
View File
@@ -1,5 +1,9 @@
from bs4 import BeautifulSoup
import Src.Utilities.config as config
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
tivu = {
"dazn-zona-a": "801",
}
@@ -171,7 +175,7 @@ async def tivu_get(id,client):
description = hour_range + " " + program_name
return description
except Exception as e:
print(e)
logger.warning(f"EPG {e}")
description = f'Watch {id}'
return description
@@ -186,28 +190,28 @@ async def epg_guide(id,client):
elif id in convert_bho_2:
new_id = convert_bho_2[id]
new_id = new_id.replace(" ","%20")
response = await client.get(f"https://mammamia-urlo-boh2.hf.space/{new_id}/now")
response = await client.get(f"https://aimammam-boh2.hf.space/{new_id}/now")
elif id in convert_bho_3:
new_id = convert_bho_3[id]
new_id = new_id.replace(" ","%20")
response = await client.get(f"https://mammamia-urlo-boh3.hf.space/{new_id}/now")
response = await client.get(f"https://aimammam-boh3.hf.space/{new_id}/now")
data = response.json()
description = data['description'].replace("- EPG by epg-guide.com","").replace("No description","")
title = data['title']
print("MammaMia: EPG FOUND")
logger.info("MammaMia: EPG FOUND")
return description,title
except Exception as e:
print(e)
logger.debug(e)
description = f'Watch {id}'
title = ""
return description,title
#async def test_animeworld():
'''
async def test_animeworld():
async with httpx.AsyncClient() as client:
test_id = "rai-news" # Replace with actual ID
test_id = "rai-1" # Replace with actual ID
try:
results = await epg_guide(test_id, client)
print(results)
@@ -216,7 +220,8 @@ async def epg_guide(id,client):
except Exception as e:
print(f"An error occurred: {e}")
#if __name__ == "__main__":
if __name__ == "__main__":
import httpx
import asyncio
asyncio.run(test_animeworld())
'''
+273
View File
@@ -0,0 +1,273 @@
from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
import Src.Utilities.config as config
from fake_headers import Headers
from urllib.parse import quote
from Src.Utilities.loadenv import load_env
from Src.API.extractors.mixdrop import mixdrop
from Src.API.extractors.deltabit import deltabit
from Src.API.extractors.maxstream import maxstream
from Src.API.extractors.uprot import bypass_uprot
import re
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
from bs4 import BeautifulSoup,SoupStrainer
env_vars = load_env()
random_headers = Headers()
try:
import pytesseract
from PIL import Image
except Exception as e:
print("You can not use ES")
import base64
from io import BytesIO
import time
import os
import json
import difflib
import random
from Src.Utilities.mfp import build_mfp
ES_DOMAIN = config.ES_DOMAIN
ES_PROXY = config.ES_PROXY
proxies = {}
if ES_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
ES_ForwardProxy = config.ES_ForwardProxy
if ES_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
async def get_maxstream(uprot_link,streams,language,client):
maxstream_link = await bypass_uprot(client,uprot_link)
if maxstream_link:
streams = await maxstream(maxstream_link,client,streams,'Eurostreaming',language,proxies,ForwardProxy)
else:
if maxstream_link == False:
return streams
else:
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}Eurostreaming\n▶️ Please do the captcha at /uprot in order to be able to play this content! \n Remember to refresh the sources!\nIf you recently did the captcha then dont worry, just refresh the sources', 'url': 'https://github.com/UrloMythus/MammaMia', 'behaviorHints': { 'bingeGroup': 'cb01'}})
return streams
def convert_numbers(base64_data):
image_data = base64.b64decode(base64_data)
image = Image.open(BytesIO(image_data))
custom_config = r'--oem 3 --psm 6 outputbase digits'
number_string = pytesseract.image_to_string(image, config=custom_config)
return number_string.strip()
async def get_numbers(safego_url,client):
headers = random_headers.generate()
headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:146.0) Gecko/20100101 Firefox/146.0'
headers['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
response = await client.get(ForwardProxy + safego_url,headers = headers, proxies = proxies, impersonate = 'chrome')
cookies = (response.cookies.get_dict())
soup = BeautifulSoup(response.text,'lxml',parse_only=SoupStrainer('img'))
numbers = soup.img['src'].split(',')[1]
return numbers,cookies
async def real_page(safego_url,client):
try:
current_directory = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(current_directory, 'cookie.txt')
headers = random_headers.generate()
headers['Origin'] = 'https://safego.cc'
headers['Referer'] = safego_url
headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:146.0) Gecko/20100101 Firefox/146.0'
with open(file_path, 'r') as file:
cookies = file.read()
cookies = json.loads(cookies.replace("'", '"'))
response = await client.post(ForwardProxy + safego_url,headers=headers, cookies = cookies, proxies = proxies)
soup = BeautifulSoup(response.text,'lxml', parse_only=SoupStrainer('a'))
if len(soup)>= 1:
return soup.a['href']
elif 'The requested URL was not found on this server.' not in response.text:
logger.info("Getting numbers")
numbers,cookies = await get_numbers(safego_url,client)
numbers = convert_numbers(numbers)
data = {'captch5': numbers}
response = await client.post(ForwardProxy + safego_url,headers=headers, data=data, cookies = cookies, proxies = proxies)
cap4 = response.headers.get('set-cookie').split(';')[0]
cookies[cap4.split('=')[0]] = cap4.split('=')[1]
with open(file_path, 'w') as file:
file.write(str(cookies))
soup = BeautifulSoup(response.text,'lxml', parse_only=SoupStrainer('a'))
return soup.a['href']
except Exception as e:
logger.info(f"ES{e}")
async def get_host_link(pattern,atag,client):
match = re.search(pattern, atag)
headers = random_headers.generate()
if match:
href_value = match.group(1)
k = 0
while 'safego' not in href_value:
response = await client.get(ForwardProxy + href_value, headers={**headers, 'Range': 'bytes=0-0'}, proxies = proxies)
href_value = response.url
if '%20' in href_value:
href_value = href_value.replace('%20','')
k+=1
if k == 5:
break
href = await real_page(href_value,client)
return href
async def scraping_links(atag,MFP,MFP_CREDENTIALS,client,streams,language):
#Check which hosts are avaiable and extract the links from one of them. Turbovid uses Cloudflare therefore is not avaiable. Maxstream has a captcha.
if "MixDrop" in atag and "DeltaBit" in atag:
pattern = r'<a\s+href="([^"]+)"[^>]*[^>]*>DeltaBit</a>'
href = await get_host_link(pattern,atag,client)
try:
streams = await deltabit(href,client,streams,"Eurostreaming",proxies,ForwardProxy,language,'Deltabit')
except Exception as e:
pattern = r'<a\s+href="([^"]+)"[^>]*rel="noopener"[^>]*>MixDrop</a>'
href = await get_host_link(pattern,atag,client)
streams,status = await mixdrop(href,client,MFP,MFP_CREDENTIALS,streams,"Eurostreaming",proxies,ForwardProxy,language)
return streams
if "MixDrop" in atag and "DeltaBit" not in atag:
try:
pattern = r'<a\s+href="([^"]+)"[^>]*rel="noopener"[^>]*>MixDrop</a>'
href = await get_host_link(pattern,atag,client)
streams,status = await mixdrop(href,client,MFP,MFP_CREDENTIALS,streams,"Eurostreaming",proxies,ForwardProxy,language)
return streams
except Exception as e:
return streams
if 'DeltaBit' in atag and "MixDrop" not in atag:
try:
pattern = r'<a\s+href="([^"]+)"[^>]*rel="noopener"[^>]*>DeltaBit</a>'
href = await get_host_link(pattern,atag,client)
streams = await deltabit(href,client,streams,"Eurostreaming",proxies,ForwardProxy,language,'Deltabit')
return streams
except Exception as e:
return streams
if 'DeltaBit' not in atag and 'MixDrop' not in atag and 'MaxStream' in atag:
try:
pattern = r'<a\s+href="([^"]+)"[^>]*rel="noopener"[^>]*>MaxStream</a>'
match = re.search(pattern, atag)
if match:
href_value = match.group(1)
streams = await get_maxstream(href_value,streams,language,client)
return streams
except Exception as e:
return streams
if 'Deltabit' not in atag and 'Mixdrop' not in atag and 'Maxstream' not in atag and 'Turbovid' in atag:
try:
pattern = r'<a\s+href="([^"]+)"[^>]*rel="noopener"?[^>]*>Turbovid</a>'
href = await get_host_link(pattern,atag,client)
streams = await deltabit(href,client,streams,"Eurostreaming",proxies,ForwardProxy,language,'Turbovid')
return streams
except Exception as e:
return streams
if 'DeltaBit' not in atag and 'MixDrop' not in atag and 'MaxStream' not in atag:
logger.info("Just give up")
return streams
async def episodes_find(description,season,episode,MFP,MFP_CREDENTIALS,client,streams):
t = 0
episode = episode.zfill(2)
pattern = rf'\b{season}&#215;{episode}\s*(.*?)(?=<br\s*/?>)'
match = re.findall(pattern, description)
if match:
for episode_details in match:
if "href" in episode_details:
if t == 0:
language = "\nITA"
elif t == 1:
language = "\nSUB-ITA"
t +=1
streams = await scraping_links(episode_details.split(' – ', 1)[1],MFP,MFP_CREDENTIALS,client,streams,language)
return streams
async def search(showname,date,season,episode,MFP,MFP_CREDENTIALS,client,streams):
headers = random_headers.generate()
showname = showname.replace("'"," ")
response = await client.get(ForwardProxy + f"{ES_DOMAIN}/wp-json/wp/v2/search?search={quote(showname)}&_fields=id", proxies = proxies, headers = headers)
results = response.json()
for i in results:
response = await client.get(ForwardProxy + f"{ES_DOMAIN}/wp-json/wp/v2/posts/{i['id']}?_fields=content,title", proxies = proxies, headers = headers)
if f'ID articolo non valido' in response.text:
continue
description = response.json()
title = description['title']['rendered']
description = description['content']['rendered']
ratio = difflib.SequenceMatcher(None, title, showname).ratio()
if ratio >=0.96 or (showname in title):
streams = await episodes_find(description,season,episode,MFP,MFP_CREDENTIALS,client,streams)
return streams
else:
year_pattern = re.compile(r'(?<!/)(19|20)\d{2}(?!/)')
match = year_pattern.search(description)
if match:
year = match.group(0)
else:
pattern = r'<a\s+href="([^"]+)"[^>]*>Continua a leggere</a>'
match = re.search(pattern, description)
if match:
href_value = match.group(1)
response_2 = await client.get(ForwardProxy + href_value, proxies = proxies, headers = headers)
match = year_pattern.search(response_2.text)
if match:
year = match.group(0)
print(abs(int(year)),int(date))
if abs(int(year) - int(date)) <=1:
streams = await episodes_find(description,season,episode,MFP,MFP_CREDENTIALS,client,streams)
return streams
return streams
async def eurostreaming(streams,id,client,MFP,MFP_CREDENTIALS):
try:
general = await is_movie(id)
ismovie = general[0]
clean_id = general[1]
type = "Eurostreaming"
if ismovie == 0 :
season = str(general[2])
episode = str(general[3])
elif ismovie == 1:
return streams
if "tmdb" in id:
showname,date = get_info_tmdb(clean_id,ismovie,type)
else:
showname,date = await get_info_imdb(clean_id,ismovie,type,client)
logger.info(f"ES {showname}")
streams = await search(showname,date, season,episode,MFP,MFP_CREDENTIALS,client,streams)
return streams
except Exception as e:
logger.warning(f"ES {e}")
return streams
async def test_euro():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await eurostreaming({'streams': []},"tt2701582:7:2",client,"0",['test','test'])
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_euro())
#python3 -m Src.API.eurostreaming
'''tt11950864
'''
+94
View File
@@ -0,0 +1,94 @@
from fake_headers import Headers
import Src.Utilities.config as config
from bs4 import BeautifulSoup,SoupStrainer
import re
import time
import logging
from Src.Utilities.config import setup_logging
from Src.Utilities.eval import eval_solver
level = config.LEVEL
logger = setup_logging(level)
Icon = config.Icon
Name = config.Name
random_headers = Headers()
async def deltabit(page_url,client,streams,site_name,proxies,ForwardProxy,language,extractor):
"""Extract Deltabit URL."""
#Set up some headers
headers = random_headers.generate()
headers2 = random_headers.generate()
#Get the redirected link, so the actual deltabit link.
page_url_response = await client.get(ForwardProxy + page_url,headers={**headers, 'Range': 'bytes=0-0'}, proxies=proxies)
page_url = page_url_response.url
logger.info(f"Page_URl is {page_url}")
#Change the referer and user agent of the generated headers
headers2['referer'] = 'https://safego.cc/'
headers2['user-agent'] = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36'
#Request to the deltabit link
response = await client.get(ForwardProxy + page_url, headers = headers2, allow_redirects = True, proxies = proxies)
page_url = response.url
#Often deltabit redirects to another deltabit link. We need the redirected link to put it in the headers.
origin = page_url.split('/')[2]
headers['origin'] = f'https://{origin}'
headers['referer'] = page_url
headers['user-agent'] = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36'
#We check the page for the data such as hash and fname.
soup = BeautifulSoup(response.text, 'lxml', parse_only=SoupStrainer('input'))
data = {}
for input in soup:
name = input.get('name')
value = input.get('value')
data[name] = value
if extractor == 'Deltabit':
imhuman = ''
elif extractor == 'Turbovid':
imhuman = 'Proceed+to+video'
data['imhuman'] = imhuman
data['referer']= page_url
#We need to wait 2.5/5 seconds or the request will fail
if extractor == 'Deltabit':
time.sleep(2.5)
elif extractor == 'Turbovid':
time.sleep(5)
fname = data['fname']
#Request to the deltabit link
response = await client.post(ForwardProxy + page_url, data = data, headers = headers, proxies = proxies)
if extractor == 'Deltabit':
link = re.findall(r'sources:\s*\["([^"]+)"', response.text, re.DOTALL)
if link:
link = link[0]
elif extractor == 'Turbovid':
link = await eval_solver(response.text,proxies, ForwardProxy, client,r'sources:\s*\["([^"]+)"')
if not link:
i = 0
if not i >= 3:
link,fname = await deltabit(page_url,client,streams,site_name,proxies,ForwardProxy,language,extractor)
i +=1
if link:
streams['streams'].append({'name': f"{Name}{language}",'title': f'{Icon}{site_name}\n▶️ {extractor}\n{fname}', 'url': link, 'behaviorHints': {'bingeGroup': f'{site_name.lower()}'}})
return streams
#Testing
async def test_deltabit():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await deltabit("https://turbovid.me/squc5gdzptgw",client,{'streams': []},'Deltabit', {},"","",'Turbovid')
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_deltabit())
# https://loadm.cam/#cfnqx
+18
View File
@@ -0,0 +1,18 @@
import Src.Utilities.config as config
from Src.Utilities.eval import eval_solver
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
Icon = config.Icon
Name = config.Name
async def dropload(player_link,client,streams,site_name, proxies, ForwardProxy):
url = await eval_solver(player_link, proxies,ForwardProxy, client)
if url:
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}{site_name}\n▶️ Dropload', 'url': url, 'behaviorHints': {'proxyHeaders': {"request": {"User-Agent": 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'}}, 'notWebReady': True, 'bingeGroup': f'{site_name.lower()}'}})
logger.info(f"{site_name} on Dropload found results for the current ID")
return streams
+41
View File
@@ -0,0 +1,41 @@
import Src.Utilities.config as config
Icon = config.Icon
Name = config.Name
import re
from fake_headers import Headers
random_headers = Headers()
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
async def hdplayer(hdplayer,client,streams,Referer,site_name,proxies,ForwardProxy):
headers = random_headers.generate()
response = await client.get(hdplayer, allow_redirects=True, headers = headers)
match = re.search(r'sources:\s*\[\s*\{\s*file\s*:\s*"([^"]*)"', response.text)
url = match.group(1)
if url:
#Fix for Exoplayer which needs .m3u8 in the url to play the file
url = url + ".m3u8"
streams['streams'].append({'name': f"{Name}\n720/1080p",'title': f'{Icon}{site_name}\n ▶️ HDPlayer', 'url': url, 'behaviorHints': {'proxyHeaders': {"request": {"Referer": Referer}}, 'notWebReady': True, 'bingeGroup': f'{site_name.lower()}'}})
logger.info(f"{site_name} on HDPlayer found results for the current ID")
return streams
#Testing
async def test_hdplayer():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await hdplayer("https://hdplayer.gives/embed/udnjutxECQGuwsU",client,{'streams': []},'https://hdplayer.gives/', "StreamingWatch", {},'')
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_hdplayer())
+99
View File
@@ -0,0 +1,99 @@
import requests
from Crypto.Cipher import AES
import json
import re
from rich.prompt import Prompt
from rich.console import Console
from fake_headers import Headers
import Src.Utilities.config as config
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
Icon = config.Icon
Name = config.Name
'''
This script was done mostly by @Arrowar, creator of https://github.com/Arrowar/StreamingCommunity/
It was modified for the use in MammaMia
'''
random_headers = Headers()
KEY = b'kiemtienmua911ca' # 16 byte
IV = b'1234567890oiuytr' # 16 byte
async def fetch_response(client,referer,player_url,url,id, proxies, ForwardProxy):
headers = random_headers.generate()
headers['referer'] = player_url
data = {
'id': id,
'w': '2560',
'h': '1440',
'r': referer,
}
response = await client.get(ForwardProxy + url, headers=headers, params = data, proxies = proxies)
return response.text
def hex_to_bytes(hex_str):
hex_str = re.sub(r'[^0-9a-fA-F]', '', hex_str)
if len(hex_str) % 2 != 0:
hex_str = '0' + hex_str
return bytes(int(hex_str[i:i+2], 16) for i in range(0, len(hex_str), 2))
def decrypt_aes_cbc(ciphertext_bytes, key, iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = cipher.decrypt(ciphertext_bytes)
pad_len = decrypted[-1]
if 1 <= pad_len <= 16:
decrypted = decrypted[:-pad_len]
return decrypted
async def loadm(player_link,client,streams,referer,site_name,proxies,ForwardProxy):
parts = player_link.split('#')
id = parts[1]
player_url = parts[0]
api = player_url + 'api/v1/video'
#It downloads m (crypted informations) from the API"
response_hex = await fetch_response(client,referer,player_url,api,id, proxies, ForwardProxy)
#Convert Hex in Bytes
ciphertext_bytes = hex_to_bytes(response_hex)
#We decrypt AES-CBC encryption with Key,IV and the bytes
decrypted_bytes = decrypt_aes_cbc(ciphertext_bytes, KEY, IV)
decrypted_str = decrypted_bytes.decode('utf-8')
data = json.loads(decrypted_str)
#We get the hls
hls = data['cf']
title = data['title']
m3u8 = data['source']
if hls:
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}{site_name}\n▶️ Loadm\nPlayer One\n{title}', 'url': hls, 'behaviorHints': {'proxyHeaders': {"request": {"Referer": player_url}}, 'notWebReady': True, 'bingeGroup': f'{site_name.lower()}hls'}})
logger.info(f"{site_name} on Loadm found results for player one in the current ID")
if m3u8:
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}{site_name}\n▶️ Loadm\nPlayer Two\n{title}', 'url': m3u8, 'behaviorHints': {'proxyHeaders': {"request": {"Referer": player_url}}, 'notWebReady': True, 'bingeGroup': f'{site_name.lower()}m3u8'}})
logger.info(f"{site_name} on Loadm found results for player two in the current ID")
return streams
#Testing
async def test_loadm():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await loadm("https://loadm.cam/#6wx1p",client,{'streams': []},'guardoserie.live', 'Guardoserie', {},"")
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_loadm())
# https://loadm.cam/#cfnqx
+31
View File
@@ -0,0 +1,31 @@
import Src.Utilities.config as config
from Src.Utilities.eval import eval_solver
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
Icon = config.Icon
Name = config.Name
from fake_headers import Headers
random_headers = Headers()
import re
async def maxstream(url,client,streams,site_name,language,proxies,ForwardProxy):
headers = random_headers.generate()
response = await client.get( ForwardProxy + url, allow_redirects=True, timeout=30, headers = headers, proxies = proxies, impersonate = "chrome")
pattern = r'sources\W+src\W+(.*)",'
match = re.search(pattern,response.text)
if match:
url = match.group(1)
logger.info(f"{site_name} on Maxstream found results for the current ID")
streams['streams'].append({'name': f"{Name}{language}",'title': f'{Icon}{site_name}\n▶️ Maxstream', 'url': url, 'behaviorHints': { 'bingeGroup': f'{site_name.lower()}'}})
return streams
async def test_maxstream():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await maxstream("https://maxstream.video/emvvv/a7wc8bb0h68c",client,{'streams': []},'CB01', {},'')
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_maxstream())
+34
View File
@@ -0,0 +1,34 @@
import Src.Utilities.config as config
Icon = config.Icon
Name = config.Name
from Src.Utilities.mfp import build_mfp
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
from Src.Utilities.eval import eval_solver
async def mixdrop(url,client,MFP,MFP_CREDENTIALS,streams,site_name,proxies,ForwardProxy,language):
"""Extract Mixdrop URL."""
status = False
if "club" in url:
url = url.replace("club", "cv").split("/2")[0]
if "cfd" in url:
url = url.replace("cfd", "cv").replace("emb","e").split("/2")[0]
if MFP == "1":
url = await build_mfp(MFP_CREDENTIALS,url,"Mixdrop",client)
if url and "https%3ANone" not in url:
logger.info(f"{site_name} on Mixdrop found results for the current ID")
status = True
streams['streams'].append({'name': f"{Name} 🕵️‍♂️\n{language}",'title': f'{Icon}{site_name}\n▶️ MixDrop', 'url': url, 'behaviorHints':{'bingeGroup': f'{site_name.lower()}'}})
else:
headers = {"accept-language": "en-US,en;q=0.5"}
url = await eval_solver(url, proxies , ForwardProxy, client,r'MDCore.wurl ?= ?"(.*?)"')
if url:
url = "https:" + url
logger.info(f"{site_name} on Mixdrop found results for the current ID")
status = True
streams['streams'].append({'name': f"{Name}{language}",'title': f'{Icon}{site_name}\n▶️ MixDrop', 'url': url, 'behaviorHints': {'proxyHeaders': {"request": {"User-Agent": 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'}}, 'notWebReady': True, 'bingeGroup': f'{site_name.lower()}'}})
return streams,status
+45
View File
@@ -0,0 +1,45 @@
import Src.Utilities.config as config
from Src.Utilities.eval import eval_solver
import logging
from Src.Utilities.config import setup_logging
from Src.Utilities.mfp import build_mfp
level = config.LEVEL
logger = setup_logging(level)
Icon = config.Icon
Name = config.Name
async def streamhg(link,client,MFP,MFP_CREDENTIALS,streams, site_name, proxies,ForwardProxy):
link = 'https://audinifer.com/e/' + link.split('/e/')[1]
if MFP == '1':
url = await build_mfp(MFP_CREDENTIALS,link,"StreamHG",client)
logger.info(f"{site_name} on StreamHG found results for the current ID")
if url:
status = True
streams['streams'].append({'name': f"{Name} 🕵️‍♂️",'title': f'{Icon}{site_name}\n▶️ StreamHG', 'url': url, 'behaviorHints':{'bingeGroup': f'{site_name.lower()}'}})
else:
status = False
else:
url = await eval_solver(link,proxies, ForwardProxy, client,r'"hls2":"([^"]+)"')
if url:
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}{site_name}\n▶️ StreamHG', 'url': url, 'behaviorHints': {'bingeGroup': f'{site_name.lower()}'}})
logger.info(f"{site_name} on StreamHG found results for the current ID")
status = True
else:
status = False
return streams,status
async def test_streamhg():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await streamhg("https://dhcplay.com/e/zctlgpn3zoll",client,"1",['',''],{'streams': []}, "StreamHG", {},"")
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_streamhg())
+18
View File
@@ -0,0 +1,18 @@
import Src.Utilities.config as config
from Src.Utilities.eval import eval_solver
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
Icon = config.Icon
Name = config.Name
async def supervideo(supervideo_link,client,streams, site_name, proxies,ForwardProxy):
url = await eval_solver(supervideo_link,proxies, ForwardProxy, client,r'file:"(.*?)"')
if url:
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}{site_name}\n▶️ Supervideo', 'url': url, 'behaviorHints': {'bingeGroup': f'{site_name.lower()}'}})
logger.info(f"{site_name} on SuperVideo found results for the current ID")
return streams
+157
View File
@@ -0,0 +1,157 @@
import os
from bs4 import BeautifulSoup,SoupStrainer
import json
import logging
import Src.Utilities.config as config
from Src.Utilities.config import setup_logging
from Src.Utilities.loadenv import load_env
from fake_headers import Headers
random_headers = Headers()
UT_PROXY = config.UT_PROXY
UT_ForwardProxy = config.UT_ForwardProxy
level = config.LEVEL
env_vars = load_env()
import random
logger = setup_logging(level)
#Set up proxies
proxies = {}
if UT_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
if UT_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
url = 'https://uprot.net/msf/r4hcq47tarq8'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Content-Type': 'application/x-www-form-urlencoded',
'Origin': url.split('msf')[0],
'Sec-GPC': '1',
'Connection': 'keep-alive',
'Referer': url,
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-User': '?1',
'DNT': '1',
'Priority': 'u=0, i',
}
async def get_uprot_numbers(client):
try:
response = await client.post(ForwardProxy + url, headers=headers, proxies = proxies, impersonate = 'chrome')
set_cookie = response.headers.get('set-cookie')
parts = set_cookie.split(';')[0].split('=')
key = parts[0]
value = parts[1]
cookies = {
key:value
}
soup = BeautifulSoup(response.text,'lxml',parse_only=SoupStrainer('img'))
img = soup.find('img')['src']
return img,cookies
except Exception as e:
logger.info(f'Uprot failed to generate numbers/cookies: {e}')
return None,None
async def generate_uprot_txt(numbers,cookies,client):
try:
data = {
'captcha': str(numbers),
}
response = await client.post(ForwardProxy + url, cookies=cookies, headers=headers, data=data, proxies = proxies, impersonate = 'chrome')
if response.status_code != 200:
return False
set_cookie = response.headers.get('set-cookie')
parts = set_cookie.split(';')[0].split('=')
key = parts[0]
value = parts[1]
cookies[key] = value
current_directory = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(current_directory, 'uprot.txt')
with open(file_path,'w') as file:
file.write(f'{str(cookies)}\n{str(data)}')
return True
return False
except Exception as e:
logger.info(f'Uprot failed to generate captcha cookie: {e}')
return False
async def find_link(text,client):
soup = BeautifulSoup(text,'lxml',parse_only=SoupStrainer('a'))
a_tags = soup.find_all('a')
max_stream = None
for tag in a_tags:
if 'C O N T I N U E' in tag.text.upper() or 'CONTINUE' in tag.text.upper() :
max_stream = tag['href']
return max_stream
async def get_maxstream_link(text,client):
max_stream = await find_link(text,client)
if max_stream:
redirect = max_stream
time = 0
while 'uprots' in redirect:
response = await client.head(ForwardProxy + max_stream,headers=headers,impersonate = 'chrome', allow_redirects = True, proxies = proxies)
redirect = response.url
time+=1
if time == 10:
return False
max_stream = 'https://maxstream.video/emvvv/' + response.url.split('watchfree/')[1].split('/')[1]
return max_stream
async def bypass_uprot(client,link):
try:
if 'msfi' not in link:
if 'msf' in link:
link = link.replace('msf','mse')
headers2 = random_headers.generate()
headers2['Origin'] = url.split('msf')[0]
headers2['Referer'] = url
response = await client.get(ForwardProxy + link, headers=headers2, impersonate = 'chrome', proxies = proxies)
if response.status_code != 403:
max_stream = await find_link(response.text,client)
else:
logger.info("Uprot blocked the request: 403")
else:
if 'mse' in link:
link = link.replace('mse','msf')
current_directory = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(current_directory, 'uprot.txt')
with open(file_path,'r') as file:
text = file.read()
parts = text.split('\n')
cookies = json.loads(parts[0].replace("'", '"'))
data = json.loads(parts[1].replace("'", '"'))
response = await client.post(ForwardProxy + link, cookies=cookies, headers=headers, data =data, impersonate = 'chrome', proxies = proxies)
if response.status_code != 403:
max_stream = await get_maxstream_link(response.text,client)
if response.status_code == 403:
max_stream = False
return max_stream
except Exception as e:
logger.info(f'Uprot failed: {e}')
if '[Errno 2] No such file or directory' in e:
return None
return False
+2
View File
@@ -0,0 +1,2 @@
{}
{}
+28
View File
@@ -0,0 +1,28 @@
from fake_headers import Headers
import Src.Utilities.config as config
Icon = config.Icon
Name = config.Name
from Src.Utilities.mfp import build_mfp
from fake_headers import Headers
import re
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
random_headers = Headers()
async def uqload(player_link,client,MFP,MFP_CREDENTIALS,streams,site_name,proxies,ForwardProxy):
headers = random_headers.generate()
if MFP == "1":
url = await build_mfp(MFP_CREDENTIALS, player_link, "Uqload",client)
streams['streams'].append({'name': f"{Name} 🕵️‍♂️",'title': f'{Icon}{site_name}\n▶️ Uqload', 'url': url, 'behaviorHints': {'proxyHeaders': {"request": {"User-Agent": 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'}}, 'notWebReady': True, 'bingeGroup': 'guardaflix'}})
return streams
response = await client.get(ForwardProxy + player_link, headers = headers, proxies = proxies)
video_url_match = re.search(r'sources: \["(.*?)"]', response.text)
title = re.search(r'title: "(.*?)"', response.text).group(1)
if video_url_match:
url = video_url_match.group(1)
if url:
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}{site_name}\n▶️ Uqload\n{title}', 'url': url, 'behaviorHints': {'proxyHeaders': {"request": {"User-Agent": 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'}}, 'notWebReady': True, 'bingeGroup': f'{site_name.lower()}'}})
logger.info(f"{site_name} on Uqload found results for the current ID")
return streams
+128
View File
@@ -0,0 +1,128 @@
import Src.Utilities.config as config
Icon = config.Icon
Name = config.Name
import re
from fake_headers import Headers
random_headers = Headers()
import logging
from Src.Utilities.config import setup_logging
from base64 import b64encode,b64decode
level = config.LEVEL
logger = setup_logging(level)
import base64
from bs4 import BeautifulSoup,SoupStrainer
VD_DOMAIN = config.VD_DOMAIN
from curl_cffi.requests import AsyncSession
import json
VD_PROXY = config.VD_PROXY
proxies = {}
if VD_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
VD_ForwardProxy = config.VD_ForwardProxy
if VD_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
VD_DOMAIN = config.VD_DOMAIN
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
# 'Accept-Encoding': 'gzip, deflate, br, zstd',
'Sec-GPC': '1',
'Alt-Used': 'v.vidxgo.co',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'iframe',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'DNT': '1',
'Referer': 'https://altadefinizione.you/',
'Sec-Fetch-Storage-Access': 'none',
'-': '-',
'Priority': 'u=0, i',
}
headers2 = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.9',
'Referer': 'https://v.vidxgo.co/tt34437972',
'Sec-GPC': '1',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'DNT': '1',
'Priority': 'u=4',
}
async def vidxgo_refresh(link,id):
async with AsyncSession() as client:
headers['Referer'] = f'{VD_DOMAIN}/t/{id}'
response = await client.get(ForwardProxy + f'{VD_DOMAIN}/t/{id}', allow_redirects=True, headers = headers2, proxies = proxies)
return response.json()['url'].replace('\\','')
async def vidxgo(link,client,streams,instance_url):
#headers = random_headers.generate()
response = await client.get(ForwardProxy + link, allow_redirects=True, headers = headers, proxies = proxies)
soup = BeautifulSoup(response.text,'lxml',parse_only=SoupStrainer('script'))
scripts = soup.find_all('script')
text = scripts[6]
match = re.search(r"var .+'(.*)',d=atob\('(.*)'",text.text)
if match:
key = match.group(1)
base64_text = match.group(2)
decoded = base64.b64decode(base64_text)
u = bytearray(len(decoded))
for i in range(len(decoded)):
u[i] = decoded[i] ^ ord(key[i % len(key)])
decrypted_code = u.decode('utf-8')
match = re.search(r'currentSrc.+"(https:[^";]+)',decrypted_code)
submatch = re.search(r'window.__EXTERNAL_SUBS\s+=\s+(\[.*]);',decrypted_code)
suburlmatch = re.search(r'window.__SUBS_ORIGIN\s+=\s*"(.*)";',decrypted_code)
if match:
url = match.group(1).replace("\\","")
subtitles = []
if submatch and suburlmatch:
subtitles = json.loads(submatch.group(1))
for item in subtitles:
if item['forced'] == True:
item['id'] = item['lang'] + '-forced'
else:
item['id'] = item['lang']
del item['forced']
del item['file']
item['url'] = suburlmatch.group(1).replace('\\','') + item['url']
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}Vidxgo\n ▶️ Vidxgo', 'url': f'{instance_url}/clone/manifest.m3u8?d={b64encode(url.encode("utf-8")).decode("utf-8")}', 'behaviorHints': {'proxyHeaders': {"request": {"User-Agent": 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36',"Accept": "*/*", "Accept-Language":"en-US,en;q=0.9","Referer":VD_DOMAIN+"/","Origin":VD_DOMAIN,"Sec-GPC": "1","Connection": "keep-alive","Sec-Fetch-Dest":"empty","Sec-Fetch-Mode":"cors","Sec-Fetch-Site":"cross-site","DNT": "1","Priority":"u=0"}}, 'notWebReady': True, 'bingeGroup': f'vidxgo'},'subtitles' : subtitles})
logger.info(f"Vidxgo found results for the current ID")
return streams
#Testing
async def test_vidxgo():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await vidxgo("https://v.vidxgo.co/tt0816692",client,{'streams': []},"localhost")
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_vidxgo())
# XOR decryption
+81
View File
@@ -0,0 +1,81 @@
from fake_headers import Headers
import re
from bs4 import BeautifulSoup,SoupStrainer
random_headers = Headers()
import Src.Utilities.config as config
Icon = config.Icon
Name = config.Name
from Src.Utilities.mfp import build_mfp
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
SC_DOMAIN = config.SC_DOMAIN
User_Agent= "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
async def vixcloud(link,client,MFP,MFP_CREDENTIALS,streams,site_name,proxies,ForwardProxy):
if MFP == "1":
final_url = await build_mfp(MFP_CREDENTIALS, link, "VixCloud",client)
quality = ""
mfp_icon = '🕵️‍♂️'
if final_url:
streams['streams'].append({"name":f'{Name} {mfp_icon}\n{quality}', 'title': f'{Icon} StreamingCommunity\n▶️ Vixcloud','url': final_url,'behaviorHints': {'bingeGroup': f'{site_name.lower()}{quality}'}})
return streams
mfp_icon = ''
headers = random_headers.generate()
headers['Referer'] = f"{SC_DOMAIN}/"
headers['Origin'] = f"{SC_DOMAIN}"
headers['User-Agent'] = User_Agent
headers['user-agent'] = User_Agent
# I will get real link from API
parts = link.split(SC_DOMAIN)
response = await client.get(ForwardProxy + SC_DOMAIN + '/api' + parts[1],proxies=proxies)
link = SC_DOMAIN + '/' + response.json()['src']
response = await client.get(ForwardProxy + link,headers=headers, proxies = proxies)
if response.status_code != 200:
logger.warning(f"Failed to extract URL components from VixSRC, Invalid Request: {response.status_code}")
soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer("body"))
if soup:
script = soup.find("body").find("script").text
token = re.search(r"'token':\s*'(\w+)'", script).group(1)
expires = re.search(r"'expires':\s*'(\d+)'", script).group(1)
server_url = re.search(r"url:\s*'([^']+)'", script).group(1)
try:
quality = re.search(r'"quality":(\d+)', script).group(1)
except:
quality = ""
if "?b=1" in server_url:
final_url = f'{server_url}&token={token}&expires={expires}'
else:
final_url = f"{server_url}?token={token}&expires={expires}"
if "window.canPlayFHD = true" in script:
final_url += "&h=1"
if final_url:
logger.info(f"Vixcloud Found Results for the current ID")
#We add .m3u8 after the VixID in order to make the video playable by ExoPlayer
parts_final_url = final_url.split("?")
first_part_final_url = parts_final_url[0] + ".m3u8"
final_url = first_part_final_url + "?" + parts_final_url[1]
streams['streams'].append({"name":f'{Name} {mfp_icon}\n{quality}', 'title': f'{Icon} StreamingCommunity\n▶️ Vixcloud','url': final_url,'behaviorHints': {'proxyHeaders': {"request": {"user-agent": User_Agent}}, 'notWebReady': True, 'bingeGroup': f'{site_name.lower()}{quality}'}})
return streams
#Testing
async def test_vixcloud():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await vixcloud("https://vixsrc.to/tv/76479/5/6/",client,"0",['',''],{'streams': []},'guardoserie.live', {},'')
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_vixcloud())
+100
View File
@@ -0,0 +1,100 @@
'''
Code taken from https://github.com/mhdzumair/mediaflow-proxy/blob/main/mediaflow_proxy/extractors/voe.py adpted to work with MammaMia
The owner of MammaMia should not be thanked for any code in this script.
'''
import base64
import re
from typing import Dict, Any
from urllib.parse import urljoin
import Src.Utilities.config as config
from Src.Utilities.config import setup_logging
from Src.Utilities.mfp import build_mfp
level = config.LEVEL
logger = setup_logging(level)
Icon = config.Icon
Name = config.Name
from fake_headers import Headers
random_headers = Headers()
async def voe(url,streams,site_name,MFP,MFP_CREDENTIALS,proxies,ForwardProxy,client):
if MFP == '1':
url = await build_mfp(MFP_CREDENTIALS,url,"Voe",client)
if url and "https%3ANone" not in url:
logger.info(f"{site_name} on Voe found results for the current ID")
streams['streams'].append({'name': f"{Name} 🕵️‍♂️",'title': f'{Icon}{site_name}\n▶️ Voe', 'url': url, 'behaviorHints':{'bingeGroup': f'{site_name.lower()}'}})
return streams
headers = random_headers.generate()
response = await client.get(ForwardProxy + url,headers=headers, impersonate = 'chrome', proxies = proxies)
# See https://github.com/Gujal00/ResolveURL/blob/master/script.module.resolveurl/lib/resolveurl/plugins/voesx.py
redirect_pattern = r'''window\.location\.href\s*=\s*'([^']+)'''
redirect_match = re.search(redirect_pattern, response.text, re.DOTALL)
if redirect_match:
if redirected:
logger.info("VOE: too many redirects")
return await voe(redirect_match.group(1))
code_and_script_pattern = r'json">\["([^"]+)"]</script>\s*<script\s*src="([^"]+)'
code_and_script_match = re.search(code_and_script_pattern, response.text, re.DOTALL)
if not code_and_script_match:
logger.info("VOE: unable to locate obfuscated payload or external script URL")
script_response = await client.get(ForwardProxy+urljoin(url, code_and_script_match.group(2)),headers=headers, proxies = proxies)
luts_pattern = r"(\[(?:'\W{2}'[,\]]){1,9})"
luts_match = re.search(luts_pattern, script_response.text, re.DOTALL)
if not luts_match:
logger.info("VOE: unable to locate LUTs in external script")
data = voe_decode(code_and_script_match.group(1), luts_match.group(1))
final_url = data.get('source')
if not final_url:
logger.info("VOE: failed to extract video URL")
return streams
if final_url:
logger.info(f"{site_name} on Voe found results for the current ID")
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}{site_name}\n▶️ Voe', 'url': final_url, 'behaviorHints': {'proxyHeaders': {"request": {"Referer": url}}, 'notWebReady': True, 'bingeGroup': f'{site_name.lower()}'}})
return streams
def voe_decode(ct: str, luts: str) -> Dict[str, Any]:
import json
lut = [''.join([('\\' + x) if x in '.*+?^${}()|[]\\' else x for x in i]) for i in luts[2:-2].split("','")]
txt = ''
for i in ct:
x = ord(i)
if 64 < x < 91:
x = (x - 52) % 26 + 65
elif 96 < x < 123:
x = (x - 84) % 26 + 97
txt += chr(x)
for i in lut:
txt = re.sub(i, '', txt)
ct = base64.b64decode(txt).decode('utf-8')
txt = ''.join([chr(ord(i) - 3) for i in ct])
txt = base64.b64decode(txt[::-1]).decode('utf-8')
return json.loads(txt)
async def test_voe():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await voe("https://crystaltreatmenteast.com/wnnov1m62xzy",{'streams': []},'ToonItalia','1','[https:idk.com,a]',{},'',client)
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_voe())
-183
View File
@@ -1,183 +0,0 @@
from tmdbv3api import TMDb, Movie, TV
from bs4 import BeautifulSoup,SoupStrainer
import string
import re
import dateparser
from Src.Utilities.convert import get_TMDb_id_from_IMDb_id
from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
from Src.Utilities.convert_date import convert_US_date
import Src.Utilities.config as config
FT_DOMAIN = config.FT_DOMAIN
import urllib.parse
WOA = 0
#Some basic headers
headers = {
'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',
'Accept-Language': 'en-US,en;q=0.5'
}
#Map months to check if date = date
month_mapping = {
'Jan': 'Gennaio', 'Feb': 'Febbraio', 'Mar': 'Marzo', 'Apr': 'Aprile',
'May': 'Maggio', 'Jun': 'Giugno', 'Jul': 'Luglio', 'Aug': 'Agosto',
'Sep': 'Settembre', 'Oct': 'Ottobre', 'Nov': 'Novembre', 'Dec': 'Dicembre'
}
async def search(query,date,client,season,ismovie):
response = await client.get(query)
response = response.json()
#Get link tid of every item and then open the link to see if the date = date
for json in response:
link = json['link']
tid = json['id']
series_response = await client.get(link, headers=headers, allow_redirects=True, timeout = 30)
series_soup = BeautifulSoup(series_response.text, 'lxml')
release_span = series_soup.find('span', class_='released')
if release_span:
if release_span.text != "Data di uscita: N/A":
date_string = release_span.text.split(': ')[-1] # Get the date part
release_date = date_string[-4:]
if WOA:
for eng, ita in month_mapping.items():
date_string = re.sub(rf'\b{eng}\b', ita, date_string)
# Swap to YY-MM-DD formatting using dateparser
release_date = dateparser.parse(date_string, languages=['it']).strftime("%Y-%m-%d")
if release_date == date:
url = link
tid = tid
if ismovie == 0:
Seasons = series_soup.find_all('span', class_="season-name")
i = 0
for item in Seasons:
season_text = item.text.strip()
if season in season_text and "SUB" not in season_text:
actual_season = i
return url, tid, actual_season
else:
i = i + 1
continue
else:
actual_season = None
return url, tid, actual_season
else:
print("")
def get_episode_link(actual_season,episode,tid,url):
#Get the link from where we have to obtain mixdrop link
tlink = f'{url}?show_video=true&post_id={tid}&season_id={actual_season}&episode_id={episode-1}'
return tlink
def get_film(url):
#Get the link from where we have to obtain mixdrop link
tlink = url + "?show_video=true"
return tlink
async def get_real_link(tlink,client):
#Some basic code to get the mixdrop link
page = await client.get(tlink, headers=headers, allow_redirects=True)
soup = BeautifulSoup(page.content, features="lxml",parse_only=SoupStrainer('iframe'))
iframe_src = soup.find('iframe')['src']
iframe_page = await client.get(iframe_src, headers=headers, allow_redirects=True, timeout = 30)
iframe_soup = BeautifulSoup(iframe_page.content, features="lxml")
mega_button = iframe_soup.find('div', attrs={'class': 'megaButton', 'rel': 'nofollow'}, string='MIXDROP')
if mega_button:
real_link = mega_button.get('meta-link')
return real_link
async def get_true_link(real_link,client):
response = await client.get(real_link, headers=headers, allow_redirects=True,timeout = 30)
[s1, s2] = re.search(r"\}\('(.+)',.+,'(.+)'\.split", response.text).group(1, 2)
schema = s1.split(";")[2][5:-1]
terms = s2.split("|")
charset = string.digits + string.ascii_letters
d = dict()
for i in range(len(terms)):
d[charset[i]] = terms[i] or charset[i]
s = 'https:'
for c in schema:
s += d[c] if c in d else c
return s
async def filmpertutti(imdb,client):
general = is_movie(imdb)
ismovie = general[0]
imdb_id = general[1]
type = "Filmpertutti"
if ismovie == 0 :
season = general[2]
episode = int(general[3])
if "tt" in imdb:
if ismovie == 0:
#Get showname and date
showname,date = await get_info_imdb(imdb_id,ismovie,type,client)
else:
#THIS IS needed cause the only way to get all releases dates is by giving a tmdb ID not a IMDB
showname,date = await get_info_imdb(imdb_id,ismovie,type, client)
season = None
elif "tmdb" in imdb:
#Get showname and date
tmdba = imdb_id.replace("tmdb:","")
showname,date = get_info_tmdb(tmdba,ismovie,type)
showname = showname.replace(" ", "+").replace("–", "+").replace("—","+")
showname = urllib.parse.quote_plus(showname)
#Build the query
query = f'https://filmpertutti.{FT_DOMAIN}/wp-json/wp/v2/posts?search={showname}&page=1&_fields=link,id'
try:
url,tid,actual_season = await search(query,date,client,season,ismovie)
except:
print("MammaMia: No results found for Filmpertutti")
return None
if ismovie == 0:
episode_link = get_episode_link(actual_season,episode,tid,url)
#Let's get mixdrop link
real_link = await get_real_link(episode_link,client)
#let's get delivery link, streaming link
streaming_link = await get_true_link(real_link,client)
print(streaming_link)
return streaming_link
elif ismovie == 1:
film_link = get_film(url)
#Let's get mixdrop link
real_link = await get_real_link(film_link,client)
#let's get delivery link, streaming link
streaming_link = await get_true_link(real_link,client)
return streaming_link
'''
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "tt4655480:1:1" # This is an example ID format
results = await filmpertutti(test_id, client)
if __name__ == "__main__":
import asyncio
asyncio.run(test_animeworld())
'''
'''
series_response = await client.get(link, headers=headers, follow_redirects=True)
series_soup = BeautifulSoup(series_response.text, 'lxml')
release_span = series_soup.find('span', class_='released')
if release_span:
if release_span.text != "Data di uscita: N/A":
date_string = release_span.text.split(': ')[-1] # Get the date part
for eng, ita in month_mapping.items():
date_string = re.sub(rf'\b{eng}\b', ita, date_string)
# Swap to YY-MM-DD formatting using dateparser
release_date = dateparser.parse(date_string, languages=['it']).strftime("%Y-%m-%d")
'''
+134
View File
@@ -0,0 +1,134 @@
from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
import Src.Utilities.config as config
from fake_headers import Headers
from Src.Utilities.loadenv import load_env
from urllib.parse import quote
from bs4 import BeautifulSoup, SoupStrainer
from Src.API.extractors.loadm import loadm
from Src.API.extractors.uqload import uqload
from Src.API.extractors.dropload import dropload
import logging
from Src.Utilities.config import setup_logging
from Src.Utilities.update_config import update_site
import json
import random
level = config.LEVEL
logger = setup_logging(level)
env_vars = load_env()
random_headers = Headers()
GF_DOMAIN = config.GF_DOMAIN
GF_PROXY = config.GF_PROXY
proxies = {}
if GF_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
GF_ForwardProxy = config.GF_ForwardProxy
if GF_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
async def new_domain(url,data,headers,proxies,ForwardProxy,client):
url = url.split('/wp-admin')[0]
headers['Origin'] = url
headers['Referer'] = f'{url}/'
response = await client.post(ForwardProxy + f'{url}/wp-admin/admin-ajax.php', data = data, headers = headers, proxies = proxies)
if response.status_code != 200:
logger.warning(f"Guardaflix Failed to fetch search results: {response.status_code}")
result = await update_site(client,['guardaplay','Guardaflix'])
return response.text
async def get_player(page_link,MFP, MFP_CREDENTIALS,client, headers,streams):
response = await client.get(ForwardProxy + page_link, headers= headers, proxies = proxies)
soup = BeautifulSoup(response.text,'lxml', parse_only=SoupStrainer('iframe'))
iframe = soup.find('iframe')
player_link = iframe.get('data-src') or iframe.get('src')
if "loadm" in player_link:
referer = page_link.split('//')[1].split('/')[0]
streams = await loadm(player_link,client,streams,referer,"Guardaflix", proxies, ForwardProxy)
elif "uqload" in player_link:
streams = await uqload(player_link,client,MFP,MFP_CREDENTIALS,streams,"Guardaflix", proxies, ForwardProxy)
elif "dropload" in player_link:
streams = await dropload(player_link,client,streams,"Guardaflix", proxies, ForwardProxy)
return streams
async def search(showname,date,MFP,MFP_CREDENTIALS,client,streams):
headers = random_headers.generate()
headers['Origin'] = f'{GF_DOMAIN}'
headers['Referer'] = f'{GF_DOMAIN}/'
headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
data = {
'action': 'action_tr_search_suggest',
'nonce': '20115729b4',
'term': showname,
}
response = await client.post(ForwardProxy + f'{GF_DOMAIN}/wp-admin/admin-ajax.php', headers=headers, data=data, proxies = proxies)
text = response.text
if response.status_code != 200:
if response.status_code == 400:
text = await new_domain(response.url,data,headers,proxies,ForwardProxy,client)
if len(text) < 10:
logger.warning(f"Guardaflix Failed to fetch search results: {response.status_code}")
soup = BeautifulSoup(text,'lxml', parse_only= SoupStrainer('a'))
a_tags = soup.find_all('a')
for a in a_tags:
href = a['href']
logger.info(href)
response = await client.get(ForwardProxy + href, headers = headers, proxies = proxies)
soup = BeautifulSoup(response.text,'lxml', parse_only = SoupStrainer(['iframe', 'span']))
year = soup.find('span',class_='year fa-calendar far').text
if year == date:
iframe = soup.find('iframe')
page_link = iframe.get('data-src') or iframe.get('src')
streams = await get_player(page_link,MFP,MFP_CREDENTIALS,client, headers,streams)
return streams
return streams
async def guardaflix(streams,id,client,MFP,MFP_CREDENTIALS):
try:
general = await is_movie(id)
ismovie = general[0]
clean_id = general[1]
type = "Guardaflix"
if ismovie == 0:
return streams
if "tmdb" in id:
showname,date = get_info_tmdb(clean_id,ismovie,type)
else:
showname,date = await get_info_imdb(clean_id,ismovie,type,client)
logger.info(showname)
streams = await search(showname,date,MFP,MFP_CREDENTIALS,client,streams)
return streams
except Exception as e:
logger.warning(f'GF {e}')
return streams
async def test_guardaflix():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await guardaflix({'streams': []},"tt4045450",client,"0",['test','test'])
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_guardaflix())
+82
View File
@@ -0,0 +1,82 @@
from Src.Utilities.info import is_movie
from bs4 import BeautifulSoup,SoupStrainer
import re
import Src.Utilities.config as config
from fake_headers import Headers
from Src.Utilities.loadenv import load_env
from Src.API.extractors.streamhg import streamhg
from Src.API.extractors.mixdrop import mixdrop
import json, random
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
env_vars = load_env()
GH_PROXY = config.GH_PROXY
proxies = {}
if GH_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
GH_ForwardProxy = config.GH_ForwardProxy
if GH_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
GHD_DOMAIN = config.GHD_DOMAIN
random_headers = Headers()
async def search(clean_id,client):
headers = random_headers.generate()
response = await client.get(ForwardProxy + f"{GHD_DOMAIN}/set-movie-a/{clean_id}", allow_redirects=True, headers = headers, proxies = proxies)
if response.status_code != 200:
logger.warning(f"GuardaHD Failed to fetch search results: {response.status_code}")
soup = BeautifulSoup(response.text,'lxml',parse_only=SoupStrainer('li'))
li_tags = soup.find_all('li')
results = {}
for tag in li_tags:
if tag.get('data-link') and (('mixdrop') in tag.text or ('streamhg') in tag.text):
results[tag.text.strip()] = 'https:' + tag['data-link']
return results
async def guardahd(streams,id,client,MFP,MFP_CREDENTIALS):
try:
general = await is_movie(id)
ismovie = general[0]
clean_id = general[1]
if ismovie == 0:
return streams
results = await search(clean_id,client)
status = False
if 'streamhg' in results:
streams,status = await streamhg(results['streamhg'], client,MFP,MFP_CREDENTIALS,streams,"GuardaHD",proxies, ForwardProxy)
if 'mixdrop' in results and not status:
streams,status = await mixdrop(results['mixdrop'],client,MFP,MFP_CREDENTIALS,streams,"GuardaHD",proxies,ForwardProxy,'')
return streams
except Exception as e:
logger.warning(f"MammaMia: GuardaHD Failed {e}")
return streams
async def test_script():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "tt16426418" # This is an example ID format
results = await guardahd({'streams': []},test_id, client,'0','')
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_script())
+151
View File
@@ -0,0 +1,151 @@
from Src.Utilities.info import is_movie
from bs4 import BeautifulSoup,SoupStrainer
import re
import Src.Utilities.config as config
from fake_headers import Headers
from Src.Utilities.loadenv import load_env
import json, random
from Src.Utilities.info import get_info_imdb,get_info_tmdb
import urllib.parse
from Src.Utilities.convert import get_IMDB_id_from_TMDb_id
from Src.API.extractors.supervideo import supervideo
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
env_vars = load_env()
GS_PROXY = config.GS_PROXY
proxies = {}
if GS_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
GS_ForwardProxy = config.GS_ForwardProxy
if GS_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
#Get domain
GS_DOMAIN = config.GS_DOMAIN
random_headers = Headers()
async def search_imdb(clean_id,client):
try:
headers = random_headers.generate()
response = await client.get(ForwardProxy + f'{GS_DOMAIN}/?story={clean_id}&do=search&subaction=search', allow_redirects=True, headers = headers, proxies = proxies)
if response.status_code != 200:
logger.warning(f"Guardaserie Failed to fetch search results: {response.status_code}")
soup = BeautifulSoup(response.text,'lxml',parse_only=SoupStrainer('div',class_="mlnh-2"))
div_mlnh2 = soup.select_one('div.mlnh-2:nth-of-type(2)')
a_tag = div_mlnh2.find('h2').find('a')
href = a_tag['href']
return href
except Exception as e:
logger.warning(f'GS {e}')
return None
'''
async def search(showname,date,client):
try:
headers = random_headers.generate()
showname = urllib.parse.quote(showname)
response = await client.get(ForwardProxy + f'{GS_DOMAIN}/?story={showname}&do=search&subaction=search', allow_redirects=True, impersonate = "chrome124", headers = headers, proxies = proxies)
if response.status_code != 200:
logger.warning(f"Guardaserie Failed to fetch search results: {response.status_code}")
soup = BeautifulSoup(response.text,'lxml',parse_only=SoupStrainer('div'))
div_mlnew = soup.find_all('div', class_='mlnew')
for mlnew in div_mlnew:
div_date = mlnew.find('div', class_='mlnh-3 hdn').text
div_date = div_date[:4]
if div_date == date:
a_tag = mlnew.find('div', class_='mlnh-2').find('h2').find('a')
href = a_tag['href']
return href
except Exception as e:
return None
'''
async def player_url(page_url, season, episode,client):
try:
headers = random_headers.generate()
response = await client.get(ForwardProxy + page_url, allow_redirects=True, headers = headers, proxies = proxies)
soup = BeautifulSoup(response.text,'lxml',parse_only=SoupStrainer('a'))
a_tag = soup.find('a', id = f"serie-{season}_{episode}")
href = a_tag['data-link']
return href
except Exception as e:
return None
async def guardaserie(streams,id,client):
try:
general = await is_movie(id)
ismovie = general[0]
clean_id = general[1]
if ismovie == 1:
return streams
if ismovie == 0:
season = general[2]
episode = general[3]
type = "Guardaserie"
page_url = await search_imdb(clean_id,client)
supervideo_link =await player_url(page_url,season,episode,client)
if supervideo_link:
streams = await supervideo(supervideo_link, client, streams,"Guardaserie",proxies, ForwardProxy)
return streams
else:
logger.warning(" GS Couldn't find iframe source")
return streams
except Exception as e:
logger.warning(f"MammaMia: Guardaserie Failed{e}")
return streams
async def test_script():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "tt33318655:2:5" # This is an example ID format tt0460649
results = await guardaserie({'streams': []},test_id, client)
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_script())
'''
if "tt" not in clean_id:
clean_id = await get_IMDB_id_from_TMDb_id(clean_id,client)
print(clean_id)
'''
'''
if "tt" in id:
showname,date = await get_info_imdb(clean_id,ismovie,type,client)
else:
showname,date = get_info_tmdb(clean_id,ismovie,type)
showname = showname.replace("'"," ")
if "Guru" in showname:
showname = showname.split("-")[0]
'''
'''
page_url = await search(showname,date,client)
'''
+157
View File
@@ -0,0 +1,157 @@
from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
import Src.Utilities.config as config
from fake_headers import Headers
from Src.Utilities.loadenv import load_env
from urllib.parse import quote
from bs4 import BeautifulSoup, SoupStrainer
import re
from Src.API.extractors.uqload import uqload
from Src.API.extractors.loadm import loadm
from Src.API.extractors.dropload import dropload
import logging
from Src.Utilities.config import setup_logging
from Src.Utilities.update_config import update_site
level = config.LEVEL
import json
import random
logger = setup_logging(level)
env_vars = load_env()
random_headers = Headers()
GO_DOMAIN = config.GO_DOMAIN
GO_PROXY = config.GO_PROXY
proxies = {}
if GO_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
GO_ForwardProxy = config.GO_ForwardProxy
if GO_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
async def new_domain(url,data,headers,proxies,ForwardProxy,client):
url = url.split('/wp-admin')[0]
headers['Origin'] = url
headers['Referer'] = f'{url}/'
response = await client.post(ForwardProxy + f'{url}/wp-admin/admin-ajax.php', data = data, headers = headers, proxies = proxies)
if response.status_code != 200:
logger.warning(f"Guardoserie Failed to fetch search results: {response.status_code}")
result = await update_site(client,['guardoserie_2','Guardoserie'])
return response.text
async def get_player(page_link,MFP,MFP_CREDENTIALS,client, headers, streams):
response = await client.get(ForwardProxy + page_link, headers= headers, proxies = proxies)
soup = BeautifulSoup(response.text,'lxml', parse_only=SoupStrainer('iframe'))
iframe = soup.find('iframe')
player_link = iframe.get('data-src') or iframe.get('src')
urls = []
if "loadm" in player_link:
referer = page_link.split('//')[1].split('/')[0]
streams = await loadm(player_link,client,streams,referer,"Guardoserie", proxies,ForwardProxy)
elif "uqload" in player_link:
streams = await uqload(player_link,client,MFP,MFP_CREDENTIALS,streams,"Guardoserie",proxies,ForwardProxy)
elif "dropload" in player_link:
streams = await dropload(player_link,client,streams,"Guardoserie",proxies,ForwardProxy)
return streams
async def search(showname,date,season,episode,MFP, MFP_CREDENTIALS,ismovie,client,streams,):
headers = random_headers.generate()
headers['Origin'] = f'{GO_DOMAIN}'
headers['Referer'] = f'{GO_DOMAIN}/'
headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
showname = quote(showname)
data = f's={showname}&action=searchwp_live_search&swpengine=default&swpquery={showname}'
response = await client.post(ForwardProxy + f'{GO_DOMAIN}/wp-admin/admin-ajax.php', data = data, headers = headers, proxies = proxies)
text = response.text
if response.status_code != 200:
if response.status_code == 400:
text = await new_domain(response.url,data,headers,proxies,ForwardProxy,client)
if len(text) < 10:
logger.warning(f"Guardoserie Failed to fetch search results: {response.status_code}")
soup = BeautifulSoup(text,'lxml', parse_only= SoupStrainer('a', class_='ss-title'))
a_tags = soup.find_all('a')
for a in a_tags:
href = a['href']
response = await client.get(ForwardProxy + href, headers = headers, proxies = proxies)
pattern = r'(?<=/release-year\/)(\d{4})(?=\/" rel="tag">)'
match = re.search(pattern, response.text)
if match:
year = match.group(0)
if year == date:
if ismovie == 0:
soup = BeautifulSoup(response.text, 'lxml', parse_only= SoupStrainer('div', class_='les-content'))
divs = soup.find_all('div', class_='les-content')
actual_div = divs[int(season)-1]
episodes_a = actual_div.find_all('a')
actual_episode = episodes_a[int(episode)-1]
page_link = actual_episode['href']
logger.info(page_link)
elif ismovie == 1:
page_link = href
streams = await get_player(page_link,MFP,MFP_CREDENTIALS,client, headers,streams)
return streams
return streams
async def guardoserie(streams,id,client,MFP,MFP_CREDENTIALS):
try:
general = await is_movie(id)
ismovie = general[0]
clean_id = general[1]
type = "Guardoserie"
if ismovie == 0 :
season = str(general[2])
episode = str(general[3])
elif ismovie == 1:
season = None
episode = None
if "tmdb" in id:
showname,date = get_info_tmdb(clean_id,ismovie,type)
else:
showname,date = await get_info_imdb(clean_id,ismovie,type,client)
logger.info(f'GO {showname}')
streams = await search(showname,date, season,episode,MFP,MFP_CREDENTIALS,ismovie,client,streams)
return streams
except Exception as e:
logger.warning(f'GO {e}')
return streams
async def test_guardoserie():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await guardoserie({'streams': []},"tt9165438:3:1",client,"1",['test','test'])
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_guardoserie())
+11 -17
View File
@@ -3,6 +3,7 @@ from Src.Utilities.info import get_info_tmdb,is_movie
from Src.Utilities.convert import get_TMDb_id_from_IMDb_id
from Src.Utilities.loadenv import load_env
env_vars = load_env()
ForwardProxy = env_vars.get('ALTERNATIVE_LINK')
MYSTERIUS_KEY = env_vars.get('MYSTERIUS_KEY')
async def get_links(slug,season,episode,ismovie,client):
@@ -10,31 +11,28 @@ async def get_links(slug,season,episode,ismovie,client):
headers = {
"x-api-key": MYSTERIUS_KEY
}
response = await client.get("https://mammamia-urlo-ulala12431.hf.space/api/cookie", headers=headers)
response = await client.get("https://aimammam-ulala12431.hf.space/api/cookie", headers=headers)
Auths = response.json()
Bearer = Auths.get('cookie')
ap_session = Auths.get('auth')
cookies = {'ap_session': ap_session}
print(cookies)
headers = {
'accept': 'application/json, text/plain, */*',
'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
'authorization': f'Bearer {Bearer}',
'referer': f'https://altadefinizione-originale.com/play/{slug}',
'referer': f'https://altadefinizioneapp.com/play/{slug}',
'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',
'x-requested-with': 'XMLHttpRequest',
}
if ismovie == 1:
response = await client.get(f'https://altadefinizione-originale.com/api/post/urls/stream/{slug}',cookies=cookies,headers=headers)
response = await client.get(f'https://altadefinizioneapp.com/api/post/urls/stream/{slug}',cookies=cookies,headers=headers)
elif ismovie == 0:
print("HERE SEASON",season)
print("HERE EPISODE",episode)
request_url =f'https://altadefinizione-originale.com/api/post/urls/stream/{slug}/{season}/{episode}'
request_url =f'https://altadefinizioneapp.com/api/post/urls/stream/{slug}/{season}/{episode}'
print(request_url)
response = await client.get(request_url,cookies=cookies,headers=headers)
print(response.text)
try:
video_data = response.json() # Assuming this is the JSON response containing video streams
if 'streams' not in video_data:
@@ -82,7 +80,7 @@ async def get_links(slug,season,episode,ismovie,client):
async def search_imdb(showname,tmdba,client):
showname = showname.replace(" ","%20")
tmdba = str(tmdba)
query = f'https://altadefinizione-originale.com/api/search?search={showname}&page=1'
query = f'https://altadefinizioneapp.com/api/search?search={showname}&page=1'
response = await client.get(query,allow_redirects=True, impersonate = "chrome120")
if response.status_code == 200:
data = response.json()
@@ -92,7 +90,6 @@ async def search_imdb(showname,tmdba,client):
tmdb_id = ''.join(char for char in tmdb_id if char.isdigit())
if tmdb_id == tmdba:
slug = item.get('slug')
print(slug)
return slug
@@ -100,11 +97,9 @@ async def search_imdb(showname,tmdba,client):
def parse_links(resolution_links):
results = {}
if resolution_links:
print("Video links:")
for resolution, link in resolution_links.items():
if "cdn.altadefinizione-originale.com" in link:
link = link.replace("cdn.altadefinizione-originale.com","protectlinknt.b-cdn.net")
print(f"{resolution}: {link}")
if "cdn.altadefinizione-originale.com" in link or "cdn.altadefinizioneapp.com" in link:
link = link.replace("cdn.altadefinizione-originale.com","protectlinknt.b-cdn.net").replace("cdn.altadefinizioneapp.com","protectlinknt.b-cdn.net")
results[resolution] = link
return results
else:
@@ -114,7 +109,7 @@ def parse_links(resolution_links):
async def cool(imdb,client):
try:
type = "Cool"
general = is_movie(imdb)
general = await is_movie(imdb)
ismovie = general[0]
imdb_id = general[1]
if ismovie == 0 :
@@ -146,7 +141,7 @@ async def cool(imdb,client):
except Exception as e:
print("Cool Error",e)
return None
'''
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
@@ -157,4 +152,3 @@ async def test_animeworld():
if __name__ == "__main__":
import asyncio
asyncio.run(test_animeworld())
'''
@@ -3,16 +3,23 @@ import re
from bs4 import BeautifulSoup, SoupStrainer
from Src.Utilities.info import get_info_imdb, is_movie, get_info_tmdb
import urllib.parse
import Src.Utilities.config as config
DDL_DOMAIN = config.DDL_DOMAIN
ips4_device_key = config.ips4_device_key
ips4_login_key = config.ips4_login_key
ips4_member_id = config.ips4_member_id
ips4_IPSSessionFront = config.ips4_IPSSessionFront
cookies = {
'ips4_device_key': 'b6f084be79c28bb53ecfc556fd7a2a70',
'ips4_IPSSessionFront': 'f2b9db91793e084cf2003a07c563e6aa',
'ips4_member_id': '4029711',
'ips4_login_key': '41b6a70b16cce2fd39482f5b21a9c35f',
'ips4_device_key': ips4_device_key,
'ips4_IPSSessionFront': ips4_IPSSessionFront,
'ips4_member_id': ips4_member_id,
'ips4_login_key': ips4_login_key
}
async def search_series(client,id,season,episode,showname):
showname = showname.replace(" ", "%20").replace("–", "+").replace("—","+")
response = await client.get(f"https://ddlstreamitaly.co/search/?&q={showname}%20{season}%20Streaming&type=videobox_video&quick=1&nodes=11&search_and_or=and&search_in=titles&sortby=relevancy")
response = await client.get(f"{DDL_DOMAIN}/search/?&q={showname}%20{season}%20Streaming&type=videobox_video&quick=1&nodes=11,36&search_and_or=and&search_in=titles&sortby=relevancy", cookies = cookies)
soup = BeautifulSoup(response.text, 'lxml',parse_only=SoupStrainer('a'))
a_tags = soup.find_all('a', {'data-linktype': 'link'})
for a in a_tags:
@@ -48,7 +55,6 @@ async def get_episode(client,link,episode):
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-User': '?1',
'Connection': 'keep-alive',
# 'Cookie': 'ips4_device_key=b6f084be79c28bb53ecfc556fd7a2a70; ips4_IPSSessionFront=f2b9db91793e084cf2003a07c563e6aa; ips4_ipsTimezone=Europe/Rome; ips4_hasJS=true; ips4_noCache=1; ips4_announcement_3=true; ips4_member_id=4029711; ips4_login_key=41b6a70b16cce2fd39482f5b21a9c35f; ips4_loggedIn=1725985598',
'Priority': 'u=1',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
@@ -58,11 +64,7 @@ async def get_episode(client,link,episode):
}
episode = "6"
response = await client.get(link, cookies = cookies, headers = headers, params = params, impersonate="chrome120")
print(link)
response = await client.get(link, cookies = cookies, headers = headers, params = params, impersonate="chrome124")
pattern = rf'<a\s+href="([^"]+)"[^>]*>\s*Part {episode}\s*</a>'
match = re.search(pattern, response.text)
mp4_link = match.group(1)
@@ -71,9 +73,9 @@ async def get_episode(client,link,episode):
return mp4_link
async def search_movie(client,showname,id):
showname = showname.replace(" ", "%20").replace("–", "+").replace("—","+")
showname = urllib.parse.quote_plus(showname)
link = f"https://ddlstreamitaly.co/search/?&q={showname}%20Streaming&quick=1&nodes=11&search_and_or=and&search_in=titles&sortby=relevancy"
showname = showname.replace("–", "+").replace("—","+")
showname = urllib.parse.quote(showname)
link = f"{DDL_DOMAIN}/search/?&q={showname}%20Streaming&quick=1&nodes=11&search_and_or=and&search_in=titles&sortby=relevancy"
response = await client.get(link,impersonate = "chrome120")
soup = BeautifulSoup(response.text, 'lxml',parse_only=SoupStrainer('a'))
a_tags = soup.find_all('a', {'data-linktype': 'link'})
@@ -116,13 +118,12 @@ async def get_mp4(client,link):
async def ddlstream(imdb,client):
try:
general = is_movie(imdb)
general = await is_movie(imdb)
ismovie = general[0]
id = general[1]
type = "DDLStream"
if "tt" in imdb:
showname = await get_info_imdb(id,ismovie,type,client)
print(showname)
else:
showname = get_info_tmdb(id,ismovie,type)
if ismovie == 0:
@@ -131,24 +132,22 @@ async def ddlstream(imdb,client):
page_link = await search_series(client,id,season,episode,showname)
mp4_link = await get_episode(client,page_link,episode)
final_url = await get_mp4(client,mp4_link)
print(final_url)
return final_url
else:
page_link = await search_movie(client,showname,id)
mp4_link = page_link + "?area=online"
final_url = await get_mp4(client,mp4_link)
print(final_url)
return final_url
except Exception as e:
print(f"MammaMia: DDLStream Failed {e}")
return None,None
return None
'''
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
test_id = "tt6263850" # This is an example ID format
test_id = "tt3148266:3:4" # This is an example ID format
results = await ddlstream(test_id, client)
print(results)
@@ -158,4 +157,3 @@ if __name__ == "__main__":
#python3 -m Src.API.ddlstream
'''
+211
View File
@@ -0,0 +1,211 @@
from tmdbv3api import TMDb, Movie, TV
from bs4 import BeautifulSoup,SoupStrainer
import string
import re
import dateparser
from Src.Utilities.convert import get_TMDb_id_from_IMDb_id, get_IMDB_id_from_TMDb_id
from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
from Src.Utilities.convert_date import convert_US_date
import Src.Utilities.config as config
FT_DOMAIN = config.FT_DOMAIN
import urllib.parse
#Some basic headers
headers = {
'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',
'Accept-Language': 'en-US,en;q=0.5'
}
#Map months to check if date = date
month_mapping = {
'Jan': 'Gennaio', 'Feb': 'Febbraio', 'Mar': 'Marzo', 'Apr': 'Aprile',
'May': 'Maggio', 'Jun': 'Giugno', 'Jul': 'Luglio', 'Aug': 'Agosto',
'Sep': 'Settembre', 'Oct': 'Ottobre', 'Nov': 'Novembre', 'Dec': 'Dicembre'
}
async def get_streamtape(link,client):
headers = {
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
}
response = await client.get(link, headers=headers, impersonate = "chrome124")
regex = r"id=.*?(?=')"
matches = re.findall(regex, response.text)
i = 0
final_url = next((f"https://streamtape.com/get_video?{matches[i + 1]}" for i in range(len(matches) - 1) if matches[i] == matches[i + 1]), None)
return final_url
async def search(query,imdb_id,client,season,ismovie):
response = await client.get(query)
response = response.json()
#Get link tid of every item and then open the link to see if the date = date
for json in response:
link = json['link']
tid = json['id']
series_response = await client.get(link, headers=headers, allow_redirects=True, timeout = 30)
series_soup = BeautifulSoup(series_response.text, 'lxml')
imdb_pattern = r"'imdb_id':\s*'([^']+)'"
imdb_match = re.search(imdb_pattern, series_response.text)
if imdb_match:
id = imdb_match.group(1)
print(id)
if id == imdb_id:
url = link
tid = tid
if ismovie == 0:
Seasons = series_soup.find_all('span', class_="season-name")
i = 0
for item in Seasons:
season_text = item.text.strip()
if season in season_text and "SUB" not in season_text:
actual_season = i
return url, tid, actual_season
else:
i = i + 1
continue
else:
actual_season = None
return url, tid, actual_season
else:
print("There's no IMDB_ID")
def get_episode_link(actual_season,episode,tid,url):
#Get the link from where we have to obtain mixdrop link
tlink = f'{url}?show_video=true&post_id={tid}&season_id={actual_season}&episode_id={episode-1}'
return tlink
def get_film(url):
#Get the link from where we have to obtain mixdrop link
tlink = url + "?show_video=true"
return tlink
async def get_real_link(tlink,client):
try:
print(tlink)
#Some basic code to get the mixdrop link
page = await client.get(tlink, headers=headers, allow_redirects=True)
soup = BeautifulSoup(page.content, features="lxml",parse_only=SoupStrainer('iframe'))
iframe_src = soup.find('iframe')['src']
iframe_page = await client.get(iframe_src, headers=headers, allow_redirects=True, timeout = 30)
iframe_soup = BeautifulSoup(iframe_page.content, features="lxml", parse_only=SoupStrainer('div',class_="megaButton"))
mega_button = iframe_soup.find('div', attrs={'class': 'megaButton', 'rel': 'nofollow'}, string='MIXDROP')
if mega_button:
real_link = mega_button.get('meta-link')
return real_link
else:
mega_button = iframe_soup.find('div', attrs={'class': 'megaButton', 'rel': 'nofollow'}, string='STREAMTAPE')
real_link = mega_button.get('meta-link')
return real_link
except Exception as e:
print(f"Error: {e}")
return None
async def get_true_link(real_link,client):
response = await client.get(real_link, headers=headers, allow_redirects=True,timeout = 30)
[s1, s2] = re.search(r"\}\('(.+)',.+,'(.+)'\.split", response.text).group(1, 2)
schema = s1.split(";")[2][5:-1]
terms = s2.split("|")
charset = string.digits + string.ascii_letters
d = dict()
for i in range(len(terms)):
d[charset[i]] = terms[i] or charset[i]
s = 'https:'
for c in schema:
s += d[c] if c in d else c
return s
async def filmpertutti(imdb,client,MFP):
try:
general = await is_movie(imdb)
ismovie = general[0]
imdb_id = general[1]
type = "Filmpertutti"
if ismovie == 0 :
season = general[2]
episode = int(general[3])
else:
season = None
episode = None
if "tt" in imdb:
showname = await get_info_imdb(imdb_id,ismovie,type,client)
elif "tmdb" in imdb:
#Get showname and date
tmdba = imdb_id.replace("tmdb:","")
imdb_id = await get_IMDB_id_from_TMDb_id(tmdba,client)
showname = get_info_tmdb(tmdba,ismovie,type)
showname = showname.replace(" ", "+").replace("–", "+").replace("—","+")
showname = urllib.parse.quote_plus(showname)
# Build the query
query = f'{FT_DOMAIN}/wp-json/wp/v2/posts?search={showname}&page=1&_fields=link,id'
try:
url,tid,actual_season = await search(query,imdb_id,client,season,ismovie)
except:
print("MammaMia: No results found for Filmpertutti")
return None,None
if ismovie == 0:
episode_link = get_episode_link(actual_season,episode,tid,url)
#Let's get mixdrop link
real_link = await get_real_link(episode_link,client)
if MFP == "1":
if "mixdrop" in real_link:
Host = "Mixdrop"
elif "streamtape" in real_link:
Host = "Streamtape"
return real_link, Host
#let's get delivery link, streaming link
if "mixdrop" in real_link:
streaming_link = await get_true_link(real_link,client)
elif "streamtape" in real_link:
streaming_link = await get_streamtape(real_link,client)
Host = None
return streaming_link, Host
elif ismovie == 1:
film_link = get_film(url)
#Let's get mixdrop link
real_link = await get_real_link(film_link,client)
if MFP == "1":
if "mixdrop" in real_link:
Host = "Mixdrop"
elif "streamtape" in real_link:
Host = "Streamtape"
return real_link, Host
if "mixdrop" in real_link:
streaming_link = await get_true_link(real_link,client)
elif "streamtape" in real_link:
streaming_link = await get_streamtape(real_link,client)
#let's get delivery link, streaming link
Host = None
return streaming_link, Host
except Exception as e:
print(f"Filmpertutti failed: {e}")
return None,None
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
MFP = "1"
# Replace with actual id, for example 'anime_id:episode' format
test_id = "tt1190634:1:1" # This is an example ID format
results = await filmpertutti(test_id, client,MFP)
if __name__ == "__main__":
import asyncio
asyncio.run(test_animeworld())
'''
series_response = await client.get(link, headers=headers, follow_redirects=True)
series_soup = BeautifulSoup(series_response.text, 'lxml')
release_span = series_soup.find('span', class_='released')
if release_span:
if release_span.text != "Data di uscita: N/A":
date_string = release_span.text.split(': ')[-1] # Get the date part
for eng, ita in month_mapping.items():
date_string = re.sub(rf'\b{eng}\b', ita, date_string)
# Swap to YY-MM-DD formatting using dateparser
release_date = dateparser.parse(date_string, languages=['it']).strftime("%Y-%m-%d")
'''
@@ -12,11 +12,11 @@ async def search(showname,date,season,episode,ismovie,client):
}
headers = {
'authority': f'lordchannel.{LC_DOMAIN}',
'authority': f'{LC_DOMAIN}',
'accept': '*/*',
'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
# 'cookie': 'csrftoken=7lvc502CZe8Zbx7iSX1xkZOBA1NbDxJZ',
'referer': f'https://lordchannel.{LC_DOMAIN}/anime/anime-ita/',
'referer': f'{LC_DOMAIN}/anime/anime-ita/',
'sec-ch-ua': '"Not-A.Brand";v="99", "Chromium";v="124"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Android"',
@@ -31,13 +31,13 @@ async def search(showname,date,season,episode,ismovie,client):
'media': showname,
'_': '1724421723999',
}
response = await client.get(f'https://lordchannel.{LC_DOMAIN}/live_search/', params=params, cookies=cookies, headers=headers, allow_redirects=True, impersonate = "chrome120")
response = await client.get(f'{LC_DOMAIN}/live_search/', params=params, cookies=cookies, headers=headers, allow_redirects=True, impersonate = "chrome124")
data = json.loads(response.text)
for entry in data['data']:
if entry is not None: # check if the a_tag exists
href = entry['url']
quality = entry['qualit\u00e0_video']
link = f'https://lordchannel.{LC_DOMAIN}{href}'
link = f'{LC_DOMAIN}{href}'
response = await client.get(link, allow_redirects=True, impersonate = "chrome120")
soup2 = BeautifulSoup(response.text,'lxml')
li_tag = soup2.select_one("ul.card__meta li:nth-of-type(2)")
@@ -62,16 +62,15 @@ async def search(showname,date,season,episode,ismovie,client):
async def get_m3u8(video_url,client):
response = await client.get(video_url, allow_redirects=True, impersonate = "chrome120")
pattern = r'const\s+videoData\s*=\s*\[(.*?)\];'
pattern = r'https?://[^\s]+\.m3u8'
match = re.search(pattern, response.text)
if match:
video_data = match.group(1).strip().split(', ')
url = video_data[0]
url = match.group(0)
return url
async def lordchannel(imdb,client):
try:
general = is_movie(imdb)
general = await is_movie(imdb)
ismovie = general[0]
imdb_id = general[1]
type = "LordChannel"
@@ -99,8 +98,6 @@ async def lordchannel(imdb,client):
print("MammaMia: Lordchannel Failed",e)
return None,None
'''
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
@@ -110,4 +107,4 @@ async def test_animeworld():
if __name__ == "__main__":
import asyncio
asyncio.run(test_animeworld())
'''
#python3 -m Src.API.lordchannel
+132
View File
@@ -0,0 +1,132 @@
from urllib.parse import urlparse, parse_qs,unquote,quote
from fastapi import APIRouter, HTTPException, Response, Request
from curl_cffi.requests import AsyncSession
import Src.Utilities.config as config
from Src.Utilities.loadenv import load_env
env_vars = load_env()
SC_PROXY = config.SC_PROXY
VX_PROXY = config.VX_PROXY
import json
import re
import random
proxies = {}
proxies2 = {}
if VX_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies2 = {}
else:
proxies2 = {
"http": proxy,
"https": proxy
}
if SC_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
if VX_PROXY == "1":
proxies2 = proxies
SC_ForwardProxy = config.SC_ForwardProxy
VX_ForwardProxy = config.VX_ForwardProxy
if SC_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
if VX_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
router = APIRouter()
User_Agent= "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0"
async def fetch_m3u8(url):
"""Fetch the M3U8 file from the URL and store it in memory."""
async with AsyncSession() as client:
response = await client.get(ForwardProxy + url,headers = {"User-Agent": User_Agent, "user-agent": User_Agent}, proxies = proxies2)
response.raise_for_status() # Raise an error for bad responses
return response.text
@router.get("/clone/manifest.m3u8")
async def clone_m3u8(d: str = None):
if d:
try:
d = unquote(d)
m3u8_content = await fetch_m3u8(d)
return Response(content=m3u8_content, media_type='application/vnd.apple.mpegurl')
except Exception as e:
print(f"Failed to fetch M3U8 file: {e}")
raise HTTPException(status_code=404, detail="M3U8 content not found")
#This is just for testing, ignore that endpoint and the func
@router.api_route("/vixcloud/manifest.m3u8", methods=["GET", "HEAD"])
async def clone2_m3u8(d:str,token:str,expires:str,h:str = None, b:str = None, request: Request = None):
try:
m3u8 = f'{d}?token={token}&expires={expires}'
if h:
m3u8 = m3u8 + f'&h={h}'
if b:
m3u8 = m3u8 + f'&b={b}'
forwarded_proto = request.headers.get("x-forwarded-proto")
scheme = forwarded_proto if forwarded_proto else request.url.scheme
instance_url = f"{scheme}://{request.url.netloc}"
m3u8_content = await fetch_m3u8(m3u8)
modified_playlist = m3u8_content.replace("https://vixcloud.co/playlist/", f"{instance_url}/clony/")
return Response(content=modified_playlist, media_type='application/vnd.apple.mpegurl')
except Exception as e:
print(f"Failed to fetch M3U8 file: {e}")
raise HTTPException(status_code=404, detail="M3U8 content not found")
@router.api_route("/clony/{segment:path}", methods=["GET", "HEAD"])
async def clony_m3u8(segment: str, request: Request):
base_url = "https://vixcloud.co/playlist/"
full_url = f"{base_url}{segment}?{request.query_params}"
print(full_url, "A",request.query_params)
if "rendition=1080p" in full_url or "type=subtitle" in full_url:
print(full_url)
raise HTTPException(status_code=404, detail="Requested variant not available.")
m3u8_content = await fetch_m3u8(full_url)
if "sc-u12" not in m3u8_content:
m3u8_content = re.sub(r"https://sc-[a-zA-Z0-9]+-\d+.scws-content.net", "https://sc-u12-01.scws-content.net", m3u8_content)
return Response(content=m3u8_content, media_type='application/vnd.apple.mpegurl')
@router.api_route('/storage/enc.key')
async def get_key():
async with AsyncSession(timeout = 20) as client:
response = await client.get(ForwardProxy + 'https://vixcloud.co/storage/enc.key', headers = {"User-Agent": User_Agent, "user-agent": User_Agent}, proxies = proxies2)
response_headers = {
'date': response.headers['date'],
'content-length': response.headers['content-length'],
'content-type': 'application/octet-stream',
'access-control-allow-origin': '*'
}
return Response(
response.content,
response.status_code,
response_headers
)
#r"https://sc-b1-([0-2][0-9]|30).scws-content.net", "https://sc-u9-01.scws-content.net", m3u8_content)
'''
forwarded_proto = request.headers.get("x-forwarded-proto")
scheme = forwarded_proto if forwarded_proto else request.url.scheme
instance_url = f"{scheme}://{request.url.netloc}"
url_streaming_community = url_streaming_community.replace("?","&")
url_streaming_community = instance_url + "/vixcloud/manifest.m3u8?d=" + url_streaming_community
'''
+38
View File
@@ -0,0 +1,38 @@
from bs4 import BeautifulSoup
import json
from Src.Utilities.dictionaries import okru
User_Agent= "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0"
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'DNT': '1',
'Sec-GPC': '1',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Priority': 'u=1',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
}
async def okru_get_url(id,client):
try:
embed_link = okru[id]
response = await client.get(embed_link, allow_redirects=True, headers = headers, impersonate = "chrome124")
soup = BeautifulSoup(response.text, 'lxml')
div = soup.find('div', {'data-module': 'OKVideo'})
data_options = div.get('data-options')
data = json.loads(data_options)
metadata = json.loads(data['flashvars']['metadata'])
m3u8_link = metadata['hlsMasterPlaylistUrl']
print("MammaMia: Found results for Okru")
return m3u8_link
except Exception as e:
print("MammaMia: No results found for Okru")
return None
+341
View File
@@ -0,0 +1,341 @@
from bs4 import BeautifulSoup,SoupStrainer
from Src.Utilities.convert import get_TMDb_id_from_IMDb_id
from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
import Src.Utilities.config as config
import json
import random
import re
from urllib.parse import urlparse, parse_qs
from fake_headers import Headers
from Src.Utilities.loadenv import load_env
from Src.API.extractors.vixcloud import vixcloud
import urllib.parse
User_Agent= "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0"
env_vars = load_env()
SC_PROXY = config.SC_PROXY
VX_PROXY = config.VX_PROXY
proxies = {}
proxies2 = {}
if VX_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies2 = {}
else:
proxies2 = {
"http": proxy,
"https": proxy
}
if SC_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
if VX_PROXY == "1":
proxies2 = proxies
SC_ForwardProxy = config.SC_ForwardProxy
VX_ForwardProxy = config.VX_ForwardProxy
if SC_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
elif VX_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
#Get domain
SC_DOMAIN = config.SC_DOMAIN
Public_Instance = config.Public_Instance
Alternative_Link = env_vars.get('ALTERNATIVE_LINK')
headers = Headers()
#GET VERSION OF STREAMING COMMUNITY:
async def get_version(client):
#Extract the version from the main page of the site
#You can extract it from any page of the site but I chose one of the lightiest
try:
random_headers = headers.generate()
random_headers['Referer'] = f"{SC_DOMAIN}/"
random_headers['Origin'] = f"{SC_DOMAIN}"
base_url = f'{SC_DOMAIN}/richiedi-un-titolo'
response = await client.get(ForwardProxy + base_url, headers=random_headers, allow_redirects = True, impersonate="chrome124", proxies = proxies)
#Soup the response
soup = BeautifulSoup(response.text, "lxml")
# Extract version
version = json.loads(soup.find("div", {"id": "app"}).get("data-page"))['version']
return version
except Exception as e:
print("Couldn't find the version",e)
version = "65e52dcf34d64173542cd2dc6b8bb75b"
return version
async def search(query,date,ismovie, client,SC_FAST_SEARCH,movie_id):
'''
This function is used to search for a movie or a show in the Streaming Community website using the API
After it checks if the imdb id given is the same as the one in the website
We need to convert imdb id to tmdb id because often imdb ids are missing
'''
random_headers = headers.generate()
random_headers['Referer'] = f"{SC_DOMAIN}/"
random_headers['Origin'] = f"{SC_DOMAIN}"
random_headers['Accept'] = 'application/json' # Assuming the API returns JSON
random_headers['Content-Type'] = 'application/json'
#Do a request to get the ID of serie/move and it's slug in the URL
response = await client.get(ForwardProxy + query, headers = random_headers, allow_redirects=True, impersonate = "chrome124", proxies = proxies)
print(response)
response = response.json()
for item in response['data']:
tid = item['id']
slug = item['slug']
type = item['type']
if type == "tv":
type = 0
elif type == "movie":
type = 1
if type == ismovie:
#Added a Check to see if the result is what it is supposed to be
if SC_FAST_SEARCH == "0":
random_headers = headers.generate()
random_headers['Referer'] = f"{SC_DOMAIN}/"
random_headers['Origin'] = f"{SC_DOMAIN}"
response = await client.get ( ForwardProxy + f'{SC_DOMAIN}/it/titles/{tid}-{slug}', headers = random_headers, allow_redirects=True,impersonate = "chrome124", proxies = proxies)
soup = BeautifulSoup(response.text, "lxml")
data = json.loads(soup.find("div", {"id": "app"}).get("data-page"))
version = data['version']
if "tt" in movie_id:
movie_id = str(await get_TMDb_id_from_IMDb_id(movie_id,client))
print(movie_id)
#Here we need to convert because the IMDB ID is often bugged
tmdb_id = str(data['props']['title']['tmdb_id'])
if tmdb_id == movie_id:
return tid,slug,version
elif SC_FAST_SEARCH == "1":
version = await get_version(client)
return tid,slug,version
else:
print("Couldn't find anything")
async def get_film(tid,version,client,MFP):
''''
This function is used to get the link of the m3u8 from the Streaming Community player,vixcloud
'''
random_headers = headers.generate()
random_headers['Referer'] = f"{SC_DOMAIN}/"
random_headers['Origin'] = f"{SC_DOMAIN}"
random_headers['x-inertia'] = "true"
random_headers['x-inertia-version'] = version
random_headers['User-Agent'] = User_Agent
random_headers['user-agent'] = User_Agent
#Access the iframe
url = f'{SC_DOMAIN}/it/iframe/{tid}'
if MFP == "1":
url = f'{SC_DOMAIN}/it/iframe/{tid}'
quality = "Unknown"
return url,quality
response = await client.get(ForwardProxy + url, headers=random_headers, allow_redirects=True,impersonate = "chrome124", proxies = proxies)
iframe = BeautifulSoup(response.text, 'lxml')
#Get the link of iframe
iframe = iframe.find('iframe').get("src")
#Get the ID containted in the src of iframe
vixid = iframe.split("/embed/")[1].split("?")[0]
parsed_url = urlparse(iframe)
query_params = parse_qs(parsed_url.query)
random_headers = headers.generate()
random_headers['Referer'] = f"{SC_DOMAIN}/"
random_headers['Origin'] = f"{SC_DOMAIN}"
random_headers['x-inertia'] = "true"
random_headers['x-inertia-version'] = version
random_headers['User-Agent'] = User_Agent
random_headers['user-agent'] = User_Agent
#Get real token and expires by looking at the page in the iframe, vixcloud/embed
resp = await client.get(ForwardProxy + iframe, headers = random_headers, allow_redirects=True,impersonate= "chrome124", proxies = proxies2)
soup= BeautifulSoup(resp.text, "lxml")
script = soup.find("body").find("script").text
token = re.search(r"'token':\s*'(\w+)'", script).group(1)
expires = re.search(r"'expires':\s*'(\d+)'", script).group(1)
quality = re.search(r'"quality":(\d+)', script).group(1)
base_url = re.search(r"url:\s*'(https?://[^']+)'", script).group(1)
#Example url https://vixcloud.co/playlist/231315?b=1&token=bce060eec3dc9d1965a5d258dc78c964&expires=1728995040&rendition=1080p
url = f'https://vixcloud.co/playlist/{vixid}.m3u8?token={token}&expires={expires}'
if 'canPlayFHD' in query_params:
canPlayFHD = 'h=1'
url += "&h=1"
if 'b=1' in base_url:
url += "&b=1"
'''
if 'b' in query_params:
b = 'b=1'
url += "&b=1"
'''
'''
if quality == "1080":
if "&h" in url:
url = url
elif "&b" in url and quality == "1080":
url = url.replace("&b=1","&h=1")
elif quality == "1080" and "&b" and "&h" not in url:
url = url + "&h=1"
else:
url = url + f"&token={token}"
'''
return url,quality
async def get_season_episode_id(tid,slug,season,episode,version,client):
'''
This function is used to get the ID of the episode in the Streaming Community website
'''
random_headers = headers.generate()
random_headers['Referer'] = f"{SC_DOMAIN}/"
random_headers['Origin'] = f"{SC_DOMAIN}"
random_headers['x-inertia'] = "true"
random_headers['x-inertia-version'] = version
random_headers['accept'] = 'text/html, application/xhtml+xml'
random_headers['accept-language'] = 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7'
#Set some basic headers for the request
#Get episode ID
response = await client.get(ForwardProxy + f'{SC_DOMAIN}/it/titles/{tid}-{slug}/season-{season}', headers=random_headers, allow_redirects=True, impersonate = "chrome124", proxies = proxies)
# Print the json got
json_response = response.json().get('props', {}).get('loadedSeason', {}).get('episodes', [])
for dict_episode in json_response:
if dict_episode['number'] == episode:
return dict_episode['id']
async def get_episode_link(episode_id,tid,version,client,MFP):
''''
This function is used to get the link of the m3u8 from the Streaming Community player,vixcloud
'''
#The parameters for the request
random_headers = headers.generate()
random_headers['Referer'] = f"{SC_DOMAIN}/"
random_headers['Origin'] = f"{SC_DOMAIN}"
random_headers['User-Agent'] = User_Agent
random_headers['user-agent'] = User_Agent
params = {
'episode_id': episode_id,
'next_episode': '1'
}
#Let's try to get the link from iframe source
# Make a request to get iframe source
if MFP == "1":
url = f'{SC_DOMAIN}/it/iframe/{tid}?episode_id={episode_id}&next_episode=1'
quality = "Unknown"
return url,quality
response = await client.get(ForwardProxy + f"{SC_DOMAIN}/it/iframe/{tid}", params=params, headers = random_headers, allow_redirects=True, impersonate = "chrome124", proxies = proxies)
# Parse response with BeautifulSoup to get iframe source
soup = BeautifulSoup(response.text, "lxml")
iframe = soup.find("iframe").get("src")
vixid = iframe.split("/embed/")[1].split("?")[0]
random_headers = headers.generate()
random_headers['Referer'] = f"{SC_DOMAIN}/"
random_headers['Origin'] = f"{SC_DOMAIN}"
random_headers['x-inertia'] = "true"
random_headers['x-inertia-version'] = version
random_headers['User-Agent'] = User_Agent
random_headers['user-agent'] = User_Agent
parsed_url = urlparse(iframe)
query_params = parse_qs(parsed_url.query)
#Get real token and expires by looking at the page in the iframe, vixcloud/embed
resp = await client.get(ForwardProxy + iframe, headers = random_headers, allow_redirects=True, impersonate = "chrome124", proxies = proxies2)
soup= BeautifulSoup(resp.text, "lxml")
script = soup.find("body").find("script").text
token = re.search(r"'token':\s*'(\w+)'", script).group(1)
expires = re.search(r"'expires':\s*'(\d+)'", script).group(1)
quality = re.search(r'"quality":(\d+)', script).group(1)
base_url = re.search(r"url:\s*'(https?://[^']+)'", script).group(1)
#Example url https://vixcloud.co/playlist/231315?b=1&token=bce060eec3dc9d1965a5d258dc78c964&expires=1728995040&rendition=1080p
url = f'https://vixcloud.co/playlist/{vixid}.m3u8?token={token}&expires={expires}'
if 'canPlayFHD' in query_params:
canPlayFHD = 'h=1'
url += "&h=1"
if 'b=1' in base_url:
b = 'b=1'
url += "&b=1"
'''
if quality == "1080":
if "&h" in url:
url = url
elif "&b" in url and quality == "1080":
url = url.replace("&b=1","&h=1")
elif quality == "1080" and "&b" and "&h" not in url:
url = url + "&h=1"
else:
url = url + f"&token={token}"
'''
return url,quality
async def streamingcommunity_site(imdb,client,SC_FAST_SEARCH,MFP):
general = await is_movie(imdb)
ismovie = general[0]
imdb_id = general[1]
if ismovie == 0 :
season = int(general[2])
episode = int(general[3])
#Check if fast search is enabled or disabled
if SC_FAST_SEARCH == "1":
type = "StreamingCommunityFS"
if "tt" in imdb:
#Get showname
showname = await get_info_imdb(imdb_id,ismovie,type,client)
date = None
else:
#I just set n season to None to avoid bugs, but it is not needed if Fast search is enabled
date = None
#else just equals them
tmdba = imdb_id.replace("tmdb:","")
showname = get_info_tmdb(tmdba,ismovie,type)
elif SC_FAST_SEARCH == "0":
type = "StreamingCommunity"
if "tt" in imdb:
tmdba = await get_TMDb_id_from_IMDb_id(imdb_id,client)
showname,date = get_info_tmdb(tmdba,ismovie,type)
#HERE THE CASE IF IT IS A MOVIE
else:
if SC_FAST_SEARCH == "1":
type = "StreamingCommunityFS"
if "tt" in imdb:
#Get showname
date = None
showname = await get_info_imdb(imdb_id,ismovie,type,client)
else:
date = None
tmdba = imdb_id.replace("tmdb:","")
showname = get_info_tmdb(tmdba,ismovie,type)
elif SC_FAST_SEARCH == "0":
type = "StreamingCommunity"
if "tt" in imdb:
#Get showname
showname,date = await get_info_imdb(imdb_id,ismovie,type,client)
else:
tmdba = imdb_id.replace("tmdb:","")
showname,date = get_info_tmdb(tmdba,ismovie,type)
showname = showname.replace(" ", "+").replace("–", "+").replace("—","+")
showname = urllib.parse.quote_plus(showname)
query = f'{SC_DOMAIN}/api/search?q={showname}'
tid,slug,version = await search(query,date,ismovie,client,SC_FAST_SEARCH,imdb_id)
if ismovie == 1:
#TID means temporaly ID
url,quality = await get_film(tid,version,client,MFP)
print("MammaMia found results for StreamingCommunity")
return url,quality,slug
if ismovie == 0:
#Uid = URL ID
episode_id = await get_season_episode_id(tid,slug,season,episode,version,client)
url,quality = await get_episode_link(episode_id,tid,version,client,MFP)
return url,quality,slug
@@ -4,10 +4,37 @@ from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
import Src.Utilities.config as config
import re
import json
import urllib.parse
from Src.API.extractors.hdplayer import hdplayer
from Src.Utilities.loadenv import load_env
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
SW_DOMAIN = config.SW_DOMAIN
env_vars = load_env()
SW_PROXY = config.SW_PROXY
proxies = {}
if SW_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
SW_ForwardProxy = config.SW_ForwardProxy
if SW_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
async def wponce_get(client):
response = await client.get(f"https://www.streamingwatch.{SW_DOMAIN}/contatto/")
response = await client.get(ForwardProxy + f"{SW_DOMAIN}/contatto/", proxies = proxies)
pattern = r'"admin_ajax_nonce":"(\w+)"'
matches = re.findall(pattern, response.text)
wponce = matches[1]
@@ -16,15 +43,15 @@ async def wponce_get(client):
async def search(showname,season,episode,date,ismovie,client):
if ismovie == 1:
wponce = await wponce_get(client)
query = f'https://www.streamingwatch.{SW_DOMAIN}/wp-admin/admin-ajax.php'
query = f'{SW_DOMAIN}/wp-admin/admin-ajax.php'
headers = {
'authority': f'www.streamingwatch.{SW_DOMAIN}',
'authority': f'{SW_DOMAIN}',
'accept': '*/*',
'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
# 'cookie': 'wordpress_test_cookie=WP%20Cookie%20check',
'origin': f'https://www.streamingwatch.{SW_DOMAIN}',
'referer': f'https://www.streamingwatch.{SW_DOMAIN}',
'origin': f'{SW_DOMAIN}',
'referer': f'{SW_DOMAIN}/',
'sec-ch-ua': '"Not-A.Brand";v="99", "Chromium";v="124"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Android"',
@@ -42,12 +69,16 @@ async def search(showname,season,episode,date,ismovie,client):
cookies = {
'wordpress_test_cookie': 'WP%20Cookie%20check',
}
response = await client.post(query,cookies=cookies, headers=headers, data=data)
response = await client.post(ForwardProxy + query,cookies=cookies, headers=headers, data=data, proxies = proxies)
soup = BeautifulSoup(response.content,'lxml')
page_date = soup.find(id = 'search-cat-year').text.strip()
if page_date == date:
all_page_dates = soup.find_all(id = 'search-cat-year')
all_hrefs = soup.find_all('a')
for temp_data,temp_href in zip(all_page_dates,all_hrefs):
page_date = temp_data.text.strip()
if date == page_date:
href = temp_href['href']
href = soup.find('a')['href']
response = await client.get(href, allow_redirects=True, impersonate = "chrome120")
response = await client.get(ForwardProxy + href, allow_redirects=True, proxies = proxies)
soup = BeautifulSoup(response.text,'lxml',parse_only=SoupStrainer('iframe'))
iframe = soup.find('iframe')
hdplayer = iframe.get('data-lazy-src')
@@ -55,15 +86,16 @@ async def search(showname,season,episode,date,ismovie,client):
return hdplayer
elif ismovie == 0:
#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
id_response = await client.get(f'https://streamingwatch.{SW_DOMAIN}/wp-json/wp/v2/categories?search={showname}&_fields=id', allow_redirects=True, impersonate = "chrome120")
id_response = await client.get(ForwardProxy + f'{SW_DOMAIN}/wp-json/wp/v2/categories?search={showname}&_fields=id', allow_redirects=True, proxies = proxies)
data = json.loads(id_response.text)
category_id = data[0]['id']
query = f'https://streamingwatch.{SW_DOMAIN}/wp-json/wp/v2/posts?categories={category_id}&per_page=100'
response = await client.get(query, allow_redirects=True, impersonate = "chrome120")
query = f'{SW_DOMAIN}/wp-json/wp/v2/posts?categories={category_id}&per_page=100'
response = await client.get(ForwardProxy + query, allow_redirects=True, impersonate = "chrome120", proxies = proxies)
data_json = response.text
data = json.loads(data_json)
for entry in data:
if f"stagione-{season}-episodio-{episode}" in entry["slug"] and f"stagione-{season}-episodio-{episode}0" not in entry["slug"]:
if f"stagione-{season}-episodio-{episode}" in entry["slug"] or f"stagione-{season}-episode-{episode}" in entry["slug"]:
if f"stagione-{season}-episodio-{episode}0" not in entry["slug"]:
content = entry["content"]["rendered"]
#"content":{
# "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}
@@ -71,14 +103,10 @@ async def search(showname,season,episode,date,ismovie,client):
end = content.find('"', start) #end of url
hdplayer = content[start:end]
return hdplayer
async def hls_url(hdplayer,client):
response = await client.get(hdplayer, allow_redirects=True, impersonate = "chrome120")
match = re.search(r'sources:\s*\[\s*\{\s*file\s*:\s*"([^"]*)"', response.text)
url = match.group(1)
return url
async def streamingwatch(imdb,client):
async def streamingwatch(streams,imdb,client):
try:
general = is_movie(imdb)
general = await is_movie(imdb)
ismovie = general[0]
imdb_id = general[1]
type = "StreamingWatch"
@@ -97,24 +125,23 @@ async def streamingwatch(imdb,client):
else:
tmdba = imdb_id
showname,date = get_info_tmdb(tmdba,ismovie,type)
showname = showname.replace(" ", "+").replace("–", "+").replace("—","+")
hdplayer = await search(showname,season,episode,date,ismovie,client)
url = await hls_url(hdplayer,client)
print(f"MammaMia: StreamingWatch found results for {showname}")
return url
showname = showname.replace(" ", "+").replace("–", "+").replace("—","+").replace("&","")
url_hdplayer = await search(showname,season,episode,date,ismovie,client)
streams = await hdplayer(url_hdplayer,client,streams,url_hdplayer,"Streamingwatch",proxies,ForwardProxy)
return streams
except Exception as e:
print("MammaMia: StreamingWatch Failed",e)
return None
logger.warning(f"MammaMia: StreamingWatch Failed {e}")
return streams
'''
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "tt16426418" # This is an example ID format
results = await streamingwatch(test_id, client)
results = await streamingwatch({'streams': []},test_id, client)
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_animeworld())
'''
@@ -4,21 +4,26 @@ import time
from Src.Utilities.info import is_movie,get_info_imdb,get_info_tmdb
import Src.Utilities.config as config
from Src.Utilities.loadenv import load_env
HF = config.HF
env_vars = load_env()
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
TF_PROXY = config.TF_PROXY
if TF_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
TF_FORWARDPROXY = config.TF_ForwardProxy
if TF_FORWARDPROXY == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
TF_DOMAIN = config.TF_DOMAIN
import urllib.parse
async def search(showname,ismovie,date,client):
showname = showname.replace(" ","%20")
showname = urllib.parse.quote_plus(showname)
url = f'https://www.tanti.bond/ajax/posts?q={showname}'
response = await client.post(url, allow_redirects=True, impersonate = "chrome120")
showname = showname.replace(" ","+")
url = f'{TF_DOMAIN}/ajax/posts?q={showname}'
response = await client.get(url, allow_redirects=True)
response = response.json()['data']
if ismovie == 1:
for link in response:
url = link['url']
response = client.get(url, allow_redirects=True, impersonate = "chrome120")
response = await client.get(url, allow_redirects=True, impersonate = "chrome120")
pattern = r'Data di rilascio\s*</div>\s*<div class="text">\s*(\d{4})\s*</div>'
found_date = re.search(pattern, response.text)
release_date = str(found_date.group(1))
@@ -45,7 +50,7 @@ async def search(showname,ismovie,date,client):
async def fast_search(showname,ismovie,client):
showname = showname.replace(" ","%20")
url = f'https://www.tanti.{TF_DOMAIN}/search/{showname}'
url = f'{TF_DOMAIN}/search/{showname}'
response = await client.get(url, allow_redirects=True, impersonate = "chrome120")
soup = BeautifulSoup(response.text, "lxml")
if ismovie == 1:
@@ -86,7 +91,7 @@ async def get_protect_link(id,url,client):
data = {
'id': embed_id
}
ajax_url = f"https://www.tanti.{TF_DOMAIN}/ajax/embed"
ajax_url = f"{TF_DOMAIN}/ajax/embed"
response = await client.post(ajax_url, headers=headers, data=data)
hdplayer = response.text[43:-27]
response = await client.get(hdplayer, allow_redirects=True, impersonate = "chrome120")
@@ -105,7 +110,7 @@ async def get_protect_link(id,url,client):
soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer('iframe'))
protect_link = soup.iframe['src']
if "protect" in protect_link:
url = true_url(protect_link)
url = await true_url(protect_link,client)
links_dict[title] = url
return links_dict
# Get the value of the href attribute
@@ -120,7 +125,7 @@ async def get_nuovo_indirizzo_and_protect_link(url,embed_id,season,episode,clien
data = {
'id': embed_id
}
ajax_url = f"https://www.tanti.{TF_DOMAIN}/ajax/embed"
ajax_url = f"{TF_DOMAIN}/ajax/embed"
response = await client.post(ajax_url, headers=headers, data=data)
nuovo_indirizzo = response.text[43:-27]
response = await client.get(nuovo_indirizzo, allow_redirects=True, impersonate = "chrome120")
@@ -157,19 +162,27 @@ async def true_url(protect_link,client):
"Range": "bytes=0-",
"Referer": "https://d000d.com/",
}
if HF == "1":
doodstream_url = protect_link
proxies = {}
if TF_PROXY == "1":
import random
import json
print(PROXY_CREDENTIALS)
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
response = await client.get(protect_link, proxies=proxies, allow_redirects=True, impersonate = "chrome120")
else:
response = await client.get(protect_link, allow_redirects=True, impersonate = "chrome120")
elif TF_FORWARDPROXY == "1":
response = await client.head(protect_link, allow_redirects=True, impersonate = "chrome120", proxies = proxies)
doodstream_url = response.url
response = await client.get(ForwardProxy + doodstream_url, allow_redirects=True, impersonate = "chrome120", proxies = proxies)
if response.status_code == 200:
# Get unique timestamp for the request
@@ -185,15 +198,13 @@ async def true_url(protect_link,client):
if match:
# Create real link (match[0] includes all matched elements)
url =f'https://d000d.com{match[1]}'
if "HF" == "1" :
rebobo = await client.get(url, headers=headers, allow_redirects=True, impersonate = "chrome120",proxies= proxies)
else:
rebobo = await client.get(url, headers=headers, allow_redirects=True, impersonate = "chrome120")
rebobo = await client.get(ForwardProxy + url, headers=headers, allow_redirects=True, impersonate = "chrome120",proxies= proxies)
if len(rebobo.text)> 2:
real_url = f'{rebobo.text}123456789{match[2]}{real_time}'
print("MammaMia: Found results for Tantifilm")
return real_url
else:
print("No match found in the text.")
print("Tantifilm: No match found in the text. Please be sure you are using a local instance")
return None
print("Error: Could not get the response.")
@@ -205,7 +216,7 @@ async def true_url(protect_link,client):
async def tantifilm(imdb,client,TF_FAST_SEARCH):
urls = None
try:
general = is_movie(imdb)
general = await is_movie(imdb)
ismovie = general[0]
imdb_id = general[1]
if ismovie == 0 :
@@ -272,17 +283,19 @@ async def tantifilm(imdb,client,TF_FAST_SEARCH):
return None
'''
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "tt6468322:1:1" # This is an example ID format
test_id = "tt3148266:1:1" # This is an example ID format
results = await tantifilm(test_id, client,"0")
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_animeworld())
'''
+186
View File
@@ -0,0 +1,186 @@
import random
from bs4 import BeautifulSoup,SoupStrainer
import Src.Utilities.config as config
from Src.Utilities.dictionaries import webru_vary,webru_dlhd,skystreaming
from Src.Utilities.loadenv import load_env
from urllib.parse import urlparse
import re
TF_DOMAIN = config.TF_DOMAIN
DLHD_DOMAIN = config.DLHD_DOMAIN
env_vars = load_env()
MEDIAFLOW_PASS = env_vars.get('MEDIAFLOW_PASS')
Referer = "https://ilovetoplay.xyz/"
Origin = "https://ilovetoplay.xyz"
key_url = "https%3A%2F%2Fkey2.keylocking.ru%2F"
headers = {
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0",
"Accept": "*/*",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Origin": Origin,
"DNT": "1",
"Sec-GPC": "1",
"Connection": "keep-alive",
"Referer": Referer,
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "cross-site",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
}
async def get_stream_link(id,site,client):
try:
if site == "dlhd":
dlhd_id = webru_dlhd[id]
response = await client.get(f"{DLHD_DOMAIN}/embed/stream-853.php", impersonate = "chrome124", headers = headers)
soup = BeautifulSoup(response.text, 'lxml', parse_only=SoupStrainer('iframe'))
iframe = soup.find('iframe', id='thatframe')
real_link = iframe.get('src')
parent_site_domain = real_link.split('/premiumtv')[0]
server_key_link = (f'{parent_site_domain}/server_lookup.php?channel_id={dlhd_id}')
response = await client.get(server_key_link, allow_redirects = False)
server_key = response.json()['server_key']
'''
response = await client.get(real_link, allow_redirects = False)
print(response.text)
pattern = r"source:\s*'([^']*\.m3u8)'"
match = re.search(pattern, response.text)
if match:
m3u8_url = match.group(1) # The URL is captured in the first capturing group
parsed_url = urlparse(m3u8_url)
domain = parsed_url.netloc
else:
print("No .m3u8 URL found.")
'''
stream_url = f"https://{server_key}new.iosplayer.ru/{server_key}/{dlhd_id}" + "/mono.m3u8"
return stream_url,Referer,Origin
elif site == "vary":
response = await client.get("https://calcio.monster/streaming-gratis-calcio-1.php", impersonate = "chrome124", headers = headers)
soup = BeautifulSoup(response.text, 'lxml', parse_only=SoupStrainer('div', class_='ticket_btn'))
href = soup.find('a').get('href')
response = await client.get(href)
soup = BeautifulSoup(response.text, 'lxml', parse_only=SoupStrainer('button'))
webru_iframe = soup.find_all('button', {"data-type": "embed"})
for i in webru_iframe:
webru_iframe = i.get('data-url')
if "php" not in webru_iframe:
continue
else:
break
webru_iframe = "https://" + webru_iframe.split("/")[2]
vary_id = webru_vary[id]
vary_link = f"{webru_iframe}/server_lookup.php?channel_id={vary_id}"
response = await client.get(vary_link, headers=headers, allow_redirects=True, impersonate = "chrome124")
server_key = response.json()['server_key']
stream_url = f"https://{server_key}new.iosplayer.ru/{server_key}/{vary_id}" + "/mono.m3u8"
return stream_url,Referer,Origin
except Exception as e:
print("WebRu failed",e)
return None,None,None
async def webru(id,site,client):
try:
new_stream_url,Referer,Origin = await get_stream_link(id,site,client)
if new_stream_url == None:
raise Exception("No stream URL found")
return new_stream_url,Referer,Origin
except Exception as e:
print("WebRu failed",e)
return None,None,None
async def get_skystreaming(id,client):
try:
skystreaming_link = skystreaming[id]
if type(skystreaming_link) == list:
for link in skystreaming_link:
m3u8_url,Host,Origin = await get_skystreaming_url(link,client)
else:
m3u8_url,Host,Origin = await get_skystreaming_url(skystreaming_link,client)
return m3u8_url,Host,Origin
except Exception as e:
print("SkyStreaming failed",e)
return None,None,None
async def get_skystreaming_url(skystreaming_link,client):
try:
if "hls" in skystreaming_link:
m3u8_url = skystreaming_link
Host = m3u8_url.replace("https://","").split("/")[0]
response = await client.get(skystreaming_link, headers=headers, allow_redirects=True, impersonate = "chrome120")
Origin = response.url.split('/embed')[0]
return m3u8_url,Host,Origin
response = await client.get(skystreaming_link, headers=headers, allow_redirects=True, impersonate = "chrome120")
Origin = response.url.split('/embed')[0]
soup = BeautifulSoup(response.text, 'lxml', parse_only=SoupStrainer('source'))
source_tag = soup.find('source')
m3u8_url = source_tag.get('src')
Host = m3u8_url.replace("https://","").split("/")[0]
return m3u8_url,Host,Origin
except Exception as e:
print("SkyStreaming failed",e)
return None,None
'''
async def webru(id,site,client,MFP_CREDENTIALS):
try:
stream_url, Referer,Origin = await get_stream_link(id,site,client)
mfp_url = MFP_CREDENTIALS[0]
mfp_pass = MFP_CREDENTIALS[1]
new_stream_url = f'{mfp_url}/proxy/hls/manifest.m3u8?api_password={mfp_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'
return new_stream_url
except Exception as e:
print("WebRu failed",e)
return None
'''
'''
async def webru2(id,site,client):
try:
print(id)
if site == "vary":
print("1")
url = await get_stream_link(id,site)
if any(keyword in id for keyword in ["cinema", "arte", "nature", "investigation", "sky-uno", "sky-serie"]):
print("2")
url = await get_stream_link(id,site)
else:
print("3")
response = await client.get(f"https://848b3516657c-worldwide-sports-tv.baby-beamup.club/stream/tv/wwstv-it-{id}.json", impersonate = "chrome120", headers = headers)
data = response.json()
url = data['streams'][0]['url']
print(url)
return url
except Exception as e:
print("WorldSport failed",e)
return None
'''
'''
if id in skystreaming:
i = i+1
url,Host = await get_skystreaming(id,client)
streams['streams'].append({'title': f'{HF}Server {i}', 'url': url, "behaviorHints": {"notWebReady": True, "proxyHeaders": {"request": {"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0", "Accept": "*/*", "Accept-Language": "en-US,en;q=0.5", "Origin": "https://skystreaming.guru", "DNT": "1", "Sec-GPC": "1", "Connection": "keep-alive", "Referer": "https://skystreaming.guru/", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "cross-site", "Pragma": "no-cache", "Cache-Control": "no-cache", "TE": "trailers","Host": Host}}}})
'''
async def test_webru():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "sky-sport-uno" # This is an example ID format
results = await get_skystreaming(test_id,client)
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_webru())
+3 -3
View File
@@ -1,7 +1,7 @@
from Src.Utilities.info import is_movie,get_info_imdb,get_info_tmdb
import json
import urllib.parse
#This doesn't work anymore.
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0',
'Accept': '*/*',
@@ -76,6 +76,7 @@ async def whvx(id,client):
showname = urllib.parse.quote_plus(showname)
response = await client.get(f'https://api.whvx.net/search', params = params, headers=headers, impersonate = "chrome120")
data = json.loads(response.text)
print(data)
url = data['url']
print(data)
params = {
@@ -110,7 +111,7 @@ async def whvx(id,client):
print(resolution_links)
return resolution_links
'''
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
@@ -123,4 +124,3 @@ if __name__ == "__main__":
asyncio.run(test_animeworld())
'''
-23
View File
@@ -1,23 +0,0 @@
from bs4 import BeautifulSoup
import json
from Src.Utilities.dictionaries import okru
async def okru_get_url(id,client):
try:
embed_link = okru[id]
print(embed_link)
response = await client.get(embed_link, allow_redirects=True, impersonate = "chrome120")
soup = BeautifulSoup(response.text, 'lxml')
div = soup.find('div', {'data-module': 'OKVideo'})
data_options = div.get('data-options')
data = json.loads(data_options)
metadata = json.loads(data['flashvars']['metadata'])
m3u8_link = metadata['hlsMasterPlaylistUrl']
print("MammaMia: Found results for Okru")
print(m3u8_link)
return m3u8_link
except Exception as e:
print("MammaMia: No results found for Okru")
return None
+156
View File
@@ -0,0 +1,156 @@
from Src.Utilities.info import get_info_imdb, is_movie, get_info_tmdb
from bs4 import BeautifulSoup,SoupStrainer
import Src.Utilities.config as config
from fake_headers import Headers
from Src.Utilities.loadenv import load_env
import json, random
import re
from Src.Utilities.eval import eval_solver
import urllib.parse
from Src.API.extractors.maxstream import maxstream
from Src.API.extractors.uprot import bypass_uprot
OST_DOMAIN = config.OST_DOMAIN
OST_PROXY = config.OST_PROXY
env_vars = load_env()
proxies = {}
random_headers = Headers()
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
if OST_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
OST_ForwardProxy = config.OST_ForwardProxy
if OST_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
Name = config.Name
Icon = config.Icon
async def search(showname,date,client,ismovie,episode,season):
headers = random_headers.generate()
headers['Referer'] = f'{OST_DOMAIN}/'
cookies = {
'player_opt': 'fx',
}
params = {
's': showname,
'action': 'searchwp_live_search',
'swpengine': 'default',
'swpquery': showname,
'origin_id': '50141',
'searchwp_live_search_client_nonce': 'undefined',
}
response = await client.get(ForwardProxy + f"{OST_DOMAIN}/wp-admin/admin-ajax.php?s={urllib.parse.quote(showname)}&action=searchwp_live_search&swpengine=default&swpquery={urllib.parse.quote(showname)}&origin_id=50141&searchwp_live_search_client_nonce=undefined", headers=headers, cookies=cookies, impersonate = "chrome", proxies = proxies)
if response.status_code != 200:
logger.info("IP Blocked by OnlineserieTV",response)
soup = BeautifulSoup(response.text, 'lxml', parse_only=SoupStrainer('a'))
a_tags_with_href = soup.find_all("a", href=True)
for a_tag in a_tags_with_href:
href = a_tag.get("href")
if ismovie == 1:
if "film" in href:
response = await client.get(ForwardProxy + href, headers=headers, impersonate = "chrome", proxies = proxies)
if response.status_code != 200:
logger.info("IP Blocked by OnlineserieTV",response)
year_match = re.search(r'Anno: <i>(\d{4})</i>', response.text)
year = year_match.group(1) if year_match else None
if year == date:
pattern = r'https://uprot\.net/msf/[^\s"<>]+'
match = re.search(pattern, response.text)
if match:
name = a_tag.text.replace("\t","").replace("\n","")
maxstream_link = match.group()
return maxstream_link,name
else:
logger.info("No Maxstream link found.")
else:
continue
elif ismovie == 0:
if "serietv" in href:
response = await client.get(ForwardProxy + href, headers=headers, impersonate = "chrome", proxies = proxies)
if response.status_code != 200:
logger.info("IP Blocked by OnlineserieTV",response)
year_match = re.search(r'Anno: <i>(\d{4})</i>', response.text)
year = year_match.group(1) if year_match else None
if year == date:
season = season.zfill(2)
episode = episode.zfill(2)
pattern = rf'{season}x{episode}.*?<a href=[\'"](https://uprot\.net/msf/[^\'"]+)'
match = re.search(pattern, response.text, re.DOTALL)
if not match:
pattern = rf'0{episode}.*?<a href=[\'"](https://uprot\.net/msf/[^\'"]+)'
match = re.search(pattern, response.text, re.DOTALL)
if match:
name = a_tag.text.replace("\t","").replace("\n","")
maxstream_link = match.group(1)
return maxstream_link,name
else:
logger.info("No maxstream link found.")
else:
continue
return None,None
async def get_maxstream(uprot_link,streams,language,client):
maxstream_link = await bypass_uprot(client,uprot_link)
if maxstream_link:
streams = await maxstream(maxstream_link,client,streams,'OnlineSerieTV',language,proxies,ForwardProxy)
else:
if maxstream_link == False:
return streams
else:
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}OnlineSerieTV\n▶️ Please do the captcha at /uprot in order to be able to play this content! \n Remember to refresh the sources!\nIf you recently did the captcha then dont worry, just refresh the sources', 'url': 'https://github.com/UrloMythus/MammaMia', 'behaviorHints': { 'bingeGroup': 'cb01'}})
return streams
async def onlineserietv(streams,id,client):
try:
general = await is_movie(id)
ismovie = general[0]
clean_id = general[1]
if ismovie == 0:
season = general[2]
episode = general[3]
elif ismovie == 1:
season = None
episode = None
type = "Onlineserietv"
if "tt" in id:
showname,date = await get_info_imdb(clean_id,ismovie,type,client)
else:
showname,date = get_info_tmdb(clean_id,ismovie,type)
showname = showname.replace("'"," ")
uprot_link,name = await search(showname,date,client,ismovie,episode,season)
if uprot_link != None:
streams = await get_maxstream(uprot_link,streams,'',client)
return streams
except Exception as e:
logger.info("MammaMia: Onlineserietv Failed")
logger.info(e)
return streams
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
test_id = "tt16426418" # This is an example ID format
results = await onlineserietv({'streams': []},test_id, client)
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_animeworld())
# Guru Guru tt0330592 Uomo tigre tt0206516
#python3 -m Src.API.onlineserietv
+298
View File
@@ -0,0 +1,298 @@
from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
import Src.Utilities.config as config
from fake_headers import Headers
from Src.Utilities.loadenv import load_env
from urllib.parse import quote
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
import random
Icon = config.Icon
Name = config.Name
logger = setup_logging(level)
env_vars = load_env()
random_headers = Headers()
RT_PROXY = config.RT_PROXY
proxies = {}
if RT_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
RT_ForwardProxy = config.RT_ForwardProxy
if RT_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
endpoints = {
'it' : 'https://public.aurora.enhanced.live',
'dplay' : 'https://eu1-prod.disco-api.com'
}
async def search(showname,date,client):
showname = showname.split('-')[0]
showname = quote(showname)
response = await client.get(ForwardProxy + f'https://public.aurora.enhanced.live/site/search/page/?include=default&filter[environment]=realtime&v=2&q={showname}&page[number]=1&page[size]=20', proxies = proxies)
data = response.json()
for item in data['data']:
return item['slug']
async def program_info(slug,season,episode,client):
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:143.0) Gecko/20100101 Firefox/143.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://realtime.it/',
'Origin': 'https://realtime.it',
'Sec-GPC': '1',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
'DNT': '1',
'Priority': 'u=4',
}
link = f'https://public.aurora.enhanced.live/site/page/{slug}/?include=default&filter[environment]=realtime&v=2&parent_slug=programmi-real-time'
response = await client.get(ForwardProxy + link,headers = headers, proxies = proxies)
data = response.json()
for item in reversed(data['blocks'][1]['items']):
if season == item['seasonNumber'] and episode == item['episodeNumber']:
if 'aurora' in data['blocks'][0]['item']['poster']['src']:
platform = 'IT'
elif 'eu1-prod' in data['blocks'][0]['item']['poster']['src']:
platform = 'DPLAY'
x_realm_it = ''
x_realm_dplay = ''
if 'X-REALM-IT' in data['userMeta']['realm']:
x_realm_it = data['userMeta']['realm']['X-REALM-IT']
if 'X-REALM-DPLAY' in data['userMeta']['realm']:
x_realm_dplay = data['userMeta']['realm']['X-REALM-DPLAY']
return item['id'],x_realm_it,x_realm_dplay, platform
return None,None,None,None
async def get_token(client):
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:143.0) Gecko/20100101 Firefox/143.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://realtime.it/',
'Content-Type': 'application/json',
'X-disco-client': 'WEB:UNKNOWN:wbdatv:2.1.9',
'X-disco-params': 'realm=dplay',
'X-Device-Info': 'STONEJS/1 (Unknown/Unknown; Linux/undefined; Unknown)',
'Origin': 'https://realtime.it',
'Sec-GPC': '1',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
'DNT': '1',
'Priority': 'u=4',
}
response = await client.get(ForwardProxy + 'https://public.aurora.enhanced.live/site/page/casa-a-prima-vista/?include=default&filter[environment]=realtime&v=2&parent_slug=programmi-real-time', headers = headers, proxies = proxies)
data = response.json()
x_realm_it = data['userMeta']['realm']['X-REALM-IT']
x_realm_dplay = data['userMeta']['realm']['X-REALM-DPLAY']
return x_realm_it,x_realm_dplay
async def get_url(id, endpoint, x_realm_it,x_realm_dplay,streams,client):
if 'IT' in endpoint:
base_url = endpoints['it']
token = x_realm_it
elif 'DPLAY' in endpoint:
base_url = endpoints['dplay']
token = x_realm_dplay
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:143.0) Gecko/20100101 Firefox/143.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://realtime.it/',
'Content-Type': 'application/json',
'X-disco-client': 'WEB:UNKNOWN:wbdatv:2.1.9',
'X-disco-params': 'realm=dplay',
'X-Device-Info': 'STONEJS/1 (Unknown/Unknown; Linux/undefined; Unknown)',
'Authorization': f'Bearer {token}',
'Origin': 'https://realtime.it',
'Sec-GPC': '1',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
'DNT': '1',
'Priority': 'u=4',
}
json_data = {
'deviceInfo': {
'adBlocker': False,
'drmSupported': True,
'hdrCapabilities': [
'SDR',
],
'hwDecodingCapabilities': [],
'soundCapabilities': [
'STEREO',
],
},
'wisteriaProperties': {},
'videoId': id,
}
response = await client.post(ForwardProxy + f'{base_url}/playback/v3/videoPlaybackInfo', headers=headers, json=json_data, proxies = proxies)
data = response.json()
for item in data['data']['attributes']['streaming']:
if item['type'] == 'hls':
m3u8 = item['url']
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}▶️ Realtime\n HLS', 'url': m3u8, 'behaviorHints': {'bingeGroup': f'realtimehls'}})
elif item['type'] == 'dash':
mpd = item['url']
streams['streams'].append({'name': f"{Name}",'title': f'{Icon}▶️ Realtime\n MPD', 'url': mpd, 'behaviorHints': {'bingeGroup': f'realtimempd'}})
return streams
async def search_catalog(query,catalog,client):
showname = quote(query)
response = await client.get(f'https://public.aurora.enhanced.live/site/search/page/?include=default&filter[environment]=realtime&v=2&q={showname}&page[number]=1&page[size]=20')
data = response.json()
for item in data['data']:
title = item['title']
description = item['subtitle']
date = item['datePublished'].split('-')[0]
id = item['slug']
image = item['image']['url']
typeof = item['type']
catalog['metas'].append({'id': f'realtime{typeof}:'+id, 'type': "series",'name': f'{title}', 'description': description, 'releaseInfo': date, 'background': image, 'poster': image })
return catalog
async def meta_catalog(id,catalog,client):
try:
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:143.0) Gecko/20100101 Firefox/143.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://realtime.it/',
'Origin': 'https://realtime.it',
'Sec-GPC': '1',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
'DNT': '1',
'Priority': 'u=4',
}
parts = id.split(':')
slug = parts[1]
parts2 = parts[0].split('realtime')
typeof= parts2[1]
if typeof == 'showpage':
link = f'https://public.aurora.enhanced.live/site/page/{slug}/?include=default&filter[environment]=realtime&v=2&parent_slug=programmi-real-time'
elif typeof == 'article':
link = f'https://public.aurora.enhanced.live/site/page/{slug}/?include=default&filter[environment]=realtime&v=2'
response = await client.get(ForwardProxy + link,headers = headers, proxies = proxies)
data = response.json()
title = data['title']
subtitle = data['subtitle']
if data['type'] == 'articlepage':
if data['blocks'][1]['sonicOverrideEnabled'] == True:
platform = 'IT'
else:
platform = 'DPLAY'
elif data['type'] == 'showpage':
if 'aurora' in data['blocks'][0]['item']['poster']['src']:
platform = 'IT'
elif 'eu1-prod' in data['blocks'][0]['item']['poster']['src']:
platform = 'DPLAY'
if typeof == 'showpage':
for item in reversed(data['blocks'][1]['items']):
id = item['id']
description = item['description']
episode = item['episodeNumber']
season = item['seasonNumber']
poster = item['poster']
date = item['publishStart']
catalog['meta']['videos'].append({'title': f'S{season}'+ f'E{episode}','season': season, 'episode': episode,'firstAired':date,'overview': description, 'thumbnail': poster['src'], 'id': f'realtime{platform}:id:'+id})
elif typeof == 'article':
item = data['blocks'][1]['item']
id = item['id']
description = item['description']
episode = item['episodeNumber']
season = item['seasonNumber']
poster = item['poster']
date = item['publishStart']
catalog['meta']['videos'].append({'title': f'{title}','season': season, 'episode': episode,'firstAired':date,'overview': description, 'thumbnail': poster['src'], 'id': f'realtime{platform}:id:'+id})
catalog['meta']['name'] = title
catalog['meta']['description'] = subtitle
catalog['meta']['releaseInfo'] = '-' + data['datePublished'].split('-')[0]
catalog['meta']['background'] = data['metaMedia'][0]['media']['url']
return catalog
except Exception as e:
catalog['meta']['name'] = title
catalog['meta']['description'] = subtitle
catalog['meta']['releaseInfo'] = '-' + data['datePublished'].split('-')[0]
catalog['meta']['background'] = data['metaMedia'][0]['media']['url']
return catalog
async def realtime(streams,id,client):
try:
if 'realtime' in id:
parts = id.split('id:')
id = parts[1]
endpoint = parts[0]
x_realm_it,x_realm_dplay = await get_token(client)
streams = await get_url(id, endpoint, x_realm_it,x_realm_dplay,streams,client)
else:
general = await is_movie(id)
ismovie = general[0]
clean_id = general[1]
type = "Realtime"
if ismovie == 0 :
season = int(general[2])
episode = int(general[3])
elif ismovie == 1:
season = None
episode = None
if "tmdb" in id:
showname,date = get_info_tmdb(clean_id,ismovie,type)
else:
showname,date = await get_info_imdb(clean_id,ismovie,type,client)
logger.info(f'RT {showname}')
slug = await search(showname,date,client)
id,x_realm_it,x_realm_dplay,platform = await program_info(slug,season,episode,client)
streams = await get_url(id,platform,x_realm_it,x_realm_dplay,streams,client)
return streams
except Exception as e:
logger.warning(f'RT {e}')
return streams
async def test_realtime():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await realtime({'streams': []},"tt5684368:13:10",client)
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_realtime())
+81 -241
View File
@@ -1,264 +1,104 @@
from bs4 import BeautifulSoup
from bs4 import BeautifulSoup,SoupStrainer
from Src.Utilities.convert import get_TMDb_id_from_IMDb_id
from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
from Src.Utilities.info import is_movie
import Src.Utilities.config as config
import json
import random
import re
from urllib.parse import urlparse, parse_qs
from fake_headers import Headers
from Src.Utilities.loadenv import load_env
import urllib.parse
from Src.API.extractors.vixcloud import vixcloud
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
User_Agent= "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0"
env_vars = load_env()
SC_PROXY = config.SC_PROXY
VX_PROXY = config.VX_PROXY
proxies = {}
proxies2 = {}
if VX_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies2 = {}
else:
proxies2 = {
"http": proxy,
"https": proxy
}
if SC_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
if VX_PROXY == "1":
proxies2 = proxies
SC_ForwardProxy = config.SC_ForwardProxy
VX_ForwardProxy = config.VX_ForwardProxy
if SC_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
elif VX_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
#Get domain
SC_DOMAIN = config.SC_DOMAIN
Public_Instance = config.Public_Instance
Alternative_Link = env_vars.get('ALTERNATIVE_LINK')
headers = Headers()
#GET VERSION OF STREAMING COMMUNITY:
async def get_version(client):
#Extract the version from the main page of the site
try:
random_headers = headers.generate()
random_headers['Referer'] = f"https://streamingcommunity.{SC_DOMAIN}/"
random_headers['Origin'] = f"https://streamingcommunity.{SC_DOMAIN}"
base_url = f'https://streamingcommunity.{SC_DOMAIN}/richiedi-un-titolo'
response = await client.get(base_url, headers=random_headers, allow_redirects = True, impersonate="chrome120")
#Soup the response
soup = BeautifulSoup(response.text, "lxml")
# Extract version
version = json.loads(soup.find("div", {"id": "app"}).get("data-page"))['version']
return version
except Exception as e:
print("Couldn't find the version",e)
version = "65e52dcf34d64173542cd2dc6b8bb75b"
return version
async def search(query,date,ismovie, client,SC_FAST_SEARCH):
random_headers = headers.generate()
random_headers['Referer'] = "https://streamingcommunity.buzz/"
random_headers['Origin'] = "https://streamingcommunity.buzz"
random_headers['Accept'] = 'application/json' # Assuming the API returns JSON
random_headers['Content-Type'] = 'application/json'
#Do a request to get the ID of serie/move and it's slug in the URL
response = await client.get(query, headers = random_headers, allow_redirects=True)
print(response)
response = response.json()
for item in response['data']:
tid = item['id']
slug = item['slug']
type = item['type']
if type == "tv":
type = 0
elif type == "movie":
type = 1
if type == ismovie:
#Added a Check to see if the result is what it is supposed to be
if SC_FAST_SEARCH == "0":
random_headers = headers.generate()
random_headers['Referer'] = "https://streamingcommunity.buzz/"
random_headers['Origin'] = "https://streamingcommunity.buzz"
response = await client.get ( f'https://streamingcommunity.{SC_DOMAIN}/titles/{tid}-{slug}', headers = random_headers, allow_redirects=True,impersonate = "chrome120")
pattern = r'<div[^>]*class="features"[^>]*>.*?<span[^>]*>(.*?)<\/span>'
match = re.search(pattern, response.text)
print(match.group(1).split("-")[0])
first_air_year = match.group(1).split("-")[0]
date = int(date)
first_air_year = int(first_air_year)
if first_air_year == date:
return tid,slug
elif SC_FAST_SEARCH == "1":
return tid,slug
else:
print("Couldn't find anything")
async def get_film(tid,version,client):
random_headers = headers.generate()
random_headers['Referer'] = "https://streamingcommunity.buzz/"
random_headers['Origin'] = "https://streamingcommunity.buzz"
random_headers['x-inertia'] = "true"
random_headers['x-inertia-version'] = version
#Access the iframe
url = f'https://streamingcommunity.{SC_DOMAIN}/iframe/{tid}'
response = await client.get(url, headers=random_headers, allow_redirects=True,impersonate = "chrome120")
iframe = BeautifulSoup(response.text, 'lxml')
#Get the link of iframe
iframe = iframe.find('iframe').get("src")
#Get the ID containted in the src of iframe
vixid = iframe.split("/embed/")[1].split("?")[0]
parsed_url = urlparse(iframe)
query_params = parse_qs(parsed_url.query)
random_headers = headers.generate()
random_headers['Referer'] = "https://streamingcommunity.buzz/"
random_headers['Origin'] = "https://streamingcommunity.buzz"
random_headers['x-inertia'] = "true"
random_headers['x-inertia-version'] = version
#Get real token and expires by looking at the page in the iframe, vixcloud/embed
resp = await client.get(iframe, headers = random_headers, allow_redirects=True,impersonate= "chrome120")
soup= BeautifulSoup(resp.text, "lxml")
script = soup.find("body").find("script").text
token = re.search(r"'token':\s*'(\w+)'", script).group(1)
expires = re.search(r"'expires':\s*'(\d+)'", script).group(1)
quality = re.search(r'"quality":(\d+)', script).group(1)
#Example url https://vixcloud.co/playlist/231315?b=1&token=bce060eec3dc9d1965a5d258dc78c964&expires=1728995040&rendition=1080p
url = f'https://vixcloud.co/playlist/{vixid}.m3u8?token={token}&expires={expires}'
if 'canPlayFHD' in query_params:
canPlayFHD = 'h=1'
url += "&h=1"
if 'b' in query_params:
b = 'b=1'
url += "&b=1"
url720 = f'https://vixcloud.co/playlist/{vixid}.m3u8'
return url,url720,quality,
async def get_season_episode_id(tid,slug,season,episode,version,client):
random_headers = headers.generate()
random_headers['Referer'] = "https://streamingcommunity.buzz/"
random_headers['Origin'] = "https://streamingcommunity.buzz"
random_headers['x-inertia'] = "true"
random_headers['x-inertia-version'] = version
#Set some basic headers for the request
#Get episode ID
response = await client.get(f'https://streamingcommunity.{SC_DOMAIN}/titles/{tid}-{slug}/stagione-{season}', headers=random_headers, allow_redirects=True, impersonate = "chrome120")
# Print the json got
json_response = response.json().get('props', {}).get('loadedSeason', {}).get('episodes', [])
for dict_episode in json_response:
if dict_episode['number'] == episode:
return dict_episode['id']
async def get_episode_link(episode_id,tid,version,client):
#The parameters for the request
random_headers = headers.generate()
random_headers['Referer'] = "https://streamingcommunity.buzz/"
random_headers['Origin'] = "https://streamingcommunity.buzz"
params = {
'episode_id': episode_id,
'next_episode': '1'
}
#Let's try to get the link from iframe source
# Make a request to get iframe source
response = await client.get(f"https://streamingcommunity.{SC_DOMAIN}/iframe/{tid}", params=params, headers = random_headers, allow_redirects=True, impersonate = "chrome120")
# Parse response with BeautifulSoup to get iframe source
soup = BeautifulSoup(response.text, "lxml")
iframe = soup.find("iframe").get("src")
vixid = iframe.split("/embed/")[1].split("?")[0]
random_headers = headers.generate()
random_headers['Referer'] = "https://streamingcommunity.buzz/"
random_headers['Origin'] = "https://streamingcommunity.buzz"
random_headers['x-inertia'] = "true"
random_headers['x-inertia-version'] = version
parsed_url = urlparse(iframe)
query_params = parse_qs(parsed_url.query)
#Get real token and expires by looking at the page in the iframe, vixcloud/embed
resp = await client.get(iframe, headers = random_headers, allow_redirects=True, impersonate = "chrome120")
soup= BeautifulSoup(resp.text, "lxml")
script = soup.find("body").find("script").text
token = re.search(r"'token':\s*'(\w+)'", script).group(1)
expires = re.search(r"'expires':\s*'(\d+)'", script).group(1)
quality = re.search(r'"quality":(\d+)', script).group(1)
#Example url https://vixcloud.co/playlist/231315?b=1&token=bce060eec3dc9d1965a5d258dc78c964&expires=1728995040&rendition=1080p
url = f'https://vixcloud.co/playlist/{vixid}.m3u8?token={token}&expires={expires}'
if 'canPlayFHD' in query_params:
canPlayFHD = 'h=1'
url += "&h=1"
if 'b' in query_params:
b = 'b=1'
url += "&b=1"
url720 = f'https://vixcloud.co/playlist/{vixid}.m3u8'
return url,url720,quality
async def streaming_community(imdb,client,SC_FAST_SEARCH):
try:
if Public_Instance == "1":
Weird_Link = json.loads(Alternative_Link)
link_post = random.choice(Weird_Link)
response = await client.get(f"{link_post}fetch-data/{SC_FAST_SEARCH}/{SC_DOMAIN}/{imdb}")
url_streaming_community = response.headers.get('x-url-streaming-community')
url_720_streaming_community = response.headers.get('x-url-720-streaming-community')
quality_sc = response.headers.get('x-quality-sc')
print(quality_sc,url_streaming_community)
return url_streaming_community,url_720_streaming_community,quality_sc
general = is_movie(imdb)
async def vixsrc(streams,id,client,MFP,MFP_CREDENTIALS):
general = await is_movie(id)
ismovie = general[0]
imdb_id = general[1]
clean_id = general[1]
if "tt" in id:
tmdb_id = await get_TMDb_id_from_IMDb_id(clean_id,client)
else:
tmdb_id = clean_id
if ismovie == 0 :
season = int(general[2])
episode = int(general[3])
#Check if fast search is enabled or disabled
if SC_FAST_SEARCH == "1":
type = "StreamingCommunityFS"
if "tt" in imdb:
#Get showname
showname = await get_info_imdb(imdb_id,ismovie,type,client)
date = None
site_url = f'{SC_DOMAIN}/tv/{tmdb_id}/{general[2]}/{general[3]}/'
else:
#I just set n season to None to avoid bugs, but it is not needed if Fast search is enabled
date = None
#else just equals them
tmdba = imdb_id.replace("tmdb:","")
showname = get_info_tmdb(tmdba,ismovie,type)
elif SC_FAST_SEARCH == "0":
type = "StreamingCommunity"
tmdba = await get_TMDb_id_from_IMDb_id(imdb_id,client)
showname,date = get_info_tmdb(tmdba,ismovie,type)
#HERE THE CASE IF IT IS A MOVIE
else:
if SC_FAST_SEARCH == "1":
type = "StreamingCommunityFS"
if "tt" in imdb:
#Get showname
date = None
showname = await get_info_imdb(imdb_id,ismovie,type,client)
else:
date = None
tmdba = imdb_id.replace("tmdb:","")
showname = get_info_tmdb(tmdba,ismovie,type)
elif SC_FAST_SEARCH == "0":
type = "StreamingCommunity"
if "tt" in imdb:
#Get showname
showname,date = await get_info_imdb(imdb_id,ismovie,type,client)
else:
tmdba = imdb_id.replace("tmdb:","")
showname,date = get_info_tmdb(tmdba,ismovie,type)
site_url = f'{SC_DOMAIN}/movie/{tmdb_id}/'
streams = await vixcloud(site_url,client,MFP,MFP_CREDENTIALS,streams,"Vixcloud",proxies,ForwardProxy)
return streams
showname = showname.replace(" ", "+").replace("–", "+").replace("—","+")
showname = urllib.parse.quote_plus(showname)
query = f'https://streamingcommunity.{SC_DOMAIN}/api/search?q={showname}'
version = await get_version(client)
tid,slug = await search(query,date,ismovie,client,SC_FAST_SEARCH)
if ismovie == 1:
#TID means temporaly ID
url,url720,quality = await get_film(tid,version,client)
print("MammaMia found results for StreamingCommunity")
return url,url720,quality
if ismovie == 0:
#Uid = URL ID
episode_id = await get_season_episode_id(tid,slug,season,episode,version,client)
url,url720,quality = await get_episode_link(episode_id,tid,version,client)
print("MammaMia found results for StreamingCommunity")
return url,url720,quality
async def streaming_community(streams,id,client,MFP,MFP_CREDENTIALS):
try:
if "vixsrc" in SC_DOMAIN:
streams = await vixsrc(streams,id,client,MFP,MFP_CREDENTIALS)
return streams
except Exception as e:
print("MammaMia: StreamingCommunity failed",e)
return None,None,None
'''
async def test_animeworld():
logger.warning(f"StreamingCommunity failed {e}")
return streams
async def test_vixsrc():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "tt12930350" # This is an example ID format
results = await streaming_community(test_id, client,"0")
test_id = "tt6468322:1:1" # This is an example ID format
results = await streaming_community({'streams': []},test_id, client,"0",['test','welp'])
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_animeworld())
'''
asyncio.run(test_vixsrc())
+123
View File
@@ -0,0 +1,123 @@
from fake_headers import Headers
random_headers = Headers()
import Src.Utilities.config as config
from Src.Utilities.info import get_info_imdb,get_info_tmdb
from urllib.parse import quote
from Src.Utilities.convert import get_IMDB_id_from_TMDb_id
from Src.Utilities.info import get_info_tmdb, is_movie, get_info_imdb
from Src.API.extractors.voe import voe
from Src.API.extractors.maxstream import maxstream
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
import re
import json
import random
logger = setup_logging(level)
from Src.Utilities.loadenv import load_env
env_vars = load_env()
TI_DOMAIN = config.TI_DOMAIN
TI_PROXY = config.TI_PROXY
proxies = {}
if TI_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
TI_ForwardProxy = config.TI_ForwardProxy
if TI_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
async def search(showname,date,season,episode,MFP,MFP_CREDENTIALS,ismovie,client,streams):
headers = random_headers.generate()
response = await client.get(ForwardProxy + f'{TI_DOMAIN}/wp-json/wp/v2/search?search={quote(showname)}',headers=headers, proxies = proxies)
data = response.json()
for item in data:
response = await client.get(ForwardProxy + item['_links']['self'][0]['href'],headers=headers, proxies = proxies)
info = response.json()
html = info['content']['rendered']
if 'Stagione' in html and ismovie == 1:
continue
if 'Stagione' not in html and ismovie == 0:
continue
if ismovie == 0:
episode = episode.zfill(2)
pattern = rf'{season}&#215;{episode}.*?<a[^>]*href="([^"]*)'
if ismovie == 1:
pattern = r'Link.*href="([^"]*)(?=.*VOE)'
match = re.search(pattern,html)
if match:
url = match.group(1)
if 'maxstream' in url:
parts = url.split('.video/')
url = 'https://maxstream.video/emvvv/' + parts[1]
streams = await maxstream(url,client,streams,'ToonItalia','',proxies,ForwardProxy)
else:
streams = await voe(url,streams,'ToonItalia',MFP,MFP_CREDENTIALS,proxies,ForwardProxy,client)
return streams
return streams
async def toonitalia(streams,id,client,MFP,MFP_CREDENTIALS):
try:
general = await is_movie(id)
ismovie = general[0]
clean_id = general[1]
type = "Toonitalia"
if ismovie == 0 :
season = str(general[2])
episode = str(general[3])
elif ismovie == 1:
season = None
episode = None
if "tmdb" in id:
showname,date = get_info_tmdb(clean_id,ismovie,type)
else:
showname,date = await get_info_imdb(clean_id,ismovie,type,client)
streams = await search(showname,date, season,episode,MFP,MFP_CREDENTIALS,ismovie,client,streams)
return streams
except Exception as e:
logger.warning(f'Toonitalia Error: {e}')
return streams
async def test_toonitalia():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await toonitalia({'streams': []},"tt0096697:1:1",client,"0",['test','test'])
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_toonitalia())
+65
View File
@@ -0,0 +1,65 @@
from Src.Utilities.info import is_movie
import Src.Utilities.config as config
from Src.Utilities.loadenv import load_env
from Src.API.extractors.vidxgo import vidxgo
import json, random
import logging
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
env_vars = load_env()
VD_PROXY = config.VD_PROXY
proxies = {}
if VD_PROXY == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxy_list = json.loads(PROXY_CREDENTIALS)
proxy = random.choice(proxy_list)
if proxy == "":
proxies = {}
else:
proxies = {
"http": proxy,
"https": proxy
}
VD_ForwardProxy = config.VD_ForwardProxy
if VD_ForwardProxy == "1":
ForwardProxy = env_vars.get('ForwardProxy')
else:
ForwardProxy = ""
VD_DOMAIN = config.VD_DOMAIN
async def vidxgoalta(streams,id,client,instance_url):
try:
general = await is_movie(id)
ismovie = general[0]
clean_id = general[1]
type = "Vidxgo"
if "tmdb" in id:
clean_id = await get_IMDB_id_from_TMDb_id(clean_id,client)
if ismovie == 0 :
season = str(general[2])
episode = str(general[3])
link = f'{VD_DOMAIN}/{clean_id}/{season}/{episode}'
elif ismovie == 1:
link = f'{VD_DOMAIN}/{clean_id}'
streams = await vidxgo(link,client,streams,instance_url)
return streams
except Exception as e:
logger.info("Vidxgo failed due to ")
logger.info(e)
return streams
async def test_script():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
# Replace with actual id, for example 'anime_id:episode' format
test_id = "tt7181546" # This is an example ID format
results = await vidxgoalta({'streams': []},test_id, client)
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_script())
-106
View File
@@ -1,106 +0,0 @@
import random
from bs4 import BeautifulSoup,SoupStrainer
import Src.Utilities.config as config
from Src.Utilities.dictionaries import webru_vary,webru_dlhd,skystreaming
from Src.Utilities.loadenv import load_env
env_vars = load_env()
MEDIAFLOW_PASS = env_vars.get('MEDIAFLOW_PASS')
Referer = "https://ilovetoplay.xyz/"
Origin = "https://ilovetoplay.xyz"
key_url = "https%3A%2F%2Fkey2.keylocking.ru%2F"
headers = {
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0",
"Accept": "*/*",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Origin": Origin,
"DNT": "1",
"Sec-GPC": "1",
"Connection": "keep-alive",
"Referer": Referer,
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "cross-site",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
}
medialink = config.MediaProxy
async def get_stream_link(id,site,client):
try:
if site == "dlhd":
stream_url = "https://xyzdddd.mizhls.ru/lb/" + webru_dlhd[id] + "/index.m3u8"
elif site == "vary":
stream_url = "https://webuit.mizhls.ru/lb/"+ webru_vary[id] + "/index.m3u8"
return stream_url,Referer,Origin
except Exception as e:
return None
async def webru(id,site,client):
try:
stream_url, Referer,Origin = await get_stream_link(id,site,client)
mediaproxy = config.MediaProxy
medialink = random.choice(mediaproxy)
new_stream_url = f'{medialink}proxy/hls/manifest.m3u8?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'
return new_stream_url
except Exception as e:
print("WebRu failed",e)
return None
async def get_skystreaming(id,client):
try:
skystreaming_link = skystreaming[id]
m3u8_urls = {}
if type(skystreaming_link) == list:
for link in skystreaming_link:
m3u8_url,Host = await get_skystreaming_url(link,client)
m3u8_urls[m3u8_url] = Host
print(m3u8_urls)
else:
m3u8_url,Host = await get_skystreaming_url(skystreaming_link,client)
m3u8_urls[m3u8_url] = Host
return m3u8_urls
except Exception as e:
print("SkyStreaming failed",e)
return None,None
async def get_skystreaming_url(skystreaming_link,client):
try:
if "hls" in skystreaming_link:
m3u8_url = skystreaming_link
Host = m3u8_url.replace("https://","").split("/")[0]
return m3u8_url,Host
response = await client.get(skystreaming_link, headers=headers, allow_redirects=True, impersonate = "chrome120")
soup = BeautifulSoup(response.text, 'lxml', parse_only=SoupStrainer('source'))
source_tag = soup.find('source')
m3u8_url = source_tag.get('src')
Host = m3u8_url.replace("https://","").split("/")[0]
print(Host)
return m3u8_url,Host
except Exception as e:
print("SkyStreaming failed",e)
return None,None
'''
async def webru(id,site,client):
try:
stream_url, Referer,Origin = await get_stream_link(id,site,client)
mediaproxy = config.MediaProxy
medialink = random.choice(mediaproxy)
new_stream_url = f'{medialink}proxy/hls/manifest.m3u8?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'
return new_stream_url
except Exception as e:
print("WebRu failed",e)
return None
'''
+69 -15
View File
@@ -1,28 +1,82 @@
#LOAD THE CONFIG
import json
import logging
# Open the configuration file
with open('config.json') as f:
# Load JSON data from file
config = json.load(f)
# Accessing SC_DOMAIN
SITE = config["Siti"]
FT_DOMAIN = SITE["Filmpertutti"]['domain']
SC_DOMAIN = SITE["StreamingCommunity"]['domain']
TF_DOMAIN = SITE["Tantifilm"]['domain']
LC_DOMAIN = SITE["LordChannel"]['domain']
SW_DOMAIN = SITE["StreamingWatch"]['domain']
AW_DOMAIN = SITE['AnimeWorld']['domain']
SKY_DOMAIN = SITE['SkyStreaming']['domain']
MYSTERIUS = SITE['Mysterius']['enabled']
DLHD = SITE['DaddyLiveHD']['enabled']
SC_DOMAIN = SITE["StreamingCommunity"]['url']
AW_DOMAIN = SITE['AnimeWorld']['url']
CB_DOMAIN = SITE['CB01']['url']
GS_DOMAIN = SITE['Guardaserie']['url']
GHD_DOMAIN = SITE['GuardaHD']['url']
ES_DOMAIN = SITE['Eurostreaming']['url']
GF_DOMAIN = SITE['Guardaflix']['url']
GO_DOMAIN = SITE['Guardoserie']['url']
RT_DOMAIN = SITE['Realtime']['url']
TI_DOMAIN = SITE['Toonitalia']['url']
OST_DOMAIN = SITE['OnlineSerieTV']['url']
VD_DOMAIN = SITE['Vidxgo']['url']
SC = SITE['StreamingCommunity']['enabled']
AW = SITE['AnimeWorld']['enabled']
CB = SITE['CB01']['enabled']
GS = SITE['Guardaserie']['enabled']
GHD = SITE['GuardaHD']['enabled']
ES= SITE['Eurostreaming']['enabled']
GF = SITE['Guardaflix']['enabled']
GO = SITE['Guardoserie']['enabled']
RT = SITE['Realtime']['enabled']
TI = SITE['Toonitalia']['enabled']
OST = SITE['OnlineSerieTV']['enabled']
VD = SITE['Vidxgo']['enabled']
SC_ForwardProxy = SITE['StreamingCommunity']["SC_ForwardProxy"]
GS_ForwardProxy = SITE['Guardaserie']["GS_ForwardProxy"]
GH_ForwardProxy = SITE['GuardaHD']["GH_ForwardProxy"]
VX_ForwardProxy = SITE['StreamingCommunity']["VX_ForwardProxy"]
AW_ForwardProxy = SITE['AnimeWorld']["AW_ForwardProxy"]
MX_ForwardProxy = SITE['CB01']["MX_ForwardProxy"]
CB_ForwardProxy = SITE['CB01']["CB_ForwardProxy"]
ES_ForwardProxy = SITE['Eurostreaming']['ES_ForwardProxy']
GF_ForwardProxy = SITE['Guardaflix']['GF_ForwardProxy']
GO_ForwardProxy = SITE['Guardoserie']['GO_ForwardProxy']
RT_ForwardProxy = SITE['Realtime']['RT_ForwardProxy']
OST_ForwardProxy = SITE['OnlineSerieTV']['OST_ForwardProxy']
TI_ForwardProxy = SITE['Toonitalia']['TI_ForwardProxy']
VD_ForwardProxy = SITE['Vidxgo']['VD_ForwardProxy']
GS_PROXY = SITE['Guardaserie']["GS_PROXY"]
GH_PROXY = SITE['GuardaHD']["GH_PROXY"]
CB_PROXY = SITE['CB01']["CB_PROXY"]
SC_PROXY = SITE['StreamingCommunity']["SC_PROXY"]
VX_PROXY = SITE['StreamingCommunity']["VX_PROXY"]
AW_PROXY = SITE['AnimeWorld']["AW_PROXY"]
MX_PROXY = SITE['CB01']["MX_PROXY"]
ES_PROXY = SITE['Eurostreaming']['ES_PROXY']
GF_PROXY = SITE['Guardaflix']['GF_PROXY']
GO_PROXY = SITE['Guardoserie']['GO_PROXY']
RT_PROXY = SITE['Realtime']['RT_PROXY']
TI_PROXY = SITE['Toonitalia']['TI_PROXY']
OST_PROXY = SITE['OnlineSerieTV']['OST_PROXY']
VD_PROXY = SITE['Vidxgo']['VD_PROXY']
#Captcha
CAPTCHA = config['Captcha']
UT_ForwardProxy = CAPTCHA['Uprot']['UT_ForwardProxy']
UT_PROXY = CAPTCHA['Uprot']['UT_PROXY']
#General
GENERAL = config['General']
dotenv = GENERAL["load_env"]
HOST = GENERAL["HOST"]
PORT = GENERAL["PORT"]
HF = GENERAL["HF"]
Public_Instance = GENERAL["Public_Instance"]
MediaProxy = GENERAL["MediaProxy"]
ForwardProxy = GENERAL["ForwardProxy"]
Icon = GENERAL["Icon"]
Name = GENERAL["Name"]
LEVEL = GENERAL["level"]
Global_Proxy = GENERAL["Global_Proxy"]
def setup_logging(LEVEL):
LEVEL = LEVEL.upper()
level = getattr(logging, LEVEL, logging.DEBUG)
logging.basicConfig(level=level,format='%(message)s')
logger = logging.getLogger(__name__)
return logger
+11
View File
@@ -12,3 +12,14 @@ async def get_TMDb_id_from_IMDb_id(imdb_id,client):
return tmbda['tv_results'][0]['id']
else:
return None
async def get_IMDB_id_from_TMDb_id(tmdb_id,client):
url = f"https://api.themoviedb.org/3/movie/{tmdb_id}?api_key={TMDB_KEY}"
response = await client.get(url)
if response.status_code == 200:
data = response.json()
imdb_id = data.get('imdb_id')
if imdb_id:
return imdb_id
+63 -497
View File
@@ -1,15 +1,4 @@
okru = {
"rai-1": "https://ok.ru/videoembed/7868570672752?nochat=1",
"rai-2": "https://ok.ru/videoembed/7805618364016?nochat=1",
"canale-5": "https://ok.ru/videoembed/7871149252208?nochat=1",
"italia-1": "https://ok.ru/videoembed/7393558339184?nochat=1",
"rai-premium": "https://ok.ru/videoembed/7363152715376?nochat=1",
"rai-movie": "https://ok.ru/videoembed/7384012693104?nochat=1",
"tv8": "https://ok.ru/videoembed/7681651777136?nochat=1",
"rsi-la-2": "https://ok.ru/videoembed/7681648107120?nochat=1",
"mediaset-extra": "https://ok.ru/videoembed/7363152715376?nochat=1",
"mediaset-infinity": "https://ok.ru/videoembed/6323249159792%3Fnochat=1"
}
import Src.Utilities.config as config
STREAM = {
"channels": [
@@ -19,39 +8,39 @@ STREAM = {
"name": "HD/FHD",
"genres": ["La7"],
"poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/LA7_-_Logo_2011.svg/1280px-LA7_-_Logo_2011.svg.png",
"url": "https://d3749synfikwkv.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-74ylxpgd78bpb/Live.m3u8"
"url": "https://d1chghleocc9sm.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-evfku205gqrtf/Live.m3u8"
},
{
"id": "rai-1",
"title": "Rai 1",
"name": "Full HD Http",
"name": "Full HD ",
"genres": ["Rai"],
"poster": "https://i.imgur.com/OPV9jJD.png",
"url": "http://173.208.52.200/rai1/index.m3u8"
"poster": "https://i.imgur.com/bb72vqh.jpeg",
"url": "https://viamotionhsi.netplus.ch/live/eds/rai1/browser-HLS8/rai1.m3u8"
},
{
"id": "rai-2",
"title": "Rai 2",
"name": "Full HD Http",
"name": "Full HD ",
"genres": ["Rai"],
"poster": "https://i.imgur.com/uHtYy8w.png",
"url": "http://173.208.52.200/rai2/index.m3u8"
"poster": "https://i.imgur.com/jX95Qod.jpeg",
"url": "https://viamotionhsi.netplus.ch/live/eds/rai2/browser-HLS8/rai2.m3u8"
},
{
"id": "rai-3",
"title": "Rai 3",
"name": "Full HD Http",
"name": "Full HD ",
"genres": ["Rai"],
"poster": "https://i.imgur.com/iXst6me.png",
"url": "http://173.208.52.200/rai3/index.m3u8"
"poster": "https://i.imgur.com/fgAh9if.jpeg",
"url": "https://viamotionhsi.netplus.ch/live/eds/rai3/browser-HLS8/rai3.m3u8"
},
{
"id": "rai-4",
"title": "Rai 4",
"name": "Full HD Http",
"name": "Full HD ",
"genres": ["Rai"],
"poster": "https://i.imgur.com/KGg3hvr.png",
"url": "http://173.208.52.200/rai4/index.m3u8"
"poster": "https://i.imgur.com/NryLzhA.jpeg",
"url": "https://raiquattro1-dash-live.akamaized.net/dash/live/663977/raiquattro1/manifest.mpd"
},
{
"id": "rai-premium",
@@ -59,7 +48,7 @@ STREAM = {
"name": "Full HD",
"genres": ["Rai"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/rai-premium_c.png",
"url": "https://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=746992"
"url": "https://raipremium1-dash-live.akamaized.net/dash/live/663979/raipremium1/manifest.mpd"
},
{
"id": "rai-4k",
@@ -76,7 +65,7 @@ STREAM = {
"name": "",
"genres": ["Rai"],
"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",
"url": "https://streamcdnb4-8e7439fdb1694c8da3a0fd63e4dda518.msvdn.net/rainews1/hls/playlist_mo.m3u8"
"url": "https://streamcdnb2-8e7439fdb1694c8da3a0fd63e4dda518.msvdn.net/rainews1/hls/playlist_mo.m3u8"
},
{
"id": "rai-movie",
@@ -84,7 +73,7 @@ STREAM = {
"name": "",
"genres": ["Rai"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/rai-movie_c.png",
"url": "https://m3u.iranvids.com/rai-movie/output.m3u8"
"url": "https://raimovie1-dash-live.akamaized.net/dash/live/663983/raimovie1/manifest.mpd"
},
{
"id": "rai-sport",
@@ -92,15 +81,15 @@ STREAM = {
"name": "",
"genres": ["Rai"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/rai-sport_c.png",
"url": "https://m3u.iranvids.com/rai-sport01/output.m3u8"
"url": "https://viamotionhsi.netplus.ch/live/eds/raisport1/browser-HLS8/raisport1.m3u8"
},
{
"id": "rete-4",
"title": "Rete 4",
"name": "Full HD Http",
"name": "Full HD",
"genres": ["Mediaset"],
"poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5f/Rete_4_2018.svg/1024px-Rete_4_2018.svg.png",
"url": "http://173.208.52.200/rete4/index.m3u8"
"url": "https://live02-seg.msf.cdn.mediaset.net/live/ch-r4/r4-clr.isml/index.m3u8"
},
{
"id": "euronews",
@@ -108,23 +97,22 @@ STREAM = {
"name": "720p",
"genres": ["Euronews"],
"poster": "https://yt3.googleusercontent.com/t3slq37NYJRuP2UoEZDoPKyMClKyQULG8-j2DEfzL1XXcBvFpR6z6HD7rtc0wDn8Mqt0OtpU=s900-c-k-c0x00ffffff-no-rj",
"url": "https://rakuten-euronews-3-it.samsung.wurl.tv/manifest/playlist.m3u8"
},
{
"id": "canale-5",
"title": "Canale 5",
"name": "Full HD Http",
"name": "Full HD",
"genres": ["Mediaset"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/canale-5_c.png",
"url": "http://173.208.52.200/canale5/index.m3u8"
"url": "https://viamotionhsi.netplus.ch/live/eds/canale5/browser-HLS8/canale5.m3u8"
},
{
"id": "italia-1",
"title": "Italia 1",
"name": "Full HD Http",
"name": "Full HD",
"genres": ["Mediaset"],
"poster": "https://upload.wikimedia.org/wikipedia/en/thumb/e/e2/Italia_1.svg/1024px-Italia_1.svg.png",
"url": "http://173.208.52.200/italia1/index.m3u8"
"url": "https://viamotionhsi.netplus.ch/live/eds/italia1/browser-HLS8/italia1.m3u8"
},
{
"id": "topcrime",
@@ -173,13 +161,6 @@ STREAM = {
"genres": ["A+E"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/history_c.png"
},
{
"id": "comedy-central",
"title": "Comedy Central",
"name": "",
"genres": ["Paramount"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/comedy-central_c.png"
},
{
"id": "sky-tg-24",
"title": "Sky TG24",
@@ -204,308 +185,13 @@ STREAM = {
"poster": "https://static.sky.it/static_clientlibs/skycielo/clientlibs/clientlib-site/resources/images/facebook.jpg",
"url": "https://hlslive-web-gcdn-skycdn-it.akamaized.net/TACT/11219/cieloweb/master.m3u8?hdnea=st=1701861650~exp=1765449000~acl=/*~hmac=84c9f3f71e57b13c3a67afa8b29a8591ea9ed84bf786524399545d94be1ec04d"
},
{
"id": "sky-cinema-action",
"title": "Sky Cinema Action",
"name": "",
"genres": ["Sky"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-action_c.png"
},
{
"id": "sky-arte",
"title": "Sky Arte",
"name": "",
"genres": ["Sky"],
"poster": "https://www.davinciface.com/wp-content/uploads/2022/07/sky_arte_logo-270x270.jpg"
},
{
"id": "sky-atlantic",
"title": "Sky Atlantic",
"name": "",
"genres": ["Sky"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-atlantic_c.png"
},
{
"id": "sky-cinema-collection",
"title": "Sky Cinema Collection",
"name": "",
"genres": ["Sky"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-collection_c.png"
},
{
"id": "sky-cinema-comedy",
"title": "Sky Cinema Comedy",
"name": "",
"genres": ["Sky"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-comedy_c.png"
},
{
"id": "sky-cinema-drama",
"title": "Sky Cinema Drama",
"name": "",
"genres": ["Sky"],
"poster":"https://i.imgur.com/Z8hr5aR.png"
},
{
"id": "sky-cinema-due",
"title": "Sky Cinema Due",
"name": "",
"genres": ["Sky"],
"poster": "https://i.imgur.com/xfbZiXs.png"
},
{
"id": "sky-cinema-family",
"title": "Sky Cinema Family",
"name": "",
"genres": ["Sky"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-family_c.png"
},
{
"id": "sky-cinema-romance",
"title": "Sky Cinema Romance",
"name": "",
"genres": ["Sky"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-romance_c.png"
},
{
"id": "sky-cinema-suspence",
"title": "Sky Cinema Suspence",
"name": "",
"genres": ["Sky"],
"poster": "https://i.imgur.com/vS97bNg.png"
},
{
"id": "sky-cinema-uno",
"title": "Sky Cinema Uno",
"name": "",
"genres": ["Sky"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-cinema-1_c.png"
},
{
"id": "sky-crime",
"title": "Sky Crime",
"name": "",
"genres": ["Sky"],
"poster": "https://i.imgur.com/j2JdQaH.png"
},
{
"id": "sky-documentaries",
"title": "Sky Documentaries",
"name": "",
"genres": ["Sky"],
"poster": "https://artworks.thetvdb.com/banners/posters/117551-3.jpg"
},
{
"id": "sky-investigation",
"title": "Sky Investigation",
"name": "",
"genres": ["Sky"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-investigation_c.png"
},
{
"id": "sky-nature",
"title": "Sky Nature",
"name": "",
"genres": ["Sky"],
"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"
},
{
"id": "sky-serie",
"title": "Sky Serie",
"name": "",
"genres": ["Sky"],
"poster": "https://i.imgur.com/FYvSq5T.png"
},
{
"id": "sky-uno",
"title": "Sky Uno",
"name": "",
"genres": ["Sky"],
"poster": "https://www.miotvonline.com/wp-content/uploads/2020/09/sky-uno-straming-live-miotv.jpg"
},
{
"id": "sky-sport-24",
"title": "Sky Sport 24",
"name": "",
"genres": ["Sky"],
"poster": "https://img2.sport-tv-guide.live/images/tv-station-sky-sport24-it-356.png"
},
{
"id": "sky-sport-golf",
"title": "Sky Sport Golf",
"name": "",
"genres": ["Sky"],
"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"
},
{
"id": "sky-sport-251",
"title": "Sky Sport 251",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-252",
"title": "Sky Sport 252",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-253",
"title": "Sky Sport 253",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-254",
"title": "Sky Sport 254",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-255",
"title": "Sky Sport 255",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-256",
"title": "Sky Sport 256",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-257",
"title": "Sky Sport 257",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-258",
"title": "Sky Sport 258",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-259",
"title": "Sky Sport 259",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-260",
"title": "Sky Sport 260",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-261",
"title": "Sky Sport 261",
"name": "",
"genres": ["Sky"],
"poster": "https://logodownload.org/wp-content/uploads/2020/06/sky-sports-logo-0-1.png"
},
{
"id": "sky-sport-max",
"title": "Sky Sport Max",
"name": "",
"genres": ["Sky"],
"poster": "https://i.imgur.com/TWl58VI.png"
},
{
"id": "sky-sport-uno",
"title": "Sky Sport Uno",
"name": "",
"genres": ["Sky"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-sport-1_c.png"
},
{
"id": "sky-sport-f1",
"title": "Sky Sport F1",
"name": "",
"genres": ["Sky"],
"poster": "https://i1.wp.com/cache.pressmailing.net/thumbnail/story_hires/395b1e2f-a1c6-4cf6-9869-02155da4021f/Sky_F1_Logo.jpg.jpg"
},
{
"id": "sky-sport-motogp",
"title": "Sky Sport MotoGP",
"name": "",
"genres": ["Sky"],
"poster": "https://img2.sport-tv-guide.live/images/tv-station-sky-sport-motogp-360.png"
},
{
"id": "sky-sport-calcio",
"title": "Sky Sport Calcio",
"name": "",
"genres": ["Sky"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/sky-sport-2_c.png"
},
{
"id": "sky-sport-arena",
"title": "Sky Sport Arena",
"name": "",
"genres": ["Sky"],
"poster": "https://img2.sport-tv-guide.live/images/tv-station-sky-sport-arena-354.png"
},
{
"id": "sky-sport-tennis",
"title": "Sky Sport Tennis",
"name": "",
"genres": ["Sky"],
"poster": "https://pbs.twimg.com/profile_images/1752313472325431296/jr-YrkR6_400x400.png"
},
{
"id": "sky-sport-nba",
"title": "Sky Sport NBA",
"name": "",
"genres": ["Sky"],
"poster": "https://www.nbareligion.com/wp-content/uploads/2019/09/sky-sport-nba.jpg"
},
{
"id": "dazn-zona-a",
"title": "DAZN Zona A",
"name": "",
"genres": ["DAZN"],
"poster": "https://i.ytimg.com/vi/0cEfGLq-tz4/maxresdefault.jpg"
},
{
"id": "dazn-1",
"title": "DAZN 1",
"name": "",
"genres": ["DAZN"],
"poster": "https://i.ytimg.com/vi/0cEfGLq-tz4/maxresdefault.jpg"
},
{
"id": "eurosport-1",
"title": "Eurosport 1",
"name": "",
"genres": ["Warner Bros"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/eurosport-1_c.png"
},
{
"id": "eurosport-2",
"title": "Eurosport 2",
"name": "",
"genres": ["Warner Bros"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/eurosport-2_c.png"
},
{
"id": "dmax",
"title": "DMAX",
"name": "",
"genres": ["Warner Bros"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/d-max_c.png",
"url": "https://amg16146-wbdi-amg16146c8-samsung-it-1841.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-dmax-samsungit/playlist.m3u8"
"url": "https://d2j2nqgg7bzth.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-02k1gv1j0ufwn/DMAX_IT.m3u8"
},
{
"id": "foodnetwork",
@@ -513,7 +199,7 @@ STREAM = {
"name": "",
"genres": ["Warner Bros"],
"poster":"https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Food_Network_logo.svg/1024px-Food_Network_logo.svg.png",
"url": "https://amg16146-wbdi-amg16146c3-samsung-it-1836.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-foodnetwork-samsungit/playlist.m3u8"
"url": "https://dk3okdd5036kz.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-o4pw0nc02sthz/Foodnetwork_IT.m3u8"
},
{
"id": "frisbee",
@@ -521,7 +207,7 @@ STREAM = {
"name": "",
"genres": ["Warner Bros"],
"poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/FRISBEE_LOGO_2015.png/1280px-FRISBEE_LOGO_2015.png",
"url": "https://amg16146-wbdi-amg16146c7-samsung-it-1840.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-frisbee-samsungit/playlist.m3u8"
"url": "https://d6m7lubks416z.cloudfront.net/v1/manifest/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-zmbstsedxme9s/2fbb852d-6778-4a74-955b-59164269c705/0.m3u8"
},
{
"id": "giallo",
@@ -529,7 +215,7 @@ STREAM = {
"name": "",
"genres": ["Warner Bros"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/giallo_c.png",
"url": "https://amg16146-wbdi-amg16146c5-samsung-it-1838.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-giallo-samsungit/playlist.m3u8"
"url": "https://d9fqo6nfqlv2h.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-ulukbrgm1n3yb/Giallo_IT.m3u8"
},
{
"id": "hgtv",
@@ -537,7 +223,7 @@ STREAM = {
"name": "",
"genres": ["Warner Bros"],
"poster": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/HGTV_2010.svg/1920px-HGTV_2010.svg.png",
"url": "https://amg16146-wbdi-amg16146c9-samsung-it-1842.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-hgtv-samsungit/playlist.m3u8"
"url": "https://timlivetu0.cb.ticdn.it/Content/DASH/Live/channel(hgtvhd)/manifest.mpd"
},
{
"id": "k2",
@@ -545,7 +231,7 @@ STREAM = {
"name": "",
"genres": ["Warner Bros"],
"poster": "https://upload.wikimedia.org/wikipedia/it/thumb/7/70/K2_logo_%282013%29.svg/800px-K2_logo_%282013%29.svg.png",
"url": "https://amg16146-wbdi-amg16146c6-samsung-it-1839.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-k2-samsungit/playlist.m3u8"
"url": "https://d1pmpe0hs35ka5.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-39hsskpppgf72/K2_IT.m3u8"
},
{
"id": "nove",
@@ -553,7 +239,7 @@ STREAM = {
"name": "",
"genres": ["Warner Bros"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/nove_c.png",
"url": "https://amg16146-wbdi-amg16146c1-samsung-it-1831.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-nove-samsungit/playlist.m3u8"
"url": "https://d31mw7o1gs0dap.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-y5pbi2sq9r609/NOVE_IT.m3u8"
},
{
@@ -562,7 +248,7 @@ STREAM = {
"name": "",
"genres": ["Warner Bros"],
"poster": "https://www.sorrisi.com/guidatv/bundles/tvscnewsite/css/images/loghi/real-time_c.png",
"url": "https://amg16146-wbdi-amg16146c2-samsung-it-1835.playouts.now.amagi.tv/playlist/amg16146-warnerbrosdiscoveryitalia-realtime-samsungit/playlist.m3u8"
"url": "https://d3562mgijzx0zq.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-kizqtzpvvl3i8/Realtime_IT.m3u8"
},
{
"id": "supertennis",
@@ -570,7 +256,7 @@ STREAM = {
"name": "",
"genres": ["FIT"],
"poster": "https://upload.wikimedia.org/wikipedia/commons/0/02/SUPERTENNIS_HD.png",
"url": "https://live-embed.supertennix.hiway.media/restreamer/supertennix_client/gpu-a-c0-16/restreamer/rtmp/hls/h24_supertennix/manifest.m3u8"
"url": "https://live-embed.supertennix.hiway.media/restreamer/supertennix_client/gpu-a-c0-16/restreamer/outgest/aa3673f1-e178-44a9-a947-ef41db73211a/manifest.m3u8"
},
{
"id": "solocalcio",
@@ -586,22 +272,15 @@ STREAM = {
"name": "",
"genres": ["Sportitalia"],
"poster": "https://upload.wikimedia.org/wikipedia/en/5/55/Sportitalia.jpg",
"url": "https://di-kzbhv8pw.vo.lswcdn.net/sportitalia/sihd/playlist.m3u8"
},
{
"id": "sportitalia24",
"title": "Sportitalia 24",
"name": "",
"genres": ["Sportitalia"],
"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",
"url": "https://di-kzbhv8pw.vo.lswcdn.net/sportitalia/sihd/playlist.m3u8"
"url": "https://origin.streamup.eu/sportitaliain/sisolocalcio/playlist.m3u8"
},
{
"id": "rsi-la-2",
"title": "RSI LA 2",
"name": "",
"genres": ["RSI"],
"poster": "https://livehere.one/img/rsi.png"
"poster": "https://livehere.one/img/rsi.png",
"url": "https://viamotionhsi.netplus.ch/live/eds/rsila2hd/browser-HLS8/rsila2hd.m3u8"
},
{
"id": "baby-shark-tv",
@@ -611,21 +290,13 @@ STREAM = {
"poster": "https://flxt.tmsimg.com/assets/p19459897_b_v13_aa.jpg",
"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"
},
{
"id": "adrenaline-movies",
"title": "Rakuten Adrenaline Movies",
"name": "",
"genres": ["Rakuten"],
"poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBC11000050E_20231213T033148SQUARE.png_20231213033148.png",
"url": "https://minerva-fullmoon-1-eu.plex.wurl.tv/4300.m3u8"
},
{
"id": "bizzarro-movies",
"title": "Bizzarro Movies",
"name": "",
"genres": ["Rakuten"],
"poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBA3300024IU_20240214T034959SQUARE.png_20240214034959.png",
"url": "https://minerva-bizzarromovies-1-eu.plex.wurl.tv/4300.m3u8"
"url": "https://797fbe152cbe418697be037aef3a708f.mediatailor.us-east-1.amazonaws.com/v1/master/44f73ba4d03e9607dcd9bebdcb8494d86964f1d8/Samsung-it_BizzarroMovies/playlist.m3u8"
},
{
"id": "cinema-italiano",
@@ -633,7 +304,7 @@ STREAM = {
"name": "",
"genres": ["Rakuten"],
"poster": "https://tvpnlogopeu.samsungcloud.tv/platform/image/sourcelogo/vc/00/02/34/ITBA33000238E_20240313T074122SQUARE.png",
"url": "https://minerva-cinemasegreto-1-eu.plex.wurl.tv/4300.m3u8"
"url": "http://stitcher-ipv4.pluto.tv/v1/stitch/embed/hls/channel/608aa512d67fd900072323db/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&profileFloor=&profileLimit=&embedPartner=samsung-tvplus"
},
{
"id": "le-vite-degli-altri",
@@ -743,94 +414,17 @@ STREAM = {
}
REALTIME = {}
webru_vary = {
"sky-cinema-action": "calcioXac",
"comedy-central": "calcioXcomedycentral",
"history": "calcioXhistory",
"sky-arte": "calcioXskyarte",
"sky-atlantic": "calcioXskyatlantic",
"sky-cinema-collection": "calcioXskycinemacollection",
"sky-cinema-comedy": "calcioXskycinemacomedy",
"sky-cinema-drama": "calcioXskycinemadrama",
"sky-cinema-due": "calcioXskycinemadue",
"sky-cinema-family": "calcioXskycinemafamily",
"sky-cinema-romance": "calcioXskycinemaromance",
"sky-cinema-suspence": "calcioXskycinemasuspence",
"sky-cinema-uno": "calcioXskycinemauno",
"sky-crime": "calcioXskycrime",
"sky-documentaries": "calcioXskydocumentaries",
"sky-investigation": "calcioXskyinvestigation",
"sky-nature": "calcioXskynature",
"sky-serie": "calcioXskyserie",
"sky-uno": "calcioXskyuno",
"sky-sport-24": "calcioXskysport24",
}
'''
"sky-sport-golf": "https://webuit.mizhls.ru/lb/calcioXskysportgolf/index.m3u8",
"sky-sport-251": "https://webuit.mizhls.ru/lb/calcioXskysport251/index.m3u8",
"sky-sport-253": "https://webuit.mizhls.ru/lb/calcioXskysport253/index.m3u8",
"sky-sport-max": "https://webuit.mizhls.ru/lb/calcioXskysportmax/index.m3u8",
"sky-sport-255": "https://webuit.mizhls.ru/lb/calcioXskysport255/index.m3u8",
"sky-sport-259": "https://webuit.mizhls.ru/lb/calcioXsky259/index.m3u8",
"sky-sport-252": "https://webuit.mizhls.ru/lb/calcioXskysport252/index.m3u8",
"sky-sport-254": "https://webuit.mizhls.ru/lb/calcioXskysport254/index.m3u8",
"sky-sport-256": "https://webuit.mizhls.ru/lb/calcioXskysport256/index.m3u8",
"sky-sport-257": "https://webuit.mizhls.ru/lb/calcioXskysport257/index.m3u8",
"sky-sport-258": "https://webuit.mizhls.ru/lb/calcioXsky258/index.m3u8",
"sky-sport-259": "https://webuit.mizhls.ru/lb/calcioXsky259/index.m3u8",
"sky-sport-260": "https://webuit.mizhls.ru/lb/calcioXsky260/index.m3u8",
"sky-sport-261": "https://webuit.mizhls.ru/lb/calcioXsky261/index.m3u8",
"eurosport-1": "https://webuit.mizhls.ru/lb/calcioXeurosport1/index.m3u8",
"eurosport-2": "https://webuit.mizhls.ru/lb/calcioXeurosport2/index.m3u8",
"sky-sport-uno": "https://webuit.mizhls.ru/lb/calcioXskysportuno/index.m3u8",
"sky-sport-f1": "https://webuit.mizhls.ru/lb/calcioXskysportf1/index.m3u8",
"sky-sport-motogp": "https://webuit.mizhls.ru/lb/calcioXskysportmotogp/index.m3u8",
"sky-sport-calcio": "https://webuit.mizhls.ru/lb/calcioXskysportcalcio/index.m3u8",
"sky-sport-arena": "https://webuit.mizhls.ru/lb/calcioXskysportarena/index.m3u8",
"sky-sport-tennis": "https://webuit.mizhls.ru/lb/calcioXskysporttennis/index.m3u8",
"sky-sport-nba": "https://webuit.mizhls.ru/lb/calcioXskysportnba/index.m3u8",
'''
#"dazn-zona-a": "https://webuit.mizhls.ru/lb/calcioXzona/index.m3u8"
webru_dlhd = {
"sky-sport-tennis": "premium576",
"sky-sport-uno": "premium461",
"sky-cinema-collection": "premium859",
"sky-cinema-romance": "premium864",
"sky-sport-24": "premium869",
"sky-sport-254": "premium874",
"sky-sport-f1": "premium577",
"sky-sport-arena": "premium462",
"sky-cinema-uno": "premium860",
"sky-cinema-family": "premium865",
"sky-sport-calcio": "premium870",
"sky-sport-255": "premium875",
"sky-cinema-action": "premium861",
"sky-cinema-due": "premium866",
"sky-sport-251": "premium871",
"sky-sport-256": "premium876",
"sky-sport-golf": "premium574",
"sky-uno": "premium881",
"sky-cinema-comedy": "premium862",
"sky-cinema-drama": "premium867",
"sky-sport-252": "premium872",
"sky-sport-257": "premium877",
"sky-sport-motogp": "premium575",
"sky-sport-football": "premium460",
"sky-cinema-uno-24": "premium863",
"sky-cinema-suspence": "premium868",
"sky-sport-253": "premium873",
"sky-serie": "premium880",
"dazn-1": "premium877"
}
extra_sources = {
"rai-1": ["https://m3u.iranvids.com/rai01/output.m3u8"],
"rai-2": ["https://m3u.iranvids.com/rai02/output.m3u8"],
"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"],
"rete-4":["https://tvit.leicaflorianrobert.dev/mediaset/rete-4/stream.m3u8","https://live02-seg.msf.cdn.mediaset.net/live/ch-r4/r4-clr.isml/index.m3u8"],
"canale-5":["https://live02-seg.msf.cdn.mediaset.net/live/ch-c5/c5-clr.isml/index.m3u8","https://tvit.leicaflorianrobert.dev/mediaset/canale-5/stream.m3u8"],
"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"],
"rai-1": ["https://ilglobotv-live.akamaized.net/channels/RAI1/Live.m3u8"],
"rai-2": ["https://ilglobotv-live.akamaized.net/channels/RAI2/Live.m3u8"],
"rai-3": ["https://ilglobotv-live.akamaized.net/channels/RAI2/Live.m3u8","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"],
"rete-4":["https://tvit.leicaflorianrobert.dev/mediaset/rete-4/stream.m3u8","https://timlivetu0.cb.ticdn.it/Content/DASH/Live/channel(rete4)/manifest.mpd"],
"canale-5":["https://timlivetu0.cb.ticdn.it/Content/DASH/Live/channel(canale5)/manifest.mpd","https://tvit.leicaflorianrobert.dev/mediaset/canale-5/stream.m3u8",'https://timlivetu0.cb.ticdn.it/Content/DASH/Live/channel(canale5)/manifest.mpd','https://live02-seg.msf.cdn.mediaset.net/live/ch-c5/c5-clr.isml/index.m3u8'],
"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",'https://timlivetu0.cb.ticdn.it/Content/DASH/Live/channel(italia1)/manifest.mpd'],
"rai-4k": ["https://list.iptvcat.com/my_list/s/fbf04fbd9694eee71b5af9f12e49538d.m3u8"],
"rai-news":["https://8e7439fdb1694c8da3a0fd63e4dda518.msvdn.net/rainews1/hls/playlist_mo.m3u8"],
"topcrime": ["https://tvit.leicaflorianrobert.dev/mediaset/top-crime/stream.m3u8"],
@@ -843,56 +437,28 @@ extra_sources = {
"dmax": ["https://tvit.leicaflorianrobert.dev/discovery/dmax/stream.m3u8"],
"nove": ["https://tvit.leicaflorianrobert.dev/discovery/nove/stream.m3u8"],
"euronews": ["https://amg00882-amg00882c4-wedotv-eu-4536.playouts.now.amagi.tv/playlist/amg00882-euronewsfast-euronewsita-wedotveu/playlist.m3u8?app_bundle=&app_name=wedotv&app_store_url=https://wedotv.com&url=https://wedotv.com&gdpr=1&channel_name=Euronews - Italiano&content_custom_1_param=Euronews - Italiano"],
"doctor-who": ["https://amg00793-amg00793c17-samsung-it-4577.playouts.now.amagi.tv/playlist/amg00793-bbcstudios-drwhoitaly-samsungit/playlist.m3u8"]
}
skystreaming ={
"sky-sport-tennis": "https://skystreaming.guru/embed/MKCKP",
"sky-sport-24": "https://skystreaming.guru/embed/GB7zq",
"sky-sport-251": "https://skystreaming.guru/embed/drHbM",
"sky-sport-252": "https://skystreaming.guru/embed/m5kfg",
"sky-sport-253": "https://skystreaming.guru/embed/YprHf",
"sky-sport-254": "https://skystreaming.guru/embed/wroRV",
"sky-sport-255": "https://skystreaming.guru/embed/0TixN",
"sky-sport-256": "https://skystreaming.guru/embed/8g8bh",
"sky-sport-257": "https://skystreaming.guru/embed/ri859",
"sky-sport-258": "https://skystreaming.guru/embed/UoJuW",
"sky-sport-259": "https://skystreaming.guru/embed/squCy",
"sky-sport-260": "https://skystreaming.guru/embed/Z5h2e",
"sky-sport-261": "https://skystreaming.guru/embed/Hz9FW",
"sky-sport-uno": "https://skystreaming.guru/embed/tb1np",
"sky-sport-f1": "https://skystreaming.guru/embed/MLkym",
"sky-sport-motogp": "https://skystreaming.guru/embed/ARFFv",
"sky-sport-calcio": "https://skystreaming.guru/embed/STOZT",
"sky-sport-arena": "https://skystreaming.guru/embed/NkEda",
"sky-sport-max": "https://skystreaming.guru/embed/4QzWz",
"sky-sport-nba": "https://skystreaming.guru/embed/saR8j",
"sky-sport-golf": "https://skystreaming.guru/embed/s9L5f",
"eurosport-1": "https://skystreaming.guru/embed/Vyv99",
"eurosport-2": "https://skystreaming.guru/embed/um8E5",
"dazn-zona-a": ["https://hls.psz.pm/hls/serie/index.m3u8","https://hls.cls.autos/hls/serie/index.m3u8"],
"sportitalia": "https://hls.cls.autos/hls/sportitalia/index.m3u8",
}
huhu = {
"canale-5": "1101559666",
"sky-sport-motogp": "2090703806",
"rai-1": "1225653759",
"sky-cinema-drama": "1235530177",
"sky-cinema-action": "3812796171",
"Dazn": "2745635299",
"sky-sport-uno": "3192996672",
"canale-5": "1534161807",
"mediaset-extra": "477466531",
"Dazn-1": "1376440573",
"sky-sport-24": "2775802255",
"sky-sport-24": "3445562519",
"doctor-who": ["https://amg00793-amg00793c17-samsung-it-4577.playouts.now.amagi.tv/playlist/amg00793-bbcstudios-drwhoitaly-samsungit/playlist.m3u8"],
"supertennis": ["https://live-embed.supertennix.hiway.media/restreamer/supertennix_client/gpu-a-c0-16/restreamer/outgest/h24_supertennix/manifest.m3u8"]
}
provider_map = {
'SC': 'STREAMINGCOMMUNITY',
'SC_FS': 'SC_FAST_SEARCH',
'SC_MFP': 'SC_MFP',
'LC': 'LORDCHANNEL',
'SW': 'STREAMINGWATCH',
'TF_FS': 'TF_FAST_SEARCH',
'TF': 'TANTIFILM', # Assuming 'TF' should also be handled
'FT': 'FILMPERTUTTI',
'AW': 'ANIMEWORLD'
'AW': 'ANIMEWORLD',
'DDL': 'DDLSTREAM',
'CB': 'CB01',
"GS": "GUARDASERIE",
"GHD": "GUARDAHD",
"OST": "ONLINESERIETV",
"ES": "EUROSTREAMING",
"GO": "GUARDOSERIE",
"RT": "REALTIME",
"TI": "TOONITALIA",
"GF": "GUARDAFLIX",
"OST": "ONLINESERIETV",
"VD": "VIDXGO"
}
+178
View File
@@ -0,0 +1,178 @@
#Adapted for use in MammaMia from:
#https://github.com/einars/js-beautify/blob/master/python/jsbeautifier/unpackers/packer.py
# Unpacker for Dean Edward's p.a.c.k.e.r, a part of javascript beautifier
# by Einar Lielmanis <[email protected]>
#
# written by Stefano Sanfilippo <[email protected]>
#
# usage:
#
# if detect(some_string):
# unpacked = unpack(some_string)
#
from fake_headers import Headers
"""Unpacker for Dean Edward's p.a.c.k.e.r"""
import re
from bs4 import BeautifulSoup, SoupStrainer
import logging
import Src.Utilities.config as config
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
def detect(source):
if "eval(function(p,a,c,k,e,d)" in source:
mystr = "smth"
return mystr is not None
def unpack(source):
"""Unpacks P.A.C.K.E.R. packed js code."""
payload, symtab, radix, count = _filterargs(source)
if count != len(symtab):
raise UnpackingError("Malformed p.a.c.k.e.r. symtab.")
try:
unbase = Unbaser(radix)
except TypeError:
raise UnpackingError("Unknown p.a.c.k.e.r. encoding.")
def lookup(match):
"""Look up symbols in the synthetic symtab."""
word = match.group(0)
return symtab[unbase(word)] or word
payload = payload.replace("\\\\", "\\").replace("\\'", "'")
source = re.sub(r"\b\w+\b", lookup, payload)
return _replacestrings(source)
def _filterargs(source):
"""Juice from a source file the four args needed by decoder."""
juicers = [
(r"}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\), *(\d+), *(.*)\)\)"),
(r"}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\)"),
]
for juicer in juicers:
args = re.search(juicer, source, re.DOTALL)
if args:
a = args.groups()
if a[1] == "[]":
a = list(a)
a[1] = 62
a = tuple(a)
try:
return a[0], a[3].split("|"), int(a[1]), int(a[2])
except ValueError:
raise UnpackingError("Corrupted p.a.c.k.e.r. data.")
# could not find a satisfying regex
raise UnpackingError(
"Could not make sense of p.a.c.k.e.r data (unexpected code structure)"
)
def _replacestrings(source):
"""Strip string lookup table (list) and replace values in source."""
match = re.search(r'var *(_\w+)\=\["(.*?)"\];', source, re.DOTALL)
if match:
varname, strings = match.groups()
startpoint = len(match.group(0))
lookup = strings.split('","')
variable = "%s[%%d]" % varname
for index, value in enumerate(lookup):
source = source.replace(variable % index, '"%s"' % value)
return source[startpoint:]
return source
class Unbaser(object):
"""Functor for a given base. Will efficiently convert
strings to natural numbers."""
ALPHABET = {
62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
95: (
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
),
}
def __init__(self, base):
self.base = base
# fill elements 37...61, if necessary
if 36 < base < 62:
if not hasattr(self.ALPHABET, self.ALPHABET[62][:base]):
self.ALPHABET[base] = self.ALPHABET[62][:base]
# attrs = self.ALPHABET
# print ', '.join("%s: %s" % item for item in attrs.items())
# If base can be handled by int() builtin, let it do it for us
if 2 <= base <= 36:
self.unbase = lambda string: int(string, base)
else:
# Build conversion dictionary cache
try:
self.dictionary = dict(
(cipher, index) for index, cipher in enumerate(self.ALPHABET[base])
)
except KeyError:
raise TypeError("Unsupported base encoding.")
self.unbase = self._dictunbaser
def __call__(self, string):
return self.unbase(string)
def _dictunbaser(self, string):
"""Decodes a value to an integer."""
ret = 0
for index, cipher in enumerate(string[::-1]):
ret += (self.base**index) * self.dictionary[cipher]
return ret
class UnpackingError(Exception):
"""Badly packed source or general error. Argument is a
meaningful description."""
pass
random_headers = Headers()
async def eval_solver(stream_link,proxies, ForwardProxy, client,pattern):
try:
headers = random_headers.generate()
headers["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
headers["accept-language"] = 'en-US,en;q=0.5'
if len(stream_link) <= 200:
response = await client.get( ForwardProxy + stream_link, allow_redirects=True, timeout=30, headers = headers, proxies = proxies, impersonate = "chrome124")
text = response.text
logger.debug("Eval:",response.status_code)
else:
text = stream_link
soup = BeautifulSoup(text, "lxml",parse_only=SoupStrainer("script"))
script_all = soup.find_all("script")
for i in script_all:
if detect(i.text):
unpacked_code = unpack(i.text)
match = re.search(pattern, unpacked_code)
if match:
m3u8_url = match.group(1)
return m3u8_url
except Exception as e:
logger.debug("Eval solver error\n",e)
raise Exception("Error in eval_solver")
#Testing
async def test_animeworld():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await eval_solver("https://mixdrop.cv/e/l6kqxrm4t4l4or",{},"",client)
if __name__ == "__main__":
import asyncio
asyncio.run(test_animeworld())
#python3 -m Src.Utilities.eval
+87 -27
View File
@@ -16,21 +16,16 @@ def get_info_tmdb(tmbda,ismovie,type):
show= tv.details(tmbda)
showname = show.name
if type == "Filmpertutti":
date= show.first_air_date
date = date.split("-")[0]
print("Real date",date)
return showname,date
return showname
elif type == "StreamingCommunity":
full_date = show.first_air_date
date = full_date.split("-")[0]
print(date)
return showname,date
elif type == "StreamingCommunityFS":
return showname
elif type == "Tantifilm":
date = show.first_air_date
date = date.split("-")[0]
print("Real date",date)
return showname,date
elif type == "TantifilmFS":
return showname
@@ -39,12 +34,10 @@ def get_info_tmdb(tmbda,ismovie,type):
elif type == "LordChannel":
date = show.first_air_date
date = date.split("-")[0]
print("Real date",date)
return showname,date
elif type == "StreamingWatch":
date = show.first_air_date
date = date.split("-")[0]
print("Real date",date)
return showname,date
elif type == "DDLStream":
return showname
@@ -56,6 +49,25 @@ def get_info_tmdb(tmbda,ismovie,type):
date = show.first_air_date
date = date.split("-")[0]
return showname,date
elif type == "Guardaserie":
date = show.first_air_date
date = date.split("-")[0]
return showname,date
elif type == "Eurostreaming":
date = show.first_air_date
date = date.split("-")[0]
return showname,date
elif type == "Guardoserie":
date = show.first_air_date
date = date.split("-")[0]
return showname,date
elif type == 'Realtime':
date = show.first_air_date
return showname,date
elif type == 'Toonitalia':
date = show.first_air_date
date = date.split("-")[0]
return showname,date
elif ismovie == 1:
movie = Movie()
@@ -63,20 +75,16 @@ def get_info_tmdb(tmbda,ismovie,type):
showname= show.title
#Get all release dates
if type == "Filmpertutti":
date = show.release_dates
date = date.split("-")[0]
#GET US RELEASE DATE because filmpertutti somewhy uses US release date
return showname,date
elif type == "StreamingCommunity":
date = show.release_dates
date = date.split("-")[0]
return showname
elif type == "StreamingCommunity":
date = show.release_date
date = date.split("-")[0]
return showname,date
elif type == "StreamingCommunityFS":
return showname
elif type == "Tantifilm":
date = show.release_date
date = date.split("-")[0]
print("Real date",date)
return showname,date
elif type == "TantifilmFS":
return showname
@@ -85,12 +93,10 @@ def get_info_tmdb(tmbda,ismovie,type):
elif type == "LordChannel":
date = show.release_date
date = date.split("-")[0]
print("Real date",date)
return showname,date
elif type == "StreamingWatch":
date = show.release_date
date = date.split("-")[0]
print("Real date",date)
return showname,date
elif type == "DDLStream":
return showname
@@ -102,17 +108,28 @@ def get_info_tmdb(tmbda,ismovie,type):
date = show.release_date
date = date.split("-")[0]
return showname,date
elif type == "Guardoserie":
date = show.release_date
date = date.split("-")[0]
return showname,date
elif type == 'Guardaflix':
date = show.release_date
date = date.split("-")[0]
return showname,date
elif type == 'Realtime':
date = show.release_date
return showname,date
elif type == "Toonitalia":
date = show.release_date
date = date.split("-")[0]
return showname,date
async def get_info_imdb(imdb_id, ismovie, type,client):
resp = await client.get(f'https://api.themoviedb.org/3/find/{imdb_id}?api_key={TMDB_KEY}&language=it&external_source=imdb_id')
data = resp.json()
if ismovie == 0:
showname = data['tv_results'][0]['name']
if type == "Filmpertutti":
date= data['tv_results'][0]['first_air_date']
date = date.split("-")[0]
print("Real date",date)
return showname, date
return showname
elif type == "StreamingCommunity":
date = data['tv_results'][0]['first_air_date']
date = date.split("-")[0]
@@ -137,13 +154,33 @@ async def get_info_imdb(imdb_id, ismovie, type,client):
date = data['tv_results'][0]['first_air_date']
date = date.split("-")[0]
return showname,date
elif type == "Onlineserietv":
date = data['tv_results'][0]['first_air_date']
date = date.split("-")[0]
return showname,date
elif type == "Guardaserie":
date = data['tv_results'][0]['first_air_date']
date = date.split("-")[0]
return showname,date
elif type == "Eurostreaming":
date = data['tv_results'][0]['first_air_date']
date = date.split("-")[0]
return showname,date
elif type == "Guardoserie":
date = data['tv_results'][0]['first_air_date']
date = date.split("-")[0]
return showname,date
elif type == 'Realtime':
return showname,data['tv_results'][0]['first_air_date']
elif type == "Toonitalia":
date = data['tv_results'][0]['first_air_date']
date = date.split("-")[0]
return showname,date
elif ismovie == 1:
showname= data['movie_results'][0]['title']
if type == "Filmpertutti":
date = data['movie_results'][0]['release_date']
date = date.split("-")[0]
return showname,date
return showname
elif type == "StreamingCommunity":
date = data['movie_results'][0]['release_date']
date = date.split("-")[0]
@@ -166,12 +203,35 @@ async def get_info_imdb(imdb_id, ismovie, type,client):
date = data['movie_results'][0]['release_date']
date = date.split("-")[0]
return showname,date
elif type == "Onlineserietv":
date = data['movie_results'][0]['release_date']
date = date.split("-")[0]
return showname,date
elif type == "Guardoserie":
date = data['movie_results'][0]['release_date']
date = date.split("-")[0]
return showname,date
elif type == 'Guardaflix':
date = data['movie_results'][0]['release_date']
date = date.split("-")[0]
return showname,date
elif type == 'Realtime':
date = data['movie_results'][0]['release_date']
return showname,date
elif type == 'Toonitalia':
date = data['movie_results'][0]['release_date']
date = date.split("-")[0]
return showname,date
async def get_info_kitsu(kitsu_id,client):
api_url = f'https://kitsu.io/api/edge/anime/{kitsu_id}'
response = await client.get(api_url)
data = json.loads(response.text)
try:
showname = data['data']['attributes']['titles']['en']
except Exception as e:
showname = data['data']['attributes']['canonicalTitle']
date = data['data']['attributes']['startDate']
return showname,date
@@ -179,7 +239,7 @@ async def get_info_kitsu(kitsu_id,client):
def is_movie(imdb_id):
async def is_movie(imdb_id):
if "tmdb:" in imdb_id:
imdb_id = imdb_id.replace("tmdb:","")
if ":" in imdb_id:
+2 -8
View File
@@ -1,9 +1,6 @@
import os
import Src.Utilities.config as config
MYSTERIUS = config.MYSTERIUS
dotenv = config.dotenv
HF = config.HF
Public_Instance = config.Public_Instance
#You need to keep dotenv disabled on remote servers
if dotenv == "1":
from dotenv import load_dotenv
@@ -13,10 +10,7 @@ if dotenv == "1":
def load_env():
env_vars = {}
env_vars['TMDB_KEY'] = os.getenv('TMDB_KEY')
if MYSTERIUS == "1":
env_vars['MYSTERIUS_KEY'] = os.getenv('MYSTERIUS_KEY')
env_vars['PROXY_CREDENTIALS'] = os.getenv('PROXY')
env_vars['MEDIAFLOW_PASS'] = os.getenv('MEDIAFLOW_PASS')
if Public_Instance == "1":
env_vars['ALTERNATIVE_LINK'] = os.getenv('ALTERNATIVE_LINK')
env_vars['ForwardProxy'] = os.getenv('FORWARDPROXY')
env_vars['PORT_ENV'] = os.getenv('PORT')
return env_vars
+104
View File
@@ -0,0 +1,104 @@
from fastapi import APIRouter, HTTPException, Response, Request
from fastapi.responses import RedirectResponse
from curl_cffi.requests import AsyncSession
from urllib.parse import urlparse, parse_qs,unquote,quote
from base64 import b64decode,b64encode
import re
from Src.API.extractors.vidxgo import vidxgo_refresh
import time
import Src.Utilities.config as config
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
VD_DOMAIN = config.VD_DOMAIN
router = APIRouter()
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.9',
'Referer': f'{VD_DOMAIN}/',
'Origin': VD_DOMAIN,
'Sec-GPC': '1',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
'DNT': '1',
}
async def fetch_m3u8(url):
"""Fetch the M3U8 file from the URL and store it in memory."""
async with AsyncSession() as client:
response = await client.get(url,headers = headers)
return response.text,response.status_code
@router.get("/clone/manifest.m3u8")
async def clone_m3u8(d: str = None):
if d:
try:
url = b64decode(d).decode('utf-8')
m3u8_content,status = await fetch_m3u8(url)
if status != 200:
match = re.search(r'hls[\w/]*/(\d{2}\d*[/]*\d*[/]*\d*)[\w/]+master',url)
if match:
id = match.group(1)
url = await vidxgo_refresh("",id)
m3u8_content,status =await fetch_m3u8(url)
m3u8_content = re.sub(r'(&b=\d+)',rf'\1&base={d}',m3u8_content)
return Response(content=m3u8_content, media_type='application/vnd.apple.mpegurl')
except Exception as e:
logger.info(f"Failed to fetch M3U8 file: {e}")
raise HTTPException(status_code=404, detail="M3U8 content not found")
@router.get("/clone/index{suffix}")
async def index_route(suffix: str, base: str):
try:
text2 = b64decode(base).decode('utf-8')
text = text2.replace("master.m3u8",f'index{suffix}')
m3u8_content,status = await fetch_m3u8(text)
match = re.search(r'hls[\w/]*/(\d{2}\d*[/]*\d*[/]*\d*)[\w/]+master',text2)
if match:
id = match.group(1)
else:
raise HTTPException(status_code=502, detail="ID not found")
if status != 200:
text = await vidxgo_refresh("",id)
text = text.replace("master.m3u8",f'index{suffix}')
m3u8_content,status =await fetch_m3u8(text)
current_date = time.strftime('%Y-%m-%d %H:%M')
m3u8_content = re.sub(r'(b=\d+)', rf'\1&id={b64encode(id.encode("utf-8")).decode("utf-8")}&date={b64encode(current_date.encode("utf-8")).decode("utf-8")}', m3u8_content)
return Response(content=m3u8_content, media_type='application/vnd.apple.mpegurl')
except Exception as e:
logger.info(f"Failed to fetch M3U8 file: {e}")
raise HTTPException(status_code=502, detail="M3U8 content not found")
@router.get("/clone/seg{suffix}")
async def ts_route(suffix:str,id:str,date: str,t:str,e:str,b:str):
try:
url = await vidxgo_refresh("",b64decode(id).decode('utf-8'))
parsed = urlparse(url)
params = parse_qs(parsed.query)
url = url.split("?")[0]
text = url.replace("master.m3u8",f'seg{suffix}?t={params["t"][0]}&e={params["e"][0]}&b={b}')
return RedirectResponse(text,headers=headers)
except Exception as e:
logger.info(f"Failed to redirect TS file: {e}")
raise HTTPException(status_code=502, detail="Failed to redirect TS file")
async def test_fetch():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
results = await index_route('-v1-a1','aHR0cHM6Ly9jZG4udjMubWVkaWEtNjg0LmQyYi55b3UvcHJveHkvbWVkaWEtNDAyL2hscy8xNjQyNjQxOC9tYXN0ZXIubTN1OD90PTJiYjg0MGYwMzFjY2MzNmYmZT0xNzgwNTA2OTk2Njk5JmI9Mjk3Ng====')
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(test_fetch())
+34
View File
@@ -0,0 +1,34 @@
import logging
import Src.Utilities.config as config
from Src.Utilities.config import setup_logging
import urllib.parse
level = config.LEVEL
logger = setup_logging(level)
async def transform_mfp(mfp_stream_url,MFP_url,MFP_password,client):
try:
response = await client.get(mfp_stream_url)
data = response.json()
if 'mediaflow_endpoint' in data:
if data['mediaflow_endpoint'] == 'hls_manifest_proxy':
MFP_url += '/proxy/hls/manifest.m3u8'
else:
MFP_url += '/proxy/stream'
url = MFP_url + "?api_password=" + MFP_password + "&d=" + urllib.parse.quote(data['destination_url'])
else:
url = data['mediaflow_proxy_url'] + "?api_password=" + data['query_params']['api_password'] + "&d=" + urllib.parse.quote(data['destination_url'])
for i in data['request_headers']:
url += f"&h_{i}={urllib.parse.quote(data['request_headers'][i])}"
return url
except Exception as e:
logger.warning(f"Converting MFP failed {e}")
return None
async def build_mfp(MFP_CREDENTIALS,url,host,client):
MFP_url = MFP_CREDENTIALS[0]
MFP_password = MFP_CREDENTIALS[1]
url_mfp = f'{MFP_url}/extractor/video?api_password={MFP_password}&d={url}&host={host}&redirect_stream=false'
#To build pieces together
url_mfp = await transform_mfp(url_mfp,MFP_url,MFP_password,client)
return url_mfp
+66
View File
@@ -0,0 +1,66 @@
link = 'https://raw.githubusercontent.com/AstraeLabs/Domains/main/domains.json'
import json
import os
import logging
from Src.Utilities.config import setup_logging
import Src.Utilities.config as config
level = config.LEVEL
logger = setup_logging(level)
async def fetch_domain(client,site_name):
response = await client.get(link)
data = response.json()
domain = data[site_name[0]]['full_url'][:-1]
return domain
def write_config(domain,site_name):
try:
json_file_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'config.json')
with open(json_file_path, 'r') as json_file:
config_data = json.load(json_file)
try:
config_data['Siti'][site_name[1]]['url'] = domain
with open(json_file_path, 'w') as json_file:
json.dump(config_data, json_file, indent=4)
return True
except Exception as e:
with open(json_file_path, 'w') as json_file:
json.dump(config_data, json_file, indent=4)
logger.info('Failed to write into config: ',e)
return False
except Exception as e:
logger.info('Failed to write into config: ',e)
return False
async def update_site(client,site_name):
try:
domain = await fetch_domain(client,site_name)
result = write_config(domain,site_name)
return result
except Exception as e:
return False
async def update_all_sites(client):
try:
sites = [['cb01new','CB01'],['guardaserie','Guardaserie'],['eurostreaming','Eurostreaming'],['guardaplay','Guardaflix'],['guardoserie_2','Guardoserie'],['animeworld','AnimeWorld'],['toonitalia','Toonitalia']]
for item in sites:
domain = await fetch_domain(client,item)
write_config(domain,item)
return True
except Exception as e:
logger.info('Failed to update domains: ',e)
return False
async def test_update_site():
from curl_cffi.requests import AsyncSession
async with AsyncSession() as client:
result = await update_site(client,['guardoserie_2','Guardoserie'])
#result = await update_all_sites(client)
#domain = await update_site(client,['eurostreamings','Eurostreaming'])
#write_config(domain,['eurostreamings','Eurostreaming'])
if __name__ == "__main__":
import asyncio
asyncio.run(test_update_site())
+4
View File
@@ -0,0 +1,4 @@
{
"projectName": "mammamia",
"lastCommit": "58af5b8"
}
+78 -24
View File
@@ -1,41 +1,95 @@
{
"Siti": {
"StreamingCommunity": {
"domain": "buzz"
"url": "https://vixsrc.to",
"SC_ForwardProxy": "0",
"SC_PROXY": "0",
"VX_ForwardProxy": "0",
"VX_PROXY": "0",
"enabled": "1"
},
"Filmpertutti": {
"domain": "diy"
"CB01": {
"url": "https://cb01uno.click",
"CB_PROXY": "0",
"CB_ForwardProxy": "0",
"MX_ForwardProxy": "0",
"MX_PROXY": "0",
"enabled": "1"
},
"Tantifilm":{
"domain": "bond"
"Guardaserie": {
"url": "https://guarda-serie.click",
"enabled": "1",
"GS_ForwardProxy": "0",
"GS_PROXY": "0"
},
"Mysterius":{
"enabled": "0"
"GuardaHD": {
"url": "https://mostraguarda.stream",
"enabled": "1",
"GH_ForwardProxy": "0",
"GH_PROXY": "0"
},
"LordChannel":{
"domain":"com"
"Eurostreaming": {
"url": "https://eurostream.ing",
"enabled": "1",
"ES_ForwardProxy": "0",
"ES_PROXY": "0"
},
"StreamingWatch":{
"domain":"org"
"Guardaflix": {
"url": "https://guardaplay.live",
"enabled": "1",
"GF_ForwardProxy": "0",
"GF_PROXY": "0"
},
"AnimeWorld":{
"domain":"so"
"Guardoserie": {
"url": "https://guardoserie.run",
"enabled": "1",
"GO_ForwardProxy": "0",
"GO_PROXY": "0"
},
"SkyStreaming":{
"domain":"guru"
"AnimeWorld": {
"url": "https://www.animeworld.ac",
"enabled": "1",
"AW_ForwardProxy": "0",
"AW_PROXY": "0"
},
"DaddyLiveHD":{
"enabled":"1"
"Realtime": {
"url": "https://realtime.it",
"enabled": "1",
"RT_ForwardProxy": "0",
"RT_PROXY": "0"
},
"Toonitalia": {
"url": "https://toonitalia.xyz",
"enabled": "1",
"TI_ForwardProxy": "0",
"TI_PROXY": "0"
},
"OnlineSerieTV": {
"url": "https://onlineserietv.lol",
"enabled": "1",
"OST_ForwardProxy": "0",
"OST_PROXY": "0"
},
"Vidxgo": {
"url": "https://v.vidxgo.co",
"enabled": "1",
"VD_ForwardProxy": "0",
"VD_PROXY": "0"
}
},
"General":{
"Captcha": {
"Uprot": {
"UT_ForwardProxy": "0",
"UT_PROXY": "0"
}
},
"General": {
"load_env": "0",
"HOST": "0.0.0.0",
"PORT": "8080",
"HF": "1",
"Public_Instance": "0",
"MediaProxy": ["Test"],
"ForwardProxy": ["Test"],
"Proxy": []
"PORT": 8080,
"Name": "MammaMia",
"Icon": "\ud83c\udf55",
"level": "info",
"Global_Proxy": "0"
}
}
+6 -2
View File
@@ -1,3 +1,7 @@
# This env variable is mandatory
# Questa variabile è obbligatoria
TMDB_KEY= "INSERT YOUR API KEY HERE"
MEDIAFLOW_PASS = "INSERT YOUR MEDIAFLOW PASS HERE"
# Those env variable are not mandatory
# Queste variabili non sono obbligatoria
PROXY = ["PROXY1","PROXY2"]
FORWARDPROXY = "YOURFORWARDPROXY/"
+17
View File
@@ -0,0 +1,17 @@
services:
- type: web
name: MammaMia
runtime: python
buildCommand: pip install -r requirements.txt
startCommand: python3 run.py
plan: free
region: frankfurt
envVars:
# Sets a hardcoded value
# (DO NOT hardcode secrets in your Blueprint file!)
- key: PORT
value: 8080
# Prompts for a value in the Render Dashboard on creation
# (useful for secrets)
- key: TMDB_KEY
sync: false
+4
View File
@@ -9,3 +9,7 @@ lxml
slowapi
curl_cffi
fake-headers
pycryptodome
rich
python-multipart
jinja2
+238 -134
View File
@@ -1,48 +1,89 @@
from fastapi import FastAPI, HTTPException,Request
from fastapi import FastAPI, HTTPException,Request, Form,Cookie
from fastapi.responses import JSONResponse,RedirectResponse,HTMLResponse
from Src.API.filmpertutti import filmpertutti
from Src.API.streamingcommunity import streaming_community
from Src.API.tantifilm import tantifilm
from Src.API.lordchannel import lordchannel
from Src.API.streamingwatch import streamingwatch
import Src.Utilities.config as config
import logging
from Src.API.okru import okru_get_url
from Src.API.animeworld import animeworld
from Src.Utilities.dictionaries import okru,STREAM,extra_sources,webru_vary,webru_dlhd,provider_map,skystreaming
from Src.API.epg import tivu, tivu_get,epg_guide,convert_bho_1,convert_bho_2,convert_bho_3
from Src.API.webru import webru,get_skystreaming
from curl_cffi.requests import AsyncSession
from slowapi import Limiter
from slowapi.util import get_remote_address
from slowapi.middleware import SlowAPIMiddleware
from static.static import HTML
# Configure logging
MYSTERIUS = config.MYSTERIUS
DLHD = config.DLHD
from static.configure import CONFIGURE
from fastapi.templating import Jinja2Templates
from Src.API.streamingcommunity import streaming_community
from Src.API.cb01 import cb01
from Src.API.guardaserie import guardaserie
from Src.API.guardahd import guardahd
from Src.API.animeworld import animeworld
from Src.API.guardaflix import guardaflix
from Src.API.guardoserie import guardoserie
from Src.API.eurostreaming import eurostreaming
from Src.API.onlineserietv import onlineserietv
from Src.API.vidxgoalta import vidxgoalta
from Src.API.toonitalia import toonitalia
from Src.API.realtime import search_catalog as realtime
from Src.API.realtime import meta_catalog as meta_catalog_realtime
from Src.API.realtime import realtime as streams_realtime
from Src.Utilities.dictionaries import STREAM,extra_sources,provider_map
from Src.Utilities.update_config import update_all_sites
from Src.API.epg import tivu, tivu_get,epg_guide,convert_bho_1,convert_bho_2,convert_bho_3
from Src.API.extractors.uprot import get_uprot_numbers,generate_uprot_txt
import logging
from urllib.parse import unquote
from curl_cffi.requests import AsyncSession
import base64
import Src.Utilities.config as config
from Src.Utilities.config import setup_logging
level = config.LEVEL
logger = setup_logging(level)
from Src.Utilities.loadenv import load_env
env_vars = load_env()
from Src.Utilities.manifest import router as clone
#Configure Env Vars
Global_Proxy = config.Global_Proxy
if Global_Proxy == "1":
PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS')
proxies = {
"http": PROXY_CREDENTIALS,
"https": PROXY_CREDENTIALS
}
else:
proxies = {}
# Configure config
SC = config.SC
SC_DOMAIN = config.SC_DOMAIN
AW = config.AW
CB = config.CB
GS = config.GS
GHD = config.GHD
ES = config.ES
GF = config.GF
GO = config.GO
RT = config.RT
TI = config.TI
OST = config.OST
VD = config.VD
HOST = config.HOST
PORT = int(config.PORT)
HF = config.HF
if HF == "1":
HF = "🤗️"
#Cool code to set the hugging face if the service is hosted there.
else:
HF = ""
if MYSTERIUS == "1":
from Src.API.cool import cool
if env_vars.get('PORT_ENV'):
PORT = int(env_vars.get('PORT_ENV'))
Icon = config.Icon
Name = config.Name
app = FastAPI()
app.include_router(clone)
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_middleware(SlowAPIMiddleware)
User_Agent= "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
#Tells Where to look for static files
static = Jinja2Templates(directory="static")
MANIFEST = {
"id": "org.stremio.mammamia",
"version": "1.1.0",
"version": "2.0.0",
"catalogs": [
{
"type": "tv",
"id": "tv_channels",
"name": "TV Channels",
"name": "MammaMia",
"behaviorHints": {
"configurable": True,
"configurationRequired": True
@@ -54,11 +95,22 @@ MANIFEST = {
"options": ["Rai", "Mediaset", "Sky", "Euronews", "La7", "Warner Bros", "FIT", "Sportitalia","RSI","DAZN", "Rakuten", "Pluto", "A+E", "Paramount", "Chill"]
}
]
},
{
'id': 'realtime',
'type': "series",
"name": "realtime",
'extra' :[
{
"name": "search",
"isRequired": True
}
]
}
],
"resources": ["stream", "catalog", "meta"],
"types": ["movie", "series", "tv"],
"name": "Mamma Mia",
"name": Name,
"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",
"logo": "https://creazilla-store.fra1.digitaloceanspaces.com/emojis/49647/pizza-emoji-clipart-md.png"
}
@@ -70,15 +122,38 @@ def respond_with(data):
resp.headers['Access-Control-Allow-Headers'] = '*'
return resp
@app.get('/config')
def config():
return RedirectResponse(url="/")
@app.get('/{config}/manifest.json')
def addon_manifest():
return respond_with(MANIFEST)
@app.get('/configure',response_class=HTMLResponse)
def config(request: Request):
forwarded_proto = request.headers.get("x-forwarded-proto")
scheme = forwarded_proto if forwarded_proto else request.url.scheme
instance_url = f"{scheme}://{request.url.netloc}"
html_content = CONFIGURE.replace("{instance_url}", instance_url)
return html_content
@app.get('/{config:path}/manifest.json')
def addon_manifest(config: str):
manifest_copy = MANIFEST.copy()
config = base64.b64decode(config).decode('utf-8')
if "LIVETV" not in config:
if "catalog" in manifest_copy["resources"]:
for item in manifest_copy['catalogs']:
if item['id'] == 'tv_channels':
manifest_copy['catalogs'].remove(item)
if not any(manifest_copy['catalogs']):
manifest_copy["resources"].remove('catalog')
if 'RT' not in config or RT == '0':
if "catalog" in manifest_copy["resources"]:
for item in manifest_copy['catalogs']:
if item['id'] == 'realtime':
manifest_copy['catalogs'].remove(item)
if not any(manifest_copy['catalogs']):
manifest_copy["resources"].remove('catalog')
return respond_with(manifest_copy)
@app.get('/manifest.json')
def manifest():
return RedirectResponse(url="/|SC|LC|SW|/manifest.json")
return RedirectResponse(url="/|SC|LC|/manifest.json")
@app.get('/', response_class=HTMLResponse)
def root(request: Request):
@@ -88,7 +163,6 @@ def root(request: Request):
html_content = HTML.replace("{instance_url}", instance_url)
return html_content
async def addon_catalog(type: str, id: str, genre: str = None):
print(f"Received genre parameter: {genre}")
if type != "tv":
raise HTTPException(status_code=404)
@@ -109,18 +183,26 @@ async def addon_catalog(type: str, id: str, genre: str = None):
})
return catalogs
@app.get('/{config}/catalog/{type}/{id}.json')
@app.get('/{config:path}/catalog/{type}/{id}.json')
@limiter.limit("5/second")
async def first_catalog(request: Request,type: str, id: str, genre: str = None):
catalogs = await addon_catalog(type, id,genre)
return respond_with(catalogs)
@app.get('/{config}/catalog/{type}/{id}/genre={genre}.json')
@app.get('/{config:path}/catalog/{type}/{id}/genre={genre}.json')
async def first_catalog(type: str, id: str, genre: str = None):
catalogs = await addon_catalog(type, id,genre)
return respond_with(catalogs)
@app.get('/{config}/meta/tv/{id}.json')
@app.get('/{config:path}/catalog/{type}/{id}/search={query}.json')
async def realtime_catalog(type:str,id:str,query: str = None):
if type != 'series':
raise HTTPException(status_code=404)
catalogs = {"query": query,'cacheMaxAge': 86400,"metas": []}
async with AsyncSession(proxies = proxies) as client:
catalogs = await realtime(query, catalogs,client)
return respond_with(catalogs)
@app.get('/{config:path}/meta/tv/{id}.json')
@limiter.limit("20/second")
async def addon_meta(request: Request,id: str):
# Find the channel by ID
@@ -128,12 +210,11 @@ async def addon_meta(request: Request,id: str):
if not channel:
raise HTTPException(status_code=404, detail="Channel not found")
async with AsyncSession() as client:
async with AsyncSession(proxies = proxies) as client:
if channel["id"] in convert_bho_1 or channel["id"] in convert_bho_2 or channel["id"] in convert_bho_3:
description,title = await epg_guide(channel["id"],client)
elif channel["id"] in tivu:
description = await tivu_get(channel["id"],client)
print(description)
title = ""
else:
description = f'Watch {channel["title"]}'
@@ -156,132 +237,155 @@ async def addon_meta(request: Request,id: str):
meta['meta']['url'] = channel['url'] # Using the stream URL as a website link
return respond_with(meta)
@app.get('/{config}/stream/{type}/{id}.json')
@app.get('/{config:path}/meta/series/{id}.json')
async def addon_meta(request: Request,id: str):
meta = {'meta': {'videos':[], 'status': 'Continuing', 'type': 'series', 'id': id}}
async with AsyncSession(proxies = proxies) as client:
if 'realtime' not in id:
raise HTTPException(status_code=404)
meta = await meta_catalog_realtime(id,meta,client)
return respond_with(meta)
@app.get('/{config:path}/stream/{type}/{id}.json')
@limiter.limit("5/second")
async def addon_stream(request: Request,config, type, id,):
if type not in MANIFEST['types']:
raise HTTPException(status_code=404)
streams = {'streams': []}
config = base64.b64decode(config).decode('utf-8')
if "|" in config:
config_providers = config.split('|')
elif "%7C" in config:
config_providers = config.split('%7C')
provider_maps = {name: "0" for name in provider_map.values()}
for provider in config_providers:
if provider in provider_map:
provider_name = provider_map[provider]
provider_maps[provider_name] = "1"
if "MFP[" in config:
# Extract proxy data between "MFP(" and ")"
mfp_data = config.split("MFP[")[1].split(")")[0]
# Split the data by comma to get proxy URL and password
MFP_url, MFP_password = mfp_data.split(",")
MFP_password = MFP_password[:-2]
#If mfp_url ends with a string we remove it
if MFP_url.endswith('/'):
MFP_url = MFP_url[:-1]
# Store them in a list
MFP_CREDENTIALS = [MFP_url, MFP_password]
if MFP_url and MFP_password:
MFP = "1"
async with AsyncSession() as client:
else:
MFP = "0"
MFP_CREDENTIALS = ['','']
#Get instance URL to pass it to vidxgo
forwarded_proto = request.headers.get("x-forwarded-proto")
scheme = forwarded_proto if forwarded_proto else request.url.scheme
instance_url = f"{scheme}://{request.url.netloc}"
async with AsyncSession(proxies = proxies) as client:
if type == "tv":
for channel in STREAM["channels"]:
if channel["id"] == id:
i = 0
if 'url' in channel:
i = i+1
streams['streams'].append({
'title': f"{HF}Server {i} " + f" "+ channel['name'] + " " + channel['title'] ,
'url': channel['url']
})
if id in okru:
i = i+1
channel_url = await okru_get_url(id,client)
streams['streams'].append({
'title': f"{HF}Server {i} " + channel['title'] + " OKRU",
'url': channel_url
})
streams['streams'].append({'title': f"{Icon}Server {i} " + f" "+ channel['name'] + " " + channel['title'] ,'url': channel['url']})
if id in extra_sources:
list_sources = extra_sources[id]
for item in list_sources:
i = i+1
streams['streams'].append({'title':f"{HF}Server {i} " + channel['title'],'url': item})
if id in skystreaming:
urls = await get_skystreaming(id,client)
for url in urls:
i = i+1
Host = urls[url]
print(url,Host)
streams['streams'].append({'title': f'{HF}Server {i}', 'url': url, "behaviorHints": {"notWebReady": True, "proxyHeaders": {"request": {"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0", "Accept": "*/*", "Accept-Language": "en-US,en;q=0.5", "Origin": "https://skystreaming.guru", "DNT": "1", "Sec-GPC": "1", "Connection": "keep-alive", "Referer": "https://skystreaming.guru/", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "cross-site", "Pragma": "no-cache", "Cache-Control": "no-cache", "TE": "trailers","Host": Host}}}})
if id in webru_vary:
i = i+1
webru_url = await webru(id,"vary",client)
streams['streams'].append({'title': f"{HF}Server {i} " + channel['title'],'url': webru_url})
if id in webru_dlhd:
if DLHD == "1":
i = i+1
webru_url_2 = await webru(id,"dlhd",client)
streams['streams'].append({'title': f"{HF}Server {i} " + channel['title'],'url': webru_url_2})
streams['streams'].append({'title':f"{Icon}Server {i} " + channel['title'],'url': item})
if not streams['streams']:
raise HTTPException(status_code=404)
return respond_with(streams)
elif "realtime" in id and RT == '1':
streams = await streams_realtime(streams,id,client)
return respond_with(streams)
elif "tt" in id or "tmdb" in id or "kitsu" in id:
print(f"Handling movie or series: {id}")
logger.info(f"Handling movie or series: {id}")
if "kitsu" in id:
if provider_maps['ANIMEWORLD'] == "1":
animeworld_urls = await animeworld(id,client)
if animeworld_urls:
print(f"AnimeWorld Found Results for {id}")
i = 0
for url in animeworld_urls:
if url:
if i == 0:
title = "Original"
elif i == 1:
title = "Italian"
streams['streams'].append({'title': f'{HF}Animeworld {title}', 'url': url})
i+=1
if provider_maps['ANIMEWORLD'] == "1" and AW == "1":
streams = await animeworld(streams,id,client)
else:
if MYSTERIUS == "1":
results = await cool(id,client)
if results:
print(f"Mysterius Found Results for {id}")
for resolution, link in results.items():
streams['streams'].append({'title': f'{HF}Mysterious {resolution}', 'url': link})
print(provider_maps['STREAMINGCOMMUNITY'])
if provider_maps['STREAMINGCOMMUNITY'] == "1":
SC_FAST_SEARCH = provider_maps['SC_FAST_SEARCH']
url_streaming_community,url_720_streaming_community,quality_sc = await streaming_community(id,client,SC_FAST_SEARCH)
if url_streaming_community is not None:
print(f"StreamingCommunity Found Results for {id}")
if quality_sc == "1080":
streams['streams'].append({'title': f'{HF}StreamingCommunity 1080p Max', 'url': url_streaming_community})
streams['streams'].append({'title': f'{HF}StreamingCommunity 720p Max', 'url': url_720_streaming_community})
if provider_maps['STREAMINGCOMMUNITY'] == "1" and SC == "1":
if provider_maps['SC_MFP'] != "0":
SC_MFP = "1"
else:
streams['streams'].append({'title': f'{HF}StreamingCommunity 720p Max', 'url': url_streaming_community})
if provider_maps['LORDCHANNEL'] == "1":
url_lordchannel,quality_lordchannel = await lordchannel(id,client)
if quality_lordchannel == "FULL HD" and url_lordchannel != None:
print(f"LordChannel Found Results for {id}")
streams['streams'].append({'title': f'{HF}LordChannel 1080p', 'url': url_lordchannel})
elif url_lordchannel != None:
print(f"LordChannel Found Results for {id}")
streams['streams'].append({'title': f'{HF}LordChannel 720p', 'url': url_lordchannel})
if provider_maps['FILMPERTUTTI'] == "1":
url_filmpertutti = await filmpertutti(id,client)
if url_filmpertutti is not None:
print(f"Filmpertutti Found Results for {id}")
streams['streams'].append({'title': 'Filmpertutti', 'url': url_filmpertutti})
if provider_maps['TANTIFILM'] == "1":
TF_FAST_SEARCH = provider_maps['TF_FAST_SEARCH']
url_tantifilm = await tantifilm(id,client,TF_FAST_SEARCH)
if url_tantifilm:
print(f"TantiFilm Found Results for {id}")
if not isinstance(url_tantifilm, str):
for title, url in url_tantifilm.items():
streams['streams'].append({'title': f'{HF}Tantifilm {title}', 'url': url, 'behaviorHints': {'proxyHeaders': {"request": {"Referer": "https://d000d.com/"}}, 'notWebReady': True}})
else:
streams['streams'].append({'title': f'{HF}Tantifilm', 'url': url_tantifilm, 'behaviorHints': {'proxyHeaders': {"request": {"Referer": "https://d000d.com/"}}, 'notWebReady': True}})
if provider_maps['STREAMINGWATCH'] == "1":
url_streamingwatch = await streamingwatch(id,client)
if url_streamingwatch:
print(f"Streaming Watch Found Results for {id}")
streams['streams'].append({'title': f'{HF}StreamingWatch 720p', 'url': url_streamingwatch})
SC_MFP = '0'
streams = await streaming_community(streams,id,client,SC_MFP,MFP_CREDENTIALS)
if provider_maps['CB01'] == "1" and CB == "1":
streams = await cb01(streams,id,MFP,MFP_CREDENTIALS,client)
if provider_maps['GUARDASERIE'] == "1" and GS == "1":
streams = await guardaserie(streams,id,client)
if provider_maps['GUARDAHD'] == "1" and GHD == "1":
streams = await guardahd(streams,id,client,MFP,MFP_CREDENTIALS)
if provider_maps['EUROSTREAMING'] == "1" and ES == "1":
streams = await eurostreaming(streams,id,client,MFP,MFP_CREDENTIALS)
if provider_maps['GUARDAFLIX'] == "1" and GF == "1":
streams = await guardaflix(streams,id,client,MFP,MFP_CREDENTIALS)
if provider_maps['GUARDOSERIE'] == "1" and GO == "1":
streams = await guardoserie(streams,id,client,MFP,MFP_CREDENTIALS)
if provider_maps['REALTIME'] == '1' and RT == '1':
streams = await streams_realtime(streams,id,client)
if provider_maps['TOONITALIA'] == '1' and TI == '1':
streams = await toonitalia(streams,id,client,MFP,MFP_CREDENTIALS)
if provider_maps['ONLINESERIETV'] == '1' and OST == '1':
streams = await onlineserietv(streams,id,client)
if provider_maps['VIDXGO'] == '1' and VD == '1':
streams = await vidxgoalta(streams,id,client,instance_url)
return respond_with(streams)
if not streams['streams']:
raise HTTPException(status_code=404)
return respond_with(streams)
@app.get('/uprot')
async def uprot(request: Request):
async with AsyncSession(proxies = proxies) as client:
image, cookies = await get_uprot_numbers(client)
context = {
'request': request,
'image_url': image
}
response = static.TemplateResponse(name='uprot.html',context=context,request=request)
if cookies:
response.set_cookie(key='PHPSESSID', value=cookies.get('PHPSESSID'),httponly=True)
return response
@app.post("/uprot")
async def execute_uprot(request: Request,user_input = Form(...),PHPSESSID: str = Cookie(None)):
async with AsyncSession(proxies = proxies) as client:
cookies = {
'PHPSESSID': PHPSESSID
}
status = await generate_uprot_txt(user_input,cookies,client)
if status == True:
context = {
'request': request,
'image_url': 'https://tinyurl.com/doneokdone'
}
return static.TemplateResponse(name='uprot.html',context=context,request=request)
elif status == False:
context = {
'request': request,
'image_url': 'https://tinyurl.com/tryagaindumb'
}
return static.TemplateResponse('uprot.html',context=context,request=request)
@app.get('/update')
async def update(request: Request):
async with AsyncSession(proxies = proxies) as client:
result = await update_all_sites(client)
print(result)
if result:
return JSONResponse(content={"message": "200"})
if not result:
return JSONResponse(content={"message": "Failed"})
if __name__ == '__main__':
import uvicorn
uvicorn.run("run:app", host=HOST, port=PORT, log_level="info")
uvicorn.run("run:app", host=HOST, port=PORT, log_level=level)
+348
View File
@@ -0,0 +1,348 @@
# static.py
CONFIGURE = """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Mamma Mia</title>
<link rel="icon" href="https://creazilla-store.fra1.digitaloceanspaces.com/emojis/49647/pizza-emoji-clipart-md.png" type="image/x-icon">
<title>Fast Search Example</title>
<style>
* {
box-sizing: border-box;
}
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
font-size: 2.2vh;
font-family: 'Open Sans', Arial, sans-serif;
color: white;
background: url('https://i.postimg.cc/ry3p76HY/italian-seamless-free-vector-pattern3.png') center center repeat;
background-size: cover;
display: flex;
align-items: flex-start;
justify-content: center;
overflow-y: auto;
}
#addon {
background: rgba(0, 0, 0, 0.8);
padding: 0.5vh;
border-radius: 10px;
width: 65vh;
max-width: 100%;
text-align: center;
margin-top: 10vh;
}
.logo {
width: 12vh;
margin: 0 auto;
margin-bottom: 3vh;
margin-top: -3vh;
}
.logo img {
width: 100%;
height: auto;
}
h1, h2, h3 {
margin: 0;
text-shadow: 0 0 1vh rgba(0, 0, 0, 0.15);
}
h1 {
font-size: 4.5vh;
font-weight: 700;
}
h2 {
font-size: 2vh;
font-weight: normal;
font-style: italic;
opacity: 0.8;
margin-bottom: 20px;
}
h3 {
font-size: 2.2vh;
margin-bottom: 10px;
}
.provider-group {
display: flex;
align-items: center; /* Vertically align items */
justify-content: space-between; /* Spread items across the available space */
margin-bottom: 2vh;
background: rgba(255, 255, 255, 0.1);
padding: 1.5vh;
border-radius: 5px;
overflow: hidden;
width: 100%;
}
.provider-group label {
display: flex;
align-items: center; /* Align items within label vertically centered */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex-grow: 1; /* Let the label take as much space as possible */
font-size: 2.2vh;
}
.provider-group input[type="checkbox"] {
margin-right: 1.5vh;
width: 4vh;
height: 4vh;
}
.provider-group input[type="checkbox"][id$="_mfp"] {
margin-left: 2.2vh;
width: 4vh;
height: 4vh;
}
.parent-container {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.contact {
position: absolute;
left: 0;
bottom: 4vh;
width: 100%;
text-align: center;
}
.contact a {
font-size: 1.4vh;
font-style: italic;
}
button {
border: 0;
outline: 0;
color: white;
background: #8A5AAB;
padding: 1.2vh 3.5vh;
text-align: center;
font-family: 'Open Sans', Arial, sans-serif;
font-size: 2.2vh;
font-weight: 600;
cursor: pointer;
display: block;
box-shadow: 0 0.5vh 1vh rgba(0, 0, 0, 0.2);
transition: box-shadow 0.1s ease-in-out;
width: 80%;
max-width: 35vh;
margin: 1vh auto;
}
button:hover {
box-shadow: none;
}
button:active {
box-shadow: 0 0 0 0.5vh white inset;
}
#manifestBox {
margin-top: 2vh;
padding: 2vh;
background: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: none; /* Initially hidden */
text-align: left;
white-space: pre-wrap; /* Preserves whitespace and wraps text */
overflow-wrap: break-word; /* Breaks long words to prevent overflow */
word-wrap: break-word; /* For older browsers */
max-width: 100%; /* Ensures it doesn't exceed the container width */
border: 1px solid #ccc; /* Optional: Add a border for visibility */
}
#generateManifestButton {
background: #4CAF50;
}
#installButton {
background: #FF5722;
}
#installButton a {
color: white;
text-decoration: none;
}
#additionalText {
margin-top: 2vh;
font-size: 1.8vh;
text-align: left;
}
/* Responsive adjustments for smaller screens */
@media (max-width: 600px) {
.provider-group label {
font-size: 2vh;
white-space: nowrap;
}
}
</style>
</head>
<body>
<div id="addon">
<div class="logo">
<img src="https://creazilla-store.fra1.digitaloceanspaces.com/emojis/49647/pizza-emoji-clipart-md.png" alt="Logo">
</div>
<h1 class="name">Mamma Mia</h1>
<h2 class="version">v2.2.0</h2>
<div id="additionalText">
<h2>This addon provides Movie, Series, Anime, and Live TV HTTPS Streams.<br> https://github.com/UrloMythus/MammaMia/</h2>
</div>
<p class="description">🕵️‍♂️ = Mediaflowproxy might be needed <br>Select the box with this icon if you want to enable MFP for that source<br></p>
<h3 class="gives">Select Providers:</h3>
<form class="pure-form" id="provider-form">
<div class="provider-group">
<label for="guardoserie" class="provider-label">
<input type="checkbox" id="guardoserie"> Guardoserie
</label>
</div>
<div class="provider-group">
<label for="guardaflix" class="provider-label">
<input type="checkbox" id="guardaflix"> Guardaflix
</label>
</div>
<div class="provider-group">
<label for="animeworld" class="provider-label">
<input type="checkbox" id="animeworld"> Animeworld
</label>
</div>
<div class="provider-group">
<label for="guardaserie" class="provider-label">
<input type="checkbox" id="guardaserie"> Guardaserie
</label>
</div>
<div class="provider-group">
<label for="guardahd" class="provider-label">
<input type="checkbox" id="guardahd"> GuardaHD
</label>
</div>
<div>
</div>
<div class="provider-group">
<label for="cb01" class="provider-label">
<input type="checkbox" id="cb01"> CB01 🕵️‍♂️
</label>
</div>
<div class="provider-group">
<label for="onlineserietv" class="provider-label">
<input type="checkbox" id="onlineserietv"> OnlineSerieTV
</label>
</div>
<div class="provider-group">
<label for="vidxgo" class="provider-label">
<input type="checkbox" id="vidxgo"> Vidxgo
</label>
</div>
<div class="provider-group">
<label for="streamingcommunity" class="provider-label">
<input type="checkbox" id="streamingcommunity"> StreamingCommunity 🕵️‍♂️
<input type="checkbox" id="streamingcommunity_mfp" checked> 🕵️‍♂️
</label>
</div>
<div class="provider-group">
<label for="eurostreaming" class="provider-label">
<input type="checkbox" id="eurostreaming"> Eurostreaming 🕵️‍♂️
</label>
</div>
<div class="provider-group">
<label for="realtime" class="provider-label">
<input type="checkbox" id="toonitalia"> Toonitalia 🕵️‍♂️
</label>
</div>
<div class="provider-group">
<label for="realtime" class="provider-label">
<input type="checkbox" id="realtime"> Realtime
</label>
</div>
<div class="provider-group">
<label for="livetv" class="provider-label">
<input type="checkbox" id="livetv"> LiveTV
</label>
</div>
<div class="provider-group">
<label for="mediaflowproxy" class="provider-label">
<input type="checkbox" id="mediaflowproxy"> MediaFlow Proxy
</label>
<button type="button" id="mediaFlowProxyButton">Insert Proxy Info</button>
</div>
<div id="mediaFlowProxyInputContainer" style="display: none;">
<input type="text" id="mediaFlowProxyInput" placeholder="Proxy URL">
</div>
<div id="mediaFlowProxyPasswordContainer" style="display: none;">
<input type="password" id="mediaFlowProxyPassword" placeholder="Insert Password">
</div>
</form>
<button id="generateManifestButton">Generate Manifest</button>
<div id="manifestBox"></div>
<button id="installButton">Install in Stremio</button>
</div>
<script>
// Toggle visibility of proxy input fields
document.getElementById('mediaFlowProxyButton').addEventListener('click', function() {
const inputContainer = document.getElementById('mediaFlowProxyInputContainer');
const passwordInputContainer = document.getElementById('mediaFlowProxyPasswordContainer');
inputContainer.style.display = inputContainer.style.display === 'none' ? 'block' : 'none';
passwordInputContainer.style.display = passwordInputContainer.style.display === 'none' ? 'block' : 'none';
});
// Function to generate the manifest URL
function generateManifest() {
let manifest = "|";
const providers = {
"streamingcommunity": "SC",
"animeworld": "AW",
"livetv": "LIVETV",
"cb01": "CB",
"guardaserie": "GS",
"guardahd": "GHD",
"guardoserie": "GO",
"guardaflix": "GF",
"eurostreaming": "ES",
"realtime": "RT",
"toonitalia": "TI",
"onlineserietv": "OST",
"vidxgo": "VD",
"streamingcommunity_mfp": "SC_MFP",
"mediaflowproxy": "MFP"
};
// Loop through providers and add selected ones to the manifest
for (const id in providers) {
if (document.getElementById(id).checked) {
if (id === "mediaflowproxy") {
// Add proxy details if MFP is selected
const proxyUrl = document.getElementById("mediaFlowProxyInput").value.trim();
const proxyPassword = document.getElementById("mediaFlowProxyPassword").value.trim();
if (proxyUrl && proxyPassword) {
manifest += `MFP[${proxyUrl},${proxyPassword}]|`;
} else {
manifest += providers[id] + "|"; // Fallback to just "MFP" if no details provided
}
} else {
manifest += providers[id] + "|";
}
}
}
const encodedProviders = btoa(manifest);
const instanceUrl = "{instance_url}"; // Replace with your instance URL
const manifestUrl = instanceUrl + "/" + encodedProviders + "/" + "manifest.json";
return manifestUrl;
}
// Generate manifest URL and display it
document.getElementById('generateManifestButton').addEventListener('click', function() {
const manifestUrl = generateManifest();
const manifestBox = document.getElementById("manifestBox");
manifestBox.style.display = "block";
manifestBox.innerText = manifestUrl;
});
// Install the manifest in Stremio
document.getElementById('installButton').addEventListener('click', function() {
let manifestUrl = generateManifest();
manifestUrl = manifestUrl.replace("http://", "");
manifestUrl = manifestUrl.replace("https://", "");
const stremioUrl = "stremio://" + manifestUrl;
window.location.href = stremioUrl;
});
</script>
</body>
</html>
"""
+132 -57
View File
@@ -20,7 +20,7 @@ HTML = """
font-size: 2.2vh;
font-family: 'Open Sans', Arial, sans-serif;
color: white;
background: url('https://i.postimg.cc/m2ZqvpZj/italian-seamless-free-vector-pattern3.png') center center repeat;
background: url('https://i.postimg.cc/ry3p76HY/italian-seamless-free-vector-pattern3.png') center center repeat;
background-size: cover;
display: flex;
align-items: flex-start;
@@ -75,6 +75,7 @@ HTML = """
border-radius: 5px;
overflow: hidden;
width: 100%;
}
.provider-group label {
display: flex;
@@ -85,21 +86,16 @@ HTML = """
flex-grow: 1; /* Let the label take as much space as possible */
font-size: 2.2vh;
}
.fast-search {
display: flex;
align-items: center; /* Align the Fast Search checkbox vertically centered */
margin-left: 10px; /* Space between provider and Fast Search */
}
.fast-search input[type="checkbox"] {
margin-right: 0.5vh; /* Space between the checkbox and label */
width: 3vh;
height: 3vh;
}
.provider-group input[type="checkbox"] {
margin-right: 1.5vh;
width: 4vh;
height: 4vh;
}
.provider-group input[type="checkbox"][id$="_mfp"] {
margin-left: 2.2vh;
width: 4vh;
height: 4vh;
}
.parent-container {
display: flex;
align-items: center;
@@ -146,9 +142,13 @@ HTML = """
padding: 2vh;
background: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: none;
display: none; /* Initially hidden */
text-align: left;
white-space: pre-wrap;
white-space: pre-wrap; /* Preserves whitespace and wraps text */
overflow-wrap: break-word; /* Breaks long words to prevent overflow */
word-wrap: break-word; /* For older browsers */
max-width: 100%; /* Ensures it doesn't exceed the container width */
border: 1px solid #ccc; /* Optional: Add a border for visibility */
}
#generateManifestButton {
background: #4CAF50;
@@ -180,46 +180,21 @@ HTML = """
<img src="https://creazilla-store.fra1.digitaloceanspaces.com/emojis/49647/pizza-emoji-clipart-md.png" alt="Logo">
</div>
<h1 class="name">Mamma Mia</h1>
<h2 class="version">v1.1.0</h2>
<h2 class="version">v2.2.0</h2>
<div id="additionalText">
<h2>This addon provides Movie, Series, Anime, and Live TV HTTPS Streams.<br> https://github.com/UrloMythus/MammaMia/</h2>
</div>
<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>
<p class="description">🕵️‍♂️ = Mediaflowproxy might be needed <br>Select the box with this icon if you want to enable MFP for that source<br></p>
<h3 class="gives">Select Providers:</h3>
<form class="pure-form" id="provider-form">
<div class="provider-group">
<label for="streamingcommunity" class="provider-label">
<input type="checkbox" id="streamingcommunity"> StreamingCommunity
</label>
<span class="fast-search">
<label for="fast_search_sc">
<input type="checkbox" id="fast_search_sc"> Fast Search
</label>
</span>
</div>
<div class="provider-group">
<label for="lordchannel" class="provider-label">
<input type="checkbox" id="lordchannel"> LordChannel
<label for="guardoserie" class="provider-label">
<input type="checkbox" id="guardoserie"> Guardoserie
</label>
</div>
<div class="provider-group">
<label for="streamingwatch" class="provider-label">
<input type="checkbox" id="streamingwatch"> StreamingWatch
</label>
</div>
<div class="provider-group">
<label for="tantifilm" class="provider-label">
<input type="checkbox" id="tantifilm"> Tantifilm
</label>
<span class="fast-search">
<label for="fast_search_tf">
<input type="checkbox" id="fast_search_tf"> Fast Search
</label>
</span>
</div>
<div class="provider-group">
<label for="filmpertutti" class="provider-label">
<input type="checkbox" id="filmpertutti"> Filmpertutti
<label for="guardaflix" class="provider-label">
<input type="checkbox" id="guardaflix"> Guardaflix
</label>
</div>
<div class="provider-group">
@@ -227,39 +202,139 @@ HTML = """
<input type="checkbox" id="animeworld"> Animeworld
</label>
</div>
<div class="provider-group">
<label for="guardaserie" class="provider-label">
<input type="checkbox" id="guardaserie"> Guardaserie
</label>
</div>
<div class="provider-group">
<label for="guardahd" class="provider-label">
<input type="checkbox" id="guardahd"> GuardaHD
</label>
</div>
<div>
</div>
<div class="provider-group">
<label for="cb01" class="provider-label">
<input type="checkbox" id="cb01"> CB01 🕵️‍♂️
</label>
</div>
<div class="provider-group">
<label for="onlineserietv" class="provider-label">
<input type="checkbox" id="onlineserietv"> OnlineSerieTV
</label>
</div>
<div class="provider-group">
<label for="vidxgo" class="provider-label">
<input type="checkbox" id="vidxgo"> Vidxgo
</label>
</div>
<div class="provider-group">
<label for="streamingcommunity" class="provider-label">
<input type="checkbox" id="streamingcommunity"> StreamingCommunity 🕵️‍♂️
<input type="checkbox" id="streamingcommunity_mfp" checked> 🕵️‍♂️
</label>
</div>
<div class="provider-group">
<label for="eurostreaming" class="provider-label">
<input type="checkbox" id="eurostreaming"> Eurostreaming 🕵️‍♂️
</label>
</div>
<div class="provider-group">
<label for="realtime" class="provider-label">
<input type="checkbox" id="toonitalia"> Toonitalia 🕵️‍♂️
</label>
</div>
<div class="provider-group">
<label for="realtime" class="provider-label">
<input type="checkbox" id="realtime"> Realtime
</label>
</div>
<div class="provider-group">
<label for="livetv" class="provider-label">
<input type="checkbox" id="livetv"> LiveTV
</label>
</div>
<div class="provider-group">
<label for="mediaflowproxy" class="provider-label">
<input type="checkbox" id="mediaflowproxy"> MediaFlow Proxy
</label>
<button type="button" id="mediaFlowProxyButton">Insert Proxy Info</button>
</div>
<div id="mediaFlowProxyInputContainer" style="display: none;">
<input type="text" id="mediaFlowProxyInput" placeholder="Proxy URL">
</div>
<div id="mediaFlowProxyPasswordContainer" style="display: none;">
<input type="password" id="mediaFlowProxyPassword" placeholder="Insert Password">
</div>
</form>
<button id="generateManifestButton">Generate Link</button>
<button id="installButton">INSTALL</button>
<button id="generateManifestButton">Generate Manifest</button>
<div id="manifestBox"></div>
<button id="installButton">Install in Stremio</button>
</div>
<script>
// Toggle visibility of proxy input fields
document.getElementById('mediaFlowProxyButton').addEventListener('click', function() {
const inputContainer = document.getElementById('mediaFlowProxyInputContainer');
const passwordInputContainer = document.getElementById('mediaFlowProxyPasswordContainer');
inputContainer.style.display = inputContainer.style.display === 'none' ? 'block' : 'none';
passwordInputContainer.style.display = passwordInputContainer.style.display === 'none' ? 'block' : 'none';
});
// Function to generate the manifest URL
function generateManifest() {
let manifest = "|";
const providers = {
"streamingcommunity": "SC",
"fast_search_sc": "SC_FS",
"lordchannel": "LC",
"streamingwatch": "SW",
"tantifilm": "TF",
"fast_search_tf": "TF_FS",
"filmpertutti": "FT",
"animeworld": "AW"
"animeworld": "AW",
"livetv": "LIVETV",
"cb01": "CB",
"guardaserie": "GS",
"guardahd": "GHD",
"guardoserie": "GO",
"guardaflix": "GF",
"eurostreaming": "ES",
"realtime": "RT",
"toonitalia": "TI",
"onlineserietv": "OST",
"vidxgo": "VD",
"streamingcommunity_mfp": "SC_MFP",
"mediaflowproxy": "MFP"
};
// Loop through providers and add selected ones to the manifest
for (const id in providers) {
if (document.getElementById(id).checked) {
if (id === "mediaflowproxy") {
// Add proxy details if MFP is selected
const proxyUrl = document.getElementById("mediaFlowProxyInput").value.trim();
const proxyPassword = document.getElementById("mediaFlowProxyPassword").value.trim();
if (proxyUrl && proxyPassword) {
manifest += `MFP[${proxyUrl},${proxyPassword}]|`;
} else {
manifest += providers[id] + "|"; // Fallback to just "MFP" if no details provided
}
} else {
manifest += providers[id] + "|";
}
}
const instanceUrl = "{instance_url}"; // Keep http in the URL
const manifestUrl = instanceUrl + "/" + manifest + "/" + "manifest.json";
}
const encodedProviders = btoa(manifest);
const instanceUrl = "{instance_url}"; // Replace with your instance URL
const manifestUrl = instanceUrl + "/" + encodedProviders + "/" + "manifest.json";
return manifestUrl;
}
// Generate manifest URL and display it
document.getElementById('generateManifestButton').addEventListener('click', function() {
const manifestUrl = generateManifest();
document.getElementById("manifestBox").style.display = "block";
document.getElementById("manifestBox").innerText = manifestUrl;
const manifestBox = document.getElementById("manifestBox");
manifestBox.style.display = "block";
manifestBox.innerText = manifestUrl;
});
// Install the manifest in Stremio
document.getElementById('installButton').addEventListener('click', function() {
let manifestUrl = generateManifest();
manifestUrl = manifestUrl.replace("http://", "");
+128
View File
@@ -0,0 +1,128 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Mamma Mia</title>
<link rel="icon" href="https://creazilla-store.fra1.digitaloceanspaces.com/emojis/49647/pizza-emoji-clipart-md.png" type="image/x-icon">
<title>Fast Search Example</title>
<style>
* {
box-sizing: border-box;
}
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
font-size: 2.2vh;
font-family: 'Open Sans', Arial, sans-serif;
color: white;
background: url('https://i.postimg.cc/ry3p76HY/italian-seamless-free-vector-pattern3.png') center center repeat;
background-size: cover;
display: flex;
align-items: flex-start;
justify-content: center;
overflow-y: auto;
}
#captcha {
background: rgba(0, 0, 0, 0.8);
padding: 0.5vh;
border-radius: 10px;
width: 65vh;
max-width: 100%;
text-align: center;
margin-top: 10vh;
}
.logo {
width: 12vh;
margin: 0 auto;
margin-bottom: 3vh;
margin-top: -3vh;
}
.logo img {
width: 100%;
height: auto;
}
.captchaimg img {
width: 80%;
height: auto;
object-fit: contain;
display: block;
margin: 0 auto;
}
h1, h2, h3 {
margin: 0;
text-shadow: 0 0 1vh rgba(0, 0, 0, 0.15);
}
h1 {
font-size: 4.5vh;
font-weight: 700;
}
h2 {
font-size: 2vh;
font-weight: normal;
font-style: italic;
opacity: 0.8;
margin-bottom: 20px;
}
h3 {
font-size: 2.2vh;
margin-bottom: 10px;
}
#additionalText {
margin-top: 2vh;
font-size: 1.8vh;
text-align: left;
}
/* Responsive adjustments for smaller screens */
@media (max-width: 600px) {
.provider-group label {
font-size: 2vh;
white-space: nowrap;
}
}
form {
border: 0;
outline: 0;
color: white;
background: #8A5AAB;
padding: 1.2vh 3.5vh;
text-align: center;
font-family: 'Open Sans', Arial, sans-serif;
font-size: 2.2vh;
font-weight: 600;
cursor: pointer;
display: block;
box-shadow: 0 0.5vh 1vh rgba(0, 0, 0, 0.2);
transition: box-shadow 0.1s ease-in-out;
width: 80%;
max-width: 35vh;
margin: 1vh auto;
}
form:hover {
box-shadow: none;
}
</style>
</head>
<body>
<div id="captcha">
<div class="logo">
<img src="https://creazilla-store.fra1.digitaloceanspaces.com/emojis/49647/pizza-emoji-clipart-md.png" alt="Logo">
</div>
<h1 class="name">Uprot Captcha</h1>
<h2 class="version">Per abilitare MaxStream</h2>
<div id="additionalText">
<h2>Inserire i numeri in foto per abilitare la fonte MaxStream per la durata di un giorno<br> https://github.com/UrloMythus/MammaMia/</h2>
<div class="captchaimg">
<img src="{{ image_url }}" alt="Failed to get the captcha">
</div>
<form id = 'form' action="/uprot" method="post">
<input type="text" name="user_input" required>
<button type="submit">Submit</button>
</form>
</body>
</html>
+159
View File
@@ -0,0 +1,159 @@
#!/usr/bin/env python3
"""
Merge remote URLs into local config.json, replacing ONLY the "url" lines.
- Scarica config.json remoto (raw GitHub).
- Per ogni sito in "Siti", segue i redirect e trova l'URL finale.
- Apre il config.json locale come testo, trova le righe "url" relative ai siti
e sostituisce SOLO il valore dentro le virgolette, preservando tutto il resto.
- Crea un backup del config.json locale prima di sovrascriverlo.
"""
from pathlib import Path
from datetime import datetime
import shutil
import re
import requests
import urllib3
from urllib.parse import urlparse
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# --- CONFIGURAZIONE ---
REMOTE_RAW_URL = "https://raw.githubusercontent.com/UrloMythus/MammaMia/main/config.json"
LOCAL_CONFIG_PATH = Path("config.json")
HEADERS = {"User-Agent": "Mozilla/5.0 (compatible; DomainMerger/1.0)"}
REQUEST_TIMEOUT = 12
# -----------------------
def backup_file(path: Path) -> Path | None:
if not path.exists():
return None
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
bak = path.with_name(f"{path.name}.bak_{ts}")
shutil.copy2(path, bak)
return bak
def normalize_url(u: str) -> str:
parsed = urlparse(u)
scheme = parsed.scheme if parsed.scheme else "https"
netloc = parsed.netloc or parsed.path
return f"{scheme}://{netloc}"
def follow_redirect(url: str) -> str | None:
if not url.startswith(("http://", "https://")):
test = "http://" + url
else:
test = url
try:
r = requests.get(test, allow_redirects=True, headers=HEADERS,
timeout=REQUEST_TIMEOUT, verify=False)
return normalize_url(r.url)
except requests.RequestException as e:
print(f"⚠️ Redirect fallito per '{url}': {e}")
return None
def load_remote_urls(remote_raw_url: str) -> dict:
"""Scarica il JSON remoto e ritorna mappa site_key -> url (o None se mancante)."""
try:
r = requests.get(remote_raw_url, headers=HEADERS, timeout=REQUEST_TIMEOUT)
r.raise_for_status()
remote_json = r.json()
except Exception as e:
raise RuntimeError(f"Impossibile scaricare/parsing remote config: {e}")
siti = remote_json.get("Siti", {})
result = {}
for site_key, site_info in siti.items():
url = site_info.get("url")
if url:
result[site_key] = url
return result
def merge_remote_into_local(remote_map: dict, local_path: Path):
if not local_path.exists():
raise FileNotFoundError(f"File locale non trovato: {local_path}")
# backup
bak = backup_file(local_path)
if bak:
print(f"📦 Backup creato: {bak.name}")
text = local_path.read_text(encoding="utf-8")
lines = text.splitlines()
# regex: match apertura blocco sito es. "CB01":{
site_open_re = re.compile(r'^\s*"(?P<site>[^"]+)"\s*:\s*\{\s*$')
# regex per trovare esattamente la riga "url": "valore" preservando indentazione e virgola finale
url_line_re = re.compile(r'^(\s*)"url"\s*:\s*"([^"]*)"( *)(,?)\s*$')
current_site = None
updated_lines = []
changes = []
for idx, line in enumerate(lines):
site_match = site_open_re.match(line)
if site_match:
current_site = site_match.group("site")
updated_lines.append(line)
continue
url_match = url_line_re.match(line)
if url_match:
indent = url_match.group(1)
old_value = url_match.group(2)
trailing_space = url_match.group(3) or ""
trailing_comma = url_match.group(4) or ""
site_key = current_site or "unknown"
# se il sito esiste nella mappa remota, proviamo ad aggiornare
remote_url = remote_map.get(site_key)
if remote_url:
final_url = follow_redirect(remote_url)
if final_url and final_url != normalize_url(old_value):
# sostituisco solo la parte tra virgolette
new_line = f'{indent}"url": "{final_url}"{trailing_space}{trailing_comma}'
updated_lines.append(new_line)
changes.append((site_key, old_value, final_url))
print(f"✅ {site_key}: {old_value} → {final_url}")
else:
# nessuna modifica (redirect fallito o identico)
updated_lines.append(line)
print(f"ℹ️ {site_key}: nessuna modifica per '{old_value}'")
else:
# il sito non è nella lista remota: non tocchiamo la riga
updated_lines.append(line)
print(f"ℹ️ {site_key}: nessun URL remoto per questo sito, riga lasciata invariata")
continue
# linea normale
updated_lines.append(line)
# Scrivo solo se ci sono cambiamenti (ma anche se non ci sono, sovrascrivo per coerenza)
new_text = "\n".join(updated_lines)
# preserva newline finale se il file originale ce l'aveva
if text.endswith("\n") and not new_text.endswith("\n"):
new_text += "\n"
local_path.write_text(new_text, encoding="utf-8")
print("💾 Merge completato: solo le righe 'url' del file locale sono state eventualmente aggiornate.")
if not changes:
print("🔎 Nessun cambiamento effettuato.")
else:
print("📄 Riepilogo modifiche:")
for s, old, new in changes:
print(f" - {s}: {old} → {new}")
def main():
try:
remote_map = load_remote_urls(REMOTE_RAW_URL)
except Exception as e:
print(f"❌ Errore: {e}")
return
try:
merge_remote_into_local(remote_map, LOCAL_CONFIG_PATH)
except Exception as e:
print(f"❌ Errore durante il merge: {e}")
if __name__ == "__main__":
main()
+15
View File
@@ -0,0 +1,15 @@
{
"devCommand": "uvicorn run:app --host 0.0.0.0 --port 8080",
"builds": [
{
"src": "run.py",
"use": "@vercel/python"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "run.py"
}
]
}