async def info(self, ctx, auction: AuctionConverter): """View a pokémon from an auction.""" host = (self.bot.get_user(auction.user_id) or await query_member(ctx.guild, auction.user_id) or FakeUser(auction.user_id)) embed = self.make_base_embed(host, auction.pokemon, auction.id) if auction.bidder_id is None: auction_info = ( f"**Starting Bid:** {auction.current_bid + auction.bid_increment:,} Pokécoins", f"**Bid Increment:** {auction.bid_increment:,} Pokécoins", ) else: bidder = (self.bot.get_user(auction.bidder_id) or await query_member(ctx.guild, auction.bidder_id) or FakeUser(auction.bidder_id)) auction_info = ( f"**Current Bid:** {auction.current_bid:,} Pokécoins", f"**Bidder:** {bidder.mention}", f"**Bid Increment:** {auction.bid_increment:,} Pokécoins", ) embed.add_field(name="Auction Details", value="\n".join(auction_info)) embed.set_footer( text=f"Bid with `{ctx.prefix}auction bid {auction.id} <bid>`\n" f"Ends in {converters.strfdelta(auction.ends - datetime.utcnow())} at" ) embed.timestamp = auction.ends await ctx.send(embed=embed)
def build_from_mongo(cls, bot, x): guild = bot.get_guild(bot.config.GUILD_ID) user = guild.get_member(x["user_id"]) or FakeUser(x["user_id"]) target = guild.get_member(x["target_id"]) or FakeUser(x["target_id"]) kwargs = { "_id": x["_id"], "target": target, "user": user, "reason": x["reason"], "created_at": x["created_at"], } if "expires_at" in x: kwargs["expires_at"] = x["expires_at"] kwargs["resolved"] = x["resolved"] return cls_dict[x["type"]](**kwargs)
class Auctions(commands.Cog): """For auctions.""" def __init__(self, bot): self.bot = bot self.check_auctions.start() @tasks.loop(seconds=20) async def check_auctions(self): auctions = self.bot.mongo.Auction.find( {"ends": { "$lt": datetime.utcnow() }}) async for auction in auctions: try: await self.end_auction(auction) except Exception as e: pass @check_auctions.before_loop async def before_check_auctions(self): await self.bot.wait_until_ready() async def try_get_member(self, guild, id): if user := self.bot.get_user(id): return user with contextlib.suppress(discord.HTTPException): return await guild.fetch_member(id) with contextlib.suppress(discord.HTTPException): return await self.bot.fetch_user(id) return FakeUser(id)
async def convert(self, ctx, arg): with suppress(commands.MemberNotFound): return await commands.MemberConverter().convert(ctx, arg) try: return FakeUser(int(arg)) except ValueError: raise commands.MemberNotFound(arg)
async def convert(self, ctx, arg): try: return await commands.MemberConverter().convert(ctx, arg) except commands.MemberNotFound: pass try: return FakeUser(int(arg)) except ValueError: raise commands.MemberNotFound(arg)
def build_from_mongo(cls, bot, x): guild = bot.get_guild(GUILD_ID) user = guild.get_member(x["user_id"]) or FakeUser(x["user_id"]) target = guild.get_member(x["target_id"]) or FakeUser(x["target_id"]) kwargs = { "_id": x["_id"], "target": target, "user": user, "reason": x["reason"], "channel_id": x.get("channel_id"), "message_id": x.get("message_id"), "created_at": x["created_at"], } if "expires_at" in x: kwargs["expires_at"] = x["expires_at"] kwargs["resolved"] = x["resolved"] if "automod_bucket" in x: kwargs["automod_bucket"] = x["automod_bucket"] return cls_dict[x["type"]](**kwargs)
async def send_submission(self, channel, submission): status = submission.get("status", 0) user = self.bot.get_user(submission["user_id"]) or FakeUser( submission["user_id"]) embed = discord.Embed( title=f"{TEXT[status]} ({submission['form_id']})", url= f"https://forms.poketwo.net/a/{submission['form_id']}/submissions/{submission['_id']}", color=COLORS[status], ) embed.set_author(name=submission["user_tag"], icon_url=user.display_avatar.url) embed.set_footer(text=f"User ID • {user.id}") if reviewer_id := submission.get("reviewer_id"): reviewer = self.bot.get_user(reviewer_id) or FakeUser(reviewer_id) embed.set_footer(text=embed.footer.text + f"\nReviewed by • {reviewer}")
def build_from_mongo(cls, bot, x): guild = bot.get_guild(x["guild_id"]) user = guild.get_member(x["user_id"]) or FakeUser(x["user_id"]) kwargs = { "bot": bot, "_id": x["_id"], "user": user, "category": ALL_CATEGORIES[x["category"]], "guild_id": x["guild_id"], "channel_id": x["channel_id"], "thread_id": x["thread_id"], "created_at": x["created_at"], "closed_at": x.get("closed_at"), "status_channel_id": x.get("status_channel_id"), "status_message_id": x.get("status_message_id"), } if "agent_id" in x: kwargs["agent"] = guild.get_member(x["agent_id"]) or FakeUser( x["agent_id"]) return cls(**kwargs)
async def info(self, ctx, *, name): """Retrieves info about a tag.""" tag = await self.get_tag(name) if tag is None: return await ctx.send("Tag not found.") user = self.bot.get_user(tag.owner_id) if user is None: user = FakeUser(tag.owner_id) embed = discord.Embed(color=discord.Color.blurple(), title=tag.name) embed.add_field(name="Owner", value=user.mention) if tag.alias: embed.add_field(name="Original", value=tag.original) else: embed.add_field(name="Uses", value=tag.uses) embed.set_author(name=str(user), icon_url=user.display_avatar.url) await ctx.send(embed=embed)
class Auctions(commands.Cog): """For auctions.""" def __init__(self, bot): self.bot = bot self.check_auctions.start() self.sem = asyncio.Semaphore(1) @tasks.loop(minutes=1) async def check_auctions(self): await self.bot.wait_until_ready() auctions = self.bot.mongo.Auction.find( {"ends": { "$lt": datetime.utcnow() }}) async for auction in auctions: try: await self.end_auction(auction) except Exception as e: print(e) continue async def end_auction(self, auction): if (auction_guild := self.bot.get_guild(auction.guild_id)) is None: return guild = await self.bot.mongo.fetch_guild(auction_guild) if auction.bidder_id is None: auction.bidder_id = auction.user_id auction.current_bid = 0 host = (self.bot.get_user(auction.user_id) or await query_member(auction_guild, auction.user_id) or FakeUser(auction.user_id)) bidder = (self.bot.get_user(auction.bidder_id) or await query_member(auction_guild, auction.bidder_id) or FakeUser(auction.bidder_id)) embed = self.make_base_embed(host, auction.pokemon, auction.id) embed.title = "[SOLD] " + embed.title auction_info = ( f"**Winning Bid:** {auction.current_bid:,} Pokécoins", f"**Bidder:** {bidder.mention}", ) embed.add_field(name="Auction Details", value="\n".join(auction_info)) embed.set_footer(text=f"The auction has ended.") auction_channel = auction_guild.get_channel(guild.auction_channel) if auction_channel is not None: self.bot.loop.create_task(auction_channel.send(embed=embed)) # ok, bid await self.bot.mongo.db.auction.delete_one({"_id": auction.id}) try: await self.bot.mongo.db.pokemon.insert_one({ **auction.pokemon.to_mongo(), "owner_id": auction.bidder_id, "idx": await self.bot.mongo.fetch_next_idx(bidder), }) except pymongo.errors.DuplicateKeyError: return await self.bot.mongo.update_member( host, {"$inc": { "balance": auction.current_bid }}) self.bot.loop.create_task( host.send( f"The auction for your **{auction.pokemon.iv_percentage:.2%} {auction.pokemon.species}** ended with a highest bid of **{auction.current_bid:,}** Pokécoins (Auction #{auction.id})." )) self.bot.loop.create_task( bidder.send( f"You won the auction for the **{auction.pokemon.iv_percentage:.2%} {auction.pokemon.species}** with a bid of **{auction.current_bid:,}** Pokécoins (Auction #{auction.id})." )) if auction.current_bid > 0: try: await self.bot.mongo.db.logs.insert_one({ "event": "auction", "user": auction.bidder_id, "item": auction.pokemon.id, "seller_id": auction.user_id, "price": auction.current_bid, }) except: print("Error trading auction logs.")
async def bid(self, ctx, auction: AuctionConverter, bid: int): """Bid on an auction.""" if ctx.author.id == auction.user_id: return await ctx.send("You can't bid on your own auction.") if ctx.author.id == auction.bidder_id: return await ctx.send("You are already the highest bidder.") if bid < auction.current_bid + auction.bid_increment: return await ctx.send( f"Your bid must be at least {auction.current_bid + auction.bid_increment:,} Pokécoins." ) guild = await self.bot.mongo.fetch_guild(ctx.guild) member = await self.bot.mongo.fetch_member_info(ctx.author) if member.balance < bid: return await ctx.send("You don't have enough Pokécoins for that!") # confirm await ctx.send( f"Do you want to bid **{bid:,} Pokécoins** on the **{auction.pokemon.iv_percentage:.2%} {auction.pokemon:s}**? [y/N]" ) def check(m): return m.channel.id == ctx.channel.id and m.author.id == ctx.author.id try: msg = await self.bot.wait_for("message", timeout=30, check=check) except asyncio.TimeoutError: return await ctx.send("Time's up. Aborted.") if msg.content.lower() != "y": return await ctx.send("Aborted.") # go! async with self.sem: auction = await self.bot.mongo.Auction.find_one({ "guild_id": ctx.guild.id, "_id": auction.id }) if auction is None: return await ctx.send("Couldn't find that auction!") if bid < auction.current_bid + auction.bid_increment: return await ctx.send( f"Your bid must be at least {auction.current_bid + auction.bid_increment:,} Pokécoins." ) member = await self.bot.mongo.fetch_member_info(ctx.author) if member.balance < bid: return await ctx.send( "You don't have enough Pokécoins for that!") # send embed host = (self.bot.get_user(auction.user_id) or await query_member(ctx.guild, auction.user_id) or FakeUser(auction.user_id)) embed = self.make_base_embed(host, auction.pokemon, auction.id) auction_info = ( f"**Current Bid:** {bid:,} Pokécoins", f"**Bidder:** {ctx.author.mention}", f"**Bid Increment:** {auction.bid_increment:,} Pokécoins", ) embed.add_field(name="Auction Details", value="\n".join(auction_info)) embed.set_footer( text=f"Bid with `{ctx.prefix}auction bid {auction.id} <bid>`\n" f"Ends in {converters.strfdelta(auction.ends - datetime.utcnow())} at" ) embed.timestamp = auction.ends update = { "$set": { "current_bid": bid, "bidder_id": ctx.author.id, } } if datetime.utcnow() + timedelta(minutes=5) > auction.ends: update["$set"]["ends"] = datetime.utcnow() + timedelta( minutes=5) # check to make sure still there r = await self.bot.mongo.db.auction.update_one({"_id": auction.id}, update) if r.modified_count == 0: return await ctx.send("That auction has already ended.") auction_channel = ctx.guild.get_channel(guild.auction_channel) if auction_channel is not None: self.bot.loop.create_task(auction_channel.send(embed=embed)) # ok, bid await self.bot.mongo.update_member(ctx.author, {"$inc": { "balance": -bid }}) if auction.bidder_id is not None: await self.bot.mongo.update_member( auction.bidder_id, {"$inc": { "balance": auction.current_bid }}) priv = await self.bot.http.start_private_message( auction.bidder_id) self.bot.loop.create_task(await self.bot.http.send_message( priv["id"], f"You have been outbid on the **{auction.pokemon.iv_percentage:.2%} {auction.pokemon.species}** (Auction #{auction.id}).", )) self.bot.loop.create_task( ctx.send( f"You bid **{bid:,} Pokécoins** on the **{auction.pokemon.iv_percentage:.2%} {auction.pokemon.species}** (Auction #{auction.id})." ))