From 010ff377e5b4af772f2dbe2736608cee4f04f58a Mon Sep 17 00:00:00 2001 From: Anna Wiggins Date: Thu, 21 Jan 2016 11:11:53 -0500 Subject: [PATCH] Initial commit. This is based on code from ed_tools and fvbot. --- Readme.md | 21 ++++++++ __init__.py | 0 inara.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 Readme.md create mode 100644 __init__.py create mode 100644 inara.py diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..f835289 --- /dev/null +++ b/Readme.md @@ -0,0 +1,21 @@ +# inara.py + +This is a simple python library that is used to retrieve and store data to inara.py. + +It subclasses requests_cache.core.CachedSession to provide a specialized HTTP session to talk to inara. +Usage is simple: + + from inara.inara import InaraSession + + session = InaraSession(inara_username, inara_password) + session.update_location('Chona') + session.update_credits(1000000000) + info = session.get_cmdr_info() + pprint(info) + + +If the logged-in user is a member of a Wing, you can get information about wing-mates like so: + + info = session.get_cmdr_info(wing_id, cmdr_id) + +where the 'id's are the numeric identifiers visible in inara's URLs. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/inara.py b/inara.py new file mode 100644 index 0000000..0831024 --- /dev/null +++ b/inara.py @@ -0,0 +1,145 @@ +""" +A wrapper around the requests library to retrieve and update various information +about a commander from inara.cz +""" + +from bs4 import BeautifulSoup +import re +import requests_cache +from requests_cache.core import CachedSession + +BASE_URL = "http://inara.cz/" +CMDR_URL = BASE_URL + 'cmdr/' + +# Some fun exceptions to raise! +class ServerError(Exception): + pass + +class CredentialsError(Exception): + pass + +class LoggingInException(Exception): + pass + +class CmdrNotFoundException(Exception): + pass + + +class InaraSession(CachedSession): + def __init__(self, username, password): + CachedSession.__init__(self, + cache_name='inara', + backend='memory', + expire_after=600.0, + old_data_on_error=True) + + self.username = username + self.password = password + self.inara_login() + + def inara_login(self): + if (not self.username or not self.password): + raise CredentialsError() + + data = { + "loginid": self.username, + "loginpass": self.password, + "formact": "ENT_LOGIN", + "location": "intro" + } + + r = self.post(BASE_URL, data=data) + r.raise_for_status() + + def _inara_is_logged_in(self, soup): + logout_link = soup.find(href=re.compile('ENT_LOGOUT')) + return logout_link is not None + + def update_credits(self, credits): + soup = session.get_soup(CMDR_URL) + if not self._inara_is_logged_in(soup): + return False + + oass = int(soup.find(id='oassinput')['value']) + data = { + "location": "cmdr", + "formact": "USER_CREDITS_SET", + "playercredits": credits, + "playercreditsassets": credits + oass, + "oass": oass, + } + r = self.post(CMDR_URL, data=data) + r.raise_for_status() + return True + + def update_location(self, location): + data = { + 'formact': 'USER_LOCATION_SET', + 'playercurloc': location + } + r = self.post(CMDR_URL, data=data) + r.raise_for_status() + + def get_cmdr_info(wing_id=None, cmdr_id=None): + result = {} + + if wing_id is not None and cmdr_id is not None: + wing_soup = session.get_soup("%s/wing/%s" % (BASE_URL, wing_id)) + result['rank'] = _get_rank(wing_soup, cmdr_id) + result['location'] = _get_location(wing_soup, cmdr_id) + + if cmdr_id is not None: + cmdr_soup = session.get_soup("%s/cmdr/%s" % (BASE_URL, cmdr_id)) + else: + cmdr_soup = session.get_soup(CMDR_URL) + + result['balance'] = _get_cmdr_balance(cmdr_soup) + result['assets'] = _get_cmdr_assets(cmdr_soup) + + return result + + def get_soup(self, url): + r = self.get(url) + r.raise_for_status() + soup = BeautifulSoup(r.text, 'html.parser') + + if not self._inara_is_logged_in(soup): + self.inara_login() + # invalidate the cache entry, since we only want logged-in data + self.cache.delete_url(url) + raise LoggingInException() + + return soup + + def _get_cmdr_row(soup, cmdr_id): + link = soup.find(attrs={'class': 'subtable'}).find( + href=re.compile('/cmdr/' + cmdr_id)) + + for parent in link.parents: + if parent.name == 'tr': + return parent + + raise CmdrNotFoundException() + + def _get_rank(soup, cmdr_id): + row = _get_cmdr_row(soup, cmdr_id) + return row.td.img['title'] + + def _get_location(soup, cmdr_id): + row = _get_cmdr_row(soup, cmdr_id) + + location_link = row.find(href=re.compile('market')) + if not location_link or len(location_link.contents) == 0: + return "Unknown" + else: + return location_link.contents[0] + + def _get_cmdr_balance(soup): + title_text = soup.find(text="Credit Balance") + br = title_text.parent.next_sibling + return br.contents[0] + + def _get_cmdr_assets(soup): + title_text = soup.find(text="Overall assets") + br = title_text.parent.next_sibling + return br.contents[0]