-Add more shorteners: linkvertise, shorte and bitly
-Minor fixes

Co-authored-by: Juned KH <junedkh@users.noreply.github.com>

Signed-off-by: anas <e.anastayyar@gmail.com>
This commit is contained in:
anas 2021-08-27 04:20:51 +03:00
parent b9656e3799
commit 10237fd58e
6 changed files with 101 additions and 57 deletions

View File

@ -0,0 +1,27 @@
import requests
import random
import base64
import pyshorteners
from urllib.parse import quote
from urllib3 import disable_warnings
from bot import SHORTENER, SHORTENER_API
def short_url(longurl):
if "shorte.st" in SHORTENER:
disable_warnings()
return requests.get(f'http://api.shorte.st/stxt/{SHORTENER_API}/{longurl}', verify=False).text
elif "linkvertise" in SHORTENER:
url = quote(base64.b64encode(longurl.encode("utf-8")))
linkvertise = [
f"https://link-to.net/{SHORTENER_API}/{random.random() * 1000}/dynamic?r={url}",
f"https://up-to-down.net/{SHORTENER_API}/{random.random() * 1000}/dynamic?r={url}",
f"https://direct-link.net/{SHORTENER_API}/{random.random() * 1000}/dynamic?r={url}",
f"https://file-link.net/{SHORTENER_API}/{random.random() * 1000}/dynamic?r={url}"]
return random.choice(linkvertise)
elif "bitly.com" in SHORTENER:
s = pyshorteners.Shortener(api_key=SHORTENER_API)
bitly = s.bitly.short(longurl)
return bitly
else:
return requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={longurl}&format=text').text

View File

@ -1,27 +0,0 @@
# An abstract class which will be inherited by the tool specific classes like aria2_helper or mega_download_helper
import threading
class MethodNotImplementedError(NotImplementedError):
def __init__(self):
super(self, 'Not implemented method')
class DownloadHelper:
def __init__(self):
self.name = '' # Name of the download; empty string if no download has been started
self.size = 0.0 # Size of the download
self.downloaded_bytes = 0.0 # Bytes downloaded
self.speed = 0.0 # Download speed in bytes per second
self.progress = 0.0
self.progress_string = '0.00%'
self.eta = 0 # Estimated time of download complete
self.eta_string = '0s' # A listener class which have event callbacks
self._resource_lock = threading.Lock()
def add_download(self, link: str, path):
raise MethodNotImplementedError
def cancel_download(self):
# Returns None if successfully cancelled, else error string
raise MethodNotImplementedError

View File

@ -77,10 +77,10 @@ class MegaAppListener(MegaListener):
self.continue_event.set()
def onRequestTemporaryError(self, api, request, error: MegaError):
LOGGER.info(f'Mega Request error in {error}')
LOGGER.error(f'Mega Request error in {error}')
if not self.is_cancelled:
self.listener.onDownloadError("RequestTempError: " + error.toString())
self.is_cancelled = True
self.listener.onDownloadError("RequestTempError: " + error.toString())
self.error = error.toString()
self.continue_event.set()
@ -90,12 +90,15 @@ class MegaAppListener(MegaListener):
def onTransferUpdate(self, api: MegaApi, transfer: MegaTransfer):
if self.is_cancelled:
api.cancelTransfer(transfer, None)
return
self.__speed = transfer.getSpeed()
self.__bytes_transferred = transfer.getTransferredBytes()
def onTransferFinish(self, api: MegaApi, transfer: MegaTransfer, error):
try:
if transfer.isFolderTransfer() and transfer.isFinished() or transfer.getFileName() == self.name and not self.is_cancelled:
if self.is_cancelled:
self.continue_event.set()
elif transfer.isFinished() and (transfer.isFolderTransfer() or transfer.getFileName() == self.name):
self.listener.onDownloadComplete()
self.continue_event.set()
except Exception as e:
@ -105,7 +108,7 @@ class MegaAppListener(MegaListener):
filen = transfer.getFileName()
state = transfer.getState()
errStr = error.toString()
LOGGER.info(f'Mega download error in file {transfer} {filen}: {error}')
LOGGER.error(f'Mega download error in file {transfer} {filen}: {error}')
if state == 1 or state == 4:
# Sometimes MEGA (offical client) can't stream a node either and raises a temp failed error.
@ -163,7 +166,7 @@ class MegaDownloadHelper:
executor.do(folder_api.loginToFolder, (mega_link,))
node = folder_api.authorizeNode(mega_listener.node)
if mega_listener.error is not None:
return listener.onDownloadError(str(mega_listener.error))
return sendMessage(str(mega_listener.error), listener.bot, listener.update)
if STOP_DUPLICATE:
LOGGER.info(f'Checking File/Folder if already in Drive')
mname = node.getName()

