client_controller.py 15 KB

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