189 lines
6.6 KiB
Python
189 lines
6.6 KiB
Python
import asyncio
|
|
import json
|
|
import typing as t
|
|
from io import StringIO
|
|
|
|
import discord
|
|
from aiocache import cached
|
|
from redbot.core import bank, commands
|
|
from redbot.core.bot import Red
|
|
from redbot.core.i18n import Translator
|
|
from redbot.core.utils.chat_formatting import humanize_number, humanize_timedelta
|
|
from redbot.core.utils.menus import start_adding_reactions
|
|
from redbot.core.utils.predicates import MessagePredicate, ReactionPredicate
|
|
|
|
from ..common.models import DB, CommandCost, GuildSettings
|
|
|
|
_ = Translator("ExtendedEconomy", __file__)
|
|
CTYPES = commands.Context | discord.app_commands.ContextMenu | discord.app_commands.Command
|
|
|
|
|
|
async def edit_delete_delay(message: discord.Message, new_content: str, delay: int = None):
|
|
await message.edit(content=new_content, view=None)
|
|
if delay:
|
|
await message.delete(delay=delay)
|
|
|
|
|
|
def ctx_to_id(ctx: commands.Context):
|
|
"""Generate a unique ID for a context command"""
|
|
parts = [
|
|
str(ctx.author.id),
|
|
str(ctx.guild.id if ctx.guild else 0),
|
|
str(ctx.channel.id if ctx.guild else 0),
|
|
str(int(ctx.message.created_at.timestamp())),
|
|
ctx.command.qualified_name,
|
|
]
|
|
return "-".join(parts)
|
|
|
|
|
|
def ctx_to_dict(c: t.Union[commands.Context, discord.Interaction]):
|
|
if isinstance(c, discord.Interaction):
|
|
info = {
|
|
"type": "Interaction",
|
|
"id": c.id,
|
|
"user": c.user.id,
|
|
"guild": c.guild.id if c.guild else None,
|
|
"channel": c.channel.id,
|
|
}
|
|
else:
|
|
info = {
|
|
"type": "Context",
|
|
"id": c.message.id,
|
|
"user": c.author.id,
|
|
"guild": c.guild.id if c.guild else None,
|
|
"channel": c.channel.id,
|
|
}
|
|
return json.dumps(info, indent=2)
|
|
|
|
|
|
@cached(ttl=600)
|
|
async def get_cached_credits_name(guild: discord.Guild) -> str:
|
|
return await bank.get_currency_name(guild)
|
|
|
|
|
|
def has_cost_check(command: CTYPES):
|
|
"""Check if a command already has the cost check attached to it"""
|
|
for check in command.checks:
|
|
if check.__qualname__ == "Checks.cost_check":
|
|
return True
|
|
return False
|
|
|
|
|
|
async def confirm_msg(ctx: t.Union[commands.Context, discord.Interaction]) -> t.Union[bool, None]:
|
|
"""Wait for user to respond yes or no"""
|
|
if isinstance(ctx, discord.Interaction):
|
|
pred = MessagePredicate.yes_or_no(channel=ctx.channel, user=ctx.user)
|
|
bot = ctx.client
|
|
else:
|
|
pred = MessagePredicate.yes_or_no(ctx)
|
|
bot = ctx.bot
|
|
try:
|
|
await bot.wait_for("message", check=pred, timeout=30)
|
|
except asyncio.TimeoutError:
|
|
return None
|
|
else:
|
|
return pred.result
|
|
|
|
|
|
async def confirm_msg_reaction(message: discord.Message, author: t.Union[discord.Member, discord.User], bot: Red):
|
|
"""Wait for user to react with a checkmark or x"""
|
|
start_adding_reactions(message, ReactionPredicate.YES_OR_NO_EMOJIS)
|
|
pred = ReactionPredicate.yes_or_no(message, author)
|
|
try:
|
|
await bot.wait_for("reaction_add", check=pred, timeout=30)
|
|
except asyncio.TimeoutError:
|
|
return None
|
|
else:
|
|
return pred.result
|
|
|
|
|
|
def format_settings(
|
|
db: DB,
|
|
conf: GuildSettings,
|
|
is_global: bool,
|
|
owner: bool,
|
|
delay: t.Union[int, None],
|
|
) -> discord.Embed:
|
|
not_set = _("Not Set")
|
|
txt = StringIO()
|
|
txt.write(_("# Extended Economy Settings\n"))
|
|
tax = f"{round(conf.transfer_tax * 100, 2)}%" if conf.transfer_tax else _("None")
|
|
txt.write(_("`Transfer Tax: `{}\n").format(tax))
|
|
if not is_global:
|
|
tax_whitelist = [f"<@&{r}>" for r in conf.transfer_tax_whitelist]
|
|
txt.write(_("`Tax Whitelist: `{}\n").format(", ".join(tax_whitelist) if tax_whitelist else _("None")))
|
|
costs = len(db.command_costs) if is_global else len(conf.command_costs)
|
|
txt.write(_("`Command Costs: `{}\n").format(costs or _("None")))
|
|
txt.write(_("`Global Bank: `{}\n").format(is_global))
|
|
# If owner
|
|
txt.write(
|
|
_("`Delete After: `{}\n").format(humanize_timedelta(seconds=delay) if delay else _("Disabled"))
|
|
if owner
|
|
else ""
|
|
)
|
|
# If global
|
|
txt.write(
|
|
_("`Set Global: `{}\n").format(f"<#{db.logs.set_global}>" if db.logs.set_global else not_set)
|
|
if is_global
|
|
else ""
|
|
)
|
|
# If not global
|
|
txt.write(_("`Stack Roles: `{}\n").format(conf.stack_paydays) if not is_global else "")
|
|
if not is_global:
|
|
bonuses = ", ".join([f"<@&{r}>" for r in conf.role_bonuses]) if conf.role_bonuses else _("None")
|
|
txt.write(_("`Role Bonuses: `{}\n").format(bonuses) if not is_global else "")
|
|
txt.write(_("`Payday Autoclaim: `{}\n").format(db.auto_payday_claim))
|
|
if not is_global:
|
|
autoclaim_channel = f"<#{conf.logs.auto_claim}>" if conf.logs.auto_claim else not_set
|
|
txt.write(_("`Autoclaim Channel: `{}\n").format(autoclaim_channel))
|
|
roles = ", ".join([f"<@&{r}>" for r in conf.auto_claim_roles]) if conf.auto_claim_roles else _("None")
|
|
txt.write(_("`Autoclaim Roles: `{}\n").format(roles))
|
|
|
|
logs = _(
|
|
"## Event Log Channels\n"
|
|
"`Default Log Channel: `{}\n"
|
|
"`Set Balance: `{}\n"
|
|
"`Transfer Credits: `{}\n"
|
|
"`Bank Wipe: `{}\n"
|
|
"`Prune Accounts: `{}\n"
|
|
).format(
|
|
f"<#{conf.logs.default_log_channel}>" if conf.logs.default_log_channel else not_set,
|
|
f"<#{conf.logs.set_balance}>" if conf.logs.set_balance else not_set,
|
|
f"<#{conf.logs.transfer_credits}>" if conf.logs.transfer_credits else not_set,
|
|
f"<#{conf.logs.bank_wipe}>" if conf.logs.bank_wipe else not_set,
|
|
f"<#{conf.logs.prune}>" if conf.logs.prune else not_set,
|
|
)
|
|
txt.write(logs)
|
|
if not is_global and db.auto_payday_claim:
|
|
txt.write(
|
|
_("`Payday AutoClaim: `{}\n").format(f"<#{db.logs.auto_claim}>" if db.logs.auto_claim else not_set)
|
|
)
|
|
|
|
if isinstance(conf, DB):
|
|
footer = _("Showing settings for global bank")
|
|
else:
|
|
footer = _("Showing settings for this server")
|
|
embed = discord.Embed(description=txt.getvalue(), color=discord.Color.green())
|
|
embed.set_footer(text=footer)
|
|
return embed
|
|
|
|
|
|
def format_command_txt(com: CommandCost):
|
|
txt = _(
|
|
"`Cost: `{}\n"
|
|
"`Duration: `{}\n"
|
|
"`Level: `{}\n"
|
|
"`Prompt: `{}\n"
|
|
"`Modifier: `{}\n"
|
|
"`Value: `{}\n"
|
|
"`Cached Uses: `{}\n"
|
|
).format(
|
|
humanize_number(com.cost),
|
|
humanize_timedelta(seconds=com.duration),
|
|
com.level,
|
|
com.prompt,
|
|
com.modifier,
|
|
com.value,
|
|
humanize_number(len(com.uses)),
|
|
)
|
|
return txt
|