ytdlbot/ytdl.py

220 lines
7.8 KiB
Python
Raw Normal View History

2021-05-03 11:26:47 +00:00
#!/usr/local/bin/python3
# coding: utf-8
2021-08-14 09:57:42 +00:00
# ytdlbot - new.py
# 8/14/21 14:37
2021-05-03 11:26:47 +00:00
#
__author__ = "Benny <benny.think@gmail.com>"
2021-07-11 15:01:32 +00:00
import logging
2021-05-03 11:26:47 +00:00
import os
import pathlib
2021-05-04 07:58:01 +00:00
import re
2021-07-11 15:01:32 +00:00
import tempfile
2021-08-14 09:57:42 +00:00
import typing
2021-05-09 12:12:58 +00:00
2021-08-24 14:34:52 +00:00
import ffmpeg
from apscheduler.schedulers.background import BackgroundScheduler
2021-08-14 09:57:42 +00:00
from pyrogram import Client, filters, types
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
2021-05-03 11:26:47 +00:00
from tgbot_ping import get_runtime
2021-08-29 02:02:11 +00:00
from config import APP_HASH, APP_ID, ENABLE_VIP, OWNER, TOKEN, WORKERS
2021-08-16 11:45:36 +00:00
from constant import BotText
from downloader import convert_flac, sizeof_fmt, upload_hook, ytdl_download
2021-08-29 02:02:11 +00:00
from limit import Redis, verify_payment
def customize_logger(logger: "list"):
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(filename)s [%(levelname)s]: %(message)s')
for log in logger:
logging.getLogger(log).setLevel(level=logging.WARNING)
def create_app(session="ytdl", workers=WORKERS):
_app = Client(session, APP_ID, APP_HASH,
bot_token=TOKEN, workers=workers)
return _app
customize_logger(["pyrogram.client", "pyrogram.session.session", "pyrogram.client", "pyrogram.connection.connection"])
app = create_app()
bot_text = BotText()
2021-08-24 14:34:52 +00:00
def get_metadata(video_path):
2021-08-25 14:13:25 +00:00
width, height, duration = 1280, 720, 0
2021-08-24 14:34:52 +00:00
try:
video_streams = ffmpeg.probe(video_path, select_streams="v")
for item in video_streams.get("streams", []):
height = item["height"]
width = item["width"]
duration = int(float(video_streams["format"]["duration"]))
except Exception as e:
logging.error(e)
return dict(height=height, width=width, duration=duration)
2021-08-14 09:57:42 +00:00
@app.on_message(filters.command(["start"]))
def start_handler(client: "Client", message: "types.Message"):
chat_id = message.chat.id
logging.info("Welcome to youtube-dl bot!")
client.send_chat_action(chat_id, "typing")
greeting = bot_text.get_vip_greeting(chat_id)
client.send_message(message.chat.id, greeting + bot_text.start + "\n\n" + bot_text.remaining_quota_caption(chat_id))
2021-05-04 03:30:22 +00:00
2021-05-04 07:58:01 +00:00
2021-08-14 09:57:42 +00:00
@app.on_message(filters.command(["help"]))
def help_handler(client: "Client", message: "types.Message"):
chat_id = message.chat.id
client.send_chat_action(chat_id, "typing")
2021-08-16 11:45:36 +00:00
client.send_message(chat_id, bot_text.help, disable_web_page_preview=True)
2021-05-04 07:58:01 +00:00
2021-08-14 09:57:42 +00:00
@app.on_message(filters.command(["ping"]))
def ping_handler(client: "Client", message: "types.Message"):
chat_id = message.chat.id
client.send_chat_action(chat_id, "typing")
2021-08-30 14:06:32 +00:00
if os.uname().sysname == "Darwin" or ".heroku" in os.getenv("PYTHONHOME", ""):
bot_info = "ping unavailable."
else:
bot_info = get_runtime("botsrunner_ytdl_1", "YouTube-dl")
2021-08-29 02:02:11 +00:00
if message.chat.username == OWNER:
client.send_document(chat_id, Redis().generate_file(), caption=bot_info)
else:
client.send_message(chat_id, f"{bot_info}")
2021-05-10 09:19:45 +00:00
2021-05-03 11:26:47 +00:00
2021-08-14 09:57:42 +00:00
@app.on_message(filters.command(["about"]))
def help_handler(client: "Client", message: "types.Message"):
chat_id = message.chat.id
client.send_chat_action(chat_id, "typing")
2021-08-16 11:45:36 +00:00
client.send_message(chat_id, bot_text.about)
@app.on_message(filters.command(["terms"]))
def terms_handler(client: "Client", message: "types.Message"):
chat_id = message.chat.id
client.send_chat_action(chat_id, "typing")
client.send_message(chat_id, bot_text.terms)
@app.on_message(filters.command(["vip"]))
def vip_handler(client: "Client", message: "types.Message"):
chat_id = message.chat.id
text = message.text.strip()
client.send_chat_action(chat_id, "typing")
if text == "/vip":
client.send_message(chat_id, bot_text.vip, disable_web_page_preview=True)
else:
bm: typing.Union["types.Message", "typing.Any"] = message.reply_text(bot_text.vip_pay, quote=True)
unique = text.replace("/vip", "").strip()
msg = verify_payment(chat_id, unique)
bm.edit_text(msg)
2021-05-03 11:26:47 +00:00
2021-05-13 11:14:01 +00:00
2021-08-26 12:16:16 +00:00
@app.on_message(filters.incoming)
2021-08-14 09:57:42 +00:00
def download_handler(client: "Client", message: "types.Message"):
2021-08-16 01:00:27 +00:00
# check remaining quota
chat_id = message.chat.id
Redis().user_count(chat_id)
2021-08-25 14:13:25 +00:00
2021-08-15 07:14:41 +00:00
if message.chat.type != "private" and not message.text.lower().startswith("/ytdl"):
logging.warning("%s, it's annoying me...🙄️ ", message.text)
return
2021-08-14 09:57:42 +00:00
url = re.sub(r'/ytdl\s*', '', message.text)
logging.info("start %s", url)
2021-05-13 11:14:01 +00:00
2021-08-14 09:57:42 +00:00
if not re.findall(r"^https?://", url.lower()):
Redis().update_metrics("bad_request")
2021-08-14 09:57:42 +00:00
message.reply_text("I think you should send me a link.", quote=True)
return
Redis().update_metrics("video_request")
2021-08-14 09:57:42 +00:00
bot_msg: typing.Union["types.Message", "typing.Any"] = message.reply_text("Processing", quote=True)
client.send_chat_action(chat_id, 'upload_video')
temp_dir = tempfile.TemporaryDirectory()
2021-08-14 09:57:42 +00:00
result = ytdl_download(url, temp_dir.name, bot_msg)
logging.info("Download complete.")
2021-08-14 09:57:42 +00:00
markup = InlineKeyboardMarkup(
[
[ # First row
InlineKeyboardButton( # Generates a callback query when pressed
"audio",
callback_data="audio"
)
]
]
)
2021-08-14 09:57:42 +00:00
if result["status"]:
client.send_chat_action(chat_id, 'upload_document')
video_paths = result["filepath"]
2021-08-25 14:13:25 +00:00
bot_msg.edit_text('Download complete. Sending now...')
for video_path in video_paths:
filename = pathlib.Path(video_path).name
remain = bot_text.remaining_quota_caption(chat_id)
size = sizeof_fmt(os.stat(video_path).st_size)
2021-08-24 14:34:52 +00:00
meta = get_metadata(video_path)
client.send_video(chat_id, video_path,
supports_streaming=True,
caption=f"`{filename}`\n\n{url}\n\nsize: {size}\n\n{remain}",
progress=upload_hook, progress_args=(bot_msg,),
2021-08-24 14:34:52 +00:00
reply_markup=markup,
**meta
)
Redis().update_metrics("video_success")
2021-08-14 09:57:42 +00:00
bot_msg.edit_text('Download success!✅')
else:
client.send_chat_action(chat_id, 'typing')
tb = result["error"][0:4000]
2021-08-25 14:13:25 +00:00
bot_msg.edit_text(f"Download failed!❌\n\n```{tb}```", disable_web_page_preview=True)
2021-05-03 11:26:47 +00:00
2021-08-14 09:57:42 +00:00
temp_dir.cleanup()
2021-05-03 11:26:47 +00:00
2021-07-11 15:29:12 +00:00
2021-08-14 09:57:42 +00:00
@app.on_callback_query()
def answer(client: "Client", callback_query: types.CallbackQuery):
callback_query.answer(f"Converting to audio...please wait patiently")
Redis().update_metrics("audio_request")
2021-08-14 09:57:42 +00:00
msg = callback_query.message
2021-07-11 15:29:12 +00:00
2021-08-14 09:57:42 +00:00
chat_id = msg.chat.id
mp4_name = msg.video.file_name # 'youtube-dl_test_video_a.mp4'
2021-07-11 16:07:26 +00:00
flac_name = mp4_name.replace("mp4", "m4a")
2021-07-11 15:01:32 +00:00
with tempfile.NamedTemporaryFile() as tmp:
2021-08-14 09:57:42 +00:00
logging.info("downloading to %s", tmp.name)
client.send_chat_action(chat_id, 'record_video_note')
client.download_media(msg, tmp.name)
logging.info("downloading complete %s", tmp.name)
2021-07-11 15:01:32 +00:00
# execute ffmpeg
2021-08-14 09:57:42 +00:00
client.send_chat_action(chat_id, 'record_audio')
flac_tmp = convert_flac(flac_name, tmp)
client.send_chat_action(chat_id, 'upload_audio')
client.send_audio(chat_id, flac_tmp)
Redis().update_metrics("audio_success")
os.unlink(flac_tmp)
2021-05-03 11:26:47 +00:00
if __name__ == '__main__':
scheduler = BackgroundScheduler()
scheduler.add_job(Redis().reset_today, 'cron', hour=0, minute=0)
scheduler.start()
2021-08-29 02:02:11 +00:00
banner = f"""
By @BennyThink, VIP mode: {ENABLE_VIP}
"""
print(banner)
2021-08-14 09:57:42 +00:00
app.run()