client.py 11 KB

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