client_controller.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. import sys
  2. from getpass import getpass
  3. from inspect import signature
  4. import connection
  5. from run_client import allowed_commands, fake_loading_bar
  6. from connection import client_request
  7. import tabulate
  8. from debug import debug
  9. exiting = False
  10. def login(username=None, password=None):
  11. if connection.session_id is not None:
  12. fake_loading_bar('Signing out', duration=0.7)
  13. connection.session_id = None
  14. if username is None:
  15. username = input('Username: ')
  16. if password is None:
  17. if sys.stdin.isatty():
  18. password = getpass('Password: ')
  19. else:
  20. password = input('Password: ')
  21. fake_loading_bar('Signing in', duration=2.3)
  22. response = client_request('login', {"username": username, "password": password})
  23. success = 'session_id' in response
  24. if success:
  25. connection.session_id = response['session_id']
  26. print('Login successful.')
  27. else:
  28. if 'error_message' in response:
  29. print('Login failed with message:', response['error_message'])
  30. else:
  31. print('Login failed.')
  32. def register(username=None, game_key='', password=None, retype_pw=None):
  33. if connection.session_id is not None:
  34. connection.session_id = None
  35. fake_loading_bar('Signing out', duration=0.7)
  36. if username is None:
  37. username = input('Username: ')
  38. if password is None:
  39. if sys.stdin.isatty():
  40. password = getpass('New password: ')
  41. retype_pw = getpass('Retype password: ')
  42. else:
  43. password = input('New password: ')
  44. retype_pw = input('Retype password: ')
  45. if password != retype_pw:
  46. print('Passwords do not match.')
  47. return
  48. elif retype_pw is None:
  49. if sys.stdin.isatty():
  50. retype_pw = getpass('Retype password: ')
  51. else:
  52. retype_pw = input('Retype password: ')
  53. if password != retype_pw:
  54. print('Passwords do not match.')
  55. return
  56. if not debug:
  57. if game_key == '':
  58. print('Entering a game key will provide you with some starting money and other useful stuff.')
  59. game_key = input('Game key (leave empty if you don\'t have one): ')
  60. fake_loading_bar('Validating Registration', duration=5.2)
  61. if game_key != '':
  62. fake_loading_bar('Validating Game Key', duration=0.4)
  63. response = client_request('register', {"username": username, "password": password, "game_key": game_key})
  64. if 'error_message' in response:
  65. print('Registration failed with message:', response['error_message'])
  66. def cancel_order(order_no=None):
  67. if order_no is None:
  68. order_no = input('Order No.: ')
  69. fake_loading_bar('Validating Request', duration=0.6)
  70. response = client_request('cancel_order', {"session_id": connection.session_id, "order_id": order_no})
  71. if 'error_message' in response:
  72. print('Order cancelling failed with message:', response['error_message'])
  73. def change_pw(password=None, retype_pw=None):
  74. if password != retype_pw:
  75. password = None
  76. if password is None:
  77. if sys.stdin.isatty():
  78. password = getpass('New password: ')
  79. retype_pw = getpass('Retype password: ')
  80. else:
  81. password = input('New password: ')
  82. retype_pw = input('Retype password: ')
  83. if password != retype_pw:
  84. print('Passwords do not match.')
  85. return
  86. elif retype_pw is None:
  87. if sys.stdin.isatty():
  88. retype_pw = getpass('Retype password: ')
  89. else:
  90. retype_pw = input('Retype password: ')
  91. if password != retype_pw:
  92. print('Passwords do not match.')
  93. return
  94. fake_loading_bar('Validating password', duration=1.2)
  95. fake_loading_bar('Changing password', duration=5.2)
  96. response = client_request('change_password', {"session_id": connection.session_id, "password": password})
  97. if 'error_message' in response:
  98. print('Changing password failed with message:', response['error_message'])
  99. fake_loading_bar('Signing out', duration=0.7)
  100. connection.session_id = None
  101. # noinspection PyShadowingBuiltins
  102. def help():
  103. print('Allowed commands:')
  104. command_table = []
  105. for cmd in allowed_commands:
  106. this_module = sys.modules[__name__]
  107. method = getattr(this_module, cmd)
  108. params = signature(method).parameters
  109. command_table.append([cmd] + [p for p in params])
  110. print(_my_tabulate(command_table, tablefmt='pipe', headers=['command',
  111. 'param 1',
  112. 'param 2',
  113. 'param 3',
  114. 'param 4',
  115. 'param 5',
  116. ]))
  117. print('NOTE:')
  118. print(' All parameters for all commands are optional!')
  119. print(' Commands can be combined in one line with ; between them.')
  120. print(' Parameters are separated with any whitespace.')
  121. print(' Use . as a decimal separator.')
  122. print(' Use 0/1 for boolean parameters (other strings might work).')
  123. def _my_tabulate(data, **params):
  124. if data == [] and 'headers' in params:
  125. data = [(None for _ in params['headers'])]
  126. tabulate.MIN_PADDING = 0
  127. return tabulate.tabulate(data, **params)
  128. def depot():
  129. fake_loading_bar('Loading data', duration=1.3)
  130. response = client_request('depot', {"session_id": connection.session_id})
  131. success = 'data' in response and 'own_wealth' in response
  132. if success:
  133. data = response['data']
  134. for row in data:
  135. row.append(row[1] * row[2])
  136. print(_my_tabulate(data,
  137. headers=['Object', 'Amount', 'Course', 'Bid', 'Ask', 'Est. Value'],
  138. tablefmt="pipe"))
  139. print('This corresponds to a wealth of roughly', response['own_wealth'])
  140. else:
  141. if 'error_message' in response:
  142. print('Depot access failed with message:', response['error_message'])
  143. else:
  144. print('Depot access failed.')
  145. def leaderboard():
  146. fake_loading_bar('Loading data', duration=1.3)
  147. response = client_request('leaderboard', {})
  148. success = 'data' in response
  149. if success:
  150. print(_my_tabulate(response['data'], headers=['Trader', 'Wealth'], tablefmt="pipe"))
  151. # print('Remember that the goal is to be as rich as possible, not to be richer than other traders!')
  152. else:
  153. if 'error_message' in response:
  154. print('Leaderboard access failed with message:', response['error_message'])
  155. else:
  156. print('Leaderboard access failed.')
  157. def activate_key(key=''):
  158. if key == '':
  159. print('Entering a game key may get you some money or other useful stuff.')
  160. key = input('Key: ')
  161. if key == '':
  162. print('Invalid key.')
  163. fake_loading_bar('Validating Key', duration=0.4)
  164. response = client_request('activate_key', {"session_id": connection.session_id, 'key': key})
  165. if 'error_message' in response:
  166. print('Key activation failed with message:', response['error_message'])
  167. def yn_dialog(msg):
  168. while True:
  169. result = input(msg + ' [y/n]: ')
  170. if result == 'y':
  171. return True
  172. if result == 'n':
  173. return False
  174. print('Type in \'y\' or \'n\'!')
  175. def buy(obj_name=None, amount=None, limit='', stop_loss='', expiry=None):
  176. if obj_name is None: # TODO list some available objects
  177. obj_name = input('Name of object to buy: ')
  178. if amount is None:
  179. amount = input('Amount: ')
  180. if limit == '':
  181. set_limit = yn_dialog('Do you want to place a limit?')
  182. if set_limit:
  183. limit = input('Limit: ')
  184. stop_loss = yn_dialog('Is this a stop-loss limit?')
  185. else:
  186. limit = None
  187. stop_loss = None
  188. if limit != '' and stop_loss == '':
  189. stop_loss = yn_dialog('Is this a stop-loss limit?')
  190. if limit is not None and \
  191. float(limit) <= 0 and \
  192. input(input('Are you sure you want to use such a low limit (limit=' + str(
  193. limit) + ')? (type in "yes" or something else):') != 'yes'):
  194. print('Order was not placed.')
  195. return
  196. if expiry is None:
  197. expiry = input('Time until order expires (minutes, default 43200):')
  198. if expiry == '':
  199. expiry = 43200
  200. try:
  201. expiry = float(expiry)
  202. except ValueError:
  203. print('Invalid expiration time.')
  204. return
  205. fake_loading_bar('Loading Data', duration=1.3)
  206. response = client_request('order', {"buy": True,
  207. "session_id": connection.session_id,
  208. "amount": amount,
  209. "ownable": obj_name,
  210. "limit": limit,
  211. "stop_loss": stop_loss,
  212. "time_until_expiration": expiry})
  213. if 'error_message' in response:
  214. print('Order placement failed with message:', response['error_message'])
  215. else:
  216. print('You might want to use the `transactions` or `depot` commands',
  217. 'to see if the order has been executed already.')
  218. def sell(obj_name=None, amount=None, limit='', stop_loss='', expiry=None):
  219. if obj_name is None: # TODO list some available objects
  220. obj_name = input('Name of object to sell: ')
  221. if amount is None:
  222. amount = input('Amount: ')
  223. if limit == '':
  224. set_limit = yn_dialog('Do you want to place a limit?')
  225. if set_limit:
  226. limit = input('Limit: ')
  227. stop_loss = yn_dialog('Is this a stop-loss limit?')
  228. else:
  229. limit = None
  230. stop_loss = None
  231. if limit != '' and stop_loss == '':
  232. stop_loss = yn_dialog('Is this a stop-loss limit?')
  233. if limit is not None and \
  234. float(limit) <= 0 and \
  235. input('Are you sure you want to use such a low limit (limit=' + str(
  236. limit) + ')? (type in "yes" or something else):') != 'yes':
  237. print('Order was not placed.')
  238. return
  239. if expiry is None:
  240. expiry = input('Time until order expires (minutes, default 43200):')
  241. if expiry == '':
  242. expiry = 43200
  243. try:
  244. expiry = float(expiry)
  245. except ValueError:
  246. print('Invalid expiration time.')
  247. return
  248. fake_loading_bar('Loading Data', duration=1.3)
  249. response = client_request('order', {"buy": False,
  250. "session_id": connection.session_id,
  251. "amount": amount,
  252. "ownable": obj_name,
  253. "limit": limit,
  254. "stop_loss": stop_loss,
  255. "time_until_expiration": expiry})
  256. if 'error_message' in response:
  257. print('Order placement failed with message:', response['error_message'])
  258. else:
  259. print('You might want to use the `transactions` or `depot` commands',
  260. 'to see if the order has been executed already.')
  261. def orders():
  262. fake_loading_bar('Loading Data', duration=0.9)
  263. response = client_request('orders', {"session_id": connection.session_id})
  264. success = 'data' in response
  265. if success:
  266. print(_my_tabulate(response['data'],
  267. headers=['Buy?', 'Name', 'Size', 'Limit', 'stop-loss', 'Expires', 'No.'],
  268. tablefmt="pipe"))
  269. else:
  270. if 'error_message' in response:
  271. print('Order access failed with message:', response['error_message'])
  272. else:
  273. print('Order access failed.')
  274. def orders_on(obj_name=None):
  275. if obj_name is None: # TODO list some available objects
  276. obj_name = input('Name of object to check: ')
  277. fake_loading_bar('Loading Data', duration=2.3)
  278. response = client_request('orders_on', {"session_id": connection.session_id, "ownable": obj_name})
  279. success = 'data' in response
  280. if success:
  281. print(_my_tabulate(response['data'],
  282. headers=['My', 'Buy?', 'Name', 'Size', 'Limit', 'Expires', 'No.'],
  283. tablefmt="pipe"))
  284. else:
  285. if 'error_message' in response:
  286. print('Order access failed with message:', response['error_message'])
  287. else:
  288. print('Order access failed.')
  289. def gift(username=None, obj_name=None, amount=None):
  290. if username is None:
  291. username = input('Username of recipient: ')
  292. if obj_name is None:
  293. obj_name = input('Name of object to give: ')
  294. if amount is None:
  295. amount = input('How many?: ')
  296. fake_loading_bar('Sending Gift', duration=4.2)
  297. response = client_request('gift',
  298. {"session_id": connection.session_id,
  299. "username": username,
  300. "object_name": obj_name,
  301. "amount": amount})
  302. if 'error_message' in response:
  303. print('Order access failed with message:', response['error_message'])
  304. elif 'message' in response:
  305. print(response['message'])
  306. def news():
  307. fake_loading_bar('Loading Data', duration=0.76)
  308. response = client_request('news', {})
  309. success = 'data' in response
  310. if success:
  311. print(_my_tabulate(response['data'],
  312. headers=['Date', 'Title'],
  313. tablefmt="pipe"))
  314. else:
  315. if 'error_message' in response:
  316. print('News access failed with message:', response['error_message'])
  317. else:
  318. print('News access failed.')
  319. def tradables():
  320. fake_loading_bar('Loading Data', duration=12.4)
  321. response = client_request('tradables', {})
  322. success = 'data' in response
  323. if success:
  324. print(_my_tabulate(response['data'],
  325. headers=['Name', 'Course', 'Market Cap.'],
  326. tablefmt="pipe"))
  327. world_wealth = 0
  328. for row in response['data']:
  329. if row[2] is not None:
  330. world_wealth += row[2]
  331. print('Estimated worldwide wealth:', world_wealth)
  332. else:
  333. if 'error_message' in response:
  334. print('Data access failed with message:', response['error_message'])
  335. else:
  336. print('Data access failed.')
  337. def transactions(obj_name=None, limit=5):
  338. limit = float(limit)
  339. if obj_name is None: # TODO list some available objects
  340. obj_name = input('Name of object to check: ')
  341. fake_loading_bar('Loading Data', duration=1.3)
  342. response = client_request('transactions', {"session_id": connection.session_id,
  343. "ownable": obj_name,
  344. "limit": limit})
  345. success = 'data' in response
  346. if success:
  347. print(_my_tabulate(response['data'],
  348. headers=['Time', 'Volume', 'Price'],
  349. tablefmt="pipe"))
  350. else:
  351. if 'error_message' in response:
  352. print('Transactions access failed with message:', response['error_message'])
  353. else:
  354. print('Transactions access failed.')
  355. # noinspection PyShadowingBuiltins
  356. def exit():
  357. global exiting
  358. exiting = True