mirror of
https://github.com/tgbot-collection/ytdlbot.git
synced 2024-09-20 15:05:56 +08:00
support instagram
This commit is contained in:
parent
07cbf8f0fb
commit
b101ff2b92
45
README.md
45
README.md
|
@ -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
BIN
assets/instagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 MiB |
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue