async def trade(self, ctx, *args): """Trades to a person a number of a given object for a given price.""" if has_post_permission(ctx.guild.id, ctx.channel.id): if len(args) < 4: await ctx.send( 'Arguments missing. ' 'Syntax is `~trade [name] [number] [item] [offer]`.') return try: trade = { 'user1': ctx.author.id, 'user2': args[0], 'amount1': args[1], 'amount2': args[-1], 'item1': ' '.join(args[2:-1]), 'item2': 'coins' } ctx.bot.trade_manager.add_trade(ctx, trade) except TradeError as e: await ctx.send(e.msg) return name = args[0] for member in ctx.guild.members: if name.lower() in member.name.lower(): name_member = member break offer = users.parse_int(args[-1]) number = users.parse_int(args[1]) itemid = items.find_by_name(' '.join(args[2:-1])) name = get_display_name(ctx.author) offer_formatted = '{:,}'.format(offer) out = ( f'{items.SHOP_HEADER}{name.title()} wants to sell {name_member.mention} ' f'{items.add_plural(number, itemid)} for {offer_formatted} coins. ' f'To accept this offer, reply to this post with a :thumbsup:. ' f'Otherwise, this offer will expire in one minute.') msg = await ctx.send(out) if await self.confirm(ctx, msg, out, timeout=60): price = {"0": offer} users.update_inventory(name_member.id, price, remove=True) users.update_inventory(ctx.author.id, price) loot = {itemid: number} users.update_inventory(ctx.author.id, loot, remove=True) users.update_inventory(name_member.id, loot) buyer_name = get_display_name(name_member) await ctx.send( f'{items.SHOP_HEADER}{name.title()} successfully sold ' f'{items.add_plural(number, itemid)} to {buyer_name} for ' f'{offer_formatted} coins!') ctx.bot.trade_manager.reset_trade(trade, ctx.author.id, name_member.id)
async def sellall(self, ctx, maxvalue=None): """Sells all items in the player's inventory (below a certain value) for gold pieces.""" if has_post_permission(ctx.guild.id, ctx.channel.id): name = get_display_name(ctx.author) if maxvalue is not None: value = users.get_value_of_inventory(ctx.author.id, under=maxvalue) users.update_inventory(ctx.author.id, value * ["0"]) users.clear_inventory(ctx.author.id, under=maxvalue) value_formatted = '{:,}'.format(value) maxvalue_formatted = '{:,}'.format(users.parse_int(maxvalue)) name = get_display_name(ctx.author) out = f"All items in {name}'s inventory worth under {maxvalue_formatted} coins "\ f"sold for {value_formatted} coins!" else: value = users.get_value_of_inventory(ctx.author.id) users.update_inventory(ctx.author.id, value * ["0"]) users.clear_inventory(ctx.author.id) value_formatted = '{:,}'.format(value) out = f"All items in {name}'s inventory "\ f"sold for {value_formatted} coins!" await ctx.send(out)
async def deathmatch(self, ctx, opponent='rand', bet=None): """Allows users to duke it out in a 1v1 match.""" author = ctx.user_object author_name = author.plain_name if bet is not None: if author.is_ironman: await ctx.send('Ironmen cannot start staked deathmatches.') return try: bet = users.parse_int(bet) except ValueError: await ctx.send(f'{bet} does not represent a valid number.') bet_formatted = '{:,}'.format(bet) if not author.has_item_amount_by_name('coins', bet): await ctx.send(f'You do not have {bet_formatted} coins.') return try: opponent_member = parse_name(ctx.message.guild, opponent) opponent_obj = User.objects.get(id=opponent_member.id) opponent_name = opponent_obj.plain_name except NameError: await ctx.send(f'{opponent} not found in server.') return except AmbiguousInputError as members: await ctx.send( f'Input {opponent} can refer to multiple people ({members})' ) return if opponent_obj == author: await ctx.send('You cannot fight yourself.') return if opponent_obj.is_ironman: await ctx.send( 'You cannot start a staked deathmatch with an ironman.') return if not opponent_obj.has_item_amount_by_name('coins', bet): await ctx.send( f'{opponent_name} does not have {bet_formatted} coins.') return author.update_inventory({'0': bet}, remove=True) out = f'Deathmatch set up between {author_name} and {opponent_member.mention} with bet ' \ f'{bet_formatted} coins! To confirm this match, {opponent_name} must react to ' \ f'this message with a :thumbsup: in the next minute. If a minute passes or if the ' \ f'challenger reacts to this message, the deathmatch will be cancelled and the deposit ' \ f'refunded.' msg = await ctx.send(out) await msg.add_reaction('\N{THUMBS UP SIGN}') while True: try: reaction, user = await self.bot.wait_for('reaction_add', timeout=60) if str(reaction.emoji) == '👍' and user == opponent_member: opponent_obj.update_inventory({'0': bet}, remove=True) deathmatch_messages, winner = dm.do_deathmatch( author, opponent_obj, bet=bet_formatted) for message in deathmatch_messages[:-1]: await msg.edit(content=message) await asyncio.sleep(1) winner.update_inventory({'0': 2 * bet}) return elif user == ctx.author: author.update_inventory({'0': bet}) await msg.edit( content= f'{author_name} has declined their challenge and ' f'the deposit of {bet_formatted} coins has been returned.' ) return except asyncio.TimeoutError: author.update_inventory({'0': bet}) await msg.edit( content= f'One minute has passed and the deathmatch has been cancelled. ' f'The deposit of {bet_formatted} coins has been returned.' ) return else: try: opponent_member = parse_name(ctx.message.guild, opponent) opponent_obj = User.objects.get(id=opponent_member.id) except NameError: await ctx.send(f'{opponent} not found in server.') return except AmbiguousInputError as members: await ctx.send( f'Input {opponent} can refer to multiple people ({members})' ) return msg = await ctx.send(dm.DEATHMATCH_HEADER) deathmatch_messages, winner = dm.do_deathmatch( author, opponent_obj) for message in deathmatch_messages[:-1]: await msg.edit(content=message) await asyncio.sleep(2)
def __is_trade_valid(self): # Make sure our second user (the recipient of the items) is a real user here name = self.curr_trade['user2'] for member in self.ctx.guild.members: if name.lower() in member.name.lower(): self.name_member = member break else: raise TradeError(f'{name} not found in server.') # Check if either user is an Ironman if True in users.read_user_multi(self.curr_trade['user1'], self.name_member.id, key=users.IRONMAN_KEY): raise TradeError('Ironmen Cannot trade') # Make sure our second user (the recipient of the items) is a real user here name = self.curr_trade['user2'] for member in self.ctx.guild.members: if name.lower() in member.name.lower(): self.name_member = member break else: raise TradeError(f'{name} not found in server.') # Make sure they actually provided a number try: self.number = int(self.curr_trade['amount1']) if self.number < 0: raise ValueError except ValueError: raise TradeError( f'{self.curr_trade["amount1"]} is not a valid number.') # Check that the other one is a number too try: self.offer = users.parse_int(self.curr_trade['amount2']) except ValueError: raise TradeError( f'{self.curr_trade["amount2"]} is not a valid offer.') # Make sure the item is valid try: self.itemid = items.find_by_name(self.curr_trade['item1']) except KeyError: raise TradeError( f'{self.curr_trade["item1"]} is not a valid item.') # Make sure user actually has the item and quantity if not users.item_in_inventory(self.curr_trade['user1'], self.itemid, self.number): raise TradeError( f'You do not have {items.add_plural(self.number, self.itemid)} ' f'in your inventory.') # Check that it's tradeable if not items.is_tradable(self.itemid): raise TradeError( f'You can not trade this item. ({items.get_attr(itemid)})') # Check user2 has enough coins if not users.item_in_inventory(self.name_member.id, "0", self.offer): raise TradeError(f'{get_display_name(name_member)} does not have ' f'enough gold to buy this many items.') # Check that neither user is trading if not self._active_traders.isdisjoint( {self.curr_trade['user1'], self.name_member.id}): raise TradeError( "Each user can only have one active trade at a time") # Check that the user isn't him/herself if self.curr_trade['user1'] == self.name_member.id: raise TradeError("You cannot trade with yourself.") return True