text: # Copyright (C) 2020 Adek Maulana.
  #
  # Licensed under the Raphielscape Public License, Version 1.d (the "License");
  # you may not use this file except in compliance with the License.
  #
  
  from asyncio import create_subprocess_shell as asyncSubprocess
  from asyncio.subprocess import PIPE as asyncPIPE
  
  import asyncio
  import re
  import json
  import os
  import multiprocessing
  import errno
  
  from pySmartDL import SmartDL
  from urllib.error import HTTPError
  
  from userbot import CMD_HELP, LOGS
  from userbot.events import register
  from userbot.modules.upload_download import humanbytes
  
  
  async def subprocess_run(megadl, cmd):
      subproc = await asyncSubprocess(cmd, stdout=asyncPIPE, stderr=asyncPIPE)
      stdout, stderr = await subproc.communicate()
      exitCode = subproc.returncode
      if exitCode != 0:
          await megadl.edit(
              '**An error was detected while running subprocess**\n'
              f'```exitCode: {exitCode}\n'
              f'stdout: {stdout.decode().strip()}\n'
              f'stderr: {stderr.decode().strip()}```')
          return exitCode
      return stdout.decode().strip(), stderr.decode().strip(), exitCode
  
  
  @register(outgoing=True, pattern=r"^.mega(?: |$)(.*)")
  async def mega_downloader(megadl):
      await megadl.edit("`Processing...`")
      msg_link = await megadl.get_reply_message()
      link = megadl.pattern_match.group(1)
      if link:
          pass
      elif msg_link:
          link = msg_link.text
      else:
          return await megadl.edit("Usage: `.mega <MEGA.nz link>`")
      try:
          link = re.findall(r'\bhttps?://.*mega.*\.nz\S+', link)[0]
          """ - Mega changed their URL again - """
          if "file" in link:
              link = link.replace("#", "!").replace("file/", "#!")
          elif "folder" in link or "#F" in link or "#N" in link:
              await megadl.edit("`Currently support folder download are removed`.")
              return
      except IndexError:
          return await megadl.edit("`No MEGA.nz link found`\n")
      cmd = f'bin/megadown -q -m {link}'
      result = await subprocess_run(megadl, cmd)
      try:
          data = json.loads(result[0])
      except json.JSONDecodeError:
          return await megadl.edit("`Error: Can't extract the link`\n")
      except (IndexError, TypeError):
          return
      file_name = data["file_name"]
      file_url = data["url"]
      hex_key = data["hex_key"]
      hex_raw_key = data["hex_raw_key"]
      temp_file_name = file_name + ".temp"
      downloaded_file_name = "./" + "" + temp_file_name
      downloader = SmartDL(
          file_url, downloaded_file_name, progress_bar=False)
      display_message = None
      try:
          downloader.start(blocking=False)
      except HTTPError as e:
          return await megadl.edit("`" + str(e) + "`")
      while not downloader.isFinished():
          status = downloader.get_status().capitalize()
          total_length = downloader.filesize if downloader.filesize else None
          downloaded = downloader.get_dl_size()
          percentage = int(downloader.get_progress() * 100)
          progress = downloader.get_progress_bar()
          speed = downloader.get_speed(human=True)
          estimated_total_time = downloader.get_eta(human=True)
          try:
              current_message = (
                  "File Name:"
                  f"\n`{file_name}`\n\n"
                  "Status:"
                  f"\n**{status}** | {progress} `{percentage}%`"
                  f"\n{humanbytes(downloaded)} of {humanbytes(total_length)}"
                  f" @ {speed}"
                  f"\nETA: {estimated_total_time}"
              )
              if display_message != current_message:
                  await megadl.edit(current_message)
                  await asyncio.sleep(0.2)
                  display_message = current_message
          except Exception:
              pass
          finally:
              if status == "Combining":
                  await asyncio.sleep(float(downloader.get_eta()))
      if downloader.isSuccessful():
          download_time = downloader.get_dl_time(human=True)
          try:
              P = multiprocessing.Process(target=await decrypt_file(megadl,
                                          file_name, temp_file_name,
                                          hex_key, hex_raw_key),
                                          name="Decrypt_File")
              P.start()
              P.join()
          except FileNotFoundError as e:
              return await megadl.edit(str(e))
          else:
              return await megadl.edit(f"`{file_name}`\n\n"
                                       "Successfully downloaded\n"
                                       f"Download took: {download_time}")
      else:
          await megadl.edit("`Failed to download, "
                            "check heroku Logs for more details`")
          for e in downloader.get_errors():
              LOGS.info(str(e))
      return
  
  
  async def decrypt_file(megadl, file_name, temp_file_name,
                         hex_key, hex_raw_key):
      cmd = ("cat '{}' | openssl enc -d -aes-128-ctr -K {} -iv {} > '{}'"
             .format(temp_file_name, hex_key, hex_raw_key, file_name))
      if await subprocess_run(megadl, cmd):
          os.remove(temp_file_name)
      else:
          raise FileNotFoundError(
              errno.ENOENT, os.strerror(errno.ENOENT), file_name)
      return
  
  
  CMD_HELP.update({
      "mega":
      ".mega <MEGA.nz link>"
      "\nUsage: Reply to a MEGA.nz link or paste your MEGA.nz link to "
      "download the file into your userbot server."
  })