Advertisement
Guest User

Untitled

a guest
Jan 19th, 2020
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.32 KB | None | 0 0
  1. # Thanks to @AvinashReddy3108 for this plugin
  2.  
  3. """
  4. Audio and video downloader using Youtube-dl
  5. .playlista To Download in mp3 format
  6. .playlistv To Download in mp4 format
  7. """
  8.  
  9. import os
  10. import time
  11. import math
  12. import asyncio
  13. from youtube_dl import YoutubeDL
  14. from youtube_dl.utils import (DownloadError, ContentTooShortError,
  15. ExtractorError, GeoRestrictedError,
  16. MaxDownloadsReached, PostProcessingError,
  17. UnavailableVideoError, XAttrMetadataError)
  18. from asyncio import sleep
  19. from telethon.tl.types import DocumentAttributeAudio, DocumentAttributeVideo
  20.  
  21. from userbot.util import admin_cmd, humanbytes, progress, time_formatter
  22. from PIL import Image
  23. from hachoir.metadata import extractMetadata
  24. from hachoir.parser import createParser
  25. from telethon.tl.types import DocumentAttributeAudio
  26. from uniborg.util import admin_cmd
  27. from sample_config import Config
  28. import shutil
  29. import wget
  30.  
  31. DELETE_TIMEOUT = 3
  32.  
  33.  
  34.  
  35.  
  36. async def progress(current, total, event, start, type_of_ps, file_name=None):
  37. """Generic progress_callback for uploads and downloads."""
  38. now = time.time()
  39. diff = now - start
  40. if round(diff % 10.00) == 0 or current == total:
  41. percentage = current * 100 / total
  42. speed = current / diff
  43. elapsed_time = round(diff) * 1000
  44. time_to_completion = round((total - current) / speed) * 1000
  45. estimated_total_time = elapsed_time + time_to_completion
  46. progress_str = "{0}{1} {2}%\n".format(
  47. ''.join(["█" for i in range(math.floor(percentage / 10))]),
  48. ''.join(["░" for i in range(10 - math.floor(percentage / 10))]),
  49. round(percentage, 2))
  50. tmp = progress_str + \
  51. "{0} of {1}\nETA: {2}".format(
  52. humanbytes(current),
  53. humanbytes(total),
  54. time_formatter(estimated_total_time)
  55. )
  56. if file_name:
  57. await event.edit("{}\nFile Name: `{}`\n{}".format(
  58. type_of_ps, file_name, tmp))
  59. else:
  60. await event.edit("{}\n{}".format(type_of_ps, tmp))
  61.  
  62.  
  63. def humanbytes(size):
  64. """Input size in bytes,
  65. outputs in a human readable format"""
  66. # https://stackoverflow.com/a/49361727/4723940
  67. if not size:
  68. return ""
  69. # 2 ** 10 = 1024
  70. power = 2**10
  71. raised_to_pow = 0
  72. dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"}
  73. while size > power:
  74. size /= power
  75. raised_to_pow += 1
  76. return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B"
  77.  
  78.  
  79. def time_formatter(milliseconds: int) -> str:
  80. """Inputs time in milliseconds, to get beautified time,
  81. as string"""
  82. seconds, milliseconds = divmod(int(milliseconds), 1000)
  83. minutes, seconds = divmod(seconds, 60)
  84. hours, minutes = divmod(minutes, 60)
  85. days, hours = divmod(hours, 24)
  86. tmp = ((str(days) + " day(s), ") if days else "") + \
  87. ((str(hours) + " hour(s), ") if hours else "") + \
  88. ((str(minutes) + " minute(s), ") if minutes else "") + \
  89. ((str(seconds) + " second(s), ") if seconds else "") + \
  90. ((str(milliseconds) + " millisecond(s), ") if milliseconds else "")
  91. return tmp[:-2]
  92.  
  93. @borg.on(admin_cmd(pattern="playlist(a|v) ?(.*)"))
  94. async def download_video(v_url):
  95. """ For .ytdl command, download media from YouTube and many other sites. """
  96. reply = await v_url.get_reply_message()
  97. if v_url.pattern_match.group(2) != "":
  98. url = v_url.pattern_match.group(2)
  99. elif reply is not None:
  100. url = reply.message
  101. else:
  102. return
  103. type = v_url.pattern_match.group(1).lower() if v_url.pattern_match.group(1) is not None else "a"
  104.  
  105. await v_url.edit("`Preparing to download...`")
  106. out_folder = Config.TMP_DOWNLOAD_DIRECTORY + "youtubedl/"
  107. thumb_image_path = Config.TMP_DOWNLOAD_DIRECTORY + "/thumb_image.jpg"
  108. if not os.path.isdir(out_folder):
  109. os.makedirs(out_folder)
  110.  
  111. if type == "a":
  112. opts = {
  113. 'format':'bestaudio',
  114. 'addmetadata':True,
  115. 'noplaylist': False,
  116. 'key':'FFmpegMetadata',
  117. 'writethumbnail':True,
  118. 'embedthumbnail':True,
  119. 'prefer_ffmpeg':True,
  120. 'geo_bypass':True,
  121. 'nocheckcertificate':True,
  122. 'postprocessors': [{
  123. 'key': 'FFmpegExtractAudio',
  124. 'preferredcodec': 'mp3',
  125. 'preferredquality': '320',
  126. }],
  127. 'outtmpl':out_folder + '%(title)s.%(ext)s',
  128. 'quiet':True,
  129. 'logtostderr':False
  130. }
  131. video = False
  132. song = True
  133.  
  134. elif type == "v":
  135. opts = {
  136. 'format':'best',
  137. 'addmetadata': True,
  138. 'noplaylist': False,
  139. 'getthumbnail':True,
  140. 'embedthumbnail': True,
  141. 'xattrs':True,
  142. 'writethumbnail': True,
  143. 'key':'FFmpegMetadata',
  144. 'prefer_ffmpeg':True,
  145. 'geo_bypass':True,
  146. 'nocheckcertificate':True,
  147. 'postprocessors':
  148. [{
  149. 'key': 'FFmpegVideoConvertor',
  150. 'preferedformat': 'mp4'},
  151. ],
  152. 'outtmpl':out_folder + '%(title)s.%(ext)s',
  153. 'logtostderr':False,
  154. 'quiet':True
  155. }
  156. song = False
  157. video = True
  158.  
  159. try:
  160. await v_url.edit("`Fetching playlist data, please wait..`")
  161. with YoutubeDL(opts) as ytdl:
  162. ytdl_data = ytdl.extract_info(url)
  163. # print(ytdl_data['thumbnail'])
  164. filename = sorted(get_lst_of_files(out_folder, []))
  165. except DownloadError as DE:
  166. await v_url.edit(f"`{str(DE)}`")
  167. return
  168. except ContentTooShortError:
  169. await v_url.edit("`The download content was too short.`")
  170. return
  171. except GeoRestrictedError:
  172. await v_url.edit(
  173. "`Video is not available from your geographic location due to geographic restrictions imposed by a website.`"
  174. )
  175. return
  176. except MaxDownloadsReached:
  177. await v_url.edit("`Max-downloads limit has been reached.`")
  178. return
  179. except PostProcessingError:
  180. await v_url.edit("`There was an error during post processing.`")
  181. return
  182. except UnavailableVideoError:
  183. await v_url.edit("`Media is not available in the requested format.`")
  184. return
  185. except XAttrMetadataError as XAME:
  186. await v_url.edit(f"`{XAME.code}: {XAME.msg}\n{XAME.reason}`")
  187. return
  188. except ExtractorError:
  189. await v_url.edit("`There was an error during info extraction.`")
  190. return
  191. except Exception as e:
  192. await v_url.edit(f"{str(type(e)): {str(e)}}")
  193. return
  194. c_time = time.time()
  195. await v_url.edit("`YouTube Playlist Downloading Processing Now.\nPlease Wait!`")
  196. if song:
  197. for single_file in filename:
  198. if os.path.exists(single_file):
  199. caption_rts = os.path.basename(single_file)
  200. force_document = True
  201. supports_streaming = False
  202. document_attributes = []
  203. if single_file.endswith((".mp4", ".mp3", ".flac", ".webm")):
  204. metadata = extractMetadata(createParser(single_file))
  205. duration = 0
  206. width = 0
  207. height = 180
  208. if metadata.has("duration"):
  209. duration = metadata.get('duration').seconds
  210. document_attributes = [
  211. DocumentAttributeVideo(
  212. duration=duration,
  213. w=width,
  214. h=height,
  215. round_message=False,
  216. supports_streaming=True,
  217. )
  218. ]
  219. try:
  220. ytdl_data_name_audio = os.path.basename(single_file)
  221. print(ytdl_data_name_audio)
  222. file_path = single_file
  223. song_size = file_size(file_path)
  224. await v_url.client.send_file(
  225. v_url.chat_id,
  226. single_file,
  227. caption=f"`{ytdl_data_name_audio}`" + "\n" + f"`{song_size}`",
  228. force_document=force_document,
  229. supports_streaming=supports_streaming,
  230. allow_cache=False,
  231. reply_to=v_url.message.id,
  232. attributes=document_attributes,
  233. progress_callback=lambda d, t: asyncio.get_event_loop(
  234. ).create_task(
  235. progress(d, t, v_url, c_time, "Uploading..",
  236. f"👉 {ytdl_data_name_audio}")))
  237. # os.remove(thumb)
  238. except Exception as e:
  239. await v_url.client.send_message(
  240. v_url.chat_id,
  241. "{} caused `{}`".format(caption_rts, str(e)),
  242. )
  243. continue
  244. os.remove(single_file)
  245. await asyncio.sleep(DELETE_TIMEOUT)
  246. await v_url.delete()
  247. shutil.rmtree(out_folder)
  248. if video:
  249. for single_file in filename:
  250. if os.path.exists(single_file):
  251. caption_rts = os.path.basename(single_file)
  252. force_document = False
  253. supports_streaming = True
  254. document_attributes = []
  255. if single_file.endswith((".mp4", ".mp3", ".flac", ".webm")):
  256. metadata = extractMetadata(createParser(single_file))
  257. duration = 0
  258. width = 0
  259. height = 0
  260. if metadata.has("duration"):
  261. duration = metadata.get('duration').seconds
  262. document_attributes = [
  263. DocumentAttributeVideo(
  264. duration=duration,
  265. w=width,
  266. h=height,
  267. round_message=False,
  268. supports_streaming=True,
  269. )
  270. ]
  271. image_link = ytdl_data['thumbnail']
  272. downloaded_image = wget.download(image_link,out_folder)
  273. thumb = downloaded_image
  274. file_path = single_file
  275. video_size = file_size(file_path)
  276. try:
  277. ytdl_data_name_video = os.path.basename(single_file)
  278. await v_url.client.send_file(
  279. v_url.chat_id,
  280. single_file,
  281. caption=f"`{ytdl_data_name_video}`" + "\n" + f"`{video_size}`",
  282. force_document=force_document,
  283. supports_streaming=supports_streaming,
  284. thumb = thumb,
  285. allow_cache=False,
  286. reply_to=v_url.message.id,
  287. attributes=document_attributes,
  288. progress_callback=lambda d, t: asyncio.get_event_loop(
  289. ).create_task(
  290. progress(d, t, v_url, c_time, "Uploading..",
  291. f"💦 {ytdl_data_name_video}")))
  292. # os.remove(thumb)
  293. except Exception as e:
  294. await v_url.client.send_message(
  295. v_url.chat_id,
  296. "{} caused `{}`".format(caption_rts, str(e)),
  297. )
  298. continue
  299. os.remove(single_file)
  300. await asyncio.sleep(DELETE_TIMEOUT)
  301. await v_url.delete()
  302. shutil.rmtree(out_folder)
  303.  
  304.  
  305.  
  306.  
  307.  
  308. def get_lst_of_files(input_directory, output_lst):
  309. filesinfolder = os.listdir(input_directory)
  310. for file_name in filesinfolder:
  311. current_file_name = os.path.join(input_directory, file_name)
  312. if os.path.isdir(current_file_name):
  313. return get_lst_of_files(current_file_name, output_lst)
  314. output_lst.append(current_file_name)
  315. return output_lst
  316.  
  317. async def progress(current, total, event, start, type_of_ps, file_name=None):
  318. """Generic progress_callback for uploads and downloads."""
  319. now = time.time()
  320. diff = now - start
  321. if round(diff % 10.00) == 0 or current == total:
  322. percentage = current * 100 / total
  323. speed = current / diff
  324. elapsed_time = round(diff) * 1000
  325. time_to_completion = round((total - current) / speed) * 1000
  326. estimated_total_time = elapsed_time + time_to_completion
  327. progress_str = "{0}{1} {2}%\n".format(
  328. ''.join(["█" for i in range(math.floor(percentage / 10))]),
  329. ''.join(["░" for i in range(10 - math.floor(percentage / 10))]),
  330. round(percentage, 2))
  331. tmp = progress_str + \
  332. "{0} of {1}\nETA: {2}".format(
  333. humanbytes(current),
  334. humanbytes(total),
  335. time_formatter(estimated_total_time)
  336. )
  337. if file_name:
  338. await event.edit("{}\nFile Name: `{}`\n{}".format(
  339. type_of_ps, file_name, tmp))
  340. else:
  341. await event.edit("{}\n{}".format(type_of_ps, tmp))
  342.  
  343.  
  344. def humanbytes(size):
  345. """Input size in bytes,
  346. outputs in a human readable format"""
  347. # https://stackoverflow.com/a/49361727/4723940
  348. if not size:
  349. return ""
  350. # 2 ** 10 = 1024
  351. power = 2**10
  352. raised_to_pow = 0
  353. dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"}
  354. while size > power:
  355. size /= power
  356. raised_to_pow += 1
  357. return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B"
  358.  
  359.  
  360. def time_formatter(milliseconds: int) -> str:
  361. """Inputs time in milliseconds, to get beautified time,
  362. as string"""
  363. seconds, milliseconds = divmod(int(milliseconds), 1000)
  364. minutes, seconds = divmod(seconds, 60)
  365. hours, minutes = divmod(minutes, 60)
  366. days, hours = divmod(hours, 24)
  367. tmp = ((str(days) + " day(s), ") if days else "") + \
  368. ((str(hours) + " hour(s), ") if hours else "") + \
  369. ((str(minutes) + " minute(s), ") if minutes else "") + \
  370. ((str(seconds) + " second(s), ") if seconds else "") + \
  371. ((str(milliseconds) + " millisecond(s), ") if milliseconds else "")
  372. return tmp[:-2]
  373.  
  374. def convert_bytes(num):
  375. """
  376. this function will convert bytes to MB.... GB... etc
  377. """
  378. for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
  379. if num < 1024.0:
  380. return "%3.1f %s" % (num, x)
  381. num /= 1024.0
  382.  
  383.  
  384. def file_size(file_path):
  385. """
  386. this function will return the file size
  387. """
  388. if os.path.isfile(file_path):
  389. file_info = os.stat(file_path)
  390. return convert_bytes(file_info.st_size)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement