827 lines
39 KiB
Python
827 lines
39 KiB
Python
import asyncio
|
|
import datetime
|
|
from typing import Literal, Optional
|
|
|
|
import discord
|
|
import random
|
|
import math
|
|
from redbot.core import commands, checks, Config, bank
|
|
from redbot.core.utils.chat_formatting import box, pagify, humanize_number
|
|
from redbot.core.utils.menus import menu, DEFAULT_CONTROLS
|
|
|
|
__version__ = "0.2.12"
|
|
|
|
|
|
class TrickOrTreat(commands.Cog):
|
|
"""Trick or treating for your server."""
|
|
|
|
async def red_delete_data_for_user(
|
|
self,
|
|
*,
|
|
requester: Literal["discord", "owner", "user", "user_strict"],
|
|
user_id: int,
|
|
):
|
|
await self.config.user_from_id(user_id).clear()
|
|
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
self.config = Config.get_conf(self, 2710311393, force_registration=True)
|
|
|
|
default_guild = {"cooldown": 300, "channel": [], "pick": 50, "toggle": False}
|
|
default_global = {"schema": "v1"}
|
|
|
|
default_user = {
|
|
"candies": 0,
|
|
"chocolates": 0,
|
|
"cookies": 0,
|
|
"eaten": 0,
|
|
"last_tot": "2018-01-01 00:00:00.000001",
|
|
"lollipops": 0,
|
|
"sickness": 0,
|
|
"stars": 0,
|
|
}
|
|
|
|
self.config.register_user(**default_user)
|
|
self.config.register_guild(**default_guild)
|
|
self.config.register_global(**default_global)
|
|
|
|
async def cleanup(self):
|
|
# Schema didn't exist before, so it will be initialized at v1.
|
|
# This will also run once for new cog installs
|
|
schema = await self.config.schema()
|
|
if schema == "v2":
|
|
return
|
|
await self.bot.wait_until_red_ready()
|
|
users = await self.config.all_users()
|
|
for uid, data in users.items():
|
|
if "chocolate" not in data:
|
|
continue
|
|
async with self.config.user_from_id(uid).all() as user:
|
|
user["chocolates"] += user["chocolate"]
|
|
del user["chocolate"]
|
|
await self.config.schema.set("v2")
|
|
|
|
@commands.guild_only()
|
|
@commands.cooldown(1, 1, commands.BucketType.user)
|
|
@commands.command()
|
|
async def eatcandy(self, ctx, number: Optional[int] = 1, candy_type=None):
|
|
"""Eat some candy.
|
|
|
|
Valid types: candy/candie(s), chocolate(s), lollipop(s), cookie(s), star(s)
|
|
Examples:
|
|
`[p]eatcandy 3 lollipops`
|
|
`[p]eatcandy star`
|
|
|
|
\N{CANDY}
|
|
The star of this competition. You should try to eat all of these, but don't get too sick.
|
|
|
|
\N{CHOCOLATE BAR}
|
|
Reduces sickness by 10.
|
|
|
|
\N{LOLLIPOP}
|
|
Reduces sickness by 20.
|
|
|
|
\N{FORTUNE COOKIE}
|
|
Sets sickness to a random amount - fortune favours the brave.
|
|
|
|
\N{WHITE MEDIUM STAR}
|
|
Resets sickness to 0.
|
|
"""
|
|
userdata = await self.config.user(ctx.author).all()
|
|
pick = await self.config.guild(ctx.guild).pick()
|
|
if not candy_type:
|
|
candy_type = "candies"
|
|
if number < 0:
|
|
return await ctx.send(
|
|
"That doesn't sound fun.",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
if number == 0:
|
|
return await ctx.send(
|
|
"You pretend to eat a candy.",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
if candy_type in ["candies", "candy", "\U0001f36c"]:
|
|
candy_type = "candies"
|
|
if candy_type in ["lollipops", "lollipop", "\U0001f36d"]:
|
|
candy_type = "lollipops"
|
|
if candy_type in ["stars", "star", "\U00002b50"]:
|
|
candy_type = "stars"
|
|
if candy_type in ["chocolate", "chocolates", "\U0001f36b"]:
|
|
candy_type = "chocolates"
|
|
if candy_type in ["cookie", "cookies", "\U0001f960"]:
|
|
candy_type = "cookies"
|
|
candy_list = ["candies", "chocolates", "lollipops", "cookies", "stars"]
|
|
if candy_type not in candy_list:
|
|
return await ctx.send(
|
|
"That's not a candy type! Use the inventory command to see what you have.",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
if userdata[candy_type] < number:
|
|
return await ctx.send(
|
|
f"You don't have that many {candy_type}.",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
if userdata[candy_type] == 0:
|
|
return await ctx.send(
|
|
f"You contemplate the idea of eating {candy_type}.",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
|
|
eat_phrase = [
|
|
"You leisurely enjoy",
|
|
"You take the time to savor",
|
|
"You eat",
|
|
"You scarf down",
|
|
"You sigh in contentment after eating",
|
|
"You gobble up",
|
|
"You make a meal of",
|
|
"You devour",
|
|
"You monstrously pig out on",
|
|
"You hastily chomp down on",
|
|
"You daintily partake of",
|
|
"You earnestly consume",
|
|
]
|
|
if candy_type in ["candies", "candy"]:
|
|
if (userdata["sickness"] + number * 2) in range(70, 95):
|
|
await ctx.send(
|
|
"After all that candy, sugar doesn't sound so good.",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
yuck = random.randint(1, 10)
|
|
if yuck == 10:
|
|
await self.config.user(ctx.author).sickness.set(userdata["sickness"] + 25)
|
|
if yuck in range(1, 9):
|
|
await self.config.user(ctx.author).sickness.set(userdata["sickness"] + (yuck * 2))
|
|
|
|
if userdata["candies"] > 3 + number:
|
|
lost_candy = userdata["candies"] - random.randint(1, 3) - number
|
|
else:
|
|
lost_candy = userdata["candies"]
|
|
|
|
pick_now = await self.config.guild(ctx.guild).pick()
|
|
if lost_candy < 0:
|
|
await self.config.user(ctx.author).candies.set(0)
|
|
await self.config.guild(ctx.guild).pick.set(pick_now + lost_candy)
|
|
else:
|
|
await self.config.user(ctx.author).candies.set(userdata["candies"] - lost_candy)
|
|
await self.config.guild(ctx.guild).pick.set(pick_now + lost_candy)
|
|
|
|
await self.config.user(ctx.author).eaten.set(userdata["eaten"] + (userdata["candies"] - lost_candy))
|
|
|
|
return await ctx.send(
|
|
f"You begin to think you don't need all this candy, maybe...\n*{lost_candy} candies are left behind*",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
|
|
if (userdata["sickness"] + number) > 96:
|
|
await self.config.user(ctx.author).sickness.set(userdata["sickness"] + 30)
|
|
lost_candy = userdata["candies"] - random.randint(1, 5)
|
|
if lost_candy <= 0:
|
|
await self.config.user(ctx.author).candies.set(0)
|
|
message = await ctx.send(
|
|
"...",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(2)
|
|
await message.edit(content="..........")
|
|
await asyncio.sleep(2)
|
|
return await message.edit(
|
|
content="You feel absolutely disgusted. At least you don't have any candies left."
|
|
)
|
|
await self.config.guild(ctx.guild).pick.set(pick + lost_candy)
|
|
await self.config.user(ctx.author).candies.set(0)
|
|
await self.config.user(ctx.author).eaten.set(userdata["eaten"] + (userdata["candies"] - lost_candy))
|
|
message = await ctx.send("...", reference=ctx.message.to_reference(fail_if_not_exists=False))
|
|
await asyncio.sleep(2)
|
|
await message.edit(content="..........")
|
|
await asyncio.sleep(2)
|
|
return await message.edit(
|
|
content=f"You toss your candies on the ground in disgust.\n*{lost_candy} candies are left behind*"
|
|
)
|
|
|
|
pluralcandy = "candy" if number == 1 else "candies"
|
|
await ctx.send(
|
|
f"{random.choice(eat_phrase)} {number} {pluralcandy}. (Total eaten: `{humanize_number(await self.config.user(ctx.author).eaten() + number)}` \N{CANDY})",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await self.config.user(ctx.author).sickness.set(userdata["sickness"] + (number * 2))
|
|
await self.config.user(ctx.author).candies.set(userdata["candies"] - number)
|
|
await self.config.user(ctx.author).eaten.set(userdata["eaten"] + number)
|
|
|
|
if candy_type in ["chocolates", "chocolate"]:
|
|
pluralchoc = "chocolate" if number == 1 else "chocolates"
|
|
await ctx.send(
|
|
f"{random.choice(eat_phrase)} {number} {pluralchoc}. You feel slightly better!\n*Sickness has gone down by {number * 10}*",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
new_sickness = userdata["sickness"] - (number * 10)
|
|
if new_sickness < 0:
|
|
new_sickness = 0
|
|
await self.config.user(ctx.author).sickness.set(new_sickness)
|
|
await self.config.user(ctx.author).chocolates.set(userdata["chocolates"] - number)
|
|
await self.config.user(ctx.author).eaten.set(userdata["eaten"] + number)
|
|
|
|
if candy_type in ["lollipops", "lollipop"]:
|
|
pluralpop = "lollipop" if number == 1 else "lollipops"
|
|
await ctx.send(
|
|
f"{random.choice(eat_phrase)} {number} {pluralpop}. You feel slightly better!\n*Sickness has gone down by {number * 20}*",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
new_sickness = userdata["sickness"] - (number * 20)
|
|
if new_sickness < 0:
|
|
new_sickness = 0
|
|
await self.config.user(ctx.author).sickness.set(new_sickness)
|
|
await self.config.user(ctx.author).lollipops.set(userdata["lollipops"] - number)
|
|
await self.config.user(ctx.author).eaten.set(userdata["eaten"] + number)
|
|
|
|
if candy_type in ["cookies", "cookie"]:
|
|
pluralcookie = "cookie" if number == 1 else "cookies"
|
|
new_sickness = random.randint(0, 100)
|
|
old_sickness = userdata["sickness"]
|
|
if new_sickness > old_sickness:
|
|
phrase = f"You feel worse!\n*Sickness has gone up by {new_sickness - old_sickness}*"
|
|
else:
|
|
phrase = f"You feel better!\n*Sickness has gone down by {old_sickness - new_sickness}*"
|
|
await ctx.reply(f"{random.choice(eat_phrase)} {number} {pluralcookie}. {phrase}")
|
|
await self.config.user(ctx.author).sickness.set(new_sickness)
|
|
await self.config.user(ctx.author).cookies.set(userdata["cookies"] - number)
|
|
await self.config.user(ctx.author).eaten.set(userdata["eaten"] + number)
|
|
|
|
if candy_type in ["stars", "star"]:
|
|
pluralstar = "star" if number == 1 else "stars"
|
|
await ctx.send(
|
|
f"{random.choice(eat_phrase)} {number} {pluralstar}. You feel great!\n*Sickness has been reset*",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await self.config.user(ctx.author).sickness.set(0)
|
|
await self.config.user(ctx.author).stars.set(userdata["stars"] - number)
|
|
await self.config.user(ctx.author).eaten.set(userdata["eaten"] + number)
|
|
|
|
@commands.guild_only()
|
|
@checks.mod_or_permissions(administrator=True)
|
|
@commands.command()
|
|
async def totbalance(self, ctx):
|
|
"""[Admin] Check how many candies are 'on the ground' in the guild."""
|
|
pick = await self.config.guild(ctx.guild).pick()
|
|
await ctx.send(f"The guild is currently holding: {pick} \N{CANDY}")
|
|
|
|
@commands.guild_only()
|
|
@commands.command()
|
|
async def buycandy(self, ctx, pieces: int):
|
|
"""Buy some candy. Prices could vary at any time."""
|
|
candy_now = await self.config.user(ctx.author).candies()
|
|
credits_name = await bank.get_currency_name(ctx.guild)
|
|
if pieces <= 0:
|
|
return await ctx.send(
|
|
"Not in this reality.",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
candy_price = int(round(await bank.get_balance(ctx.author)) * 0.04) * pieces
|
|
if candy_price in range(0, 10):
|
|
candy_price = pieces * 10
|
|
try:
|
|
await bank.withdraw_credits(ctx.author, candy_price)
|
|
except ValueError:
|
|
return await ctx.send(
|
|
f"Not enough {credits_name} ({candy_price} required).",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await self.config.user(ctx.author).candies.set(candy_now + pieces)
|
|
await ctx.send(
|
|
f"Bought {pieces} candies with {candy_price} {credits_name}.",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
|
|
@commands.guild_only()
|
|
@commands.command()
|
|
@commands.bot_has_permissions(embed_links=True, add_reactions=True)
|
|
async def cboard(self, ctx):
|
|
"""Show the candy eating leaderboard."""
|
|
space = "\N{SPACE}"
|
|
userinfo = await self.config._all_from_scope(scope="USER")
|
|
if not userinfo:
|
|
return await ctx.send(
|
|
"No one has any candy.",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
async with ctx.typing():
|
|
sorted_acc = sorted(userinfo.items(), key=lambda x: x[1]["eaten"], reverse=True)
|
|
# Leaderboard logic from https://github.com/Cog-Creators/Red-DiscordBot/blob/V3/develop/redbot/cogs/economy/economy.py#L445
|
|
pound_len = len(str(len(sorted_acc)))
|
|
score_len = 10
|
|
header = "{pound:{pound_len}}{score:{score_len}}{name:2}\n".format(
|
|
pound="#",
|
|
pound_len=pound_len + 3,
|
|
score="Candies Eaten",
|
|
score_len=score_len + 6,
|
|
name="Name",
|
|
)
|
|
scoreboard_msg = self._red(header)
|
|
for pos, account in enumerate(sorted_acc):
|
|
if account[1]["eaten"] == 0:
|
|
continue
|
|
try:
|
|
if account[0] in [member.id for member in ctx.guild.members]:
|
|
user_obj = ctx.guild.get_member(account[0])
|
|
else:
|
|
user_obj = await self.bot.fetch_user(account[0])
|
|
except AttributeError:
|
|
user_obj = await self.bot.fetch_user(account[0])
|
|
|
|
if user_obj.discriminator != "0":
|
|
if len(user_obj.name) > 28:
|
|
user_name = f"{user_obj.name[:19]}...#{user_obj.discriminator}"
|
|
else:
|
|
user_name = f"{user_obj.name}#{user_obj.discriminator}"
|
|
else:
|
|
if len(user_obj.name) > 28:
|
|
user_name = f"{user_obj.name[:25]}..."
|
|
else:
|
|
user_name = user_obj.name
|
|
|
|
user_idx = pos + 1
|
|
if user_obj == ctx.author:
|
|
user_highlight = self._yellow(f"<<{user_name}>>")
|
|
scoreboard_msg += (
|
|
f"{self._yellow(user_idx)}. {space*pound_len}"
|
|
f"{humanize_number(account[1]['eaten']) + ' 🍬': <{score_len + 4}} {user_highlight}\n"
|
|
)
|
|
else:
|
|
scoreboard_msg += (
|
|
f"{self._yellow(user_idx)}. {space*pound_len}"
|
|
f"{humanize_number(account[1]['eaten']) + ' 🍬': <{score_len + 4}} {user_name}\n"
|
|
)
|
|
|
|
page_list = []
|
|
pages = 1
|
|
for page in pagify(scoreboard_msg, delims=["\n"], page_length=1000):
|
|
embed = discord.Embed(
|
|
colour=0xF4731C,
|
|
description=box(f"\N{CANDY} Global Leaderboard \N{CANDY}", lang="prolog") + (box(page, lang="ansi")),
|
|
)
|
|
embed.set_footer(
|
|
text=f"Page {humanize_number(pages)}/{humanize_number(math.ceil(len(scoreboard_msg) / 1000))}"
|
|
)
|
|
pages += 1
|
|
page_list.append(embed)
|
|
return await menu(ctx, page_list, DEFAULT_CONTROLS)
|
|
|
|
@commands.guild_only()
|
|
@commands.command()
|
|
@commands.bot_has_permissions(embed_links=True)
|
|
async def cinventory(self, ctx):
|
|
"""Check your inventory."""
|
|
userdata = await self.config.user(ctx.author).all()
|
|
sickness = userdata["sickness"]
|
|
msg = f"{ctx.author.mention}'s Candy Bag:"
|
|
em = discord.Embed(color=await ctx.embed_color())
|
|
em.description = f"{userdata['candies']} \N{CANDY}"
|
|
if userdata["chocolates"]:
|
|
em.description += f"\n{userdata['chocolates']} \N{CHOCOLATE BAR}"
|
|
if userdata["lollipops"]:
|
|
em.description += f"\n{userdata['lollipops']} \N{LOLLIPOP}"
|
|
if userdata["cookies"]:
|
|
em.description += f"\n{userdata['cookies']} \N{FORTUNE COOKIE}"
|
|
if userdata["stars"]:
|
|
em.description += f"\n{userdata['stars']} \N{WHITE MEDIUM STAR}"
|
|
if sickness in range(41, 56):
|
|
em.description += f"\n\n**Sickness is over 40/100**\n*You don't feel so good...*"
|
|
elif sickness in range(56, 71):
|
|
em.description += f"\n\n**Sickness is over 55/100**\n*You don't feel so good...*"
|
|
elif sickness in range(71, 86):
|
|
em.description += f"\n\n**Sickness is over 70/100**\n*You really don't feel so good...*"
|
|
elif sickness in range(86, 101):
|
|
em.description += f"\n\n**Sickness is over 85/100**\n*The thought of more sugar makes you feel awful...*"
|
|
elif sickness > 100:
|
|
em.description += f"\n\n**Sickness is over 100/100**\n*Better wait a while for more candy...*"
|
|
await ctx.send(msg, embed=em)
|
|
|
|
@commands.guild_only()
|
|
@checks.is_owner()
|
|
@commands.command()
|
|
async def totclearall(self, ctx, are_you_sure=False):
|
|
"""[Owner] Clear all saved game data."""
|
|
if not are_you_sure:
|
|
msg = "This will clear ALL saved data for this cog and reset it to the defaults.\n"
|
|
msg += f"If you are absolutely sure you want to do this, use `{ctx.prefix}totclearall yes`."
|
|
return await ctx.send(msg)
|
|
await self.config.clear_all()
|
|
await ctx.send("All data for this cog has been cleared.")
|
|
|
|
@commands.guild_only()
|
|
@checks.mod_or_permissions(administrator=True)
|
|
@commands.command()
|
|
async def totcooldown(self, ctx, cooldown_time: int = 0):
|
|
"""Set the cooldown time for trick or treating on the server."""
|
|
if cooldown_time < 0:
|
|
return await ctx.send("Nice try.")
|
|
if cooldown_time == 0:
|
|
await self.config.guild(ctx.guild).cooldown.set(300)
|
|
return await ctx.send("Trick or treating cooldown time reset to 5m.")
|
|
elif 1 <= cooldown_time <= 30:
|
|
await self.config.guild(ctx.guild).cooldown.set(30)
|
|
return await ctx.send("Trick or treating cooldown time set to the minimum of 30s.")
|
|
else:
|
|
await self.config.guild(ctx.guild).cooldown.set(cooldown_time)
|
|
await ctx.send(f"Trick or treating cooldown time set to {cooldown_time}s.")
|
|
|
|
@commands.guild_only()
|
|
@commands.cooldown(1, 600, discord.ext.commands.BucketType.user)
|
|
@commands.command()
|
|
async def pickup(self, ctx):
|
|
"""Pick up some candy, if there is any."""
|
|
candies = await self.config.user(ctx.author).candies()
|
|
to_pick = await self.config.guild(ctx.guild).pick()
|
|
chance = random.randint(1, 100)
|
|
found = round((chance / 100) * to_pick)
|
|
await self.config.user(ctx.author).candies.set(candies + found)
|
|
await self.config.guild(ctx.guild).pick.set(to_pick - found)
|
|
message = await ctx.send(
|
|
"You start searching the area for candy...",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(3)
|
|
await message.edit(content=f"You found {found} \N{CANDY}!")
|
|
|
|
@commands.guild_only()
|
|
@commands.cooldown(1, 600, discord.ext.commands.BucketType.user)
|
|
@commands.command()
|
|
async def stealcandy(self, ctx, user: discord.Member = None):
|
|
"""Steal some candy."""
|
|
guild_users = [m.id for m in ctx.guild.members if m is not m.bot and not m == ctx.author]
|
|
candy_users = await self.config._all_from_scope(scope="USER")
|
|
valid_user = list(set(guild_users) & set(candy_users))
|
|
if not valid_user:
|
|
return await ctx.send(
|
|
"No one has any candy yet!",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
if not user:
|
|
picked_user = self.bot.get_user(random.choice(valid_user))
|
|
elif user == ctx.author or user == user.bot:
|
|
picked_user = self.bot.get_user(random.choice(valid_user))
|
|
elif user != ctx.author or user != user.bot:
|
|
picked_user = user
|
|
else:
|
|
picked_user = self.bot.get_user(random.choice(valid_user))
|
|
|
|
if picked_user.discriminator != "0":
|
|
picked_user_name = f"{picked_user.name}#{picked_user.discriminator}"
|
|
else:
|
|
picked_user_name = picked_user.name
|
|
|
|
picked_candy_now = await self.config.user(picked_user).candies()
|
|
if picked_candy_now == 0:
|
|
chance = random.randint(1, 25)
|
|
if chance in range(21, 25):
|
|
new_picked_user = self.bot.get_user(random.choice(valid_user))
|
|
|
|
if new_picked_user.discriminator != "0":
|
|
new_picked_user_name = f"{new_picked_user.name}#{new_picked_user.discriminator}"
|
|
else:
|
|
new_picked_user_name = new_picked_user.name
|
|
|
|
new_picked_candy_now = await self.config.user(new_picked_user).candies()
|
|
if chance in range(24, 25):
|
|
if new_picked_candy_now == 0:
|
|
message = await ctx.send(
|
|
"You see an unsuspecting guildmate...",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(random.randint(3, 6))
|
|
return await message.edit(
|
|
content=f"There was nothing in {picked_user}'s pockets, so you picked {new_picked_user_name}'s pockets but they had no candy either!"
|
|
)
|
|
else:
|
|
message = await ctx.send(
|
|
"You see an unsuspecting guildmate...",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(random.randint(3, 6))
|
|
return await message.edit(
|
|
content=f"There was nothing in {picked_user}'s pockets, so you looked around again... you saw {new_picked_user_name} in the distance, but you didn't think you could catch up..."
|
|
)
|
|
if chance in range(10, 20):
|
|
message = await ctx.send(
|
|
"You start sneaking around in the shadows...",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(random.randint(3, 6))
|
|
return await message.edit(
|
|
content=f"You snuck up on {picked_user} and tried picking their pockets but there was nothing there!"
|
|
)
|
|
else:
|
|
message = await ctx.send(
|
|
"You start looking around for a target...",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(random.randint(3, 6))
|
|
return await message.edit(content="You snuck around for a while but didn't find anything.")
|
|
user_candy_now = await self.config.user(ctx.author).candies()
|
|
multip = random.randint(1, 100) / 100
|
|
if multip > 0.7:
|
|
multip = 0.7
|
|
pieces = round(picked_candy_now * multip)
|
|
if pieces <= 0:
|
|
message = await ctx.send(
|
|
"You stealthily move over to an unsuspecting person...",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(4)
|
|
return await message.edit(content="You found someone to pickpocket, but they had nothing but pocket lint.")
|
|
chance = random.randint(1, 25)
|
|
sneak_phrases = [
|
|
"You look around furtively...",
|
|
"You glance around slowly, looking for your target...",
|
|
"You see someone with a full candy bag...",
|
|
]
|
|
if chance <= 10:
|
|
message = await ctx.send(
|
|
"You creep closer to the target...",
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(random.randint(3, 5))
|
|
return await message.edit(content="You snuck around for a while but didn't find anything.")
|
|
if chance > 18:
|
|
await self.config.user(picked_user).candies.set(picked_candy_now - pieces)
|
|
await self.config.user(ctx.author).candies.set(user_candy_now + pieces)
|
|
message = await ctx.send(
|
|
random.choice(sneak_phrases),
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(4)
|
|
await message.edit(content="There seems to be an unsuspecting victim in the corner...")
|
|
await asyncio.sleep(4)
|
|
return await message.edit(content=f"You stole {pieces} \N{CANDY} from {picked_user}!")
|
|
if chance in range(11, 17):
|
|
await self.config.user(picked_user).candies.set(picked_candy_now - round(pieces / 2))
|
|
await self.config.user(ctx.author).candies.set(user_candy_now + round(pieces / 2))
|
|
message = await ctx.send(
|
|
random.choice(sneak_phrases),
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(4)
|
|
await message.edit(content="There seems to be an unsuspecting victim in the corner...")
|
|
await asyncio.sleep(4)
|
|
return await message.edit(content=f"You stole {round(pieces/2)} \N{CANDY} from {picked_user}!")
|
|
else:
|
|
message = await ctx.send(
|
|
random.choice(sneak_phrases),
|
|
reference=ctx.message.to_reference(fail_if_not_exists=False),
|
|
)
|
|
await asyncio.sleep(4)
|
|
noise_msg = [
|
|
"You hear a sound behind you! When you turn back, your target is gone.",
|
|
"You look away for a moment and your target has vanished.",
|
|
"Something flashes in your peripheral vision, and as you turn to look, your target gets away...",
|
|
]
|
|
await message.edit(content=random.choice(noise_msg))
|
|
|
|
@commands.guild_only()
|
|
@checks.mod_or_permissions(administrator=True)
|
|
@commands.group()
|
|
async def totchannel(self, ctx):
|
|
"""Channel management for Trick or Treat."""
|
|
if ctx.invoked_subcommand is not None or isinstance(ctx.invoked_subcommand, commands.Group):
|
|
return
|
|
channel_list = await self.config.guild(ctx.guild).channel()
|
|
channel_msg = "Trick or Treat Channels:\n"
|
|
for chan in channel_list:
|
|
channel_obj = self.bot.get_channel(chan)
|
|
if channel_obj:
|
|
channel_msg += f"{channel_obj.name}\n"
|
|
await ctx.send(box(channel_msg))
|
|
|
|
@commands.guild_only()
|
|
@totchannel.command()
|
|
async def add(self, ctx, channel: discord.TextChannel):
|
|
"""Add a text channel for Trick or Treating."""
|
|
channel_list = await self.config.guild(ctx.guild).channel()
|
|
tottoggle = await self.config.guild(ctx.guild).toggle()
|
|
if not tottoggle:
|
|
toggle_info = (
|
|
f"\nThe game toggle for this server is **Off**. Turn it on with the `{ctx.prefix}tottoggle` command."
|
|
)
|
|
else:
|
|
toggle_info = ""
|
|
if channel.id not in channel_list:
|
|
channel_list.append(channel.id)
|
|
await self.config.guild(ctx.guild).channel.set(channel_list)
|
|
await ctx.send(f"{channel.mention} added to the valid Trick or Treat channels.{toggle_info}")
|
|
else:
|
|
await ctx.send(f"{channel.mention} is already in the list of Trick or Treat channels.{toggle_info}")
|
|
|
|
@commands.guild_only()
|
|
@totchannel.command()
|
|
async def remove(self, ctx, channel: discord.TextChannel):
|
|
"""Remove a text channel from Trick or Treating."""
|
|
channel_list = await self.config.guild(ctx.guild).channel()
|
|
if channel.id in channel_list:
|
|
channel_list.remove(channel.id)
|
|
else:
|
|
return await ctx.send(f"{channel.mention} not in whitelist.")
|
|
await self.config.guild(ctx.guild).channel.set(channel_list)
|
|
await ctx.send(f"{channel.mention} removed from the list of Trick or Treat channels.")
|
|
|
|
@commands.guild_only()
|
|
@checks.mod_or_permissions(administrator=True)
|
|
@commands.command()
|
|
async def tottoggle(self, ctx):
|
|
"""Toggle trick or treating on the whole server."""
|
|
toggle = await self.config.guild(ctx.guild).toggle()
|
|
msg = f"Trick or Treating active: {not toggle}.\n"
|
|
channel_list = await self.config.guild(ctx.guild).channel()
|
|
if not channel_list:
|
|
channel_list.append(ctx.message.channel.id)
|
|
await self.config.guild(ctx.guild).channel.set(channel_list)
|
|
msg += f"Trick or Treating channel added: {ctx.message.channel.mention}"
|
|
await self.config.guild(ctx.guild).toggle.set(not toggle)
|
|
await ctx.send(msg)
|
|
|
|
@commands.guild_only()
|
|
@commands.command(hidden=True)
|
|
async def totversion(self, ctx):
|
|
"""Trick or Treat version."""
|
|
await ctx.send(f"Trick or Treat version {__version__}")
|
|
|
|
async def has_perm(self, user):
|
|
return await self.bot.allowed_by_whitelist_blacklist(user)
|
|
|
|
@commands.Cog.listener()
|
|
async def on_message_without_command(self, message):
|
|
if isinstance(message.channel, discord.abc.PrivateChannel):
|
|
return
|
|
if message.author.bot:
|
|
return
|
|
if not await self.has_perm(message.author):
|
|
return
|
|
|
|
chance = random.randint(1, 12)
|
|
if chance % 4 == 0:
|
|
sickness_now = await self.config.user(message.author).sickness()
|
|
sick_chance = random.randint(1, 12)
|
|
if sick_chance % 3 == 0:
|
|
new_sickness = sickness_now - sick_chance
|
|
if new_sickness < 0:
|
|
new_sickness = 0
|
|
await self.config.user(message.author).sickness.set(new_sickness)
|
|
|
|
pick_chance = random.randint(1, 12)
|
|
if pick_chance % 4 == 0:
|
|
random_candies = random.randint(1, 3)
|
|
guild_pool = await self.config.guild(message.guild).pick()
|
|
await self.config.guild(message.guild).pick.set(guild_pool + random_candies)
|
|
|
|
content = (message.content).lower()
|
|
if not content.startswith("trick or treat"):
|
|
return
|
|
toggle = await self.config.guild(message.guild).toggle()
|
|
if not toggle:
|
|
return
|
|
channel = await self.config.guild(message.guild).channel()
|
|
if message.channel.id not in channel:
|
|
return
|
|
userdata = await self.config.user(message.author).all()
|
|
|
|
last_time = datetime.datetime.strptime(str(userdata["last_tot"]), "%Y-%m-%d %H:%M:%S.%f")
|
|
now = datetime.datetime.now(datetime.timezone.utc)
|
|
now = now.replace(tzinfo=None)
|
|
if int((now - last_time).total_seconds()) < await self.config.guild(message.guild).cooldown():
|
|
messages = [
|
|
"The thought of candy right now doesn't really sound like a good idea.",
|
|
"All the lights on this street are dark...",
|
|
"It's starting to get late.",
|
|
"The wind howls through the trees. Does it seem darker all of a sudden?",
|
|
"You start to walk the long distance to the next house...",
|
|
"You take a moment to count your candy before moving on.",
|
|
"The house you were approaching just turned the light off.",
|
|
"The wind starts to pick up as you look for the next house...",
|
|
]
|
|
return await message.channel.send(
|
|
random.choice(messages), reference=message.to_reference(fail_if_not_exists=False)
|
|
)
|
|
await self.config.user(message.author).last_tot.set(str(now))
|
|
candy = random.randint(1, 25)
|
|
lollipop = random.randint(0, 100)
|
|
star = random.randint(0, 100)
|
|
chocolates = random.randint(0, 100)
|
|
cookie = random.randint(0, 100)
|
|
win_message = f"{message.author.mention}\nYou received:\n{candy}\N{CANDY}"
|
|
await self.config.user(message.author).candies.set(userdata["candies"] + candy)
|
|
|
|
if chocolates == 100:
|
|
await self.config.user(message.author).chocolates.set(userdata["chocolates"] + 6)
|
|
win_message += "\n**BONUS**: 6 \N{CHOCOLATE BAR}"
|
|
elif 99 >= chocolates >= 95:
|
|
await self.config.user(message.author).chocolates.set(userdata["chocolates"] + 5)
|
|
win_message += "\n**BONUS**: 5 \N{CHOCOLATE BAR}"
|
|
elif 94 >= chocolates >= 90:
|
|
await self.config.user(message.author).chocolates.set(userdata["chocolates"] + 4)
|
|
win_message += "\n**BONUS**: 4 \N{CHOCOLATE BAR}"
|
|
elif 89 >= chocolates >= 80:
|
|
await self.config.user(message.author).chocolates.set(userdata["chocolates"] + 3)
|
|
win_message += "\n**BONUS**: 3 \N{CHOCOLATE BAR}"
|
|
elif 79 >= chocolates >= 75:
|
|
await self.config.user(message.author).chocolates.set(userdata["chocolates"] + 2)
|
|
win_message += "\n**BONUS**: 2 \N{CHOCOLATE BAR}"
|
|
elif 74 >= chocolates >= 70:
|
|
await self.config.user(message.author).chocolates.set(userdata["chocolates"] + 1)
|
|
win_message += "\n**BONUS**: 1 \N{CHOCOLATE BAR}"
|
|
|
|
if lollipop == 100:
|
|
await self.config.user(message.author).lollipops.set(userdata["lollipops"] + 4)
|
|
win_message += "\n**BONUS**: 4 \N{LOLLIPOP}"
|
|
elif 99 >= lollipop >= 95:
|
|
await self.config.user(message.author).lollipops.set(userdata["lollipops"] + 3)
|
|
win_message += "\n**BONUS**: 3 \N{LOLLIPOP}"
|
|
elif 94 >= lollipop >= 85:
|
|
await self.config.user(message.author).lollipops.set(userdata["lollipops"] + 2)
|
|
win_message += "\n**BONUS**: 2 \N{LOLLIPOP}"
|
|
elif 84 >= lollipop >= 75:
|
|
await self.config.user(message.author).lollipops.set(userdata["lollipops"] + 1)
|
|
win_message += "\n**BONUS**: 1 \N{LOLLIPOP}"
|
|
|
|
if cookie == 100:
|
|
await self.config.user(message.author).cookies.set(userdata["cookies"] + 4)
|
|
win_message += "\n**BONUS**: 4 \N{FORTUNE COOKIE}"
|
|
elif 99 >= cookie >= 97:
|
|
await self.config.user(message.author).cookies.set(userdata["cookies"] + 3)
|
|
win_message += "\n**BONUS**: 3 \N{FORTUNE COOKIE}"
|
|
elif 96 >= cookie >= 85:
|
|
await self.config.user(message.author).cookies.set(userdata["cookies"] + 2)
|
|
win_message += "\n**BONUS**: 2 \N{FORTUNE COOKIE}"
|
|
elif 84 >= cookie >= 75:
|
|
await self.config.user(message.author).cookies.set(userdata["cookies"] + 1)
|
|
win_message += "\n**BONUS**: 1 \N{FORTUNE COOKIE}"
|
|
|
|
if star == 100:
|
|
await self.config.user(message.author).stars.set(userdata["stars"] + 4)
|
|
win_message += "\n**BONUS**: 4 \N{WHITE MEDIUM STAR}"
|
|
elif 99 >= star >= 97:
|
|
await self.config.user(message.author).stars.set(userdata["stars"] + 3)
|
|
win_message += "\n**BONUS**: 3 \N{WHITE MEDIUM STAR}"
|
|
elif 96 >= star >= 85:
|
|
await self.config.user(message.author).stars.set(userdata["stars"] + 2)
|
|
win_message += "\n**BONUS**: 2 \N{WHITE MEDIUM STAR}"
|
|
elif 84 >= star >= 75:
|
|
await self.config.user(message.author).stars.set(userdata["stars"] + 1)
|
|
win_message += "\n**BONUS**: 1 \N{WHITE MEDIUM STAR}"
|
|
|
|
walking_messages = [
|
|
"*You hear footsteps...*",
|
|
"*You're left alone with your thoughts as you wait for the door to open...*",
|
|
"*The wind howls through the trees...*",
|
|
"*Does it feel colder out here all of a sudden?*",
|
|
"*Somewhere inside the house, you hear wood creaking...*",
|
|
"*You walk up the path to the door and knock...*",
|
|
"*You knock on the door...*",
|
|
"*There's a movement in the shadows by the side of the house...*",
|
|
]
|
|
bot_talking = await message.channel.send(
|
|
random.choice(walking_messages), reference=message.to_reference(fail_if_not_exists=False)
|
|
)
|
|
await asyncio.sleep(random.randint(5, 8))
|
|
door_messages = [
|
|
"*The door slowly opens...*",
|
|
"*The ancient wooden door starts to open...*",
|
|
"*A light turns on overhead...*",
|
|
"*You hear a scuffling noise...*",
|
|
"*There's someone talking inside...*",
|
|
"*The wind whips around your feet...*",
|
|
"*A crow caws ominously...*",
|
|
"*You hear an owl hooting in the distance...*",
|
|
]
|
|
await bot_talking.edit(content=random.choice(door_messages))
|
|
await asyncio.sleep(random.randint(5, 8))
|
|
greet_messages = [
|
|
"Oh, hello. What a cute costume. Here, have some candy.",
|
|
"Look at that costume. Here you go.",
|
|
"Out this late at night?",
|
|
"Here's a little something for you.",
|
|
"The peppermint ones are my favorite.",
|
|
"Come back again later if you see the light on still.",
|
|
"Go ahead, take a few.",
|
|
"Here you go.",
|
|
"Aww, look at you. Here, take this.",
|
|
"Don't eat all those at once!",
|
|
"Well, I think this is the last of it. Go ahead and take it.",
|
|
"*I hear the next door neighbors have some pretty good candy too, this year.*",
|
|
]
|
|
await bot_talking.edit(content=random.choice(greet_messages))
|
|
await asyncio.sleep(2)
|
|
await message.channel.send(win_message)
|
|
|
|
@staticmethod
|
|
def _red(to_transform: str):
|
|
red_ansi_prefix = "\u001b[0;31m"
|
|
reset_ansi_prefix = "\u001b[0;0m"
|
|
new_string = f"{red_ansi_prefix}{to_transform}{reset_ansi_prefix}"
|
|
return new_string
|
|
|
|
@staticmethod
|
|
def _yellow(to_transform: str):
|
|
yellow_ansi_prefix = "\u001b[0;33m"
|
|
reset_ansi_prefix = "\u001b[0;0m"
|
|
new_string = f"{yellow_ansi_prefix}{to_transform}{reset_ansi_prefix}"
|
|
return new_string
|