support instagram

This commit is contained in:
Benny 2023-04-16 14:27:24 +02:00
parent 07cbf8f0fb
commit b101ff2b92
No known key found for this signature in database
GPG key ID: 6CD0DBDA5235D481
5 changed files with 109 additions and 47 deletions

View file

@ -4,41 +4,42 @@
YouTube Download Bot🚀
This Telegram bot allows you to download videos from YouTube and other supported platforms.
This Telegram bot allows you to download videos from YouTube and other supported platforms, including Instagram!
-----
**READ [FAQ](FAQ.md) FIRST IF YOU ENCOUNTER ANY ISSUES.**
-----
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
<details> <summary>Deploy to heroku</summary>
<a href="https://heroku.com/deploy"><img src="https://www.herokucdn.com/deploy/button.svg" alt="Deploy to Heroku"></a>
If you are having trouble deploying, you can fork the project to your personal account and deploy it from there.
**Starting November 28, 2022, free Heroku Dynos, free Heroku Postgres, and free Heroku Data for Redis® plans will no
longer be available.**
[Heroku Announcement](https://devcenter.heroku.com/articles/free-dyno-hours)
</details>
# Usage
[https://t.me/benny_ytdlbot](https://t.me/benny_ytdlbot)
Send link directly to the bot. Any
Websites [supported by youtube-dl](https://ytdl-org.github.io/youtube-dl/supportedsites.html) will also work.
Websites [supported by youtube-dl](https://ytdl-org.github.io/youtube-dl/supportedsites.html) will work to.
# Limitations of my bot
Due to limitations on servers and bandwidth, there are some restrictions on this service.
Due to limitations on servers and bandwidth, there are some restrictions on this free service.
* Each user is limited to 5 free downloads per 24-hour period
* there is a maximum of three subscriptions allowed for YouTube channels.
If you require more downloads, you can purchase additional tokens. Additionally, you have the option of deploying your
own bot.
If you need more downloads, you can purchase additional tokens. Additionally, you have the option of deploying your
own bot. See below instructions.
# Features
![](assets/1.jpeg)
1. fast download and upload.
2. ads free
3. support progress bar
@ -50,6 +51,19 @@ own bot.
9. supports celery worker distribution - faster than before.
10. subscriptions to YouTube Channels
11. cache mechanism - download once for the same video.
12. support instagram posts
# Screenshots
## Normal download
![](assets/1.jpeg)
## Instagram download
![](assets/instagram.png)
## celery
![](assets/2.jpeg)
@ -57,6 +71,8 @@ own bot.
This bot can be deployed on any platform that supports Python.
Need help with deployment or exclusive features? I offer paid service - contact me at @BennyThink
## Run natively on your machine
To deploy this bot, follow these steps:
@ -162,16 +178,7 @@ Type "help", "copyright", "credits" or "license" for more information.
### 3.2.3 Setup instagram cookies
Required if you want to support instagram.
You can use this extension
[Get cookies.txt](https://chrome.google.com/webstore/detail/get-cookiestxt/bgaddhkoddajcdgocldbbfleckgcbcid)
to get instagram cookies
```shell
vim data/instagram.com_cookies.txt
# paste your cookies
```
You don't need to do this anymore! This bot support instagram posts out of the box, including photos, videos and reels.
## 3.3 Tidy docker-compose.yml
@ -265,6 +272,8 @@ https://dmesg.app/m3u8/prog_index.m3u8
https://twitter.com/nitori_sayaka/status/1526199729864200192
https://twitter.com/BennyThinks/status/1475836588542341124
## test instagram
# Donation
* [Buy me a coffee](https://www.buymeacoffee.com/bennythink)

BIN
assets/instagram.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View file

@ -33,6 +33,8 @@ To prevent abuse, each user is limited to 5 downloads per 24 hours.
3. You have the option to buy more tokens. Type /buy for more information.
4. The source code for this bot will always remain open and can be found here: https://github.com/tgbot-collection/ytdlbot
5. Need help with deployment or exclusive features? I offer paid service - contact me at @BennyThink
"""
about = "YouTube Downloader by @BennyThink.\n\nOpen source on GitHub: https://github.com/tgbot-collection/ytdlbot"

View file

@ -21,6 +21,7 @@ import fakeredis
import ffmpeg
import ffpb
import filetype
import requests
import yt_dlp as ytdl
from tqdm import tqdm
@ -153,7 +154,7 @@ def can_convert_mp4(video_path, uid):
return True
def ytdl_download(url, tempdir, bm, **kwargs) -> dict:
def ytdl_download(url, tempdir: "str", bm, **kwargs) -> dict:
payment = Payment()
chat_id = bm.chat.id
hijack = kwargs.get("hijack")
@ -180,7 +181,8 @@ def ytdl_download(url, tempdir, bm, **kwargs) -> dict:
None,
]
adjust_formats(chat_id, url, formats, hijack)
add_instagram_cookies(url, ydl_opts)
if download_instagram(url, tempdir):
return {"status": True, "error": "", "filepath": list(pathlib.Path(tempdir).glob("*"))}
address = ["::", "0.0.0.0"] if IPv6 else [None]
for format_ in formats:
@ -252,9 +254,20 @@ def convert_audio_format(resp: "dict", bm):
resp["filepath"][index] = new_path
def add_instagram_cookies(url: "str", opt: "dict"):
def download_instagram(url: "str", tempdir: "str"):
if url.startswith("https://www.instagram.com"):
opt["cookiefile"] = pathlib.Path(__file__).parent.joinpath("instagram.com_cookies.txt").as_posix()
api = f"https://ssmstore.store/rami/index.php?url={url}"
res = requests.get(api).json()
if isinstance(res, dict):
downloadable = {i["url"]: i["ext"] for i in res["url"]}
else:
downloadable = {i["url"]: i["ext"] for item in res for i in item["url"]}
for link, ext in downloadable.items():
save_path = pathlib.Path(tempdir, f"{id(link)}.{ext}")
with open(save_path, "wb") as f:
f.write(requests.get(link, stream=True).content)
return True
def split_large_video(response: "dict"):
@ -270,3 +283,8 @@ def split_large_video(response: "dict"):
if split and original_video:
response["filepath"] = [i.as_posix() for i in pathlib.Path(original_video).parent.glob("*")]
if __name__ == "__main__":
a = download_instagram("https://www.instagram.com/p/CrEAz-AI99Y/", "tmp")
print(a)

View file

@ -22,6 +22,7 @@ import typing
from hashlib import md5
from urllib.parse import quote_plus
import filetype
import psutil
import pyrogram.errors
import requests
@ -42,7 +43,6 @@ from config import (
ENABLE_VIP,
OWNER,
RATE_LIMIT,
TG_MAX_SIZE,
WORKERS,
)
from constant import BotText
@ -127,7 +127,7 @@ def forward_video(client, bot_msg, url):
try:
res_msg: "Message" = upload_processor(client, bot_msg, url, cached_fid)
obj = res_msg.document or res_msg.video or res_msg.audio or res_msg.animation
obj = res_msg.document or res_msg.video or res_msg.audio or res_msg.animation or res_msg.photo
caption, _ = gen_cap(bot_msg, url, obj)
res_msg.edit_text(caption, reply_markup=gen_video_markup())
@ -265,27 +265,19 @@ def ytdl_normal_download(bot_msg, client, url):
logging.info("Download complete.")
if result["status"]:
client.send_chat_action(chat_id, "upload_document")
video_paths = result["filepath"]
video_paths: "list" = result["filepath"]
bot_msg.edit_text("Download complete. Sending now...")
for video_path in video_paths:
# normally there's only one video in that path...
st_size = os.stat(video_path).st_size
if st_size > TG_MAX_SIZE:
bot_msg.edit_text(f"Your video({sizeof_fmt(st_size)}) is too large for Telegram.")
# client.send_chat_action(chat_id, 'upload_document')
# client.send_message(chat_id, upload_transfer_sh(bot_msg, video_paths))
continue
try:
upload_processor(client, bot_msg, url, video_path)
except pyrogram.errors.Flood as e:
logging.critical("FloodWait from Telegram: %s", e)
client.send_message(
chat_id,
f"I'm being rate limited by Telegram. Your video will come after {e.x} seconds. Please wait patiently.",
)
flood_owner_message(client, e)
time.sleep(e.x)
upload_processor(client, bot_msg, url, video_path)
try:
upload_processor(client, bot_msg, url, video_paths)
except pyrogram.errors.Flood as e:
logging.critical("FloodWait from Telegram: %s", e)
client.send_message(
chat_id,
f"I'm being rate limited by Telegram. Your video will come after {e.x} seconds. Please wait patiently.",
)
flood_owner_message(client, e)
time.sleep(e.x)
upload_processor(client, bot_msg, url, video_paths)
bot_msg.edit_text("Download success!✅")
else:
@ -296,12 +288,43 @@ def ytdl_normal_download(bot_msg, client, url):
temp_dir.cleanup()
def upload_processor(client, bot_msg, url, vp_or_fid: "typing.Any[str, pathlib.Path]"):
def generate_input_media(file_paths: "list", cap: "str") -> list:
input_media = []
for path in file_paths:
mime = filetype.guess_mime(path)
if "video" in mime:
input_media.append(pyrogram.types.InputMediaVideo(media=path))
elif "image" in mime:
input_media.append(pyrogram.types.InputMediaPhoto(media=path))
elif "audio" in mime:
input_media.append(pyrogram.types.InputMediaAudio(media=path))
else:
input_media.append(pyrogram.types.InputMediaDocument(media=path))
input_media[0].caption = cap
return input_media
def upload_processor(client, bot_msg, url, vp_or_fid: "typing.Any[str, list]"):
# raise pyrogram.errors.exceptions.FloodWait(13)
# if is str, it's a file id; else it's a list of paths
payment = Payment()
chat_id = bot_msg.chat.id
markup = gen_video_markup()
cap, meta = gen_cap(bot_msg, url, vp_or_fid)
if isinstance(vp_or_fid, list) and len(vp_or_fid) > 1:
# just generate the first for simplicity, send as media group(2-20)
cap, meta = gen_cap(bot_msg, url, vp_or_fid[0])
res_msg = client.send_media_group(chat_id, generate_input_media(vp_or_fid, cap))
# TODO no cache for now
return res_msg[0]
elif isinstance(vp_or_fid, list) and len(vp_or_fid) == 1:
# normal download, just contains one file in video_paths
vp_or_fid = vp_or_fid[0]
cap, meta = gen_cap(bot_msg, url, vp_or_fid)
else:
# just a file id as string
cap, meta = gen_cap(bot_msg, url, vp_or_fid)
settings = payment.get_user_settings(str(chat_id))
if ARCHIVE_ID and isinstance(vp_or_fid, pathlib.Path):
chat_id = ARCHIVE_ID
@ -364,9 +387,19 @@ def upload_processor(client, bot_msg, url, vp_or_fid: "typing.Any[str, pathlib.P
reply_markup=markup,
**meta,
)
except FileNotFoundError:
# this is likely a photo
logging.info("Retry to send as photo")
res_msg = client.send_photo(
chat_id,
vp_or_fid,
caption=cap,
progress=upload_hook,
progress_args=(bot_msg,),
)
unique = get_unique_clink(url, bot_msg.chat.id)
obj = res_msg.document or res_msg.video or res_msg.audio or res_msg.animation
obj = res_msg.document or res_msg.video or res_msg.audio or res_msg.animation or res_msg.photo
redis.add_send_cache(unique, getattr(obj, "file_id", None))
redis.update_metrics("video_success")
if ARCHIVE_ID and isinstance(vp_or_fid, pathlib.Path):