· 9 years ago · Jun 07, 2017, 09:50 PM
1# Developed by Redjumpman for Redbot.
2# Inspired by Spriter's work on a modded economy.
3# Creates 1 json file, 1 log file per 10mb, and requires tabulate.
4
5# STD Library
6import asyncio
7import logging
8import logging.handlers
9import os
10import random
11from copy import deepcopy
12from fractions import Fraction
13from operator import itemgetter
14from datetime import datetime, timedelta
15
16# Discord imports
17import discord
18from .utils import checks
19from .utils.dataIO import dataIO
20from discord.ext import commands
21from __main__ import send_cmd_help
22
23# Third Party Libraries
24try:
25 from tabulate import tabulate
26 tabulateAvailable = True
27except ImportError:
28 tabulateAvailable = False
29
30
31try:
32 from dateutil import parser
33 dateutilAvailable = True
34except ImportError:
35 dateutilAvailable = False
36
37
38# Default settings that is created when a server begin's using Casino
39server_default = {"System Config": {"Casino Name": "Redjumpman", "Casino Open": True,
40 "Chip Name": "Jump", "Chip Rate": 1, "Default Payday": 100,
41 "Payday Timer": 1200, "Threshold Switch": False,
42 "Threshold": 10000, "Credit Rate": 1, "Transfer Limit": 1000,
43 "Transfer Cooldown": 30, "Version": 1.710
44 },
45 "Memberships": {},
46 "Players": {},
47 "Games": {"Dice": {"Multiplier": 2.2, "Cooldown": 5, "Open": True, "Min": 50,
48 "Max": 500, "Access Level": 0},
49 "Coin": {"Multiplier": 1.5, "Cooldown": 5, "Open": True, "Min": 10,
50 "Max": 10, "Access Level": 0},
51 "Cups": {"Multiplier": 2.2, "Cooldown": 5, "Open": True, "Min": 50,
52 "Max": 500, "Access Level": 0},
53 "Blackjack": {"Multiplier": 2.2, "Cooldown": 5, "Open": True,
54 "Min": 50, "Max": 500, "Access Level": 0},
55 "Allin": {"Multiplier": 2.2, "Cooldown": 86400, "Open": True,
56 "Access Level": 0},
57 "Hi-Lo": {"Multiplier": 1.5, "Cooldown": 5, "Open": True,
58 "Min": 20, "Max": 20, "Access Level": 0},
59 "War": {"Multiplier": 1.5, "Cooldown": 5, "Open": True,
60 "Min": 20, "Max": 20, "Access Level": 0},
61 }
62 }
63
64new_user = {"Chips": 100,
65 "Membership": None,
66 "Pending": 0,
67 "Played": {"Dice Played": 0, "Cups Played": 0, "BJ Played": 0, "Coin Played": 0,
68 "Allin Played": 0, "Hi-Lo Played": 0, "War Played": 0},
69 "Won": {"Dice Won": 0, "Cups Won": 0, "BJ Won": 0, "Coin Won": 0, "Allin Won": 0,
70 "Hi-Lo Won": 0, "War Won": 0},
71 "Cooldowns": {"Dice": 0, "Cups": 0, "Coin": 0, "Allin": 0, "Hi-Lo": 0, "War": 0,
72 "Blackjack": 0, "Payday": 0, "Transfer": 0}
73 }
74
75# Deck used for blackjack, and a dictionary to correspond values of the cards.
76main_deck = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King', 'Ace'] * 4
77
78
79bj_values = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 'Jack': 10,
80 'Queen': 10, 'King': 10}
81
82war_values = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 'Jack': 11,
83 'Queen': 12, 'King': 13, 'Ace': 14}
84
85hilo_data = {"Played": {"Hi-Lo Played": 0}, "Won": {"Hi-Lo Won": 0}, "Cooldown": {"Hi-Lo": 0}}
86
87war_data = {"Played": {"War Played": 0}, "Won": {"War Won": 0}, "Cooldown": {"War": 0}}
88
89c_games = ["Blackjack", "Coin", "Allin", "Cups", "Dice", "Hi-Lo", "War"]
90
91
92class CasinoError(Exception):
93 pass
94
95
96class UserAlreadyRegistered(CasinoError):
97 pass
98
99
100class UserNotRegistered(CasinoError):
101 pass
102
103
104class InsufficientChips(CasinoError):
105 pass
106
107
108class NegativeChips(CasinoError):
109 pass
110
111
112class SameSenderAndReceiver(CasinoError):
113 pass
114
115
116class BotNotAUser(CasinoError):
117 pass
118
119
120class CasinoBank:
121 """Holds all of the Casino hooks for integration"""
122
123 def __init__(self, bot, file_path):
124 self.memberships = dataIO.load_json(file_path)
125 self.bot = bot
126 self.patch = 1.710
127
128 def create_account(self, user):
129 server = user.server
130 path = self.check_server_settings(server)
131
132 if user.id not in path["Players"]:
133 default_user = deepcopy(new_user)
134 path["Players"][user.id] = default_user
135 path["Players"][user.id]["Name"] = user.name
136 self.save_system()
137 membership = path["Players"][user.id]
138 return membership
139 else:
140 raise UserAlreadyRegistered()
141
142 def membership_exists(self, user):
143 try:
144 self.get_membership(user)
145 except UserNotRegistered:
146 return False
147 return True
148
149 def chip_balance(self, user):
150 account = self.get_membership(user)
151 return account["Chips"]
152
153 def can_bet(self, user, amount):
154 account = self.get_membership(user)
155 if account["Chips"] >= amount:
156 return True
157 else:
158 raise InsufficientChips()
159
160 def set_chips(self, user, amount):
161 if amount < 0:
162 raise NegativeChips()
163 account = self.get_membership(user)
164 account["Chips"] = amount
165 self.save_system()
166
167 def deposit_chips(self, user, amount):
168 amount = int(round(amount))
169 if amount < 0:
170 raise NegativeChips()
171 account = self.get_membership(user)
172 account["Chips"] += amount
173 self.save_system()
174
175 def withdraw_chips(self, user, amount):
176 if amount < 0:
177 raise NegativeChips()
178
179 account = self.get_membership(user)
180 if account["Chips"] >= amount:
181 account["Chips"] -= amount
182 self.save_system()
183 else:
184 raise InsufficientChips()
185
186 def transfer_chips(self, sender, receiver, amount):
187 if amount < 0:
188 raise NegativeChips()
189
190 if sender is receiver:
191 raise SameSenderAndReceiver()
192
193 if receiver == self.bot.user:
194 raise BotNotAUser()
195
196 if self.membership_exists(sender) and self.membership_exists(receiver):
197 sender_acc = self.get_membership(sender)
198 if sender_acc["Chips"] < amount:
199 raise InsufficientChips()
200 self.withdraw_chips(sender, amount)
201 self.deposit_chips(receiver, amount)
202 else:
203 raise UserNotRegistered()
204
205 def wipe_caisno_server(self, server):
206 self.memberships["Servers"].pop(server.id)
207 self.save_system()
208
209 def wipe_casino_members(self, server):
210 self.memberships["Servers"][server.id]["Players"] = {}
211 self.save_system()
212
213 def remove_membership(self, user):
214 server = user.server
215 self.memberships["Servers"][server.id]["Players"].pop(user.id)
216 self.save_system()
217
218 def get_membership(self, user):
219 server = user.server
220 path = self.check_server_settings(server)
221
222 try:
223 return path["Players"][user.id]
224 except KeyError:
225 raise UserNotRegistered()
226
227 def get_all_servers(self):
228 return self.memberships["Servers"]
229
230 def get_casino_server(self, server):
231 return self.memberships["Servers"][server.id]
232
233 def get_server_memberships(self, server):
234 if server.id in self.memberships["Servers"]:
235 members = self.memberships["Servers"][server.id]["Players"]
236 return members
237 else:
238 return []
239
240 def save_system(self):
241 dataIO.save_json("data/JumperCogs/casino/casino.json", self.memberships)
242
243 def check_server_settings(self, server):
244 if server.id not in self.memberships["Servers"]:
245 self.memberships["Servers"][server.id] = server_default
246 self.save_system()
247 print("Creating default casino settings for Server: {}".format(server.name))
248 path = self.memberships["Servers"][server.id]
249 return path
250 else: # NOTE Will be moved to a cmd in future patch. Used to update JSON from older version
251 path = self.memberships["Servers"][server.id]
252
253 try:
254 if path["System Config"]["Version"] < self.patch:
255 self.casino_patcher(path)
256 path["System Config"]["Version"] = self.patch
257 except KeyError:
258 path["System Config"]["Version"] = self.patch
259 self.casino_patcher(path)
260
261 return path
262
263 def casino_patcher(self, path):
264
265 if path["System Config"]["Version"] < 1.581:
266 self.DICT_PATCH_1581(path)
267
268 if path["System Config"]["Version"] < 1.692:
269 self.DICT_PATCH_1692(path)
270
271 if path["System Config"]["Version"] < 1.694:
272 self.DICT_PATCH_1694(path)
273
274 if path["System Config"]["Version"] < 1.705:
275 self.DICT_PATCH_16(path)
276
277 if path["System Config"]["Version"] < 1.706:
278 self.DICT_PATCH_1694(path) # Fix for unix cd update failure
279
280 # Save changes and return updated dictionary.
281 self.save_system()
282
283 def name_fix(self):
284 servers = self.get_all_servers()
285 removal = []
286 for server in servers:
287 try:
288 server_obj = self.bot.get_server(server)
289 self.name_bug_fix(server_obj)
290 except AttributeError:
291 removal.append(server)
292 logger.info("WIPED SERVER: {} FROM CASINO".format(server))
293 print("Removed server ID: {} from the list of servers, because the bot is no "
294 "longer on that server.".format(server))
295 for x in removal:
296 self.memberships["Servers"].pop(x)
297 self.save_system()
298
299 def name_bug_fix(self, server):
300 players = self.get_server_memberships(server)
301 for player in players:
302 mobj = server.get_member(player)
303 try:
304 if players[player]["Name"] != mobj.name:
305 players[player]["Name"] = mobj.name
306 except AttributeError:
307 print("Error updating name! {} is no longer on this server.".format(player))
308
309 def DICT_PATCH_GAMES(self, path):
310
311 # Check if player data has the war game, and if not add it.
312 for player in path["Players"]:
313 if "War Played" not in path["Players"][player]["Played"]:
314 path["Players"][player]["Played"]["War Played"] = 0
315 if "War Won" not in path["Players"][player]["Won"]:
316 path["Players"][player]["Won"]["War Won"] = 0
317 if "War" not in path["Players"][player]["Cooldowns"]:
318 path["Players"][player]["Cooldowns"]["War"] = 0
319 self.save_system()
320
321 def DICT_PATCH_1694(self, path):
322 """This patch aimed at converting the old cooldown times into unix time."""
323 print("DICT_Patch_1694 ran")
324 for player in path["Players"]:
325 try:
326 for cooldown in path["Players"][player]["Cooldowns"]:
327 s = path["Players"][player]["Cooldowns"][cooldown]
328 convert = datetime.utcnow() - timedelta(seconds=s)
329 path["Players"][player]["Cooldowns"][cooldown] = convert.isoformat()
330 except TypeError:
331 pass
332 self.save_system()
333
334 def DICT_PATCH_1692(self, path):
335 """Issues with memberships storing keys that are lower case.
336 Fire bombing everyones memberships so I don't have nightmares.
337 """
338 path["Memberships"] = {}
339 self.save_system()
340
341 def DICT_PATCH_16(self, path):
342 if "Transfer Limit" not in path["System Config"]:
343 transfer_dict = {"Transfer Limit": 1000, "Transfer Cooldown": 30}
344 path["System Config"].update(transfer_dict)
345
346 for x in path["Players"]:
347 if "Transfer" not in path["Players"][x]["Cooldowns"]:
348 path["Players"][x]["Cooldowns"]["Transfer"] = 0
349 self.save_system()
350
351 def DICT_PATCH_1581(self, path):
352 # Fixes the name bug for older versions
353 self.name_fix()
354 # Add hi-lo to older versions
355 if "Hi-Lo" not in path["Games"]:
356 hl = {"Hi-Lo": {"Multiplier": 1.5, "Cooldown": 0, "Open": True, "Min": 20,
357 "Max": 20}}
358 path["Games"].update(hl)
359
360 # Add war to older versions
361 if "War" not in path["Games"]:
362 war = {"War": {"Multiplier": 1.5, "Cooldown": 0, "Open": True, "Min": 50,
363 "Max": 100}}
364 path["Games"].update(war)
365
366 # Add membership changes from patch 1.5 to older versions
367 trash = ["Membership Lvl 0", "Membership Lvl 1", "Membership Lvl 2",
368 "Membership Lvl 3"]
369 new = {"Threshold Switch": False, "Threshold": 10000, "Default Payday": 100,
370 "Payday Timer": 1200}
371
372 for k, v in new.items():
373 if k not in path["System Config"]:
374 path["System Config"][k] = v
375
376 if "Memberships" not in path:
377 path["Memberships"] = {}
378
379 # Game access levels added
380 for x in path["Games"].values():
381 if "Access Level" not in x:
382 x["Access Level"] = 0
383
384 if "Min" in path["Games"]["Allin"]:
385 path["Games"]["Allin"].pop("Min")
386
387 if "Max" in path["Games"]["Allin"]:
388 path["Games"]["Allin"].pop("Max")
389
390 for x in trash:
391 if x in path["System Config"]:
392 path["System Config"].pop(x)
393
394 for x in path["Players"]:
395 if "CD" in path["Players"][x]:
396 path["Players"][x]["Cooldowns"] = path["Players"][x].pop("CD")
397 raw = [(x.split(" ", 1)[0], y) for x, y in
398 path["Players"][x]["Cooldowns"].items()]
399 raw.append(("Payday", 0))
400 new_dict = dict(raw)
401 path["Players"][x]["Cooldowns"] = new_dict
402
403 if "Membership" not in path["Players"][x]:
404 path["Players"][x]["Membership"] = None
405
406 if "Pending" not in path["Players"][x]:
407 path["Players"][x]["Pending"] = 0
408 self.save_system()
409
410
411class PluralDict(dict):
412 """This class is used to plural strings
413
414 You can plural strings based on the value input when using this class as a dictionary.
415 """
416 def __missing__(self, key):
417 if '(' in key and key.endswith(')'):
418 key, rest = key.split('(', 1)
419 value = super().__getitem__(key)
420 suffix = rest.rstrip(')').split(',')
421 if len(suffix) == 1:
422 suffix.insert(0, '')
423 return suffix[0] if value <= 1 else suffix[1]
424 raise KeyError(key)
425
426
427class Casino:
428 """Play Casino minigames and earn chips that integrate with Economy!
429
430 Any user can join casino by using the casino join command. Casino uses hooks from economy to
431 cash in/out chips. You are able to create your own casino name and chip name. Casino comes with
432 7 mini games that you can set min/max bets, multipliers, and access levels. Check out all of the
433 admin settings by using commands in the setcasino group. For additional information please
434 check out the wiki on my github.
435
436 """
437 __slots__ = ['bot', 'file_path', 'version', 'legacy_available', 'legacy_path', 'legacy_system',
438 'casino_bank', 'cycle_task']
439
440 def __init__(self, bot):
441 self.bot = bot
442 try: # This allows you to port accounts from older versions of casino
443 self.legacy_path = "data/casino/casino.json"
444 self.legacy_system = dataIO.load_json(self.legacy_path)
445 self.legacy_available = True
446 except FileNotFoundError:
447 self.legacy_available = False
448 self.file_path = "data/JumperCogs/casino/casino.json"
449 self.casino_bank = CasinoBank(bot, self.file_path)
450 self.version = "1.7.10"
451 self.cycle_task = bot.loop.create_task(self.membership_updater())
452
453 @commands.group(pass_context=True, no_pm=True)
454 async def casino(self, ctx):
455 """Casino Group Commands"""
456
457 if ctx.invoked_subcommand is None:
458 await send_cmd_help(ctx)
459
460 @casino.command(name="purge", pass_context=True)
461 @checks.is_owner()
462 async def _purge_casino(self, ctx):
463 """Removes all servers that the bot is no longer on.
464 If your JSON file is getting rather large, utilize this
465 command. It is possible that if your bot is on a ton of
466 servers, there are many that it is no longer running on.
467 This will remove them from the JSON file.
468 """
469 user = ctx.message.author
470 servers = self.casino_bank.get_all_servers()
471 purge_list = [x for x in servers if self.bot.get_server(x) is None]
472 if not purge_list:
473 return await self.bot.say("There are no servers for me to purge at this time.")
474 await self.bot.say("I found {} server(s) I am no longer on. Would you like for me to "
475 "delete their casino data?".format(len(purge_list)))
476 response = await self.bot.wait_for_message(timeout=15, author=user)
477
478 if response is None:
479 return await self.bot.say("You took too long to answer. Canceling purge.")
480
481 if response.content.title() == "Yes":
482 for x in purge_list:
483 servers.pop(x)
484 self.casino_bank.save_system()
485 await self.bot.say("{} server entries have been erased.".format(len(purge_list)))
486 else:
487 return await self.bot.say("Incorrect response. This is a yes or no question.")
488
489 @casino.command(name="forceupdate", pass_context=True)
490 @checks.is_owner()
491 async def _forceupdate_casino(self, ctx):
492 """Force applies older patches
493 This command will attempt to update your JSON with the
494 new dictionary keys. If you are having issues with your JSON
495 having a lot of key errors, namely Cooldown, then try using
496 this command. THIS DOES NOT UPDATE CASINO
497 """
498
499 server = ctx.message.server
500 settings = self.casino_bank.check_server_settings(server)
501 self.casino_bank.DICT_PATCH_1581(settings)
502 self.casino_bank.DICT_PATCH_16(settings)
503 self.casino_bank.DICT_PATCH_GAMES(settings)
504 self.casino_bank.DICT_PATCH_1694(settings)
505 await self.bot.say("Force applied three previous JSON updates. Please reload casino.")
506
507 @casino.command(name="memberships", pass_context=True)
508 @commands.cooldown(1, 5, commands.BucketType.user)
509 async def _memberships_casino(self, ctx):
510 """Shows all memberships on the server."""
511 server = ctx.message.server
512 settings = self.casino_bank.check_server_settings(server)
513 memberships = settings["Memberships"].keys()
514 if memberships:
515 await self.bot.say("Available Memberships:```\n{}```".format('\n'.join(memberships)))
516 else:
517 await self.bot.say("There are no memberships.")
518
519 @casino.command(name="join", pass_context=True)
520 async def _join_casino(self, ctx):
521 """Grants you membership access to the casino"""
522 user = ctx.message.author
523 settings = self.casino_bank.check_server_settings(user.server)
524 try:
525 self.casino_bank.create_account(user)
526 except UserAlreadyRegistered:
527 return await self.bot.say("{} already has a casino membership".format(user.name))
528 else:
529 name = settings["System Config"]["Casino Name"]
530 await self.bot.say("Your membership has been approved! Welcome to {} Casino!\nAs a "
531 "first time member we have credited your account with 100 free "
532 "chips.\nHave fun!".format(name))
533
534 @casino.command(name="transfer", pass_context=True)
535 @commands.cooldown(1, 5, commands.BucketType.user)
536 async def _transfer_casino(self, ctx, user: discord.Member, chips: int):
537 """Transfers chips to another player"""
538 author = ctx.message.author
539 settings = self.casino_bank.check_server_settings(author.server)
540 chip_name = settings["System Config"]["Chip Name"]
541 limit = settings["System Config"]["Transfer Limit"]
542
543 if not self.casino_bank.membership_exists(author):
544 return await self.bot.say("{} is not registered to the casino.".format(author.name))
545
546 if not self.casino_bank.membership_exists(user):
547 return await self.bot.say("{} is not registered to the casino.".format(user.name))
548
549 if chips > limit:
550 return await self.bot.say("Your transfer cannot exceed the server limit of {} {} "
551 "chips.".format(limit, chip_name))
552
553 chip_name = settings["System Config"]["Chip Name"]
554 cooldown = self.check_cooldowns(user, "Transfer", settings)
555
556 if not cooldown:
557 try:
558 self.casino_bank.transfer_chips(author, user, chips)
559 except NegativeChips:
560 return await self.bot.say("An amount cannot be negative.")
561 except SameSenderAndReceiver:
562 return await self.bot.say("Sender and Reciever cannot be the same.")
563 except BotNotAUser:
564 return await self.bot.say("You can send chips to a bot.")
565 except InsufficientChips:
566 return await self.bot.say("Not enough chips to transfer.")
567 else:
568 logger.info("{}({}) transferred {} {} to {}({}).".format(author.name, author.id,
569 chip_name, chips,
570 user.name, user.id))
571 await self.bot.say("{} transferred {} {} to {}.".format(author.name, chip_name, chips,
572 user.name))
573 else:
574 await self.bot.say(cooldown)
575
576 @casino.command(name="acctransfer", pass_context=True)
577 async def _acctransfer_casino(self, ctx):
578 """Transfers account info from old casino. Limit 1 transfer per user"""
579 user = ctx.message.author
580 settings = self.casino_bank.check_server_settings(user.server)
581
582 if not self.casino_bank.membership_exists(user):
583 msg = "I can't transfer data if you already have an account with the new casino."
584 elif not self.legacy_available:
585 msg = "No legacy file was found. Unable to perform membership transfers."
586 elif user.id in self.legacy_system["Players"]:
587 await self.bot.say("Account for {} found. Your casino data will be transferred to the "
588 "{} server. After your data is transferred your old data will be "
589 "deleted. I can only transfer data **one time**.\nDo you wish to "
590 "transfer?".format(user.name, user.server.name))
591 response = await self.bot.wait_for_message(timeout=15, author=user)
592 if response is None:
593 msg = "No response, transfer cancelled."
594 elif response.content.title() == "No":
595 msg = "Transfer cancelled."
596 elif response.content.title() == "Yes":
597 old_data = self.legacy_system["Players"][user.id]
598 transfer = {user.id: old_data}
599 settings["Players"].update(transfer)
600 self.legacy_system["Players"].pop(user.id)
601 dataIO.save_json(self.legacy_path, self.legacy_system)
602 self.casino_bank.DICT_PATCH_1581(settings)
603 self.casino_bank.DICT_PATCH_16(settings)
604 self.casino_bank.DICT_PATCH_GAMES(settings)
605 self.casino_bank.DICT_PATCH_1694(settings)
606 self.casino_bank.save_system()
607 msg = "Data transfer successful. You can now access your old casino data."
608 else:
609 msg = "Improper response. Please state yes or no. Cancelling transfer."
610 else:
611 msg = "Unable to locate your previous data."
612 await self.bot.say(msg)
613
614 @casino.command(name="leaderboard", pass_context=True)
615 @commands.cooldown(1, 5, commands.BucketType.user)
616 async def _leaderboard_casino(self, ctx, sort="top"):
617 """Displays Casino Leaderboard"""
618 user = ctx.message.author
619 self.casino_bank.check_server_settings(user.server)
620 members = self.casino_bank.get_server_memberships(user.server)
621
622 if sort not in ["top", "bottom", "place"]:
623 sort = "top"
624
625 if members:
626 players = [(x["Name"], x["Chips"]) for x in members.values()]
627 pos = [x + 1 for x, y in enumerate(players)]
628 if sort == "bottom":
629 style = sorted(players, key=itemgetter(1))
630 rev_pos = list(reversed(pos))
631 players, chips = zip(*style)
632 data = list(zip(rev_pos, players, chips))
633 elif sort == "place":
634 style = sorted([[x["Name"], x["Chips"]] if x["Name"] != user.name
635 else ["[" + x["Name"] + "]", x["Chips"]]
636 for x in members.values()], key=itemgetter(1), reverse=True)
637 players, chips = zip(*style)
638 data = list(zip(pos, players, chips))
639 else:
640 style = sorted(players, key=itemgetter(1), reverse=True)
641 players, chips = zip(*style)
642 data = list(zip(pos, players, chips))
643 headers = ["Rank", "Names", "Chips"]
644 msg = await self.table_split(user, headers, data, sort)
645 else:
646 msg = "There are no casino players to show on the leaderboard."
647 await self.bot.say(msg)
648
649 @casino.command(name="exchange", pass_context=True)
650 @commands.cooldown(1, 5, commands.BucketType.user)
651 async def _exchange_casino(self, ctx, currency: str, amount: int):
652 """Exchange chips for credits and credits for chips"""
653
654 # Declare all variables here
655 user = ctx.message.author
656 settings = self.casino_bank.check_server_settings(user.server)
657 bank = self.bot.get_cog('Economy').bank
658 currency = currency.title()
659 chip_rate = settings["System Config"]["Chip Rate"]
660 credit_rate = settings["System Config"]["Credit Rate"]
661 chip_multiple = Fraction(chip_rate).limit_denominator().denominator
662 credit_multiple = Fraction(credit_rate).limit_denominator().denominator
663 chip_name = settings["System Config"]["Chip Name"]
664 casino_name = settings["System Config"]["Casino Name"]
665
666 # Logic checks
667 if not self.casino_bank.membership_exists(user):
668 return await self.bot.say("You need to register to the {} Casino. To register type "
669 "`{}casino join`.".format(casino_name, ctx.prefix))
670 if currency not in ["Chips", "Credits"]:
671 return await self.bot.say("I can only exchange chips or credits, please specify one.")
672
673 # Logic for choosing chips
674 elif currency == "Chips":
675 if amount <= 0 and amount % credit_multiple != 0:
676 return await self.bot.say("The amount must be higher than 0 and "
677 "a multiple of {}.".format(credit_multiple))
678 try:
679 self.casino_bank.can_bet(user, amount)
680 except InsufficientChips:
681 return await self.bot.say("You don't have that many chips to exchange.")
682 else:
683 self.casino_bank.withdraw_chips(user, amount)
684 credits = int(amount * credit_rate)
685 bank.deposit_credits(user, credits)
686 return await self.bot.say("I have exchanged {} {} chips into {} credits.\nThank "
687 "you for playing at {} "
688 "Casino.".format(amount, chip_name, credits, casino_name))
689
690 # Logic for choosing Credits
691 elif currency == "Credits":
692 if amount <= 0 and amount % chip_multiple != 0:
693 return await self.bot.say("The amount must be higher than 0 and a multiple "
694 "of {}.".format(chip_multiple))
695 elif bank.can_spend(user, amount):
696 bank.withdraw_credits(user, amount)
697 chip_amount = int(amount * chip_rate)
698 self.casino_bank.deposit_chips(user, chip_amount)
699 await self.bot.say("I have exchanged {} credits for {} {} chips.\nEnjoy your time "
700 "at {} Casino!".format(amount, chip_amount, chip_name,
701 casino_name))
702 else:
703 await self.bot.say("You don't have that many credits to exchange.")
704
705 @casino.command(name="stats", pass_context=True)
706 @commands.cooldown(1, 5, commands.BucketType.user)
707 async def _stats_casino(self, ctx):
708 """Shows your casino play stats"""
709
710 # Variables
711 author = ctx.message.author
712 settings = self.casino_bank.check_server_settings(author.server)
713 chip_name = settings["System Config"]["Chip Name"]
714 casino_name = settings["System Config"]["Casino Name"]
715
716 # Check for a membership and build the table.
717 try:
718 chip_balance = self.casino_bank.chip_balance(author)
719 except UserNotRegistered:
720 await self.bot.say("You need to register to the {} Casino. To register type `{}casino "
721 "join`.".format(casino_name, ctx.prefix))
722 else:
723 pending_chips = settings["Players"][author.id]["Pending"]
724 player = settings["Players"][author.id]
725 wiki = "[Wiki](https://github.com/Redjumpman/Jumper-Cogs/wiki/Casino)"
726 membership, benefits = self.get_benefits(settings, author.id)
727 b_msg = ("Access Level: {Access}\nCooldown Reduction: {Cooldown Reduction}\n"
728 "Payday: {Payday}".format(**benefits))
729 description = ("{}\nMembership: {}\n{} Chips: "
730 "{}".format(wiki, membership, chip_name, chip_balance))
731 color = self.color_lookup(benefits["Color"])
732
733 # Build columns for the table
734 games = list(sorted(settings["Games"]))
735 played = [x[1] for x in sorted(player["Played"].items(), key=lambda tup: tup[0])]
736 won = [x[1] for x in sorted(player["Won"].items(), key=lambda tup: tup[0])]
737 cool_items = list(sorted(games + ["Payday"]))
738 cooldowns = self.stats_cooldowns(settings, author, cool_items)
739
740 # Build embed
741 embed = discord.Embed(colour=color, description=description)
742 embed.title = "{} Casino".format(casino_name)
743 embed.set_author(name=str(author), icon_url=author.avatar_url)
744 embed.add_field(name="Benefits", value=b_msg)
745 embed.add_field(name="Pending Chips", value=pending_chips, inline=False)
746 embed.add_field(name="Games", value="```Prolog\n{}```".format("\n".join(games)))
747 embed.add_field(name="Played",
748 value="```Prolog\n{}```".format("\n".join(map(str, played))))
749 embed.add_field(name="Won", value="```Prolog\n{}```".format("\n".join(map(str, won))))
750 embed.add_field(name="Cooldown Items",
751 value="```CSS\n{}```".format("\n".join(cool_items)))
752 embed.add_field(name="Cooldown Remaining",
753 value="```xl\n{}```".format("\n".join(cooldowns)))
754
755 await self.bot.say(embed=embed)
756
757 @casino.command(name="info", pass_context=True)
758 @commands.cooldown(1, 5, commands.BucketType.user)
759 async def _info_casino(self, ctx):
760 """Shows information about the server casino"""
761
762 # Variables
763 server = ctx.message.server
764 settings = self.casino_bank.check_server_settings(server)
765 players = len(self.casino_bank.get_server_memberships(server))
766 memberships = len(settings["Memberships"])
767 chip_exchange_rate = settings["System Config"]["Chip Rate"]
768 credit_exchange_rate = settings["System Config"]["Credit Rate"]
769 games = settings["Games"].keys()
770
771 if settings["System Config"]["Threshold Switch"]:
772 threshold = settings["System Config"]["Threshold"]
773 else:
774 threshold = "None"
775
776 # Create the columns through list comprehensions
777 multiplier = [subdict["Multiplier"] for subdict in settings["Games"].values()]
778 min_bet = [subdict["Min"] if "Min" in subdict else "None"
779 for subdict in settings["Games"].values()]
780 max_bet = [subdict["Max"] if "Max" in subdict else "None"
781 for subdict in settings["Games"].values()]
782 cooldown = [subdict["Cooldown"] for subdict in settings["Games"].values()]
783 cooldown_formatted = [self.time_format(x) for x in cooldown]
784
785 # Determine the ratio calculations for chips and credits
786 chip_ratio = str(Fraction(chip_exchange_rate).limit_denominator()).replace("/", ":")
787 credit_ratio = str(Fraction(credit_exchange_rate).limit_denominator()).replace("/", ":")
788
789 # If a fraction reduces to 1, we make it 1:1
790 if chip_ratio == "1":
791 chip_ratio = "1:1"
792 if credit_ratio == "1":
793 credit_ratio = "1:1"
794
795 # Build the table and send the message
796 m = list(zip(games, multiplier, min_bet, max_bet, cooldown_formatted))
797 m = sorted(m, key=itemgetter(0))
798 t = tabulate(m, headers=["Game", "Multiplier", "Min Bet", "Max Bet", "Cooldown"])
799 msg = ("```Python\n{}\n\nCredit Exchange Rate: {}\nChip Exchange Rate: {}\n"
800 "Casino Members: {}\nServer Memberships: {}\nServer Threshold: "
801 "{}```".format(t, credit_ratio, chip_ratio, players, memberships, threshold))
802 print("THIS MESSAGE IS {} CHARACTERS".format(len(msg)))
803 await self.bot.say(msg)
804
805 @casino.command(name="payday", pass_context=True)
806 @commands.cooldown(1, 5, commands.BucketType.user)
807 async def _payday_casino(self, ctx):
808 """Gives you some chips"""
809
810 user = ctx.message.author
811 settings = self.casino_bank.check_server_settings(user.server)
812 casino_name = settings["System Config"]["Casino Name"]
813 chip_name = settings["System Config"]["Chip Name"]
814
815 if not self.casino_bank.membership_exists(user):
816 await self.bot.say("You need to register to the {} Casino. To register type `{}casino "
817 "join`.".format(casino_name, ctx.prefix))
818 else:
819 cooldown = self.check_cooldowns(user, "Payday", settings)
820 if not cooldown:
821 if settings["Players"][user.id]["Membership"]:
822 membership = settings["Players"][user.id]["Membership"]
823 amount = settings["Memberships"][membership]["Payday"]
824 self.casino_bank.deposit_chips(user, amount)
825 msg = "You received {} {} chips.".format(amount, chip_name)
826 else:
827 payday = settings["System Config"]["Default Payday"]
828 self.casino_bank.deposit_chips(user, payday)
829 msg = "You received {} {} chips. Enjoy!".format(payday, chip_name)
830 else:
831 msg = cooldown
832 await self.bot.say(msg)
833
834 @casino.command(name="balance", pass_context=True)
835 @commands.cooldown(1, 5, commands.BucketType.user)
836 async def _balance_casino(self, ctx):
837 """Shows your number of chips"""
838 user = ctx.message.author
839 settings = self.casino_bank.check_server_settings(user.server)
840 chip_name = settings["System Config"]["Chip Name"]
841 casino_name = settings["System Config"]["Casino Name"]
842 try:
843 balance = self.casino_bank.chip_balance(user)
844 except UserNotRegistered:
845 await self.bot.say("You need to register to the {} Casino. To register type `{}casino "
846 "join`.".format(casino_name, ctx.prefix))
847 else:
848 await self.bot.say("```Python\nYou have {} {} chips.```".format(balance, chip_name))
849
850 @commands.command(pass_context=True, no_pm=True, aliases=["hl", "hi-lo"])
851 @commands.cooldown(1, 5, commands.BucketType.user)
852 async def hilo(self, ctx, choice: str, bet: int):
853 """Pick High, Low, Seven. Lo is < 7 Hi is > 7. 6x payout on 7"""
854
855 # Declare variables for the game.
856 user = ctx.message.author
857 settings = self.casino_bank.check_server_settings(user.server)
858 chip_name = settings["System Config"]["Chip Name"]
859 choice = choice.title()
860 choices = ["Hi", "High", "Low", "Lo", "Seven", "7"]
861
862 # Run a logic check to determine if the user can play the game
863 check = self.game_checks(settings, ctx.prefix, user, bet, "Hi-Lo", choice, choices)
864 if check:
865 msg = check
866 else: # Run the game when the checks return None
867 self.casino_bank.withdraw_chips(user, bet)
868 settings["Players"][user.id]["Played"]["Hi-Lo Played"] += 1
869 await self.bot.say("The dice hit the table and slowly fall into place...")
870 die_one = random.randint(1, 6)
871 die_two = random.randint(1, 6)
872 result = die_one + die_two
873 outcome = self.hl_outcome(result)
874 await asyncio.sleep(2)
875
876 # Begin game logic to determine a win or loss
877 msg = ("The dice landed on {} and {} \n".format(die_one, die_two))
878 if choice in outcome:
879 msg += ("Congratulations! The outcome was "
880 "{} ({})!".format(outcome[0], outcome[2]))
881 settings["Players"][user.id]["Won"]["Hi-Lo Won"] += 1
882
883 # Check for a 7 to give a 12x multiplier
884 if outcome[2] == "Seven":
885 amount = bet * 6
886 msg += "\n**BONUS!** 6x multiplier for Seven!"
887 else:
888 amount = int(round(bet * settings["Games"]["Hi-Lo"]["Multiplier"]))
889
890 # Check if a threshold is set and withold chips if amount is exceeded
891 if self.threshold_check(settings, amount):
892 settings["Players"][user.id]["Pending"] = amount
893 msg += ("```Your winnings exceeded the threshold set on this server. "
894 "The amount of {} {} chips will be withheld until reviewed and "
895 "released by an admin. Do not attempt to play additional games "
896 "exceeding the threshold until this has been cleared.```"
897 "".format(amount, chip_name, user.id))
898 logger.info("{}({}) won {} chips exceeding the threshold. Game "
899 "details:\nPlayer Choice: {}\nPlayer Bet: {}\nGame "
900 "Outcome: {}\n[END OF REPORT]"
901 "".format(user.name, user.id, amount, choice.ljust(10),
902 str(bet).ljust(10), str(outcome[0]).ljust(10)))
903 else:
904 self.casino_bank.deposit_chips(user, amount)
905 msg += "```Python\nYou just won {} {} chips.```".format(amount, chip_name)
906 else:
907 msg += "Sorry. The outcome was {} ({}).".format(outcome[0], outcome[2])
908 # Save the results of the game
909 self.casino_bank.save_system()
910 # Send a message telling the user the outcome of this command
911 await self.bot.say(msg)
912
913 @commands.command(pass_context=True, no_pm=True)
914 @commands.cooldown(1, 5, commands.BucketType.user)
915 async def cups(self, ctx, cup: int, bet: int):
916 """Pick the cup that is hiding the gold coin. Choose 1, 2, 3, or 4"""
917
918 # Declare variables for the game.
919 user = ctx.message.author
920 settings = self.casino_bank.check_server_settings(user.server)
921 choice = cup
922 choices = [1, 2, 3, 4]
923 chip_name = settings["System Config"]["Chip Name"]
924
925 # Run a logic check to determine if the user can play the game
926 check = self.game_checks(settings, ctx.prefix, user, bet, "Cups", choice, choices)
927 if check:
928 msg = check
929 else: # Run the game when the checks return None
930 self.casino_bank.withdraw_chips(user, bet)
931 settings["Players"][user.id]["Played"]["Cups Played"] += 1
932 outcome = random.randint(1, 4)
933 await self.bot.say("The cups start shuffling along the table...")
934 await asyncio.sleep(3)
935
936 # Begin game logic to determine a win or loss
937 if cup == outcome:
938 amount = int(round(bet * settings["Games"]["Cups"]["Multiplier"]))
939 settings["Players"][user.id]["Won"]["Cups Won"] += 1
940 msg = "Congratulations! The coin was under cup {}!".format(outcome)
941
942 # Check if a threshold is set and withold chips if amount is exceeded
943 if self.threshold_check(settings, amount):
944 settings["Players"][user.id]["Pending"] = amount
945 msg += ("Your winnings exceeded the threshold set on this server. "
946 "The amount of {} {} chips will be withheld until reviewed and "
947 "released by an admin. Do not attempt to play additional games "
948 "exceeding the threshold until this has been cleared."
949 "".format(amount, chip_name, user.id))
950 logger.info("{}({}) won {} chips exceeding the threshold. Game "
951 "details:\nPlayer Cup: {}\nPlayer Bet: {}\nGame "
952 "Outcome: {}\n[END OF REPORT]"
953 "".format(user.name, user.id, amount, str(cup).ljust(10),
954 str(bet).ljust(10), str(outcome).ljust(10)))
955 else:
956 self.casino_bank.deposit_chips(user, amount)
957 msg += "```Python\nYou just won {} {} chips.```".format(amount, chip_name)
958 else:
959 msg = "Sorry! The coin was under cup {}.".format(outcome)
960 # Save the results of the game
961 self.casino_bank.save_system()
962 # Send a message telling the user the outcome of this command
963 await self.bot.say(msg)
964
965 @commands.command(pass_context=True, no_pm=True)
966 @commands.cooldown(1, 5, commands.BucketType.user)
967 async def coin(self, ctx, choice: str, bet: int):
968 """Bet on heads or tails"""
969
970 # Declare variables for the game.
971 user = ctx.message.author
972 settings = self.casino_bank.check_server_settings(user.server)
973 choice = choice.title()
974 choices = ["Heads", "Tails"]
975 chip_name = settings["System Config"]["Chip Name"]
976
977 # Run a logic check to determine if the user can play the game
978 check = self.game_checks(settings, ctx.prefix, user, bet, "Coin", choice, choices)
979 if check:
980 msg = check
981 else: # Run the game when the checks return None
982 self.casino_bank.withdraw_chips(user, bet)
983 settings["Players"][user.id]["Played"]["Coin Played"] += 1
984 outcome = random.choice(["Heads", "Tails"])
985 await self.bot.say("The coin flips into the air...")
986 await asyncio.sleep(2)
987
988 # Begin game logic to determine a win or loss
989 if choice == outcome:
990 amount = int(round(bet * settings["Games"]["Coin"]["Multiplier"]))
991 msg = "Congratulations! The coin landed on {}!".format(outcome)
992 settings["Players"][user.id]["Won"]["Coin Won"] += 1
993
994 # Check if a threshold is set and withold chips if amount is exceeded
995 if self.threshold_check(settings, amount):
996 settings["Players"][user.id]["Pending"] = amount
997 msg += ("\nYour winnings exceeded the threshold set on this server. "
998 "The amount of {} {} chips will be withheld until reviewed and "
999 "released by an admin. Do not attempt to play additional games "
1000 "exceeding the threshold until this has been cleared."
1001 "".format(amount, chip_name, user.id))
1002 logger.info("{}({}) won {} chips exceeding the threshold. Game "
1003 "details:\nPlayer Choice: {}\nPlayer Bet: {}\nGame "
1004 "Outcome: {}\n[END OF REPORT]"
1005 "".format(user.name, user.id, amount, choice.ljust(10),
1006 str(bet).ljust(10), outcome[0].ljust(10)))
1007 else:
1008 self.casino_bank.deposit_chips(user, amount)
1009 msg += "```Python\nYou just won {} {} chips.```".format(amount, chip_name)
1010 else:
1011 msg = "Sorry! The coin landed on {}.".format(outcome)
1012 # Save the results of the game
1013 self.casino_bank.save_system()
1014 # Send a message telling the user the outcome of this command
1015 await self.bot.say(msg)
1016
1017 @commands.command(pass_context=True, no_pm=True)
1018 @commands.cooldown(1, 5, commands.BucketType.user)
1019 async def dice(self, ctx, bet: int):
1020 """Roll 2, 7, 11 or 12 to win."""
1021
1022 # Declare variables for the game.
1023 user = ctx.message.author
1024 settings = self.casino_bank.check_server_settings(user.server)
1025 chip_name = settings["System Config"]["Chip Name"]
1026
1027 # Run a logic check to determine if the user can play the game
1028 check = self.game_checks(settings, ctx.prefix, user, bet, "Dice", 1, [1])
1029 if check:
1030 msg = check
1031 else: # Run the game when the checks return None
1032 self.casino_bank.withdraw_chips(user, bet)
1033 settings["Players"][user.id]["Played"]["Dice Played"] += 1
1034 await self.bot.say("The dice strike the back of the table and begin to tumble into "
1035 "place...")
1036 die_one = random.randint(1, 6)
1037 die_two = random.randint(1, 6)
1038 outcome = die_one + die_two
1039 await asyncio.sleep(2)
1040
1041 # Begin game logic to determine a win or loss
1042 msg = "The dice landed on {} and {} \n".format(die_one, die_two)
1043 if outcome in [2, 7, 11, 12]:
1044 amount = int(round(bet * settings["Games"]["Dice"]["Multiplier"]))
1045 settings["Players"][user.id]["Won"]["Dice Won"] += 1
1046
1047 msg += "Congratulations! The dice landed on {}.".format(outcome)
1048
1049 # Check if a threshold is set and withold chips if amount is exceeded
1050 if self.threshold_check(settings, amount):
1051 settings["Players"][user.id]["Pending"] = amount
1052 msg += ("\nYour winnings exceeded the threshold set on this server. "
1053 "The amount of {} {} chips will be withheld until reviewed and "
1054 "released by an admin. Do not attempt to play additional games "
1055 "exceeding the threshold until this has been cleared."
1056 "".format(amount, chip_name, user.id))
1057 logger.info("{}({}) won {} chips exceeding the threshold. Game "
1058 "details:\nPlayer Bet: {}\nGame "
1059 "Outcome: {}\n[END OF FILE]".format(user.name, user.id, amount,
1060 str(bet).ljust(10),
1061 str(outcome[0]).ljust(10)))
1062 else:
1063 self.casino_bank.deposit_chips(user, amount)
1064 msg += "```Python\nYou just won {} {} chips.```".format(amount, chip_name)
1065 else:
1066 msg += "Sorry! The result was {}.".format(outcome)
1067 # Save the results of the game
1068 self.casino_bank.save_system()
1069 # Send a message telling the user the outcome of this command
1070 await self.bot.say(msg)
1071
1072 @commands.command(pass_context=True, no_pm=True)
1073 @commands.cooldown(1, 5, commands.BucketType.user)
1074 async def war(self, ctx, bet: int):
1075 """Modified War Card Game."""
1076
1077 # Declare Variables for the game.
1078 user = ctx.message.author
1079 settings = self.casino_bank.check_server_settings(user.server)
1080
1081 # Run a logic check to determine if the user can play the game
1082 check = self.game_checks(settings, ctx.prefix, user, bet, "War", 1, [1])
1083 if check:
1084 msg = check
1085 else: # Run the game when the checks return None
1086 self.casino_bank.withdraw_chips(user, bet)
1087 settings["Players"][user.id]["Played"]["War Played"] += 1
1088 deck = main_deck[:] # Make a copy of the deck so we can remove cards that are drawn
1089 outcome, player_card, dealer_card, amount = await self.war_game(user, settings, deck,
1090 bet)
1091 msg = self.war_results(settings, user, outcome, player_card, dealer_card, amount)
1092 await self.bot.say(msg)
1093
1094 @commands.command(pass_context=True, no_pm=True, aliases=["bj", "21"])
1095 @commands.cooldown(1, 5, commands.BucketType.user)
1096 async def blackjack(self, ctx, bet: int):
1097 """Modified Blackjack."""
1098
1099 # Declare variables for the game.
1100 user = ctx.message.author
1101 settings = self.casino_bank.check_server_settings(user.server)
1102
1103 # Run a logic check to determine if the user can play the game
1104 check = self.game_checks(settings, ctx.prefix, user, bet, "Blackjack", 1, [1])
1105 if check:
1106 msg = check
1107 else: # Run the game when the checks return None
1108 self.casino_bank.withdraw_chips(user, bet)
1109 settings["Players"][user.id]["Played"]["BJ Played"] += 1
1110 deck = main_deck[:] # Make a copy of the deck so we can remove cards that are drawn
1111 dhand = self.dealer(deck)
1112 ph, dh, amt = await self.blackjack_game(dhand, user, bet, deck)
1113 msg = self.blackjack_results(settings, user, amt, ph, dh)
1114 # Send a message telling the user the outcome of this command
1115 await self.bot.say(msg)
1116
1117 @commands.command(pass_context=True, no_pm=True)
1118 @commands.cooldown(1, 5, commands.BucketType.user)
1119 async def allin(self, ctx, multiplier: int):
1120 """It's all or nothing. Bets everything you have."""
1121
1122 # Declare variables for the game.
1123 user = ctx.message.author
1124 settings = self.casino_bank.check_server_settings(user.server)
1125 chip_name = settings["System Config"]["Chip Name"]
1126
1127 if not self.casino_bank.membership_exists(user):
1128 return await self.bot.say("You need to register. Type "
1129 "{}casino join.".format(ctx.prefix))
1130
1131 # Run a logic check to determine if the user can play the game.
1132 check = self.game_checks(settings, ctx.prefix, user, 0, "Allin", 1, [1])
1133 if check:
1134 msg = check
1135 else: # Run the game when the checks return None.
1136 # Setup the game to determine an outcome.
1137 settings["Players"][user.id]["Played"]["Allin Played"] += 1
1138 amount = int(round(multiplier * settings["Players"][user.id]["Chips"]))
1139 balance = self.casino_bank.chip_balance(user)
1140 outcome = random.randint(0, multiplier + 1)
1141 self.casino_bank.withdraw_chips(user, balance)
1142 await self.bot.say("You put all your chips into the machine and pull the lever...")
1143 await asyncio.sleep(3)
1144
1145 # Begin game logic to determine a win or loss.
1146 if outcome == 0:
1147 self.casino_bank.deposit_chips(user, amount)
1148 msg = "```Python\nJackpot!! You just won {} {} chips!!```".format(amount, chip_name)
1149 settings["Players"][user.id]["Won"]["Allin Won"] += 1
1150 else:
1151 msg = ("Sorry! Your all or nothing gamble failed and you lost "
1152 "all your {} chips.".format(chip_name))
1153 # Save the results of the game
1154 self.casino_bank.save_system()
1155 # Send a message telling the user the outcome of this command
1156 await self.bot.say(msg)
1157
1158 @casino.command(name="version")
1159 @checks.admin_or_permissions(manage_server=True)
1160 async def _version_casino(self):
1161 """Shows current Casino version"""
1162 await self.bot.say("You are currently running Casino version {}.".format(self.version))
1163
1164 @casino.command(name="cdreset", pass_context=True)
1165 @checks.admin_or_permissions(manage_server=True)
1166 async def _cdreset_casino(self, ctx):
1167 """Resets all cooldowns on the server"""
1168 server = ctx.message.server
1169 settings = self.casino_bank.check_server_settings(server)
1170 cd_dict = {"Dice": 0, "Cups": 0, "Coin": 0, "Allin": 0, "Hi-Lo": 0, "War": 0,
1171 "Blackjack": 0, "Payday": 0}
1172
1173 for player in settings["Players"]:
1174 settings["Players"][player]["Cooldowns"] = cd_dict
1175
1176 self.casino_bank.save_system()
1177 await self.bot.say("Cooldowns have been reset for all users on this server.")
1178
1179 @casino.command(name="removemembership", pass_context=True)
1180 @checks.admin_or_permissions(manage_server=True)
1181 async def _removemembership_casino(self, ctx, *, membership):
1182 """Remove a casino membership"""
1183 author = ctx.message.author
1184 settings = self.casino_bank.check_server_settings(author.server)
1185
1186 if membership in settings["Memberships"]:
1187 settings["Memberships"].pop(membership)
1188 msg = "{} removed from the list of membership.".format(membership)
1189 else:
1190 msg = "Could not find a membership with that name."
1191
1192 await self.bot.say(msg)
1193
1194 @casino.command(name="createmembership", pass_context=True)
1195 @checks.admin_or_permissions(manage_server=True)
1196 async def _createmembership_casino(self, ctx):
1197 """Add a casino membership to reward continued play"""
1198
1199 # Declare variables
1200 author = ctx.message.author
1201 settings = self.casino_bank.check_server_settings(author.server)
1202 cancel = ctx.prefix + "cancel"
1203 requirement_list = ["Days On Server", "Credits", "Chips", "Role"]
1204 colors = ["blue", "red", "green", "orange", "purple", "yellow", "turquoise", "teal",
1205 "magenta", "pink", "white"]
1206 server_roles = [r.name for r in ctx.message.server.roles if r.name != "Bot"]
1207
1208 # Various checks for the different questions
1209 check1 = lambda m: m.content.isdigit() and int(m.content) > 0 or m.content == cancel
1210 check2 = lambda m: m.content.isdigit() or m.content == cancel
1211 check3 = lambda m: m.content.title() in requirement_list or m.content == cancel
1212 check4 = lambda m: m.content.isdigit() or m.content in server_roles or m.content == cancel
1213 check5 = lambda m: m.content.lower() in colors or m.content == cancel
1214
1215 start = ("Welcome to the membership creation process. This will create a membership to "
1216 "provide benefits to your members such as reduced cooldowns and access levels.\n"
1217 "You may cancel this process at anytime by typing {}cancel. Let's begin with the "
1218 "first question.\n\nWhat is the name of this membership? Examples: Silver, Gold, "
1219 "and Diamond.".format(ctx.prefix))
1220
1221 # Begin creation process
1222 await self.bot.say(start)
1223 name = await self.bot.wait_for_message(timeout=35, author=author)
1224
1225 if name is None:
1226 await self.bot.say("You took too long. Cancelling membership creation.")
1227 return
1228
1229 if name.content == cancel:
1230 await self.bot.say("Membership creation cancelled.")
1231 return
1232
1233 if name.content.title() in settings["Memberships"]:
1234 await self.bot.say("A membership with that name already exists. Cancelling creation.")
1235 return
1236
1237 await self.bot.say("What is the color for this membership? This color appears in the "
1238 "{}casino stats command.\nPlease pick from these colors: "
1239 "```{}```".format(ctx.prefix, ", ".join(colors)))
1240 color = await self.bot.wait_for_message(timeout=35, author=author, check=check5)
1241
1242 if color is None:
1243 await self.bot.say("You took too long. Cancelling membership creation.")
1244 return
1245
1246 if color.content == cancel:
1247 await self.bot.say("Membership creation cancelled.")
1248 return
1249
1250 await self.bot.say("What is the payday amount for this membership?")
1251 payday = await self.bot.wait_for_message(timeout=35, author=author, check=check1)
1252
1253 if payday is None:
1254 await self.bot.say("You took too long. Cancelling membership creation.")
1255 return
1256
1257 if payday.content == cancel:
1258 await self.bot.say("Membership creation cancelled.")
1259 return
1260
1261 await self.bot.say("What is the cooldown reduction for this membership in seconds? 0 for "
1262 "none")
1263 reduction = await self.bot.wait_for_message(timeout=35, author=author, check=check2)
1264
1265 if reduction is None:
1266 await self.bot.say("You took too long. Cancelling membership creation.")
1267 return
1268
1269 if reduction.content == cancel:
1270 await self.bot.say("membership creation cancelled.")
1271 return
1272
1273 await self.bot.say("What is the access level for this membership? 0 is the default access "
1274 "level for new members. Access levels can be used to restrict access to "
1275 "games. See `{}setcasino access` for more info.".format(ctx.prefix))
1276
1277 access = await self.bot.wait_for_message(timeout=35, author=author, check=check1)
1278
1279 if access is None:
1280 await self.bot.say("You took too long. Cancelling membership creation.")
1281 return
1282
1283 if access.content == cancel:
1284 await self.bot.say("Membership creation cancelled.")
1285 return
1286
1287 if int(access.content) in [x["Access"] for x in settings["Memberships"].values()]:
1288 await self.bot.say("You cannot have memberships with the same access level. Cancelling "
1289 "creation.")
1290 return
1291
1292 await self.bot.say("What is the requirement for this membership? Available options are:```"
1293 "Days on server, Credits, Chips, or Role```Which would you "
1294 "like set? You can always remove and add additional requirements later"
1295 "using `{0}setcasino addrequirements` and "
1296 "`{0}setcasino removerequirements`.".format(ctx.prefix))
1297 req_type = await self.bot.wait_for_message(timeout=35, author=author, check=check3)
1298
1299 if req_type is None:
1300 await self.bot.say("You took too long. Cancelling membership creation.")
1301 return
1302
1303 if req_type.content == cancel:
1304 await self.bot.say("Membership creation cancelled.")
1305 return
1306
1307 await self.bot.say("What is the number of days, chips, credits or role name you would like "
1308 "set?")
1309 req_val = await self.bot.wait_for_message(timeout=35, author=author, check=check4)
1310
1311 if req_val is None:
1312 await self.bot.say("You took too long. Cancelling membership creation.")
1313 return
1314
1315 if req_val.content == cancel:
1316 await self.bot.say("Membership creation cancelled.")
1317 return
1318 else:
1319
1320 if req_val.content.isdigit():
1321 req_val = int(req_val.content)
1322 else:
1323 req_val = req_val.content
1324
1325 params = [name.content, color.content, payday.content, reduction.content,
1326 access.content, req_val]
1327 msg = ("Membership successfully created. Please review the details below.\n"
1328 "```Name: {0}\nColor: {1}\nPayday: {2}\nCooldown Reduction: {3}\n"
1329 "Access Level: {4}\n".format(*params))
1330 msg += "Requirement: {} {}```".format(req_val, req_type.content.title())
1331
1332 memberships = {"Payday": int(payday.content), "Access": int(access.content),
1333 "Cooldown Reduction": int(reduction.content), "Color": color.content,
1334 "Requirements": {req_type.content.title(): req_val}}
1335 settings["Memberships"][name.content.title()] = memberships
1336 self.casino_bank.save_system()
1337 await self.bot.say(msg)
1338
1339 @casino.command(name="reset", pass_context=True)
1340 @checks.admin_or_permissions(manage_server=True)
1341 async def _reset_casino(self, ctx):
1342 """Resets casino to default settings. Keeps user data"""
1343
1344 user = ctx.message.author
1345 settings = self.casino_bank.check_server_settings(user.server)
1346 await self.bot.say("This will reset casino to it's default settings and keep player data.\n"
1347 "Do you wish to reset casino settings?")
1348 response = await self.bot.wait_for_message(timeout=15, author=user)
1349
1350 if response is None:
1351 msg = "No response, reset cancelled."
1352 elif response.content.title() == "No":
1353 msg = "Cancelling reset."
1354 elif response.content.title() == "Yes":
1355 settings["System Config"] = server_default["System Config"]
1356 settings["Games"] = server_default["Games"]
1357 self.casino_bank.save_system()
1358 msg = "Casino settings reset to default."
1359 else:
1360 msg = "Improper response. Cancelling reset."
1361 await self.bot.say(msg)
1362
1363 @casino.command(name="toggle", pass_context=True)
1364 @checks.admin_or_permissions(manage_server=True)
1365 async def _toggle_casino(self, ctx):
1366 """Opens and closes the casino"""
1367
1368 server = ctx.message.server
1369 settings = self.casino_bank.check_server_settings(server)
1370 casino_name = settings["System Config"]["Casino Name"]
1371
1372 if settings["System Config"]["Casino Open"]:
1373 settings["System Config"]["Casino Open"] = False
1374 msg = "The {} Casino is now closed.".format(casino_name)
1375 else:
1376 settings["System Config"]["Casino Open"] = True
1377 msg = "The {} Casino is now open!".format(casino_name)
1378 self.casino_bank.save_system()
1379 await self.bot.say(msg)
1380
1381 @casino.command(name="approve", pass_context=True)
1382 @checks.admin_or_permissions(manage_server=True)
1383 async def _approve_casino(self, ctx, user: discord.Member):
1384 """Approve a user's pending chips."""
1385 author = ctx.message.author
1386 settings = self.casino_bank.check_server_settings(author.server)
1387 chip_name = settings["System Config"]["Chip Name"]
1388 if self.casino_bank.membership_exists(user):
1389 amount = settings["Players"][user.id]["Pending"]
1390 if amount > 0:
1391 await self.bot.say("{} has a pending amount of {}. Do you wish to approve this "
1392 "amount?".format(user.name, amount))
1393 response = await self.bot.wait_for_message(timeout=15, author=author)
1394
1395 if response is None:
1396 await self.bot.say("You took too long. Cancelling pending chip approval.")
1397 return
1398
1399 if response.content.title() in ["No", "Cancel", "Stop"]:
1400 await self.bot.say("Cancelling pending chip approval.")
1401 return
1402
1403 if response.content.title() in ["Yes", "Approve"]:
1404 await self.bot.say("{} approved the pending chips. Sending {} {} chips to "
1405 " {}.".format(author.name, amount, chip_name, user.name))
1406 self.casino_bank.deposit_chips(user, amount)
1407 else:
1408 await self.bot.say("Incorrect response. Cancelling pending chip approval.")
1409 return
1410 else:
1411 await self.bot.say("{} does not have any chips pending.".format(user.name))
1412
1413 @casino.command(name="removeuser", pass_context=True)
1414 @checks.admin_or_permissions(manage_server=True)
1415 async def _removeuser_casino(self, ctx, user: discord.Member):
1416 """Remove a user from casino"""
1417 author = ctx.message.author
1418 self.casino_bank.check_server_settings(author.server)
1419
1420 if not self.casino_bank.membership_exists(user):
1421 msg = "This user is not a member of the casino."
1422 else:
1423 await self.bot.say("Are you sure you want to remove player data for {}? Type {} to "
1424 "confirm.".format(user.name, user.name))
1425 response = await self.bot.wait_for_message(timeout=15, author=author)
1426 if response is None:
1427 msg = "No response. Player removal cancelled."
1428 elif response.content.title() == user.name:
1429 self.casino_bank.remove_membership(user)
1430 msg = "{}\'s casino data has been removed by {}.".format(user.name, author.name)
1431 else:
1432 msg = "Incorrect name. Cancelling player removal."
1433 await self.bot.say(msg)
1434
1435 @casino.command(name="wipe", pass_context=True)
1436 @checks.is_owner()
1437 async def _wipe_casino(self, ctx, *, servername: str):
1438 """Wipe casino server data. Case Sensitive"""
1439 user = ctx.message.author
1440 servers = self.casino_bank.get_all_servers()
1441 server_list = [self.bot.get_server(x).name for x in servers
1442 if hasattr(self.bot.get_server(x), 'name')]
1443 fmt_list = ["{}: {}".format(idx + 1, x) for idx, x in enumerate(server_list)]
1444 try:
1445 server = [self.bot.get_server(x) for x in servers
1446 if self.bot.get_server(x).name == servername][0]
1447 except AttributeError:
1448 msg = ("A server with that name could not be located.\n**List of "
1449 "Servers:**")
1450 if len(fmt_list) > 25:
1451 fmt_list = fmt_list[:25]
1452 msg += "\n\n{}".format('\n'.join(fmt_list))
1453 msg += "\nThere are too many server names to display, displaying first 25."
1454 else:
1455 msg += "\n\n{}".format('\n'.join(fmt_list))
1456
1457 return await self.bot.say(msg)
1458
1459 await self.bot.say("This will wipe casino server data.**WARNING** ALL PLAYER DATA WILL "
1460 "BE DESTROYED.\nDo you wish to wipe {}?".format(server.name))
1461 response = await self.bot.wait_for_message(timeout=15, author=user)
1462
1463 if response is None:
1464 msg = "No response, casino wipe cancelled."
1465 elif response.content.title() == "No":
1466 msg = "Cancelling casino wipe."
1467 elif response.content.title() == "Yes":
1468 await self.bot.say("To confirm type the server name: {}".format(server.name))
1469 response = await self.bot.wait_for_message(timeout=15, author=user)
1470 if response is None:
1471 msg = "No response, casino wipe cancelled."
1472 elif response.content == server.name:
1473 self.casino_bank.wipe_caisno_server(server)
1474 msg = "Casino wiped."
1475 else:
1476 msg = "Incorrect server name. Cancelling casino wipe."
1477 else:
1478 msg = "Improper response. Cancelling casino wipe."
1479
1480 await self.bot.say(msg)
1481
1482 @commands.group(pass_context=True, no_pm=True)
1483 async def setcasino(self, ctx):
1484 """Configures Casino Options"""
1485 if ctx.invoked_subcommand is None:
1486 await send_cmd_help(ctx)
1487
1488 @setcasino.command(name="transferlimit", pass_context=True)
1489 @checks.admin_or_permissions(manage_server=True)
1490 async def _xferlimit_setcasino(self, ctx, limit: int):
1491 """This is the limit of chips a player can transfer at one time.
1492
1493 Remember, that without a cooldown, a player can still use this command
1494 over and over. This is just to prevent a transfer of outrageous amounts.
1495
1496 """
1497 author = ctx.message.author
1498 settings = self.casino_bank.check_server_settings(author.server)
1499
1500 if limit > 0:
1501 settings["System Config"]["Transfer Limit"] = limit
1502 msg = "{} set transfer limit to {}.".format(author.name, limit)
1503 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1504 self.casino_bank.save_system()
1505 else:
1506 msg = "Limit must be higher than 0."
1507
1508 await self.bot.say(msg)
1509
1510 @setcasino.command(name="transfercd", pass_context=True)
1511 @checks.admin_or_permissions(manage_server=True)
1512 async def _xcdlimit_setcasino(self, ctx, seconds: int):
1513 """Set the cooldown for transferring chips.
1514
1515 There is already a five second cooldown in place. Use this to prevent
1516 users from circumventing the transfer limit through spamming. Default
1517 is set to 30 seconds.
1518
1519 """
1520 author = ctx.message.author
1521 settings = self.casino_bank.check_server_settings(author.server)
1522
1523 if seconds > 0:
1524 settings["System Config"]["Transfer Cooldown"] = seconds
1525 time_fmt = self.time_format(seconds)
1526 msg = "{} set transfer cooldown to {}.".format(author.name, time_fmt)
1527 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1528 self.casino_bank.save_system()
1529 else:
1530 msg = "Seconds must be higher than 0."
1531
1532 await self.bot.say(msg)
1533
1534 @setcasino.command(name="threshold", pass_context=True)
1535 @checks.admin_or_permissions(manage_server=True)
1536 async def _threshold_setcasino(self, ctx, threshold: int):
1537 """Players that exceed this amount require an admin to approve the payout"""
1538 author = ctx.message.author
1539 settings = self.casino_bank.check_server_settings(author.server)
1540
1541 if threshold > 0:
1542 settings["System Config"]["Threshold"] = threshold
1543 msg = "{} set payout threshold to {}.".format(author.name, threshold)
1544 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1545 self.casino_bank.save_system()
1546 else:
1547 msg = "Threshold amount needs to be higher than 0."
1548
1549 await self.bot.say(msg)
1550
1551 @setcasino.command(name="thresholdtoggle", pass_context=True)
1552 @checks.admin_or_permissions(manage_server=True)
1553 async def _threshholdtoggle_setcasino(self, ctx):
1554 """Turns on a chip win limit"""
1555 author = ctx.message.author
1556 settings = self.casino_bank.check_server_settings(author.server)
1557
1558 if settings["System Config"]["Threshold Switch"]:
1559 msg = "{} turned the threshold OFF.".format(author.name)
1560 settings["System Config"]["Threshold Switch"] = False
1561 else:
1562 msg = "{} turned the threshold ON.".format(author.name)
1563 settings["System Config"]["Threshold Switch"] = True
1564
1565 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1566 self.casino_bank.save_system()
1567 await self.bot.say(msg)
1568
1569 @setcasino.command(name="payday", pass_context=True)
1570 @checks.admin_or_permissions(manage_server=True)
1571 async def _payday_setcasino(self, ctx, amount: int):
1572 """Set the default payday amount with no membership
1573
1574 This amount is what users who have no membership will receive. If the
1575 user has a membership it will be based on what payday amount that was set
1576 for it.
1577 """
1578
1579 author = ctx.message.author
1580 settings = self.casino_bank.check_server_settings(author.server)
1581 chip_name = settings["System Config"]["Chip Name"]
1582
1583 if amount >= 0:
1584 settings["System Config"]["Default Payday"] = amount
1585 self.casino_bank.save_system()
1586 msg = "{} set the default payday to {} {} chips.".format(author.name, amount, chip_name)
1587 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1588 else:
1589 msg = "You cannot set a negative number to payday."
1590
1591 await self.bot.say(msg)
1592
1593 @setcasino.command(name="paydaytimer", pass_context=True)
1594 @checks.admin_or_permissions(manage_server=True)
1595 async def _paydaytimer_setcasino(self, ctx, seconds: int):
1596 """Set the cooldown on payday
1597
1598 This timer is not affected by cooldown reduction from membership.
1599 """
1600
1601 author = ctx.message.author
1602 settings = self.casino_bank.check_server_settings(author.server)
1603
1604 if seconds >= 0:
1605 settings["System Config"]["Payday Timer"] = seconds
1606 self.casino_bank.save_system()
1607 time_set = self.time_format(seconds)
1608 msg = "{} set the default payday to {}.".format(author.name, time_set)
1609 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1610 else:
1611 msg = ("You cannot set a negative number to payday timer. That would be like going back"
1612 " in time. Which would be totally cool, but I don't understand the physics of "
1613 "how it might apply in this case. One would assume you would go back in time to "
1614 "the point in which you could receive a payday, but it is actually quite the "
1615 "opposite. You would go back to the point where you were about to claim a "
1616 "payday and thus claim it again, but unfortunately your total would not receive "
1617 "a net gain, because you are robbing from yourself. Next time think before you "
1618 "do something so stupid.")
1619
1620 await self.bot.say(msg)
1621
1622 @setcasino.command(name="multiplier", pass_context=True)
1623 @checks.admin_or_permissions(manage_server=True)
1624 async def _multiplier_setcasino(self, ctx, game: str, multiplier: float):
1625 """Sets the payout multiplier for casino games"""
1626 author = ctx.message.author
1627 settings = self.casino_bank.check_server_settings(author.server)
1628
1629 if game.title() not in c_games:
1630 msg = "This game does not exist. Please pick from: {}".format(", ".join(c_games))
1631 elif multiplier > 0:
1632 multiplier = float(abs(multiplier))
1633 settings["Games"][game.title()]["Multiplier"] = multiplier
1634 self.casino_bank.save_system()
1635 msg = "Now setting the payout multiplier for {} to {}".format(game, multiplier)
1636 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1637 else:
1638 msg = "Multiplier needs to be higher than 0."
1639
1640 await self.bot.say(msg)
1641
1642 @setcasino.command(name="access", pass_context=True)
1643 @checks.admin_or_permissions(manage_server=True)
1644 async def _access_setcasino(self, ctx, game: str, access: int):
1645 """Set the access level for a game. Default is 0. Used with membership."""
1646
1647 author = ctx.message.author
1648 settings = self.casino_bank.check_server_settings(author.server)
1649 game = game.title()
1650
1651 if game not in c_games:
1652 msg = "This game does not exist. Please pick from: {}".format(", ".join(c_games))
1653 elif access >= 0:
1654 settings["Games"][game.title()]["Access Level"] = access
1655 self.casino_bank.save_system()
1656 msg = "{} changed the access level for {} to {}.".format(author.name, game, access)
1657 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1658 else:
1659 msg = "Access level must be higher than 0."
1660
1661 await self.bot.say(msg)
1662
1663 @setcasino.command(name="reqadd", pass_context=True)
1664 @checks.admin_or_permissions(manage_server=True)
1665 async def _reqadd_setcasino(self, ctx, *, membership):
1666 """Add a requirement to a membership"""
1667
1668 # Declare variables
1669 author = ctx.message.author
1670 settings = self.casino_bank.check_server_settings(author.server)
1671 cancel_message = "You took too long to respond. Cancelling requirement addition."
1672 requirement_options = ["Days On Server", "Credits", "Chips", "Role"]
1673 server_roles = [r.name for r in ctx.message.server.roles if r.name != "Bot"]
1674
1675 # Message checks
1676 check1 = lambda m: m.content.title() in requirement_options
1677 check2 = lambda m: m.content.isdigit() and int(m.content) > 0
1678 check3 = lambda m: m.content in server_roles
1679
1680 # Begin logic
1681 if membership not in settings["Memberships"]:
1682 await self.bot.say("This membership does not exist.")
1683 else:
1684
1685 await self.bot.say("Which of these requirements would you like to add to the {} "
1686 " membership?```{}.```NOTE: You cannot have multiple requirements of"
1687 " the same type.".format(membership, ', '.join(requirement_options)))
1688 rsp = await self.bot.wait_for_message(timeout=15, author=author, check=check1)
1689
1690 if rsp is None:
1691 await self.bot.say(cancel_message)
1692 return
1693
1694 else:
1695 # Determine amount for DoS, Credits, or Chips
1696 if rsp.content.title() != "Role":
1697 name = rsp.content.split(' ', 1)[0]
1698 await self.bot.say("How many {} are required?".format(name))
1699 reply = await self.bot.wait_for_message(timeout=15, author=author, check=check2)
1700
1701 if reply is None:
1702 await self.bot.say(cancel_message)
1703 return
1704 else:
1705 await self.bot.say("Adding the requirement of {} {} to the membership "
1706 "{}.".format(reply.content, rsp.content, membership))
1707 reply = int(reply.content)
1708
1709 # Determine the role for the requirement
1710 else:
1711 await self.bot.say("Which role would you like set? This role must already be "
1712 "set on server.")
1713 reply = await self.bot.wait_for_message(timeout=15, author=author, check=check3)
1714
1715 if reply is None:
1716 await self.bot.say(cancel_message)
1717 return
1718 else:
1719 await self.bot.say("Adding the requirement role of {} to the membership "
1720 "{}.".format(reply.content, membership))
1721 reply = reply.content
1722
1723 # Add and save the requirement
1724 key = rsp.content.title()
1725 settings["Memberships"][membership]["Requirements"][key] = reply
1726 self.casino_bank.save_system()
1727
1728 @setcasino.command(name="reqremove", pass_context=True)
1729 @checks.admin_or_permissions(manage_server=True)
1730 async def _reqremove_setcasino(self, ctx, *, membership):
1731 """Remove a requirement to a membership"""
1732
1733 # Declare variables
1734 author = ctx.message.author
1735 settings = self.casino_bank.check_server_settings(author.server)
1736
1737 if membership not in settings["Memberships"]:
1738 await self.bot.say("This membership does not exist.")
1739 else: # Membership was found.
1740 current_requirements = settings["Memberships"][membership]["Requirements"].keys()
1741
1742 if not current_requirements:
1743 return await self.bot.say("This membership has no requirements.")
1744
1745 check = lambda m: m.content.title() in current_requirements
1746
1747 await self.bot.say("The current requirements for this membership are:\n```{}```Which "
1748 "would you like to remove?".format(", ".join(current_requirements)))
1749 resp = await self.bot.wait_for_message(timeout=15, author=author, check=check)
1750
1751 if resp is None:
1752 return await self.bot.say("You took too long. Cancelling requirement removal.")
1753 else:
1754 settings["Memberships"][membership]["Requirements"].pop(resp.content.title())
1755 self.casino_bank.save_system()
1756 await self.bot.say("{} requirement removed from {}.".format(resp.content.title(),
1757 membership))
1758
1759 @setcasino.command(name="balance", pass_context=True)
1760 @checks.admin_or_permissions(manage_server=True)
1761 async def _balance_setcasino(self, ctx, user: discord.Member, chips: int):
1762 """Sets a Casino member's chip balance"""
1763 author = ctx.message.author
1764 settings = self.casino_bank.check_server_settings(author.server)
1765 chip_name = settings["System Config"]["Chip Name"]
1766 casino_name = settings["System Config"]["Casino Name"]
1767 try:
1768 self.casino_bank.set_chips(user, chips)
1769 except NegativeChips:
1770 return await self.bot.say("Chips must be higher than 0.")
1771 except UserNotRegistered:
1772 return await self.bot.say("You need to register to the {} Casino. To register type "
1773 "`{}casino join`.".format(casino_name, ctx.prefix))
1774 else:
1775 logger.info("SETTINGS CHANGED {}({}) set {}({}) chip balance to "
1776 "{}".format(author.name, author.id, user.name, user.id, chips))
1777 await self.bot.say("```Python\nSetting the chip balance of {} to "
1778 "{} {} chips.```".format(user.name, chips, chip_name))
1779
1780 @setcasino.command(name="exchange", pass_context=True)
1781 @checks.admin_or_permissions(manage_server=True)
1782 async def _exchange_setcasino(self, ctx, rate: float, currency: str):
1783 """Sets the exchange rate for chips or credits"""
1784 author = ctx.message.author
1785 settings = self.casino_bank.check_server_settings(author.server)
1786
1787 if rate <= 0:
1788 msg = "Rate must be higher than 0. Default is 1."
1789 elif currency.title() == "Chips":
1790 settings["System Config"]["Chip Rate"] = rate
1791 logger.info("{}({}) changed the chip rate to {}".format(author.name, author.id, rate))
1792 self.casino_bank.save_system()
1793 msg = "Setting the exchange rate for credits to chips to {}.".format(rate)
1794 elif currency.title() == "Credits":
1795 settings["System Config"]["Credit Rate"] = rate
1796 logger.info("SETTINGS CHANGED {}({}) changed the credit rate to "
1797 "{}".format(author.name, author.id, rate))
1798 self.casino_bank.save_system()
1799 msg = "Setting the exchange rate for chips to credits to {}.".format(rate)
1800 else:
1801 msg = "Please specify chips or credits"
1802
1803 await self.bot.say(msg)
1804
1805 @setcasino.command(name="name", pass_context=True)
1806 @checks.admin_or_permissions(manage_server=True)
1807 async def _name_setcasino(self, ctx, *, name: str):
1808 """Sets the name of the Casino."""
1809 author = ctx.message.author
1810 settings = self.casino_bank.check_server_settings(author.server)
1811 settings["System Config"]["Casino Name"] = name
1812 self.casino_bank.save_system()
1813 msg = "Changed the casino name to {}.".format(name)
1814 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1815 await self.bot.say(msg)
1816
1817 @setcasino.command(name="chipname", pass_context=True)
1818 @checks.admin_or_permissions(manage_server=True)
1819 async def _chipname_setcasino(self, ctx, *, name: str):
1820 """Sets the name of your Casino chips."""
1821 author = ctx.message.author
1822 settings = self.casino_bank.check_server_settings(author.server)
1823 settings["System Config"]["Chip Name"] = name
1824 self.casino_bank.save_system()
1825 msg = ("Changed the name of your chips to {0}.\nTest Display:\n"
1826 "```Python\nCongratulations, you just won 50 {0} chips.```".format(name))
1827 logger.info("SETTINGS CHANGED {}({}) chip name set to "
1828 "{}".format(author.name, author.id, name))
1829
1830 await self.bot.say(msg)
1831
1832 @setcasino.command(name="cooldown", pass_context=True)
1833 @checks.admin_or_permissions(manage_server=True)
1834 async def _cooldown_setcasino(self, ctx, game, seconds: int):
1835 """Set the cooldown period for casino games"""
1836 author = ctx.message.author
1837 settings = self.casino_bank.check_server_settings(author.server)
1838
1839 if game.title() not in c_games:
1840 msg = "This game does not exist. Please pick from: {}".format(", ".join(c_games))
1841 else:
1842 settings["Games"][game.title()]["Cooldown"] = seconds
1843 time_set = self.time_format(seconds)
1844 self.casino_bank.save_system()
1845 msg = "Setting the cooldown period for {} to {}.".format(game, time_set)
1846 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1847
1848 await self.bot.say(msg)
1849
1850 @setcasino.command(name="min", pass_context=True)
1851 @checks.admin_or_permissions(manage_server=True)
1852 async def _min_setcasino(self, ctx, game, minbet: int):
1853 """Set the minimum bet to play a game"""
1854 author = ctx.message.author
1855 settings = self.casino_bank.check_server_settings(author.server)
1856 min_games = [x for x in c_games if x != "Allin"]
1857
1858 if game.title() not in min_games:
1859 msg = "This game does not exist. Please pick from: {}".format(", ".join(min_games))
1860 elif minbet < 0:
1861 msg = "You need to set a minimum bet higher than 0."
1862 elif minbet < settings["Games"][game.title()]["Max"]:
1863 settings["Games"][game.title()]["Min"] = minbet
1864 chips = settings["System Config"]["Chip Name"]
1865 self.casino_bank.save_system()
1866 msg = ("Setting the minimum bet for {} to {} {} "
1867 "chips.".format(game.title(), minbet, chips))
1868 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1869 else:
1870 maxbet = settings["Games"][game.title()]["Max"]
1871 msg = ("The minimum bet can't bet set higher than the maximum bet of "
1872 "{} for {}.".format(maxbet, game.title()))
1873
1874 await self.bot.say(msg)
1875
1876 @setcasino.command(name="max", pass_context=True)
1877 @checks.admin_or_permissions(manage_server=True)
1878 async def _max_setcasino(self, ctx, game, maxbet: int):
1879 """Set the maximum bet to play a game"""
1880 author = ctx.message.author
1881 settings = self.casino_bank.check_server_settings(author.server)
1882 max_games = [x for x in c_games if x != "Allin"]
1883
1884 if game.title() not in max_games:
1885 msg = "This game does not exist. Please pick from: {}".format(", ".join(max_games))
1886 elif maxbet <= 0:
1887 msg = "You need to set a maximum bet higher than 0."
1888 elif maxbet > settings["Games"][game.title()]["Min"]:
1889 settings["Games"][game.title()]["Max"] = maxbet
1890 chips = settings["System Config"]["Chip Name"]
1891 self.casino_bank.save_system()
1892 msg = ("Setting the maximum bet for {} to {} {} "
1893 "chips.".format(game.title(), maxbet, chips))
1894 logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
1895 else:
1896 minbet = settings["Games"][game.title()]["Min"]
1897 msg = "The max bet needs be higher than the minimum bet of {}.".format(minbet)
1898
1899 await self.bot.say(msg)
1900
1901 async def table_split(self, user, headers, data, sort):
1902 groups = [data[i:i + 20] for i in range(0, len(data), 20)]
1903 pages = len(groups)
1904
1905 if sort == "place":
1906 name = "[{}]".format(user.name)
1907 page = next((idx for idx, sub in enumerate(groups) for tup in sub if name in tup), None)
1908 if not page:
1909 page = 0
1910 table = tabulate(groups[page], headers=headers, numalign="left", tablefmt="simple")
1911 msg = ("```ini\n{}``````Python\nYou are viewing page {} of {}. "
1912 "{} casino members.```".format(table, page + 1, pages, len(data)))
1913 return msg
1914 elif pages == 1:
1915 page = 0
1916 table = tabulate(groups[page], headers=headers, numalign="left", tablefmt="simple")
1917 msg = ("```ini\n{}``````Python\nYou are viewing page 1 of {}. "
1918 "{} casino members```".format(table, pages, len(data)))
1919 return msg
1920
1921 await self.bot.say("There are {} pages of high scores. "
1922 "Which page would you like to display?".format(pages))
1923 response = await self.bot.wait_for_message(timeout=15, author=user)
1924 if response is None:
1925 page = 0
1926 table = tabulate(groups[page], headers=headers, numalign="left", tablefmt="simple")
1927 msg = ("```ini\n{}``````Python\nYou are viewing page {} of {}. "
1928 "{} casino members.```".format(table, page + 1, pages, len(data)))
1929 return msg
1930 else:
1931 try:
1932 page = int(response.content) - 1
1933 table = tabulate(groups[page], headers=headers, numalign="left", tablefmt="simple")
1934 msg = ("```ini\n{}``````Python\nYou are viewing page {} of {}. "
1935 "{} casino members.```".format(table, page + 1, pages, len(data)))
1936 return msg
1937 except ValueError:
1938 await self.bot.say("Sorry your response was not a number. Defaulting to page 1")
1939 page = 0
1940 table = tabulate(groups[page], headers=headers, numalign="left", tablefmt="simple")
1941 msg = ("```ini\n{}``````Python\nYou are viewing page 1 of {}. "
1942 "{} casino members```".format(table, pages, len(data)))
1943 return msg
1944
1945 async def membership_updater(self):
1946 """Updates user membership based on requirements every 5 minutes"""
1947 await self.bot.wait_until_ready()
1948 try:
1949 await asyncio.sleep(15)
1950 bank = self.bot.get_cog('Economy').bank
1951 while True:
1952 servers = self.casino_bank.get_all_servers()
1953 for server in servers:
1954 try:
1955 server_obj = self.bot.get_server(server)
1956 settings = self.casino_bank.check_server_settings(server_obj)
1957 except AttributeError:
1958 continue
1959 else:
1960 user_path = self.casino_bank.get_server_memberships(server_obj)
1961 users = [server_obj.get_member(user) for user in user_path
1962 if server_obj.get_member(user) is not None] # Check for None
1963 if users:
1964 for user in users:
1965 membership = self.gather_requirements(settings, user, bank)
1966 settings["Players"][user.id]["Membership"] = membership
1967 else:
1968 continue
1969 self.casino_bank.save_system()
1970 await asyncio.sleep(300) # Wait 5 minutes
1971 except asyncio.CancelledError:
1972 pass
1973
1974 async def war_game(self, user, settings, deck, amount):
1975 player_card, dealer_card, pc, dc = self.war_draw(deck)
1976 multiplier = settings["Games"]["War"]["Multiplier"]
1977
1978 await self.bot.say("The dealer shuffles the deck and deals 1 card face down to the player "
1979 "and dealer...")
1980 await asyncio.sleep(2)
1981 await self.bot.say("**FLIP!**")
1982 await asyncio.sleep(1)
1983
1984 if pc > dc:
1985 outcome = "Win"
1986 amount = int(amount * multiplier)
1987 elif dc > pc:
1988 outcome = "Loss"
1989 else:
1990 check = lambda m: m.content.title() in ["War", "Surrender", "Ffs"]
1991 await self.bot.say("The player and dealer are both showing a **{}**!\nTHIS MEANS WAR! "
1992 "You may choose to surrender and forfeit half your bet, or you can "
1993 "go to war.\nYour bet will be doubled, but you will only win on "
1994 "half the bet, the rest will be pushed.".format(player_card))
1995 choice = await self.bot.wait_for_message(timeout=15, author=user, check=check)
1996
1997 if choice is None or choice.content.title() in ["Surrender", "Ffs"]:
1998 outcome = "Surrender"
1999 amount = int(amount / 2)
2000 elif choice.content.title() == "War":
2001 self.casino_bank.withdraw_chips(user, amount)
2002 player_card, dealer_card, pc, dc = self.burn_three(deck)
2003
2004 await self.bot.say("The dealer burns three cards and deals two cards face down...")
2005 await asyncio.sleep(3)
2006 await self.bot.say("**FLIP!**")
2007
2008 if pc >= dc:
2009 outcome = "Win"
2010 amount = int(amount * multiplier + amount)
2011 else:
2012 outcome = "Loss"
2013 else:
2014 await self.bot.say("Improper response. You are being forced to forfeit.")
2015 outcome = "Surrender"
2016 amount = int(amount / 2)
2017
2018 return outcome, player_card, dealer_card, amount
2019
2020 async def blackjack_game(self, dh, user, amount, deck):
2021 # Setup dealer and player starting hands
2022 ph = self.draw_two(deck)
2023 count = self.count_hand(ph)
2024 # checks used to ensure the player uses the correct input
2025 check = lambda m: m.content.title() in ["Hit", "Stay", "Double"]
2026 check2 = lambda m: m.content.title() in ["Hit", "Stay"]
2027
2028 # End the game if the player has 21 in the starting hand.
2029 if count == 21:
2030 return ph, dh, amount
2031
2032 msg = ("{}\nYour cards: {}\nYour score: {}\nThe dealer shows: "
2033 "{}\nHit, stay, or double?".format(user.mention, ", ".join(ph), count, dh[0]))
2034 await self.bot.say(msg)
2035 choice = await self.bot.wait_for_message(timeout=15, author=user, check=check)
2036
2037 # Stop the blackjack game if the player chooses stay or double.
2038 if choice is None or choice.content.title() == "Stay":
2039 return ph, dh, amount
2040 elif choice.content.title() == "Double":
2041 # Create a try/except block to catch when people are dumb and don't have enough chips
2042 try:
2043 self.casino_bank.withdraw_chips(user, amount)
2044 amount = amount * 2
2045 ph = self.draw_card(ph, deck)
2046 count = self.count_hand(ph)
2047 return ph, dh, amount
2048 except InsufficientChips:
2049 await self.bot.say("Not enough chips. Please choose hit or stay.")
2050 choice2 = await self.bot.wait_for_message(timeout=15, author=user, check=check2)
2051
2052 if choice2 is None or choice2.content.title() == "Stay":
2053 return ph, dh, amount
2054
2055 elif choice2.content.title() == "Hit":
2056 # This breaks PEP8 for DRY but I didn't want to create a sperate coroutine.
2057 while count < 21:
2058 ph = self.draw_card(ph, deck)
2059 count = self.count_hand(ph)
2060
2061 if count >= 21:
2062 break
2063 msg = ("{}\nYour cards: {}\nYour score: {}\nThe dealer shows: "
2064 "{}\nHit or stay?".format(user.mention, ", ".join(ph), count, dh[0]))
2065 await self.bot.say(msg)
2066 resp = await self.bot.wait_for_message(timeout=15, author=user,
2067 check=check2)
2068
2069 if resp is None or resp.content.title() == "Stay":
2070 break
2071 else:
2072 continue
2073 # Return player hand & dealer hand when count >= 21 or the player picks stay.
2074 return ph, dh, amount
2075
2076 # Continue game logic in a loop until the player's count is 21 or bust.
2077 elif choice.content.title() == "Hit":
2078 while count < 21:
2079 ph = self.draw_card(ph, deck)
2080 count = self.count_hand(ph)
2081
2082 if count >= 21:
2083 break
2084 msg = ("{}\nYour cards: {}\nYour score: {}\nThe dealer shows: "
2085 "{}\nHit or stay?".format(user.mention, ", ".join(ph), count, dh[0]))
2086 await self.bot.say(msg)
2087 response = await self.bot.wait_for_message(timeout=15, author=user, check=check2)
2088
2089 if response is None or response.content.title() == "Stay":
2090 break
2091 else:
2092 continue
2093 # Return player hand and dealer hand when count is 21 or greater or player picks stay.
2094 return ph, dh, amount
2095
2096 def war_results(self, settings, user, outcome, player_card, dealer_card, amount):
2097 chip_name = settings["System Config"]["Chip Name"]
2098 msg = ("======**{}**======\nPlayer Card: {}"
2099 "\nDealer Card: {}\n".format(user.name, player_card, dealer_card))
2100 if outcome == "Win":
2101 settings["Players"][user.id]["Won"]["War Won"] += 1
2102 # Check if a threshold is set and withold chips if amount is exceeded
2103 if self.threshold_check(settings, amount):
2104 settings["Players"][user.id]["Pending"] = amount
2105 msg += ("Your winnings exceeded the threshold set on this server. "
2106 "The amount of {} {} chips will be withheld until reviewed and "
2107 "released by an admin. Do not attempt to play additional games "
2108 "exceeding the threshold until this has been cleared."
2109 "".format(amount, chip_name, user.id))
2110 logger.info("{}({}) won {} chips exceeding the threshold. Game "
2111 "details:\nPlayer Bet: {}\nGame "
2112 "Outcome: {}\n[END OF FILE]".format(user.name, user.id, amount,
2113 str(amount).ljust(10),
2114 str(outcome[0]).ljust(10)))
2115 else:
2116 self.casino_bank.deposit_chips(user, amount)
2117 msg += ("**\*\*\*\*\*\*Winner!\*\*\*\*\*\***\n```Python\nYou just won {} {} "
2118 "chips.```".format(amount, chip_name))
2119
2120 elif outcome == "Loss":
2121 msg += "======House Wins!======"
2122 else:
2123 self.casino_bank.deposit_chips(user, amount)
2124 msg = ("======**{}**======\n:flag_white: Surrendered :flag_white:\n==================\n"
2125 "{} {} chips returned.".format(user.name, amount, chip_name))
2126
2127 # Save results and return appropriate outcome message.
2128 self.casino_bank.save_system()
2129 return msg
2130
2131 def blackjack_results(self, settings, user, amount, ph, dh):
2132 chip_name = settings["System Config"]["Chip Name"]
2133 dc = self.count_hand(dh)
2134 pc = self.count_hand(ph)
2135 msg = ("======**{}**======\nYour hand: {}\nYour score: {}\nDealer's hand: {}\nDealer's "
2136 "score: {}\n".format(user.name, ", ".join(ph), pc, ", ".join(dh), dc))
2137
2138 if dc > 21 and pc <= 21 or dc < pc <= 21:
2139 settings["Players"][user.id]["Won"]["BJ Won"] += 1
2140 total = int(round(amount * settings["Games"]["Blackjack"]["Multiplier"]))
2141 # Check if a threshold is set and withold chips if amount is exceeded
2142 if self.threshold_check(settings, total):
2143 settings["Players"][user.id]["Pending"] = total
2144 msg = ("Your winnings exceeded the threshold set on this server. "
2145 "The amount of {} {} chips will be withheld until reviewed and "
2146 "released by an admin. Do not attempt to play additional games "
2147 "exceeding the threshold until this has been cleared."
2148 "".format(total, chip_name, user.id))
2149 logger.info("{}({}) won {} chips exceeding the threshold. Game "
2150 "details:\nPlayer Bet: {}\nGame\n"
2151 "[END OF FILE]".format(user.name, user.id, total, str(total).ljust(10)))
2152 else:
2153 msg += ("**\*\*\*\*\*\*Winner!\*\*\*\*\*\***\n```Python\nYou just "
2154 "won {} {} chips.```".format(total, chip_name))
2155 self.casino_bank.deposit_chips(user, total)
2156 elif pc > 21:
2157 msg += "======BUST!======"
2158 elif dc == pc and dc <= 21 and pc <= 21:
2159 msg += ("======Pushed======\nReturned {} {} chips to your "
2160 "account.".format(amount, chip_name))
2161 amount = int(round(amount))
2162 self.casino_bank.deposit_chips(user, amount)
2163 elif dc > pc and dc <= 21:
2164 msg += "======House Wins!======".format(user.name)
2165 # Save results and return appropriate outcome message.
2166 self.casino_bank.save_system()
2167 return msg
2168
2169 def draw_two(self, deck):
2170 hand = random.sample(deck, 2)
2171 deck.remove(hand[0])
2172 deck.remove(hand[1])
2173 return hand
2174
2175 def draw_card(self, hand, deck):
2176 card = random.choice(deck)
2177 deck.remove(card)
2178 hand.append(card)
2179 return hand
2180
2181 def count_hand(self, hand):
2182 count = sum([bj_values[x] for x in hand if x in bj_values])
2183 count += sum([1 if x == 'Ace' and count + 11 > 21 else 11
2184 if x == 'Ace' and hand.count('Ace') == 1 else 1
2185 if x == 'Ace' and hand.count('Ace') > 1 else 0 for x in hand])
2186 return count
2187
2188 def dealer(self, deck):
2189 dh = self.draw_two(deck)
2190 count = self.count_hand(dh)
2191
2192 # forces hit if ace in first two cards
2193 if 'Ace' in dh:
2194 dh = self.draw_card(dh, deck)
2195 count = self.count_hand(dh)
2196
2197 # defines maximum hit score X
2198 while count < 16:
2199 self.draw_card(dh, deck)
2200 count = self.count_hand(dh)
2201 return dh
2202
2203 def war_draw(self, deck):
2204 player_card = random.choice(deck)
2205 deck.remove(player_card)
2206 dealer_card = random.choice(deck)
2207 pc = war_values[player_card]
2208 dc = war_values[dealer_card]
2209 return player_card, dealer_card, pc, dc
2210
2211 def burn_three(self, deck):
2212 burn_cards = random.sample(deck, 3)
2213
2214 for x in burn_cards:
2215 deck.remove(x)
2216
2217 player_card = random.choice(deck)
2218 deck.remove(player_card)
2219 dealer_card = random.choice(deck)
2220 pc = war_values[player_card]
2221 dc = war_values[dealer_card]
2222
2223 return player_card, dealer_card, pc, dc
2224
2225 def gather_requirements(self, settings, user, bank):
2226 # Declare variables
2227 path = settings["Memberships"]
2228 memberships = settings["Memberships"]
2229 memberships_met = []
2230 # Loop through the memberships and their requirements
2231 for membership in memberships:
2232 req_switch = False
2233 for req in path[membership]["Requirements"]:
2234
2235 # If the requirement is a role, run role logic
2236 if req == "Role":
2237 role = path[membership]["Requirements"]["Role"]
2238 if role in [r.name for r in user.roles]:
2239 req_switch = True
2240 else:
2241 req_switch = False
2242 # If the requirement is a credits, run credit logic
2243 elif req == "Credits":
2244 if bank.account_exists(user):
2245 user_credits = bank.get_balance(user)
2246 if user_credits >= int(path[membership]["Requirements"]["Credits"]):
2247 req_switch = True
2248 else:
2249 req_switch = False
2250 else:
2251 req_switch = False
2252
2253 # If the requirement is a chips, run chip logic
2254 elif req == "Chips":
2255 balance = self.casino_bank.chip_balance(user)
2256 if balance >= int(path[membership]["Requirements"][req]):
2257 req_switch = True
2258 else:
2259 req_switch = False
2260
2261 # If the requirement is a DoS, run DoS logic
2262 elif req == "Days On Server":
2263 dos = (datetime.utcnow() - user.joined_at).days
2264 if dos >= path[membership]["Requirements"]["Days On Server"]:
2265 req_switch = True
2266 else:
2267 req_switch = False
2268
2269 # You have to meet all the requirements to qualify for the membership
2270 if req_switch:
2271 memberships_met.append((membership, path[membership]["Access"]))
2272
2273 # Returns the membership with the highest access value
2274 if memberships_met:
2275 try:
2276 membership = max(memberships_met, key=itemgetter(1))[0]
2277 return membership
2278 except (ValueError, TypeError):
2279 return
2280
2281 else: # Returns none if the user has not qualified for any memberships
2282 return
2283
2284 def get_benefits(self, settings, player):
2285 payday = settings["System Config"]["Default Payday"]
2286 benefits = {"Cooldown Reduction": 0, "Access": 0, "Payday": payday, "Color": "grey"}
2287 membership = settings["Players"][player]["Membership"]
2288
2289 if membership:
2290 if membership in settings["Memberships"]:
2291 benefits = settings["Memberships"][membership]
2292 else:
2293 settings["Players"][player]["Membership"] = None
2294 self.casino_bank.save_system()
2295 membership = None
2296
2297 return membership, benefits
2298
2299 def threshold_check(self, settings, amount):
2300 if settings["System Config"]["Threshold Switch"]:
2301 if amount > settings["System Config"]["Threshold"]:
2302 return True
2303 else:
2304 return False
2305 else:
2306 return False
2307
2308 def hl_outcome(self, dicetotal):
2309 choices = [(1, "Lo", "Low"), (2, "Lo", "Low"), (3, "Lo", "Low"), (4, "Lo", "Low"),
2310 (5, "Lo", "Low"), (6, "Lo", "Low"), (7, "7", "Seven"), (8, "Hi", "High"),
2311 (9, "Hi", "High"), (10, "Hi", "High"), (11, "Hi", "High"), (12, "Hi", "High")]
2312 outcome = choices[dicetotal - 1]
2313 return outcome
2314
2315 def minmax_check(self, bet, game, settings):
2316 mi = settings["Games"][game]["Min"]
2317 mx = settings["Games"][game]["Max"]
2318
2319 if mi <= bet <= mx:
2320 return None
2321 else:
2322 if mi != mx:
2323 msg = ("Your bet needs to be {} or higher, but cannot exceed the "
2324 "maximum of {} chips.".format(mi, mx))
2325 else:
2326 msg = ("Your bet needs to be exactly {}.".format(mi))
2327 return msg
2328
2329 def stats_cooldowns(self, settings, user, cd_list):
2330 user_membership = settings["Players"][user.id]["Membership"]
2331 reduction = 0
2332
2333 # Check for cooldown reduction, if the membership was removed, set the user back to None.
2334 try:
2335 if user_membership:
2336 reduction = settings["Memberships"][user_membership]["Cooldown Reduction"]
2337 except KeyError:
2338 settings["Players"][user.id]["Membership"] = None
2339 self.casino_bank.save_system()
2340
2341 # Begin cooldown logic calculation
2342 cooldowns = []
2343 for method in cd_list:
2344 user_time = settings["Players"][user.id]["Cooldowns"][method]
2345
2346 # Check if method is for a game or for payday
2347 if method in c_games:
2348 base = settings["Games"][method]["Cooldown"]
2349 else:
2350 reduction = 0
2351 base = settings["System Config"]["Payday Timer"]
2352
2353 # Begin cooldown logic calculation
2354 if user_time == 0: # For new accounts
2355 cooldowns.append("<<Ready to Play!")
2356 elif (datetime.utcnow() - parser.parse(user_time)).seconds + reduction < base:
2357 ut = parser.parse(user_time)
2358 seconds = abs((datetime.utcnow() - ut).seconds - base - reduction)
2359 remaining = self.time_format(seconds, brief=True)
2360 cooldowns.append(remaining)
2361 else:
2362 cooldowns.append("<<Ready to Play!")
2363 return cooldowns
2364
2365 def check_cooldowns(self, user, method, settings):
2366 user_time = settings["Players"][user.id]["Cooldowns"][method]
2367 user_membership = settings["Players"][user.id]["Membership"]
2368 reduction = 0
2369
2370 # Check for cooldown reduction, if the membership was removed, set the user back to None.
2371 try:
2372 if user_membership:
2373 reduction = settings["Memberships"][user_membership]["Cooldown Reduction"]
2374 except KeyError:
2375 settings["Players"][user.id]["Membership"] = None
2376 self.casino_bank.save_system()
2377 # Check if method is for a game or for payday
2378 if method in c_games:
2379 base = settings["Games"][method]["Cooldown"]
2380 elif method == "Payday":
2381 reduction = 0
2382 base = settings["System Config"]["Payday Timer"]
2383 else:
2384 reduction = 0
2385 base = settings["System Config"]["Transfer Cooldown"]
2386
2387 # Begin cooldown logic calculation
2388 if user_time == 0: # For new accounts
2389 settings["Players"][user.id]["Cooldowns"][method] = datetime.utcnow().isoformat()
2390 self.casino_bank.save_system()
2391 return None
2392 elif (datetime.utcnow() - parser.parse(user_time)).seconds + reduction < base:
2393 seconds = abs((datetime.utcnow() - parser.parse(user_time)).seconds - base - reduction)
2394 remaining = self.time_format(seconds)
2395 msg = "{} is still on a cooldown. You still have: {}".format(method, remaining)
2396 return msg
2397 else:
2398 settings["Players"][user.id]["Cooldowns"][method] = datetime.utcnow().isoformat()
2399 self.casino_bank.save_system()
2400 return None
2401
2402 def access_calculator(self, settings, user):
2403 user_membership = settings["Players"][user.id]["Membership"]
2404
2405 if user_membership is None:
2406 return 0
2407 else:
2408 if user_membership in settings["Memberships"]:
2409 access = settings["Memberships"][user_membership]["Access"]
2410 return access
2411 else:
2412 settings["Players"][user.id]["Membership"] = None
2413 self.casino_bank.save_system()
2414 return 0
2415
2416 def game_checks(self, settings, prefix, user, bet, game, choice, choices):
2417 casino_name = settings["System Config"]["Casino Name"]
2418 game_access = settings["Games"][game]["Access Level"]
2419 # Allin does not require a minmax check, so we set it to None if Allin.
2420 if game != "Allin":
2421 minmax_fail = self.minmax_check(bet, game, settings)
2422 else:
2423 minmax_fail = None
2424 bet = int(settings["Players"][user.id]["Chips"])
2425 # Check for membership first.
2426 try:
2427 self.casino_bank.can_bet(user, bet)
2428 except UserNotRegistered:
2429 msg = ("You need to register to the {} Casino. To register type `{}casino "
2430 "join`.".format(casino_name, prefix))
2431 return msg
2432 except InsufficientChips:
2433 msg = "You do not have enough chips to cover the bet."
2434 return msg
2435
2436 # Check if casino json file has the hi-lo game, and if not add it.
2437 if "Hi-Lo Played" not in settings["Players"][user.id]["Played"]:
2438 self.player_update(settings["Players"][user.id], hilo_data)
2439
2440 if "War Played" not in settings["Players"][user.id]["Played"]:
2441 self.player_update(settings["Players"][user.id], war_data)
2442
2443 user_access = self.access_calculator(settings, user)
2444 # Begin logic to determine if the game can be played.
2445 if choice not in choices:
2446 msg = "Incorrect response. Accepted response are:\n{}".format(", ".join(choices))
2447 return msg
2448 elif not settings["System Config"]["Casino Open"]:
2449 msg = "The {} Casino is closed.".format(casino_name)
2450 return msg
2451 elif game_access > user_access:
2452 msg = ("{} requires an access level of {}. Your current access level is {}. Obtain a "
2453 "higher membership to play this game.")
2454 return msg
2455 elif minmax_fail:
2456 msg = minmax_fail
2457 return msg
2458 else:
2459 cd_check = self.check_cooldowns(user, game, settings)
2460 # Cooldowns are checked last incase another check failed.
2461 return cd_check
2462
2463 def color_lookup(self, color):
2464 color = color.lower()
2465 colors = {"blue": 0x3366FF, "red": 0xFF0000, "green": 0x00CC33, "orange": 0xFF6600,
2466 "purple": 0xA220BD, "yellow": 0xFFFF00, "teal": 0x009999, "magenta": 0xBA2586,
2467 "turquoise": 0x00FFFF, "grey": 0x666666, "pink": 0xFE01D1, "white": 0xFFFFFF}
2468 color = colors[color]
2469 return color
2470
2471 def player_update(self, player_data, new_game, path=None):
2472 """Helper function to add new data into the player's data"""
2473
2474 if path is None:
2475 path = []
2476 for key in new_game:
2477 if key in player_data:
2478 if isinstance(player_data[key], dict) and isinstance(new_game[key], dict):
2479 self.player_update(player_data[key], new_game[key], path + [str(key)])
2480 elif player_data[key] == new_game[key]:
2481 pass
2482 else:
2483 raise Exception("Conflict at {}".format("".join(path + [str(key)])))
2484 else:
2485 player_data[key] = new_game[key]
2486 self.casino_bank.save_system()
2487
2488 def time_format(self, seconds, brief=False):
2489 # Calculate the time and input into a dict to plural the strings later.
2490 m, s = divmod(seconds, 60)
2491 h, m = divmod(m, 60)
2492 data = PluralDict({'hour': h, 'minute': m, 'second': s})
2493
2494 # Determine the remaining time.
2495 if not brief:
2496 if h > 0:
2497 fmt = "{hour} hour{hour(s)}"
2498 if data["minute"] > 0 and data["second"] > 0:
2499 fmt += ", {minute} minute{minute(s)}, and {second} second{second(s)}"
2500 if data["second"] > 0 == data["minute"]:
2501 fmt += ", and {second} second{second(s)}"
2502 msg = fmt.format_map(data)
2503 elif h == 0 and m > 0:
2504 if data["second"] == 0:
2505 fmt = "{minute} minute{minute(s)}"
2506 else:
2507 fmt = "{minute} minute{minute(s)}, and {second} second{second(s)}"
2508 msg = fmt.format_map(data)
2509 elif m == 0 and h == 0 and s > 0:
2510 fmt = "{second} second{second(s)}"
2511 msg = fmt.format_map(data)
2512 else:
2513 msg = "None"
2514 # Return remaining time.
2515 else:
2516
2517 if h > 0:
2518 msg = "{0}h"
2519 if m > 0 and s > 0:
2520 msg += ", {1}m, and {2}s"
2521
2522 elif s > 0 and m == 0:
2523 msg += "and {2}s"
2524 elif h == 0 and m > 0:
2525 if s == 0:
2526 msg = "{1}m"
2527 else:
2528 msg = "{1}m and {2}s"
2529 elif m == 0 and h == 0 and s > 0:
2530 msg = "{2}s"
2531 else:
2532 msg = "None"
2533 return msg.format(h, m, s)
2534
2535 def __unload(self):
2536 self.cycle_task.cancel()
2537 self.casino_bank.save_system()
2538
2539
2540def check_folders():
2541 if not os.path.exists("data/JumperCogs/casino"):
2542 print("Creating data/JumperCogs/casino folder...")
2543 os.makedirs("data/JumperCogs/casino")
2544
2545
2546def check_files():
2547 system = {"Servers": {}}
2548
2549 f = "data/JumperCogs/casino/casino.json"
2550 if not dataIO.is_valid_json(f):
2551 print("Creating default casino.json...")
2552 dataIO.save_json(f, system)
2553
2554
2555def setup(bot):
2556 global logger
2557 check_folders()
2558 check_files()
2559 logger = logging.getLogger("red.casino")
2560 if logger.level == 0:
2561 logger.setLevel(logging.INFO)
2562 # Rotates to a new file every 10mb, up to 5
2563 handler = logging.handlers.RotatingFileHandler(filename='data/JumperCogs/casino/casino.log',
2564 encoding='utf-8', backupCount=5,
2565 maxBytes=100000)
2566 handler.setFormatter(logging.Formatter('%(asctime)s %(name)-12s %(message)s',
2567 datefmt="[%d/%m/%Y %H:%M]"))
2568 logger.addHandler(handler)
2569 if not tabulateAvailable:
2570 raise RuntimeError("You need to run 'pip3 install tabulate'")
2571 elif not dateutilAvailable:
2572 raise RuntimeError("You need to install the library python-dateutil.")
2573 else:
2574 bot.add_cog(Casino(bot))