mirror of
https://github.com/Arrowar/StreamingCommunity.git
synced 2025-06-06 11:35:29 +00:00
Integration telegram (#251)
* sistemato il file telegram_bot.py come spiegato in chat, fatto un fix nel file session.py per l'aggiornamento del file script.json e sto caricando i file config.json e requerements.txt perchè vengono creati se non esistono quando si avvia il bot con python3 telegram_bot.py * sistemato il file telegram_bot.py come spiegato in chat, fatto un fix nel file session.py per l'aggiornamento del file script.json e sto caricando i file config.json e requerements.txt perchè vengono creati se non esistono quando si avvia il bot con python3 telegram_bot.py * fixato creazione dei file config.json e requerement.txt nella folder del bot
This commit is contained in:
parent
f3dbdffd52
commit
54567a8711
42
README.md
42
README.md
@ -53,7 +53,7 @@
|
|||||||
- 💬 [Support](#support)
|
- 💬 [Support](#support)
|
||||||
- 🤝 [Contribute](#contributing)
|
- 🤝 [Contribute](#contributing)
|
||||||
- ⚠️ [Disclaimer](#disclaimer)
|
- ⚠️ [Disclaimer](#disclaimer)
|
||||||
- ⚡ [Contributors](#contributors)
|
- ⚡ [Contributors](#contributors)
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ For detailed Windows PATH instructions, see the [Windows PATH guide](https://www
|
|||||||
```bash
|
```bash
|
||||||
# For bash (edit ~/.bash_profile)
|
# For bash (edit ~/.bash_profile)
|
||||||
export PATH="/your/custom/path:$PATH"
|
export PATH="/your/custom/path:$PATH"
|
||||||
|
|
||||||
# For zsh (edit ~/.zshrc)
|
# For zsh (edit ~/.zshrc)
|
||||||
export PATH="/your/custom/path:$PATH"
|
export PATH="/your/custom/path:$PATH"
|
||||||
```
|
```
|
||||||
@ -185,7 +185,7 @@ For detailed Windows PATH instructions, see the [Windows PATH guide](https://www
|
|||||||
```bash
|
```bash
|
||||||
# For bash
|
# For bash
|
||||||
source ~/.bash_profile
|
source ~/.bash_profile
|
||||||
|
|
||||||
# For zsh
|
# For zsh
|
||||||
source ~/.zshrc
|
source ~/.zshrc
|
||||||
```
|
```
|
||||||
@ -196,7 +196,7 @@ For detailed Windows PATH instructions, see the [Windows PATH guide](https://www
|
|||||||
```bash
|
```bash
|
||||||
# For bash (edit ~/.bashrc)
|
# For bash (edit ~/.bashrc)
|
||||||
export PATH="/your/custom/path:$PATH"
|
export PATH="/your/custom/path:$PATH"
|
||||||
|
|
||||||
# For zsh (edit ~/.zshrc)
|
# For zsh (edit ~/.zshrc)
|
||||||
export PATH="/your/custom/path:$PATH"
|
export PATH="/your/custom/path:$PATH"
|
||||||
```
|
```
|
||||||
@ -279,7 +279,7 @@ The configuration file is divided into several main sections:
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `root_path`: Directory where all videos will be saved
|
- `root_path`: Directory where all videos will be saved
|
||||||
|
|
||||||
### Path examples:
|
### Path examples:
|
||||||
* Windows: `C:\\MyLibrary\\Folder` or `\\\\MyServer\\MyLibrary` (if you want to use a network folder)
|
* Windows: `C:\\MyLibrary\\Folder` or `\\\\MyServer\\MyLibrary` (if you want to use a network folder)
|
||||||
* Linux/MacOS: `Desktop/MyLibrary/Folder`
|
* Linux/MacOS: `Desktop/MyLibrary/Folder`
|
||||||
@ -305,7 +305,7 @@ The configuration file is divided into several main sections:
|
|||||||
`<br/><br/>`
|
`<br/><br/>`
|
||||||
* Can be changed from terminal with `--map_episode_name`
|
* Can be changed from terminal with `--map_episode_name`
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
|
|
||||||
- `add_siteName`: If set to true, appends the site_name to the root path before the movie and serie folders.
|
- `add_siteName`: If set to true, appends the site_name to the root path before the movie and serie folders.
|
||||||
* Can be changed from terminal with `--add_siteName true/false`
|
* Can be changed from terminal with `--add_siteName true/false`
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
@ -501,15 +501,31 @@ The `run-container` command mounts also the `config.json` file, so any change to
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
You need to create an .env file and enter your Telegram token
|
The bot was created to replace terminal commands and allow interaction via Telegram. Each download runs within a screen session, enabling multiple downloads to run simultaneously.
|
||||||
|
|
||||||
and user ID to authorize only one user to use it
|
To run the bot in the background, simply start it inside a screen session and then press Ctrl + A, followed by D, to detach from the session without stopping the bot.
|
||||||
|
|
||||||
|
Command Functions:
|
||||||
|
|
||||||
|
🔹 /start – Starts a new search for a download. This command performs the same operations as manually running the script in the terminal with test_run.py.
|
||||||
|
|
||||||
|
🔹 /list – Displays the status of active downloads, with options to:
|
||||||
|
|
||||||
|
Stop an incorrect download using /stop <ID>.
|
||||||
|
|
||||||
|
View the real-time output of a download using /screen <ID>.
|
||||||
|
|
||||||
|
⚠ Warning: If a download is interrupted, incomplete files may remain in the folder specified in config.json. These files must be deleted manually to avoid storage or management issues.
|
||||||
|
|
||||||
|
🛠 Configuration: Currently, the bot's settings are stored in the config.json file, which is located in the same directory as the telegram_bot.py script.
|
||||||
|
|
||||||
## .env Example:
|
## .env Example:
|
||||||
|
|
||||||
|
You need to create an .env file and enter your Telegram token and user ID to authorize only one user to use it
|
||||||
|
|
||||||
```
|
```
|
||||||
TOKEN_TELEGRAM=IlTuo2131TOKEN$12D3Telegram
|
TOKEN_TELEGRAM=IlTuo2131TOKEN$12D3Telegram
|
||||||
AUTHORIZED_USER_ID=12345678
|
AUTHORIZED_USER_ID=12345678
|
||||||
DEBUG=False
|
DEBUG=False
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -521,11 +537,13 @@ pip install -r requirements.txt
|
|||||||
|
|
||||||
## On Linux/MacOS:
|
## On Linux/MacOS:
|
||||||
|
|
||||||
|
Start the bot from the folder /StreamingCommunity/TelegramHelp
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 telegram_bot.py
|
python3 telegram_bot.py
|
||||||
```
|
```
|
||||||
|
|
||||||
# Website Status
|
# Website Status
|
||||||
|
|
||||||
| Website | Status | Command |
|
| Website | Status | Command |
|
||||||
|:-------------------|:------:|:--------:|
|
|:-------------------|:------:|:--------:|
|
||||||
@ -540,14 +558,14 @@ python3 telegram_bot.py
|
|||||||
| [StreamingCommunity](https://streamingcommunity.paris/) | ✅ | -STR |
|
| [StreamingCommunity](https://streamingcommunity.paris/) | ✅ | -STR |
|
||||||
|
|
||||||
|
|
||||||
# Tutorials
|
# Tutorials
|
||||||
|
|
||||||
- [Windows Tutorial](https://www.youtube.com/watch?v=mZGqK4wdN-k)
|
- [Windows Tutorial](https://www.youtube.com/watch?v=mZGqK4wdN-k)
|
||||||
- [Linux Tutorial](https://www.youtube.com/watch?v=0qUNXPE_mTg)
|
- [Linux Tutorial](https://www.youtube.com/watch?v=0qUNXPE_mTg)
|
||||||
- [Pypy Tutorial](https://www.youtube.com/watch?v=C6m9ZKOK0p4)
|
- [Pypy Tutorial](https://www.youtube.com/watch?v=C6m9ZKOK0p4)
|
||||||
- [Compiled .exe Tutorial](https://www.youtube.com/watch?v=pm4lqsxkTVo)
|
- [Compiled .exe Tutorial](https://www.youtube.com/watch?v=pm4lqsxkTVo)
|
||||||
|
|
||||||
# To Do
|
# To Do
|
||||||
|
|
||||||
- To Finish [website API](https://github.com/Arrowar/StreamingCommunity/tree/test_gui_1)
|
- To Finish [website API](https://github.com/Arrowar/StreamingCommunity/tree/test_gui_1)
|
||||||
- To finish [website API 2](https://github.com/hydrosh/StreamingCommunity/tree/test_gui_1)
|
- To finish [website API 2](https://github.com/hydrosh/StreamingCommunity/tree/test_gui_1)
|
||||||
|
@ -8,9 +8,7 @@ from StreamingCommunity.Util.console import console
|
|||||||
from StreamingCommunity.Util.os import os_manager
|
from StreamingCommunity.Util.os import os_manager
|
||||||
from StreamingCommunity.Util.message import start_message
|
from StreamingCommunity.Util.message import start_message
|
||||||
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
||||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
|
||||||
from StreamingCommunity.TelegramHelp.session import get_session, updateScriptId, deleteScriptId
|
|
||||||
|
|
||||||
|
|
||||||
# Logic class
|
# Logic class
|
||||||
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
||||||
@ -38,17 +36,17 @@ def download_film(select_title: MediaItem) -> str:
|
|||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
bot = get_bot_instance()
|
bot = get_bot_instance()
|
||||||
bot.send_message(f"Download in corso:\n{select_title.name}", None)
|
bot.send_message(f"Download in corso:\n{select_title.name}", None)
|
||||||
|
|
||||||
# Get script_id
|
# Get script_id
|
||||||
script_id = get_session()
|
script_id = TelegramSession.get_session()
|
||||||
if script_id != "unknown":
|
if script_id != "unknown":
|
||||||
updateScriptId(script_id, select_title.name)
|
TelegramSession.updateScriptId(script_id, select_title.name)
|
||||||
|
|
||||||
# Start message and display film information
|
# Start message and display film information
|
||||||
start_message()
|
start_message()
|
||||||
console.print(f"[yellow]Download: [red]{select_title.name} \n")
|
console.print(f"[yellow]Download: [red]{select_title.name} \n")
|
||||||
console.print(f"[cyan]You can safely stop the download with [bold]Ctrl+c[bold] [cyan] \n")
|
console.print(f"[cyan]You can safely stop the download with [bold]Ctrl+c[bold] [cyan] \n")
|
||||||
|
|
||||||
# Set domain and media ID for the video source
|
# Set domain and media ID for the video source
|
||||||
video_source = VideoSource(select_title.url)
|
video_source = VideoSource(select_title.url)
|
||||||
|
|
||||||
@ -61,17 +59,17 @@ def download_film(select_title: MediaItem) -> str:
|
|||||||
|
|
||||||
# Download the film using the m3u8 playlist, and output filename
|
# Download the film using the m3u8 playlist, and output filename
|
||||||
r_proc = HLS_Downloader(
|
r_proc = HLS_Downloader(
|
||||||
m3u8_url=master_playlist,
|
m3u8_url=master_playlist,
|
||||||
output_path=os.path.join(mp4_path, title_name)
|
output_path=os.path.join(mp4_path, title_name)
|
||||||
).start()
|
).start()
|
||||||
|
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
|
|
||||||
# Delete script_id
|
# Delete script_id
|
||||||
script_id = get_session()
|
script_id = TelegramSession.get_session()
|
||||||
if script_id != "unknown":
|
if script_id != "unknown":
|
||||||
deleteScriptId(script_id)
|
TelegramSession.deleteScriptId(script_id)
|
||||||
|
|
||||||
if "error" in r_proc.keys():
|
if "error" in r_proc.keys():
|
||||||
try:
|
try:
|
||||||
os.remove(r_proc['path'])
|
os.remove(r_proc['path'])
|
||||||
|
@ -10,8 +10,7 @@ from StreamingCommunity.Util.console import console, msg
|
|||||||
from StreamingCommunity.Util.os import os_manager
|
from StreamingCommunity.Util.os import os_manager
|
||||||
from StreamingCommunity.Util.message import start_message
|
from StreamingCommunity.Util.message import start_message
|
||||||
from StreamingCommunity.Lib.Downloader import MP4_downloader
|
from StreamingCommunity.Lib.Downloader import MP4_downloader
|
||||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
|
||||||
from StreamingCommunity.TelegramHelp.session import get_session, updateScriptId, deleteScriptId
|
|
||||||
|
|
||||||
|
|
||||||
# Logic class
|
# Logic class
|
||||||
@ -43,7 +42,7 @@ def download_episode(index_select: int, scrape_serie: ScrapeSerieAnime, video_so
|
|||||||
"""
|
"""
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
bot = get_bot_instance()
|
bot = get_bot_instance()
|
||||||
|
|
||||||
# Get information about the selected episode
|
# Get information about the selected episode
|
||||||
obj_episode = scrape_serie.get_info_episode(index_select)
|
obj_episode = scrape_serie.get_info_episode(index_select)
|
||||||
|
|
||||||
@ -52,14 +51,14 @@ def download_episode(index_select: int, scrape_serie: ScrapeSerieAnime, video_so
|
|||||||
start_message()
|
start_message()
|
||||||
console.print(f"[yellow]Download: [red]EP_{obj_episode.number} \n")
|
console.print(f"[yellow]Download: [red]EP_{obj_episode.number} \n")
|
||||||
console.print("[cyan]You can safely stop the download with [bold]Ctrl+c[bold] [cyan] \n")
|
console.print("[cyan]You can safely stop the download with [bold]Ctrl+c[bold] [cyan] \n")
|
||||||
|
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
bot.send_message(f"Download in corso:\nTitolo:{scrape_serie.series_name}\nEpisodio: {obj_episode.number}", None)
|
bot.send_message(f"Download in corso:\nTitolo:{scrape_serie.series_name}\nEpisodio: {obj_episode.number}", None)
|
||||||
|
|
||||||
# Get script_id
|
# Get script_id
|
||||||
script_id = get_session()
|
script_id = TelegramSession.get_session()
|
||||||
if script_id != "unknown":
|
if script_id != "unknown":
|
||||||
updateScriptId(script_id, f"{scrape_serie.series_name} - E{obj_episode.number}")
|
TelegramSession.updateScriptId(script_id, f"{scrape_serie.series_name} - E{obj_episode.number}")
|
||||||
|
|
||||||
# Collect mp4 url
|
# Collect mp4 url
|
||||||
video_source.get_embed(obj_episode.id)
|
video_source.get_embed(obj_episode.id)
|
||||||
@ -75,15 +74,15 @@ def download_episode(index_select: int, scrape_serie: ScrapeSerieAnime, video_so
|
|||||||
mp4_path = os_manager.get_sanitize_path(os.path.join(MOVIE_FOLDER, scrape_serie.series_name))
|
mp4_path = os_manager.get_sanitize_path(os.path.join(MOVIE_FOLDER, scrape_serie.series_name))
|
||||||
|
|
||||||
# Create output folder
|
# Create output folder
|
||||||
os_manager.create_path(mp4_path)
|
os_manager.create_path(mp4_path)
|
||||||
|
|
||||||
# Start downloading
|
# Start downloading
|
||||||
path, kill_handler = MP4_downloader(
|
path, kill_handler = MP4_downloader(
|
||||||
url=str(video_source.src_mp4).strip(),
|
url=str(video_source.src_mp4).strip(),
|
||||||
path=os.path.join(mp4_path, title_name)
|
path=os.path.join(mp4_path, title_name)
|
||||||
)
|
)
|
||||||
|
|
||||||
return path, kill_handler
|
return path, kill_handler
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logging.error(f"Skip index: {index_select} cant find info with api.")
|
logging.error(f"Skip index: {index_select} cant find info with api.")
|
||||||
@ -98,7 +97,7 @@ def download_series(select_title: MediaItem):
|
|||||||
- tv_name (str): The name of the TV series.
|
- tv_name (str): The name of the TV series.
|
||||||
"""
|
"""
|
||||||
start_message()
|
start_message()
|
||||||
|
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
bot = get_bot_instance()
|
bot = get_bot_instance()
|
||||||
|
|
||||||
@ -123,9 +122,9 @@ def download_series(select_title: MediaItem):
|
|||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
# Prompt user to select an episode index
|
# Prompt user to select an episode index
|
||||||
last_command = msg.ask("\n[cyan]Insert media [red]index [yellow]or [red](*) [cyan]to download all media [yellow]or [red][1-2] [cyan]or [red][3-*] [cyan]for a range of media")
|
last_command = msg.ask("\n[cyan]Insert media [red]index [yellow]or [red](*) [cyan]to download all media [yellow]or [red][1-2] [cyan]or [red][3-*] [cyan]for a range of media")
|
||||||
|
|
||||||
# Manage user selection
|
# Manage user selection
|
||||||
list_episode_select = manage_selection(last_command, episoded_count)
|
list_episode_select = manage_selection(last_command, episoded_count)
|
||||||
@ -140,16 +139,16 @@ def download_series(select_title: MediaItem):
|
|||||||
kill_handler = False
|
kill_handler = False
|
||||||
for i_episode in list_episode_select:
|
for i_episode in list_episode_select:
|
||||||
if kill_handler:
|
if kill_handler:
|
||||||
break
|
break
|
||||||
_, kill_handler = download_episode(i_episode-1, scrape_serie, video_source)
|
_, kill_handler = download_episode(i_episode-1, scrape_serie, video_source)
|
||||||
|
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
bot.send_message(f"Finito di scaricare tutte le serie e episodi", None)
|
bot.send_message(f"Finito di scaricare tutte le serie e episodi", None)
|
||||||
|
|
||||||
# Get script_id
|
# Get script_id
|
||||||
script_id = get_session()
|
script_id = TelegramSession.get_session()
|
||||||
if script_id != "unknown":
|
if script_id != "unknown":
|
||||||
deleteScriptId(script_id)
|
TelegramSession.deleteScriptId(script_id)
|
||||||
|
|
||||||
|
|
||||||
def download_film(select_title: MediaItem):
|
def download_film(select_title: MediaItem):
|
||||||
|
@ -8,8 +8,7 @@ from StreamingCommunity.Util.console import console
|
|||||||
from StreamingCommunity.Util.os import os_manager
|
from StreamingCommunity.Util.os import os_manager
|
||||||
from StreamingCommunity.Util.message import start_message
|
from StreamingCommunity.Util.message import start_message
|
||||||
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
||||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
|
||||||
from StreamingCommunity.TelegramHelp.session import get_session, updateScriptId, deleteScriptId
|
|
||||||
|
|
||||||
|
|
||||||
# Logic class
|
# Logic class
|
||||||
@ -39,13 +38,13 @@ def download_film(select_title: MediaItem) -> str:
|
|||||||
bot = get_bot_instance()
|
bot = get_bot_instance()
|
||||||
bot.send_message(f"Download in corso:\n{select_title.name}", None)
|
bot.send_message(f"Download in corso:\n{select_title.name}", None)
|
||||||
|
|
||||||
# Viene usato per lo screen
|
# Viene usato per lo screen
|
||||||
console.print(f"## Download: [red]{select_title.name} ##")
|
console.print(f"## Download: [red]{select_title.name} ##")
|
||||||
|
|
||||||
# Get script_id
|
# Get script_id
|
||||||
script_id = get_session()
|
script_id = TelegramSession.get_session()
|
||||||
if script_id != "unknown":
|
if script_id != "unknown":
|
||||||
updateScriptId(script_id, select_title.name)
|
TelegramSession.updateScriptId(script_id, select_title.name)
|
||||||
|
|
||||||
# Start message and display film information
|
# Start message and display film information
|
||||||
start_message()
|
start_message()
|
||||||
@ -66,16 +65,16 @@ def download_film(select_title: MediaItem) -> str:
|
|||||||
|
|
||||||
# Download the film using the m3u8 playlist, and output filename
|
# Download the film using the m3u8 playlist, and output filename
|
||||||
r_proc = HLS_Downloader(
|
r_proc = HLS_Downloader(
|
||||||
m3u8_url=master_playlist,
|
m3u8_url=master_playlist,
|
||||||
output_path=os.path.join(mp4_path, title_name)
|
output_path=os.path.join(mp4_path, title_name)
|
||||||
).start()
|
).start()
|
||||||
|
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
|
|
||||||
# Delete script_id
|
# Delete script_id
|
||||||
script_id = get_session()
|
script_id = TelegramSession.get_session()
|
||||||
if script_id != "unknown":
|
if script_id != "unknown":
|
||||||
deleteScriptId(script_id)
|
TelegramSession.deleteScriptId(script_id)
|
||||||
|
|
||||||
if "error" in r_proc.keys():
|
if "error" in r_proc.keys():
|
||||||
try:
|
try:
|
||||||
|
@ -10,9 +10,7 @@ from StreamingCommunity.Util.console import console, msg
|
|||||||
from StreamingCommunity.Util.message import start_message
|
from StreamingCommunity.Util.message import start_message
|
||||||
from StreamingCommunity.Util.table import TVShowManager
|
from StreamingCommunity.Util.table import TVShowManager
|
||||||
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
||||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
|
||||||
from StreamingCommunity.TelegramHelp.session import get_session, updateScriptId, deleteScriptId
|
|
||||||
|
|
||||||
|
|
||||||
# Logic class
|
# Logic class
|
||||||
from .util.ScrapeSerie import ScrapeSerie
|
from .util.ScrapeSerie import ScrapeSerie
|
||||||
@ -50,7 +48,7 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|||||||
|
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
bot = get_bot_instance()
|
bot = get_bot_instance()
|
||||||
|
|
||||||
# Invio a telegram
|
# Invio a telegram
|
||||||
bot.send_message(
|
bot.send_message(
|
||||||
f"Download in corso\nSerie: {scrape_serie.series_name}\nStagione: {index_season_selected}\nEpisodio: {index_episode_selected}\nTitolo: {obj_episode.name}",
|
f"Download in corso\nSerie: {scrape_serie.series_name}\nStagione: {index_season_selected}\nEpisodio: {index_episode_selected}\nTitolo: {obj_episode.name}",
|
||||||
@ -58,9 +56,9 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Get script_id and update it
|
# Get script_id and update it
|
||||||
script_id = get_session()
|
script_id = TelegramSession.get_session()
|
||||||
if script_id != "unknown":
|
if script_id != "unknown":
|
||||||
updateScriptId(script_id, f"{scrape_serie.series_name} - S{index_season_selected} - E{index_episode_selected} - {obj_episode.name}")
|
TelegramSession.updateScriptId(script_id, f"{scrape_serie.series_name} - S{index_season_selected} - E{index_episode_selected} - {obj_episode.name}")
|
||||||
|
|
||||||
# Define filename and path for the downloaded video
|
# Define filename and path for the downloaded video
|
||||||
mp4_name = f"{map_episode_title(scrape_serie.series_name, index_season_selected, index_episode_selected, obj_episode.name)}.mp4"
|
mp4_name = f"{map_episode_title(scrape_serie.series_name, index_season_selected, index_episode_selected, obj_episode.name)}.mp4"
|
||||||
@ -70,13 +68,13 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|||||||
video_source.get_iframe(obj_episode.id)
|
video_source.get_iframe(obj_episode.id)
|
||||||
video_source.get_content()
|
video_source.get_content()
|
||||||
master_playlist = video_source.get_playlist()
|
master_playlist = video_source.get_playlist()
|
||||||
|
|
||||||
# Download the episode
|
# Download the episode
|
||||||
r_proc = HLS_Downloader(
|
r_proc = HLS_Downloader(
|
||||||
m3u8_url=master_playlist,
|
m3u8_url=master_playlist,
|
||||||
output_path=os.path.join(mp4_path, mp4_name)
|
output_path=os.path.join(mp4_path, mp4_name)
|
||||||
).start()
|
).start()
|
||||||
|
|
||||||
if "error" in r_proc.keys():
|
if "error" in r_proc.keys():
|
||||||
try:
|
try:
|
||||||
os.remove(r_proc['path'])
|
os.remove(r_proc['path'])
|
||||||
@ -204,9 +202,9 @@ def download_series(select_season: MediaItem, version: str) -> None:
|
|||||||
bot.send_message(f"Finito di scaricare tutte le serie e episodi", None)
|
bot.send_message(f"Finito di scaricare tutte le serie e episodi", None)
|
||||||
|
|
||||||
# Get script_id
|
# Get script_id
|
||||||
script_id = get_session()
|
script_id = TelegramSession.get_session()
|
||||||
if script_id != "unknown":
|
if script_id != "unknown":
|
||||||
deleteScriptId(script_id)
|
TelegramSession.deleteScriptId(script_id)
|
||||||
|
|
||||||
|
|
||||||
def display_episodes_list(scrape_serie) -> str:
|
def display_episodes_list(scrape_serie) -> str:
|
||||||
|
@ -60,11 +60,11 @@ class HLSClient:
|
|||||||
def request(self, url: str, return_content: bool = False) -> Optional[httpx.Response]:
|
def request(self, url: str, return_content: bool = False) -> Optional[httpx.Response]:
|
||||||
"""
|
"""
|
||||||
Makes HTTP GET requests with retry logic.
|
Makes HTTP GET requests with retry logic.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
url: Target URL to request
|
url: Target URL to request
|
||||||
return_content: If True, returns response content instead of text
|
return_content: If True, returns response content instead of text
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Response content/text or None if all retries fail
|
Response content/text or None if all retries fail
|
||||||
"""
|
"""
|
||||||
@ -74,7 +74,7 @@ class HLSClient:
|
|||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
return response.content if return_content else response.text
|
return response.content if return_content else response.text
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Attempt {attempt+1} failed: {str(e)}")
|
logging.error(f"Attempt {attempt+1} failed: {str(e)}")
|
||||||
time.sleep(1.5 ** attempt)
|
time.sleep(1.5 ** attempt)
|
||||||
@ -103,7 +103,7 @@ class PathManager:
|
|||||||
root = config_manager.get('DEFAULT', 'root_path')
|
root = config_manager.get('DEFAULT', 'root_path')
|
||||||
hash_name = compute_sha1_hash(self.m3u8_url) + ".mp4"
|
hash_name = compute_sha1_hash(self.m3u8_url) + ".mp4"
|
||||||
return os.path.join(root, "undefined", hash_name)
|
return os.path.join(root, "undefined", hash_name)
|
||||||
|
|
||||||
if not path.endswith(".mp4"):
|
if not path.endswith(".mp4"):
|
||||||
path += ".mp4"
|
path += ".mp4"
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ class M3U8Manager:
|
|||||||
content = self.client.request(self.m3u8_url)
|
content = self.client.request(self.m3u8_url)
|
||||||
if not content:
|
if not content:
|
||||||
raise ValueError("Failed to fetch M3U8 content")
|
raise ValueError("Failed to fetch M3U8 content")
|
||||||
|
|
||||||
self.parser.parse_data(uri=self.m3u8_url, raw_content=content)
|
self.parser.parse_data(uri=self.m3u8_url, raw_content=content)
|
||||||
self.url_fixer.set_playlist(self.m3u8_url)
|
self.url_fixer.set_playlist(self.m3u8_url)
|
||||||
self.is_master = self.parser.is_master_playlist
|
self.is_master = self.parser.is_master_playlist
|
||||||
@ -162,7 +162,7 @@ class M3U8Manager:
|
|||||||
self.video_url, self.video_res = self.m3u8_url, "0p"
|
self.video_url, self.video_res = self.m3u8_url, "0p"
|
||||||
self.audio_streams = []
|
self.audio_streams = []
|
||||||
self.sub_streams = []
|
self.sub_streams = []
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if FILTER_CUSTOM_REOLUTION != -1:
|
if FILTER_CUSTOM_REOLUTION != -1:
|
||||||
self.video_url, self.video_res = self.parser._video.get_custom_uri(y_resolution=FILTER_CUSTOM_REOLUTION)
|
self.video_url, self.video_res = self.parser._video.get_custom_uri(y_resolution=FILTER_CUSTOM_REOLUTION)
|
||||||
@ -266,7 +266,7 @@ class DownloadManager:
|
|||||||
"""Downloads audio segments for a specific language track."""
|
"""Downloads audio segments for a specific language track."""
|
||||||
if self.stopped:
|
if self.stopped:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
audio_full_url = self.url_fixer.generate_full_url(audio['uri'])
|
audio_full_url = self.url_fixer.generate_full_url(audio['uri'])
|
||||||
audio_tmp_dir = os.path.join(self.temp_dir, 'audio', audio['language'])
|
audio_tmp_dir = os.path.join(self.temp_dir, 'audio', audio['language'])
|
||||||
|
|
||||||
@ -282,7 +282,7 @@ class DownloadManager:
|
|||||||
"""Downloads and saves subtitle file for a specific language."""
|
"""Downloads and saves subtitle file for a specific language."""
|
||||||
if self.stopped:
|
if self.stopped:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
content = self.client.request(sub['uri'])
|
content = self.client.request(sub['uri'])
|
||||||
if content:
|
if content:
|
||||||
sub_path = os.path.join(self.temp_dir, 'subs', f"{sub['language']}.vtt")
|
sub_path = os.path.join(self.temp_dir, 'subs', f"{sub['language']}.vtt")
|
||||||
@ -299,7 +299,7 @@ class DownloadManager:
|
|||||||
if not os.path.exists(video_file):
|
if not os.path.exists(video_file):
|
||||||
if self.download_video(video_url):
|
if self.download_video(video_url):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
for audio in audio_streams:
|
for audio in audio_streams:
|
||||||
if self.stopped:
|
if self.stopped:
|
||||||
break
|
break
|
||||||
@ -317,7 +317,7 @@ class DownloadManager:
|
|||||||
if not os.path.exists(sub_file):
|
if not os.path.exists(sub_file):
|
||||||
if self.download_subtitle(sub):
|
if self.download_subtitle(sub):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return self.stopped
|
return self.stopped
|
||||||
|
|
||||||
|
|
||||||
@ -340,7 +340,7 @@ class MergeManager:
|
|||||||
"""
|
"""
|
||||||
Merges downloaded streams into final video file.
|
Merges downloaded streams into final video file.
|
||||||
Returns path to the final merged file.
|
Returns path to the final merged file.
|
||||||
|
|
||||||
Process:
|
Process:
|
||||||
1. If no audio/subs, just process video
|
1. If no audio/subs, just process video
|
||||||
2. If audio exists, merge with video
|
2. If audio exists, merge with video
|
||||||
@ -383,7 +383,7 @@ class MergeManager:
|
|||||||
subtitles_list=sub_tracks,
|
subtitles_list=sub_tracks,
|
||||||
out_path=merged_subs_path
|
out_path=merged_subs_path
|
||||||
)
|
)
|
||||||
|
|
||||||
return merged_file
|
return merged_file
|
||||||
|
|
||||||
|
|
||||||
@ -400,14 +400,14 @@ class HLS_Downloader:
|
|||||||
def start(self) -> Dict[str, Any]:
|
def start(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Main execution flow with handling for both index and playlist M3U8s.
|
Main execution flow with handling for both index and playlist M3U8s.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict containing:
|
Dict containing:
|
||||||
- path: Output file path
|
- path: Output file path
|
||||||
- url: Original M3U8 URL
|
- url: Original M3U8 URL
|
||||||
- is_master: Whether the M3U8 was a master playlist
|
- is_master: Whether the M3U8 was a master playlist
|
||||||
Or raises an exception if there's an error
|
Or raises an exception if there's an error
|
||||||
"""
|
"""
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
bot = get_bot_instance()
|
bot = get_bot_instance()
|
||||||
|
|
||||||
@ -417,12 +417,12 @@ class HLS_Downloader:
|
|||||||
response = {
|
response = {
|
||||||
'path': self.path_manager.output_path,
|
'path': self.path_manager.output_path,
|
||||||
'url': self.m3u8_url,
|
'url': self.m3u8_url,
|
||||||
'is_master': False,
|
'is_master': False,
|
||||||
'error': 'File already exists',
|
'error': 'File already exists',
|
||||||
'stopped': False
|
'stopped': False
|
||||||
}
|
}
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
bot.send_message(response)
|
bot.send_message(f"Contenuto già scaricato!", None)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
self.path_manager.setup_directories()
|
self.path_manager.setup_directories()
|
||||||
@ -437,7 +437,7 @@ class HLS_Downloader:
|
|||||||
client=self.client,
|
client=self.client,
|
||||||
url_fixer=self.m3u8_manager.url_fixer
|
url_fixer=self.m3u8_manager.url_fixer
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if download was stopped
|
# Check if download was stopped
|
||||||
download_stopped = self.download_manager.download_all(
|
download_stopped = self.download_manager.download_all(
|
||||||
video_url=self.m3u8_manager.video_url,
|
video_url=self.m3u8_manager.video_url,
|
||||||
@ -478,7 +478,7 @@ class HLS_Downloader:
|
|||||||
error_msg = str(e)
|
error_msg = str(e)
|
||||||
console.print(f"[red]Download failed: {error_msg}[/red]")
|
console.print(f"[red]Download failed: {error_msg}[/red]")
|
||||||
logging.error("Download error", exc_info=True)
|
logging.error("Download error", exc_info=True)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'path': None,
|
'path': None,
|
||||||
'url': self.m3u8_url,
|
'url': self.m3u8_url,
|
||||||
@ -486,7 +486,7 @@ class HLS_Downloader:
|
|||||||
'error': error_msg,
|
'error': error_msg,
|
||||||
'stopped': False
|
'stopped': False
|
||||||
}
|
}
|
||||||
|
|
||||||
def _print_summary(self):
|
def _print_summary(self):
|
||||||
"""Prints download summary including file size, duration, and any missing segments."""
|
"""Prints download summary including file size, duration, and any missing segments."""
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
# 04.02.25
|
|
||||||
# Made by: @GiuPic
|
|
||||||
|
|
||||||
import json
|
|
||||||
import time
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
class RequestManager:
|
|
||||||
_instance = None
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
if not cls._instance:
|
|
||||||
cls._instance = super().__new__(cls)
|
|
||||||
return cls._instance
|
|
||||||
|
|
||||||
def __init__(self, json_file: str = "active_requests.json"):
|
|
||||||
if not hasattr(self, 'initialized'):
|
|
||||||
self.json_file = json_file
|
|
||||||
self.initialized = True
|
|
||||||
self.on_response_callback = None
|
|
||||||
|
|
||||||
def create_request(self, type: str) -> str:
|
|
||||||
request_data = {
|
|
||||||
"type": type,
|
|
||||||
"response": None,
|
|
||||||
"timestamp": time.time()
|
|
||||||
}
|
|
||||||
|
|
||||||
with open(self.json_file, "w") as f:
|
|
||||||
json.dump(request_data, f)
|
|
||||||
|
|
||||||
return "Ok"
|
|
||||||
|
|
||||||
def save_response(self, message_text: str) -> bool:
|
|
||||||
try:
|
|
||||||
# Carica il file JSON
|
|
||||||
with open(self.json_file, "r") as f:
|
|
||||||
data = json.load(f)
|
|
||||||
|
|
||||||
# Controlla se esiste la chiave 'type' e se la risposta è presente
|
|
||||||
if "type" in data and "response" in data:
|
|
||||||
data["response"] = message_text # Aggiorna la risposta
|
|
||||||
|
|
||||||
with open(self.json_file, "w") as f:
|
|
||||||
json.dump(data, f, indent=4)
|
|
||||||
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
||||||
print(f"⚠️ save_response - errore: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_response(self) -> Optional[str]:
|
|
||||||
try:
|
|
||||||
with open(self.json_file, "r") as f:
|
|
||||||
data = json.load(f)
|
|
||||||
|
|
||||||
# Verifica se esiste la chiave "response"
|
|
||||||
if "response" in data:
|
|
||||||
response = data["response"] # Ottieni la risposta direttamente
|
|
||||||
|
|
||||||
if response is not None and self.on_response_callback:
|
|
||||||
self.on_response_callback(response)
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
||||||
print(f"get_response - errore: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def clear_file(self) -> bool:
|
|
||||||
try:
|
|
||||||
with open(self.json_file, "w") as f:
|
|
||||||
json.dump({}, f)
|
|
||||||
print(f"File {self.json_file} è stato svuotato con successo.")
|
|
||||||
return True
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"⚠️ clear_file - errore: {e}")
|
|
||||||
return False
|
|
@ -1,56 +0,0 @@
|
|||||||
# 04.02.25
|
|
||||||
# Made by: @GiuPic
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
session_data = {}
|
|
||||||
|
|
||||||
def set_session(value):
|
|
||||||
session_data['script_id'] = value
|
|
||||||
|
|
||||||
def get_session():
|
|
||||||
return session_data.get('script_id', 'unknown')
|
|
||||||
|
|
||||||
def updateScriptId(screen_id, titolo):
|
|
||||||
json_file = "scripts.json"
|
|
||||||
try:
|
|
||||||
with open(json_file, 'r') as f:
|
|
||||||
scripts_data = json.load(f)
|
|
||||||
except FileNotFoundError:
|
|
||||||
scripts_data = []
|
|
||||||
|
|
||||||
# cerco lo script con lo screen_id
|
|
||||||
for script in scripts_data:
|
|
||||||
if script["screen_id"] == screen_id:
|
|
||||||
# se trovo il match, aggiorno il titolo
|
|
||||||
script["titolo"] = titolo
|
|
||||||
|
|
||||||
# aggiorno il file json
|
|
||||||
with open(json_file, 'w') as f:
|
|
||||||
json.dump(scripts_data, f, indent=4)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"Screen_id {screen_id} non trovato.")
|
|
||||||
|
|
||||||
def deleteScriptId(screen_id):
|
|
||||||
json_file = "scripts.json"
|
|
||||||
try:
|
|
||||||
with open(json_file, 'r') as f:
|
|
||||||
scripts_data = json.load(f)
|
|
||||||
except FileNotFoundError:
|
|
||||||
scripts_data = []
|
|
||||||
|
|
||||||
for script in scripts_data:
|
|
||||||
if script["screen_id"] == screen_id:
|
|
||||||
# se trovo il match, elimino lo script
|
|
||||||
scripts_data.remove(script)
|
|
||||||
|
|
||||||
# aggiorno il file json
|
|
||||||
with open(json_file, 'w') as f:
|
|
||||||
json.dump(scripts_data, f, indent=4)
|
|
||||||
|
|
||||||
print(f"Script eliminato per screen_id {screen_id}")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"Screen_id {screen_id} non trovato.")
|
|
@ -1,4 +1,4 @@
|
|||||||
# 04.02.25
|
# 04.02.26
|
||||||
# Made by: @GiuPic
|
# Made by: @GiuPic
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@ -9,16 +9,141 @@ import uuid
|
|||||||
import json
|
import json
|
||||||
import threading
|
import threading
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import threading
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
# External libraries
|
# External libraries
|
||||||
import telebot
|
import telebot
|
||||||
|
|
||||||
|
session_data = {}
|
||||||
|
|
||||||
# Fix import
|
class TelegramSession:
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
|
|
||||||
from StreamingCommunity.TelegramHelp.request_manager import RequestManager
|
|
||||||
|
|
||||||
|
def set_session(value):
|
||||||
|
session_data['script_id'] = value
|
||||||
|
|
||||||
|
def get_session():
|
||||||
|
return session_data.get('script_id', 'unknown')
|
||||||
|
|
||||||
|
def updateScriptId(screen_id, titolo):
|
||||||
|
json_file = "../../scripts.json"
|
||||||
|
try:
|
||||||
|
with open(json_file, 'r') as f:
|
||||||
|
scripts_data = json.load(f)
|
||||||
|
except FileNotFoundError:
|
||||||
|
scripts_data = []
|
||||||
|
|
||||||
|
# cerco lo script con lo screen_id
|
||||||
|
for script in scripts_data:
|
||||||
|
if script["screen_id"] == screen_id:
|
||||||
|
# se trovo il match, aggiorno il titolo
|
||||||
|
script["titolo"] = titolo
|
||||||
|
|
||||||
|
# aggiorno il file json
|
||||||
|
with open(json_file, 'w') as f:
|
||||||
|
json.dump(scripts_data, f, indent=4)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Screen_id {screen_id} non trovato.")
|
||||||
|
|
||||||
|
def deleteScriptId(screen_id):
|
||||||
|
json_file = "../../scripts.json"
|
||||||
|
try:
|
||||||
|
with open(json_file, 'r') as f:
|
||||||
|
scripts_data = json.load(f)
|
||||||
|
except FileNotFoundError:
|
||||||
|
scripts_data = []
|
||||||
|
|
||||||
|
for script in scripts_data:
|
||||||
|
if script["screen_id"] == screen_id:
|
||||||
|
# se trovo il match, elimino lo script
|
||||||
|
scripts_data.remove(script)
|
||||||
|
|
||||||
|
# aggiorno il file json
|
||||||
|
with open(json_file, 'w') as f:
|
||||||
|
json.dump(scripts_data, f, indent=4)
|
||||||
|
|
||||||
|
print(f"Script eliminato per screen_id {screen_id}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Screen_id {screen_id} non trovato.")
|
||||||
|
|
||||||
|
class TelegramRequestManager:
|
||||||
|
_instance = None
|
||||||
|
|
||||||
|
def __new__(cls, *args, **kwargs):
|
||||||
|
if not cls._instance:
|
||||||
|
cls._instance = super().__new__(cls)
|
||||||
|
return cls._instance
|
||||||
|
|
||||||
|
def __init__(self, json_file: str = "active_requests.json"):
|
||||||
|
if not hasattr(self, 'initialized'):
|
||||||
|
self.json_file = json_file
|
||||||
|
self.initialized = True
|
||||||
|
self.on_response_callback = None
|
||||||
|
|
||||||
|
def create_request(self, type: str) -> str:
|
||||||
|
request_data = {
|
||||||
|
"type": type,
|
||||||
|
"response": None,
|
||||||
|
"timestamp": time.time()
|
||||||
|
}
|
||||||
|
|
||||||
|
with open(self.json_file, "w") as f:
|
||||||
|
json.dump(request_data, f)
|
||||||
|
|
||||||
|
return "Ok"
|
||||||
|
|
||||||
|
def save_response(self, message_text: str) -> bool:
|
||||||
|
try:
|
||||||
|
# Carica il file JSON
|
||||||
|
with open(self.json_file, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
# Controlla se esiste la chiave 'type' e se la risposta è presente
|
||||||
|
if "type" in data and "response" in data:
|
||||||
|
data["response"] = message_text # Aggiorna la risposta
|
||||||
|
|
||||||
|
with open(self.json_file, "w") as f:
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
except (FileNotFoundError, json.JSONDecodeError) as e:
|
||||||
|
print(f"⚠️ save_response - errore: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_response(self) -> Optional[str]:
|
||||||
|
try:
|
||||||
|
with open(self.json_file, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
# Verifica se esiste la chiave "response"
|
||||||
|
if "response" in data:
|
||||||
|
response = data["response"] # Ottieni la risposta direttamente
|
||||||
|
|
||||||
|
if response is not None and self.on_response_callback:
|
||||||
|
self.on_response_callback(response)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
except (FileNotFoundError, json.JSONDecodeError) as e:
|
||||||
|
print(f"get_response - errore: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def clear_file(self) -> bool:
|
||||||
|
try:
|
||||||
|
with open(self.json_file, "w") as f:
|
||||||
|
json.dump({}, f)
|
||||||
|
print(f"File {self.json_file} è stato svuotato con successo.")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ clear_file - errore: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
# Funzione per caricare variabili da un file .env
|
# Funzione per caricare variabili da un file .env
|
||||||
def load_env(file_path="../../.env"):
|
def load_env(file_path="../../.env"):
|
||||||
@ -44,13 +169,17 @@ class TelegramBot:
|
|||||||
if os.path.exists(cls._config_file):
|
if os.path.exists(cls._config_file):
|
||||||
with open(cls._config_file, "r") as f:
|
with open(cls._config_file, "r") as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
cls._instance = cls.init_bot(
|
|
||||||
config["token"], config["authorized_user_id"]
|
# Assicura che authorized_user_id venga trattato come una lista
|
||||||
)
|
authorized_users = config.get('authorized_user_id', [])
|
||||||
|
if isinstance(authorized_users, str):
|
||||||
|
authorized_users = [int(uid) for uid in authorized_users.split(",") if uid.strip().isdigit()]
|
||||||
|
|
||||||
|
cls._instance = cls.init_bot(config['token'], authorized_users)
|
||||||
|
#cls._instance = cls.init_bot(config['token'], config['authorized_user_id'])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception(
|
raise Exception("Bot non ancora inizializzato. Chiamare prima init_bot() con token e authorized_user_id")
|
||||||
"Bot non ancora inizializzato. Chiamare prima init_bot() con token e authorized_user_id"
|
|
||||||
)
|
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -63,7 +192,8 @@ class TelegramBot:
|
|||||||
json.dump(config, f)
|
json.dump(config, f)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def __init__(self, token, authorized_user_id):
|
def __init__(self, token, authorized_users):
|
||||||
|
|
||||||
def monitor_scripts():
|
def monitor_scripts():
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@ -132,10 +262,10 @@ class TelegramBot:
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.token = token
|
self.token = token
|
||||||
self.authorized_user_id = authorized_user_id
|
self.authorized_users = authorized_users
|
||||||
self.chat_id = authorized_user_id
|
self.chat_id = authorized_users
|
||||||
self.bot = telebot.TeleBot(token)
|
self.bot = telebot.TeleBot(token)
|
||||||
self.request_manager = RequestManager()
|
self.request_manager = TelegramRequestManager()
|
||||||
|
|
||||||
# Registra gli handler
|
# Registra gli handler
|
||||||
self.register_handlers()
|
self.register_handlers()
|
||||||
@ -171,7 +301,7 @@ class TelegramBot:
|
|||||||
self.handle_response(message)
|
self.handle_response(message)
|
||||||
|
|
||||||
def is_authorized(self, user_id):
|
def is_authorized(self, user_id):
|
||||||
return user_id == self.authorized_user_id
|
return user_id in self.authorized_users
|
||||||
|
|
||||||
def handle_get_id(self, message):
|
def handle_get_id(self, message):
|
||||||
if not self.is_authorized(message.from_user.id):
|
if not self.is_authorized(message.from_user.id):
|
||||||
@ -194,7 +324,6 @@ class TelegramBot:
|
|||||||
|
|
||||||
screen_id = str(uuid.uuid4())[:8]
|
screen_id = str(uuid.uuid4())[:8]
|
||||||
debug_mode = os.getenv("DEBUG")
|
debug_mode = os.getenv("DEBUG")
|
||||||
verbose = debug_mode
|
|
||||||
|
|
||||||
if debug_mode == "True":
|
if debug_mode == "True":
|
||||||
subprocess.Popen(["python3", "../../test_run.py", screen_id])
|
subprocess.Popen(["python3", "../../test_run.py", screen_id])
|
||||||
@ -407,6 +536,13 @@ class TelegramBot:
|
|||||||
temp_file = f"/tmp/screen_output_{screen_id}.txt"
|
temp_file = f"/tmp/screen_output_{screen_id}.txt"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Verifica se lo screen con l'ID specificato esiste
|
||||||
|
existing_screens = subprocess.check_output(["screen", "-list"]).decode('utf-8')
|
||||||
|
if screen_id not in existing_screens:
|
||||||
|
print(f"⚠️ La sessione screen con ID {screen_id} non esiste.")
|
||||||
|
self.bot.send_message(message.chat.id, f"⚠️ La sessione screen con ID {screen_id} non esiste.")
|
||||||
|
return
|
||||||
|
|
||||||
# Cattura l'output della screen
|
# Cattura l'output della screen
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["screen", "-X", "-S", screen_id, "hardcopy", "-h", temp_file],
|
["screen", "-X", "-S", screen_id, "hardcopy", "-h", temp_file],
|
||||||
@ -440,51 +576,22 @@ class TelegramBot:
|
|||||||
"\n\n", "\n"
|
"\n\n", "\n"
|
||||||
) # Rimuovi newline multipli
|
) # Rimuovi newline multipli
|
||||||
|
|
||||||
# Estrarre tutte le parti da "Download:" fino a "Video" o "Subtitle", senza includerli
|
# Dentro cleaned_output c'è una stringa recupero quello che si trova tra ## ##
|
||||||
download_matches = re.findall(
|
download_section = re.search(r"##(.*?)##", cleaned_output, re.DOTALL)
|
||||||
r"Download: (.*?)(?:Video|Subtitle)", cleaned_output
|
if download_section:
|
||||||
)
|
cleaned_output_0 = "Download: " + download_section.group(1).strip()
|
||||||
if download_matches:
|
|
||||||
# Serie TV e Film StreamingCommunity
|
|
||||||
|
|
||||||
proc_matches = re.findall(r"Proc: ([\d\.]+%)", cleaned_output)
|
# Recupero tutto quello che viene dopo con ####
|
||||||
|
download_section_bottom = re.search(r"####(.*)", cleaned_output, re.DOTALL)
|
||||||
|
if download_section_bottom:
|
||||||
|
cleaned_output_1 = download_section_bottom.group(1).strip()
|
||||||
|
|
||||||
# Creare una stringa unica con tutti i risultati
|
# Unico i due risultati se esistono
|
||||||
result_string = "\n".join(
|
if cleaned_output_0 and cleaned_output_1:
|
||||||
[
|
cleaned_output = f"{cleaned_output_0}\n{cleaned_output_1}"
|
||||||
f"Download: {download_matches[i].strip()}\nDownload al {proc_matches[i]}"
|
# Rimuovo 'segments.py:302' e 'downloader.py:385' se presente
|
||||||
for i in range(len(download_matches))
|
cleaned_output = re.sub(r'downloader\.py:\d+', '', cleaned_output)
|
||||||
if i < len(proc_matches)
|
cleaned_output = re.sub(r'segments\.py:\d+', '', cleaned_output)
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
if result_string != "":
|
|
||||||
cleaned_output = result_string
|
|
||||||
else:
|
|
||||||
print(f"❌ La parola 'Download:' non è stata trovata nella stringa.")
|
|
||||||
else:
|
|
||||||
|
|
||||||
download_list = []
|
|
||||||
|
|
||||||
# Estrai tutte le righe che iniziano con "Download:" fino al prossimo "Download" o alla fine della riga
|
|
||||||
matches = re.findall(r"Download:\s*(.*?)(?=Download|$)", cleaned_output)
|
|
||||||
|
|
||||||
# Se sono stati trovati download, stampali
|
|
||||||
if matches:
|
|
||||||
for i, match in enumerate(matches, 1):
|
|
||||||
# rimuovo solo la parte "downloader.py:57Result:400" se esiste
|
|
||||||
match = re.sub(r"downloader.py:\d+Result:400", "", match)
|
|
||||||
match = match.strip() # Rimuovo gli spazi bianchi in eccesso
|
|
||||||
if match: # Assicurati che la stringa non sia vuota
|
|
||||||
print(f"Download {i}: {match}")
|
|
||||||
|
|
||||||
# Aggiungi il risultato modificato alla lista
|
|
||||||
download_list.append(f"Download {i}: {match}")
|
|
||||||
|
|
||||||
# Creare una stringa unica con tutti i risultati
|
|
||||||
cleaned_output = "\n".join(download_list)
|
|
||||||
else:
|
|
||||||
print("❌ Nessun download trovato")
|
|
||||||
|
|
||||||
# Invia l'output pulito
|
# Invia l'output pulito
|
||||||
print(f"📄 Output della screen {screen_id}:\n{cleaned_output}")
|
print(f"📄 Output della screen {screen_id}:\n{cleaned_output}")
|
||||||
@ -505,7 +612,16 @@ class TelegramBot:
|
|||||||
os.remove(temp_file)
|
os.remove(temp_file)
|
||||||
|
|
||||||
def send_message(self, message, choices):
|
def send_message(self, message, choices):
|
||||||
if choices is None:
|
|
||||||
|
formatted_message = message
|
||||||
|
if choices:
|
||||||
|
formatted_choices = "\n".join(choices)
|
||||||
|
formatted_message = f"{message}\n\n{formatted_choices}"
|
||||||
|
|
||||||
|
for chat_id in self.authorized_users:
|
||||||
|
self.bot.send_message(chat_id, formatted_message)
|
||||||
|
|
||||||
|
""" if choices is None:
|
||||||
if self.chat_id:
|
if self.chat_id:
|
||||||
print(f"{message}")
|
print(f"{message}")
|
||||||
self.bot.send_message(self.chat_id, message)
|
self.bot.send_message(self.chat_id, message)
|
||||||
@ -514,7 +630,7 @@ class TelegramBot:
|
|||||||
message = f"{message}\n\n{formatted_choices}"
|
message = f"{message}\n\n{formatted_choices}"
|
||||||
if self.chat_id:
|
if self.chat_id:
|
||||||
print(f"{message}")
|
print(f"{message}")
|
||||||
self.bot.send_message(self.chat_id, message)
|
self.bot.send_message(self.chat_id, message) """
|
||||||
|
|
||||||
def _send_long_message(self, chat_id, text, chunk_size=4096):
|
def _send_long_message(self, chat_id, text, chunk_size=4096):
|
||||||
"""Suddivide e invia un messaggio troppo lungo in più parti."""
|
"""Suddivide e invia un messaggio troppo lungo in più parti."""
|
||||||
@ -527,16 +643,20 @@ class TelegramBot:
|
|||||||
|
|
||||||
if choices is None:
|
if choices is None:
|
||||||
print(f"{prompt_message}")
|
print(f"{prompt_message}")
|
||||||
self.bot.send_message(
|
""" self.bot.send_message(
|
||||||
self.chat_id,
|
self.chat_id,
|
||||||
f"{prompt_message}",
|
f"{prompt_message}",
|
||||||
)
|
) """
|
||||||
|
for chat_id in self.authorized_users: # Manda a tutti gli ID autorizzati
|
||||||
|
self.bot.send_message(chat_id, f"{prompt_message}")
|
||||||
else:
|
else:
|
||||||
print(f"{prompt_message}\n\nOpzioni: {', '.join(choices)}")
|
print(f"{prompt_message}\n\nOpzioni: {', '.join(choices)}")
|
||||||
self.bot.send_message(
|
""" self.bot.send_message(
|
||||||
self.chat_id,
|
self.chat_id,
|
||||||
f"{prompt_message}\n\nOpzioni: {', '.join(choices)}",
|
f"{prompt_message}\n\nOpzioni: {', '.join(choices)}",
|
||||||
)
|
) """
|
||||||
|
for chat_id in self.authorized_users: # Manda a tutti gli ID autorizzati
|
||||||
|
self.bot.send_message(chat_id, f"{prompt_message}\n\nOpzioni: {', '.join(choices)}")
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
@ -546,7 +666,8 @@ class TelegramBot:
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
print(f"⚠️ Timeout: nessuna risposta ricevuta.")
|
print(f"⚠️ Timeout: nessuna risposta ricevuta.")
|
||||||
self.bot.send_message(self.chat_id, "⚠️ Timeout: nessuna risposta ricevuta.")
|
for chat_id in self.authorized_users: # Manda a tutti gli ID autorizzati
|
||||||
|
self.bot.send_message(chat_id, "⚠️ Timeout: nessuna risposta ricevuta.")
|
||||||
self.request_manager.clear_file()
|
self.request_manager.clear_file()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -558,4 +679,37 @@ class TelegramBot:
|
|||||||
|
|
||||||
|
|
||||||
def get_bot_instance():
|
def get_bot_instance():
|
||||||
return TelegramBot.get_instance()
|
return TelegramBot.get_instance()
|
||||||
|
|
||||||
|
# Esempio di utilizzo
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
# Usa le variabili
|
||||||
|
token = os.getenv("TOKEN_TELEGRAM")
|
||||||
|
authorized_users = os.getenv("AUTHORIZED_USER_ID")
|
||||||
|
|
||||||
|
# Controlla se le variabili sono presenti
|
||||||
|
if not token:
|
||||||
|
print("Errore: TOKEN_TELEGRAM non è definito nel file .env.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not authorized_users:
|
||||||
|
print("Errore: AUTHORIZED_USER_ID non è definito nel file .env.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
TOKEN = token # Inserisci il token del tuo bot Telegram sul file .env
|
||||||
|
AUTHORIZED_USER_ID = list(map(int, authorized_users.split(","))) # Inserisci il tuo ID utente Telegram sul file .env
|
||||||
|
except ValueError as e:
|
||||||
|
print(f"Errore nella conversione degli ID autorizzati: {e}. Controlla il file .env e assicurati che gli ID siano numeri interi separati da virgole.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Inizializza il bot
|
||||||
|
bot = TelegramBot.init_bot(TOKEN, AUTHORIZED_USER_ID)
|
||||||
|
bot.run()
|
||||||
|
|
||||||
|
"""
|
||||||
|
start - Avvia lo script
|
||||||
|
list - Lista script attivi
|
||||||
|
get - Mostra ID utente Telegram
|
||||||
|
"""
|
||||||
|
@ -4,17 +4,18 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
from typing import Any, List
|
from typing import Any, List
|
||||||
|
|
||||||
|
|
||||||
class ConfigManager:
|
class ConfigManager:
|
||||||
def __init__(self, file_path: str = 'config.json') -> None:
|
def __init__(self, file_name: str = 'config.json') -> None:
|
||||||
"""Initialize the ConfigManager.
|
"""Initialize the ConfigManager.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- file_path (str, optional): The path to the configuration file. Default is 'config.json'.
|
- file_path (str, optional): The path to the configuration file. Default is 'config.json'.
|
||||||
"""
|
"""
|
||||||
self.file_path = file_path
|
self.file_path = Path(__file__).parent.parent.parent / file_name
|
||||||
self.config = {}
|
self.config = {}
|
||||||
self.cache = {}
|
self.cache = {}
|
||||||
|
|
||||||
@ -50,17 +51,17 @@ class ConfigManager:
|
|||||||
def download_requirements(self, url: str, filename: str):
|
def download_requirements(self, url: str, filename: str):
|
||||||
"""
|
"""
|
||||||
Download the requirements.txt file from the specified URL if not found locally using requests.
|
Download the requirements.txt file from the specified URL if not found locally using requests.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
url (str): The URL to download the requirements file from.
|
url (str): The URL to download the requirements file from.
|
||||||
filename (str): The local filename to save the requirements file as.
|
filename (str): The local filename to save the requirements file as.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
logging.info(f"{filename} not found locally. Downloading from {url}...")
|
logging.info(f"{filename} not found locally. Downloading from {url}...")
|
||||||
response = requests.get(url)
|
response = requests.get(url)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
with open(filename, 'wb') as f:
|
with open(filename, 'wb') as f:
|
||||||
f.write(response.content)
|
f.write(response.content)
|
||||||
@ -68,7 +69,7 @@ class ConfigManager:
|
|||||||
else:
|
else:
|
||||||
logging.error(f"Failed to download {filename}. HTTP Status code: {response.status_code}")
|
logging.error(f"Failed to download {filename}. HTTP Status code: {response.status_code}")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Failed to download {filename}: {e}")
|
logging.error(f"Failed to download {filename}: {e}")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
@ -89,15 +90,15 @@ class ConfigManager:
|
|||||||
|
|
||||||
if cache_key in self.cache:
|
if cache_key in self.cache:
|
||||||
return self.cache[cache_key]
|
return self.cache[cache_key]
|
||||||
|
|
||||||
if section in self.config and key in self.config[section]:
|
if section in self.config and key in self.config[section]:
|
||||||
value = self.config[section][key]
|
value = self.config[section][key]
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Key '{key}' not found in section '{section}'")
|
raise ValueError(f"Key '{key}' not found in section '{section}'")
|
||||||
|
|
||||||
value = self._convert_to_data_type(value, data_type)
|
value = self._convert_to_data_type(value, data_type)
|
||||||
self.cache[cache_key] = value
|
self.cache[cache_key] = value
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _convert_to_data_type(self, value: str, data_type: type) -> Any:
|
def _convert_to_data_type(self, value: str, data_type: type) -> Any:
|
||||||
@ -120,7 +121,7 @@ class ConfigManager:
|
|||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def get(self, section: str, key: str) -> Any:
|
def get(self, section: str, key: str) -> Any:
|
||||||
"""Read a value from the configuration file.
|
"""Read a value from the configuration file.
|
||||||
|
|
||||||
@ -144,7 +145,7 @@ class ConfigManager:
|
|||||||
int: The integer value.
|
int: The integer value.
|
||||||
"""
|
"""
|
||||||
return self.read_key(section, key, int)
|
return self.read_key(section, key, int)
|
||||||
|
|
||||||
def get_float(self, section: str, key: str) -> int:
|
def get_float(self, section: str, key: str) -> int:
|
||||||
"""Read an float value from the configuration file.
|
"""Read an float value from the configuration file.
|
||||||
|
|
||||||
@ -180,7 +181,7 @@ class ConfigManager:
|
|||||||
list: The list value.
|
list: The list value.
|
||||||
"""
|
"""
|
||||||
return self.read_key(section, key, list)
|
return self.read_key(section, key, list)
|
||||||
|
|
||||||
def get_dict(self, section: str, key: str) -> dict:
|
def get_dict(self, section: str, key: str) -> dict:
|
||||||
"""Read a dictionary value from the configuration file.
|
"""Read a dictionary value from the configuration file.
|
||||||
|
|
||||||
@ -220,7 +221,7 @@ class ConfigManager:
|
|||||||
json.dump(self.config, f, indent=4)
|
json.dump(self.config, f, indent=4)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error writing configuration file: {e}")
|
print(f"Error writing configuration file: {e}")
|
||||||
|
|
||||||
|
|
||||||
# Initialize
|
# Initialize
|
||||||
config_manager = ConfigManager()
|
config_manager = ConfigManager()
|
||||||
|
@ -13,6 +13,7 @@ import subprocess
|
|||||||
import contextlib
|
import contextlib
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import importlib.metadata
|
import importlib.metadata
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
# External library
|
# External library
|
||||||
@ -67,7 +68,7 @@ class OsManager:
|
|||||||
|
|
||||||
# Convert Windows separators to Unix
|
# Convert Windows separators to Unix
|
||||||
normalized = path.replace('\\', '/')
|
normalized = path.replace('\\', '/')
|
||||||
|
|
||||||
# Ensure absolute paths start with /
|
# Ensure absolute paths start with /
|
||||||
if normalized.startswith('/'):
|
if normalized.startswith('/'):
|
||||||
return os.path.normpath(normalized)
|
return os.path.normpath(normalized)
|
||||||
@ -82,17 +83,17 @@ class OsManager:
|
|||||||
# Decode and sanitize
|
# Decode and sanitize
|
||||||
decoded = unidecode(filename)
|
decoded = unidecode(filename)
|
||||||
sanitized = sanitize_filename(decoded)
|
sanitized = sanitize_filename(decoded)
|
||||||
|
|
||||||
# Split name and extension
|
# Split name and extension
|
||||||
name, ext = os.path.splitext(sanitized)
|
name, ext = os.path.splitext(sanitized)
|
||||||
|
|
||||||
# Calculate available length for name considering the '...' and extension
|
# Calculate available length for name considering the '...' and extension
|
||||||
max_name_length = self.max_length - len('...') - len(ext)
|
max_name_length = self.max_length - len('...') - len(ext)
|
||||||
|
|
||||||
# Truncate name if it exceeds the max name length
|
# Truncate name if it exceeds the max name length
|
||||||
if len(name) > max_name_length:
|
if len(name) > max_name_length:
|
||||||
name = name[:max_name_length] + '...'
|
name = name[:max_name_length] + '...'
|
||||||
|
|
||||||
# Ensure the final file name includes the extension
|
# Ensure the final file name includes the extension
|
||||||
return name + ext
|
return name + ext
|
||||||
|
|
||||||
@ -103,7 +104,7 @@ class OsManager:
|
|||||||
|
|
||||||
# Decode unicode characters
|
# Decode unicode characters
|
||||||
decoded = unidecode(path)
|
decoded = unidecode(path)
|
||||||
|
|
||||||
# Basic path sanitization
|
# Basic path sanitization
|
||||||
sanitized = sanitize_filepath(decoded)
|
sanitized = sanitize_filepath(decoded)
|
||||||
|
|
||||||
@ -121,7 +122,7 @@ class OsManager:
|
|||||||
if part
|
if part
|
||||||
])
|
])
|
||||||
return '\\'.join(sanitized_parts)
|
return '\\'.join(sanitized_parts)
|
||||||
|
|
||||||
# Handle drive letters
|
# Handle drive letters
|
||||||
elif len(path) >= 2 and path[1] == ':':
|
elif len(path) >= 2 and path[1] == ':':
|
||||||
drive = path[:2]
|
drive = path[:2]
|
||||||
@ -132,7 +133,7 @@ class OsManager:
|
|||||||
if part
|
if part
|
||||||
]
|
]
|
||||||
return '\\'.join(path_parts)
|
return '\\'.join(path_parts)
|
||||||
|
|
||||||
# Regular path
|
# Regular path
|
||||||
else:
|
else:
|
||||||
parts = path.replace('/', '\\').split('\\')
|
parts = path.replace('/', '\\').split('\\')
|
||||||
@ -146,21 +147,21 @@ class OsManager:
|
|||||||
for part in parts
|
for part in parts
|
||||||
if part
|
if part
|
||||||
]
|
]
|
||||||
|
|
||||||
result = '/'.join(sanitized_parts)
|
result = '/'.join(sanitized_parts)
|
||||||
if is_absolute:
|
if is_absolute:
|
||||||
result = '/' + result
|
result = '/' + result
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def create_path(self, path: str, mode: int = 0o755) -> bool:
|
def create_path(self, path: str, mode: int = 0o755) -> bool:
|
||||||
"""
|
"""
|
||||||
Create directory path with specified permissions.
|
Create directory path with specified permissions.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path (str): Path to create.
|
path (str): Path to create.
|
||||||
mode (int, optional): Directory permissions. Defaults to 0o755.
|
mode (int, optional): Directory permissions. Defaults to 0o755.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if path created successfully, False otherwise.
|
bool: True if path created successfully, False otherwise.
|
||||||
"""
|
"""
|
||||||
@ -168,7 +169,7 @@ class OsManager:
|
|||||||
sanitized_path = self.get_sanitize_path(path)
|
sanitized_path = self.get_sanitize_path(path)
|
||||||
os.makedirs(sanitized_path, mode=mode, exist_ok=True)
|
os.makedirs(sanitized_path, mode=mode, exist_ok=True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Path creation error: {e}")
|
logging.error(f"Path creation error: {e}")
|
||||||
return False
|
return False
|
||||||
@ -176,21 +177,21 @@ class OsManager:
|
|||||||
def remove_folder(self, folder_path: str) -> bool:
|
def remove_folder(self, folder_path: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Safely remove a folder.
|
Safely remove a folder.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
folder_path (str): Path of directory to remove.
|
folder_path (str): Path of directory to remove.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: Removal status.
|
bool: Removal status.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(folder_path)
|
shutil.rmtree(folder_path)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
logging.error(f"Folder removal error: {e}")
|
logging.error(f"Folder removal error: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def remove_files_except_one(self, folder_path: str, keep_file: str) -> None:
|
def remove_files_except_one(self, folder_path: str, keep_file: str) -> None:
|
||||||
"""
|
"""
|
||||||
Delete all files in a folder except for one specified file.
|
Delete all files in a folder except for one specified file.
|
||||||
@ -203,11 +204,11 @@ class OsManager:
|
|||||||
try:
|
try:
|
||||||
# List all files in the folder
|
# List all files in the folder
|
||||||
files_in_folder = os.listdir(folder_path)
|
files_in_folder = os.listdir(folder_path)
|
||||||
|
|
||||||
# Iterate over each file in the folder
|
# Iterate over each file in the folder
|
||||||
for file_name in files_in_folder:
|
for file_name in files_in_folder:
|
||||||
file_path = os.path.join(folder_path, file_name)
|
file_path = os.path.join(folder_path, file_name)
|
||||||
|
|
||||||
# Check if the file is not the one to keep and is a regular file
|
# Check if the file is not the one to keep and is a regular file
|
||||||
if file_name != keep_file and os.path.isfile(file_path):
|
if file_name != keep_file and os.path.isfile(file_path):
|
||||||
os.remove(file_path) # Delete the file
|
os.remove(file_path) # Delete the file
|
||||||
@ -215,7 +216,7 @@ class OsManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"An error occurred: {e}")
|
logging.error(f"An error occurred: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def check_file(self, file_path: str) -> bool:
|
def check_file(self, file_path: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if a file exists at the given file path.
|
Check if a file exists at the given file path.
|
||||||
@ -229,7 +230,7 @@ class OsManager:
|
|||||||
try:
|
try:
|
||||||
logging.info(f"Check if file exists: {file_path}")
|
logging.info(f"Check if file exists: {file_path}")
|
||||||
return os.path.exists(file_path)
|
return os.path.exists(file_path)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"An error occurred while checking file existence: {e}")
|
logging.error(f"An error occurred while checking file existence: {e}")
|
||||||
return False
|
return False
|
||||||
@ -299,7 +300,7 @@ class OsSummary:
|
|||||||
"""Get the binary directory based on OS."""
|
"""Get the binary directory based on OS."""
|
||||||
system = platform.system().lower()
|
system = platform.system().lower()
|
||||||
home = os.path.expanduser('~')
|
home = os.path.expanduser('~')
|
||||||
|
|
||||||
if system == 'windows':
|
if system == 'windows':
|
||||||
return os.path.join(os.path.splitdrive(home)[0] + os.path.sep, 'binary')
|
return os.path.join(os.path.splitdrive(home)[0] + os.path.sep, 'binary')
|
||||||
elif system == 'darwin':
|
elif system == 'darwin':
|
||||||
@ -315,41 +316,41 @@ class OsSummary:
|
|||||||
try:
|
try:
|
||||||
result = subprocess.check_output(command, text=True).strip()
|
result = subprocess.check_output(command, text=True).strip()
|
||||||
return result.split('\n')[0] if result else None
|
return result.split('\n')[0] if result else None
|
||||||
|
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_library_version(self, lib_name: str):
|
def get_library_version(self, lib_name: str):
|
||||||
"""
|
"""
|
||||||
Retrieve the version of a Python library.
|
Retrieve the version of a Python library.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
lib_name (str): The name of the Python library.
|
lib_name (str): The name of the Python library.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: The library name followed by its version, or `-not installed` if not found.
|
str: The library name followed by its version, or `-not installed` if not found.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
version = importlib.metadata.version(lib_name)
|
version = importlib.metadata.version(lib_name)
|
||||||
return f"{lib_name}-{version}"
|
return f"{lib_name}-{version}"
|
||||||
|
|
||||||
except importlib.metadata.PackageNotFoundError:
|
except importlib.metadata.PackageNotFoundError:
|
||||||
return f"{lib_name}-not installed"
|
return f"{lib_name}-not installed"
|
||||||
|
|
||||||
def download_requirements(self, url: str, filename: str):
|
def download_requirements(self, url: str, filename: str):
|
||||||
"""
|
"""
|
||||||
Download the requirements.txt file from the specified URL if not found locally using requests.
|
Download the requirements.txt file from the specified URL if not found locally using requests.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
url (str): The URL to download the requirements file from.
|
url (str): The URL to download the requirements file from.
|
||||||
filename (str): The local filename to save the requirements file as.
|
filename (str): The local filename to save the requirements file as.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
logging.info(f"{filename} not found locally. Downloading from {url}...")
|
logging.info(f"{filename} not found locally. Downloading from {url}...")
|
||||||
response = requests.get(url)
|
response = requests.get(url)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
with open(filename, 'wb') as f:
|
with open(filename, 'wb') as f:
|
||||||
f.write(response.content)
|
f.write(response.content)
|
||||||
@ -357,7 +358,7 @@ class OsSummary:
|
|||||||
else:
|
else:
|
||||||
logging.error(f"Failed to download {filename}. HTTP Status code: {response.status_code}")
|
logging.error(f"Failed to download {filename}. HTTP Status code: {response.status_code}")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Failed to download {filename}: {e}")
|
logging.error(f"Failed to download {filename}: {e}")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
@ -373,7 +374,7 @@ class OsSummary:
|
|||||||
console.print(f"Installing {lib_name}...", style="bold yellow")
|
console.print(f"Installing {lib_name}...", style="bold yellow")
|
||||||
subprocess.check_call([sys.executable, "-m", "pip", "install", lib_name])
|
subprocess.check_call([sys.executable, "-m", "pip", "install", lib_name])
|
||||||
console.print(f"{lib_name} installed successfully!", style="bold green")
|
console.print(f"{lib_name} installed successfully!", style="bold green")
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
console.print(f"Failed to install {lib_name}: {e}", style="bold red")
|
console.print(f"Failed to install {lib_name}: {e}", style="bold red")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -400,7 +401,7 @@ class OsSummary:
|
|||||||
arch = platform.machine()
|
arch = platform.machine()
|
||||||
os_info = platform.platform()
|
os_info = platform.platform()
|
||||||
glibc_version = 'glibc ' + '.'.join(map(str, platform.libc_ver()[1]))
|
glibc_version = 'glibc ' + '.'.join(map(str, platform.libc_ver()[1]))
|
||||||
|
|
||||||
console.print(f"[cyan]Python[white]: [bold red]{python_version} ({python_implementation} {arch}) - {os_info} ({glibc_version})[/bold red]")
|
console.print(f"[cyan]Python[white]: [bold red]{python_version} ({python_implementation} {arch}) - {os_info} ({glibc_version})[/bold red]")
|
||||||
logging.info(f"Python: {python_version} ({python_implementation} {arch}) - {os_info} ({glibc_version})")
|
logging.info(f"Python: {python_version} ({python_implementation} {arch}) - {os_info} ({glibc_version})")
|
||||||
|
|
||||||
@ -408,10 +409,10 @@ class OsSummary:
|
|||||||
binary_dir = self.get_binary_directory()
|
binary_dir = self.get_binary_directory()
|
||||||
system = platform.system().lower()
|
system = platform.system().lower()
|
||||||
arch = platform.machine().lower()
|
arch = platform.machine().lower()
|
||||||
|
|
||||||
# Map architecture names
|
# Map architecture names
|
||||||
arch_map = {
|
arch_map = {
|
||||||
'amd64': 'x64',
|
'amd64': 'x64',
|
||||||
'x86_64': 'x64',
|
'x86_64': 'x64',
|
||||||
'x64': 'x64',
|
'x64': 'x64',
|
||||||
'arm64': 'arm64',
|
'arm64': 'arm64',
|
||||||
@ -424,15 +425,15 @@ class OsSummary:
|
|||||||
|
|
||||||
# Check binary directory
|
# Check binary directory
|
||||||
if os.path.exists(binary_dir):
|
if os.path.exists(binary_dir):
|
||||||
|
|
||||||
# Search for any file containing 'ffmpeg' and the architecture
|
# Search for any file containing 'ffmpeg' and the architecture
|
||||||
ffmpeg_files = glob.glob(os.path.join(binary_dir, f'*ffmpeg*{arch}*'))
|
ffmpeg_files = glob.glob(os.path.join(binary_dir, f'*ffmpeg*{arch}*'))
|
||||||
ffprobe_files = glob.glob(os.path.join(binary_dir, f'*ffprobe*{arch}*'))
|
ffprobe_files = glob.glob(os.path.join(binary_dir, f'*ffprobe*{arch}*'))
|
||||||
|
|
||||||
if ffmpeg_files and ffprobe_files:
|
if ffmpeg_files and ffprobe_files:
|
||||||
self.ffmpeg_path = ffmpeg_files[0]
|
self.ffmpeg_path = ffmpeg_files[0]
|
||||||
self.ffprobe_path = ffprobe_files[0]
|
self.ffprobe_path = ffprobe_files[0]
|
||||||
|
|
||||||
# Set executable permissions if needed
|
# Set executable permissions if needed
|
||||||
if system != 'windows':
|
if system != 'windows':
|
||||||
os.chmod(self.ffmpeg_path, 0o755)
|
os.chmod(self.ffmpeg_path, 0o755)
|
||||||
@ -451,15 +452,17 @@ class OsSummary:
|
|||||||
# Handle requirements.txt
|
# Handle requirements.txt
|
||||||
if not getattr(sys, 'frozen', False):
|
if not getattr(sys, 'frozen', False):
|
||||||
requirements_file = 'requirements.txt'
|
requirements_file = 'requirements.txt'
|
||||||
|
|
||||||
|
requirements_file = Path(__file__).parent.parent.parent / requirements_file
|
||||||
|
|
||||||
if not os.path.exists(requirements_file):
|
if not os.path.exists(requirements_file):
|
||||||
self.download_requirements(
|
self.download_requirements(
|
||||||
'https://raw.githubusercontent.com/Arrowar/StreamingCommunity/refs/heads/main/requirements.txt',
|
'https://raw.githubusercontent.com/Arrowar/StreamingCommunity/refs/heads/main/requirements.txt',
|
||||||
requirements_file
|
requirements_file
|
||||||
)
|
)
|
||||||
|
|
||||||
optional_libraries = [line.strip().split("=")[0] for line in open(requirements_file, 'r', encoding='utf-8-sig')]
|
optional_libraries = [line.strip().split("=")[0] for line in open(requirements_file, 'r', encoding='utf-8-sig')]
|
||||||
|
|
||||||
for lib in optional_libraries:
|
for lib in optional_libraries:
|
||||||
installed_version = self.get_library_version(lib.split("<")[0])
|
installed_version = self.get_library_version(lib.split("<")[0])
|
||||||
if 'not installed' in installed_version:
|
if 'not installed' in installed_version:
|
||||||
@ -468,7 +471,7 @@ class OsSummary:
|
|||||||
self.install_library(lib)
|
self.install_library(lib)
|
||||||
else:
|
else:
|
||||||
logging.info(f"Library: {installed_version}")
|
logging.info(f"Library: {installed_version}")
|
||||||
|
|
||||||
#console.print(f"[cyan]Libraries[white]: [bold red]{', '.join([self.get_library_version(lib) for lib in optional_libraries])}[/bold red]\n")
|
#console.print(f"[cyan]Libraries[white]: [bold red]{', '.join([self.get_library_version(lib) for lib in optional_libraries])}[/bold red]\n")
|
||||||
logging.info(f"Libraries: {', '.join([self.get_library_version(lib) for lib in optional_libraries])}")
|
logging.info(f"Libraries: {', '.join([self.get_library_version(lib) for lib in optional_libraries])}")
|
||||||
|
|
||||||
@ -495,6 +498,6 @@ def compute_sha1_hash(input_string: str) -> str:
|
|||||||
"""
|
"""
|
||||||
# Compute the SHA-1 hash
|
# Compute the SHA-1 hash
|
||||||
hashed_string = hashlib.sha1(input_string.encode()).hexdigest()
|
hashed_string = hashlib.sha1(input_string.encode()).hexdigest()
|
||||||
|
|
||||||
# Return the hashed string
|
# Return the hashed string
|
||||||
return hashed_string
|
return hashed_string
|
||||||
|
@ -22,8 +22,7 @@ from StreamingCommunity.Util.logger import Logger
|
|||||||
|
|
||||||
|
|
||||||
# Telegram util
|
# Telegram util
|
||||||
from StreamingCommunity.TelegramHelp.session import get_session, deleteScriptId
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, TelegramSession
|
||||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
|
||||||
|
|
||||||
|
|
||||||
# Config
|
# Config
|
||||||
@ -62,7 +61,7 @@ def load_search_functions():
|
|||||||
|
|
||||||
api_dir = os.path.join(base_path, 'Api', 'Site')
|
api_dir = os.path.join(base_path, 'Api', 'Site')
|
||||||
init_files = glob.glob(os.path.join(api_dir, '*', '__init__.py'))
|
init_files = glob.glob(os.path.join(api_dir, '*', '__init__.py'))
|
||||||
|
|
||||||
# Retrieve modules and their indices
|
# Retrieve modules and their indices
|
||||||
for init_file in init_files:
|
for init_file in init_files:
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ def load_search_functions():
|
|||||||
# Se il modulo è nella lista da escludere, saltalo
|
# Se il modulo è nella lista da escludere, saltalo
|
||||||
if module_name in excluded_sites:
|
if module_name in excluded_sites:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
logging.info(f"Load module name: {module_name}")
|
logging.info(f"Load module name: {module_name}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -176,7 +175,7 @@ def force_exit():
|
|||||||
|
|
||||||
print("🚨 Uscita forzata con os._exit(0)")
|
print("🚨 Uscita forzata con os._exit(0)")
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
|
||||||
|
|
||||||
def main(script_id = 0):
|
def main(script_id = 0):
|
||||||
|
|
||||||
@ -332,7 +331,7 @@ def main(script_id = 0):
|
|||||||
if category in input_to_function:
|
if category in input_to_function:
|
||||||
run_function(input_to_function[category])
|
run_function(input_to_function[category])
|
||||||
else:
|
else:
|
||||||
|
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
bot.send_message(f"Categoria non valida", None)
|
bot.send_message(f"Categoria non valida", None)
|
||||||
|
|
||||||
@ -347,6 +346,6 @@ def main(script_id = 0):
|
|||||||
bot.send_message(f"Chiusura in corso", None)
|
bot.send_message(f"Chiusura in corso", None)
|
||||||
|
|
||||||
# Delete script_id
|
# Delete script_id
|
||||||
script_id = get_session()
|
script_id = TelegramSession.get_session()
|
||||||
if script_id != "unknown":
|
if script_id != "unknown":
|
||||||
deleteScriptId(script_id)
|
TelegramSession.deleteScriptId(script_id)
|
||||||
|
@ -3,19 +3,17 @@
|
|||||||
import sys
|
import sys
|
||||||
from StreamingCommunity.run import main
|
from StreamingCommunity.run import main
|
||||||
from StreamingCommunity.Util._jsonConfig import config_manager
|
from StreamingCommunity.Util._jsonConfig import config_manager
|
||||||
from StreamingCommunity.TelegramHelp.request_manager import RequestManager
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramRequestManager, TelegramSession
|
||||||
from StreamingCommunity.TelegramHelp.session import set_session
|
|
||||||
|
|
||||||
# Svuoto il file
|
# Svuoto il file
|
||||||
TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
|
TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
|
||||||
|
|
||||||
if TELEGRAM_BOT:
|
if TELEGRAM_BOT:
|
||||||
request_manager = RequestManager()
|
request_manager = TelegramRequestManager()
|
||||||
request_manager.clear_file()
|
request_manager.clear_file()
|
||||||
script_id = sys.argv[1] if len(sys.argv) > 1 else "unknown"
|
script_id = sys.argv[1] if len(sys.argv) > 1 else "unknown"
|
||||||
|
|
||||||
set_session(script_id)
|
TelegramSession.set_session(script_id)
|
||||||
main(script_id)
|
main(script_id)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
main()
|
main()
|
Loading…
x
Reference in New Issue
Block a user