client.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. """
  2. Client module
  3. """
  4. import logging
  5. import re
  6. import time
  7. from datetime import datetime
  8. import json
  9. import requests
  10. from webbot.webbot import Browser
  11. logging.basicConfig(
  12. format='%(name)s - %(levelname)s - %(message)s',
  13. level=logging.INFO
  14. )
  15. LOGGER = logging.getLogger(__name__)
  16. class RRClientException(Exception):
  17. """RR exception"""
  18. def __init__(self, *args, **kwargs):
  19. Exception.__init__(self, *args, **kwargs)
  20. LOGGER.warning('RRClientException')
  21. class SessionExpireException(Exception):
  22. """Raise when session has expired"""
  23. def __init__(self, *args, **kwargs):
  24. Exception.__init__(self, *args, **kwargs)
  25. LOGGER.warning('Session has expired')
  26. class NoLogginException(Exception):
  27. """Raise exception when client isn't logged in"""
  28. def __init__(self, *args, **kwargs):
  29. Exception.__init__(self, *args, **kwargs)
  30. LOGGER.warning('Session has expired')
  31. class NoPHPsessidException(Exception):
  32. """Raise exception when cookie isn't found"""
  33. def __init__(self, *args, **kwargs):
  34. Exception.__init__(self, *args, **kwargs)
  35. LOGGER.warning('No phpsessid found')
  36. def session_handler(func):
  37. """Handle expired sessions"""
  38. def wrapper(*args, **kwargs):
  39. instance = args[0]
  40. return try_run(instance, func, *args, **kwargs)
  41. def try_run(instance, func, *args, **kwargs):
  42. try:
  43. return func(*args, **kwargs)
  44. except (SessionExpireException, ConnectionError, ConnectionResetError):
  45. instance.remove_cookie(instance.username)
  46. instance.login()
  47. return try_run(instance, func, *args, **kwargs)
  48. except NoLogginException:
  49. instance.login()
  50. return try_run(instance, func, *args, **kwargs)
  51. return wrapper
  52. class Client:
  53. """class for RR client"""
  54. resource_id = {
  55. 'oil': 3,
  56. 'ore': 4,
  57. 'uranium': 11,
  58. 'diamond': 15,
  59. 'liquid oxygen': 21,
  60. 'helium-3': 24,
  61. 'antirad': 13,
  62. 'energy drink': 17,
  63. 'spacerockets': 20,
  64. 'tanks': 2,
  65. 'aircrafts': 1,
  66. 'missiles': 14,
  67. 'bombers': 16,
  68. 'battleships': 18,
  69. 'moon tanks': 22,
  70. 'space stations': 23
  71. }
  72. cookie = None
  73. var_c = None
  74. login_method = None
  75. username = None
  76. password = None
  77. session = None
  78. def __init__(self, show_window=False):
  79. self.show_window = show_window
  80. LOGGER.info('Init client, show window %s', self.show_window)
  81. def set_credentials(self, credentials):
  82. """Set the credentials"""
  83. LOGGER.info('Setting "%s" credentials', credentials['username'])
  84. self.login_method = credentials['login_method']
  85. self.username = credentials['username']
  86. self.password = credentials['password']
  87. def login(self):
  88. """Login user if needed"""
  89. cookie = self.get_cookie(self.username)
  90. if cookie is None:
  91. LOGGER.info('Client login "%s" username "%s"', self.login_method, self.username)
  92. if self.login_method not in ["g", "google", "v", "vk", "f", "facebook"]:
  93. raise RRClientException("Not a valid login method.")
  94. auth_text = requests.get("http://rivalregions.com").text
  95. web = Browser(showWindow=self.show_window)
  96. method_dict = {
  97. 'g': self.login_google,
  98. 'google': self.login_google,
  99. 'v': self.login_vk,
  100. 'vk': self.login_vk,
  101. 'f': self.login_facebook,
  102. 'facebook': self.login_facebook,
  103. }
  104. if self.login_method in method_dict:
  105. web = method_dict[self.login_method](web, auth_text)
  106. else:
  107. LOGGER.info('Invallid loggin method "%s"', self.login_method)
  108. exit()
  109. LOGGER.info('Get cookie')
  110. phpsessid = web.get_cookie('PHPSESSID')
  111. if phpsessid:
  112. cookie = self.create_cookie(
  113. phpsessid.get('expiry', None),
  114. phpsessid.get('value', None)
  115. )
  116. self.write_cookie(self.username, cookie)
  117. else:
  118. raise NoPHPsessidException()
  119. LOGGER.info('closing login tab')
  120. web.close_current_tab()
  121. self.cookie = cookie
  122. self.session = requests.Session()
  123. self.session.headers.update({'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)' \
  124. 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'})
  125. self.session.cookies.set(**cookie)
  126. LOGGER.info('set the var_c')
  127. response = self.session.get('http://rivalregions.com/#overview')
  128. lines = response.text.split("\n")
  129. for line in lines:
  130. if re.match("(.*)var c_html(.*)", line):
  131. var_c = line.split("'")[-2]
  132. LOGGER.info('var_c: %s', var_c)
  133. self.var_c = line.split("'")[-2]
  134. def login_google(self, web, auth_text):
  135. """login using Google"""
  136. LOGGER.info('Login method Google')
  137. auth_text1 = auth_text.split('\t<a href="')
  138. auth_text2 = auth_text1[1].split('" class="sa')
  139. web.go_to(auth_text2[0])
  140. LOGGER.info('Typing in username')
  141. web.type(self.username, into='Email')
  142. web.click('Volgende')
  143. LOGGER.info('Typing in password')
  144. web.type(self.password, css_selector="input")
  145. web.click('Inloggen')
  146. web.click(css_selector=".sa_sn.float_left.imp.gogo")
  147. time.sleep(1)
  148. return web
  149. def login_vk(self, web, auth_text):
  150. """login using VK"""
  151. LOGGER.info('Login method VK')
  152. auth_text1 = auth_text.split("(\'.vkvk\').attr(\'url\', \'")
  153. auth_text2 = auth_text1[1].split('&response')
  154. web.go_to(auth_text2[0])
  155. web.type(self.username, into='email')
  156. web.type(self.password, xpath="/html/body/div/div/div/div[2]/form/div/div/input[7]")
  157. web.click('Log in')
  158. return web
  159. def login_facebook(self, web, auth_text):
  160. """login using Facebook"""
  161. LOGGER.info('Login method Facebook')
  162. auth_text1 = auth_text.split('">\r\n\t\t\t\t<div class="sa_sn imp float_left" ')
  163. auth_text2 = auth_text1[0].split('200px;"><a class="sa_link" href="')
  164. url = auth_text2[1]
  165. web.go_to(url)
  166. web.type(self.username, into='Email')
  167. web.type(self.password, into='Password')
  168. web.click('Log In')
  169. time.sleep(5)
  170. web.click(css_selector='.sa_sn.imp.float_left')
  171. return web
  172. @classmethod
  173. def write_cookie(cls, username, cookie):
  174. """Write cookie to file"""
  175. LOGGER.info('Saving cookie for "%s"', username)
  176. cookies = None
  177. try:
  178. with open('cookies.json', 'r') as cookies_file:
  179. cookies = json.load(cookies_file)
  180. except FileNotFoundError:
  181. cookies = {}
  182. cookies[username] = {
  183. 'expires': cookie['expires'],
  184. 'value': cookie['value'],
  185. }
  186. with open('cookies.json', 'w+') as cookies_file:
  187. json.dump(cookies, cookies_file)
  188. LOGGER.info('Saved cookie for "%s"', username)
  189. @classmethod
  190. def get_cookie(cls, username):
  191. """Read cookies for username"""
  192. LOGGER.info('Read cookie for "%s"', username)
  193. try:
  194. with open('cookies.json', 'r') as cookies_file:
  195. cookies = json.load(cookies_file)
  196. for cookie_username, cookie in cookies.items():
  197. if cookie_username == username:
  198. LOGGER.info('Found cookie')
  199. expires = datetime.fromtimestamp(int(cookie['expires']))
  200. if datetime.now() >= expires:
  201. LOGGER.info('Cookie is expired')
  202. return None
  203. cookie = cls.create_cookie(
  204. cookie['expires'],
  205. cookie['value'],
  206. )
  207. return cookie
  208. except FileNotFoundError:
  209. pass
  210. return None
  211. @classmethod
  212. def remove_cookie(cls, username):
  213. """Remove cookie from storage"""
  214. LOGGER.info('Removing cookie for "%s"', username)
  215. cookies = None
  216. try:
  217. with open('cookies.json', 'r') as cookies_file:
  218. cookies = json.load(cookies_file)
  219. except FileNotFoundError:
  220. cookies = {}
  221. cookies.pop(username, None)
  222. with open('cookies.json', 'w+') as cookies_file:
  223. json.dump(cookies, cookies_file)
  224. LOGGER.info('Removed cookie for "%s"', username)
  225. @staticmethod
  226. def create_cookie(expires, value):
  227. """Create cookie"""
  228. return {
  229. 'domain': 'rivalregions.com',
  230. 'name': 'PHPSESSID',
  231. 'path': '/',
  232. 'secure': False,
  233. 'expires': expires,
  234. 'value': value,
  235. }
  236. @session_handler
  237. def get(self, path, add_var_c=False):
  238. """Send get request to Rival Regions"""
  239. if path[0] == '/':
  240. path = path[1:]
  241. params = {}
  242. if add_var_c:
  243. params['c'] = self.var_c
  244. if self.session:
  245. response = self.session.get(
  246. url='http://rivalregions.com/{}'.format(path),
  247. params=params
  248. )
  249. if "Session expired, please, reload the page" in response.text:
  250. raise SessionExpireException()
  251. else:
  252. raise NoLogginException()
  253. return response.text
  254. @session_handler
  255. def post(self, path, data=None):
  256. """Send post request to Rival Regions"""
  257. if path[0] == '/':
  258. path = path[1:]
  259. data['c'] = self.var_c
  260. if self.session:
  261. response = self.session.post(
  262. "http://rivalregions.com/{}".format(path),
  263. data=data
  264. )
  265. if "Session expired, please, reload the page" in response.text:
  266. raise SessionExpireException()
  267. else:
  268. raise NoLogginException()
  269. return response.text
  270. @session_handler
  271. def send_chat(self, language, message):
  272. """send chat message"""
  273. if self.session:
  274. response = self.session.get("http://rivalregions.com/#overview")
  275. if "Session expired, please, reload the page" in response.text:
  276. raise SessionExpireException()
  277. web = Browser(showWindow=self.show_window)
  278. web.go_to('http://rivalregions.com/')
  279. web.add_cookie(self.get_cookie(self.username))
  280. web.go_to('http://rivalregions.com/#slide/chat/lang_{}'.format(language))
  281. web.refresh()
  282. time.sleep(2)
  283. web.type(message, id='message')
  284. web.click(id='chat_send')
  285. web.close_current_tab()
  286. else:
  287. raise NoLogginException()