View File

@ -26,14 +26,20 @@ from bot import parent_id, DOWNLOAD_DIR, IS_TEAM_DRIVE, INDEX_URL, \
USE_SERVICE_ACCOUNTS, telegraph_token, BUTTON_FOUR_NAME, BUTTON_FOUR_URL, BUTTON_FIVE_NAME, BUTTON_FIVE_URL, BUTTON_SIX_NAME, BUTTON_SIX_URL, SHORTENER, SHORTENER_API, VIEW_LINK
from bot.helper.ext_utils.bot_utils import get_readable_file_size, setInterval
from bot.helper.ext_utils.fs_utils import get_mime_type, get_path_size
from bot.helper.ext_utils.shortenurl import short_url
LOGGER = logging.getLogger(__name__)
logging.getLogger('googleapiclient.discovery').setLevel(logging.ERROR)
if USE_SERVICE_ACCOUNTS:
SERVICE_ACCOUNT_INDEX = randrange(len(os.listdir("accounts")))
TELEGRAPHLIMIT = 80
class GoogleDriveHelper:
def __init__(self, name=None, listener=None):
self.__G_DRIVE_TOKEN_FILE = "token.pickle"
# Check https://developers.google.com/drive/scopes for all available scopes
@ -69,6 +75,7 @@ class GoogleDriveHelper:
self.transferred_size = 0
self.sa_count = 0
def speed(self):
"""
It calculates the average upload speed and returns it in bytes/seconds unit
@ -79,18 +86,21 @@ class GoogleDriveHelper:
except ZeroDivisionError:
return 0
def dspeed(self):
try:
return self.downloaded_bytes / self.dtotal_time
except ZeroDivisionError:
return 0
def cspeed(self):
try:
return self.transferred_size / int(time.time() - self.start_time)
except ZeroDivisionError:
return 0
@staticmethod
def getIdFromUrl(link: str):
if "folders" in link or "file" in link:
@ -102,6 +112,7 @@ class GoogleDriveHelper:
parsed = urlparse.urlparse(link)
return parse_qs(parsed.query)['id'][0]
@retry(wait=wait_exponential(multiplier=2, min=3, max=6), stop=stop_after_attempt(5),
retry=retry_if_exception_type(HttpError), before=before_log(LOGGER, logging.DEBUG))
def _on_upload_progress(self):
@ -112,6 +123,7 @@ class GoogleDriveHelper:
self.uploaded_bytes += chunk_size
self.total_time += self.update_interval
def __upload_empty_file(self, path, file_name, mime_type, parent_id=None):
media_body = MediaFileUpload(path,
mimetype=mime_type,
@ -125,6 +137,8 @@ class GoogleDriveHelper:
file_metadata['parents'] = [parent_id]
return self.__service.files().create(supportsTeamDrives=True,
body=file_metadata, media_body=media_body).execute()
def deletefile(self, link: str):
try:
file_id = self.getIdFromUrl(link)
@ -144,6 +158,7 @@ class GoogleDriveHelper:
finally:
return msg
def switchServiceAccount(self):
global SERVICE_ACCOUNT_INDEX
service_account_count = len(os.listdir("accounts"))
@ -153,7 +168,8 @@ class GoogleDriveHelper:
SERVICE_ACCOUNT_INDEX += 1
LOGGER.info(f"Switching to {SERVICE_ACCOUNT_INDEX}.json service account")
self.__service = self.authorize()
@retry(wait=wait_exponential(multiplier=2, min=3, max=6), stop=stop_after_attempt(5),
retry=retry_if_exception_type(HttpError), before=before_log(LOGGER, logging.DEBUG))
def __set_permission(self, drive_id):
@ -166,6 +182,7 @@ class GoogleDriveHelper:
return self.__service.permissions().create(supportsTeamDrives=True, fileId=drive_id,
body=permissions).execute()
@retry(wait=wait_exponential(multiplier=2, min=3, max=6), stop=stop_after_attempt(5),
retry=retry_if_exception_type(HttpError), before=before_log(LOGGER, logging.DEBUG))
def upload_file(self, file_path, file_name, mime_type, parent_id):
@ -234,6 +251,7 @@ class GoogleDriveHelper:
download_url = self.__G_DRIVE_BASE_DOWNLOAD_URL.format(drive_file.get('id'))
return download_url
def upload(self, file_name: str):
self.is_downloading = False
self.is_uploading = True
@ -299,6 +317,7 @@ class GoogleDriveHelper:
self.__listener.onUploadComplete(link, size, files, folders, typ)
return link
@retry(wait=wait_exponential(multiplier=2, min=3, max=6), stop=stop_after_attempt(5),
retry=retry_if_exception_type(HttpError), before=before_log(LOGGER, logging.DEBUG))
def copyFile(self, file_id, dest_id):
@ -327,12 +346,14 @@ class GoogleDriveHelper:
else:
raise err
@retry(wait=wait_exponential(multiplier=2, min=3, max=6), stop=stop_after_attempt(5),
retry=retry_if_exception_type(HttpError), before=before_log(LOGGER, logging.DEBUG))
def getFileMetadata(self,file_id):
return self.__service.files().get(supportsAllDrives=True, fileId=file_id,
fields="name,id,mimeType,size").execute()
@retry(wait=wait_exponential(multiplier=2, min=3, max=6), stop=stop_after_attempt(5),
retry=retry_if_exception_type(HttpError), before=before_log(LOGGER, logging.DEBUG))
def getFilesByFolderId(self,folder_id):
@ -354,6 +375,7 @@ class GoogleDriveHelper:
break
return files
def clone(self, link):
self.is_cloning = True
self.start_time = time.time()
@ -385,7 +407,7 @@ class GoogleDriveHelper:
msg += f'\n<b>Files: </b><code>{self.total_files}</code>'
buttons = button_build.ButtonMaker()
if SHORTENER is not None and SHORTENER_API is not None:
surl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={durl}&format=text').text
surl = short_url(durl)
buttons.buildbutton("☁️ Drive Link", surl)
else:
buttons.buildbutton("☁️ Drive Link", durl)
@ -393,7 +415,7 @@ class GoogleDriveHelper:
url_path = requests.utils.quote(f'{meta.get("name")}')
url = f'{INDEX_URL}/{url_path}/'
if SHORTENER is not None and SHORTENER_API is not None:
siurl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={url}&format=text').text
siurl = short_url(url)
buttons.buildbutton("⚡ Index Link", siurl)
else:
buttons.buildbutton("⚡ Index Link", url)
@ -409,17 +431,17 @@ class GoogleDriveHelper:
durl = self.__G_DRIVE_BASE_DOWNLOAD_URL.format(file.get("id"))
buttons = button_build.ButtonMaker()
if SHORTENER is not None and SHORTENER_API is not None:
surl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={durl}&format=text').text
surl = short_url(durl)
buttons.buildbutton("☁️ Drive Link", surl)
else:
buttons.buildbutton("☁️ Drive Link", durl)
try:
typeee = file.get('mimeType')
typ = file.get('mimeType')
except:
typeee = 'File'
typ = 'File'
try:
msg += f'\n<b>Size: </b><code>{get_readable_file_size(int(meta.get("size")))}</code>'
msg += f'\n<b>Type: </b><code>{typeee}</code>'
msg += f'\n<b>Type: </b><code>{typ}</code>'
except TypeError:
pass
if INDEX_URL is not None:
@ -427,10 +449,10 @@ class GoogleDriveHelper:
url = f'{INDEX_URL}/{url_path}'
urls = f'{INDEX_URL}/{url_path}?a=view'
if SHORTENER is not None and SHORTENER_API is not None:
siurl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={url}&format=text').text
siurls = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={urls}&format=text').text
siurl = short_url(url)
buttons.buildbutton("⚡ Index Link", siurl)
if VIEW_LINK:
siurls = short_url(urls)
buttons.buildbutton("🌐 View Link", siurls)
else:
buttons.buildbutton("⚡ Index Link", url)
@ -457,6 +479,7 @@ class GoogleDriveHelper:
return msg, ""
return msg, InlineKeyboardMarkup(buttons.build_menu(2))
def cloneFolder(self, name, local_path, folder_id, parent_id):
LOGGER.info(f"Syncing: {local_path}")
files = self.getFilesByFolderId(folder_id)
@ -480,6 +503,7 @@ class GoogleDriveHelper:
if self.is_cancelled:
break
@retry(wait=wait_exponential(multiplier=2, min=3, max=6), stop=stop_after_attempt(5),
retry=retry_if_exception_type(HttpError), before=before_log(LOGGER, logging.DEBUG))
def create_directory(self, directory_name, parent_id):
@ -496,6 +520,7 @@ class GoogleDriveHelper:
LOGGER.info("Created G-Drive Folder:\nName: {}\nID: {} ".format(file.get("name"), file_id))
return file_id
def upload_dir(self, input_directory, parent_id):
list_dirs = os.listdir(input_directory)
if len(list_dirs) == 0:
@ -518,6 +543,7 @@ class GoogleDriveHelper:
break
return new_id
def authorize(self):
# Get credentials
credentials = None
@ -543,6 +569,8 @@ class GoogleDriveHelper:
f'accounts/{SERVICE_ACCOUNT_INDEX}.json',
scopes=self.__OAUTH_SCOPE)
return build('drive', 'v3', credentials=credentials, cache_discovery=False)
def edit_telegraph(self):
nxt_page = 1
prev_page = 0
@ -564,12 +592,14 @@ class GoogleDriveHelper:
html_content=content)
return
def escapes(self, str):
chars = ['\\', "'", '"', r'\a', r'\b', r'\f', r'\n', r'\r', r'\t']
for char in chars:
str = str.replace(char, '\\'+char)
return str
def drive_list(self, fileName):
msg = ""
fileName = self.escapes(str(fileName))
@ -590,7 +620,7 @@ class GoogleDriveHelper:
furl = f"https://drive.google.com/drive/folders/{file.get('id')}"
msg += f"📁 <code>{file.get('name')}<br>(folder)</code><br>"
if SHORTENER is not None and SHORTENER_API is not None:
sfurl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={furl}&format=text').text
sfurl = short_url(furl)
msg += f"<b><a href={sfurl}>Drive Link</a></b>"
else:
msg += f"<b><a href={furl}>Drive Link</a></b>"
@ -598,7 +628,7 @@ class GoogleDriveHelper:
url_path = requests.utils.quote(f'{file.get("name")}')
url = f'{INDEX_URL}/{url_path}/'
if SHORTENER is not None and SHORTENER_API is not None:
siurl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={url}&format=text').text
siurl = short_url(url)
msg += f' <b>| <a href="{siurl}">Index Link</a></b>'
else:
msg += f' <b>| <a href="{url}">Index Link</a></b>'
@ -610,7 +640,7 @@ class GoogleDriveHelper:
furl = f"https://drive.google.com/uc?id={file.get('id')}&export=download"
msg += f"📄 <code>{file.get('name')}<br>({get_readable_file_size(int(file.get('size')))})</code><br>"
if SHORTENER is not None and SHORTENER_API is not None:
sfurl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={furl}&format=text').text
sfurl = short_url(furl)
msg += f"<b><a href={sfurl}>Drive Link</a></b>"
else:
msg += f"<b><a href={furl}>Drive Link</a></b>"
@ -619,10 +649,10 @@ class GoogleDriveHelper:
url = f'{INDEX_URL}/{url_path}'
urls = f'{INDEX_URL}/{url_path}?a=view'
if SHORTENER is not None and SHORTENER_API is not None:
siurl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={url}&format=text').text
siurls = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={urls}&format=text').text
siurl = short_url(url)
msg += f' <b>| <a href="{siurl}">Index Link</a></b>'
if VIEW_LINK:
siurls = short_url(urls)
msg += f' <b>| <a href="{siurls}">View Link</a></b>'
else:
msg += f' <b>| <a href="{url}">Index Link</a></b>'
@ -662,6 +692,7 @@ class GoogleDriveHelper:
else :
return '', ''
def count(self, link):
try:
file_id = self.getIdFromUrl(link)
@ -706,6 +737,7 @@ class GoogleDriveHelper:
return msg
return msg
def gDrive_file(self, **kwargs):
try:
size = int(kwargs['size'])
@ -713,6 +745,7 @@ class GoogleDriveHelper:
size = 0
self.total_bytes += size
def gDrive_directory(self, **kwargs) -> None:
files = self.getFilesByFolderId(kwargs['id'])
if len(files) == 0:
@ -725,6 +758,7 @@ class GoogleDriveHelper:
self.total_files += 1
self.gDrive_file(**file_)
def clonehelper(self, link):
try:
file_id = self.getIdFromUrl(link)
@ -757,6 +791,7 @@ class GoogleDriveHelper:
return msg, "", "", ""
return "", clonesize, name, files
def download(self, link):
self.is_downloading = True
file_id = self.getIdFromUrl(link)
@ -784,6 +819,7 @@ class GoogleDriveHelper:
return
self.__listener.onDownloadComplete()
def download_folder(self, folder_id, path, folder_name):
if not os.path.exists(path + folder_name):
os.makedirs(path + folder_name)
@ -819,6 +855,7 @@ class GoogleDriveHelper:
if self.is_cancelled:
break
def download_file(self, file_id, path, filename, mime_type):
request = self.__service.files().get_media(fileId=file_id)
fh = io.FileIO('{}{}'.format(path, filename), 'wb')
@ -850,13 +887,15 @@ class GoogleDriveHelper:
raise err
self._file_downloaded_bytes = 0
def _on_download_progress(self):
if self.dstatus is not None:
chunk_size = self.dstatus.total_size * self.dstatus.progress() - self._file_downloaded_bytes
self._file_downloaded_bytes = self.dstatus.total_size * self.dstatus.progress()
self.downloaded_bytes += chunk_size
self.dtotal_time += self.update_interval
def cancel_download(self):
self.is_cancelled = True
if self.is_downloading:
@ -865,5 +904,5 @@ class GoogleDriveHelper:
elif self.is_cloning:
LOGGER.info(f"Cancelling Clone: {self.name}")
elif self.is_uploading:
LOGGER.info(f"Cancelling upload: {self.name}")
LOGGER.info(f"Cancelling Upload: {self.name}")
self.__listener.onUploadError('your upload has been stopped and uploaded data has been deleted!')

View File

@ -5,7 +5,7 @@ from telegram import InlineKeyboardMarkup
from bot import Interval, INDEX_URL, BUTTON_FOUR_NAME, BUTTON_FOUR_URL, BUTTON_FIVE_NAME, BUTTON_FIVE_URL, BUTTON_SIX_NAME, BUTTON_SIX_URL, BLOCK_MEGA_FOLDER, BLOCK_MEGA_LINKS, VIEW_LINK, aria2, get_client
from bot import dispatcher, DOWNLOAD_DIR, download_dict, download_dict_lock, SHORTENER, SHORTENER_API, TAR_UNZIP_LIMIT
from bot.helper.ext_utils import fs_utils, bot_utils
from bot.helper.ext_utils.bot_utils import get_mega_link_type, check_limit
from bot.helper.ext_utils.shortenurl import short_url
from bot.helper.ext_utils.exceptions import DirectDownloadLinkException, NotSupportedExtractionArchive
from bot.helper.mirror_utils.download_utils.aria2_download import AriaDownloadHelper
from bot.helper.mirror_utils.download_utils.mega_downloader import MegaDownloadHelper
@ -164,7 +164,7 @@ class MirrorListener(listeners.MirrorListeners):
msg += f'\n<b>Type: </b><code>{typ}</code>'
buttons = button_build.ButtonMaker()
if SHORTENER is not None and SHORTENER_API is not None:
surl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={link}&format=text').text
surl = short_url(link)
buttons.buildbutton("☁️ Drive Link", surl)
else:
buttons.buildbutton("☁️ Drive Link", link)
@ -175,17 +175,17 @@ class MirrorListener(listeners.MirrorListeners):
if os.path.isdir(f'{DOWNLOAD_DIR}/{self.uid}/{download_dict[self.uid].name()}'):
share_url += '/'
if SHORTENER is not None and SHORTENER_API is not None:
siurl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={share_url}&format=text').text
siurl = short_url(share_url)
buttons.buildbutton("⚡ Index Link", siurl)
else:
buttons.buildbutton("⚡ Index Link", share_url)
else:
share_urls = f'{INDEX_URL}/{url_path}?a=view'
if SHORTENER is not None and SHORTENER_API is not None:
siurl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={share_url}&format=text').text
siurls = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={share_urls}&format=text').text
siurl = short_url(share_url)
buttons.buildbutton("⚡ Index Link", siurl)
if VIEW_LINK:
siurls = short_url(share_urls)
buttons.buildbutton("🌐 View Link", siurls)
else:
buttons.buildbutton("⚡ Index Link", share_url)
@ -335,7 +335,7 @@ def _mirror(bot, update, isTar=False, extract=False, isZip=False, isQbit=False):
sendMessage(res, bot, update)
return
if TAR_UNZIP_LIMIT is not None:
result = check_limit(size, TAR_UNZIP_LIMIT)
result = bot_utils.check_limit(size, TAR_UNZIP_LIMIT)
if result:
msg = f'Failed, Tar/Unzip limit is {TAR_UNZIP_LIMIT}.\nYour File/Folder size is {get_readable_file_size(size)}.'
sendMessage(msg, listener.bot, listener.update)
@ -350,11 +350,12 @@ def _mirror(bot, update, isTar=False, extract=False, isZip=False, isQbit=False):
drive.download(link)
elif bot_utils.is_mega_link(link):
link_type = get_mega_link_type(link)
if BLOCK_MEGA_LINKS:
sendMessage("Mega links are blocked!", bot, update)
return
link_type = bot_utils.get_mega_link_type(link)
if link_type == "folder" and BLOCK_MEGA_FOLDER:
sendMessage("Mega folder are blocked!", bot, update)
elif BLOCK_MEGA_LINKS:
sendMessage("Mega links are blocked!", bot, update)
else:
mega_dl = MegaDownloadHelper()
mega_dl.add_download(link, f'{DOWNLOAD_DIR}{listener.uid}/', listener)

View File

@ -30,3 +30,4 @@ TgCrypto
torrentool
urllib3
youtube_dl
pyshorteners