class QBitTorrentWrapper(object): def __init__(self, ip, username, password): self.ip = ip self.username = username self.password = password self.qb = Client(ip) self.qb.login(self.username, self.password) def addTorrentsFromFolder(self, dl_location_path): self.dl_location_path = dl_location_path for filename in filter(os.path.isfile, os.listdir(os.curdir)): if filename.endswith(".torrent"): torrent_file = open('%s' % filename, 'rb') self.qb.download_from_file(torrent_file, savepath=dl_location_path) def startDownloading(self): self.qb.resume_all() def stopDownloading(self): self.qb.pause_all() def timeInterval(self): schedule.every().day.at("00:00").do(self.startDownloading) schedule.every().day.at("06:00").do(self.stopDownloading) while True: schedule.run_pending()
# open the torrent file of the file you wanna download torrent_file = open("debian-10.2.0-amd64-netinst.iso.torrent", "rb") # start downloading qb.download_from_file(torrent_file) # this magnet is not valid, replace with yours # magnet_link = "magnet:?xt=urn:btih:e334ab9ddd91c10938a7....." # qb.download_from_link(magnet_link) # you can specify the save path for downloads # qb.download_from_file(torrent_file, savepath="/the/path/you/want/to/save") # pause all downloads qb.pause_all() # resume them qb.resume_all() def get_size_format(b, factor=1024, suffix="B"): """ Scale bytes to its proper byte format e.g: 1253656 => '1.20MB' 1253656678 => '1.17GB' """ for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]: if b < factor: return f"{b:.2f}{unit}{suffix}" b /= factor return f"{b:.2f}Y{suffix}"
def on_callback_query(msg): global qb, magnet, p1, r1, dell, torrent, user, password, ip, port query_id, chat_id, query_data = telepot.glance(msg, flavor='callback_query') print('Callback Query:', query_id, chat_id, query_data) if query_data=='rc': #reconnect qb = Client("http://{}:{}".format(ip, port)) qb.login(user, password) bot.answerCallbackQuery(query_id, text="Reconnected") elif query_data=='addm': #add one or more magnet bot.sendMessage(chat_id, "Add Magnet") magnet=True elif query_data=='addt': #add one torrent file bot.sendMessage(chat_id, "Send the Torrent") torrent=True elif query_data=='list': #print the list of torrents if not qb.torrents(): bot.answerCallbackQuery(query_id, text="No Torrents in downloading") else: bot.sendMessage(chat_id, listt(1)) elif query_data=='pa': #pause all if not qb.torrents(): bot.answerCallbackQuery(query_id, text="No Torrents in downloading") else: qb.pause_all() bot.answerCallbackQuery(query_id, text="All paused") elif query_data=='ra': #resume all if not qb.torrents(): bot.answerCallbackQuery(query_id, text="No Torrents in downloading") else: qb.resume_all() bot.answerCallbackQuery(query_id, text="All resumed") elif query_data=='p1': #pause one if not qb.torrents(): bot.answerCallbackQuery(query_id, text="No Torrents in downloading") else: bot.sendMessage(chat_id, "Select a torrent in the list:\n"+listt(0)) p1=True elif query_data=='r1': #resume one if not qb.torrents(): bot.answerCallbackQuery(query_id, text="No Torrents in downloading") else: bot.sendMessage(chat_id, "Select a torrent in the list:\n"+listt(0)) r1=True elif query_data=='del': #delete one if not qb.torrents(): bot.answerCallbackQuery(query_id, text="No Torrents in downloading") else: bot.sendMessage(chat_id, "Select a torrent in the list:\n"+listt(0)) dell=True elif query_data=='delal': #delete all if not qb.torrents(): bot.answerCallbackQuery(query_id, text="No Torrents in downloading") else: if dellall() == True: bot.sendMessage(chat_id, "Deleted") else: bot.sendMessage(chat_id, "error")
def start_all(): qb = Client(URL) qb.login(user, password) qb.resume_all()
class Bot: qb = None download_folder = "./downloads" logged_in = False TOKEN = bot_auth.token # Enable logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) logger = logging.getLogger(name=__name__) IP = 0 LOGIN_PROMPT = 1 ADD_FILE = 0 ip_port_text = None username_password = None def start(self, bot, update): self.ip_port_text = None self.username_password = None self.logged_in = False user = update.message.from_user if str(user.id) in bot_auth.user_id: self.logger.info("Authorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "Hello, I'm QBitTorrent Remote controller.\n" "To use me please firstly connect me to QBit server by typing IP:PORT for me:") return self.IP else: self.logger.info("Unauthorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You don't have rights to use me! Who the f*** are you?") return ConversationHandler.END def ip(self, bot, update): self.ip_port_text = update.message.text user = update.message.from_user if re.match('^(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}|localhost):\d{1,5}$', self.ip_port_text): self.logger.info("User %s entered a right IP and PORT" % user.id) self.logger.info("Trying to connect to client") try: self.qb = Client("http://%s/" % self.ip_port_text) try: self.qb.torrents() self.logger.info("Logging in was successful.") update.message.reply_text("Logged in! Now you can use me.\n" "To get info about commands type /help") self.logged_in = True except client.LoginRequired: self.logger.info("Login required.") update.message.reply_text("Username and password is required to connect client.\n" "Please enter an username and password by seperating them with space.\n" "If you don't know username and password you can" " '/cancel'. and try again later") return self.LOGIN_PROMPT except exceptions.ConnectionError: self.logger.info("Connection refused.") update.message.reply_text("Connection to given IP address is refused." "\nPlease try again by typing /start") self.ip_port_text = None else: self.logger.info("User %s entered a wrong IP and PORT" % user.id) update.message.reply_text("Please enter a proper ip and port. You can restart by typing /start") return ConversationHandler.END def login(self, bot, update): self.logger.info("Checking if message fits the RegEX") username_password = update.message.text self.username_password = username_password user = update.message.from_user if re.match('^[^ ]+ [^ ]+$', username_password): username_password_split = username_password.split(" ") self.logger.info("Trying to login with given username and password") try: self.qb.login(username=username_password_split[0], password=username_password_split[1]) self.qb.torrents() self.logger.info("Logging in was successful.") update.message.reply_text("Logged in! Now you can use me.\n" "To get info about commands type /help") self.logged_in = True except client.LoginRequired: self.logger.info("Username and Password was wrong") update.message.reply_text("Username and Password was wrong\n" "Please enter a new username and password by seperating them with space.\n" "If you don't know username and password you can" " '/cancel'. and try again later") return self.LOGIN_PROMPT return ConversationHandler.END else: self.logger.info("Typed message does not match what is asked.") update.message.reply_text("Please enter a new username and password by seperating them with space.\n" "And make sure your username or password does not contain " "any space(\" \") character" "If you don't know username and password you can" " '/cancel'. and try again later") return self.LOGIN_PROMPT def reconnect(self, bot, update): user = update.message.from_user if self.ip_port_text is not None and not self.logged_in and str(user.id) in bot_auth.user_id: try: self.qb = Client("http://%s/" % self.ip_port_text) try: self.qb.torrents() self.logger.info("Logging in was successful.") update.message.reply_text("Logged in! Now you can use me.\n" "To get info about commands type /help") self.logged_in = True except client.LoginRequired: self.logger.info("Trying to log in using previous info") username_password_split = self.username_password.split(" ") self.qb.login(username=username_password_split[0], password=username_password_split[1]) try: self.qb.torrents() self.logger.info("Logging in was successful.") update.message.reply_text("Logged in! Now you can use me.\n" "To get info about commands type /help") self.logged_in = True except client.LoginRequired: self.logger.info("Logging in with old info was unsuccessful.") update.message.reply_text("Logging in with old info was unsuccessful.\n" "You can try again later (/reconnect)\nor type new info using /start") except exceptions.ConnectionError: self.logger.info("Connection refused.") update.message.reply_text("Connection to client IP address is refused." "\nPlease try again by typing /start" "\nOr try to /reconnect later.") elif str(user) not in bot_auth.user_id: self.logger.info("Unauthorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You don't have rights to use me! Who the f*** are you?") elif self.logged_in: self.logger.info("User tried to use reconnect while already logged in.") update.message.reply_text("You are already logged in. You don't need to reconnect") elif self.ip_port_text is None: self.logger.info("User tried to use reconnect without any previous info.") update.message.reply_text("You don't have any previous info. \nPlease type /start to connect") def cancel(self, bot, update): user = update.message.from_user self.logger.info("User %s canceled the conversation." % user.first_name) update.message.reply_text('Bye! I hope we can talk again some day.') self.ip_port_text = None return ConversationHandler.END def list_downloading_torrents(self, bot, update): user = update.message.from_user try: if str(user.id) in bot_auth.user_id and self.logged_in: output = "" self.logger.info("%s tried listing downloading." % update.message.from_user) if len(self.qb.torrents()) > 0: for torrent in self.qb.torrents(filter="downloading"): output += "%s\n | Size: %.2f GB\n | Download Speed: %.1f MB/s\n | Downloaded: %s%%\n\n" % (torrent["name"], float(torrent["size"]/1073741824), float(torrent["dlspeed"]/1048576), int(torrent["progress"]*100)) update.message.reply_text("Torrents currently downloading:\n%s" % output) else: update.message.reply_text("There is no torrents to list.") elif not self.logged_in: self.logger.info("Usage without logging in tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You should first login by typing /start") else: self.logger.info("Unauthorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You don't have rights to use me! Who the f*** are you?") except exceptions.ConnectionError: self.logger.info("Connection is lost. Retrying to connect...") self.logged_in = False update.message.reply_text( "Ups. Connection to qBit Client is lost. \nRetrying to connect with previous info.") return self.reconnect(bot=bot, update=update) # key | type | Description # --------------------------------------- # hash string Torrent hash # name string Torrent name # size integer Torrent size (bytes) # progress float Torrent progress (%/100) # dlspeed integer Torrent download speed (bytes/s) # upspeed integer Torrent upload speed (bytes/s) # priority integer Torrent priority. Returns -1 if queuing is disabled # num_seeds integer Torrent seeds connected to # num_complete integer Torrent seeds in the swarm # num_leechs integer Torrent leechers connected to # num_incomplete integer Torrent leechers in the swarm # ratio float Torrent share ratio. Max ratio value: 9999. # eta integer Torrent ETA (seconds) # state string Torrent state. See possible values here below # seq_dl bool True if sequential download is enabled # f_l_piece_prio bool True if first last piece are prioritized def list(self, bot, update): user = update.message.from_user try: if str(user.id) in bot_auth.user_id and self.logged_in: output = "" self.logger.info("%s tried listing." % update.message.from_user) if len(self.qb.torrents()) > 0: for torrent in self.qb.torrents(): output += "%s\n | Status: %s\n | Size: %.2f GB\n | Download Speed: %.1f MB/s\n | Downloaded: %s%%\n\n" % (torrent["name"], torrent["state"].upper(), float(torrent["size"]/1073741824), float(torrent["dlspeed"]/1048576), int(torrent["progress"]*100)) update.message.reply_text("Torrents currently downloading:\n%s" % output) else: update.message.reply_text("There is no torrents to list.") elif not self.logged_in: self.logger.info("Usage without logging in tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You should first login by typing /start") else: self.logger.info("Unauthorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You don't have rights to use me! Who the f*** are you?") except exceptions.ConnectionError: self.logger.info("Connection is lost. Retrying to connect...") self.logged_in = False update.message.reply_text( "Ups. Connection to qBit Client is lost. \nRetrying to connect with previous info.") return self.reconnect(bot=bot, update=update) def pause(self, bot, update, args): user = update.message.from_user try: if str(user.id) in bot_auth.user_id and self.logged_in: torrents_to_pause = [] torrents_copy = self.qb.torrents().copy() for arg in args: for torrent in torrents_copy: if re.match(arg, torrent["name"], re.IGNORECASE): torrents_copy.remove(torrent) torrents_to_pause.append(str(torrent["hash"])) self.qb.pause_multiple(torrents_to_pause) self.logger.info("Paused following: %s" % args) output = "" for torrent in torrents_to_pause: output += "--%s, %s%%\n" % (torrent["name"], int(torrent["progress"]*100)) update.message.reply_text("Following torrents paused:\n%s" % output) elif not self.logged_in: self.logger.info("Usage without logging in tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You should first login by typing /start") else: self.logger.info("Unauthorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You don't have rights to use me! Who the f*** are you?") except exceptions.ConnectionError: self.logger.info("Connection is lost. Retrying to connect...") self.logged_in = False update.message.reply_text( "Ups. Connection to qBit Client is lost. \nRetrying to connect with previous info.") return self.reconnect(bot=bot, update=update) def pause_all(self, bot, update): user = update.message.from_user try: if str(user.id) in bot_auth.user_id: self.qb.pause_all() self.logger.info("Paused all") elif not self.logged_in: self.logger.info("Usage without logging in tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You should first login by typing /start") else: self.logger.info("Unauthorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You don't have rights to use me! Who the f*** are you?") except exceptions.ConnectionError: self.logger.info("Connection is lost. Retrying to connect...") self.logged_in = False update.message.reply_text( "Ups. Connection to qBit Client is lost. \nRetrying to connect with previous info.") return self.reconnect(bot=bot, update=update) def resume(self, bot, update, args): user = update.message.from_user try: if str(user.id) in bot_auth.user_id: torrents_to_resume = [] torrents_copy = self.qb.torrents().copy() for arg in args: for torrent in torrents_copy: if re.match(arg, torrent["name"], re.IGNORECASE): torrents_copy.remove(torrent) torrents_to_resume.append(str(torrent["hash"])) self.qb.resume_multiple(torrents_to_resume) self.logger.info("Paused following: %s" % args) output = "" for torrent in torrents_to_resume: output += "--%s, %s%%\n" % (torrent["name"], int(torrent["progress"]*100)) update.message.reply_text("Following torrents resumed:\n%s" % output) elif not self.logged_in: self.logger.info("Usage without logging in tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You should first login by typing /start") else: self.logger.info("Unauthorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You don't have rights to use me! Who the f*** are you?") except exceptions.ConnectionError: self.logger.info("Connection is lost. Retrying to connect...") self.logged_in = False update.message.reply_text( "Ups. Connection to qBit Client is lost. \nRetrying to connect with previous info.") return self.reconnect(bot=bot, update=update) def resume_all(self, bot, update, args): user = update.message.from_user try: if str(user.id) in bot_auth.user_id: self.qb.resume_all() self.logger.info("Resumed all") elif not self.logged_in: self.logger.info("Usage without logging in tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You should first login by typing /start") else: self.logger.info("Unauthorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You don't have rights to use me! Who the f*** are you?") except exceptions.ConnectionError: self.logger.info("Connection is lost. Retrying to connect...") self.logged_in = False update.message.reply_text( "Ups. Connection to qBit Client is lost. \nRetrying to connect with previous info.") return self.reconnect(bot=bot, update=update) def add(self, bot, update): user = update.message.from_user try: if str(user.id) in bot_auth.user_id: update.message.reply_text("Send .torrent file you want to download.") return self.ADD_FILE elif not self.logged_in: self.logger.info("Usage without logging in tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You should first login by typing /start") else: self.logger.info("Unauthorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You don't have rights to use me! Who the f*** are you?") return ConversationHandler.END except exceptions.ConnectionError: self.logger.info("Connection is lost. Retrying to connect...") self.logged_in = False update.message.reply_text( "Ups. Connection to qBit Client is lost. \nRetrying to connect with previous info.") self.reconnect(bot=bot, update=update) return ConversationHandler.END def add_file(self, bot, update): try: user = update.message.from_user if str(user.id) in bot_auth.user_id: update.message.reply_text("File received. ") file = bot.get_file(file_id=update.message.document.file_id) # print(file) document = update.message.document file_extension = document.file_name.split(".")[-1] if re.match("^torrent$", file_extension, re.IGNORECASE): # file. file.download(custom_path="%s/%s" % (self.download_folder, document.file_name)) file_read = open("%s/%s" % (self.download_folder, document.file_name), "rb") self.logger.info("Torrent file downloaded to %s" % self.download_folder) self.qb.download_from_file(file_read) self.logger.info("Started downloading %s" % document.file_name) update.message.reply_text("Downloading the file.") elif not self.logged_in: self.logger.info("Usage without logging in tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You should first login by typing /start") else: self.logger.info("Unauthorized usage tried by: %s -- %s" % (user.username, user.id)) update.message.reply_text( "You don't have rights to use me! Who the f*** are you?") return ConversationHandler.END except exceptions.ConnectionError: self.logger.info("Connection is lost. Retrying to connect...") self.logged_in = False update.message.reply_text( "Ups. Connection to qBit Client is lost. \nRetrying to connect with previous info.") self.reconnect(bot=bot, update=update) return ConversationHandler.END def help(self, bot, update): update.message.reply_text("Simple bot for using qBit client via Telegram.\n" "Available commands:\n" "/start\n" "--- Start logging in process with new info.\n" "/reconnect\n" "--- Try to reconnect using previously entered info.\n" "/pause NAME1 NAME2 NAME3 ...\n" "--- Pause torrents : NAME1, NAME2 etc.\n" "/pause_all\n" "--- Pause all torrents.\n" "/resume NAME1 NAME2 NAME3 ...\n" "--- Resume torrents : NAME1, NAME2 etc.\n" "/resume_all\n" "--- Resume all torrents. \n" "/list\n" "--- List all torrents.\n" "/downloading\n" "--- List all torrents with Downloading status\n" "/add\n" "--- Start downloading of a new .torrent file.\n" "/help\n" "--- Display this message.\n" "PS: NAME1 NAME2 etc. does *NOT* have to be FULL name.") def error(self, bot, update, error): self.logger.warn('Update "%s" caused error "%s"' % (update, error)) def main(self): # Create the EventHandler and pass it your bot's token. updater = Updater(self.TOKEN) # Get the dispatcher to register handlers dp = updater.dispatcher # Add conversation handler with the states GENDER, PHOTO, LOCATION and BIO conv_handler_start = ConversationHandler( entry_points=[CommandHandler('start', self.start)], states={ self.IP: [MessageHandler(Filters.text, self.ip)], self.LOGIN_PROMPT: [MessageHandler(Filters.text, self.login)] }, fallbacks=[CommandHandler('cancel', self.cancel)] ) conv_handler_torrent = ConversationHandler( entry_points=[CommandHandler("add", self.add)], states={ self.ADD_FILE: [MessageHandler(Filters.document, self.add_file)] }, fallbacks=[CommandHandler('cancel', self.cancel)] ) # dp.add_handler() dp.add_handler(conv_handler_start) dp.add_handler(conv_handler_torrent) dp.add_handler(CommandHandler("downloading", self.list_downloading_torrents)) dp.add_handler(CommandHandler("list", self.list)) dp.add_handler(CommandHandler("pause", self.pause, pass_args=True)) dp.add_handler(CommandHandler("resume", self.resume, pass_args=True)) dp.add_handler(CommandHandler("pause_all", self.pause_all)) dp.add_handler(CommandHandler("resume_all", self.resume_all, pass_args=True)) dp.add_handler(CommandHandler("reconnect", self.reconnect)) dp.add_handler(CommandHandler("help", self.help)) # log all errors dp.add_error_handler(self.error) # Start the Bot updater.start_polling() # Run the bot until the you presses Ctrl-C or the process receives SIGINT, # SIGTERM or SIGABRT. This should be used most of the time, since # start_polling() is non-blocking and will stop the bot gracefully. updater.idle()