Made network requests safe, fixed connection reestablish mem leak
This commit is contained in:
parent
f7075b01e3
commit
db315652d1
152
bot.py
152
bot.py
|
@ -39,7 +39,8 @@ class QBittorrentAPICaller():
|
|||
self.username = username
|
||||
self.password = password
|
||||
self.session = requests.Session()
|
||||
self.reestablish_session()
|
||||
# self.reestablish_session()
|
||||
self.run_session_maintainer()
|
||||
|
||||
def __del__(self):
|
||||
self.logout()
|
||||
|
@ -58,55 +59,122 @@ class QBittorrentAPICaller():
|
|||
return to_ret
|
||||
|
||||
# We need to reestablish a connection to the server periodically, this does that
|
||||
def reestablish_session(self):
|
||||
#def reestablish_session(self):
|
||||
# Every 10 minutes, run this
|
||||
threading.Timer(600, self.reestablish_session).start()
|
||||
self.logout()
|
||||
self.login()
|
||||
logging.info("Reestablished connection to QBittorrent server")
|
||||
#threading.Timer(600, self.reestablish_session).start()
|
||||
# self.logout()
|
||||
# self.login()
|
||||
# logging.info("Reestablished connection to QBittorrent server")
|
||||
|
||||
def run_session_maintainer(self):
|
||||
def loop():
|
||||
while True:
|
||||
try:
|
||||
self.logout()
|
||||
self.login()
|
||||
logging.info("Reestablished connection to QBittorrent server")
|
||||
except Exception as e:
|
||||
logging.error(f"Session maintainer error: {e}", exc_info=True)
|
||||
time.sleep(600) # 10 minutes
|
||||
threading.Thread(target=loop, daemon=True).start()
|
||||
|
||||
def truncate_string(self, s, max_length=25):
|
||||
return s[:max_length] + '...' if len(s) > max_length else s
|
||||
|
||||
def safe_get(self, path, params=None):
|
||||
try:
|
||||
# resp = self.session.get(self.url + path, params=params, timeout=5)
|
||||
resp = self.session.get(path, params=params, timeout=5)
|
||||
resp.raise_for_status()
|
||||
return resp
|
||||
except requests.exceptions.RequestException as e:
|
||||
logging.warning(f"GET {path} failed: {e}")
|
||||
return None
|
||||
|
||||
def safe_post(self, path, data=None):
|
||||
try:
|
||||
# resp = self.session.post(self.url + path, data=data, timeout=5)
|
||||
resp = self.session.post(path, data=data, timeout=5)
|
||||
resp.raise_for_status()
|
||||
return resp
|
||||
except requests.exceptions.RequestException as e:
|
||||
logging.warning(f"POST {path} failed: {e}")
|
||||
return None
|
||||
|
||||
def login(self):
|
||||
the_url = self.url + "/" + "api/v2/auth/login"
|
||||
data={"username":self.username, "password":self.password}
|
||||
|
||||
resp = self.session.post(the_url, data=data)
|
||||
try:
|
||||
resp = self.session.post(the_url, data=data, timeout=5)
|
||||
resp.raise_for_status()
|
||||
except requests.exceptions.RequestException as e:
|
||||
logging.warning(f"Login failed: {e}")
|
||||
#resp = self.session.post(the_url, data=data)
|
||||
|
||||
def logout(self):
|
||||
the_url = self.url + "/" + "api/v2/auth/logout"
|
||||
resp = self.session.post(the_url)
|
||||
# resp = self.session.post(the_url)
|
||||
try:
|
||||
resp = self.session.post(the_url, timeout=5)
|
||||
resp.raise_for_status()
|
||||
except requests.exceptions.RequestException as e:
|
||||
logging.warning(f"Logout failed: {e}")
|
||||
|
||||
couldnt_connect_text = "Could not connect to qbittorrent server"
|
||||
|
||||
def version(self):
|
||||
the_url = self.url + "/" + "api/v2/app/version"
|
||||
resp = self.session.get(the_url)
|
||||
if resp.status_code != 200:
|
||||
return "Got status" + str(resp.status_code)
|
||||
return resp.text
|
||||
# resp = self.session.get(the_url)
|
||||
# if resp.status_code != 200:
|
||||
# return "Got status" + str(resp.status_code)
|
||||
# return resp.text
|
||||
resp = self.safe_get(the_url)
|
||||
if not resp:
|
||||
return self.couldnt_connect_text
|
||||
else:
|
||||
return resp.text
|
||||
|
||||
def webapiVersion(self):
|
||||
the_url = self.url + "/" + "api/v2/app/webapiVersion"
|
||||
resp = self.session.get(the_url)
|
||||
if resp.status_code != 200:
|
||||
return "Got status" + str(resp.status_code)
|
||||
return resp.text
|
||||
resp = self.safe_get(the_url)
|
||||
if not resp:
|
||||
return self.couldnt_connect_text
|
||||
else:
|
||||
return resp.text
|
||||
# try:
|
||||
# resp = self.session.get(the_url)
|
||||
# resp.raise_for_status()
|
||||
# return resp.text
|
||||
# except requests.exceptions.RequestException as e:
|
||||
# logging.warning(f"Couldn't get version")
|
||||
# if resp.status_code != 200:
|
||||
# return "Got status" + str(resp.status_code)
|
||||
|
||||
def buildInfo(self):
|
||||
the_url = self.url + "/" + "api/v2/app/buildInfo"
|
||||
resp = self.session.get(the_url)
|
||||
if resp.status_code != 200:
|
||||
return "Got status" + str(resp.status_code)
|
||||
resp = self.safe_get(the_url)
|
||||
if not resp:
|
||||
return self.couldnt_connect_text
|
||||
else:
|
||||
return json_to_key_value_string(resp.text)
|
||||
|
||||
return json_to_key_value_string(resp.text)
|
||||
# resp = self.session.get(the_url)
|
||||
# if resp.status_code != 200:
|
||||
# return "Got status" + str(resp.status_code)
|
||||
|
||||
# return json_to_key_value_string(resp.text)
|
||||
|
||||
def torrentList(self, modifier=""):
|
||||
the_url = self.url + "/" + "api/v2/torrents/info"
|
||||
to_ret = "```\n"
|
||||
for f in ["downloading", "completed"]:
|
||||
resp = self.session.post(the_url, data={"filter":f})
|
||||
if resp.status_code != 200:
|
||||
return "Got status" + str(resp.status_code)
|
||||
# resp = self.session.post(the_url, data={"filter":f})
|
||||
# if resp.status_code != 200:
|
||||
# return "Got status" + str(resp.status_code)
|
||||
resp = self.safe_post(the_url, data={"filter":f})
|
||||
if not resp:
|
||||
return self.couldnt_connect_text
|
||||
|
||||
parsed = json.loads(resp.text)
|
||||
to_ret += f.upper() + "\n"
|
||||
|
@ -122,13 +190,17 @@ class QBittorrentAPICaller():
|
|||
to_ret += "```"
|
||||
return to_ret
|
||||
|
||||
# Too lazy to make this safe, hopefully will be fine idk
|
||||
def add(self, url, username, category="unknown"):
|
||||
if not url.startswith("magnet:"):
|
||||
return "Please supply a magnet link (begins with \"magnet:\")"
|
||||
|
||||
the_url = self.url + "/" + "api/v2/torrents/add"
|
||||
|
||||
resp = self.session.post(the_url, data={"urls":url,"category":category,"tags":username})
|
||||
# resp = self.session.post(the_url, data={"urls":url,"category":category,"tags":username})
|
||||
resp = self.safe_post(the_url, data={"urls":url,"category":category,"tags":username})
|
||||
if not resp:
|
||||
return self.couldnt_connect_text
|
||||
if (resp.status_code == 415):
|
||||
return "Torrent file not valid"
|
||||
|
||||
|
@ -138,7 +210,10 @@ class QBittorrentAPICaller():
|
|||
# Make request to torrentlist with particular hash
|
||||
the_url2 = self.url + "/" + "api/v2/torrents/info"
|
||||
time.sleep(5)
|
||||
resp2 = self.session.post(the_url2)
|
||||
# resp2 = self.session.post(the_url2)
|
||||
resp2 = self.safe_post(the_url2)
|
||||
if not resp2:
|
||||
return self.couldnt_connect_text
|
||||
if (resp2.status_code != 200):
|
||||
return "Could not verify if torrent was added"
|
||||
parsed = json.loads(resp2.text)
|
||||
|
@ -153,27 +228,39 @@ class QBittorrentAPICaller():
|
|||
|
||||
def get_search_plugins(self):
|
||||
the_url = self.url + "/" + "api/v2/search/plugins"
|
||||
return self.session.post(the_url)
|
||||
# return self.session.post(the_url)
|
||||
resp = self.safe_post(the_url)
|
||||
return resp if resp else self.couldnt_connect_text
|
||||
|
||||
def search_start(self, searchstring, category="all"):
|
||||
the_url = self.url + "/" + "api/v2/search/start"
|
||||
return self.session.post(the_url, data={"pattern":searchstring, "plugins":"enabled", "category":category})
|
||||
resp = self.safe_post(the_url, data={"pattern":searchstring, "plugins":"enabled", "category":category})
|
||||
return resp if resp else self.couldnt_connect_text
|
||||
# return self.session.post(the_url, data={"pattern":searchstring, "plugins":"enabled", "category":category})
|
||||
|
||||
def search_status(self, search_id):
|
||||
the_url = self.url + "/" + "api/v2/search/status"
|
||||
return self.session.post(the_url, data={"id":search_id})
|
||||
resp = self.safe_post(the_url, data={"id":search_id})
|
||||
return resp if resp else self.couldnt_connect_text
|
||||
# return self.session.post(the_url, data={"id":search_id})
|
||||
|
||||
def search_stop(self, search_id):
|
||||
the_url = self.url + "/" + "api/v2/search/stop"
|
||||
return self.session.post(the_url, data={"id":search_id})
|
||||
resp = self.safe_post(the_url, data={"id":search_id})
|
||||
return resp if resp else self.couldnt_connect_text
|
||||
# return self.session.post(the_url, data={"id":search_id})
|
||||
|
||||
def search_results(self, search_id):
|
||||
the_url = self.url + "/" + "api/v2/search/results"
|
||||
return self.session.post(the_url, data={"id":search_id})
|
||||
resp = self.safe_post(the_url, data={"id":search_id})
|
||||
return resp if resp else self.couldnt_connect_text
|
||||
# return self.session.post(the_url, data={"id":search_id})
|
||||
|
||||
def search_delete(self, search_id):
|
||||
the_url = self.url + "/" + "api/v2/search/delete"
|
||||
return self.session.post(the_url, data={"id":search_id})
|
||||
resp = self.safe_post(the_url, data={"id":search_id})
|
||||
return resp if resp else self.couldnt_connect_text
|
||||
# return self.session.post(the_url, data={"id":search_id})
|
||||
|
||||
|
||||
|
||||
|
@ -198,7 +285,8 @@ class QBBot(slixmpp.ClientXMPP):
|
|||
|
||||
# If you wanted more functionality, here's how to register plugins:
|
||||
# self.register_plugin('xep_0030') # Service Discovery
|
||||
# self.register_plugin('xep_0199') # XMPP Ping
|
||||
self.register_plugin('xep_0199') # XMPP Ping
|
||||
self['xep_0199'].enable_keepalive(interval=60, timeout=10)
|
||||
|
||||
# Here's how to access plugins once you've registered them:
|
||||
# self['xep_0030'].add_feature('echo_demo')
|
||||
|
|
Loading…
Reference in New Issue