client.py 11 KB

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