Add multiple new cogs for banking, economy tracking, and referrals, including setup, commands, and localization files.
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
This commit is contained in:
parent
7da3f0ab66
commit
651c9372f2
212 changed files with 32627 additions and 0 deletions
16
bankbackup/README.md
Normal file
16
bankbackup/README.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# BankBackup Help
|
||||
|
||||
Backup bank balances for all members of a guild
|
||||
|
||||
# bankbackup
|
||||
- Usage: `[p]bankbackup`
|
||||
- Restricted to: `GUILD_OWNER`
|
||||
|
||||
Backup your server's bank balances
|
||||
|
||||
# bankrestore
|
||||
- Usage: `[p]bankrestore <set_or_add>`
|
||||
- Restricted to: `GUILD_OWNER`
|
||||
|
||||
Restore your server's bank balances.<br/>Attach your backup file with this command.<br/><br/>**Arguments**<br/>- `<set_or_add>`: Whether you want to `add` or `set` balances from the backup.
|
||||
|
15
bankbackup/__init__.py
Normal file
15
bankbackup/__init__.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import discord
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.utils import get_end_user_data_statement
|
||||
|
||||
from .base import BankBackup
|
||||
|
||||
__red_end_user_data_statement__ = get_end_user_data_statement(__file__)
|
||||
|
||||
|
||||
async def setup(bot: Red):
|
||||
cog = BankBackup(bot)
|
||||
if discord.__version__ > "1.7.3":
|
||||
await bot.add_cog(cog)
|
||||
else:
|
||||
bot.add_cog(cog)
|
86
bankbackup/base.py
Normal file
86
bankbackup/base.py
Normal file
|
@ -0,0 +1,86 @@
|
|||
import json
|
||||
import typing as t
|
||||
|
||||
import aiohttp
|
||||
from redbot.core import bank, commands
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.errors import BalanceTooHigh
|
||||
from redbot.core.utils.chat_formatting import box, text_to_file
|
||||
|
||||
|
||||
class BankBackup(commands.Cog):
|
||||
"""
|
||||
Backup bank balances for all members of a guild
|
||||
"""
|
||||
|
||||
__author__ = "[vertyco](https://github.com/vertyco/vrt-cogs)"
|
||||
__version__ = "0.0.2"
|
||||
|
||||
def format_help_for_context(self, ctx):
|
||||
helpcmd = super().format_help_for_context(ctx)
|
||||
return f"{helpcmd}\nCog Version: {self.__version__}\nAuthor: {self.__author__}"
|
||||
|
||||
async def red_delete_data_for_user(self, *, requester, user_id: int):
|
||||
"""No data to delete"""
|
||||
|
||||
def __init__(self, bot: Red):
|
||||
self.bot: Red = bot
|
||||
|
||||
@commands.command(name="bankbackup")
|
||||
@commands.guildowner()
|
||||
async def backup(self, ctx: commands.Context):
|
||||
"""Backup your guild's bank balances"""
|
||||
if await bank.is_global():
|
||||
return await ctx.send("Cannot make backup. Bank is set to global.")
|
||||
|
||||
_bank_members = await bank._config.all_members(ctx.guild)
|
||||
bank_members: t.Dict[str, int] = {str(k): v["balance"] for k, v in _bank_members.items()}
|
||||
raw = json.dumps(bank_members, indent=2)
|
||||
file = text_to_file(raw, filename=f"bank_backup_{ctx.guild.id}.json")
|
||||
await ctx.send("Here's your bank backup file!", file=file)
|
||||
|
||||
@commands.command(name="bankrestore")
|
||||
@commands.guildowner()
|
||||
async def restore(self, ctx: commands.Context, set_or_add: str):
|
||||
"""
|
||||
Restore your guild's bank balances.
|
||||
Attach your backup file with this command.
|
||||
|
||||
**Arguments**
|
||||
- `<set_or_add>`: Whether you want to `add` or `set` balances from the backup.
|
||||
"""
|
||||
if await bank.is_global():
|
||||
return await ctx.send("Cannot restore backup because bank is set to global.")
|
||||
if not ctx.message.attachments:
|
||||
return await ctx.send("Attach your backup file to the message when using this command.")
|
||||
if "a" not in set_or_add.lower() and "s" not in set_or_add.lower():
|
||||
return await ctx.send(
|
||||
"Specify whether you want to `add` or `set` balances from the backup.\n"
|
||||
"Add: adds the backed up balance to the user's current balance\n"
|
||||
"Set: sets the backup balance as the user's new balance.\n"
|
||||
"You just type in 'set' or 'add' for this argument."
|
||||
)
|
||||
attachment_url = ctx.message.attachments[0].url
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(attachment_url) as resp:
|
||||
bank_data = await resp.json()
|
||||
except Exception as e:
|
||||
return await ctx.send(f"Error:{box(str(e), lang='python')}")
|
||||
|
||||
for uid, balance in bank_data.items():
|
||||
member = ctx.guild.get_member(int(uid))
|
||||
if not member:
|
||||
continue
|
||||
if "a" in set_or_add.lower():
|
||||
try:
|
||||
await bank.deposit_credits(member, balance)
|
||||
except BalanceTooHigh as e:
|
||||
await bank.set_balance(member, e.max_balance)
|
||||
else:
|
||||
await bank.set_balance(member, balance)
|
||||
|
||||
if "a" in set_or_add.lower():
|
||||
await ctx.send("Saved balances have been added to user's current balance!")
|
||||
else:
|
||||
await ctx.send("Balances have been restored from the backup!")
|
28
bankbackup/info.json
Normal file
28
bankbackup/info.json
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"author": [
|
||||
"Vertyco"
|
||||
],
|
||||
"description": "Backup/Restore for server bank balances",
|
||||
"disabled": false,
|
||||
"end_user_data_statement": "This cog does not store data about users.",
|
||||
"hidden": false,
|
||||
"install_msg": "Thank you for installing! This cog is for transferring bank balances on a per-server basis for bots that have local banks enabled.",
|
||||
"min_bot_version": "3.4.0",
|
||||
"min_python_version": [
|
||||
3,
|
||||
8,
|
||||
1
|
||||
],
|
||||
"permissions": [
|
||||
"administrator"
|
||||
],
|
||||
"required_cogs": {},
|
||||
"requirements": [],
|
||||
"short": "Backup and restore bank balances for all members in a server",
|
||||
"tags": [
|
||||
"utility",
|
||||
"economy",
|
||||
"bank"
|
||||
],
|
||||
"type": "COG"
|
||||
}
|
62
bankdecay/README.md
Normal file
62
bankdecay/README.md
Normal file
|
@ -0,0 +1,62 @@
|
|||
Economy decay!<br/><br/>Periodically reduces users' red currency based on inactivity, encouraging engagement.<br/>Server admins can configure decay parameters, view settings, and manually trigger decay cycles.<br/>User activity is tracked via messages and reactions.
|
||||
|
||||
# [p]bankdecay
|
||||
Setup economy credit decay for your server<br/>
|
||||
- Usage: `[p]bankdecay`
|
||||
- Restricted to: `ADMIN`
|
||||
- Aliases: `bdecay`
|
||||
- Checks: `server_only`
|
||||
## [p]bankdecay toggle
|
||||
Toggle the bank decay feature on or off.<br/>
|
||||
- Usage: `[p]bankdecay toggle`
|
||||
## [p]bankdecay setdays
|
||||
Set the number of inactive days before decay starts.<br/>
|
||||
- Usage: `[p]bankdecay setdays <days>`
|
||||
## [p]bankdecay setpercent
|
||||
Set the percentage of decay that occurs after the inactive period.<br/>
|
||||
|
||||
**Example**<br/>
|
||||
If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.<br/>
|
||||
- Usage: `[p]bankdecay setpercent <percent>`
|
||||
## [p]bankdecay resettotal
|
||||
Reset the total amount decayed to zero.<br/>
|
||||
- Usage: `[p]bankdecay resettotal`
|
||||
## [p]bankdecay initialize
|
||||
Initialize the server and add every member to the config.<br/>
|
||||
|
||||
**Arguments**<br/>
|
||||
- as_expired: (t/f) if True, initialize users as already expired<br/>
|
||||
- Usage: `[p]bankdecay initialize <as_expired>`
|
||||
## [p]bankdecay getexpired
|
||||
Get a list of users who are currently expired and how much they will lose if decayed<br/>
|
||||
- Usage: `[p]bankdecay getexpired`
|
||||
## [p]bankdecay ignorerole
|
||||
Add/Remove a role from the ignore list<br/>
|
||||
|
||||
Users with an ignored role will not have their balance decay<br/>
|
||||
- Usage: `[p]bankdecay ignorerole <role>`
|
||||
## [p]bankdecay logchannel
|
||||
Set the log channel, each time the decay cycle runs this will be updated<br/>
|
||||
- Usage: `[p]bankdecay logchannel <channel>`
|
||||
## [p]bankdecay cleanup
|
||||
Remove users from the config that are no longer in the server or have no balance<br/>
|
||||
- Usage: `[p]bankdecay cleanup <confirm>`
|
||||
## [p]bankdecay seen
|
||||
Check when a user was last active (if at all)<br/>
|
||||
- Usage: `[p]bankdecay seen <user>`
|
||||
## [p]bankdecay bulkaddpercent
|
||||
Add a percentage to all member balances.<br/>
|
||||
|
||||
Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.<br/>
|
||||
- Usage: `[p]bankdecay bulkaddpercent <percent> <confirm>`
|
||||
## [p]bankdecay bulkrempercent
|
||||
Remove a percentage from all member balances.<br/>
|
||||
|
||||
Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.<br/>
|
||||
- Usage: `[p]bankdecay bulkrempercent <percent> <confirm>`
|
||||
## [p]bankdecay decaynow
|
||||
Run a decay cycle on this server right now<br/>
|
||||
- Usage: `[p]bankdecay decaynow [force=False]`
|
||||
## [p]bankdecay view
|
||||
View Bank Decay Settings<br/>
|
||||
- Usage: `[p]bankdecay view`
|
11
bankdecay/__init__.py
Normal file
11
bankdecay/__init__.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from redbot.core.bot import Red
|
||||
from redbot.core.utils import get_end_user_data_statement
|
||||
|
||||
from .main import BankDecay
|
||||
|
||||
__red_end_user_data_statement__ = get_end_user_data_statement(__file__)
|
||||
|
||||
|
||||
async def setup(bot: Red):
|
||||
cog = BankDecay(bot)
|
||||
await bot.add_cog(cog)
|
27
bankdecay/abc.py
Normal file
27
bankdecay/abc.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
import typing as t
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
import discord
|
||||
from discord.ext.commands.cog import CogMeta
|
||||
from redbot.core.bot import Red
|
||||
|
||||
from .common.models import DB
|
||||
|
||||
|
||||
class CompositeMetaClass(CogMeta, ABCMeta):
|
||||
"""Type detection"""
|
||||
|
||||
|
||||
class MixinMeta(metaclass=ABCMeta):
|
||||
"""Type hinting"""
|
||||
|
||||
bot: Red
|
||||
db: DB
|
||||
|
||||
@abstractmethod
|
||||
async def save(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
async def decay_guild(self, guild: discord.Guild, check_only: bool = False) -> t.Dict[str, int]:
|
||||
raise NotImplementedError
|
369
bankdecay/commands/admin.py
Normal file
369
bankdecay/commands/admin.py
Normal file
|
@ -0,0 +1,369 @@
|
|||
import math
|
||||
from datetime import datetime, timedelta
|
||||
from io import StringIO
|
||||
|
||||
import discord
|
||||
from redbot.core import bank, commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import humanize_number, text_to_file
|
||||
|
||||
from ..abc import MixinMeta
|
||||
from ..common.confirm_view import ConfirmView
|
||||
from ..common.models import User
|
||||
|
||||
_ = Translator("BankDecay", __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Admin(MixinMeta):
|
||||
@commands.group(aliases=["bdecay"])
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@commands.guild_only()
|
||||
async def bankdecay(self, ctx: commands.Context):
|
||||
"""
|
||||
Setup economy credit decay for your server
|
||||
"""
|
||||
pass
|
||||
|
||||
@bankdecay.command(name="view")
|
||||
@commands.bot_has_permissions(embed_links=True)
|
||||
async def view_settings(self, ctx: commands.Context):
|
||||
"""View Bank Decay Settings"""
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
|
||||
expired = 0
|
||||
active = 0
|
||||
left_server = 0
|
||||
for uid, user in conf.users.items():
|
||||
member = ctx.guild.get_member(uid)
|
||||
if not member:
|
||||
left_server += 1
|
||||
elif user.last_active + timedelta(days=conf.inactive_days) < datetime.now():
|
||||
expired += 1
|
||||
else:
|
||||
active += 1
|
||||
|
||||
ignored_roles = [f"<@&{i}>" for i in conf.ignored_roles]
|
||||
log_channel = (
|
||||
ctx.guild.get_channel(conf.log_channel) if ctx.guild.get_channel(conf.log_channel) else _("Not Set")
|
||||
)
|
||||
now = datetime.now()
|
||||
next_midnight = now.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1)
|
||||
next_run = f"<t:{round(next_midnight.timestamp())}:R>"
|
||||
txt = _(
|
||||
"`Decay Enabled: `{}\n"
|
||||
"`Inactive Days: `{}\n"
|
||||
"`Percent Decay: `{}\n"
|
||||
"`Saved Users: `{}\n"
|
||||
"`Active Users: `{}\n"
|
||||
"`Expired Users: `{}\n"
|
||||
"`Stale Users: `{}\n"
|
||||
"`Total Decayed: `{}\n"
|
||||
"`Log Channel: `{}\n"
|
||||
).format(
|
||||
conf.enabled,
|
||||
conf.inactive_days,
|
||||
round(conf.percent_decay * 100),
|
||||
humanize_number(len(conf.users)),
|
||||
humanize_number(active),
|
||||
humanize_number(expired),
|
||||
humanize_number(left_server),
|
||||
humanize_number(conf.total_decayed),
|
||||
log_channel,
|
||||
)
|
||||
if conf.enabled:
|
||||
txt += _("`Next Runtime: `{}\n").format(next_run)
|
||||
if ignored_roles:
|
||||
joined = ", ".join(ignored_roles)
|
||||
txt += _("**Ignored Roles**\n") + joined
|
||||
embed = discord.Embed(
|
||||
title=_("BankDecay Settings"),
|
||||
description=txt,
|
||||
color=ctx.author.color,
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@bankdecay.command(name="toggle")
|
||||
async def toggle_decay(self, ctx: commands.Context):
|
||||
"""
|
||||
Toggle the bank decay feature on or off.
|
||||
"""
|
||||
if await bank.is_global():
|
||||
await ctx.send(_("This command is not available when using global bank."))
|
||||
return
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
conf.enabled = not conf.enabled
|
||||
await ctx.send(_("Bank decay has been {}.").format(_("enabled") if conf.enabled else _("disabled")))
|
||||
await self.save()
|
||||
|
||||
@bankdecay.command(name="setdays")
|
||||
async def set_inactive_days(self, ctx: commands.Context, days: commands.positive_int):
|
||||
"""
|
||||
Set the number of inactive days before decay starts.
|
||||
"""
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
conf.inactive_days = days
|
||||
await ctx.send(_("Inactive days set to {}.").format(days))
|
||||
await self.save()
|
||||
|
||||
@bankdecay.command(name="setpercent")
|
||||
async def set_percent_decay(self, ctx: commands.Context, percent: float):
|
||||
"""
|
||||
Set the percentage of decay that occurs after the inactive period.
|
||||
|
||||
**Example**
|
||||
If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.
|
||||
"""
|
||||
if not 0 <= percent <= 1:
|
||||
await ctx.send(_("Percent decay must be between 0 and 1."))
|
||||
return
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
conf.percent_decay = percent
|
||||
await ctx.send(_("Percent decay set to {}%.").format(round(percent * 100)))
|
||||
await self.save()
|
||||
|
||||
@bankdecay.command(name="resettotal")
|
||||
async def reset_total_decayed(self, ctx: commands.Context):
|
||||
"""
|
||||
Reset the total amount decayed to zero.
|
||||
"""
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
conf.total_decayed = 0
|
||||
await ctx.send(_("Total decayed amount has been reset to 0."))
|
||||
await self.save()
|
||||
|
||||
@bankdecay.command(name="decaynow")
|
||||
async def decay_now(self, ctx: commands.Context, force: bool = False):
|
||||
"""
|
||||
Run a decay cycle on this server right now
|
||||
"""
|
||||
if await bank.is_global():
|
||||
await ctx.send(_("This command is not available when using global bank."))
|
||||
return
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
if not conf.enabled:
|
||||
txt = _("The decay system is currently disabled!")
|
||||
return await ctx.send(txt)
|
||||
async with ctx.typing():
|
||||
currency = await bank.get_currency_name(ctx.guild)
|
||||
if not force:
|
||||
decayed = await self.decay_guild(ctx.guild, check_only=True)
|
||||
if not decayed:
|
||||
txt = _("There were no users affected by the decay cycle")
|
||||
return await ctx.send(txt)
|
||||
grammar = _("account") if len(decayed) == 1 else _("accounts")
|
||||
txt = _("Are you sure you want to decay {} for a total of {}?").format(
|
||||
f"**{humanize_number(len(decayed))}** {grammar}",
|
||||
f"**{humanize_number(sum(decayed.values()))}** {currency}",
|
||||
)
|
||||
view = ConfirmView(ctx.author)
|
||||
msg = await ctx.send(txt, view=view)
|
||||
await view.wait()
|
||||
if not view.value:
|
||||
txt = _("Decay cycle cancelled")
|
||||
return await msg.edit(content=txt, view=None)
|
||||
txt = _("Decaying user accounts, one moment...")
|
||||
await msg.edit(content=txt, view=None)
|
||||
else:
|
||||
txt = _("Decaying user accounts, one moment...")
|
||||
msg = await ctx.send(txt)
|
||||
|
||||
decayed = await self.decay_guild(ctx.guild)
|
||||
|
||||
txt = _("User accounts have been decayed!\n- Users Affected: {}\n- Total {} Decayed: {}").format(
|
||||
humanize_number(len(decayed)), currency, humanize_number(sum(decayed.values()))
|
||||
)
|
||||
await msg.edit(content=txt)
|
||||
await self.save()
|
||||
|
||||
@bankdecay.command(name="getexpired")
|
||||
async def get_expired_users(self, ctx: commands.Context):
|
||||
"""Get a list of users who are currently expired and how much they will lose if decayed"""
|
||||
if await bank.is_global():
|
||||
await ctx.send(_("This command is not available when using global bank."))
|
||||
return
|
||||
async with ctx.typing():
|
||||
decayed = await self.decay_guild(ctx.guild, check_only=True)
|
||||
if not decayed:
|
||||
txt = _("There were no users that would be affected by the decay cycle")
|
||||
return await ctx.send(txt)
|
||||
|
||||
grammar = _("account") if len(decayed) == 1 else _("accounts")
|
||||
txt = _("This would decay {} for a total of {}").format(
|
||||
f"**{humanize_number(len(decayed))}** {grammar}",
|
||||
f"**{humanize_number(sum(decayed.values()))}** credits",
|
||||
)
|
||||
# Create a text file with the list of users and how much they will lose
|
||||
buffer = StringIO()
|
||||
for user, amount in sorted(decayed.items(), key=lambda x: x[1], reverse=True):
|
||||
buffer.write(f"{user}: {amount}\n")
|
||||
buffer.seek(0)
|
||||
file = text_to_file(buffer.getvalue(), filename="expired_users.txt")
|
||||
await ctx.send(txt, file=file)
|
||||
|
||||
@bankdecay.command(name="cleanup")
|
||||
async def cleanup(self, ctx: commands.Context, confirm: bool):
|
||||
"""
|
||||
Remove users from the config that are no longer in the server or have no balance
|
||||
"""
|
||||
if await bank.is_global():
|
||||
await ctx.send(_("This command is not available when using global bank."))
|
||||
return
|
||||
|
||||
if not confirm:
|
||||
txt = _("Not removing users from the config")
|
||||
return await ctx.send(txt)
|
||||
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
global_bank = await bank.is_global()
|
||||
cleaned = 0
|
||||
for uid in conf.users.copy():
|
||||
member = ctx.guild.get_member(uid)
|
||||
if not member:
|
||||
del conf.users[uid]
|
||||
cleaned += 1
|
||||
elif not global_bank and await bank.get_balance(member) == 0:
|
||||
del conf.users[uid]
|
||||
cleaned += 1
|
||||
if not cleaned:
|
||||
txt = _("No users were removed from the config.")
|
||||
return await ctx.send(txt)
|
||||
|
||||
grammar = _("user") if cleaned == 1 else _("users")
|
||||
txt = _("Removed {} from the config.").format(f"{cleaned} {grammar}")
|
||||
await ctx.send(txt)
|
||||
await self.save()
|
||||
|
||||
@bankdecay.command(name="initialize")
|
||||
async def initialize_guild(self, ctx: commands.Context, as_expired: bool):
|
||||
"""
|
||||
Initialize the server and add every member to the config.
|
||||
|
||||
**Arguments**
|
||||
- as_expired: (t/f) if True, initialize users as already expired
|
||||
"""
|
||||
if await bank.is_global():
|
||||
await ctx.send(_("This command is not available when using global bank."))
|
||||
return
|
||||
|
||||
async with ctx.typing():
|
||||
initialized = 0
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
for member in ctx.guild.members:
|
||||
if member.bot: # Skip bots
|
||||
continue
|
||||
if member.id in conf.users:
|
||||
continue
|
||||
user = conf.get_user(member) # This will add the member to the config if not already present
|
||||
initialized += 1
|
||||
if as_expired:
|
||||
user.last_active = user.last_active - timedelta(days=conf.inactive_days + 1)
|
||||
|
||||
grammar = _("member") if initialized == 1 else _("members")
|
||||
await ctx.send(_("Server initialized! {} added to the config.").format(f"{initialized} {grammar}"))
|
||||
await self.save()
|
||||
|
||||
@bankdecay.command(name="seen")
|
||||
async def last_seen(self, ctx: commands.Context, *, user: discord.Member | int):
|
||||
"""
|
||||
Check when a user was last active (if at all)
|
||||
"""
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
uid = user if isinstance(user, int) else user.id
|
||||
if uid not in conf.users:
|
||||
txt = _("This user is not in the config yet!")
|
||||
return await ctx.send(txt)
|
||||
user: User = conf.get_user(uid)
|
||||
txt = _("User was last seen {}").format(f"{user.seen_f} ({user.seen_r})")
|
||||
await ctx.send(txt)
|
||||
|
||||
@bankdecay.command(name="ignorerole")
|
||||
async def ignore_role(self, ctx: commands.Context, *, role: discord.Role):
|
||||
"""
|
||||
Add/Remove a role from the ignore list
|
||||
|
||||
Users with an ignored role will not have their balance decay
|
||||
"""
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
if role.id in conf.ignored_roles:
|
||||
conf.ignored_roles.remove(role.id)
|
||||
txt = _("Role removed from the ignore list.")
|
||||
else:
|
||||
conf.ignored_roles.append(role.id)
|
||||
txt = _("Role added to the ignore list.")
|
||||
await ctx.send(txt)
|
||||
await self.save()
|
||||
|
||||
@bankdecay.command(name="logchannel")
|
||||
async def set_log_channel(self, ctx: commands.Context, *, channel: discord.TextChannel):
|
||||
"""
|
||||
Set the log channel, each time the decay cycle runs this will be updated
|
||||
"""
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
conf.log_channel = channel.id
|
||||
await ctx.send(_("Log channel has been set!"))
|
||||
await self.save()
|
||||
|
||||
@bankdecay.command(name="bulkaddpercent")
|
||||
async def bulk_add_percent(self, ctx: commands.Context, percent: int, confirm: bool):
|
||||
"""
|
||||
Add a percentage to all member balances.
|
||||
|
||||
Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.
|
||||
"""
|
||||
if await bank.is_global():
|
||||
await ctx.send(_("This command is not available when using global bank."))
|
||||
return
|
||||
|
||||
if not confirm:
|
||||
txt = _("Not adding credits to users")
|
||||
return await ctx.send(txt)
|
||||
|
||||
if percent < 1:
|
||||
txt = _("Percent must be greater than 1!")
|
||||
return await ctx.send(txt)
|
||||
|
||||
async with ctx.typing():
|
||||
refunded = 0
|
||||
ratio = percent / 100
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
users = [ctx.guild.get_member(int(i)) for i in conf.users if ctx.guild.get_member(int(i))]
|
||||
for user in users:
|
||||
bal = await bank.get_balance(user)
|
||||
to_give = math.ceil(bal * ratio)
|
||||
await bank.set_balance(user, bal + to_give)
|
||||
refunded += to_give
|
||||
|
||||
await ctx.send(_("Credits added: {}").format(humanize_number(refunded)))
|
||||
|
||||
@bankdecay.command(name="bulkrempercent")
|
||||
async def bulk_rem_percent(self, ctx: commands.Context, percent: int, confirm: bool):
|
||||
"""
|
||||
Remove a percentage from all member balances.
|
||||
|
||||
Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.
|
||||
"""
|
||||
if await bank.is_global():
|
||||
await ctx.send(_("This command is not available when using global bank."))
|
||||
return
|
||||
|
||||
if not confirm:
|
||||
txt = _("Not removing credits from users")
|
||||
return await ctx.send(txt)
|
||||
|
||||
if percent < 1:
|
||||
txt = _("Percent must be greater than 1!")
|
||||
return await ctx.send(txt)
|
||||
|
||||
async with ctx.typing():
|
||||
taken = 0
|
||||
ratio = percent / 100
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
users = [ctx.guild.get_member(int(i)) for i in conf.users if ctx.guild.get_member(int(i))]
|
||||
for user in users:
|
||||
bal = await bank.get_balance(user)
|
||||
to_take = math.ceil(bal * ratio)
|
||||
await bank.withdraw_credits(user, to_take)
|
||||
taken += to_take
|
||||
|
||||
await ctx.send(_("Credits removed: {}").format(humanize_number(taken)))
|
307
bankdecay/commands/locales/de-DE.po
Normal file
307
bankdecay/commands/locales/de-DE.po
Normal file
|
@ -0,0 +1,307 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-01-04 12:10-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: German\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: de\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/commands/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 108\n"
|
||||
"Language: de_DE\n"
|
||||
|
||||
#: commands\admin.py:23
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Setup economy credit decay for your server\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:31
|
||||
#, docstring
|
||||
msgid "View Bank Decay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:48
|
||||
msgid "Not Set"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:53
|
||||
msgid "`Decay Enabled: `{}\n"
|
||||
"`Inactive Days: `{}\n"
|
||||
"`Percent Decay: `{}\n"
|
||||
"`Saved Users: `{}\n"
|
||||
"`Active Users: `{}\n"
|
||||
"`Expired Users: `{}\n"
|
||||
"`Stale Users: `{}\n"
|
||||
"`Total Decayed: `{}\n"
|
||||
"`Log Channel: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:75
|
||||
msgid "`Next Runtime: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:78
|
||||
msgid "**Ignored Roles**\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:80
|
||||
msgid "BankDecay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:88
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Toggle the bank decay feature on or off.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:92 commands\admin.py:144 commands\admin.py:186
|
||||
#: commands\admin.py:213 commands\admin.py:249 commands\admin.py:318
|
||||
#: commands\admin.py:350
|
||||
msgid "This command is not available when using global bank."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "Bank decay has been {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:101
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of inactive days before decay starts.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:105
|
||||
msgid "Inactive days cannot be negative."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:109
|
||||
msgid "Inactive days set to {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:114
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the percentage of decay that occurs after the inactive period.\n\n"
|
||||
" **Example**\n"
|
||||
" If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:121
|
||||
msgid "Percent decay must be between 0 and 1."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:125
|
||||
msgid "Percent decay set to {}%."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:130
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Reset the total amount decayed to zero.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:135
|
||||
msgid "Total decayed amount has been reset to 0."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:140
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Run a decay cycle on this server right now\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:148
|
||||
msgid "The decay system is currently disabled!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:155
|
||||
msgid "There were no users affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "accounts"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:158
|
||||
msgid "Are you sure you want to decay {} for a total of {}?"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:166
|
||||
msgid "Decay cycle cancelled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:168 commands\admin.py:171
|
||||
msgid "Decaying user accounts, one moment..."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:176
|
||||
msgid "User accounts have been decayed!\n"
|
||||
"- Users Affected: {}\n"
|
||||
"- Total {} Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:184
|
||||
#, docstring
|
||||
msgid "Get a list of users who are currently expired and how much they will lose if decayed"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:191
|
||||
msgid "There were no users that would be affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:195
|
||||
msgid "This would decay {} for a total of {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:209
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove users from the config that are no longer in the server or have no balance\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:217
|
||||
msgid "Not removing users from the config"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:232
|
||||
msgid "No users were removed from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:236
|
||||
msgid "Removed {} from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:242
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Initialize the server and add every member to the config.\n\n"
|
||||
" **Arguments**\n"
|
||||
" - as_expired: (t/f) if True, initialize users as already expired\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "member"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "members"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:266
|
||||
msgid "Server initialized! {} added to the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:271
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Check when a user was last active (if at all)\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:277
|
||||
msgid "This user is not in the config yet!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:280
|
||||
msgid "User was last seen {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:285
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove a role from the ignore list\n\n"
|
||||
" Users with an ignored role will not have their balance decay\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:293
|
||||
msgid "Role removed from the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:296
|
||||
msgid "Role added to the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:302
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the log channel, each time the decay cycle runs this will be updated\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:307
|
||||
msgid "Log channel has been set!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:312
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add a percentage to all member balances.\n\n"
|
||||
" Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:322
|
||||
msgid "Not adding credits to users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:326 commands\admin.py:358
|
||||
msgid "Percent must be greater than 1!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:340
|
||||
msgid "Credits added: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:344
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove a percentage from all member balances.\n\n"
|
||||
" Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:354
|
||||
msgid "Not removing credits from users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:372
|
||||
msgid "Credits removed: {}"
|
||||
msgstr ""
|
||||
|
350
bankdecay/commands/locales/es-ES.po
Normal file
350
bankdecay/commands/locales/es-ES.po
Normal file
|
@ -0,0 +1,350 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-01-04 12:10-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Spanish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: es-ES\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/commands/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 108\n"
|
||||
"Language: es_ES\n"
|
||||
|
||||
#: commands\admin.py:23
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Setup economy credit decay for your server\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Configura la caída de créditos de la economía para tu servidor\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:31
|
||||
#, docstring
|
||||
msgid "View Bank Decay Settings"
|
||||
msgstr "Ver Configuraciones de Caída del Banco"
|
||||
|
||||
#: commands\admin.py:48
|
||||
msgid "Not Set"
|
||||
msgstr "No fijado"
|
||||
|
||||
#: commands\admin.py:53
|
||||
msgid "`Decay Enabled: `{}\n"
|
||||
"`Inactive Days: `{}\n"
|
||||
"`Percent Decay: `{}\n"
|
||||
"`Saved Users: `{}\n"
|
||||
"`Active Users: `{}\n"
|
||||
"`Expired Users: `{}\n"
|
||||
"`Stale Users: `{}\n"
|
||||
"`Total Decayed: `{}\n"
|
||||
"`Log Channel: `{}\n"
|
||||
msgstr "`Decadencia Activada: `{}\n"
|
||||
"`Días Inactivos: `{}\n"
|
||||
"`Porcentaje de Decadencia: `{}\n"
|
||||
"`Usuarios Guardados: `{}\n"
|
||||
"`Usuarios Activos: `{}\n"
|
||||
"`Usuarios Expirados: `{}\n"
|
||||
"`Usuarios Antiguos: `{}\n"
|
||||
"`Total Decadente: `{}\n"
|
||||
"`Canal de Registro: `{}\n"
|
||||
|
||||
#: commands\admin.py:75
|
||||
msgid "`Next Runtime: `{}\n"
|
||||
msgstr "`Próxima Ejecución: `{}\n"
|
||||
|
||||
#: commands\admin.py:78
|
||||
msgid "**Ignored Roles**\n"
|
||||
msgstr "**Funciones ignoradas**\n"
|
||||
|
||||
#: commands\admin.py:80
|
||||
msgid "BankDecay Settings"
|
||||
msgstr "Configuraciones de Decadencia del Banco"
|
||||
|
||||
#: commands\admin.py:88
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Toggle the bank decay feature on or off.\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Activa o desactiva la función de caída del banco.\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:92 commands\admin.py:144 commands\admin.py:186
|
||||
#: commands\admin.py:213 commands\admin.py:249 commands\admin.py:318
|
||||
#: commands\admin.py:350
|
||||
msgid "This command is not available when using global bank."
|
||||
msgstr "Este comando no está disponible cuando se usa el banco global."
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "Bank decay has been {}."
|
||||
msgstr "La caída del banco ha sido {}."
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "enabled"
|
||||
msgstr "activada"
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "disabled"
|
||||
msgstr "desactivada"
|
||||
|
||||
#: commands\admin.py:101
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of inactive days before decay starts.\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Establece el número de días inactivos antes de que comience la decadencia.\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:105
|
||||
msgid "Inactive days cannot be negative."
|
||||
msgstr "Los días inactivos no pueden ser negativos."
|
||||
|
||||
#: commands\admin.py:109
|
||||
msgid "Inactive days set to {}."
|
||||
msgstr "Días inactivos establecidos en {}."
|
||||
|
||||
#: commands\admin.py:114
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the percentage of decay that occurs after the inactive period.\n\n"
|
||||
" **Example**\n"
|
||||
" If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Establece el porcentaje de decadencia que ocurre después del período de inactividad.\n\n"
|
||||
" **Ejemplo**\n"
|
||||
" Si la decadencia es del 5%, después de los días establecidos de inactividad perderán el 5% de su saldo cada día.\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:121
|
||||
msgid "Percent decay must be between 0 and 1."
|
||||
msgstr "El porcentaje de decadencia debe estar entre 0 y 1."
|
||||
|
||||
#: commands\admin.py:125
|
||||
msgid "Percent decay set to {}%."
|
||||
msgstr "Porcentaje de decadencia establecido en {}%."
|
||||
|
||||
#: commands\admin.py:130
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Reset the total amount decayed to zero.\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Restablece la cantidad total decadente a cero.\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:135
|
||||
msgid "Total decayed amount has been reset to 0."
|
||||
msgstr "La cantidad total decadente ha sido restablecida a 0."
|
||||
|
||||
#: commands\admin.py:140
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Run a decay cycle on this server right now\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Ejecuta un ciclo de decadencia en este servidor ahora mismo\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:148
|
||||
msgid "The decay system is currently disabled!"
|
||||
msgstr "¡El sistema de decadencia está actualmente desactivado!"
|
||||
|
||||
#: commands\admin.py:155
|
||||
msgid "There were no users affected by the decay cycle"
|
||||
msgstr "No hubo usuarios afectados por el ciclo de decadencia"
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "account"
|
||||
msgstr "cuenta"
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "accounts"
|
||||
msgstr "cuentas"
|
||||
|
||||
#: commands\admin.py:158
|
||||
msgid "Are you sure you want to decay {} for a total of {}?"
|
||||
msgstr "¿Estás seguro de que quieres decaer {} por un total de {}?"
|
||||
|
||||
#: commands\admin.py:166
|
||||
msgid "Decay cycle cancelled"
|
||||
msgstr "Ciclo de decadencia cancelado"
|
||||
|
||||
#: commands\admin.py:168 commands\admin.py:171
|
||||
msgid "Decaying user accounts, one moment..."
|
||||
msgstr "Decayendo cuentas de usuarios, un momento..."
|
||||
|
||||
#: commands\admin.py:176
|
||||
msgid "User accounts have been decayed!\n"
|
||||
"- Users Affected: {}\n"
|
||||
"- Total {} Decayed: {}"
|
||||
msgstr "¡Las cuentas de usuario han decaído!\n"
|
||||
"- Usuarios Afectados: {}\n"
|
||||
"- Total {} Decadido: {}"
|
||||
|
||||
#: commands\admin.py:184
|
||||
#, docstring
|
||||
msgid "Get a list of users who are currently expired and how much they will lose if decayed"
|
||||
msgstr "Obtener una lista de usuarios que están actualmente expirados y cuánto perderán si se descomponen"
|
||||
|
||||
#: commands\admin.py:191
|
||||
msgid "There were no users that would be affected by the decay cycle"
|
||||
msgstr "No hubo usuarios que se verían afectados por el ciclo de descomposición"
|
||||
|
||||
#: commands\admin.py:195
|
||||
msgid "This would decay {} for a total of {}"
|
||||
msgstr "Esto descompondría {} por un total de {}"
|
||||
|
||||
#: commands\admin.py:209
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove users from the config that are no longer in the server or have no balance\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Eliminar usuarios de la configuración que ya no están en el servidor o no tienen saldo\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:217
|
||||
msgid "Not removing users from the config"
|
||||
msgstr "No se están eliminando usuarios de la configuración"
|
||||
|
||||
#: commands\admin.py:232
|
||||
msgid "No users were removed from the config."
|
||||
msgstr "No se eliminaron usuarios de la configuración."
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "user"
|
||||
msgstr "usuario"
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "users"
|
||||
msgstr "usuarios"
|
||||
|
||||
#: commands\admin.py:236
|
||||
msgid "Removed {} from the config."
|
||||
msgstr "Eliminado {} de la configuración."
|
||||
|
||||
#: commands\admin.py:242
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Initialize the server and add every member to the config.\n\n"
|
||||
" **Arguments**\n"
|
||||
" - as_expired: (t/f) if True, initialize users as already expired\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Inicializar el servidor y agregar a cada miembro a la configuración.\n\n"
|
||||
" **Argumentos**\n"
|
||||
" - as_expired: (t/f) si es True, inicializa a los usuarios como ya expirados\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "member"
|
||||
msgstr "miembro"
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "members"
|
||||
msgstr "miembros"
|
||||
|
||||
#: commands\admin.py:266
|
||||
msgid "Server initialized! {} added to the config."
|
||||
msgstr "¡Servidor inicializado! {} añadido a la configuración."
|
||||
|
||||
#: commands\admin.py:271
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Check when a user was last active (if at all)\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Verifica cuándo fue la última vez que un usuario estuvo activo (si es que alguna vez)\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:277
|
||||
msgid "This user is not in the config yet!"
|
||||
msgstr "¡Este usuario aún no está en la configuración!"
|
||||
|
||||
#: commands\admin.py:280
|
||||
msgid "User was last seen {}"
|
||||
msgstr "El usuario fue visto por última vez {}"
|
||||
|
||||
#: commands\admin.py:285
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove a role from the ignore list\n\n"
|
||||
" Users with an ignored role will not have their balance decay\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Añadir/Eliminar un rol de la lista de ignorados\n\n"
|
||||
" Los usuarios con un rol ignorado no verán decaer su saldo\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:293
|
||||
msgid "Role removed from the ignore list."
|
||||
msgstr "Rol eliminado de la lista de ignorados."
|
||||
|
||||
#: commands\admin.py:296
|
||||
msgid "Role added to the ignore list."
|
||||
msgstr "Rol añadido a la lista de ignorados."
|
||||
|
||||
#: commands\admin.py:302
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the log channel, each time the decay cycle runs this will be updated\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Configurar el canal de registro, cada vez que se ejecute el ciclo de descomposición esto se actualizará\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:307
|
||||
msgid "Log channel has been set!"
|
||||
msgstr "¡Se ha establecido el canal de registro!"
|
||||
|
||||
#: commands\admin.py:312
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add a percentage to all member balances.\n\n"
|
||||
" Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Agregar un porcentaje a los saldos de todos los miembros.\n\n"
|
||||
" ¿Dismuiste accidentalmente demasiados créditos? Añadir en masa a cada saldo de usuario en el servidor basado en un porcentaje de su saldo actual.\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:322
|
||||
msgid "Not adding credits to users"
|
||||
msgstr "No agregando créditos a los usuarios"
|
||||
|
||||
#: commands\admin.py:326 commands\admin.py:358
|
||||
msgid "Percent must be greater than 1!"
|
||||
msgstr "¡El porcentaje debe ser mayor que 1!"
|
||||
|
||||
#: commands\admin.py:340
|
||||
msgid "Credits added: {}"
|
||||
msgstr "Créditos agregados: {}"
|
||||
|
||||
#: commands\admin.py:344
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove a percentage from all member balances.\n\n"
|
||||
" Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" Eliminar un porcentaje de los saldos de todos los miembros.\n\n"
|
||||
" ¿Reembolsaste accidentalmente demasiados créditos con bulkaddpercent? Eliminar en masa de cada saldo de usuario en el servidor basado en un porcentaje de su saldo actual.\n"
|
||||
" "
|
||||
|
||||
#: commands\admin.py:354
|
||||
msgid "Not removing credits from users"
|
||||
msgstr "No eliminando créditos a los usuarios"
|
||||
|
||||
#: commands\admin.py:372
|
||||
msgid "Credits removed: {}"
|
||||
msgstr "Créditos eliminados: {}"
|
||||
|
307
bankdecay/commands/locales/fr-FR.po
Normal file
307
bankdecay/commands/locales/fr-FR.po
Normal file
|
@ -0,0 +1,307 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-01-04 12:10-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:56\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: French\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: fr\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/commands/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 108\n"
|
||||
"Language: fr_FR\n"
|
||||
|
||||
#: commands\admin.py:23
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Setup economy credit decay for your server\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:31
|
||||
#, docstring
|
||||
msgid "View Bank Decay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:48
|
||||
msgid "Not Set"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:53
|
||||
msgid "`Decay Enabled: `{}\n"
|
||||
"`Inactive Days: `{}\n"
|
||||
"`Percent Decay: `{}\n"
|
||||
"`Saved Users: `{}\n"
|
||||
"`Active Users: `{}\n"
|
||||
"`Expired Users: `{}\n"
|
||||
"`Stale Users: `{}\n"
|
||||
"`Total Decayed: `{}\n"
|
||||
"`Log Channel: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:75
|
||||
msgid "`Next Runtime: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:78
|
||||
msgid "**Ignored Roles**\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:80
|
||||
msgid "BankDecay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:88
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Toggle the bank decay feature on or off.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:92 commands\admin.py:144 commands\admin.py:186
|
||||
#: commands\admin.py:213 commands\admin.py:249 commands\admin.py:318
|
||||
#: commands\admin.py:350
|
||||
msgid "This command is not available when using global bank."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "Bank decay has been {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:101
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of inactive days before decay starts.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:105
|
||||
msgid "Inactive days cannot be negative."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:109
|
||||
msgid "Inactive days set to {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:114
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the percentage of decay that occurs after the inactive period.\n\n"
|
||||
" **Example**\n"
|
||||
" If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:121
|
||||
msgid "Percent decay must be between 0 and 1."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:125
|
||||
msgid "Percent decay set to {}%."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:130
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Reset the total amount decayed to zero.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:135
|
||||
msgid "Total decayed amount has been reset to 0."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:140
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Run a decay cycle on this server right now\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:148
|
||||
msgid "The decay system is currently disabled!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:155
|
||||
msgid "There were no users affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "accounts"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:158
|
||||
msgid "Are you sure you want to decay {} for a total of {}?"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:166
|
||||
msgid "Decay cycle cancelled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:168 commands\admin.py:171
|
||||
msgid "Decaying user accounts, one moment..."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:176
|
||||
msgid "User accounts have been decayed!\n"
|
||||
"- Users Affected: {}\n"
|
||||
"- Total {} Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:184
|
||||
#, docstring
|
||||
msgid "Get a list of users who are currently expired and how much they will lose if decayed"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:191
|
||||
msgid "There were no users that would be affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:195
|
||||
msgid "This would decay {} for a total of {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:209
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove users from the config that are no longer in the server or have no balance\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:217
|
||||
msgid "Not removing users from the config"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:232
|
||||
msgid "No users were removed from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:236
|
||||
msgid "Removed {} from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:242
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Initialize the server and add every member to the config.\n\n"
|
||||
" **Arguments**\n"
|
||||
" - as_expired: (t/f) if True, initialize users as already expired\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "member"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "members"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:266
|
||||
msgid "Server initialized! {} added to the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:271
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Check when a user was last active (if at all)\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:277
|
||||
msgid "This user is not in the config yet!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:280
|
||||
msgid "User was last seen {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:285
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove a role from the ignore list\n\n"
|
||||
" Users with an ignored role will not have their balance decay\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:293
|
||||
msgid "Role removed from the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:296
|
||||
msgid "Role added to the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:302
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the log channel, each time the decay cycle runs this will be updated\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:307
|
||||
msgid "Log channel has been set!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:312
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add a percentage to all member balances.\n\n"
|
||||
" Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:322
|
||||
msgid "Not adding credits to users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:326 commands\admin.py:358
|
||||
msgid "Percent must be greater than 1!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:340
|
||||
msgid "Credits added: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:344
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove a percentage from all member balances.\n\n"
|
||||
" Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:354
|
||||
msgid "Not removing credits from users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:372
|
||||
msgid "Credits removed: {}"
|
||||
msgstr ""
|
||||
|
307
bankdecay/commands/locales/hr-HR.po
Normal file
307
bankdecay/commands/locales/hr-HR.po
Normal file
|
@ -0,0 +1,307 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-01-04 12:10-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Croatian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: hr\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/commands/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 108\n"
|
||||
"Language: hr_HR\n"
|
||||
|
||||
#: commands\admin.py:23
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Setup economy credit decay for your server\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:31
|
||||
#, docstring
|
||||
msgid "View Bank Decay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:48
|
||||
msgid "Not Set"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:53
|
||||
msgid "`Decay Enabled: `{}\n"
|
||||
"`Inactive Days: `{}\n"
|
||||
"`Percent Decay: `{}\n"
|
||||
"`Saved Users: `{}\n"
|
||||
"`Active Users: `{}\n"
|
||||
"`Expired Users: `{}\n"
|
||||
"`Stale Users: `{}\n"
|
||||
"`Total Decayed: `{}\n"
|
||||
"`Log Channel: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:75
|
||||
msgid "`Next Runtime: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:78
|
||||
msgid "**Ignored Roles**\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:80
|
||||
msgid "BankDecay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:88
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Toggle the bank decay feature on or off.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:92 commands\admin.py:144 commands\admin.py:186
|
||||
#: commands\admin.py:213 commands\admin.py:249 commands\admin.py:318
|
||||
#: commands\admin.py:350
|
||||
msgid "This command is not available when using global bank."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "Bank decay has been {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:101
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of inactive days before decay starts.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:105
|
||||
msgid "Inactive days cannot be negative."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:109
|
||||
msgid "Inactive days set to {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:114
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the percentage of decay that occurs after the inactive period.\n\n"
|
||||
" **Example**\n"
|
||||
" If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:121
|
||||
msgid "Percent decay must be between 0 and 1."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:125
|
||||
msgid "Percent decay set to {}%."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:130
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Reset the total amount decayed to zero.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:135
|
||||
msgid "Total decayed amount has been reset to 0."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:140
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Run a decay cycle on this server right now\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:148
|
||||
msgid "The decay system is currently disabled!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:155
|
||||
msgid "There were no users affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "accounts"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:158
|
||||
msgid "Are you sure you want to decay {} for a total of {}?"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:166
|
||||
msgid "Decay cycle cancelled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:168 commands\admin.py:171
|
||||
msgid "Decaying user accounts, one moment..."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:176
|
||||
msgid "User accounts have been decayed!\n"
|
||||
"- Users Affected: {}\n"
|
||||
"- Total {} Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:184
|
||||
#, docstring
|
||||
msgid "Get a list of users who are currently expired and how much they will lose if decayed"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:191
|
||||
msgid "There were no users that would be affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:195
|
||||
msgid "This would decay {} for a total of {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:209
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove users from the config that are no longer in the server or have no balance\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:217
|
||||
msgid "Not removing users from the config"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:232
|
||||
msgid "No users were removed from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:236
|
||||
msgid "Removed {} from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:242
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Initialize the server and add every member to the config.\n\n"
|
||||
" **Arguments**\n"
|
||||
" - as_expired: (t/f) if True, initialize users as already expired\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "member"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "members"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:266
|
||||
msgid "Server initialized! {} added to the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:271
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Check when a user was last active (if at all)\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:277
|
||||
msgid "This user is not in the config yet!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:280
|
||||
msgid "User was last seen {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:285
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove a role from the ignore list\n\n"
|
||||
" Users with an ignored role will not have their balance decay\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:293
|
||||
msgid "Role removed from the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:296
|
||||
msgid "Role added to the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:302
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the log channel, each time the decay cycle runs this will be updated\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:307
|
||||
msgid "Log channel has been set!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:312
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add a percentage to all member balances.\n\n"
|
||||
" Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:322
|
||||
msgid "Not adding credits to users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:326 commands\admin.py:358
|
||||
msgid "Percent must be greater than 1!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:340
|
||||
msgid "Credits added: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:344
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove a percentage from all member balances.\n\n"
|
||||
" Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:354
|
||||
msgid "Not removing credits from users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:372
|
||||
msgid "Credits removed: {}"
|
||||
msgstr ""
|
||||
|
307
bankdecay/commands/locales/ko-KR.po
Normal file
307
bankdecay/commands/locales/ko-KR.po
Normal file
|
@ -0,0 +1,307 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-01-04 12:10-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Korean\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: ko\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/commands/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 108\n"
|
||||
"Language: ko_KR\n"
|
||||
|
||||
#: commands\admin.py:23
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Setup economy credit decay for your server\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:31
|
||||
#, docstring
|
||||
msgid "View Bank Decay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:48
|
||||
msgid "Not Set"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:53
|
||||
msgid "`Decay Enabled: `{}\n"
|
||||
"`Inactive Days: `{}\n"
|
||||
"`Percent Decay: `{}\n"
|
||||
"`Saved Users: `{}\n"
|
||||
"`Active Users: `{}\n"
|
||||
"`Expired Users: `{}\n"
|
||||
"`Stale Users: `{}\n"
|
||||
"`Total Decayed: `{}\n"
|
||||
"`Log Channel: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:75
|
||||
msgid "`Next Runtime: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:78
|
||||
msgid "**Ignored Roles**\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:80
|
||||
msgid "BankDecay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:88
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Toggle the bank decay feature on or off.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:92 commands\admin.py:144 commands\admin.py:186
|
||||
#: commands\admin.py:213 commands\admin.py:249 commands\admin.py:318
|
||||
#: commands\admin.py:350
|
||||
msgid "This command is not available when using global bank."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "Bank decay has been {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:101
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of inactive days before decay starts.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:105
|
||||
msgid "Inactive days cannot be negative."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:109
|
||||
msgid "Inactive days set to {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:114
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the percentage of decay that occurs after the inactive period.\n\n"
|
||||
" **Example**\n"
|
||||
" If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:121
|
||||
msgid "Percent decay must be between 0 and 1."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:125
|
||||
msgid "Percent decay set to {}%."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:130
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Reset the total amount decayed to zero.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:135
|
||||
msgid "Total decayed amount has been reset to 0."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:140
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Run a decay cycle on this server right now\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:148
|
||||
msgid "The decay system is currently disabled!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:155
|
||||
msgid "There were no users affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "accounts"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:158
|
||||
msgid "Are you sure you want to decay {} for a total of {}?"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:166
|
||||
msgid "Decay cycle cancelled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:168 commands\admin.py:171
|
||||
msgid "Decaying user accounts, one moment..."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:176
|
||||
msgid "User accounts have been decayed!\n"
|
||||
"- Users Affected: {}\n"
|
||||
"- Total {} Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:184
|
||||
#, docstring
|
||||
msgid "Get a list of users who are currently expired and how much they will lose if decayed"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:191
|
||||
msgid "There were no users that would be affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:195
|
||||
msgid "This would decay {} for a total of {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:209
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove users from the config that are no longer in the server or have no balance\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:217
|
||||
msgid "Not removing users from the config"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:232
|
||||
msgid "No users were removed from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:236
|
||||
msgid "Removed {} from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:242
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Initialize the server and add every member to the config.\n\n"
|
||||
" **Arguments**\n"
|
||||
" - as_expired: (t/f) if True, initialize users as already expired\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "member"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "members"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:266
|
||||
msgid "Server initialized! {} added to the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:271
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Check when a user was last active (if at all)\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:277
|
||||
msgid "This user is not in the config yet!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:280
|
||||
msgid "User was last seen {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:285
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove a role from the ignore list\n\n"
|
||||
" Users with an ignored role will not have their balance decay\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:293
|
||||
msgid "Role removed from the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:296
|
||||
msgid "Role added to the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:302
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the log channel, each time the decay cycle runs this will be updated\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:307
|
||||
msgid "Log channel has been set!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:312
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add a percentage to all member balances.\n\n"
|
||||
" Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:322
|
||||
msgid "Not adding credits to users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:326 commands\admin.py:358
|
||||
msgid "Percent must be greater than 1!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:340
|
||||
msgid "Credits added: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:344
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove a percentage from all member balances.\n\n"
|
||||
" Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:354
|
||||
msgid "Not removing credits from users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:372
|
||||
msgid "Credits removed: {}"
|
||||
msgstr ""
|
||||
|
322
bankdecay/commands/locales/messages.pot
Normal file
322
bankdecay/commands/locales/messages.pot
Normal file
|
@ -0,0 +1,322 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"POT-Creation-Date: 2024-02-08 18:30-0500\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
|
||||
#: commands\admin.py:23
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Setup economy credit decay for your server\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:31
|
||||
#, docstring
|
||||
msgid "View Bank Decay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:48
|
||||
msgid "Not Set"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:53
|
||||
msgid ""
|
||||
"`Decay Enabled: `{}\n"
|
||||
"`Inactive Days: `{}\n"
|
||||
"`Percent Decay: `{}\n"
|
||||
"`Saved Users: `{}\n"
|
||||
"`Active Users: `{}\n"
|
||||
"`Expired Users: `{}\n"
|
||||
"`Stale Users: `{}\n"
|
||||
"`Total Decayed: `{}\n"
|
||||
"`Log Channel: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:75
|
||||
msgid "`Next Runtime: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:78
|
||||
msgid "**Ignored Roles**\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:80
|
||||
msgid "BankDecay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:88
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Toggle the bank decay feature on or off.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:92 commands\admin.py:144 commands\admin.py:186
|
||||
#: commands\admin.py:213 commands\admin.py:249 commands\admin.py:318
|
||||
#: commands\admin.py:350
|
||||
msgid "This command is not available when using global bank."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "Bank decay has been {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:101
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Set the number of inactive days before decay starts.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:105
|
||||
msgid "Inactive days cannot be negative."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:109
|
||||
msgid "Inactive days set to {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:114
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Set the percentage of decay that occurs after the inactive period.\n"
|
||||
"\n"
|
||||
" **Example**\n"
|
||||
" If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:121
|
||||
msgid "Percent decay must be between 0 and 1."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:125
|
||||
msgid "Percent decay set to {}%."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:130
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Reset the total amount decayed to zero.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:135
|
||||
msgid "Total decayed amount has been reset to 0."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:140
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Run a decay cycle on this server right now\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:148
|
||||
msgid "The decay system is currently disabled!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:155
|
||||
msgid "There were no users affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "accounts"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:158
|
||||
msgid "Are you sure you want to decay {} for a total of {}?"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:166
|
||||
msgid "Decay cycle cancelled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:168 commands\admin.py:171
|
||||
msgid "Decaying user accounts, one moment..."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:176
|
||||
msgid ""
|
||||
"User accounts have been decayed!\n"
|
||||
"- Users Affected: {}\n"
|
||||
"- Total {} Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:184
|
||||
#, docstring
|
||||
msgid ""
|
||||
"Get a list of users who are currently expired and how much they will lose if"
|
||||
" decayed"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:191
|
||||
msgid "There were no users that would be affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:195
|
||||
msgid "This would decay {} for a total of {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:209
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Remove users from the config that are no longer in the server or have no balance\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:217
|
||||
msgid "Not removing users from the config"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:232
|
||||
msgid "No users were removed from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:236
|
||||
msgid "Removed {} from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:242
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Initialize the server and add every member to the config.\n"
|
||||
"\n"
|
||||
" **Arguments**\n"
|
||||
" - as_expired: (t/f) if True, initialize users as already expired\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "member"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "members"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:266
|
||||
msgid "Server initialized! {} added to the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:271
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Check when a user was last active (if at all)\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:277
|
||||
msgid "This user is not in the config yet!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:280
|
||||
msgid "User was last seen {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:285
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Add/Remove a role from the ignore list\n"
|
||||
"\n"
|
||||
" Users with an ignored role will not have their balance decay\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:293
|
||||
msgid "Role removed from the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:296
|
||||
msgid "Role added to the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:302
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Set the log channel, each time the decay cycle runs this will be updated\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:307
|
||||
msgid "Log channel has been set!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:312
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Add a percentage to all member balances.\n"
|
||||
"\n"
|
||||
" Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:322
|
||||
msgid "Not adding credits to users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:326 commands\admin.py:358
|
||||
msgid "Percent must be greater than 1!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:340
|
||||
msgid "Credits added: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:344
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Remove a percentage from all member balances.\n"
|
||||
"\n"
|
||||
" Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:354
|
||||
msgid "Not removing credits from users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:372
|
||||
msgid "Credits removed: {}"
|
||||
msgstr ""
|
307
bankdecay/commands/locales/pt-PT.po
Normal file
307
bankdecay/commands/locales/pt-PT.po
Normal file
|
@ -0,0 +1,307 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-01-04 12:10-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: pt-PT\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/commands/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 108\n"
|
||||
"Language: pt_PT\n"
|
||||
|
||||
#: commands\admin.py:23
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Setup economy credit decay for your server\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:31
|
||||
#, docstring
|
||||
msgid "View Bank Decay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:48
|
||||
msgid "Not Set"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:53
|
||||
msgid "`Decay Enabled: `{}\n"
|
||||
"`Inactive Days: `{}\n"
|
||||
"`Percent Decay: `{}\n"
|
||||
"`Saved Users: `{}\n"
|
||||
"`Active Users: `{}\n"
|
||||
"`Expired Users: `{}\n"
|
||||
"`Stale Users: `{}\n"
|
||||
"`Total Decayed: `{}\n"
|
||||
"`Log Channel: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:75
|
||||
msgid "`Next Runtime: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:78
|
||||
msgid "**Ignored Roles**\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:80
|
||||
msgid "BankDecay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:88
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Toggle the bank decay feature on or off.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:92 commands\admin.py:144 commands\admin.py:186
|
||||
#: commands\admin.py:213 commands\admin.py:249 commands\admin.py:318
|
||||
#: commands\admin.py:350
|
||||
msgid "This command is not available when using global bank."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "Bank decay has been {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:101
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of inactive days before decay starts.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:105
|
||||
msgid "Inactive days cannot be negative."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:109
|
||||
msgid "Inactive days set to {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:114
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the percentage of decay that occurs after the inactive period.\n\n"
|
||||
" **Example**\n"
|
||||
" If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:121
|
||||
msgid "Percent decay must be between 0 and 1."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:125
|
||||
msgid "Percent decay set to {}%."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:130
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Reset the total amount decayed to zero.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:135
|
||||
msgid "Total decayed amount has been reset to 0."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:140
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Run a decay cycle on this server right now\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:148
|
||||
msgid "The decay system is currently disabled!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:155
|
||||
msgid "There were no users affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "accounts"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:158
|
||||
msgid "Are you sure you want to decay {} for a total of {}?"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:166
|
||||
msgid "Decay cycle cancelled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:168 commands\admin.py:171
|
||||
msgid "Decaying user accounts, one moment..."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:176
|
||||
msgid "User accounts have been decayed!\n"
|
||||
"- Users Affected: {}\n"
|
||||
"- Total {} Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:184
|
||||
#, docstring
|
||||
msgid "Get a list of users who are currently expired and how much they will lose if decayed"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:191
|
||||
msgid "There were no users that would be affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:195
|
||||
msgid "This would decay {} for a total of {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:209
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove users from the config that are no longer in the server or have no balance\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:217
|
||||
msgid "Not removing users from the config"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:232
|
||||
msgid "No users were removed from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:236
|
||||
msgid "Removed {} from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:242
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Initialize the server and add every member to the config.\n\n"
|
||||
" **Arguments**\n"
|
||||
" - as_expired: (t/f) if True, initialize users as already expired\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "member"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "members"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:266
|
||||
msgid "Server initialized! {} added to the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:271
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Check when a user was last active (if at all)\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:277
|
||||
msgid "This user is not in the config yet!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:280
|
||||
msgid "User was last seen {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:285
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove a role from the ignore list\n\n"
|
||||
" Users with an ignored role will not have their balance decay\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:293
|
||||
msgid "Role removed from the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:296
|
||||
msgid "Role added to the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:302
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the log channel, each time the decay cycle runs this will be updated\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:307
|
||||
msgid "Log channel has been set!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:312
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add a percentage to all member balances.\n\n"
|
||||
" Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:322
|
||||
msgid "Not adding credits to users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:326 commands\admin.py:358
|
||||
msgid "Percent must be greater than 1!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:340
|
||||
msgid "Credits added: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:344
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove a percentage from all member balances.\n\n"
|
||||
" Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:354
|
||||
msgid "Not removing credits from users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:372
|
||||
msgid "Credits removed: {}"
|
||||
msgstr ""
|
||||
|
307
bankdecay/commands/locales/ru-RU.po
Normal file
307
bankdecay/commands/locales/ru-RU.po
Normal file
|
@ -0,0 +1,307 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-01-04 12:10-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Russian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: ru\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/commands/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 108\n"
|
||||
"Language: ru_RU\n"
|
||||
|
||||
#: commands\admin.py:23
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Setup economy credit decay for your server\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:31
|
||||
#, docstring
|
||||
msgid "View Bank Decay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:48
|
||||
msgid "Not Set"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:53
|
||||
msgid "`Decay Enabled: `{}\n"
|
||||
"`Inactive Days: `{}\n"
|
||||
"`Percent Decay: `{}\n"
|
||||
"`Saved Users: `{}\n"
|
||||
"`Active Users: `{}\n"
|
||||
"`Expired Users: `{}\n"
|
||||
"`Stale Users: `{}\n"
|
||||
"`Total Decayed: `{}\n"
|
||||
"`Log Channel: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:75
|
||||
msgid "`Next Runtime: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:78
|
||||
msgid "**Ignored Roles**\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:80
|
||||
msgid "BankDecay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:88
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Toggle the bank decay feature on or off.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:92 commands\admin.py:144 commands\admin.py:186
|
||||
#: commands\admin.py:213 commands\admin.py:249 commands\admin.py:318
|
||||
#: commands\admin.py:350
|
||||
msgid "This command is not available when using global bank."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "Bank decay has been {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:101
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of inactive days before decay starts.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:105
|
||||
msgid "Inactive days cannot be negative."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:109
|
||||
msgid "Inactive days set to {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:114
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the percentage of decay that occurs after the inactive period.\n\n"
|
||||
" **Example**\n"
|
||||
" If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:121
|
||||
msgid "Percent decay must be between 0 and 1."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:125
|
||||
msgid "Percent decay set to {}%."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:130
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Reset the total amount decayed to zero.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:135
|
||||
msgid "Total decayed amount has been reset to 0."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:140
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Run a decay cycle on this server right now\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:148
|
||||
msgid "The decay system is currently disabled!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:155
|
||||
msgid "There were no users affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "accounts"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:158
|
||||
msgid "Are you sure you want to decay {} for a total of {}?"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:166
|
||||
msgid "Decay cycle cancelled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:168 commands\admin.py:171
|
||||
msgid "Decaying user accounts, one moment..."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:176
|
||||
msgid "User accounts have been decayed!\n"
|
||||
"- Users Affected: {}\n"
|
||||
"- Total {} Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:184
|
||||
#, docstring
|
||||
msgid "Get a list of users who are currently expired and how much they will lose if decayed"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:191
|
||||
msgid "There were no users that would be affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:195
|
||||
msgid "This would decay {} for a total of {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:209
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove users from the config that are no longer in the server or have no balance\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:217
|
||||
msgid "Not removing users from the config"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:232
|
||||
msgid "No users were removed from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:236
|
||||
msgid "Removed {} from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:242
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Initialize the server and add every member to the config.\n\n"
|
||||
" **Arguments**\n"
|
||||
" - as_expired: (t/f) if True, initialize users as already expired\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "member"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "members"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:266
|
||||
msgid "Server initialized! {} added to the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:271
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Check when a user was last active (if at all)\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:277
|
||||
msgid "This user is not in the config yet!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:280
|
||||
msgid "User was last seen {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:285
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove a role from the ignore list\n\n"
|
||||
" Users with an ignored role will not have their balance decay\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:293
|
||||
msgid "Role removed from the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:296
|
||||
msgid "Role added to the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:302
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the log channel, each time the decay cycle runs this will be updated\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:307
|
||||
msgid "Log channel has been set!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:312
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add a percentage to all member balances.\n\n"
|
||||
" Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:322
|
||||
msgid "Not adding credits to users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:326 commands\admin.py:358
|
||||
msgid "Percent must be greater than 1!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:340
|
||||
msgid "Credits added: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:344
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove a percentage from all member balances.\n\n"
|
||||
" Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:354
|
||||
msgid "Not removing credits from users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:372
|
||||
msgid "Credits removed: {}"
|
||||
msgstr ""
|
||||
|
307
bankdecay/commands/locales/tr-TR.po
Normal file
307
bankdecay/commands/locales/tr-TR.po
Normal file
|
@ -0,0 +1,307 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-01-04 12:10-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Turkish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: tr\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/commands/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 108\n"
|
||||
"Language: tr_TR\n"
|
||||
|
||||
#: commands\admin.py:23
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Setup economy credit decay for your server\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:31
|
||||
#, docstring
|
||||
msgid "View Bank Decay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:48
|
||||
msgid "Not Set"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:53
|
||||
msgid "`Decay Enabled: `{}\n"
|
||||
"`Inactive Days: `{}\n"
|
||||
"`Percent Decay: `{}\n"
|
||||
"`Saved Users: `{}\n"
|
||||
"`Active Users: `{}\n"
|
||||
"`Expired Users: `{}\n"
|
||||
"`Stale Users: `{}\n"
|
||||
"`Total Decayed: `{}\n"
|
||||
"`Log Channel: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:75
|
||||
msgid "`Next Runtime: `{}\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:78
|
||||
msgid "**Ignored Roles**\n"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:80
|
||||
msgid "BankDecay Settings"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:88
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Toggle the bank decay feature on or off.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:92 commands\admin.py:144 commands\admin.py:186
|
||||
#: commands\admin.py:213 commands\admin.py:249 commands\admin.py:318
|
||||
#: commands\admin.py:350
|
||||
msgid "This command is not available when using global bank."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "Bank decay has been {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:96
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:101
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of inactive days before decay starts.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:105
|
||||
msgid "Inactive days cannot be negative."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:109
|
||||
msgid "Inactive days set to {}."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:114
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the percentage of decay that occurs after the inactive period.\n\n"
|
||||
" **Example**\n"
|
||||
" If decay is 5%, then after the set days of inactivity they will lose 5% of their balance every day.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:121
|
||||
msgid "Percent decay must be between 0 and 1."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:125
|
||||
msgid "Percent decay set to {}%."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:130
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Reset the total amount decayed to zero.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:135
|
||||
msgid "Total decayed amount has been reset to 0."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:140
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Run a decay cycle on this server right now\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:148
|
||||
msgid "The decay system is currently disabled!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:155
|
||||
msgid "There were no users affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:157 commands\admin.py:194
|
||||
msgid "accounts"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:158
|
||||
msgid "Are you sure you want to decay {} for a total of {}?"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:166
|
||||
msgid "Decay cycle cancelled"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:168 commands\admin.py:171
|
||||
msgid "Decaying user accounts, one moment..."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:176
|
||||
msgid "User accounts have been decayed!\n"
|
||||
"- Users Affected: {}\n"
|
||||
"- Total {} Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:184
|
||||
#, docstring
|
||||
msgid "Get a list of users who are currently expired and how much they will lose if decayed"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:191
|
||||
msgid "There were no users that would be affected by the decay cycle"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:195
|
||||
msgid "This would decay {} for a total of {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:209
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove users from the config that are no longer in the server or have no balance\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:217
|
||||
msgid "Not removing users from the config"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:232
|
||||
msgid "No users were removed from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:235
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:236
|
||||
msgid "Removed {} from the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:242
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Initialize the server and add every member to the config.\n\n"
|
||||
" **Arguments**\n"
|
||||
" - as_expired: (t/f) if True, initialize users as already expired\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "member"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:265
|
||||
msgid "members"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:266
|
||||
msgid "Server initialized! {} added to the config."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:271
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Check when a user was last active (if at all)\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:277
|
||||
msgid "This user is not in the config yet!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:280
|
||||
msgid "User was last seen {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:285
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove a role from the ignore list\n\n"
|
||||
" Users with an ignored role will not have their balance decay\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:293
|
||||
msgid "Role removed from the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:296
|
||||
msgid "Role added to the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:302
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the log channel, each time the decay cycle runs this will be updated\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:307
|
||||
msgid "Log channel has been set!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:312
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add a percentage to all member balances.\n\n"
|
||||
" Accidentally decayed too many credits? Bulk add to every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:322
|
||||
msgid "Not adding credits to users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:326 commands\admin.py:358
|
||||
msgid "Percent must be greater than 1!"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:340
|
||||
msgid "Credits added: {}"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:344
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Remove a percentage from all member balances.\n\n"
|
||||
" Accidentally refunded too many credits with bulkaddpercent? Bulk remove from every user's balance in the server based on a percentage of their current balance.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:354
|
||||
msgid "Not removing credits from users"
|
||||
msgstr ""
|
||||
|
||||
#: commands\admin.py:372
|
||||
msgid "Credits removed: {}"
|
||||
msgstr ""
|
||||
|
28
bankdecay/common/__init__.py
Normal file
28
bankdecay/common/__init__.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
import orjson
|
||||
from pydantic import VERSION, BaseModel
|
||||
|
||||
|
||||
class Base(BaseModel):
|
||||
def model_dump_json(self, *args, **kwargs):
|
||||
if VERSION >= "2.0.1":
|
||||
return super().model_dump_json(*args, **kwargs)
|
||||
return super().json(*args, **kwargs)
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
if VERSION >= "2.0.1":
|
||||
return super().model_dump(*args, **kwargs)
|
||||
if kwargs.pop("mode", "") == "json":
|
||||
return orjson.loads(super().json(*args, **kwargs))
|
||||
return super().dict(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def model_validate_json(cls, obj, *args, **kwargs):
|
||||
if VERSION >= "2.0.1":
|
||||
return super().model_validate_json(obj, *args, **kwargs)
|
||||
return super().parse_raw(obj, *args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def model_validate(cls, obj, *args, **kwargs):
|
||||
if VERSION >= "2.0.1":
|
||||
return super().model_validate(obj, *args, **kwargs)
|
||||
return super().parse_obj(obj, *args, **kwargs)
|
42
bankdecay/common/confirm_view.py
Normal file
42
bankdecay/common/confirm_view.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
from contextlib import suppress
|
||||
|
||||
import discord
|
||||
from redbot.core.i18n import Translator
|
||||
|
||||
_ = Translator("BankDecay", __file__)
|
||||
|
||||
|
||||
class ConfirmView(discord.ui.View):
|
||||
def __init__(self, author: discord.Member):
|
||||
super().__init__(timeout=60)
|
||||
self.author = author
|
||||
self.yes.label = _("Yes")
|
||||
self.no.label = _("No")
|
||||
|
||||
self.value = None
|
||||
|
||||
async def interaction_check(self, interaction: discord.Interaction) -> bool:
|
||||
if interaction.user.id != self.author.id:
|
||||
await interaction.response.send_message(_("This isn't your menu!"), ephemeral=True)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
async def on_timeout(self) -> None:
|
||||
self.stop()
|
||||
|
||||
@discord.ui.button(style=discord.ButtonStyle.primary)
|
||||
async def yes(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
with suppress(discord.NotFound):
|
||||
await interaction.response.defer()
|
||||
|
||||
self.value = True
|
||||
self.stop()
|
||||
|
||||
@discord.ui.button(style=discord.ButtonStyle.primary)
|
||||
async def no(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
with suppress(discord.NotFound):
|
||||
await interaction.response.defer()
|
||||
|
||||
self.value = False
|
||||
self.stop()
|
84
bankdecay/common/listeners.py
Normal file
84
bankdecay/common/listeners.py
Normal file
|
@ -0,0 +1,84 @@
|
|||
import discord
|
||||
from redbot.core import commands
|
||||
|
||||
from ..abc import MixinMeta
|
||||
|
||||
|
||||
class Listeners(MixinMeta):
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message: discord.Message) -> None:
|
||||
if not message.guild:
|
||||
return
|
||||
if not message.author:
|
||||
return
|
||||
if message.author.bot:
|
||||
return
|
||||
self.db.refresh_user(message.author)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message_edit(self, before: discord.Message, after: discord.Message) -> None:
|
||||
guild = before.guild or after.guild
|
||||
if not guild:
|
||||
return
|
||||
author = before.author or after.author
|
||||
if not author:
|
||||
return
|
||||
if author.bot:
|
||||
return
|
||||
self.db.refresh_user(author)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent) -> None:
|
||||
if not payload.guild_id:
|
||||
return
|
||||
guild = self.bot.get_guild(payload.guild_id)
|
||||
if not guild:
|
||||
return
|
||||
if not payload.member:
|
||||
return
|
||||
if payload.member.bot:
|
||||
return
|
||||
self.db.refresh_user(payload.member)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_raw_reaction_remove(self, payload: discord.RawReactionActionEvent) -> None:
|
||||
if not payload.guild_id:
|
||||
return
|
||||
guild = self.bot.get_guild(payload.guild_id)
|
||||
if not guild:
|
||||
return
|
||||
if not payload.member:
|
||||
return
|
||||
if payload.member.bot:
|
||||
return
|
||||
self.db.refresh_user(payload.member)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_presence_update(self, before: discord.Member, after: discord.Member) -> None:
|
||||
guild = before.guild or after.guild
|
||||
if not guild:
|
||||
return
|
||||
author = before or after
|
||||
if author.bot:
|
||||
return
|
||||
self.db.refresh_user(author)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_member_update(self, before: discord.Member, after: discord.Member) -> None:
|
||||
guild = before.guild or after.guild
|
||||
if not guild:
|
||||
return
|
||||
author = before or after
|
||||
if author.bot:
|
||||
return
|
||||
self.db.refresh_user(author)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_voice_state_update(
|
||||
self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState
|
||||
) -> None:
|
||||
if not member.guild:
|
||||
return
|
||||
if member.bot:
|
||||
return
|
||||
self.db.refresh_user(member)
|
47
bankdecay/common/models.py
Normal file
47
bankdecay/common/models.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
from datetime import datetime
|
||||
|
||||
import discord
|
||||
from pydantic import Field
|
||||
|
||||
from . import Base
|
||||
|
||||
|
||||
class User(Base):
|
||||
last_active: datetime = Field(default_factory=lambda: datetime.now())
|
||||
|
||||
@property
|
||||
def seen_r(self) -> str:
|
||||
return f"<t:{int(self.last_active.timestamp())}:R>"
|
||||
|
||||
@property
|
||||
def seen_f(self) -> str:
|
||||
return f"<t:{int(self.last_active.timestamp())}:F>"
|
||||
|
||||
|
||||
class GuildSettings(Base):
|
||||
enabled: bool = False
|
||||
inactive_days: int = 30
|
||||
percent_decay: float = 0.05 # 5%
|
||||
users: dict[int, User] = {}
|
||||
total_decayed: int = 0
|
||||
ignored_roles: list[int] = []
|
||||
log_channel: int = 0
|
||||
|
||||
def get_user(self, user: discord.Member | discord.User | int) -> User:
|
||||
uid = user if isinstance(user, int) else user.id
|
||||
return self.users.setdefault(uid, User())
|
||||
|
||||
|
||||
class DB(Base):
|
||||
configs: dict[int, GuildSettings] = {}
|
||||
last_run: datetime = None
|
||||
|
||||
def get_conf(self, guild: discord.Guild | int) -> GuildSettings:
|
||||
gid = guild if isinstance(guild, int) else guild.id
|
||||
return self.configs.setdefault(gid, GuildSettings())
|
||||
|
||||
def refresh_user(self, user: discord.Member | discord.User) -> None:
|
||||
if isinstance(user, discord.User):
|
||||
return
|
||||
conf = self.get_conf(user.guild)
|
||||
conf.get_user(user).last_active = datetime.now()
|
10
bankdecay/common/scheduler.py
Normal file
10
bankdecay/common/scheduler.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
import os
|
||||
|
||||
import pytz
|
||||
from apscheduler.jobstores.memory import MemoryJobStore
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
|
||||
if "TZ" not in os.environ:
|
||||
os.environ["TZ"] = "UTC"
|
||||
scheduler = AsyncIOScheduler(jobstores={"default": MemoryJobStore()})
|
||||
scheduler.configure(timezone=pytz.timezone("UTC"))
|
16
bankdecay/info.json
Normal file
16
bankdecay/info.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"author": ["Vertyco"],
|
||||
"description": "Inactivity-based economy credit decay with customizable settings",
|
||||
"disabled": false,
|
||||
"end_user_data_statement": "This cog does not store any private data about users.",
|
||||
"hidden": false,
|
||||
"install_msg": "Thank you for installing! Type `[p]bankdecay` to view the commands.\n**NOTE**: THIS DOES NOT WORK WITH GLOBAL BANKS",
|
||||
"min_bot_version": "3.5.3",
|
||||
"min_python_version": [3, 10, 0],
|
||||
"permissions": [],
|
||||
"required_cogs": {},
|
||||
"requirements": ["pydantic", "pytz", "apscheduler"],
|
||||
"short": "Inactivity-based economy credit decay",
|
||||
"tags": [],
|
||||
"type": "COG"
|
||||
}
|
47
bankdecay/locales/de-DE.po
Normal file
47
bankdecay/locales/de-DE.po
Normal file
|
@ -0,0 +1,47 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-02-08 18:30-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: German\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: de\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 110\n"
|
||||
"Language: de_DE\n"
|
||||
|
||||
#: main.py:29
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Economy decay!\n\n"
|
||||
" Periodically reduces users' red currency based on inactivity, encouraging engagement.\n"
|
||||
" Server admins can configure decay parameters, view settings, and manually trigger decay cycles.\n"
|
||||
" User activity is tracked via messages and reactions.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: main.py:157
|
||||
msgid "Bank Decay Cycle"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:159
|
||||
msgid "- User Balances Decayed: {}\n"
|
||||
"- Total Amount Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:164
|
||||
msgid "No user balances were decayed during this cycle."
|
||||
msgstr ""
|
||||
|
||||
#: main.py:214
|
||||
#, docstring
|
||||
msgid "No data to delete"
|
||||
msgstr ""
|
||||
|
53
bankdecay/locales/es-ES.po
Normal file
53
bankdecay/locales/es-ES.po
Normal file
|
@ -0,0 +1,53 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-02-08 18:30-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Spanish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: es-ES\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 110\n"
|
||||
"Language: es_ES\n"
|
||||
|
||||
#: main.py:29
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Economy decay!\n\n"
|
||||
" Periodically reduces users' red currency based on inactivity, encouraging engagement.\n"
|
||||
" Server admins can configure decay parameters, view settings, and manually trigger decay cycles.\n"
|
||||
" User activity is tracked via messages and reactions.\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
" ¡Degradación de la economía!\n\n"
|
||||
" Reduce periódicamente la moneda roja de los usuarios basada en la inactividad, fomentando la participación.\n"
|
||||
" Los administradores del servidor pueden configurar parámetros de degradación, ver configuraciones y activar manualmente ciclos de degradación.\n"
|
||||
" La actividad de los usuarios se rastrea a través de mensajes y reacciones.\n"
|
||||
" "
|
||||
|
||||
#: main.py:157
|
||||
msgid "Bank Decay Cycle"
|
||||
msgstr "Ciclo de Degradación Bancaria"
|
||||
|
||||
#: main.py:159
|
||||
msgid "- User Balances Decayed: {}\n"
|
||||
"- Total Amount Decayed: {}"
|
||||
msgstr "- Saldos de Usuarios Degradados: {}\n"
|
||||
"- Cantidad Total Degradada: {}"
|
||||
|
||||
#: main.py:164
|
||||
msgid "No user balances were decayed during this cycle."
|
||||
msgstr "No se degradaron saldos de usuarios durante este ciclo."
|
||||
|
||||
#: main.py:214
|
||||
#, docstring
|
||||
msgid "No data to delete"
|
||||
msgstr "No hay datos que borrar"
|
||||
|
47
bankdecay/locales/fr-FR.po
Normal file
47
bankdecay/locales/fr-FR.po
Normal file
|
@ -0,0 +1,47 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-02-08 18:30-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: French\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: fr\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 110\n"
|
||||
"Language: fr_FR\n"
|
||||
|
||||
#: main.py:29
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Economy decay!\n\n"
|
||||
" Periodically reduces users' red currency based on inactivity, encouraging engagement.\n"
|
||||
" Server admins can configure decay parameters, view settings, and manually trigger decay cycles.\n"
|
||||
" User activity is tracked via messages and reactions.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: main.py:157
|
||||
msgid "Bank Decay Cycle"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:159
|
||||
msgid "- User Balances Decayed: {}\n"
|
||||
"- Total Amount Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:164
|
||||
msgid "No user balances were decayed during this cycle."
|
||||
msgstr ""
|
||||
|
||||
#: main.py:214
|
||||
#, docstring
|
||||
msgid "No data to delete"
|
||||
msgstr ""
|
||||
|
47
bankdecay/locales/hr-HR.po
Normal file
47
bankdecay/locales/hr-HR.po
Normal file
|
@ -0,0 +1,47 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-02-08 18:30-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Croatian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: hr\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 110\n"
|
||||
"Language: hr_HR\n"
|
||||
|
||||
#: main.py:29
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Economy decay!\n\n"
|
||||
" Periodically reduces users' red currency based on inactivity, encouraging engagement.\n"
|
||||
" Server admins can configure decay parameters, view settings, and manually trigger decay cycles.\n"
|
||||
" User activity is tracked via messages and reactions.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: main.py:157
|
||||
msgid "Bank Decay Cycle"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:159
|
||||
msgid "- User Balances Decayed: {}\n"
|
||||
"- Total Amount Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:164
|
||||
msgid "No user balances were decayed during this cycle."
|
||||
msgstr ""
|
||||
|
||||
#: main.py:214
|
||||
#, docstring
|
||||
msgid "No data to delete"
|
||||
msgstr ""
|
||||
|
47
bankdecay/locales/ko-KR.po
Normal file
47
bankdecay/locales/ko-KR.po
Normal file
|
@ -0,0 +1,47 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-02-08 18:30-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Korean\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: ko\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 110\n"
|
||||
"Language: ko_KR\n"
|
||||
|
||||
#: main.py:29
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Economy decay!\n\n"
|
||||
" Periodically reduces users' red currency based on inactivity, encouraging engagement.\n"
|
||||
" Server admins can configure decay parameters, view settings, and manually trigger decay cycles.\n"
|
||||
" User activity is tracked via messages and reactions.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: main.py:157
|
||||
msgid "Bank Decay Cycle"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:159
|
||||
msgid "- User Balances Decayed: {}\n"
|
||||
"- Total Amount Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:164
|
||||
msgid "No user balances were decayed during this cycle."
|
||||
msgstr ""
|
||||
|
||||
#: main.py:214
|
||||
#, docstring
|
||||
msgid "No data to delete"
|
||||
msgstr ""
|
||||
|
43
bankdecay/locales/messages.pot
Normal file
43
bankdecay/locales/messages.pot
Normal file
|
@ -0,0 +1,43 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"POT-Creation-Date: 2024-02-08 18:30-0500\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
|
||||
#: main.py:29
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Economy decay!\n"
|
||||
"\n"
|
||||
" Periodically reduces users' red currency based on inactivity, encouraging engagement.\n"
|
||||
" Server admins can configure decay parameters, view settings, and manually trigger decay cycles.\n"
|
||||
" User activity is tracked via messages and reactions.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: main.py:157
|
||||
msgid "Bank Decay Cycle"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:159
|
||||
msgid ""
|
||||
"- User Balances Decayed: {}\n"
|
||||
"- Total Amount Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:164
|
||||
msgid "No user balances were decayed during this cycle."
|
||||
msgstr ""
|
||||
|
||||
#: main.py:214
|
||||
#, docstring
|
||||
msgid "No data to delete"
|
||||
msgstr ""
|
47
bankdecay/locales/pt-PT.po
Normal file
47
bankdecay/locales/pt-PT.po
Normal file
|
@ -0,0 +1,47 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-02-08 18:30-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: pt-PT\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 110\n"
|
||||
"Language: pt_PT\n"
|
||||
|
||||
#: main.py:29
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Economy decay!\n\n"
|
||||
" Periodically reduces users' red currency based on inactivity, encouraging engagement.\n"
|
||||
" Server admins can configure decay parameters, view settings, and manually trigger decay cycles.\n"
|
||||
" User activity is tracked via messages and reactions.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: main.py:157
|
||||
msgid "Bank Decay Cycle"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:159
|
||||
msgid "- User Balances Decayed: {}\n"
|
||||
"- Total Amount Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:164
|
||||
msgid "No user balances were decayed during this cycle."
|
||||
msgstr ""
|
||||
|
||||
#: main.py:214
|
||||
#, docstring
|
||||
msgid "No data to delete"
|
||||
msgstr ""
|
||||
|
47
bankdecay/locales/ru-RU.po
Normal file
47
bankdecay/locales/ru-RU.po
Normal file
|
@ -0,0 +1,47 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-02-08 18:30-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Russian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: ru\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 110\n"
|
||||
"Language: ru_RU\n"
|
||||
|
||||
#: main.py:29
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Economy decay!\n\n"
|
||||
" Periodically reduces users' red currency based on inactivity, encouraging engagement.\n"
|
||||
" Server admins can configure decay parameters, view settings, and manually trigger decay cycles.\n"
|
||||
" User activity is tracked via messages and reactions.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: main.py:157
|
||||
msgid "Bank Decay Cycle"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:159
|
||||
msgid "- User Balances Decayed: {}\n"
|
||||
"- Total Amount Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:164
|
||||
msgid "No user balances were decayed during this cycle."
|
||||
msgstr ""
|
||||
|
||||
#: main.py:214
|
||||
#, docstring
|
||||
msgid "No data to delete"
|
||||
msgstr ""
|
||||
|
47
bankdecay/locales/tr-TR.po
Normal file
47
bankdecay/locales/tr-TR.po
Normal file
|
@ -0,0 +1,47 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vrt-cogs\n"
|
||||
"POT-Creation-Date: 2024-02-08 18:30-0500\n"
|
||||
"PO-Revision-Date: 2024-12-03 14:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Turkish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: vrt-cogs\n"
|
||||
"X-Crowdin-Project-ID: 550681\n"
|
||||
"X-Crowdin-Language: tr\n"
|
||||
"X-Crowdin-File: /[vertyco.vrt-cogs] main/bankdecay/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 110\n"
|
||||
"Language: tr_TR\n"
|
||||
|
||||
#: main.py:29
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Economy decay!\n\n"
|
||||
" Periodically reduces users' red currency based on inactivity, encouraging engagement.\n"
|
||||
" Server admins can configure decay parameters, view settings, and manually trigger decay cycles.\n"
|
||||
" User activity is tracked via messages and reactions.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: main.py:157
|
||||
msgid "Bank Decay Cycle"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:159
|
||||
msgid "- User Balances Decayed: {}\n"
|
||||
"- Total Amount Decayed: {}"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:164
|
||||
msgid "No user balances were decayed during this cycle."
|
||||
msgstr ""
|
||||
|
||||
#: main.py:214
|
||||
#, docstring
|
||||
msgid "No data to delete"
|
||||
msgstr ""
|
||||
|
214
bankdecay/main.py
Normal file
214
bankdecay/main.py
Normal file
|
@ -0,0 +1,214 @@
|
|||
import asyncio
|
||||
import logging
|
||||
import math
|
||||
import typing as t
|
||||
from datetime import datetime, timedelta
|
||||
from io import StringIO
|
||||
|
||||
import discord
|
||||
from redbot.core import Config, bank, commands
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import humanize_number, text_to_file
|
||||
|
||||
from .abc import CompositeMetaClass
|
||||
from .commands.admin import Admin
|
||||
from .common.listeners import Listeners
|
||||
from .common.models import DB
|
||||
from .common.scheduler import scheduler
|
||||
|
||||
log = logging.getLogger("red.vrt.bankdecay")
|
||||
RequestType = t.Literal["discord_deleted_user", "owner", "user", "user_strict"]
|
||||
|
||||
_ = Translator("BankDecay", __file__)
|
||||
# redgettext -D main.py commands/admin.py --command-docstring
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class BankDecay(Admin, Listeners, commands.Cog, metaclass=CompositeMetaClass):
|
||||
"""
|
||||
Economy decay!
|
||||
|
||||
Periodically reduces users' red currency based on inactivity, encouraging engagement.
|
||||
Server admins can configure decay parameters, view settings, and manually trigger decay cycles.
|
||||
User activity is tracked via messages and reactions.
|
||||
"""
|
||||
|
||||
__author__ = "[vertyco](https://github.com/vertyco/vrt-cogs)"
|
||||
__version__ = "0.3.12"
|
||||
|
||||
def __init__(self, bot: Red):
|
||||
super().__init__()
|
||||
self.bot = bot
|
||||
self.config = Config.get_conf(self, 117, force_registration=True)
|
||||
self.config.register_global(db={})
|
||||
|
||||
self.db: DB = DB()
|
||||
self.saving = False
|
||||
|
||||
async def cog_load(self) -> None:
|
||||
scheduler.start()
|
||||
scheduler.remove_all_jobs()
|
||||
asyncio.create_task(self.initialize())
|
||||
|
||||
async def cog_unload(self) -> None:
|
||||
scheduler.remove_all_jobs()
|
||||
scheduler.shutdown(wait=False)
|
||||
|
||||
async def initialize(self) -> None:
|
||||
await self.bot.wait_until_red_ready()
|
||||
data = await self.config.db()
|
||||
self.db = await asyncio.to_thread(DB.model_validate, data)
|
||||
log.info("Config loaded")
|
||||
await self.start_jobs()
|
||||
|
||||
async def start_jobs(self):
|
||||
kwargs = {
|
||||
"func": self.autodecay_guilds,
|
||||
"trigger": "cron",
|
||||
"minute": 0,
|
||||
"hour": 0,
|
||||
"id": "BankDecay.autodecay_guilds",
|
||||
"replace_existing": True,
|
||||
"misfire_grace_time": 3600, # 1 hour grace time for missed job
|
||||
}
|
||||
# If it has been more than 24 hours since the last run, schedule it to run now
|
||||
if self.db.last_run is not None and (datetime.now() - self.db.last_run) > timedelta(hours=24):
|
||||
kwargs["next_run_time"] = datetime.now() + timedelta(seconds=5)
|
||||
|
||||
# Schedule decay job
|
||||
scheduler.add_job(**kwargs)
|
||||
|
||||
async def autodecay_guilds(self):
|
||||
if await bank.is_global():
|
||||
log.error("This cog cannot be used with a global bank!")
|
||||
return
|
||||
|
||||
log.info("Running decay_guilds!")
|
||||
total_affected = 0
|
||||
total_decayed = 0
|
||||
for guild_id in self.db.configs.copy():
|
||||
guild = self.bot.get_guild(guild_id)
|
||||
if not guild:
|
||||
# Remove guids that the bot is no longer a part of
|
||||
del self.db.configs[guild_id]
|
||||
continue
|
||||
decayed = await self.decay_guild(guild)
|
||||
total_affected += len(decayed)
|
||||
total_decayed += sum(decayed.values())
|
||||
|
||||
if total_affected or total_decayed:
|
||||
log.info(f"Decayed {total_affected} users balances for a total of {total_decayed} credits!")
|
||||
self.db.last_run = datetime.now()
|
||||
await self.save()
|
||||
|
||||
async def decay_guild(self, guild: discord.Guild, check_only: bool = False) -> t.Dict[str, int]:
|
||||
now = datetime.now()
|
||||
conf = self.db.get_conf(guild)
|
||||
if not conf.enabled and not check_only:
|
||||
return {}
|
||||
|
||||
_bank_members = await bank._config.all_members(guild)
|
||||
bank_members: t.Dict[int, int] = {int(k): v["balance"] for k, v in _bank_members.items()}
|
||||
|
||||
# Decayed users: dict[username, amount]
|
||||
decayed: t.Dict[str, int] = {}
|
||||
uids = [i for i in conf.users]
|
||||
for user_id in uids:
|
||||
user = guild.get_member(user_id)
|
||||
if not user:
|
||||
# User no longer in guild
|
||||
continue
|
||||
|
||||
if any(r.id in conf.ignored_roles for r in user.roles):
|
||||
# Don't decay user balances with roles in the ignore list
|
||||
continue
|
||||
|
||||
last_active = conf.get_user(user).last_active
|
||||
|
||||
delta = now - last_active
|
||||
if delta.days <= conf.inactive_days:
|
||||
continue
|
||||
|
||||
bal = bank_members.get(user_id)
|
||||
# bal = await bank.get_balance(user)
|
||||
if not bal:
|
||||
continue
|
||||
|
||||
credits_to_remove = math.ceil(bal * conf.percent_decay)
|
||||
new_bal = bal - credits_to_remove
|
||||
if not check_only:
|
||||
await bank.set_balance(user, new_bal)
|
||||
|
||||
decayed[user.name] = credits_to_remove
|
||||
|
||||
if check_only:
|
||||
return decayed
|
||||
|
||||
conf.total_decayed += sum(decayed.values())
|
||||
log.info(f"Decayed guild {guild.name}.\nUsers decayed: {len(decayed)}\nTotal: {sum(decayed.values())}")
|
||||
|
||||
log_channel = guild.get_channel(conf.log_channel)
|
||||
if not log_channel:
|
||||
return decayed
|
||||
if not log_channel.permissions_for(guild.me).embed_links:
|
||||
return decayed
|
||||
|
||||
title = _("Bank Decay Cycle")
|
||||
if decayed:
|
||||
txt = _("- User Balances Decayed: {}\n- Total Amount Decayed: {}").format(
|
||||
f"`{humanize_number(len(decayed))}`", f"`{humanize_number(sum(decayed.values()))}`"
|
||||
)
|
||||
color = discord.Color.yellow()
|
||||
else:
|
||||
txt = _("No user balances were decayed during this cycle.")
|
||||
color = discord.Color.blue()
|
||||
|
||||
embed = discord.Embed(
|
||||
title=title,
|
||||
description=txt,
|
||||
color=color,
|
||||
timestamp=datetime.now(),
|
||||
)
|
||||
# Create a text file with the list of users and how much they will lose
|
||||
buffer = StringIO()
|
||||
for user, amount in sorted(decayed.items(), key=lambda x: x[1], reverse=True):
|
||||
buffer.write(f"{user}: {amount}\n")
|
||||
|
||||
file = text_to_file(buffer.getvalue(), filename="decay.txt")
|
||||
perms = [
|
||||
log_channel.permissions_for(guild.me).attach_files,
|
||||
log_channel.permissions_for(guild.me).embed_links,
|
||||
]
|
||||
if not any(perms):
|
||||
return decayed
|
||||
|
||||
try:
|
||||
if perms[0] and perms[1]:
|
||||
await log_channel.send(embed=embed, file=file)
|
||||
elif perms[1]:
|
||||
await log_channel.send(embed=embed)
|
||||
except Exception as e:
|
||||
log.error(f"Failed to send decay log to {log_channel.name} in {guild.name}", exc_info=e)
|
||||
|
||||
return decayed
|
||||
|
||||
async def save(self) -> None:
|
||||
if self.saving:
|
||||
return
|
||||
try:
|
||||
self.saving = True
|
||||
dump = self.db.model_dump(mode="json")
|
||||
await self.config.db.set(dump)
|
||||
except Exception as e:
|
||||
log.exception("Failed to save config", exc_info=e)
|
||||
finally:
|
||||
self.saving = False
|
||||
|
||||
def format_help_for_context(self, ctx: commands.Context):
|
||||
helpcmd = super().format_help_for_context(ctx)
|
||||
txt = "Version: {}\nAuthor: {}".format(self.__version__, self.__author__)
|
||||
return f"{helpcmd}\n\n{txt}"
|
||||
|
||||
async def red_delete_data_for_user(self, *, requester: RequestType, user_id: int):
|
||||
"""No data to delete"""
|
6
bankevents/README.md
Normal file
6
bankevents/README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
Dispatches listener events for Red bank transactions and payday claims.<br/>- red_bank_set_balance<br/>- red_bank_transfer_credits<br/>- red_bank_wipe<br/>- red_bank_prune<br/>- red_bank_set_global<br/>- red_economy_payday_claim<br/><br/>Shoutout to YamiKaitou for starting the work on this 2+ years ago with a PR.<br/>Maybe one day it will be merged into core.<br/>https://github.com/Cog-Creators/Red-DiscordBot/pull/5325
|
||||
|
||||
# [p]bankevents
|
||||
Get help using the BankEvents cog<br/>
|
||||
- Usage: `[p]bankevents`
|
||||
- Restricted to: `BOT_OWNER`
|
10
bankevents/__init__.py
Normal file
10
bankevents/__init__.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from redbot.core.bot import Red
|
||||
from redbot.core.utils import get_end_user_data_statement
|
||||
|
||||
from .main import BankEvents
|
||||
|
||||
__red_end_user_data_statement__ = get_end_user_data_statement(__file__)
|
||||
|
||||
|
||||
async def setup(bot: Red):
|
||||
await bot.add_cog(BankEvents(bot))
|
14
bankevents/abc.py
Normal file
14
bankevents/abc.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from abc import ABCMeta
|
||||
|
||||
from discord.ext.commands.cog import CogMeta
|
||||
from redbot.core.bot import Red
|
||||
|
||||
|
||||
class CompositeMetaClass(CogMeta, ABCMeta):
|
||||
"""Type detection"""
|
||||
|
||||
|
||||
class MixinMeta(metaclass=ABCMeta):
|
||||
"""Type hinting"""
|
||||
|
||||
bot: Red
|
67
bankevents/examples.txt
Normal file
67
bankevents/examples.txt
Normal file
|
@ -0,0 +1,67 @@
|
|||
@commands.Cog.listener()
|
||||
async def on_red_bank_set_balance(self, payload: BankSetBalanceInformation):
|
||||
"""Payload attributes:
|
||||
- recipient: Union[discord.Member, discord.User]
|
||||
- guild: Union[discord.Guild, None]
|
||||
- recipient_old_balance: int
|
||||
- recipient_new_balance: int
|
||||
"""
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_transfer_credits(self, payload: BankTransferInformation):
|
||||
"""Payload attributes:
|
||||
- sender: Union[discord.Member, discord.User]
|
||||
- recipient: Union[discord.Member, discord.User]
|
||||
- guild: Union[discord.Guild, None]
|
||||
- transfer_amount: int
|
||||
- sender_new_balance: int
|
||||
- recipient_new_balance: int
|
||||
"""
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_wipe(self, scope: Union[int, None]):
|
||||
"""scope: int (-1 for global, None for all members, guild_id for server bank)"""
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_prune(self, payload: BankPruneInformation):
|
||||
"""Payload attributes:
|
||||
- guild: Union[discord.Guild, None]
|
||||
- user_id: Union[int, None]
|
||||
- scope: int (1 for global, 2 for server, 3 for user)
|
||||
- pruned_users: list[int(user_id)] or dict[int(guild_id), list[int(user_id)]]
|
||||
"""
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_set_global(self, is_global: bool):
|
||||
"""is_global: True if global bank, False if server bank"""
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_withdraw_credits(self, payload: BankWithdrawDepositInformation):
|
||||
"""Payload attributes:
|
||||
- member: discord.Member
|
||||
- guild: Union[discord.Guild, None]
|
||||
- amount: int
|
||||
- old_balance: int
|
||||
- new_balance: int
|
||||
"""
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_deposit_credits(self, payload: BankWithdrawDepositInformation):
|
||||
"""Payload attributes:
|
||||
- member_id: int
|
||||
- guild_id: int (0 if global bank)
|
||||
- amount: int
|
||||
- old_balance: int
|
||||
- new_balance: int
|
||||
"""
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_economy_payday_claim(self, payload: PaydayClaimInformation):
|
||||
"""Payload attributes:
|
||||
- member: discord.Member
|
||||
- channel: Union[discord.TextChannel, discord.Thread, discord.ForumChannel]
|
||||
- message: discord.Message
|
||||
- amount: int
|
||||
- old_balance: int
|
||||
- new_balance: int
|
||||
"""
|
16
bankevents/info.json
Normal file
16
bankevents/info.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"author": ["Vertyco"],
|
||||
"description": "Dispatches events when different bank transactions occur, such as when a user deposits credits, withdraws credits, transfers credits, or runs payday.",
|
||||
"disabled": false,
|
||||
"end_user_data_statement": "This cog does not store end user data.",
|
||||
"hidden": false,
|
||||
"install_msg": "Thank you for installing!\n**WARNING:** This cog modifies Red's bank methods by wrapping them in a method that dispatches the event. If you are not okay with that, please uninstall this cog.",
|
||||
"min_bot_version": "3.5.0",
|
||||
"min_python_version": [3, 9, 0],
|
||||
"permissions": [],
|
||||
"required_cogs": {},
|
||||
"requirements": [],
|
||||
"short": "Bank transaction listener events for 3rd party cogs",
|
||||
"tags": ["bank", "events", "listeners", "economy", "developers", "economy"],
|
||||
"type": "COG"
|
||||
}
|
140
bankevents/main.py
Normal file
140
bankevents/main.py
Normal file
|
@ -0,0 +1,140 @@
|
|||
import asyncio
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
import discord
|
||||
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 box
|
||||
|
||||
from .abc import CompositeMetaClass
|
||||
from .overrides import bank as custombank
|
||||
from .overrides.bank import init
|
||||
from .overrides.economy import PaydayOverride
|
||||
|
||||
log = logging.getLogger("red.vrt.bankevents")
|
||||
_ = Translator("BankEvents", __file__)
|
||||
|
||||
|
||||
class BankEvents(PaydayOverride, commands.Cog, metaclass=CompositeMetaClass):
|
||||
"""
|
||||
Dispatches listener events for Red bank transactions and payday claims.
|
||||
- red_bank_set_balance
|
||||
- red_bank_transfer_credits
|
||||
- red_bank_wipe
|
||||
- red_bank_prune
|
||||
- red_bank_set_global
|
||||
- red_economy_payday_claim
|
||||
|
||||
Shoutout to YamiKaitou for starting the work on this 2+ years ago with a PR.
|
||||
Maybe one day it will be merged into core.
|
||||
https://github.com/Cog-Creators/Red-DiscordBot/pull/5325
|
||||
"""
|
||||
|
||||
__author__ = "[vertyco](https://github.com/vertyco/vrt-cogs)"
|
||||
__version__ = "2.2.2"
|
||||
|
||||
def __init__(self, bot: Red):
|
||||
super().__init__()
|
||||
self.bot: Red = bot
|
||||
init(self.bot)
|
||||
# Original methods
|
||||
self.set_balance_coro = None
|
||||
self.transfer_credits_coro = None
|
||||
self.wipe_bank_coro = None
|
||||
self.bank_prune_coro = None
|
||||
self.set_global_coro = None
|
||||
self.is_global_coro = None
|
||||
# Original commands
|
||||
self.payday_callback = None
|
||||
|
||||
def format_help_for_context(self, ctx: commands.Context) -> str:
|
||||
helpcmd = super().format_help_for_context(ctx)
|
||||
txt = "Version: {}\nAuthor: {}\nContributors: YamiKaitou".format(self.__version__, self.__author__)
|
||||
return f"{helpcmd}\n\n{txt}"
|
||||
|
||||
async def red_delete_data_for_user(self, *args, **kwargs):
|
||||
return
|
||||
|
||||
async def red_get_data_for_user(self, *args, **kwargs):
|
||||
return
|
||||
|
||||
async def cog_load(self) -> None:
|
||||
asyncio.create_task(self.initialize())
|
||||
|
||||
async def initialize(self) -> None:
|
||||
await self.bot.wait_until_red_ready()
|
||||
# Save original methods
|
||||
self.set_balance_coro = bank.set_balance
|
||||
self.transfer_credits_coro = bank.transfer_credits
|
||||
self.wipe_bank_coro = bank.wipe_bank
|
||||
self.bank_prune_coro = bank.bank_prune
|
||||
self.set_global_coro = bank.set_global
|
||||
self.is_global_coro = bank.is_global
|
||||
|
||||
# Wrap methods
|
||||
setattr(bank, "set_balance", custombank.set_balance)
|
||||
setattr(bank, "transfer_credits", custombank.transfer_credits)
|
||||
setattr(bank, "wipe_bank", custombank.wipe_bank)
|
||||
setattr(bank, "bank_prune", custombank.bank_prune)
|
||||
setattr(bank, "set_global", custombank.set_global)
|
||||
setattr(bank, "is_global", custombank.is_global)
|
||||
|
||||
payday: commands.Command = self.bot.get_command("payday")
|
||||
if payday:
|
||||
self.payday_callback = payday.callback
|
||||
payday.callback = self.payday_override.callback
|
||||
|
||||
log.info("Methods wrapped")
|
||||
|
||||
async def cog_unload(self) -> None:
|
||||
if self.set_balance_coro is not None:
|
||||
setattr(bank, "set_balance", self.set_balance_coro)
|
||||
if self.transfer_credits_coro is not None:
|
||||
setattr(bank, "transfer_credits", self.transfer_credits_coro)
|
||||
if self.wipe_bank_coro is not None:
|
||||
setattr(bank, "wipe_bank", self.wipe_bank_coro)
|
||||
if self.bank_prune_coro is not None:
|
||||
setattr(bank, "bank_prune", self.bank_prune_coro)
|
||||
if self.set_global_coro is not None:
|
||||
setattr(bank, "set_global", self.set_global_coro)
|
||||
if self.is_global_coro is not None:
|
||||
setattr(bank, "is_global", self.is_global_coro)
|
||||
|
||||
payday: commands.Command = self.bot.get_command("payday")
|
||||
if payday and self.payday_callback:
|
||||
payday.callback = self.payday_callback
|
||||
|
||||
log.info("Methods restored")
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_cog_add(self, cog: commands.Cog):
|
||||
if cog.qualified_name != "Economy":
|
||||
return
|
||||
command: commands.Command = self.bot.get_command("payday")
|
||||
if command:
|
||||
self.payday_callback = command.callback
|
||||
command.callback = self.payday_override.callback
|
||||
|
||||
@commands.command()
|
||||
@commands.is_owner()
|
||||
@commands.bot_has_permissions(embed_links=True)
|
||||
async def bankevents(self, ctx: commands.Context):
|
||||
"""Get help using the BankEvents cog"""
|
||||
txt = _(
|
||||
"This cog allows you to add listeners for Red bank transactions in your own cogs "
|
||||
"by dispatching the following events:\n"
|
||||
"- red_bank_set_balance\n"
|
||||
"- red_bank_transfer_credits\n"
|
||||
"- red_bank_wipe\n"
|
||||
"- red_bank_prune\n"
|
||||
"- red_bank_set_global\n"
|
||||
"- red_economy_payday_claim\n"
|
||||
"Here are the implementations you can use in your cogs that will work when this cog is loaded:\n"
|
||||
)
|
||||
|
||||
examples = Path(__file__).parent / "examples.txt"
|
||||
await ctx.send(txt)
|
||||
embed = discord.Embed(description=box(examples.read_text(), "python"))
|
||||
await ctx.send(embed=embed)
|
0
bankevents/overrides/__init__.py
Normal file
0
bankevents/overrides/__init__.py
Normal file
247
bankevents/overrides/bank.py
Normal file
247
bankevents/overrides/bank.py
Normal file
|
@ -0,0 +1,247 @@
|
|||
import json
|
||||
from typing import Dict, NamedTuple, Optional, Union
|
||||
|
||||
import discord
|
||||
from redbot.core import bank
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.errors import BalanceTooHigh, BankPruneError
|
||||
from redbot.core.utils import AsyncIter
|
||||
from redbot.core.utils.chat_formatting import humanize_number
|
||||
|
||||
_bot_ref: Optional[Red] = None
|
||||
_cache_is_global = None
|
||||
|
||||
|
||||
def init(bot: Red):
|
||||
global _bot_ref
|
||||
_bot_ref = bot
|
||||
|
||||
|
||||
# Thanks to YamiKaitou for starting the work on this 2+ years ago
|
||||
# Maybe one day it will be merged
|
||||
# https://github.com/Cog-Creators/Red-DiscordBot/pull/5325
|
||||
class BankSetBalanceInformation(NamedTuple):
|
||||
recipient: Union[discord.Member, discord.User]
|
||||
guild: Union[discord.Guild, None]
|
||||
recipient_old_balance: int
|
||||
recipient_new_balance: int
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"recipient": self.recipient.id,
|
||||
"guild": getattr(self.guild, "id", None),
|
||||
"recipient_old_balance": self.recipient_old_balance,
|
||||
"recipient_new_balance": self.recipient_new_balance,
|
||||
}
|
||||
|
||||
def to_json(self) -> str:
|
||||
return json.dumps(self.to_dict())
|
||||
|
||||
|
||||
class BankTransferInformation(NamedTuple):
|
||||
sender: Union[discord.Member, discord.User]
|
||||
recipient: Union[discord.Member, discord.User]
|
||||
guild: Union[discord.Guild, None]
|
||||
transfer_amount: int
|
||||
sender_new_balance: int
|
||||
recipient_new_balance: int
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"sender": self.sender.id,
|
||||
"recipient": self.recipient.id,
|
||||
"guild": getattr(self.guild, "id", None),
|
||||
"transfer_amount": self.transfer_amount,
|
||||
"sender_new_balance": self.sender_new_balance,
|
||||
"recipient_new_balance": self.recipient_new_balance,
|
||||
}
|
||||
|
||||
def to_json(self) -> str:
|
||||
return json.dumps(self.to_dict())
|
||||
|
||||
|
||||
class BankWithdrawDepositInformation(NamedTuple):
|
||||
member: discord.Member
|
||||
guild: Union[discord.Guild, None]
|
||||
amount: int
|
||||
old_balance: int
|
||||
new_balance: int
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"member": self.member.id,
|
||||
"guild": getattr(self.guild, "id", None),
|
||||
"amount": self.amount,
|
||||
"old_balance": self.old_balance,
|
||||
"new_balance": self.new_balance,
|
||||
}
|
||||
|
||||
def to_json(self) -> str:
|
||||
return json.dumps(self.to_dict())
|
||||
|
||||
|
||||
class BankPruneInformation(NamedTuple):
|
||||
guild: Union[discord.Guild, None]
|
||||
user_id: Union[int, None]
|
||||
# {user_id: {name: str, balance: int, created_at: int}}
|
||||
pruned_users: Dict[str, Dict[str, Union[int, str]]]
|
||||
|
||||
@property
|
||||
def scope(self) -> str:
|
||||
if self.guild is None and self.user_id is None:
|
||||
return "global"
|
||||
elif self.guild is not None and self.user_id is None:
|
||||
return "guild"
|
||||
return "user"
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"guild": getattr(self.guild, "id", None),
|
||||
"user_id": self.user_id,
|
||||
"scope": self.scope,
|
||||
"pruned_users": self.pruned_users,
|
||||
}
|
||||
|
||||
def to_json(self) -> str:
|
||||
return json.dumps(self.to_dict())
|
||||
|
||||
|
||||
async def set_balance(member: Union[discord.Member, discord.User], amount: int) -> int:
|
||||
if not isinstance(amount, int):
|
||||
raise TypeError("Amount must be of type int, not {}.".format(type(amount)))
|
||||
if amount < 0:
|
||||
raise ValueError("Not allowed to have negative balance.")
|
||||
guild = getattr(member, "guild", None)
|
||||
max_bal = await bank.get_max_balance(guild)
|
||||
if amount > max_bal:
|
||||
currency = await bank.get_currency_name(guild)
|
||||
raise BalanceTooHigh(user=member, max_balance=max_bal, currency_name=currency)
|
||||
if await is_global():
|
||||
group = bank._config.user(member)
|
||||
else:
|
||||
group = bank._config.member(member)
|
||||
|
||||
old_balance = await group.balance()
|
||||
await group.balance.set(amount)
|
||||
|
||||
if await group.created_at() == 0:
|
||||
time = bank._encoded_current_time()
|
||||
await group.created_at.set(time)
|
||||
if await group.name() == "":
|
||||
await group.name.set(member.display_name)
|
||||
payload = BankSetBalanceInformation(member, guild, old_balance, amount)
|
||||
_bot_ref.dispatch("red_bank_set_balance", payload)
|
||||
return amount
|
||||
|
||||
|
||||
async def transfer_credits(
|
||||
from_: Union[discord.Member, discord.User],
|
||||
to: Union[discord.Member, discord.User],
|
||||
amount: int,
|
||||
) -> int:
|
||||
if not isinstance(amount, int):
|
||||
raise TypeError("Transfer amount must be of type int, not {}.".format(type(amount)))
|
||||
if bank._invalid_amount(amount):
|
||||
raise ValueError("Invalid transfer amount {} <= 0".format(humanize_number(amount, override_locale="en_US")))
|
||||
guild = getattr(to, "guild", None)
|
||||
|
||||
max_bal = await bank.get_max_balance(guild)
|
||||
if await bank.get_balance(to) + amount > max_bal:
|
||||
currency = await bank.get_currency_name(guild)
|
||||
raise bank.errors.BalanceTooHigh(user=to.display_name, max_balance=max_bal, currency_name=currency)
|
||||
|
||||
sender_new = await bank.withdraw_credits(from_, amount)
|
||||
recipient_new = await bank.deposit_credits(to, amount)
|
||||
payload = BankTransferInformation(from_, to, guild, amount, sender_new, recipient_new)
|
||||
_bot_ref.dispatch("red_bank_transfer_credits", payload)
|
||||
return recipient_new
|
||||
|
||||
|
||||
async def wipe_bank(guild: Optional[discord.Guild] = None) -> None:
|
||||
if await is_global():
|
||||
await bank._config.clear_all_users()
|
||||
_bot_ref.dispatch("red_bank_wipe", -1)
|
||||
else:
|
||||
await bank._config.clear_all_members(guild)
|
||||
_bot_ref.dispatch("red_bank_wipe", getattr(guild, "id", None))
|
||||
|
||||
|
||||
async def bank_prune(bot: Red, guild: discord.Guild = None, user_id: int = None) -> None:
|
||||
global_bank = await is_global()
|
||||
if not global_bank and guild is None:
|
||||
raise BankPruneError("'guild' can't be None when pruning a local bank")
|
||||
|
||||
_guilds = set()
|
||||
_uguilds = set()
|
||||
if global_bank:
|
||||
group = bank._config._get_base_group(bank._config.USER)
|
||||
if user_id is None:
|
||||
async for g in AsyncIter(bot.guilds, steps=100):
|
||||
if g.unavailable:
|
||||
_uguilds.add(g)
|
||||
elif not g.chunked:
|
||||
_guilds.add(g)
|
||||
else:
|
||||
group = bank._config._get_base_group(bank._config.MEMBER, str(guild.id))
|
||||
if user_id is None:
|
||||
if guild.unavailable:
|
||||
_uguilds.add(guild)
|
||||
else:
|
||||
_guilds.add(guild)
|
||||
|
||||
if user_id is None:
|
||||
for _guild in _guilds:
|
||||
await _guild.chunk()
|
||||
members = bot.get_all_members() if global_bank else guild.members
|
||||
valid_users = {str(m.id) for m in members if m.guild not in _uguilds}
|
||||
accounts = await group.all()
|
||||
valid_accounts = {k: v for k, v in accounts.items() if k in valid_users}
|
||||
await group.set(valid_accounts)
|
||||
pruned = {k: v for k, v in accounts.items() if k not in valid_users}
|
||||
else:
|
||||
pruned = {}
|
||||
user_id = str(user_id)
|
||||
accounts = await group.all()
|
||||
if user_id in accounts:
|
||||
pruned = {user_id: accounts[user_id]}
|
||||
await group.clear_raw(user_id)
|
||||
|
||||
payload = BankPruneInformation(guild, user_id, pruned)
|
||||
|
||||
_bot_ref.dispatch("red_bank_prune", payload)
|
||||
|
||||
|
||||
async def is_global() -> bool:
|
||||
"""Determine if the bank is currently global.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
:code:`True` if the bank is global, otherwise :code:`False`.
|
||||
|
||||
"""
|
||||
global _cache_is_global
|
||||
|
||||
if _cache_is_global is None:
|
||||
_cache_is_global = await bank._config.is_global()
|
||||
|
||||
return _cache_is_global
|
||||
|
||||
|
||||
async def set_global(global_: bool) -> bool:
|
||||
if (await is_global()) is global_:
|
||||
return global_
|
||||
|
||||
global _cache_is_global
|
||||
|
||||
if await is_global():
|
||||
await bank._config.clear_all_users()
|
||||
_bot_ref.dispatch("red_bank_wipe", -1)
|
||||
else:
|
||||
await bank._config.clear_all_members()
|
||||
_bot_ref.dispatch("red_bank_wipe", None)
|
||||
|
||||
await bank._config.is_global.set(global_)
|
||||
_cache_is_global = global_
|
||||
_bot_ref.dispatch("red_bank_set_global", global_)
|
||||
return global_
|
162
bankevents/overrides/economy.py
Normal file
162
bankevents/overrides/economy.py
Normal file
|
@ -0,0 +1,162 @@
|
|||
import calendar
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import NamedTuple, Union
|
||||
|
||||
import discord
|
||||
from redbot.core import bank, commands, errors
|
||||
from redbot.core.i18n import Translator
|
||||
from redbot.core.utils.chat_formatting import humanize_number
|
||||
|
||||
from ..abc import MixinMeta
|
||||
|
||||
log = logging.getLogger("red.vrt.bankevents")
|
||||
_ = Translator("BankEvents", __file__)
|
||||
|
||||
|
||||
class PaydayClaimInformation(NamedTuple):
|
||||
member: discord.Member
|
||||
channel: Union[discord.TextChannel, discord.Thread, discord.ForumChannel]
|
||||
message: discord.Message
|
||||
amount: int
|
||||
old_balance: int
|
||||
new_balance: int
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"member": self.member.id,
|
||||
"channel": self.channel.id,
|
||||
"message": self.message.id,
|
||||
"amount": self.amount,
|
||||
"old_balance": self.old_balance,
|
||||
"new_balance": self.new_balance,
|
||||
}
|
||||
|
||||
def to_json(self) -> str:
|
||||
return json.dumps(self.to_dict())
|
||||
|
||||
|
||||
class PaydayOverride(MixinMeta):
|
||||
@commands.command(hidden=True)
|
||||
@commands.guild_only()
|
||||
async def payday_override(self, ctx: commands.Context):
|
||||
cog = self.bot.get_cog("Economy")
|
||||
if cog is None:
|
||||
raise commands.ExtensionError("Economy cog is not loaded.")
|
||||
|
||||
author = ctx.author
|
||||
guild = ctx.guild
|
||||
|
||||
cur_time = calendar.timegm(ctx.message.created_at.utctimetuple())
|
||||
credits_name = await bank.get_currency_name(guild)
|
||||
old_balance = await bank.get_balance(author)
|
||||
if await bank.is_global():
|
||||
next_payday = await cog.config.user(author).next_payday() + await cog.config.PAYDAY_TIME()
|
||||
if cur_time >= next_payday:
|
||||
credit_amount = await cog.config.PAYDAY_CREDITS()
|
||||
try:
|
||||
new_balance = await bank.deposit_credits(author, credit_amount)
|
||||
except errors.BalanceTooHigh as exc:
|
||||
new_balance = await bank.set_balance(author, exc.max_balance)
|
||||
await ctx.send(
|
||||
_(
|
||||
"You've reached the maximum amount of {currency}! "
|
||||
"Please spend some more \N{GRIMACING FACE}\n\n"
|
||||
"You currently have {new_balance} {currency}."
|
||||
).format(currency=credits_name, new_balance=humanize_number(exc.max_balance))
|
||||
)
|
||||
payload = PaydayClaimInformation(
|
||||
author, ctx.channel, ctx.message, exc.max_balance - credit_amount, old_balance, new_balance
|
||||
)
|
||||
self.bot.dispatch("red_economy_payday_claim", payload)
|
||||
return
|
||||
|
||||
await cog.config.user(author).next_payday.set(cur_time)
|
||||
|
||||
pos = await bank.get_leaderboard_position(author)
|
||||
await ctx.send(
|
||||
_(
|
||||
"{author.mention} Here, take some {currency}. "
|
||||
"Enjoy! (+{amount} {currency}!)\n\n"
|
||||
"You currently have {new_balance} {currency}.\n\n"
|
||||
"You are currently #{pos} on the global leaderboard!"
|
||||
).format(
|
||||
author=author,
|
||||
currency=credits_name,
|
||||
amount=humanize_number(credit_amount),
|
||||
new_balance=humanize_number(await bank.get_balance(author)),
|
||||
pos=humanize_number(pos) if pos else pos,
|
||||
)
|
||||
)
|
||||
payload = PaydayClaimInformation(
|
||||
author, ctx.channel, ctx.message, credit_amount, new_balance, old_balance
|
||||
)
|
||||
self.bot.dispatch("red_economy_payday_claim", payload)
|
||||
else:
|
||||
relative_time = discord.utils.format_dt(
|
||||
datetime.now(timezone.utc) + timedelta(seconds=next_payday - cur_time), "R"
|
||||
)
|
||||
await ctx.send(
|
||||
_("{author.mention} Too soon. Your next payday is {relative_time}.").format(
|
||||
author=author, relative_time=relative_time
|
||||
)
|
||||
)
|
||||
else:
|
||||
# Gets the users latest successfully payday and adds the guilds payday time
|
||||
next_payday = await cog.config.member(author).next_payday() + await cog.config.guild(guild).PAYDAY_TIME()
|
||||
if cur_time >= next_payday:
|
||||
credit_amount = await cog.config.guild(guild).PAYDAY_CREDITS()
|
||||
for role in author.roles:
|
||||
role_credits = await cog.config.role(role).PAYDAY_CREDITS() # Nice variable name
|
||||
if role_credits > credit_amount:
|
||||
credit_amount = role_credits
|
||||
try:
|
||||
new_balance = await bank.deposit_credits(author, credit_amount)
|
||||
except errors.BalanceTooHigh as exc:
|
||||
new_balance = await bank.set_balance(author, exc.max_balance)
|
||||
await ctx.send(
|
||||
_(
|
||||
"You've reached the maximum amount of {currency}! "
|
||||
"Please spend some more \N{GRIMACING FACE}\n\n"
|
||||
"You currently have {new_balance} {currency}."
|
||||
).format(currency=credits_name, new_balance=humanize_number(exc.max_balance))
|
||||
)
|
||||
payload = PaydayClaimInformation(
|
||||
author, ctx.channel, ctx.message, exc.max_balance - credit_amount, new_balance, old_balance
|
||||
)
|
||||
self.bot.dispatch("red_economy_payday_claim", payload)
|
||||
return
|
||||
|
||||
# Sets the latest payday time to the current time
|
||||
next_payday = cur_time
|
||||
|
||||
await cog.config.member(author).next_payday.set(next_payday)
|
||||
pos = await bank.get_leaderboard_position(author)
|
||||
await ctx.send(
|
||||
_(
|
||||
"{author.mention} Here, take some {currency}. "
|
||||
"Enjoy! (+{amount} {currency}!)\n\n"
|
||||
"You currently have {new_balance} {currency}.\n\n"
|
||||
"You are currently #{pos} on the global leaderboard!"
|
||||
).format(
|
||||
author=author,
|
||||
currency=credits_name,
|
||||
amount=humanize_number(credit_amount),
|
||||
new_balance=humanize_number(await bank.get_balance(author)),
|
||||
pos=humanize_number(pos) if pos else pos,
|
||||
)
|
||||
)
|
||||
payload = PaydayClaimInformation(
|
||||
author, ctx.channel, ctx.message, credit_amount, new_balance, old_balance
|
||||
)
|
||||
self.bot.dispatch("red_economy_payday_claim", payload)
|
||||
else:
|
||||
relative_time = discord.utils.format_dt(
|
||||
datetime.now(timezone.utc) + timedelta(seconds=next_payday - cur_time), "R"
|
||||
)
|
||||
await ctx.send(
|
||||
_("{author.mention} Too soon. Your next payday is {relative_time}.").format(
|
||||
author=author, relative_time=relative_time
|
||||
)
|
||||
)
|
75
economytrack/README.md
Normal file
75
economytrack/README.md
Normal file
|
@ -0,0 +1,75 @@
|
|||
Track your economy's total balance over time<br/><br/>Also track you server's member count!
|
||||
|
||||
# [p]economytrack
|
||||
Configure EconomyTrack<br/>
|
||||
- Usage: `[p]economytrack`
|
||||
- Aliases: `ecotrack`
|
||||
- Checks: `server_only`
|
||||
## [p]economytrack togglebanktrack
|
||||
Enable/Disable economy tracking for this server<br/>
|
||||
- Usage: `[p]economytrack togglebanktrack`
|
||||
- Restricted to: `GUILD_OWNER`
|
||||
- Checks: `server_only`
|
||||
## [p]economytrack view
|
||||
View EconomyTrack Settings<br/>
|
||||
- Usage: `[p]economytrack view`
|
||||
## [p]economytrack maxpoints
|
||||
Set the max amount of data points the bot will store<br/>
|
||||
|
||||
**Arguments**<br/>
|
||||
`<max_points>` Maximum amount of data points to store<br/>
|
||||
|
||||
The loop runs every 2 minutes, so 720 points equals 1 day<br/>
|
||||
The default is 21600 (30 days)<br/>
|
||||
Set to 0 to store data indefinitely (Not Recommended)<br/>
|
||||
- Usage: `[p]economytrack maxpoints <max_points>`
|
||||
- Restricted to: `BOT_OWNER`
|
||||
## [p]economytrack timezone
|
||||
Set your desired timezone for the graph<br/>
|
||||
|
||||
**Arguments**<br/>
|
||||
`<timezone>` A string representing a valid timezone<br/>
|
||||
|
||||
**Example:** `[p]ecotrack timezone US/Eastern`<br/>
|
||||
|
||||
Use this command without the argument to get a huge list of valid timezones.<br/>
|
||||
- Usage: `[p]economytrack timezone <timezone>`
|
||||
## [p]economytrack togglemembertrack
|
||||
Enable/Disable member tracking for this server<br/>
|
||||
- Usage: `[p]economytrack togglemembertrack`
|
||||
- Restricted to: `GUILD_OWNER`
|
||||
- Checks: `server_only`
|
||||
# [p]remoutliers
|
||||
Cleanup data above a certain total economy balance<br/>
|
||||
|
||||
**Arguments**<br/>
|
||||
datatype: either `bank` or `member`<br/>
|
||||
- Usage: `[p]remoutliers <max_value> [datatype=bank]`
|
||||
- Restricted to: `GUILD_OWNER`
|
||||
- Checks: `server_only`
|
||||
# [p]bankgraph
|
||||
View bank status over a period of time.<br/>
|
||||
**Arguments**<br/>
|
||||
`<timespan>` How long to look for, or `all` for all-time data. Defaults to 1 day.<br/>
|
||||
Must be at least 1 hour.<br/>
|
||||
**Examples:**<br/>
|
||||
- `[p]bankgraph 3w2d`<br/>
|
||||
- `[p]bankgraph 5d`<br/>
|
||||
- `[p]bankgraph all`<br/>
|
||||
- Usage: `[p]bankgraph [timespan=1d]`
|
||||
- Aliases: `bgraph`
|
||||
- Cooldown: `5 per 60.0 seconds`
|
||||
- Checks: `server_only`
|
||||
# [p]membergraph
|
||||
View member count over a period of time.<br/>
|
||||
**Arguments**<br/>
|
||||
`<timespan>` How long to look for, or `all` for all-time data. Defaults to 1 day.<br/>
|
||||
Must be at least 1 hour.<br/>
|
||||
**Examples:**<br/>
|
||||
- `[p]membergraph 3w2d`<br/>
|
||||
- `[p]membergraph 5d`<br/>
|
||||
- `[p]membergraph all`<br/>
|
||||
- Usage: `[p]membergraph [timespan=1d]`
|
||||
- Aliases: `memgraph`
|
||||
- Cooldown: `5 per 60.0 seconds`
|
||||
- Checks: `server_only`
|
15
economytrack/__init__.py
Normal file
15
economytrack/__init__.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
from redbot.core import VersionInfo, version_info
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.utils import get_end_user_data_statement
|
||||
|
||||
from .economytrack import EconomyTrack
|
||||
|
||||
__red_end_user_data_statement__ = get_end_user_data_statement(__file__)
|
||||
|
||||
|
||||
async def setup(bot: Red):
|
||||
cog = EconomyTrack(bot)
|
||||
if version_info >= VersionInfo.from_str("3.5.0"):
|
||||
await bot.add_cog(cog)
|
||||
else:
|
||||
bot.add_cog(cog)
|
24
economytrack/abc.py
Normal file
24
economytrack/abc.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
from abc import ABC, ABCMeta, abstractmethod
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
import discord
|
||||
import pandas as pd
|
||||
from discord.ext.commands.cog import CogMeta
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.config import Config
|
||||
|
||||
|
||||
class CompositeMetaClass(CogMeta, ABCMeta):
|
||||
"""Type detection"""
|
||||
|
||||
|
||||
class MixinMeta(ABC):
|
||||
"""Type hinting"""
|
||||
|
||||
bot: Red
|
||||
config: Config
|
||||
executor: ThreadPoolExecutor
|
||||
|
||||
@abstractmethod
|
||||
async def get_plot(self, df: pd.DataFrame, y_label: str) -> discord.File:
|
||||
raise NotImplementedError
|
354
economytrack/commands.py
Normal file
354
economytrack/commands.py
Normal file
|
@ -0,0 +1,354 @@
|
|||
import datetime
|
||||
|
||||
import discord
|
||||
import pandas as pd
|
||||
import pytz
|
||||
from discord.ext.commands.cooldowns import BucketType
|
||||
from rapidfuzz import fuzz
|
||||
from redbot.core import bank, commands
|
||||
from redbot.core.commands import parse_timedelta
|
||||
from redbot.core.utils.chat_formatting import box, humanize_number, humanize_timedelta
|
||||
|
||||
from economytrack.abc import MixinMeta
|
||||
|
||||
|
||||
class EconomyTrackCommands(MixinMeta):
|
||||
@commands.group(aliases=["ecotrack"])
|
||||
@commands.has_permissions(manage_messages=True)
|
||||
@commands.guild_only()
|
||||
async def economytrack(self, ctx: commands.Context):
|
||||
"""Configure EconomyTrack"""
|
||||
|
||||
@economytrack.command()
|
||||
@commands.guildowner()
|
||||
@commands.guild_only()
|
||||
async def togglebanktrack(self, ctx: commands.Context):
|
||||
"""Enable/Disable economy tracking for this server"""
|
||||
async with self.config.guild(ctx.guild).all() as conf:
|
||||
if conf["enabled"]:
|
||||
conf["enabled"] = False
|
||||
await ctx.send("Economy tracking has been **Disabled**")
|
||||
else:
|
||||
conf["enabled"] = True
|
||||
await ctx.send("Economy tracking has been **Enabled**")
|
||||
|
||||
@economytrack.command()
|
||||
@commands.guildowner()
|
||||
@commands.guild_only()
|
||||
async def togglemembertrack(self, ctx: commands.Context):
|
||||
"""Enable/Disable member tracking for this server"""
|
||||
async with self.config.guild(ctx.guild).all() as conf:
|
||||
if conf["member_tracking"]:
|
||||
conf["member_tracking"] = False
|
||||
await ctx.send("Member tracking has been **Disabled**")
|
||||
else:
|
||||
conf["member_tracking"] = True
|
||||
await ctx.send("Member tracking has been **Enabled**")
|
||||
|
||||
@economytrack.command()
|
||||
@commands.is_owner()
|
||||
async def maxpoints(self, ctx: commands.Context, max_points: int):
|
||||
"""
|
||||
Set the max amount of data points the bot will store
|
||||
|
||||
**Arguments**
|
||||
`<max_points>` Maximum amount of data points to store
|
||||
|
||||
The loop runs every 2 minutes, so 720 points equals 1 day
|
||||
The default is 21600 (30 days)
|
||||
Set to 0 to store data indefinitely (Not Recommended)
|
||||
"""
|
||||
await self.config.max_points.set(max_points)
|
||||
await ctx.tick()
|
||||
|
||||
@economytrack.command()
|
||||
async def timezone(self, ctx: commands.Context, timezone: str):
|
||||
"""
|
||||
Set your desired timezone for the graph
|
||||
|
||||
**Arguments**
|
||||
`<timezone>` A string representing a valid timezone
|
||||
|
||||
**Example:** `[p]ecotrack timezone US/Eastern`
|
||||
|
||||
Use this command without the argument to get a huge list of valid timezones.
|
||||
"""
|
||||
timezone = timezone.lower()
|
||||
try:
|
||||
tz = pytz.timezone(timezone)
|
||||
except pytz.UnknownTimeZoneError:
|
||||
likely_match = sorted(pytz.common_timezones, key=lambda x: fuzz.ratio(timezone, x.lower()), reverse=True)[0]
|
||||
return await ctx.send(f"Invalid Timezone, did you mean `{likely_match}`?")
|
||||
time = datetime.datetime.now(tz).strftime("%I:%M %p") # Convert to 12-hour format
|
||||
await ctx.send(f"Timezone set to **{timezone}** (`{time}`)")
|
||||
await self.config.guild(ctx.guild).timezone.set(timezone)
|
||||
|
||||
@economytrack.command()
|
||||
@commands.bot_has_permissions(embed_links=True)
|
||||
async def view(self, ctx: commands.Context):
|
||||
"""View EconomyTrack Settings"""
|
||||
max_points = await self.config.max_points()
|
||||
is_global = await bank.is_global()
|
||||
conf = await self.config.guild(ctx.guild).all()
|
||||
timezone = conf["timezone"]
|
||||
enabled = conf["enabled"]
|
||||
if is_global:
|
||||
data = await self.config.data()
|
||||
points = len(data)
|
||||
else:
|
||||
data = await self.config.guild(ctx.guild).data()
|
||||
points = len(data)
|
||||
avg_iter = self.looptime if self.looptime else "(N/A)"
|
||||
ptime = humanize_timedelta(seconds=int(points * 60))
|
||||
mptime = humanize_timedelta(seconds=int(max_points * 60))
|
||||
desc = (
|
||||
f"`Enabled: `{enabled}\n"
|
||||
f"`Timezone: `{timezone}\n"
|
||||
f"`Max Points: `{humanize_number(max_points)} ({mptime})\n"
|
||||
f"`Collected: `{humanize_number(points)} ({ptime if ptime else 'None'})\n"
|
||||
f"`LoopTime: `{avg_iter}ms"
|
||||
)
|
||||
embed = discord.Embed(title="EconomyTrack Settings", description=desc, color=ctx.author.color)
|
||||
memtime = humanize_timedelta(seconds=len(conf["member_data"]) * 60)
|
||||
embed.add_field(
|
||||
name="Member Tracking",
|
||||
value=(
|
||||
f"`Enabled: `{conf['member_tracking']}\n"
|
||||
f"`Collected: `{humanize_number(len(conf['member_data']))} ({memtime if memtime else 'None'})"
|
||||
),
|
||||
inline=False,
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command()
|
||||
@commands.guildowner()
|
||||
@commands.guild_only()
|
||||
@commands.bot_has_permissions(embed_links=True)
|
||||
async def remoutliers(self, ctx: commands.Context, max_value: int, datatype: str = "bank"):
|
||||
"""
|
||||
Cleanup data above a certain total economy balance
|
||||
|
||||
**Arguments**
|
||||
datatype: either `bank` or `member`
|
||||
"""
|
||||
if datatype.lower() in ["b", "bank", "bnk"]:
|
||||
banktype = True
|
||||
else:
|
||||
banktype = False
|
||||
|
||||
is_global = await bank.is_global()
|
||||
|
||||
if banktype:
|
||||
if is_global:
|
||||
data = await self.config.data()
|
||||
else:
|
||||
data = await self.config.guild(ctx.guild).data()
|
||||
else:
|
||||
data = await self.config.guild(ctx.guild).member_data()
|
||||
|
||||
if len(data) < 10:
|
||||
embed = discord.Embed(
|
||||
description="There is not enough data collected. Try again later.",
|
||||
color=discord.Color.red(),
|
||||
)
|
||||
return await ctx.send(embed=embed)
|
||||
|
||||
newrows = [i for i in data if i[1] and i[1] <= max_value]
|
||||
deleted = len(data) - len(newrows)
|
||||
if not deleted:
|
||||
return await ctx.send("No data to delete")
|
||||
|
||||
async with ctx.typing():
|
||||
if banktype:
|
||||
if is_global:
|
||||
await self.config.data.set(newrows)
|
||||
else:
|
||||
await self.config.guild(ctx.guild).data.set(newrows)
|
||||
else:
|
||||
await self.config.guild(ctx.guild).member_data.set(newrows)
|
||||
await ctx.send("Deleted all data points above " + str(max_value))
|
||||
|
||||
@commands.command(aliases=["bgraph"])
|
||||
@commands.cooldown(5, 60.0, BucketType.user)
|
||||
@commands.guild_only()
|
||||
@commands.bot_has_permissions(embed_links=True, attach_files=True)
|
||||
async def bankgraph(self, ctx: commands.Context, timespan: str = "1d"):
|
||||
"""
|
||||
View bank status over a period of time.
|
||||
**Arguments**
|
||||
`<timespan>` How long to look for, or `all` for all-time data. Defaults to 1 day.
|
||||
Must be at least 1 hour.
|
||||
**Examples:**
|
||||
- `[p]bankgraph 3w2d`
|
||||
- `[p]bankgraph 5d`
|
||||
- `[p]bankgraph all`
|
||||
"""
|
||||
if timespan.lower() == "all":
|
||||
delta = datetime.timedelta(days=36500)
|
||||
else:
|
||||
delta = parse_timedelta(timespan, minimum=datetime.timedelta(hours=1))
|
||||
if delta is None:
|
||||
delta = datetime.timedelta(hours=1)
|
||||
is_global = await bank.is_global()
|
||||
currency_name = await bank.get_currency_name(ctx.guild)
|
||||
bank_name = await bank.get_bank_name(ctx.guild)
|
||||
if is_global:
|
||||
data = await self.config.data()
|
||||
else:
|
||||
data = await self.config.guild(ctx.guild).data()
|
||||
if len(data) < 10:
|
||||
embed = discord.Embed(
|
||||
description="There is not enough data collected to generate a graph right now. Try again later.",
|
||||
color=discord.Color.red(),
|
||||
)
|
||||
return await ctx.send(embed=embed)
|
||||
timezone = await self.config.guild(ctx.guild).timezone()
|
||||
now = datetime.datetime.now().astimezone(tz=pytz.timezone(timezone))
|
||||
start = now - delta
|
||||
columns = ["ts", "total"]
|
||||
rows = [i for i in data]
|
||||
for i in rows:
|
||||
i[0] = datetime.datetime.fromtimestamp(i[0]).astimezone(tz=pytz.timezone(timezone))
|
||||
df = pd.DataFrame(rows, columns=columns)
|
||||
df = df.set_index(["ts"])
|
||||
df = df[~df.index.duplicated(keep="first")] # Remove duplicate indexes
|
||||
mask = (df.index > start) & (df.index <= now)
|
||||
df = df.loc[mask]
|
||||
df = pd.DataFrame(df)
|
||||
|
||||
if df.empty or len(df.values) < 10: # In case there is data but it is old
|
||||
embed = discord.Embed(
|
||||
description="There is not enough data collected to generate a graph right now. Try again later.",
|
||||
color=discord.Color.red(),
|
||||
)
|
||||
return await ctx.send(embed=embed)
|
||||
|
||||
delta: datetime.timedelta = df.index[-1] - df.index[0]
|
||||
if timespan.lower() == "all":
|
||||
title = f"Total economy balance for all time ({humanize_timedelta(timedelta=delta)})"
|
||||
else:
|
||||
title = f"Total economy balance over the last {humanize_timedelta(timedelta=delta)}"
|
||||
|
||||
lowest = df.min().total
|
||||
highest = df.max().total
|
||||
avg = df.mean().total
|
||||
current = df.values[-1][0]
|
||||
|
||||
desc = (
|
||||
f"`DataPoints: `{humanize_number(len(df.values))}\n"
|
||||
f"`BankName: `{bank_name}\n"
|
||||
f"`Currency: `{currency_name}"
|
||||
)
|
||||
|
||||
field = (
|
||||
f"`Current: `{humanize_number(current)}\n"
|
||||
f"`Average: `{humanize_number(round(avg))}\n"
|
||||
f"`Highest: `{humanize_number(highest)}\n"
|
||||
f"`Lowest: `{humanize_number(lowest)}\n"
|
||||
f"`Diff: `{humanize_number(highest - lowest)}"
|
||||
)
|
||||
|
||||
first = df.values[0][0]
|
||||
diff = "+" if current > first else "-"
|
||||
field2 = f"{diff} {humanize_number(abs(current - first))}"
|
||||
|
||||
embed = discord.Embed(title=title, description=desc, color=ctx.author.color)
|
||||
embed.add_field(name="Statistics", value=field)
|
||||
embed.add_field(
|
||||
name="Change",
|
||||
value=f"Since <t:{int(df.index[0].timestamp())}:D>\n{box(field2, 'diff')}",
|
||||
)
|
||||
|
||||
embed.set_image(url="attachment://plot.png")
|
||||
embed.set_footer(text=f"Timezone: {timezone}")
|
||||
async with ctx.typing():
|
||||
file = await self.get_plot(df, "Total Economy Credits")
|
||||
await ctx.send(embed=embed, file=file)
|
||||
|
||||
@commands.command(aliases=["memgraph"])
|
||||
@commands.cooldown(5, 60.0, BucketType.user)
|
||||
@commands.guild_only()
|
||||
@commands.bot_has_permissions(embed_links=True, attach_files=True)
|
||||
async def membergraph(self, ctx: commands.Context, timespan: str = "1d"):
|
||||
"""
|
||||
View member count over a period of time.
|
||||
**Arguments**
|
||||
`<timespan>` How long to look for, or `all` for all-time data. Defaults to 1 day.
|
||||
Must be at least 1 hour.
|
||||
**Examples:**
|
||||
- `[p]membergraph 3w2d`
|
||||
- `[p]membergraph 5d`
|
||||
- `[p]membergraph all`
|
||||
"""
|
||||
if timespan.lower() == "all":
|
||||
delta = datetime.timedelta(days=36500)
|
||||
else:
|
||||
delta = parse_timedelta(timespan, minimum=datetime.timedelta(hours=1))
|
||||
if delta is None:
|
||||
delta = datetime.timedelta(hours=1)
|
||||
|
||||
data = await self.config.guild(ctx.guild).member_data()
|
||||
if len(data) < 10:
|
||||
embed = discord.Embed(
|
||||
description="There is not enough data collected to generate a graph right now. Try again later.",
|
||||
color=discord.Color.red(),
|
||||
)
|
||||
return await ctx.send(embed=embed)
|
||||
timezone = await self.config.guild(ctx.guild).timezone()
|
||||
now = datetime.datetime.now().astimezone(tz=pytz.timezone(timezone))
|
||||
start = now - delta
|
||||
columns = ["ts", "total"]
|
||||
rows = [i for i in data]
|
||||
for i in rows:
|
||||
i[0] = datetime.datetime.fromtimestamp(i[0]).astimezone(tz=pytz.timezone(timezone))
|
||||
df = pd.DataFrame(rows, columns=columns)
|
||||
df = df.set_index(["ts"])
|
||||
df = df[~df.index.duplicated(keep="first")] # Remove duplicate indexes
|
||||
mask = (df.index > start) & (df.index <= now)
|
||||
df = df.loc[mask]
|
||||
df = pd.DataFrame(df)
|
||||
|
||||
if df.empty or len(df.values) < 10: # In case there is data but it is old
|
||||
embed = discord.Embed(
|
||||
description="There is not enough data collected to generate a graph right now. Try again later.",
|
||||
color=discord.Color.red(),
|
||||
)
|
||||
return await ctx.send(embed=embed)
|
||||
|
||||
delta: datetime.timedelta = df.index[-1] - df.index[0]
|
||||
if timespan.lower() == "all":
|
||||
title = f"Total member count for all time ({humanize_timedelta(timedelta=delta)})"
|
||||
else:
|
||||
title = f"Total member count over the last {humanize_timedelta(timedelta=delta)}"
|
||||
|
||||
lowest = df.min().total
|
||||
highest = df.max().total
|
||||
avg = df.mean().total
|
||||
current = df.values[-1][0]
|
||||
|
||||
desc = f"`DataPoints: `{humanize_number(len(df.values))}"
|
||||
|
||||
field = (
|
||||
f"`Current: `{humanize_number(current)}\n"
|
||||
f"`Average: `{humanize_number(round(avg))}\n"
|
||||
f"`Highest: `{humanize_number(highest)}\n"
|
||||
f"`Lowest: `{humanize_number(lowest)}\n"
|
||||
f"`Diff: `{humanize_number(highest - lowest)}"
|
||||
)
|
||||
|
||||
first = df.values[0][0]
|
||||
diff = "+" if current > first else "-"
|
||||
field2 = f"{diff} {humanize_number(abs(current - first))}"
|
||||
|
||||
embed = discord.Embed(title=title, description=desc, color=ctx.author.color)
|
||||
embed.add_field(name="Statistics", value=field)
|
||||
embed.add_field(
|
||||
name="Change",
|
||||
value=f"Since <t:{int(df.index[0].timestamp())}:D>\n{box(field2, 'diff')}",
|
||||
)
|
||||
|
||||
embed.set_image(url="attachment://plot.png")
|
||||
embed.set_footer(text=f"Timezone: {timezone}")
|
||||
async with ctx.typing():
|
||||
file = await self.get_plot(df, "Member Count")
|
||||
await ctx.send(embed=embed, file=file)
|
275
economytrack/economytrack.py
Normal file
275
economytrack/economytrack.py
Normal file
|
@ -0,0 +1,275 @@
|
|||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from time import monotonic
|
||||
|
||||
import discord
|
||||
import pandas as pd
|
||||
import pytz
|
||||
from discord.ext import tasks
|
||||
from redbot.core import Config, bank, commands
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.utils import AsyncIter
|
||||
from redbot.core.utils.chat_formatting import box, humanize_number, humanize_timedelta
|
||||
|
||||
from economytrack.abc import CompositeMetaClass
|
||||
from economytrack.commands import EconomyTrackCommands
|
||||
from economytrack.graph import PlotGraph
|
||||
|
||||
log = logging.getLogger("red.vrt.economytrack")
|
||||
|
||||
|
||||
# Credits to Vexed01 for having a great reference cog for some of the logic that went into this!
|
||||
# Vex-Cogs - https://github.com/Vexed01/Vex-Cogs - (StatTrack)
|
||||
|
||||
|
||||
class EconomyTrack(commands.Cog, EconomyTrackCommands, PlotGraph, metaclass=CompositeMetaClass):
|
||||
"""
|
||||
Track your economy's total balance over time
|
||||
|
||||
Also track you server's member count!
|
||||
"""
|
||||
|
||||
__author__ = "[vertyco](https://github.com/vertyco/vrt-cogs)"
|
||||
__version__ = "0.5.6"
|
||||
|
||||
def format_help_for_context(self, ctx):
|
||||
helpcmd = super().format_help_for_context(ctx)
|
||||
info = f"{helpcmd}\n" f"Cog Version: {self.__version__}\n" f"Author: {self.__author__}\n"
|
||||
return info
|
||||
|
||||
async def red_delete_data_for_user(self, *, requester, user_id: int):
|
||||
"""No data to delete"""
|
||||
|
||||
def __init__(self, bot: Red, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.bot = bot
|
||||
self.config = Config.get_conf(self, identifier=117, force_registration=True)
|
||||
default_global = {"max_points": 21600, "data": []}
|
||||
default_guild = {
|
||||
"timezone": "UTC",
|
||||
"data": [],
|
||||
"enabled": False,
|
||||
"member_data": [],
|
||||
"member_tracking": False,
|
||||
}
|
||||
self.config.register_global(**default_global)
|
||||
self.config.register_guild(**default_guild)
|
||||
self.looptime = None
|
||||
self.bank_loop.start()
|
||||
|
||||
def cog_unload(self):
|
||||
self.bank_loop.cancel()
|
||||
|
||||
@tasks.loop(minutes=2)
|
||||
async def bank_loop(self):
|
||||
start = monotonic()
|
||||
is_global = await bank.is_global()
|
||||
max_points = await self.config.max_points()
|
||||
if max_points == 0: # 0 is no limit
|
||||
max_points = 26280000 # 100 years is plenty
|
||||
now = datetime.now().replace(microsecond=0, second=0).timestamp()
|
||||
if is_global:
|
||||
total = await self.get_total_bal()
|
||||
async with self.config.data() as data:
|
||||
data.append((now, total))
|
||||
if len(data) > max_points:
|
||||
del data[0 : len(data) - max_points]
|
||||
else:
|
||||
async for guild in AsyncIter(self.bot.guilds):
|
||||
if not await self.config.guild(guild).enabled():
|
||||
continue
|
||||
total = await self.get_total_bal(guild)
|
||||
async with self.config.guild(guild).data() as data:
|
||||
data.append((now, total))
|
||||
if len(data) > max_points:
|
||||
del data[0 : len(data) - max_points]
|
||||
|
||||
async for guild in AsyncIter(self.bot.guilds):
|
||||
if not await self.config.guild(guild).member_tracking():
|
||||
continue
|
||||
members = guild.member_count
|
||||
async with self.config.guild(guild).member_data() as data:
|
||||
data.append((now, members))
|
||||
if len(data) > max_points:
|
||||
del data[0 : len(data) - max_points]
|
||||
|
||||
iter_time = round((monotonic() - start) * 1000)
|
||||
avg_iter = self.looptime
|
||||
if avg_iter is None:
|
||||
self.looptime = iter_time
|
||||
else:
|
||||
self.looptime = round((avg_iter + iter_time) / 2)
|
||||
|
||||
@staticmethod
|
||||
async def get_total_bal(guild: discord.guild = None) -> int:
|
||||
is_global = await bank.is_global()
|
||||
if is_global:
|
||||
members = await bank._config.all_users()
|
||||
else:
|
||||
members = await bank._config.all_members(guild)
|
||||
total = sum(value["balance"] for value in members.values())
|
||||
return int(total)
|
||||
|
||||
@bank_loop.before_loop
|
||||
async def before_bank_loop(self):
|
||||
await self.bot.wait_until_red_ready()
|
||||
await asyncio.sleep(120)
|
||||
log.info("EconomyTrack Ready")
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_assistant_cog_add(self, cog: commands.Cog):
|
||||
schema1 = {
|
||||
"name": "get_member_count_info",
|
||||
"description": "Get member stats of the current server over a period of time",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"timespan": {
|
||||
"type": "string",
|
||||
"description": "span of time to pull data for, defaults to one day, 'all' can be specified to pull history for all time. Examples: 3w2d, 5d, 20h",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
schema2 = {
|
||||
"name": "get_economy_info",
|
||||
"description": "Get total amount of currency for the current guild, along with bank info and economy stats",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"timespan": {
|
||||
"type": "string",
|
||||
"description": "span of time to pull data for, defaults to one day, 'all' can be specified to pull history for all time. Examples: 3w2d, 5d, 20h",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
await cog.register_functions("EconomyTrack", [schema1, schema2])
|
||||
|
||||
async def get_member_count_info(self, guild: discord.Guild, timespan: str = "1d", *args, **kwargs) -> str:
|
||||
if timespan.lower() == "all":
|
||||
delta = timedelta(days=36500)
|
||||
else:
|
||||
delta = commands.parse_timedelta(timespan, minimum=timedelta(hours=1))
|
||||
if delta is None:
|
||||
delta = timedelta(hours=1)
|
||||
|
||||
data = await self.config.guild(guild).member_data()
|
||||
if len(data) < 2:
|
||||
return "There is not enough data collected. Try again later."
|
||||
|
||||
timezone = await self.config.guild(guild).timezone()
|
||||
now = datetime.now().astimezone(tz=pytz.timezone(timezone))
|
||||
start = now - delta
|
||||
columns = ["ts", "total"]
|
||||
rows = [i for i in data]
|
||||
for i in rows:
|
||||
i[0] = datetime.fromtimestamp(i[0]).astimezone(tz=pytz.timezone(timezone))
|
||||
df = pd.DataFrame(rows, columns=columns)
|
||||
df = df.set_index(["ts"])
|
||||
df = df[~df.index.duplicated(keep="first")] # Remove duplicate indexes
|
||||
mask = (df.index > start) & (df.index <= now)
|
||||
df = df.loc[mask]
|
||||
df = pd.DataFrame(df)
|
||||
|
||||
if df.empty or len(df.values) < 2: # In case there is data but it is old
|
||||
return "There is not enough data collected. Try again later."
|
||||
|
||||
if timespan.lower() == "all":
|
||||
alltime = humanize_timedelta(seconds=len(data) * 60)
|
||||
reply = f"Total member count for all time ({alltime})\n"
|
||||
else:
|
||||
delta: timedelta = df.index[-1] - df.index[0]
|
||||
reply = f"Total member count over the last {humanize_timedelta(timedelta=delta)}\n"
|
||||
|
||||
lowest = df.min().total
|
||||
highest = df.max().total
|
||||
avg = df.mean().total
|
||||
current = df.values[-1][0]
|
||||
|
||||
reply += f"`DataPoints: `{humanize_number(len(df.values))}\n"
|
||||
|
||||
reply += (
|
||||
"Statistics\n"
|
||||
f"`Current: `{humanize_number(current)}\n"
|
||||
f"`Average: `{humanize_number(round(avg))}\n"
|
||||
f"`Highest: `{humanize_number(highest)}\n"
|
||||
f"`Lowest: `{humanize_number(lowest)}\n"
|
||||
f"`Diff: `{humanize_number(highest - lowest)}\n"
|
||||
)
|
||||
|
||||
first = df.values[0][0]
|
||||
diff = "+" if current > first else "-"
|
||||
field = f"{diff} {humanize_number(abs(current - first))}"
|
||||
reply += f"Since <t:{int(df.index[0].timestamp())}:D>\n{box(field, 'diff')}"
|
||||
return reply
|
||||
|
||||
async def get_economy_info(self, guild: discord.Guild, timespan: str = "1d", *args, **kwargs) -> str:
|
||||
if timespan.lower() == "all":
|
||||
delta = timedelta(days=36500)
|
||||
else:
|
||||
delta = commands.parse_timedelta(timespan, minimum=timedelta(hours=1))
|
||||
if delta is None:
|
||||
delta = timedelta(hours=1)
|
||||
|
||||
is_global = await bank.is_global()
|
||||
currency_name = await bank.get_currency_name(guild)
|
||||
bank_name = await bank.get_bank_name(guild)
|
||||
if is_global:
|
||||
data = await self.config.data()
|
||||
else:
|
||||
data = await self.config.guild(guild).data()
|
||||
|
||||
if len(data) < 2:
|
||||
return "There is not enough data collected. Try again later."
|
||||
|
||||
timezone = await self.config.guild(guild).timezone()
|
||||
now = datetime.now().astimezone(tz=pytz.timezone(timezone))
|
||||
start = now - delta
|
||||
columns = ["ts", "total"]
|
||||
rows = [i for i in data]
|
||||
for i in rows:
|
||||
i[0] = datetime.fromtimestamp(i[0]).astimezone(tz=pytz.timezone(timezone))
|
||||
df = pd.DataFrame(rows, columns=columns)
|
||||
df = df.set_index(["ts"])
|
||||
df = df[~df.index.duplicated(keep="first")] # Remove duplicate indexes
|
||||
mask = (df.index > start) & (df.index <= now)
|
||||
df = df.loc[mask]
|
||||
df = pd.DataFrame(df)
|
||||
|
||||
if df.empty or len(df.values) < 2: # In case there is data but it is old
|
||||
return "There is not enough data collectedTry again later."
|
||||
|
||||
if timespan.lower() == "all":
|
||||
alltime = humanize_timedelta(seconds=len(data) * 60)
|
||||
reply = f"Total economy balance for all time ({alltime})"
|
||||
else:
|
||||
delta: timedelta = df.index[-1] - df.index[0]
|
||||
reply = f"Total economy balance over the last {humanize_timedelta(timedelta=delta)}"
|
||||
|
||||
lowest = df.min().total
|
||||
highest = df.max().total
|
||||
avg = df.mean().total
|
||||
current = df.values[-1][0]
|
||||
|
||||
reply += (
|
||||
f"`DataPoints: `{humanize_number(len(df.values))}\n"
|
||||
f"`BankName: `{bank_name}\n"
|
||||
f"`Currency: `{currency_name}"
|
||||
)
|
||||
|
||||
reply += (
|
||||
"Statistics\n"
|
||||
f"`Current: `{humanize_number(current)}\n"
|
||||
f"`Average: `{humanize_number(round(avg))}\n"
|
||||
f"`Highest: `{humanize_number(highest)}\n"
|
||||
f"`Lowest: `{humanize_number(lowest)}\n"
|
||||
f"`Diff: `{humanize_number(highest - lowest)}\n"
|
||||
)
|
||||
|
||||
first = df.values[0][0]
|
||||
diff = "+" if current > first else "-"
|
||||
field = f"{diff} {humanize_number(abs(current - first))}"
|
||||
reply += f"Since <t:{int(df.index[0].timestamp())}:D>\n{box(field, 'diff')}"
|
||||
return reply
|
31
economytrack/graph.py
Normal file
31
economytrack/graph.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
import asyncio
|
||||
from io import BytesIO
|
||||
|
||||
import discord
|
||||
import pandas as pd
|
||||
from plotly import express as px
|
||||
|
||||
from economytrack.abc import MixinMeta
|
||||
|
||||
|
||||
class PlotGraph(MixinMeta):
|
||||
async def get_plot(self, df: pd.DataFrame, y_label: str) -> discord.File:
|
||||
return await asyncio.to_thread(self.make_plot, df, y_label)
|
||||
|
||||
@staticmethod
|
||||
def make_plot(df: pd.DataFrame, y_label: str) -> discord.File:
|
||||
fig = px.line(
|
||||
df,
|
||||
template="plotly_dark",
|
||||
labels={"ts": "Date", "value": y_label},
|
||||
)
|
||||
fig.update_xaxes(tickformat="%I:%M %p\n%b %d %Y")
|
||||
fig.update_yaxes(tickformat="si")
|
||||
fig.update_layout(
|
||||
showlegend=False,
|
||||
)
|
||||
bytefile = fig.to_image(format="png", width=800, height=500, scale=1)
|
||||
buffer = BytesIO(bytefile)
|
||||
buffer.seek(0)
|
||||
file = discord.File(buffer, filename="plot.png")
|
||||
return file
|
32
economytrack/info.json
Normal file
32
economytrack/info.json
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"author": [
|
||||
"Vertyco"
|
||||
],
|
||||
"description": "Track your economy's total balance over time",
|
||||
"disabled": false,
|
||||
"end_user_data_statement": "This cog does not store data about users.",
|
||||
"hidden": false,
|
||||
"install_msg": "Thank you for installing EconomyTrack!\n\nDOCUMENTATION: https://github.com/vertyco/vrt-cogs/blob/main/economytrack/README.md",
|
||||
"min_bot_version": "3.4.0",
|
||||
"min_python_version": [
|
||||
3,
|
||||
9,
|
||||
1
|
||||
],
|
||||
"permissions": [],
|
||||
"required_cogs": {},
|
||||
"requirements": [
|
||||
"pandas",
|
||||
"plotly",
|
||||
"kaleido"
|
||||
],
|
||||
"short": "Economy tracker",
|
||||
"tags": [
|
||||
"utility",
|
||||
"economy",
|
||||
"bank",
|
||||
"tracking",
|
||||
"stats"
|
||||
],
|
||||
"type": "COG"
|
||||
}
|
12
economytrickle/__init__.py
Normal file
12
economytrickle/__init__.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from .economytrickle import EconomyTrickle
|
||||
|
||||
with open(Path(__file__).parent / "info.json") as fp:
|
||||
__red_end_user_data_statement__ = json.load(fp)["end_user_data_statement"]
|
||||
|
||||
|
||||
async def setup(bot):
|
||||
cog = EconomyTrickle(bot)
|
||||
await bot.add_cog(cog)
|
443
economytrickle/economytrickle.py
Normal file
443
economytrickle/economytrickle.py
Normal file
|
@ -0,0 +1,443 @@
|
|||
import logging
|
||||
import math
|
||||
from typing import Union
|
||||
|
||||
import discord
|
||||
from discord.ext import tasks
|
||||
from redbot.core import Config, bank, commands
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from tabulate import tabulate # pylint:disable=import-error
|
||||
|
||||
log = logging.getLogger("red.yamicogs.economytrickle")
|
||||
_ = Translator("EconomyTrickle", __file__)
|
||||
|
||||
|
||||
# taken from Red-Discordbot bank.py
|
||||
def is_owner_if_bank_global():
|
||||
"""
|
||||
Command decorator. If the bank is global, it checks if the author is
|
||||
bot owner, otherwise it only checks
|
||||
if command was used in guild - it DOES NOT check any permissions.
|
||||
When used on the command, this should be combined
|
||||
with permissions check like `guildowner_or_permissions()`.
|
||||
"""
|
||||
|
||||
async def pred(ctx: commands.Context):
|
||||
author = ctx.author
|
||||
if not await bank.is_global():
|
||||
if not ctx.guild:
|
||||
return False
|
||||
return True
|
||||
else:
|
||||
return await ctx.bot.is_owner(author)
|
||||
|
||||
return commands.check(pred)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class EconomyTrickle(commands.Cog):
|
||||
"""
|
||||
Trickle credits into your Economy
|
||||
|
||||
More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>
|
||||
"""
|
||||
|
||||
def __init__(self, bot: Red):
|
||||
self.bot = bot
|
||||
self.config = Config.get_conf(self, identifier=582650109, force_registration=True)
|
||||
|
||||
default_config = {"credits": 0, "messages": 0, "voice": 0, "blocklist": []}
|
||||
|
||||
self.config.register_global(**default_config)
|
||||
self.config.register_guild(**default_config)
|
||||
|
||||
self.message = {}
|
||||
self.voice = {}
|
||||
|
||||
async def cog_load(self):
|
||||
self.bank = await bank.is_global()
|
||||
self.blocklist = await self.config.blocklist()
|
||||
|
||||
self.trickle.start() # pylint:disable=no-member
|
||||
|
||||
async def cog_unload(self):
|
||||
self.trickle.cancel() # pylint:disable=no-member
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message_without_command(self, message):
|
||||
if message.author.bot:
|
||||
return
|
||||
if message.guild == None:
|
||||
return
|
||||
if await self.bot.cog_disabled_in_guild(self, message.guild):
|
||||
return
|
||||
if message.channel.id in self.blocklist:
|
||||
log.debug(
|
||||
f"Found message from {message.author.id} in a blocked channel {message.guild.id}-{message.channel.id}"
|
||||
)
|
||||
return
|
||||
|
||||
if await bank.is_global():
|
||||
try:
|
||||
log.debug(f"Found message from {message.author.id}")
|
||||
self.message[message.author.id].append(message.id)
|
||||
except KeyError:
|
||||
self.message[message.author.id] = [message.id]
|
||||
else:
|
||||
try:
|
||||
log.debug(f"Found message from {message.author.id} in {message.guild.id}")
|
||||
self.message[message.guild.id]
|
||||
try:
|
||||
self.message[message.guild.id][message.author.id].append(message.id)
|
||||
except KeyError:
|
||||
self.message[message.guild.id][message.author.id] = [message.id]
|
||||
except KeyError:
|
||||
self.message[message.guild.id] = {message.author.id: [message.id]}
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_voice_state_update(self, member, before, after):
|
||||
if member.bot:
|
||||
return
|
||||
if await self.bot.cog_disabled_in_guild(self, member.guild):
|
||||
return
|
||||
|
||||
if before.channel is None and after.channel is not None:
|
||||
if after.channel.id in self.blocklist:
|
||||
log.debug(
|
||||
f"Found voice state join from {member.id} in a blocked channel {member.guild.id}-{after.channel.id}"
|
||||
)
|
||||
return
|
||||
|
||||
if await bank.is_global():
|
||||
log.debug(f"Found voice join from {member.id}")
|
||||
self.voice[member.id] = 1
|
||||
else:
|
||||
try:
|
||||
log.debug(f"Found voice join from {member.id} in {member.guild.id}")
|
||||
self.voice[member.guild.id][member.id] = 1
|
||||
except KeyError:
|
||||
self.voice[member.guild.id] = {member.id: 1}
|
||||
|
||||
elif after.channel is None and before.channel is not None:
|
||||
if before.channel.id in self.blocklist:
|
||||
log.debug(
|
||||
f"Found voice state leave from {member.id} in a blocked channel {member.guild.id}-{after.channel.id}"
|
||||
)
|
||||
return
|
||||
|
||||
if await bank.is_global():
|
||||
log.debug(f"Found voice leave from {member.id}")
|
||||
self.voice[member.id] = 0
|
||||
else:
|
||||
try:
|
||||
log.debug(f"Found voice leave from {member.id} in {member.guild.id}")
|
||||
self.voice[member.guild.id][member.id] = 0
|
||||
except KeyError:
|
||||
self.voice[member.guild.id] = {member.id: 0}
|
||||
|
||||
elif before.channel is not after.channel:
|
||||
if after.channel.id in self.blocklist:
|
||||
log.debug(
|
||||
f"Found voice state change from {member.id} in a blocked channel {member.guild.id}-{after.channel.id}"
|
||||
)
|
||||
if await bank.is_global():
|
||||
self.voice[member.id] = 0
|
||||
else:
|
||||
try:
|
||||
self.voice[member.guild.id][member.id] = 0
|
||||
except KeyError:
|
||||
self.voice[member.guild.id] = {member.id: 0}
|
||||
return
|
||||
elif before.channel.id in self.blocklist:
|
||||
if await bank.is_global():
|
||||
log.debug(f"Found voice change from {member.id}")
|
||||
self.voice[member.id] = 1
|
||||
else:
|
||||
try:
|
||||
log.debug(f"Found voice change from {member.id} in {member.guild.id}")
|
||||
self.voice[member.guild.id][member.id] = 1
|
||||
except KeyError:
|
||||
self.voice[member.guild.id] = {member.id: 1}
|
||||
|
||||
@tasks.loop(minutes=1)
|
||||
async def trickle(self):
|
||||
if self.bank is not await bank.is_global():
|
||||
if await bank.is_global():
|
||||
self.cache = await self.config.all()
|
||||
else:
|
||||
self.cache = await self.config.all_guilds()
|
||||
self.bank = await bank.is_global()
|
||||
|
||||
if await bank.is_global():
|
||||
msgs = self.message
|
||||
cache = await self.config.all()
|
||||
|
||||
if cache["messages"] != 0 and cache["credits"] != 0:
|
||||
for user, msg in msgs.items():
|
||||
if len(msg) >= cache["messages"]:
|
||||
num = math.floor(len(msg) / cache["messages"])
|
||||
log.debug(f"Processing {num} messages for {user}")
|
||||
del (self.message[user])[0 : (num * cache["messages"])]
|
||||
await bank.deposit_credits(
|
||||
(await self.bot.get_or_fetch_user(user)),
|
||||
num * cache["credits"],
|
||||
)
|
||||
|
||||
voice = self.voice
|
||||
if cache["voice"] != 0:
|
||||
for user, yes in voice.items():
|
||||
if yes:
|
||||
log.debug(f"Processing voice for {user}")
|
||||
await bank.deposit_credits(
|
||||
(await self.bot.get_or_fetch_user(user)),
|
||||
cache["voice"],
|
||||
)
|
||||
|
||||
else:
|
||||
msgs = self.message
|
||||
for guild, users in msgs.items():
|
||||
if not await self.bot.cog_disabled_in_guild(self, self.bot.get_guild(guild)):
|
||||
cache = await self.config.guild_from_id(guild).all()
|
||||
|
||||
if cache["messages"] != 0 and cache["credits"] != 0:
|
||||
for user, msg in users.items():
|
||||
if len(msg) >= cache["messages"]:
|
||||
num = math.floor(len(msg) / cache["messages"])
|
||||
log.debug(f"Processing {num} messages for {user} in {guild}")
|
||||
del (self.message[guild][user])[0 : (num * cache["messages"])]
|
||||
await bank.deposit_credits(
|
||||
(
|
||||
await self.bot.get_or_fetch_member(
|
||||
self.bot.get_guild(guild), user
|
||||
)
|
||||
),
|
||||
num * cache["credits"],
|
||||
)
|
||||
|
||||
voice = self.voice
|
||||
for guild, users in voice.items():
|
||||
if not await self.bot.cog_disabled_in_guild(self, self.bot.get_guild(guild)):
|
||||
cache = await self.config.guild_from_id(guild).all()
|
||||
if cache["voice"] != 0:
|
||||
for user, yes in users.items():
|
||||
if yes:
|
||||
log.debug(f"Processing voice for {user} in {guild}")
|
||||
await bank.deposit_credits(
|
||||
(
|
||||
await self.bot.get_or_fetch_member(
|
||||
self.bot.get_guild(guild), user
|
||||
)
|
||||
),
|
||||
cache["voice"],
|
||||
)
|
||||
|
||||
@trickle.before_loop
|
||||
async def before_trickle(self):
|
||||
await self.bot.wait_until_red_ready()
|
||||
|
||||
@is_owner_if_bank_global()
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@commands.group(aliases=["trickleset"])
|
||||
async def economytrickle(self, ctx):
|
||||
"""Configure various settings"""
|
||||
|
||||
@is_owner_if_bank_global()
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@economytrickle.command(name="settings", aliases=["info", "showsettings"])
|
||||
async def ts_settings(self, ctx):
|
||||
"""Show the current settings"""
|
||||
|
||||
if await bank.is_global():
|
||||
cache = await self.config.all()
|
||||
await ctx.send(
|
||||
_(
|
||||
"Message Credits: {credits}\nMessage Count: {messages}\nVoice Credits: {voice}"
|
||||
).format(
|
||||
credits=cache["credits"], messages=cache["messages"], voice=cache["voice"]
|
||||
)
|
||||
)
|
||||
else:
|
||||
if ctx.guild is not None:
|
||||
cache = await self.config.guild(ctx.guild).all()
|
||||
await ctx.send(
|
||||
_(
|
||||
"Message Credits: {credits}\nMessage Count: {messages}\nVoice Credits: {voice}"
|
||||
).format(
|
||||
credits=cache["credits"], messages=cache["messages"], voice=cache["voice"]
|
||||
)
|
||||
)
|
||||
else:
|
||||
await ctx.send(
|
||||
_(
|
||||
"Your bank is set to per-server. Please try this command in a server instead"
|
||||
)
|
||||
)
|
||||
|
||||
@is_owner_if_bank_global()
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@economytrickle.command(name="credits")
|
||||
async def ts_credits(self, ctx, number: int):
|
||||
"""
|
||||
Set the number of credits to grant
|
||||
|
||||
Set the number to 0 to disable
|
||||
Max value is 1000
|
||||
"""
|
||||
|
||||
if await bank.is_global():
|
||||
if 0 <= number <= 1000:
|
||||
await self.config.credits.set(number)
|
||||
if not await ctx.tick():
|
||||
await ctx.send(_("Setting saved"))
|
||||
else:
|
||||
await ctx.send(
|
||||
_("You must specify a value that is not less than 0 and not more than 1000")
|
||||
)
|
||||
else:
|
||||
if ctx.guild is not None:
|
||||
if 0 <= number <= 1000:
|
||||
await self.config.guild(ctx.guild).credits.set(number)
|
||||
if not await ctx.tick():
|
||||
await ctx.send(_("Setting saved"))
|
||||
else:
|
||||
await ctx.send(
|
||||
_(
|
||||
"You must specify a value that is not less than 0 and not more than 1000"
|
||||
)
|
||||
)
|
||||
else:
|
||||
await ctx.send(
|
||||
_(
|
||||
"Your bank is set to per-server. Please try this command in a server instead"
|
||||
)
|
||||
)
|
||||
|
||||
@is_owner_if_bank_global()
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@economytrickle.command(name="messages")
|
||||
async def ts_messages(self, ctx, number: int):
|
||||
"""
|
||||
Set the number of messages required to gain credits
|
||||
|
||||
Set the number to 0 to disable
|
||||
Max value is 100
|
||||
"""
|
||||
|
||||
if await bank.is_global():
|
||||
if 0 <= number <= 100:
|
||||
await self.config.messages.set(number)
|
||||
if not await ctx.tick():
|
||||
await ctx.send(_("Setting saved"))
|
||||
else:
|
||||
await ctx.send(
|
||||
_("You must specify a value that is not less than 0 and not more than 100")
|
||||
)
|
||||
else:
|
||||
if ctx.guild is not None:
|
||||
if 0 <= number <= 100:
|
||||
await self.config.guild(ctx.guild).messages.set(number)
|
||||
if not await ctx.tick():
|
||||
await ctx.send(_("Setting saved"))
|
||||
else:
|
||||
await ctx.send(
|
||||
_("You must specify a value that is not less than 0 and not more than 100")
|
||||
)
|
||||
else:
|
||||
await ctx.send(
|
||||
_(
|
||||
"Your bank is set to per-server. Please try this command in a server instead"
|
||||
)
|
||||
)
|
||||
|
||||
@is_owner_if_bank_global()
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@economytrickle.command(name="voice")
|
||||
async def ts_voice(self, ctx, number: int):
|
||||
"""
|
||||
Set the number of credits to grant every minute
|
||||
|
||||
Set the number to 0 to disable
|
||||
Max value is 1000
|
||||
"""
|
||||
|
||||
if await bank.is_global():
|
||||
if 0 <= number <= 1000:
|
||||
await self.config.voice.set(number)
|
||||
if not await ctx.tick():
|
||||
await ctx.send(_("Setting saved"))
|
||||
else:
|
||||
await ctx.send(
|
||||
_("You must specify a value that is not less than 0 and not more than 1000")
|
||||
)
|
||||
else:
|
||||
if ctx.guild is not None:
|
||||
if 0 <= number <= 1000:
|
||||
await self.config.guild(ctx.guild).voice.set(number)
|
||||
if not await ctx.tick():
|
||||
await ctx.send(_("Setting saved"))
|
||||
else:
|
||||
await ctx.send(
|
||||
_(
|
||||
"You must specify a value that is not less than 0 and not more than 1000"
|
||||
)
|
||||
)
|
||||
else:
|
||||
await ctx.send(
|
||||
_(
|
||||
"Your bank is set to per-server. Please try this command in a server instead"
|
||||
)
|
||||
)
|
||||
|
||||
@commands.guild_only()
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@economytrickle.command(name="blocklist", aliases=["blacklist"])
|
||||
async def ts_blocklist(
|
||||
self, ctx, channel: Union[discord.TextChannel, discord.VoiceChannel] = None
|
||||
):
|
||||
"""
|
||||
Add/Remove the current channel (or a specific channel) to the blocklist
|
||||
|
||||
Not passing a channel will add/remove the channel you ran the command in to the blocklist
|
||||
"""
|
||||
|
||||
if channel is None:
|
||||
channel = ctx.channel
|
||||
|
||||
try:
|
||||
self.blocklist.remove(channel.id)
|
||||
await ctx.send(_("Channel removed from the blocklist"))
|
||||
except ValueError:
|
||||
self.blocklist.append(channel.id)
|
||||
await ctx.send(_("Channel added to the blocklist"))
|
||||
finally:
|
||||
await self.config.blocklist.set(self.blocklist)
|
||||
|
||||
@commands.guild_only()
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@economytrickle.command(name="showblocks", aliases=["showblock"])
|
||||
async def ts_showblocks(self, ctx):
|
||||
"""Provide a list of channels that are on the blocklist for this server"""
|
||||
|
||||
blocks = ""
|
||||
for block in self.blocklist:
|
||||
chan = self.bot.get_channel(block)
|
||||
if chan.guild is ctx.guild:
|
||||
blocks += f"{chan.name}\n"
|
||||
|
||||
if blocks == "":
|
||||
blocks = _("No channels blocked")
|
||||
|
||||
await ctx.send(
|
||||
_("The following channels are blocked from EconomyTrickle\n{blocked_channels}").format(
|
||||
blocked_channels=blocks
|
||||
)
|
||||
)
|
||||
|
||||
async def red_get_data_for_user(self, *, user_id: int):
|
||||
# this cog does not store any data
|
||||
return {}
|
||||
|
||||
async def red_delete_data_for_user(self, *, requester, user_id: int) -> None:
|
||||
# this cog does not store any data
|
||||
pass
|
20
economytrickle/info.json
Normal file
20
economytrickle/info.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"author": [
|
||||
"YamiKaitou#8975"
|
||||
],
|
||||
"name": "EconomyTrickle",
|
||||
"short": "Trickle credits into your economy",
|
||||
"description": "Automatically trickle some credits into your bot's economy",
|
||||
"tags": [
|
||||
"economy",
|
||||
"trickle"
|
||||
],
|
||||
"requirements": [
|
||||
"tabulate"
|
||||
],
|
||||
"min_bot_version": "3.5.0",
|
||||
"end_user_data_statement": "This cog does not persistently store end user data.",
|
||||
"hidden": false,
|
||||
"disabled": false,
|
||||
"install_msg": "Thanks for installing the cog. I'm in the Cog Support server if you need help with anything. Make sure you take a look under `[p]economytrickle` before getting started, the settings are all set to 0 by default"
|
||||
}
|
120
economytrickle/locales/ar-SA.po
Normal file
120
economytrickle/locales/ar-SA.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Arabic\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: ar\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: ar_SA\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/bg-BG.po
Normal file
120
economytrickle/locales/bg-BG.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Bulgarian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: bg\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: bg_BG\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/cs-CZ.po
Normal file
120
economytrickle/locales/cs-CZ.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Czech\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: cs\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: cs_CZ\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/da-DK.po
Normal file
120
economytrickle/locales/da-DK.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Danish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: da\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: da_DK\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/de-DE.po
Normal file
120
economytrickle/locales/de-DE.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: German\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: de\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: de_DE\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/es-ES.po
Normal file
120
economytrickle/locales/es-ES.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Spanish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: es-ES\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: es_ES\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/fi-FI.po
Normal file
120
economytrickle/locales/fi-FI.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Finnish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: fi\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: fi_FI\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/fr-FR.po
Normal file
120
economytrickle/locales/fr-FR.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: French\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: fr\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: fr_FR\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/hi-IN.po
Normal file
120
economytrickle/locales/hi-IN.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Hindi\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: hi\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: hi_IN\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/hr-HR.po
Normal file
120
economytrickle/locales/hr-HR.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Croatian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: hr\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: hr_HR\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/hu-HU.po
Normal file
120
economytrickle/locales/hu-HU.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Hungarian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: hu\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: hu_HU\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/id-ID.po
Normal file
120
economytrickle/locales/id-ID.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Indonesian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: id\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: id_ID\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/it-IT.po
Normal file
120
economytrickle/locales/it-IT.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Italian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: it\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: it_IT\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/ja-JP.po
Normal file
120
economytrickle/locales/ja-JP.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Japanese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: ja\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: ja_JP\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/ko-KR.po
Normal file
120
economytrickle/locales/ko-KR.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Korean\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: ko\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: ko_KR\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
127
economytrickle/locales/messages.pot
Normal file
127
economytrickle/locales/messages.pot
Normal file
|
@ -0,0 +1,127 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Trickle credits into your Economy\n"
|
||||
"\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid ""
|
||||
"Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid ""
|
||||
"Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Set the number of credits to grant\n"
|
||||
"\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid ""
|
||||
"You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Set the number of messages required to gain credits\n"
|
||||
"\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Set the number of credits to grant every minute\n"
|
||||
"\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n"
|
||||
"\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid ""
|
||||
"The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
120
economytrickle/locales/nb-NO.po
Normal file
120
economytrickle/locales/nb-NO.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Norwegian Bokmal\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: nb\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: nb_NO\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/nl-NL.po
Normal file
120
economytrickle/locales/nl-NL.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-07-17 18:56\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Dutch\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: nl\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: nl_NL\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr "Configureer verschillende instellingen"
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr "Toon de huidige instellingen"
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr "Instelling opgeslagen"
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr "Kanaal verwijderd uit de blokkeerlijst"
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr "Geen kanalen geblokkeerd"
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/pl-PL.po
Normal file
120
economytrickle/locales/pl-PL.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Polish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: pl\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: pl_PL\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/pt-BR.po
Normal file
120
economytrickle/locales/pt-BR.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese, Brazilian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: pt-BR\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: pt_BR\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/pt-PT.po
Normal file
120
economytrickle/locales/pt-PT.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: pt-PT\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: pt_PT\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/ru-RU.po
Normal file
120
economytrickle/locales/ru-RU.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Russian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: ru\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: ru_RU\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/sk-SK.po
Normal file
120
economytrickle/locales/sk-SK.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Slovak\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: sk\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: sk_SK\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/sl-SI.po
Normal file
120
economytrickle/locales/sl-SI.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-07-01 17:33\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Slovenian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: sl\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: sl_SI\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/sv-SE.po
Normal file
120
economytrickle/locales/sv-SE.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Swedish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: sv-SE\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: sv_SE\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/tr-TR.po
Normal file
120
economytrickle/locales/tr-TR.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Turkish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: tr\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: tr_TR\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/uk-UA.po
Normal file
120
economytrickle/locales/uk-UA.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Ukrainian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: uk\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: uk_UA\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/vi-VN.po
Normal file
120
economytrickle/locales/vi-VN.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Vietnamese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: vi\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: vi_VN\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/zh-CN.po
Normal file
120
economytrickle/locales/zh-CN.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: zh-CN\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: zh_CN\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
120
economytrickle/locales/zh-TW.po
Normal file
120
economytrickle/locales/zh-TW.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: yamicogs\n"
|
||||
"POT-Creation-Date: 2024-04-14 18:44+0000\n"
|
||||
"PO-Revision-Date: 2024-04-14 18:49\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Traditional\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: redgettext 3.4.2\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Crowdin-Project: yamicogs\n"
|
||||
"X-Crowdin-Project-ID: 436902\n"
|
||||
"X-Crowdin-Language: zh-TW\n"
|
||||
"X-Crowdin-File: /master/economytrickle/locales/messages.pot\n"
|
||||
"X-Crowdin-File-ID: 160\n"
|
||||
"Language: zh_TW\n"
|
||||
|
||||
#: economytrickle/economytrickle.py:40
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Trickle credits into your Economy\n\n"
|
||||
" More detailed docs: <https://cogs.yamikaitou.dev/economytrickle.html>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:243
|
||||
#, docstring
|
||||
msgid "Configure various settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:249
|
||||
#, docstring
|
||||
msgid "Show the current settings"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:254 economytrickle/economytrickle.py:264
|
||||
msgid "Message Credits: {credits}\n"
|
||||
"Message Count: {messages}\n"
|
||||
"Voice Credits: {voice}"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:272 economytrickle/economytrickle.py:311
|
||||
#: economytrickle/economytrickle.py:348 economytrickle/economytrickle.py:387
|
||||
msgid "Your bank is set to per-server. Please try this command in a server instead"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:281
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:292 economytrickle/economytrickle.py:302
|
||||
#: economytrickle/economytrickle.py:331 economytrickle/economytrickle.py:341
|
||||
#: economytrickle/economytrickle.py:368 economytrickle/economytrickle.py:378
|
||||
msgid "Setting saved"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:295 economytrickle/economytrickle.py:305
|
||||
#: economytrickle/economytrickle.py:371 economytrickle/economytrickle.py:381
|
||||
msgid "You must specify a value that is not less than 0 and not more than 1000"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:320
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of messages required to gain credits\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 100\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:334 economytrickle/economytrickle.py:344
|
||||
msgid "You must specify a value that is not less than 0 and not more than 100"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:357
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Set the number of credits to grant every minute\n\n"
|
||||
" Set the number to 0 to disable\n"
|
||||
" Max value is 1000\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:398
|
||||
#, docstring
|
||||
msgid "\n"
|
||||
" Add/Remove the current channel (or a specific channel) to the blocklist\n\n"
|
||||
" Not passing a channel will add/remove the channel you ran the command in to the blocklist\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:409
|
||||
msgid "Channel removed from the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:412
|
||||
msgid "Channel added to the blocklist"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:420
|
||||
#, docstring
|
||||
msgid "Provide a list of channels that are on the blocklist for this server"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:429
|
||||
msgid "No channels blocked"
|
||||
msgstr ""
|
||||
|
||||
#: economytrickle/economytrickle.py:432
|
||||
msgid "The following channels are blocked from EconomyTrickle\n"
|
||||
"{blocked_channels}"
|
||||
msgstr ""
|
||||
|
21
evolution/__init__.py
Normal file
21
evolution/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from . import bank
|
||||
|
||||
from .evolution import Evolution
|
||||
|
||||
__red_end_user_data_statement__ = (
|
||||
"This cog stores user's Discord IDs for the sake of storing game data. "
|
||||
"Users may delete their own data at the cost of losing game data through "
|
||||
"a data request, if the bot is configured to lose data at the cost of "
|
||||
"functionality. Alternatively, there is a in-cog command to delete user "
|
||||
"data as well."
|
||||
)
|
||||
|
||||
|
||||
async def setup(bot):
|
||||
bank._init(bot)
|
||||
is_global = await bank.is_global()
|
||||
if not is_global:
|
||||
raise RuntimeError("Bank must be global for this cog to work.")
|
||||
cog = Evolution(bot)
|
||||
await bot.add_cog(cog)
|
||||
await cog.utils.initialize()
|
774
evolution/bank.py
Normal file
774
evolution/bank.py
Normal file
|
@ -0,0 +1,774 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import datetime
|
||||
from functools import wraps
|
||||
from typing import TYPE_CHECKING, List, Optional, Union
|
||||
|
||||
import discord
|
||||
from redbot.core import Config, bank, commands, errors
|
||||
from redbot.core.bank import Account
|
||||
from redbot.core.bank import BankPruneError as BankPruneError
|
||||
from redbot.core.i18n import Translator
|
||||
from redbot.core.utils import AsyncIter
|
||||
from redbot.core.utils.chat_formatting import humanize_number
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from redbot.core.bot import Red
|
||||
|
||||
# Credits: https://github.com/Cog-Creators/Red-DiscordBot/blob/V3/develop/redbot/core/bank.py
|
||||
# This is a modified version of Red's Bank API that listen for the existance of the Adventure Cog.
|
||||
# If Cog is not loaded, then it will default to Red's Bank API
|
||||
|
||||
_ = Translator("Adventure Bank API", __file__)
|
||||
|
||||
__all__ = [
|
||||
"Account",
|
||||
"get_balance",
|
||||
"set_balance",
|
||||
"withdraw_credits",
|
||||
"deposit_credits",
|
||||
"can_spend",
|
||||
"transfer_credits",
|
||||
"wipe_bank",
|
||||
"get_account",
|
||||
"is_global",
|
||||
"set_global",
|
||||
"get_bank_name",
|
||||
"set_bank_name",
|
||||
"get_currency_name",
|
||||
"set_currency_name",
|
||||
"get_default_balance",
|
||||
"set_default_balance",
|
||||
"get_max_balance",
|
||||
"set_max_balance",
|
||||
"cost",
|
||||
"AbortPurchase",
|
||||
"bank_prune",
|
||||
"get_next_payday",
|
||||
"set_next_payday",
|
||||
"BankPruneError",
|
||||
]
|
||||
|
||||
_MAX_BALANCE = 2**63 - 1
|
||||
|
||||
_DEFAULT_MEMBER = {"balance": 0, "next_payday": 0}
|
||||
|
||||
|
||||
_config: Config = None
|
||||
_bot: Red = None
|
||||
|
||||
|
||||
def _init(bot: Red):
|
||||
global _config, _bot
|
||||
if _config is None:
|
||||
_config = Config.get_conf(
|
||||
None, 384734293238749, cog_name="AdventureBank", force_registration=True
|
||||
)
|
||||
_config.register_user(**_DEFAULT_MEMBER)
|
||||
_bot = bot
|
||||
|
||||
|
||||
class AdventureAccount:
|
||||
"""A single account.
|
||||
This class should ONLY be instantiated by the bank itself."""
|
||||
|
||||
def __init__(self, balance: int, next_payday: int):
|
||||
self.balance = balance
|
||||
self.next_payday = next_payday
|
||||
|
||||
|
||||
def _encoded_current_time() -> int:
|
||||
"""Get the current UTC time as a timestamp.
|
||||
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The current UTC timestamp.
|
||||
"""
|
||||
now = datetime.datetime.utcnow()
|
||||
return _encode_time(now)
|
||||
|
||||
|
||||
def _encode_time(time: datetime.datetime) -> int:
|
||||
"""Convert a datetime object to a serializable int.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
time : datetime.datetime
|
||||
The datetime to convert.
|
||||
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The timestamp of the datetime object.
|
||||
"""
|
||||
ret = int(time.timestamp())
|
||||
return ret
|
||||
|
||||
|
||||
def _decode_time(time: int) -> datetime.datetime:
|
||||
"""Convert a timestamp to a datetime object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
time : int
|
||||
The timestamp to decode.
|
||||
|
||||
Returns
|
||||
-------
|
||||
datetime.datetime
|
||||
The datetime object from the timestamp.
|
||||
"""
|
||||
return datetime.datetime.utcfromtimestamp(time)
|
||||
|
||||
|
||||
async def get_balance(member: discord.Member, _forced: bool = False) -> int:
|
||||
"""Get the current balance of a member.
|
||||
Parameters
|
||||
----------
|
||||
member : discord.Member
|
||||
The member whose balance to check.
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The member's balance
|
||||
"""
|
||||
acc = await get_account(member, _forced=_forced)
|
||||
return int(acc.balance)
|
||||
|
||||
|
||||
async def get_next_payday(member: discord.Member) -> int:
|
||||
"""Get the current balance of a member.
|
||||
Parameters
|
||||
----------
|
||||
member : discord.Member
|
||||
The member whose balance to check.
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The member's balance
|
||||
"""
|
||||
if (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return 0
|
||||
|
||||
acc = await get_account(member)
|
||||
return int(acc.next_payday)
|
||||
|
||||
|
||||
async def set_next_payday(member: Union[discord.Member, discord.User], amount: int) -> int:
|
||||
"""Set an account next payday.
|
||||
Parameters
|
||||
----------
|
||||
member : Union[discord.Member, discord.User]
|
||||
The member whose next payday to set.
|
||||
amount : int
|
||||
The amount to set the next payday to.
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
New account next payday.
|
||||
"""
|
||||
if (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return 0
|
||||
amount = int(amount)
|
||||
group = _config.user(member)
|
||||
await group.next_payday.set(amount)
|
||||
return amount
|
||||
|
||||
|
||||
async def can_spend(member: discord.Member, amount: int, _forced: bool = False) -> bool:
|
||||
"""Determine if a member can spend the given amount.
|
||||
Parameters
|
||||
----------
|
||||
member : discord.Member
|
||||
The member wanting to spend.
|
||||
amount : int
|
||||
The amount the member wants to spend.
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
:code:`True` if the member has a sufficient balance to spend the
|
||||
amount, else :code:`False`.
|
||||
"""
|
||||
return await get_balance(member, _forced=_forced) >= amount
|
||||
|
||||
|
||||
async def set_balance(
|
||||
member: Union[discord.Member, discord.User], amount: int, _forced: bool = False
|
||||
) -> int:
|
||||
"""Set an account balance.
|
||||
Parameters
|
||||
----------
|
||||
member : Union[discord.Member, discord.User]
|
||||
The member whose balance to set.
|
||||
amount : int
|
||||
The amount to set the balance to.
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
New account balance.
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If attempting to set the balance to a negative number.
|
||||
RuntimeError
|
||||
If the bank is guild-specific and a discord.User object is provided.
|
||||
BalanceTooHigh
|
||||
If attempting to set the balance to a value greater than
|
||||
``bank._MAX_BALANCE``.
|
||||
"""
|
||||
if _forced or (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.set_balance(member=member, amount=amount)
|
||||
|
||||
guild = getattr(member, "guild", None)
|
||||
max_bal = await get_max_balance(guild)
|
||||
if amount > max_bal:
|
||||
currency = await get_currency_name(guild)
|
||||
raise errors.BalanceTooHigh(
|
||||
user=member.display_name, max_balance=max_bal, currency_name=currency
|
||||
)
|
||||
amount = int(amount)
|
||||
group = _config.user(member)
|
||||
await group.balance.set(amount)
|
||||
return amount
|
||||
|
||||
|
||||
async def withdraw_credits(member: discord.Member, amount: int, _forced: bool = False) -> int:
|
||||
"""Remove a certain amount of credits from an account.
|
||||
Parameters
|
||||
----------
|
||||
member : discord.Member
|
||||
The member to withdraw credits from.
|
||||
amount : int
|
||||
The amount to withdraw.
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
New account balance.
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If the withdrawal amount is invalid or if the account has insufficient
|
||||
funds.
|
||||
TypeError
|
||||
If the withdrawal amount is not an `int`.
|
||||
"""
|
||||
if _forced or (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.withdraw_credits(member=member, amount=amount)
|
||||
|
||||
if not isinstance(amount, (int, float)):
|
||||
raise TypeError("Withdrawal amount must be of type int, not {}.".format(type(amount)))
|
||||
amount = int(amount)
|
||||
bal = await get_balance(member)
|
||||
if amount > bal:
|
||||
raise ValueError(
|
||||
"Insufficient funds {} > {}".format(
|
||||
humanize_number(amount, override_locale="en_US"),
|
||||
humanize_number(bal, override_locale="en_US"),
|
||||
)
|
||||
)
|
||||
|
||||
return await set_balance(member, bal - amount)
|
||||
|
||||
|
||||
async def deposit_credits(member: discord.Member, amount: int, _forced: bool = False) -> int:
|
||||
"""Add a given amount of credits to an account.
|
||||
Parameters
|
||||
----------
|
||||
member : discord.Member
|
||||
The member to deposit credits to.
|
||||
amount : int
|
||||
The amount to deposit.
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The new balance.
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If the deposit amount is invalid.
|
||||
TypeError
|
||||
If the deposit amount is not an `int`.
|
||||
"""
|
||||
if _forced or (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.deposit_credits(member=member, amount=amount)
|
||||
if not isinstance(amount, (int, float)):
|
||||
raise TypeError("Deposit amount must be of type int, not {}.".format(type(amount)))
|
||||
amount = int(amount)
|
||||
bal = int(await get_balance(member))
|
||||
return await set_balance(member, amount + bal)
|
||||
|
||||
|
||||
async def transfer_credits(
|
||||
from_: Union[discord.Member, discord.User],
|
||||
to: Union[discord.Member, discord.User],
|
||||
amount: int,
|
||||
tax: float = 0.0,
|
||||
):
|
||||
"""Transfer a given amount of credits from one account to another with a 50% tax.
|
||||
Parameters
|
||||
----------
|
||||
from_: Union[discord.Member, discord.User]
|
||||
The member to transfer from.
|
||||
to : Union[discord.Member, discord.User]
|
||||
The member to transfer to.
|
||||
amount : int
|
||||
The amount to transfer.
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The new balance of the member gaining credits.
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If the amount is invalid or if ``from_`` has insufficient funds.
|
||||
TypeError
|
||||
If the amount is not an `int`.
|
||||
RuntimeError
|
||||
If the bank is guild-specific and a discord.User object is provided.
|
||||
BalanceTooHigh
|
||||
If the balance after the transfer would be greater than
|
||||
``bank._MAX_BALANCE``.
|
||||
"""
|
||||
if (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.transfer_credits(from_=from_, to=to, amount=amount)
|
||||
|
||||
if not isinstance(amount, (int, float)):
|
||||
raise TypeError("Transfer amount must be of type int, not {}.".format(type(amount)))
|
||||
|
||||
guild = getattr(to, "guild", None)
|
||||
max_bal = await get_max_balance(guild)
|
||||
new_amount = int(amount - (amount * tax))
|
||||
if await get_balance(to) + new_amount > max_bal:
|
||||
currency = await get_currency_name(guild)
|
||||
raise errors.BalanceTooHigh(
|
||||
user=to.display_name, max_balance=max_bal, currency_name=currency
|
||||
)
|
||||
|
||||
await withdraw_credits(from_, int(amount))
|
||||
await deposit_credits(to, int(new_amount))
|
||||
return int(new_amount)
|
||||
|
||||
|
||||
async def wipe_bank(guild: Optional[discord.Guild] = None) -> None:
|
||||
"""Delete all accounts from the bank.
|
||||
Parameters
|
||||
----------
|
||||
guild : discord.Guild
|
||||
The guild to clear accounts for. If unsupplied and the bank is
|
||||
per-server, all accounts in every guild will be wiped.
|
||||
"""
|
||||
if (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.wipe_bank(guild=guild)
|
||||
await _config.clear_all_users()
|
||||
|
||||
|
||||
async def bank_prune(bot: Red, guild: discord.Guild = None, user_id: int = None) -> None:
|
||||
"""Prune bank accounts from the bank.
|
||||
Parameters
|
||||
----------
|
||||
bot : Red
|
||||
The bot.
|
||||
guild : discord.Guild
|
||||
The guild to prune. This is required if the bank is set to local.
|
||||
user_id : int
|
||||
The id of the user whose account will be pruned.
|
||||
If supplied this will prune only this user's bank account
|
||||
otherwise it will prune all invalid users from the bank.
|
||||
Raises
|
||||
------
|
||||
BankPruneError
|
||||
If guild is :code:`None` and the bank is Local.
|
||||
"""
|
||||
if (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.bank_prune(bot=bot, guild=guild, user_id=user_id)
|
||||
|
||||
_guilds = set()
|
||||
_uguilds = set()
|
||||
if user_id is None:
|
||||
async for g in AsyncIter(bot.guilds, steps=100):
|
||||
if not g.unavailable and g.large and not g.chunked:
|
||||
_guilds.add(g)
|
||||
elif g.unavailable:
|
||||
_uguilds.add(g)
|
||||
group = _config._get_base_group(_config.USER)
|
||||
|
||||
if user_id is None:
|
||||
await bot.request_offline_members(*_guilds)
|
||||
accounts = await group.all()
|
||||
tmp = accounts.copy()
|
||||
members = bot.get_all_members()
|
||||
user_list = {str(m.id) for m in members if m.guild not in _uguilds}
|
||||
|
||||
async with group.all() as bank_data: # FIXME: use-config-bulk-update
|
||||
if user_id is None:
|
||||
for acc in tmp:
|
||||
if acc not in user_list:
|
||||
del bank_data[acc]
|
||||
else:
|
||||
user_id = str(user_id)
|
||||
if user_id in bank_data:
|
||||
del bank_data[user_id]
|
||||
|
||||
|
||||
async def get_leaderboard(
|
||||
positions: int = None, guild: discord.Guild = None, _forced: bool = False
|
||||
) -> List[tuple]:
|
||||
"""
|
||||
Gets the bank's leaderboard
|
||||
Parameters
|
||||
----------
|
||||
positions : `int`
|
||||
The number of positions to get
|
||||
guild : discord.Guild
|
||||
The guild to get the leaderboard of. If the bank is global and this
|
||||
is provided, get only guild members on the leaderboard
|
||||
Returns
|
||||
-------
|
||||
`list` of `tuple`
|
||||
The sorted leaderboard in the form of :code:`(user_id, raw_account)`
|
||||
Raises
|
||||
------
|
||||
TypeError
|
||||
If the bank is guild-specific and no guild was specified
|
||||
"""
|
||||
if _forced or (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.get_leaderboard(positions=positions, guild=guild)
|
||||
raw_accounts = await _config.all_users()
|
||||
if guild is not None:
|
||||
tmp = raw_accounts.copy()
|
||||
for acc in tmp:
|
||||
if not guild.get_member(acc):
|
||||
del raw_accounts[acc]
|
||||
sorted_acc = sorted(raw_accounts.items(), key=lambda x: x[1]["balance"], reverse=True)
|
||||
if positions is None:
|
||||
return sorted_acc
|
||||
else:
|
||||
return sorted_acc[:positions]
|
||||
|
||||
|
||||
async def get_leaderboard_position(
|
||||
member: Union[discord.User, discord.Member], _forced: bool = False
|
||||
) -> Union[int, None]:
|
||||
"""
|
||||
Get the leaderboard position for the specified user
|
||||
Parameters
|
||||
----------
|
||||
member : `discord.User` or `discord.Member`
|
||||
The user to get the leaderboard position of
|
||||
Returns
|
||||
-------
|
||||
`int`
|
||||
The position of the user on the leaderboard
|
||||
Raises
|
||||
------
|
||||
TypeError
|
||||
If the bank is currently guild-specific and a `discord.User` object was passed in
|
||||
"""
|
||||
if await is_global():
|
||||
guild = None
|
||||
else:
|
||||
guild = member.guild if hasattr(member, "guild") else None
|
||||
try:
|
||||
leaderboard = await get_leaderboard(None, guild, _forced=_forced)
|
||||
except TypeError:
|
||||
raise
|
||||
else:
|
||||
pos = discord.utils.find(lambda x: x[1][0] == member.id, enumerate(leaderboard, 1))
|
||||
if pos is None:
|
||||
return None
|
||||
else:
|
||||
return pos[0]
|
||||
|
||||
|
||||
async def get_account(
|
||||
member: Union[discord.Member, discord.User], _forced: bool = False
|
||||
) -> Union[Account, AdventureAccount]:
|
||||
"""Get the appropriate account for the given user or member.
|
||||
A member is required if the bank is currently guild specific.
|
||||
Parameters
|
||||
----------
|
||||
member : `discord.User` or `discord.Member`
|
||||
The user whose account to get.
|
||||
Returns
|
||||
-------
|
||||
Account
|
||||
The user's account.
|
||||
"""
|
||||
if _forced or (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.get_account(member)
|
||||
|
||||
all_accounts = await _config.all_users()
|
||||
if member.id not in all_accounts:
|
||||
acc_data = {"balance": 250, "next_payday": 0}
|
||||
else:
|
||||
acc_data = all_accounts[member.id]
|
||||
return AdventureAccount(**acc_data)
|
||||
|
||||
|
||||
async def is_global(_forced: bool = False) -> bool:
|
||||
"""Determine if the bank is currently global.
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
:code:`True` if the bank is global, otherwise :code:`False`.
|
||||
"""
|
||||
if _forced or (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.is_global()
|
||||
return True
|
||||
|
||||
|
||||
async def set_global(global_: bool) -> bool:
|
||||
"""Set global status of the bank.
|
||||
.. important::
|
||||
All accounts are reset when you switch!
|
||||
Parameters
|
||||
----------
|
||||
global_ : bool
|
||||
:code:`True` will set bank to global mode.
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
New bank mode, :code:`True` is global.
|
||||
Raises
|
||||
------
|
||||
RuntimeError
|
||||
If bank is becoming global and a `discord.Member` was not provided.
|
||||
"""
|
||||
return await bank.set_global(global_)
|
||||
|
||||
|
||||
async def get_bank_name(guild: discord.Guild = None) -> str:
|
||||
"""Get the current bank name.
|
||||
Parameters
|
||||
----------
|
||||
guild : `discord.Guild`, optional
|
||||
The guild to get the bank name for (required if bank is
|
||||
guild-specific).
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
The bank's name.
|
||||
Raises
|
||||
------
|
||||
RuntimeError
|
||||
If the bank is guild-specific and guild was not provided.
|
||||
"""
|
||||
return await bank.get_bank_name(guild)
|
||||
|
||||
|
||||
async def set_bank_name(name: str, guild: discord.Guild = None) -> str:
|
||||
"""Set the bank name.
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
The new name for the bank.
|
||||
guild : `discord.Guild`, optional
|
||||
The guild to set the bank name for (required if bank is
|
||||
guild-specific).
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
The new name for the bank.
|
||||
Raises
|
||||
------
|
||||
RuntimeError
|
||||
If the bank is guild-specific and guild was not provided.
|
||||
"""
|
||||
return await bank.set_bank_name(name=name, guild=guild)
|
||||
|
||||
|
||||
async def get_currency_name(guild: discord.Guild = None, _forced: bool = False) -> str:
|
||||
"""Get the currency name of the bank.
|
||||
Parameters
|
||||
----------
|
||||
guild : `discord.Guild`, optional
|
||||
The guild to get the currency name for (required if bank is
|
||||
guild-specific).
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
The currency name.
|
||||
Raises
|
||||
------
|
||||
RuntimeError
|
||||
If the bank is guild-specific and guild was not provided.
|
||||
"""
|
||||
if _forced or (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.get_currency_name(guild=guild)
|
||||
return _("gold coins")
|
||||
|
||||
|
||||
async def set_currency_name(name: str, guild: discord.Guild = None) -> str:
|
||||
"""Set the currency name for the bank.
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
The new name for the currency.
|
||||
guild : `discord.Guild`, optional
|
||||
The guild to set the currency name for (required if bank is
|
||||
guild-specific).
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
The new name for the currency.
|
||||
Raises
|
||||
------
|
||||
RuntimeError
|
||||
If the bank is guild-specific and guild was not provided.
|
||||
"""
|
||||
return await bank.set_currency_name(name=name, guild=guild)
|
||||
|
||||
|
||||
async def get_max_balance(guild: discord.Guild = None) -> int:
|
||||
"""Get the max balance for the bank.
|
||||
Parameters
|
||||
----------
|
||||
guild : `discord.Guild`, optional
|
||||
The guild to get the max balance for (required if bank is
|
||||
guild-specific).
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The maximum allowed balance.
|
||||
Raises
|
||||
------
|
||||
RuntimeError
|
||||
If the bank is guild-specific and guild was not provided.
|
||||
"""
|
||||
if (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return await bank.get_max_balance(guild=guild)
|
||||
return _MAX_BALANCE
|
||||
|
||||
|
||||
async def set_max_balance(amount: int, guild: discord.Guild = None) -> int:
|
||||
"""Set the maximum balance for the bank.
|
||||
Parameters
|
||||
----------
|
||||
amount : int
|
||||
The new maximum balance.
|
||||
guild : `discord.Guild`, optional
|
||||
The guild to set the max balance for (required if bank is
|
||||
guild-specific).
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The new maximum balance.
|
||||
Raises
|
||||
------
|
||||
RuntimeError
|
||||
If the bank is guild-specific and guild was not provided.
|
||||
ValueError
|
||||
If the amount is less than 0 or higher than 2 ** 63 - 1.
|
||||
"""
|
||||
return await bank.set_max_balance(amount=amount, guild=guild)
|
||||
|
||||
|
||||
async def get_default_balance(guild: discord.Guild = None) -> int:
|
||||
"""Get the current default balance amount.
|
||||
Parameters
|
||||
----------
|
||||
guild : `discord.Guild`, optional
|
||||
The guild to get the default balance for (required if bank is
|
||||
guild-specific).
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The bank's default balance.
|
||||
Raises
|
||||
------
|
||||
RuntimeError
|
||||
If the bank is guild-specific and guild was not provided.
|
||||
"""
|
||||
return await bank.get_default_balance(guild=guild)
|
||||
|
||||
|
||||
async def set_default_balance(amount: int, guild: discord.Guild = None) -> int:
|
||||
"""Set the default balance amount.
|
||||
Parameters
|
||||
----------
|
||||
amount : int
|
||||
The new default balance.
|
||||
guild : `discord.Guild`, optional
|
||||
The guild to set the default balance for (required if bank is
|
||||
guild-specific).
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The new default balance.
|
||||
Raises
|
||||
------
|
||||
RuntimeError
|
||||
If the bank is guild-specific and guild was not provided.
|
||||
ValueError
|
||||
If the amount is less than 0 or higher than the max allowed balance.
|
||||
"""
|
||||
return await bank.set_default_balance(amount=amount, guild=guild)
|
||||
|
||||
|
||||
class AbortPurchase(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def cost(amount: int):
|
||||
"""
|
||||
Decorates a coroutine-function or command to have a cost.
|
||||
If the command raises an exception, the cost will be refunded.
|
||||
You can intentionally refund by raising `AbortPurchase`
|
||||
(this error will be consumed and not show to users)
|
||||
Other exceptions will propagate and will be handled by Red's (and/or
|
||||
any other configured) error handling.
|
||||
"""
|
||||
if not isinstance(amount, int) or amount < 0:
|
||||
raise ValueError("This decorator requires an integer cost greater than or equal to zero")
|
||||
|
||||
def deco(coro_or_command):
|
||||
is_command = isinstance(coro_or_command, commands.Command)
|
||||
if not is_command and not asyncio.iscoroutinefunction(coro_or_command):
|
||||
raise TypeError("@bank.cost() can only be used on commands or `async def` functions")
|
||||
|
||||
coro = coro_or_command.callback if is_command else coro_or_command
|
||||
|
||||
@wraps(coro)
|
||||
async def wrapped(*args, **kwargs):
|
||||
context: commands.Context = None
|
||||
for arg in args:
|
||||
if isinstance(arg, commands.Context):
|
||||
context = arg
|
||||
break
|
||||
|
||||
if not context.guild and not await is_global():
|
||||
raise commands.UserFeedbackCheckFailure(
|
||||
_("Can't pay for this command in DM without a global bank.")
|
||||
)
|
||||
try:
|
||||
await withdraw_credits(context.author, amount)
|
||||
except Exception:
|
||||
credits_name = await get_currency_name(context.guild)
|
||||
raise commands.UserFeedbackCheckFailure(
|
||||
_("You need at least {cost} {currency} to use this command.").format(
|
||||
cost=humanize_number(amount), currency=credits_name
|
||||
)
|
||||
)
|
||||
else:
|
||||
try:
|
||||
return await coro(*args, **kwargs)
|
||||
except AbortPurchase:
|
||||
await deposit_credits(context.author, amount)
|
||||
except Exception:
|
||||
await deposit_credits(context.author, amount)
|
||||
raise
|
||||
|
||||
if not is_command:
|
||||
return wrapped
|
||||
else:
|
||||
wrapped.__module__ = coro_or_command.callback.__module__
|
||||
coro_or_command.callback = wrapped
|
||||
return coro_or_command
|
||||
|
||||
|
||||
def _get_config(_forced: bool = False):
|
||||
if _forced or (cog := _bot.get_cog("Adventure")) is None or not cog._separate_economy:
|
||||
return bank._config
|
||||
return _config
|
746
evolution/evolution.py
Normal file
746
evolution/evolution.py
Normal file
|
@ -0,0 +1,746 @@
|
|||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-Present NeuroAssassin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import copy
|
||||
import math
|
||||
import random
|
||||
import traceback
|
||||
from collections import defaultdict
|
||||
from datetime import timedelta
|
||||
from typing import Literal, Optional
|
||||
|
||||
import discord
|
||||
from redbot.core import Config, commands, errors
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.utils import AsyncIter
|
||||
from redbot.core.utils.chat_formatting import box, humanize_number, humanize_timedelta, inline
|
||||
from redbot.core.utils.menus import DEFAULT_CONTROLS, menu, start_adding_reactions
|
||||
from redbot.core.utils.predicates import ReactionPredicate
|
||||
|
||||
from tabulate import tabulate
|
||||
|
||||
from .tasks import EvolutionTaskManager
|
||||
from .utils import EvolutionUtils
|
||||
|
||||
from . import bank
|
||||
|
||||
ANIMALS = ["chicken", "dog", "cat", "shark", "tiger", "penguin", "pupper", "dragon"]
|
||||
|
||||
IMAGES = {
|
||||
"shark": "https://www.bostonmagazine.com/wp-content/uploads/sites/2/2019/05/Great-white-shark.jpg",
|
||||
"chicken": "https://i1.wp.com/thechickhatchery.com/wp-content/uploads/2018/01/RI-White.jpg?fit=371%2C363&ssl=1",
|
||||
"penguin": "https://cdn.britannica.com/77/81277-050-2A6A35B2/Adelie-penguin.jpg",
|
||||
"dragon": "https://images-na.ssl-images-amazon.com/images/I/61NTUxEnn0L._SL1032_.jpg",
|
||||
"tiger": "https://c402277.ssl.cf1.rackcdn.com/photos/18134/images/hero_small/Medium_WW226365.jpg?1574452099",
|
||||
"cat": "https://icatcare.org/app/uploads/2018/07/Thinking-of-getting-a-cat.png",
|
||||
"dog": "https://d17fnq9dkz9hgj.cloudfront.net/breed-uploads/2018/09/dog-landing-hero-lg.jpg?bust=1536935129&width=1080",
|
||||
"pupper": "https://i.ytimg.com/vi/MPV2METPeJU/maxresdefault.jpg",
|
||||
}
|
||||
|
||||
import inspect
|
||||
|
||||
|
||||
class Evolution(commands.Cog):
|
||||
"""EVOLVE THOSE ANIMALS!!!!!!!!!!!"""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot: Red = bot
|
||||
|
||||
self.lock = asyncio.Lock()
|
||||
self.conf: Config = Config.get_conf(self, identifier=473541068378341376)
|
||||
self.cache = defaultdict(self.cache_defaults) # Thanks to Theelx#4980
|
||||
|
||||
self.utils: EvolutionUtils = EvolutionUtils(self)
|
||||
self.task_manager: EvolutionTaskManager = EvolutionTaskManager(self)
|
||||
|
||||
self.utils.init_config()
|
||||
self.task_manager.init_tasks()
|
||||
|
||||
self.inmarket = []
|
||||
|
||||
def cache_defaults(self):
|
||||
return {"animal": "", "animals": {}, "multiplier": 1.0, "bought": {}}
|
||||
|
||||
def cog_unload(self):
|
||||
self.__unload()
|
||||
|
||||
def __unload(self):
|
||||
self.cache.clear()
|
||||
self.task_manager.shutdown()
|
||||
|
||||
async def red_delete_data_for_user(
|
||||
self,
|
||||
*,
|
||||
requester: Literal["discord_deleted_user", "owner", "user", "user_strict"],
|
||||
user_id: int,
|
||||
):
|
||||
"""This cog stores game data by user ID. It will delete the user's game data,
|
||||
reset their progress and wipe traces of their ID."""
|
||||
await self.conf.user_from_id(user_id).clear()
|
||||
|
||||
try:
|
||||
del self.cache[user_id]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
return
|
||||
|
||||
@commands.group(aliases=["e", "evo"])
|
||||
async def evolution(self, ctx):
|
||||
"""EVOLVE THE GREATEST ANIMALS OF ALL TIME!!!!"""
|
||||
pass
|
||||
|
||||
@evolution.command(usage=" ")
|
||||
async def deletemydata(self, ctx, check: bool = False):
|
||||
"""Delete your game data.
|
||||
|
||||
WARNING! Your data *will not be able to be recovered*!"""
|
||||
if not check:
|
||||
return await ctx.send(
|
||||
f"Warning! This will completely delete your game data and restart you from scratch! If you are sure you want to do this, re-run this command as `{ctx.prefix}evolution deletemydata True`."
|
||||
)
|
||||
await self.red_delete_data_for_user(requester="user", user_id=ctx.author.id)
|
||||
await ctx.send("Data deleted. Your game data has been reset.")
|
||||
|
||||
@commands.is_owner()
|
||||
@evolution.group()
|
||||
async def tasks(self, ctx):
|
||||
"""View the status of the cog tasks.
|
||||
|
||||
These are for debugging purposes"""
|
||||
pass
|
||||
|
||||
@tasks.command(aliases=["checkdelivery", "cd"])
|
||||
async def income(self, ctx):
|
||||
"""Check the delivery status of your money.
|
||||
|
||||
In reality terms, check to see if the income background task has run into an issue"""
|
||||
statuses = self.task_manager.get_statuses()
|
||||
message = self.utils.format_task(statuses["income"])
|
||||
await ctx.send(message)
|
||||
|
||||
@commands.is_owner()
|
||||
@evolution.command(hidden=True)
|
||||
async def removeuser(self, ctx, user: discord.User):
|
||||
"""Removes a user from the market place if they are stuck for some reason.
|
||||
|
||||
Only use this if you have to, otherwise things could break"""
|
||||
try:
|
||||
self.inmarket.remove(user.id)
|
||||
except ValueError:
|
||||
return await ctx.send("The user is not in the marketplace")
|
||||
await ctx.tick()
|
||||
|
||||
@evolution.command()
|
||||
async def start(self, ctx):
|
||||
"""Start your adventure..."""
|
||||
# No locks are needed here because they are all being used with values that don't change,
|
||||
# or shouldn't be changing at the moment
|
||||
animal = await self.conf.user(ctx.author).animal()
|
||||
if animal != "":
|
||||
return await ctx.send("You have already started your evolution.")
|
||||
if animal == "P":
|
||||
return await ctx.send("You are starting your evolution.")
|
||||
async with self.lock:
|
||||
await self.conf.user(ctx.author).animal.set("P")
|
||||
await ctx.send(
|
||||
f"Hello there. Welcome to Evolution, where you can buy animals to earn credits for economy. What would you like your animals to be named (singular please)? Warning: this cannot be changed. Here is a list of the current available ones: `{'`, `'.join(ANIMALS)}`"
|
||||
)
|
||||
|
||||
def check(m):
|
||||
return (
|
||||
(m.author.id == ctx.author.id)
|
||||
and (m.channel.id == ctx.channel.id)
|
||||
and (m.content.lower() in ANIMALS)
|
||||
)
|
||||
|
||||
try:
|
||||
message = await self.bot.wait_for("message", check=check, timeout=30.0)
|
||||
except asyncio.TimeoutError:
|
||||
async with self.lock:
|
||||
await self.conf.user(ctx.author).animal.set("")
|
||||
return await ctx.send("Command timed out.")
|
||||
async with self.lock:
|
||||
async with self.conf.user(ctx.author).all() as data:
|
||||
data["animal"] = message.content.lower()
|
||||
data["animals"] = {1: 1}
|
||||
|
||||
self.cache[ctx.author.id] = data
|
||||
await ctx.send(
|
||||
f"Your animal has been set to {message.content}. You have been granted one to start."
|
||||
)
|
||||
|
||||
@evolution.group()
|
||||
async def market(self, ctx):
|
||||
"""Buy or sell animals from different sellers"""
|
||||
pass
|
||||
|
||||
@market.command(aliases=["shop"])
|
||||
async def store(
|
||||
self,
|
||||
ctx,
|
||||
level: Optional[int] = None,
|
||||
amount: Optional[int] = 1,
|
||||
skip_confirmation: Optional[bool] = False,
|
||||
):
|
||||
"""Buy animals from the always in-stock store.
|
||||
|
||||
While the store will always have animals for sale, you cannot buy above a certain level,
|
||||
and they will be for a higher price."""
|
||||
if level is None:
|
||||
if ctx.channel.permissions_for(ctx.guild.me).embed_links:
|
||||
return await self.shop(ctx)
|
||||
else:
|
||||
return await ctx.send(
|
||||
'I require the "Embed Links" permission to display the shop.'
|
||||
)
|
||||
if ctx.author.id in self.inmarket:
|
||||
return await ctx.send("Complete your current transaction or evolution first.")
|
||||
self.inmarket.append(ctx.author.id)
|
||||
async with self.lock:
|
||||
data = await self.conf.user(ctx.author).all()
|
||||
animals = data["animals"]
|
||||
bought = data["bought"]
|
||||
animal = data["animal"]
|
||||
multiplier = data["multiplier"]
|
||||
|
||||
if animal in ["", "P"]:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("Finish starting your evolution first")
|
||||
|
||||
highest = max(list(map(int, animals.keys())))
|
||||
prev = int(animals.get(str(level), 0))
|
||||
balance = await bank.get_balance(ctx.author)
|
||||
current_bought = int(bought.get(str(level), 0))
|
||||
price = self.utils.get_total_price(level, current_bought, amount)
|
||||
|
||||
e = math.ceil((multiplier - 1) * 5)
|
||||
|
||||
if balance < price:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send(f"You need {humanize_number(price)} credits for all of that!")
|
||||
if prev >= 6 + e:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("You have too many of those! Evolve some of them already.")
|
||||
if prev + amount > 6 + e:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("You'd have too many of those! Evolve some of them already.")
|
||||
if level < 1:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("Ya cant buy a negative level!")
|
||||
if amount < 1:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("Ya cant buy a negative amount!")
|
||||
if (level > int(highest) - 3) and (level > 1):
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("Please get higher animals to buy higher levels of them.")
|
||||
if level > 22:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("The highest level you can buy is level 22.")
|
||||
|
||||
if not skip_confirmation:
|
||||
m = await ctx.send(
|
||||
f"Are you sure you want to buy {amount} Level {str(level)} {animal}{'s' if amount != 1 else ''}? This will cost you {humanize_number(price)}."
|
||||
)
|
||||
await m.add_reaction("\N{WHITE HEAVY CHECK MARK}")
|
||||
await m.add_reaction("\N{CROSS MARK}")
|
||||
|
||||
def check(reaction, user):
|
||||
return (
|
||||
(user.id == ctx.author.id)
|
||||
and (str(reaction.emoji) in ["\N{WHITE HEAVY CHECK MARK}", "\N{CROSS MARK}"])
|
||||
and (reaction.message.id == m.id)
|
||||
)
|
||||
|
||||
try:
|
||||
reaction, user = await self.bot.wait_for("reaction_add", check=check, timeout=60.0)
|
||||
except asyncio.TimeoutError:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send(f"You left the {animal} shop without buying anything.")
|
||||
|
||||
if str(reaction.emoji) == "\N{CROSS MARK}":
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send(f"You left the {animal} shop without buying anything.")
|
||||
animals[str(level)] = prev + amount
|
||||
bought[level] = current_bought + 1
|
||||
|
||||
async with self.lock:
|
||||
async with self.conf.user(ctx.author).all() as data:
|
||||
data["animals"] = animals
|
||||
data["bought"] = bought
|
||||
|
||||
self.cache[ctx.author.id] = data
|
||||
|
||||
await bank.withdraw_credits(ctx.author, price)
|
||||
await ctx.send(
|
||||
box(
|
||||
f"[Transaction Complete]\nYou spent {humanize_number(price)} credits to buy {amount} Level {str(level)} {animal}{'s' if amount != 1 else ''}.",
|
||||
"css",
|
||||
)
|
||||
)
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
|
||||
async def shop(self, ctx, start_level: int = None):
|
||||
"""Friendlier menu for displaying the animals available at the store."""
|
||||
async with self.lock:
|
||||
data = await self.conf.user(ctx.author).all()
|
||||
animals = data["animals"]
|
||||
bought = data["bought"]
|
||||
animal = data["animal"]
|
||||
|
||||
if animal in ["", "P"]:
|
||||
return await ctx.send("Finish starting your evolution first")
|
||||
|
||||
embed_list = []
|
||||
for x in range(1, max(list(map(int, animals.keys()))) + 1):
|
||||
embed = discord.Embed(
|
||||
title=f"{animal.title()} Shop", description=f"Level {str(x)}", color=0xD2B48C
|
||||
)
|
||||
embed.add_field(name="You currently own", value=animals.get(str(x), 0))
|
||||
current = int(bought.get(str(x), 0))
|
||||
embed.add_field(name="You have bought", value=current)
|
||||
embed.add_field(
|
||||
name="Price", value=humanize_number(self.utils.get_total_price(int(x), current, 1))
|
||||
)
|
||||
last = 0
|
||||
chances = []
|
||||
try:
|
||||
for chance, value in self.utils.levels[int(x)].items():
|
||||
chances.append(f"{str(chance-last)}% chance to gain {str(value)}")
|
||||
last = chance
|
||||
except KeyError:
|
||||
chances = ["100% chance to gain 1000"]
|
||||
embed.add_field(name="Income", value="\n".join(chances))
|
||||
embed.add_field(
|
||||
name="Credit delay",
|
||||
value=humanize_timedelta(timedelta=timedelta(seconds=self.utils.delays[int(x)])),
|
||||
)
|
||||
embed_list.append(embed)
|
||||
|
||||
highest_level = max([int(a) for a in animals.keys() if int(animals[a]) > 0])
|
||||
highest_level -= 3
|
||||
if start_level and not (animals.get(str(start_level), False) is False):
|
||||
highest_level = start_level
|
||||
|
||||
highest_level -= 1
|
||||
|
||||
if highest_level < 0:
|
||||
highest_level = 0
|
||||
|
||||
controls = dict(DEFAULT_CONTROLS)
|
||||
controls["\N{MONEY BAG}"] = self.utils.shop_control_callback
|
||||
await menu(ctx, embed_list, controls, page=highest_level)
|
||||
|
||||
@market.command()
|
||||
async def daily(self, ctx):
|
||||
"""View the daily deals.
|
||||
|
||||
These will come at a lower price than the store, but can only be bought once per day.
|
||||
|
||||
Status guide:
|
||||
A: Available to be bought and put in backyard
|
||||
B: Already purchased
|
||||
S: Available to be bought, but will be put in stash because you either do not have the space for the, or above your level threshold
|
||||
"""
|
||||
async with self.lock:
|
||||
data = await self.conf.user(ctx.author).all()
|
||||
animals = data["animals"]
|
||||
animal = data["animal"]
|
||||
|
||||
if animal in ["", "P"]:
|
||||
return await ctx.send("Finish starting your evolution first")
|
||||
|
||||
multiplier = data["multiplier"]
|
||||
highest = max(list(map(int, animals.keys())))
|
||||
e = 6 + math.ceil((multiplier - 1) * 5)
|
||||
|
||||
display = []
|
||||
deals = await self.conf.daily()
|
||||
for did, deal in deals.items():
|
||||
status = ""
|
||||
amount = deal["details"]["amount"]
|
||||
level = deal["details"]["level"]
|
||||
if ctx.author.id in deal["bought"]:
|
||||
status = "[B]"
|
||||
elif (level > int(highest) - 3 and level != 1) or (
|
||||
amount + animals.get(str(level), 0) > e
|
||||
):
|
||||
status = "#S "
|
||||
else:
|
||||
status = " A "
|
||||
|
||||
price = self.utils.get_total_price(level, 0, amount, False) * 0.75
|
||||
|
||||
display.append(
|
||||
[
|
||||
did,
|
||||
status,
|
||||
humanize_number(price),
|
||||
f"{amount} Level {level} {animal}{'s' if amount != 1 else ''}",
|
||||
]
|
||||
)
|
||||
|
||||
message = await ctx.send(
|
||||
f"{box(tabulate(display, tablefmt='psql'), lang='css')}Would you like to buy any of these fine animals? Click the corresponding reaction below."
|
||||
)
|
||||
emojis = ReactionPredicate.NUMBER_EMOJIS[1:7]
|
||||
start_adding_reactions(message, emojis)
|
||||
|
||||
pred = ReactionPredicate.with_emojis(emojis, message, ctx.author)
|
||||
try:
|
||||
await self.bot.wait_for("reaction_add", check=pred, timeout=60.0)
|
||||
except asyncio.TimeoutError:
|
||||
return await ctx.send(
|
||||
"The vendor grew uncomfortable with you there, and told you to leave and come back later."
|
||||
)
|
||||
|
||||
if ctx.author.id in self.inmarket:
|
||||
return await ctx.send("Complete your current transaction or evolution first.")
|
||||
self.inmarket.append(ctx.author.id)
|
||||
buying = pred.result + 1
|
||||
|
||||
deal = deals[str(buying)]
|
||||
if ctx.author.id in deal["bought"]: # ;no
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send(
|
||||
"You already bought this deal. You cannot buy daily deals multiple times."
|
||||
)
|
||||
|
||||
level = deal["details"]["level"]
|
||||
amount = deal["details"]["amount"]
|
||||
|
||||
price = self.utils.get_total_price(level, 0, amount, False) * 0.75
|
||||
balance = await bank.get_balance(ctx.author)
|
||||
|
||||
if balance < price:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send(
|
||||
f"You need {humanize_number(price - balance)} more credits to buy that deal."
|
||||
)
|
||||
|
||||
stashing = 0
|
||||
delivering = amount
|
||||
if level > int(highest) - 3 and level != 1:
|
||||
stashing = amount
|
||||
delivering = 0
|
||||
elif amount + animals.get(str(level), 0) > e:
|
||||
delivering = e - animals[str(level)]
|
||||
stashing = amount - delivering
|
||||
|
||||
async with self.lock:
|
||||
async with self.conf.user(ctx.author).all() as data:
|
||||
data["animals"][str(level)] = animals.get(str(level), 0) + delivering
|
||||
|
||||
if stashing:
|
||||
current_stash = data["stash"]["animals"].get(str(level), 0)
|
||||
data["stash"]["animals"][str(level)] = current_stash + stashing
|
||||
|
||||
self.cache[ctx.author.id] = data
|
||||
async with self.conf.daily() as data: # In case someone buys at the same time, we need to re-read the data
|
||||
data[str(buying)]["bought"].append(ctx.author.id)
|
||||
|
||||
await bank.withdraw_credits(ctx.author, int(price))
|
||||
await ctx.send(
|
||||
box(
|
||||
(
|
||||
f"[Transaction Complete]\nYou spent {humanize_number(price)} credits to buy {amount} Level {str(level)} {animal}{'s' if amount != 1 else ''}."
|
||||
f"\n\n{delivering} have been added to your backyard, {stashing} have been sent to your stash."
|
||||
),
|
||||
"css",
|
||||
)
|
||||
)
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
|
||||
@evolution.group()
|
||||
async def stash(self, ctx):
|
||||
"""Where your special animals are put if you cannot hold them in your backyard"""
|
||||
if not ctx.invoked_subcommand:
|
||||
await ctx.invoke(self.view)
|
||||
|
||||
@stash.command()
|
||||
async def view(self, ctx):
|
||||
"""View the animals and perks you have in your stash"""
|
||||
async with self.lock:
|
||||
data = await self.conf.user(ctx.author).all()
|
||||
|
||||
animal = data["animal"]
|
||||
|
||||
if animal in ["", "P"]:
|
||||
return await ctx.send("Finish starting your evolution first")
|
||||
|
||||
if await ctx.embed_requested():
|
||||
embed = discord.Embed(
|
||||
title=f"{ctx.author.display_name}'s stash",
|
||||
description=(
|
||||
"Animals/perks in your stash have no impact on you. "
|
||||
"They are here because you could not hold them at the time you picked up the items, or required approval."
|
||||
),
|
||||
color=0xD2B48C,
|
||||
)
|
||||
asv = ""
|
||||
if not data["stash"]["animals"]:
|
||||
asv = inline("You do not have any animals in your stash.")
|
||||
else:
|
||||
for level, amount in data["stash"]["animals"].items():
|
||||
asv += f"{humanize_number(amount)} Level {level} animal{'s' if amount != 1 else ''}\n"
|
||||
embed.add_field(name="Animal Stash", value=asv)
|
||||
|
||||
psv = ""
|
||||
if not data["stash"]["perks"]:
|
||||
psv = inline("You do not have any perks in your stash.")
|
||||
else:
|
||||
pass
|
||||
# for level, amount in data["stash"]["perks"].items():
|
||||
# asv += f"{humanize_number(amount)} Level {level} animal{'s' if amount != 1 else ''}\n"
|
||||
embed.add_field(name="Perk Stash", value=psv)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@stash.group()
|
||||
async def claim(self, ctx):
|
||||
"""Claim animals or perks from your stash."""
|
||||
|
||||
@claim.command()
|
||||
async def animal(self, ctx, level: int):
|
||||
"""Claim animals from your stash"""
|
||||
async with self.lock:
|
||||
data = await self.conf.user(ctx.author).all()
|
||||
|
||||
animal = data["animal"]
|
||||
|
||||
if animal in ["", "P"]:
|
||||
return await ctx.send("Finish starting your evolution first")
|
||||
|
||||
animals = data["animals"]
|
||||
stash = data["stash"]
|
||||
multiplier = data["multiplier"]
|
||||
highest = max(list(map(int, animals.keys())))
|
||||
e = 6 + math.ceil((multiplier - 1) * 5)
|
||||
|
||||
try:
|
||||
level = int(level)
|
||||
except ValueError:
|
||||
return await ctx.send("Invalid level; please supply a number.")
|
||||
|
||||
if level > 25 or level < 1:
|
||||
return await ctx.send("Invalid level; level cannot be above 25 or below 1.")
|
||||
|
||||
try:
|
||||
amount = stash["animals"][str(level)]
|
||||
assert amount != 0
|
||||
except (KeyError, AssertionError):
|
||||
return await ctx.send("You don't have any animals at that level in your stash.")
|
||||
|
||||
if level > int(highest) - 3 and level != 1:
|
||||
return await ctx.send(
|
||||
"You are not of a required level to claim those animals from stash. Cancelled."
|
||||
)
|
||||
|
||||
if animals.get(str(level), 0) == e:
|
||||
return await ctx.send(
|
||||
f"You already have the max amount of Level {level} animals in your backyard. Cancelled."
|
||||
)
|
||||
|
||||
async with self.lock:
|
||||
async with self.conf.user(ctx.author).all() as new_data:
|
||||
current = new_data["animals"].get(str(level), 0)
|
||||
amount = new_data["stash"]["animals"][str(level)]
|
||||
claiming = min([e - current, amount])
|
||||
|
||||
full = True
|
||||
if claiming != amount:
|
||||
full = False
|
||||
|
||||
new_data["animals"][str(level)] = current + claiming
|
||||
if amount - claiming == 0:
|
||||
del new_data["stash"]["animals"][str(level)]
|
||||
else:
|
||||
new_data["stash"]["animals"][str(level)] = amount - claiming
|
||||
|
||||
self.cache[ctx.author.id] = new_data
|
||||
extra = ""
|
||||
if not full:
|
||||
extra = f"There are still {amount - claiming} {animal}{'s' if claiming != 1 else ''} left in your Level {level} stash."
|
||||
await ctx.send(
|
||||
f"Successfully moved {claiming} {animal}{'s' if claiming != 1 else ''} from your stash to your backyard. {extra}"
|
||||
)
|
||||
|
||||
@claim.command(hidden=True)
|
||||
async def perk(self, ctx, *, name: str):
|
||||
"""Claim a perk from your stash"""
|
||||
return await ctx.send("This command is not available. Check back soon!")
|
||||
|
||||
@commands.bot_has_permissions(embed_links=True)
|
||||
@evolution.command(aliases=["by"])
|
||||
async def backyard(self, ctx, use_menu: bool = False):
|
||||
"""Where ya animals live! Pass 1 or true to put it in a menu."""
|
||||
async with self.lock:
|
||||
data = await self.conf.user(ctx.author).all()
|
||||
animal = data["animal"]
|
||||
animals = data["animals"]
|
||||
multiplier = data["multiplier"]
|
||||
e = 6 + math.ceil((multiplier - 1) * 5)
|
||||
|
||||
if animal in ["", "P"]:
|
||||
return await ctx.send("Finish starting your evolution first")
|
||||
|
||||
if use_menu:
|
||||
embed_list = []
|
||||
for level, amount in animals.items():
|
||||
if amount == 0:
|
||||
continue
|
||||
embed = discord.Embed(
|
||||
title=f"Level {str(level)} {animal}",
|
||||
description=f"You have {str(amount)} Level {level} {animal}{'s' if amount != 1 else ''}",
|
||||
color=0xD2B48C,
|
||||
)
|
||||
embed.set_thumbnail(url=IMAGES[animal])
|
||||
embed_list.append(embed)
|
||||
await menu(ctx, embed_list, DEFAULT_CONTROLS)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title=f"The amount of {animal}s you have in your backyard.",
|
||||
color=0xD2B48C,
|
||||
description=f"Multiplier: {inline(str(multiplier))}\nMax amount of animals: {inline(str(e))}",
|
||||
)
|
||||
embed.set_thumbnail(url=IMAGES[animal])
|
||||
animals = {k: v for k, v in sorted(animals.items(), key=lambda x: int(x[0]))}
|
||||
for level, amount in animals.items():
|
||||
if amount == 0:
|
||||
continue
|
||||
embed.add_field(
|
||||
name=f"Level {str(level)} {animal}",
|
||||
value=f"You have {str(amount)} Level {level} {animal}{'s' if amount != 1 else ''} \N{ZERO WIDTH SPACE} \N{ZERO WIDTH SPACE}",
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@evolution.command()
|
||||
async def evolve(self, ctx, level: int, amount: int = 1):
|
||||
"""Evolve them animals to get more of da economy credits"""
|
||||
if ctx.author.id in self.inmarket:
|
||||
return await ctx.send("Complete your current transaction or evolution first.")
|
||||
self.inmarket.append(ctx.author.id)
|
||||
if level < 1 or amount < 1:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("Too low!")
|
||||
|
||||
async with self.lock:
|
||||
data = await self.conf.user(ctx.author).all()
|
||||
animal = data["animal"]
|
||||
animals = data["animals"]
|
||||
multiplier = data["multiplier"]
|
||||
|
||||
e = math.ceil((multiplier - 1) * 5)
|
||||
|
||||
if amount > (6 + e) // 2:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("Too high!")
|
||||
|
||||
if animal in ["", "P"]:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("Finish starting your evolution first")
|
||||
|
||||
current = animals.get(str(level), 0)
|
||||
highest = max(list(map(int, animals.keys())))
|
||||
nextlevel = animals.get(str(level + 1), 0)
|
||||
|
||||
if current < (amount * 2):
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send("You don't have enough animals at that level.")
|
||||
|
||||
if nextlevel + amount > 6 + e:
|
||||
self.inmarket.remove(ctx.author.id)
|
||||
return await ctx.send(
|
||||
f"You'd have too many Level {str(level + 1)}s! Evolve some of them instead!"
|
||||
)
|
||||
|
||||
found_new = False
|
||||
recreate = False
|
||||
currentlevelstr = str(level)
|
||||
nextlevelstr = str(level + 1)
|
||||
|
||||
if level < 11:
|
||||
number = random.randint(1, 100)
|
||||
elif level < 21:
|
||||
number = random.randint(1, 1000)
|
||||
else:
|
||||
number = random.randint(1, 10000)
|
||||
if number == 1:
|
||||
# Evolution is going to fail
|
||||
number = random.randint(1, 10)
|
||||
extra = f"Your {animal}s were successfully recovered however."
|
||||
if number != 1:
|
||||
animals[currentlevelstr] -= 2 * amount
|
||||
extra = f"Your {animal}s were unable to be recovered."
|
||||
await ctx.send(
|
||||
box(
|
||||
(
|
||||
f"Evolution [Failed]\n\nFailed to convert {str(amount * 2)} Level {currentlevelstr} {animal}s "
|
||||
f"into {str(amount)} Level {nextlevelstr} {animal}{'s'if amount != 1 else ''}. {extra}"
|
||||
),
|
||||
lang="css",
|
||||
)
|
||||
)
|
||||
else:
|
||||
animals[currentlevelstr] -= 2 * amount
|
||||
if highest == level:
|
||||
found_new = True
|
||||
animals[nextlevelstr] = animals.get(nextlevelstr, 0) + amount
|
||||
if level + 1 == 26:
|
||||
recreate = True
|
||||
|
||||
if found_new:
|
||||
sending = "CONGRATULATIONS! You have found a new animal!"
|
||||
else:
|
||||
sending = ""
|
||||
await ctx.send(
|
||||
box(
|
||||
(
|
||||
f"Evolution #Successful\n\nSuccessfully converted {str(amount * 2)} Level {currentlevelstr} {animal}s "
|
||||
f"into {str(amount)} Level {nextlevelstr} {animal}{'s' if amount != 1 else ''}.\n\n{sending}"
|
||||
),
|
||||
lang="css",
|
||||
)
|
||||
)
|
||||
if recreate:
|
||||
async with self.lock:
|
||||
async with self.conf.user(ctx.author).all() as data:
|
||||
multiplier = data["multiplier"]
|
||||
data["animals"] = {1: 1}
|
||||
data["multiplier"] = multiplier + 0.2
|
||||
new = (
|
||||
"**Report:**\n"
|
||||
f"**To:** {ctx.author.display_name}\n"
|
||||
f"**Concerning:** Animal experiment #{str(math.ceil(((multiplier - 1) * 5) + 1))}\n"
|
||||
f"**Subject:** Animal experiment concluded.\n\n"
|
||||
f"Congratulations, {ctx.author.display_name}! You have successfully combined enough animals to reach a Level 26 Animal! This means that it is time to recreate universe! This will reset your bank account, remove all of your animals, but allow one more animal of every level, and give you an extra 20% income rate for the next universe from all income. Congratulations!\n\n"
|
||||
f"From, The Head {animal.title()}"
|
||||
)
|
||||
await ctx.send(new)
|
||||
await bank.set_balance(ctx.author, 0)
|
||||
else:
|
||||
async with self.lock:
|
||||
await self.conf.user(ctx.author).animals.set(animals)
|
||||
self.inmarket.remove(ctx.author.id)
|
16
evolution/info.json
Normal file
16
evolution/info.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"author": [
|
||||
"Neuro Assassin"
|
||||
],
|
||||
"install_msg": "Thank you for downloading this cog. This cog requires for the bank to be global in order to be used.",
|
||||
"name": "evolution",
|
||||
"short": "Buy and get animals to get more economy credits!",
|
||||
"description": "Buy animals using economy credits or get them every 10 minutes, and gain a certain amount of credits every minute!",
|
||||
"tags": [
|
||||
"fun"
|
||||
],
|
||||
"requirements": [
|
||||
"tabulate"
|
||||
],
|
||||
"hidden": false
|
||||
}
|
117
evolution/tasks.py
Normal file
117
evolution/tasks.py
Normal file
|
@ -0,0 +1,117 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import contextlib
|
||||
import random
|
||||
import time
|
||||
from typing import TYPE_CHECKING, Dict
|
||||
|
||||
from redbot.core import Config
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.utils import AsyncIter
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .evolution import Evolution
|
||||
|
||||
from . import bank
|
||||
|
||||
|
||||
class EvolutionTaskManager:
|
||||
def __init__(self, cog):
|
||||
self.bot: Red = cog.bot
|
||||
self.conf: Config = cog.conf
|
||||
self.cog: Evolution = cog
|
||||
|
||||
self.tasks: Dict[str, asyncio.Task] = {}
|
||||
|
||||
async def process_credits(self, data, ct, timedata):
|
||||
all_gaining = 0
|
||||
async for key, value in AsyncIter(data.items()):
|
||||
last_processed = timedata[str(key)]
|
||||
if ct > last_processed + self.cog.utils.delays[int(key)]:
|
||||
for x in range(0, value):
|
||||
chance = random.randint(1, 100)
|
||||
chances = list(self.cog.utils.levels[int(key)].keys())
|
||||
chosen = min([c for c in chances if chance <= c])
|
||||
gaining = self.cog.utils.levels[int(key)][chosen]
|
||||
all_gaining += gaining
|
||||
return all_gaining
|
||||
|
||||
async def process_times(self, ct, timedata):
|
||||
async for key in AsyncIter(range(1, 26)):
|
||||
last_processed = timedata[str(key)]
|
||||
if ct > last_processed + self.cog.utils.delays[int(key)]:
|
||||
timedata[str(key)] = ct
|
||||
return timedata
|
||||
|
||||
async def income_task(self):
|
||||
await self.bot.wait_until_ready()
|
||||
while True:
|
||||
# First, process the credits being added
|
||||
bulk_edit = {}
|
||||
ct = time.time()
|
||||
lastcredited = await self.cog.conf.lastcredited()
|
||||
async for userid, data in AsyncIter(self.cog.cache.copy().items()):
|
||||
animal = data["animal"]
|
||||
if animal == "":
|
||||
continue
|
||||
multiplier = data["multiplier"]
|
||||
animals = data["animals"]
|
||||
gaining = await self.process_credits(animals, ct, lastcredited) * multiplier
|
||||
bulk_edit[str(userid)] = gaining
|
||||
|
||||
# Credit to aikaterna's seen cog for this bulk write
|
||||
config = bank._get_config()
|
||||
users = config._get_base_group(config.USER)
|
||||
max_credits = await bank.get_max_balance()
|
||||
async with users.all() as new_data:
|
||||
for user_id, userdata in bulk_edit.items():
|
||||
if str(user_id) not in new_data:
|
||||
new_data[str(user_id)] = {"balance": userdata}
|
||||
continue
|
||||
if new_data[str(user_id)]["balance"] + userdata > max_credits:
|
||||
new_data[str(user_id)]["balance"] = int(max_credits)
|
||||
else:
|
||||
new_data[str(user_id)]["balance"] = int(
|
||||
new_data[str(user_id)]["balance"] + userdata
|
||||
)
|
||||
|
||||
await self.cog.conf.lastcredited.set(await self.process_times(ct, lastcredited))
|
||||
await asyncio.sleep(60)
|
||||
|
||||
async def daily_task(self):
|
||||
await self.bot.wait_until_ready()
|
||||
while True:
|
||||
lastdailyupdate = await self.cog.conf.lastdailyupdate()
|
||||
if lastdailyupdate + 86400 <= time.time():
|
||||
deals = {}
|
||||
levels = random.sample(
|
||||
self.cog.utils.randlvl_chances, len(self.cog.utils.randlvl_chances)
|
||||
)
|
||||
amounts = random.sample(
|
||||
self.cog.utils.randamt_chances, len(self.cog.utils.randamt_chances)
|
||||
)
|
||||
for x in range(1, 7):
|
||||
level = random.choice(levels)
|
||||
amount = random.choice(amounts)
|
||||
deals[str(x)] = {"details": {"level": level, "amount": amount}, "bought": []}
|
||||
await self.cog.conf.daily.set(deals)
|
||||
await self.cog.conf.lastdailyupdate.set(time.time())
|
||||
await asyncio.sleep(300)
|
||||
|
||||
def get_statuses(self):
|
||||
returning = {}
|
||||
for task, obj in self.tasks.items():
|
||||
exc = None
|
||||
with contextlib.suppress(asyncio.exceptions.InvalidStateError):
|
||||
exc = obj.exception()
|
||||
returning[task] = {"state": obj._state, "exc": exc}
|
||||
return returning
|
||||
|
||||
def init_tasks(self):
|
||||
self.tasks["income"] = self.bot.loop.create_task(self.income_task())
|
||||
self.tasks["daily"] = self.bot.loop.create_task(self.daily_task())
|
||||
|
||||
def shutdown(self):
|
||||
for task in self.tasks.values():
|
||||
task.cancel()
|
211
evolution/utils.py
Normal file
211
evolution/utils.py
Normal file
|
@ -0,0 +1,211 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import traceback
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from redbot.core import Config
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.utils.menus import menu
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .evolution import Evolution
|
||||
|
||||
|
||||
class EvolutionUtils:
|
||||
def __init__(self, cog):
|
||||
self.bot: Red = cog.bot
|
||||
self.conf: Config = cog.conf
|
||||
self.cog: Evolution = cog
|
||||
|
||||
@staticmethod
|
||||
def get_total_price(level, bought, amount, bt=True):
|
||||
total = 0
|
||||
for x in range(amount):
|
||||
normal = level * 800
|
||||
level_tax = ((2**level) * 10) - 200
|
||||
if bt:
|
||||
tax = bought * 300
|
||||
extra = x * 300
|
||||
else:
|
||||
tax = 0
|
||||
extra = 0
|
||||
total += normal + level_tax + tax + extra
|
||||
return total
|
||||
|
||||
@property
|
||||
def levels(self):
|
||||
return {
|
||||
1: {100: 10},
|
||||
2: {90: 10, 100: 100},
|
||||
3: {80: 10, 100: 100},
|
||||
4: {70: 10, 100: 100},
|
||||
5: {60: 10, 100: 100},
|
||||
6: {50: 10, 90: 100, 100: 1000},
|
||||
7: {40: 10, 80: 100, 100: 1000},
|
||||
8: {30: 10, 70: 100, 100: 1000},
|
||||
9: {20: 10, 60: 100, 100: 1000},
|
||||
10: {10: 10, 50: 100, 100: 1000},
|
||||
11: {40: 100, 90: 1000, 100: 1500},
|
||||
12: {30: 100, 80: 1000, 100: 1500},
|
||||
13: {20: 100, 70: 1000, 100: 1500},
|
||||
14: {10: 100, 60: 1000, 100: 1500},
|
||||
15: {50: 1000, 100: 1500},
|
||||
16: {40: 1000, 100: 1500},
|
||||
17: {30: 1000, 100: 1500},
|
||||
18: {20: 1000, 100: 1500},
|
||||
19: {10: 1000, 100: 1500},
|
||||
20: {90: 1500, 100: 2000},
|
||||
21: {80: 1500, 100: 2000},
|
||||
22: {70: 1500, 100: 2000},
|
||||
23: {60: 1500, 100: 2000},
|
||||
24: {50: 1500, 100: 2000},
|
||||
25: {100: 2000},
|
||||
}
|
||||
|
||||
@property
|
||||
def delays(self):
|
||||
return {
|
||||
1: 86400, # 24 hours
|
||||
2: 64800, # 18 hours
|
||||
3: 43200, # 12 hours
|
||||
4: 39600, # 11 hours
|
||||
5: 36000, # 10 hours
|
||||
6: 32400, # 9 hours
|
||||
7: 28800, # 8 hours
|
||||
8: 25200, # 7 hours
|
||||
9: 21600, # 6 hours
|
||||
10: 18000, # 5 hours
|
||||
11: 14400, # 4 hours
|
||||
12: 10800, # 3 hours
|
||||
13: 7200, # 2 hours
|
||||
14: 3600, # 1 hour
|
||||
15: 3000, # 50 minutes
|
||||
16: 2400, # 40 minutes
|
||||
17: 1800, # 30 minutes
|
||||
18: 1200, # 20 minutes
|
||||
19: 600, # 10 minutes
|
||||
20: 420, # 7 minutes
|
||||
21: 300, # 5 minutes
|
||||
22: 240, # 4 minutes
|
||||
23: 180, # 3 minutes
|
||||
24: 120, # 2 minutes
|
||||
25: 60, # 1 minute
|
||||
26: 60, # 1 minute (Just in case)
|
||||
}
|
||||
|
||||
@property
|
||||
def randlvl_chances(self):
|
||||
return [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
4,
|
||||
5,
|
||||
5,
|
||||
5,
|
||||
6,
|
||||
6,
|
||||
6,
|
||||
6,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
8,
|
||||
8,
|
||||
8,
|
||||
8,
|
||||
9,
|
||||
9,
|
||||
9,
|
||||
9,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
11,
|
||||
11,
|
||||
11,
|
||||
11,
|
||||
11,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
13,
|
||||
13,
|
||||
13,
|
||||
13,
|
||||
13,
|
||||
14,
|
||||
14,
|
||||
14,
|
||||
14,
|
||||
14,
|
||||
15,
|
||||
15,
|
||||
15,
|
||||
15,
|
||||
16,
|
||||
16,
|
||||
16,
|
||||
17,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
]
|
||||
|
||||
@property
|
||||
def randamt_chances(self):
|
||||
return [1, 1, 2, 2, 2, 3, 3, 3, 4, 5]
|
||||
|
||||
async def shop_control_callback(self, ctx, pages, controls, message, page, timeout, emoji):
|
||||
description = message.embeds[0].description
|
||||
level = int(description.split(" ")[1])
|
||||
self.bot.loop.create_task(ctx.invoke(self.cog.store, level=level))
|
||||
return await menu(ctx, pages, controls, message=message, page=page, timeout=timeout)
|
||||
|
||||
def format_task(self, task):
|
||||
state = task["state"].lower()
|
||||
if task["exc"]:
|
||||
e = task["exc"]
|
||||
exc = traceback.format_exception(type(e), e, e.__traceback__)
|
||||
exc_output = (
|
||||
f"Please report the following error to Neuro Assassin: ```py\n{''.join(exc)}```"
|
||||
)
|
||||
else:
|
||||
exc_output = "No error has been encountered."
|
||||
return f"Task is currently {state}. {exc_output}"
|
||||
|
||||
def init_config(self):
|
||||
default_user = {
|
||||
"animal": "",
|
||||
"animals": {},
|
||||
"multiplier": 1.0,
|
||||
"bought": {},
|
||||
"stash": {"animals": {}, "perks": {}},
|
||||
}
|
||||
default_guild = {"cartchannel": 0, "last": 0}
|
||||
default_global = {
|
||||
"travelercooldown": "2h",
|
||||
"lastcredited": {},
|
||||
"lastdailyupdate": 0,
|
||||
"daily": {},
|
||||
}
|
||||
for x in range(1, 27):
|
||||
default_global["lastcredited"][str(x)] = 0
|
||||
|
||||
self.conf.register_user(**default_user)
|
||||
self.conf.register_guild(**default_guild)
|
||||
self.conf.register_global(**default_global)
|
||||
|
||||
async def initialize(self):
|
||||
config = await self.cog.conf.all_users()
|
||||
for k, v in config.items():
|
||||
self.cog.cache[k] = v
|
94
extendedeconomy/README.md
Normal file
94
extendedeconomy/README.md
Normal file
|
@ -0,0 +1,94 @@
|
|||
Set prices for commands, customize how prices are applied, log bank events and more!
|
||||
|
||||
# [p]bankpie
|
||||
View a pie chart of the top X bank balances.<br/>
|
||||
- Usage: `[p]bankpie [amount=10]`
|
||||
# [p]extendedeconomy
|
||||
Extended Economy settings<br/>
|
||||
|
||||
**NOTE**<br/>
|
||||
Although setting prices for pure slash commands works, there is no refund mechanism in place for them.<br/>
|
||||
|
||||
Should a hybrid or text command fail due to an unhandled exception, the user will be refunded.<br/>
|
||||
- Usage: `[p]extendedeconomy`
|
||||
- Restricted to: `ADMIN`
|
||||
- Aliases: `ecoset and exteco`
|
||||
- Checks: `server_only`
|
||||
## [p]extendedeconomy resetcooldown
|
||||
Reset the payday cooldown for a user<br/>
|
||||
- Usage: `[p]extendedeconomy resetcooldown <member>`
|
||||
## [p]extendedeconomy stackpaydays
|
||||
Toggle whether payday roles stack or not<br/>
|
||||
- Usage: `[p]extendedeconomy stackpaydays`
|
||||
- Aliases: `stackpayday`
|
||||
## [p]extendedeconomy autopaydayrole
|
||||
Add/Remove auto payday roles<br/>
|
||||
- Usage: `[p]extendedeconomy autopaydayrole <role>`
|
||||
## [p]extendedeconomy view
|
||||
View the current settings<br/>
|
||||
- Usage: `[p]extendedeconomy view`
|
||||
## [p]extendedeconomy transfertax
|
||||
Set the transfer tax percentage as a decimal<br/>
|
||||
|
||||
*Example: `0.05` is for 5% tax*<br/>
|
||||
|
||||
- Set to 0 to disable<br/>
|
||||
- Default is 0<br/>
|
||||
- Usage: `[p]extendedeconomy transfertax <tax>`
|
||||
## [p]extendedeconomy mainlog
|
||||
Set the main log channel<br/>
|
||||
- Usage: `[p]extendedeconomy mainlog [channel=None]`
|
||||
## [p]extendedeconomy autopayday
|
||||
Toggle whether paydays are claimed automatically (Global bank)<br/>
|
||||
- Usage: `[p]extendedeconomy autopayday`
|
||||
- Restricted to: `BOT_OWNER`
|
||||
## [p]extendedeconomy eventlog
|
||||
Set an event log channel<br/>
|
||||
|
||||
**Events:**<br/>
|
||||
- set_balance<br/>
|
||||
- transfer_credits<br/>
|
||||
- bank_wipe<br/>
|
||||
- prune<br/>
|
||||
- set_global<br/>
|
||||
- payday_claim<br/>
|
||||
- Usage: `[p]extendedeconomy eventlog <event> [channel=None]`
|
||||
## [p]extendedeconomy rolebonus
|
||||
Add/Remove Payday role bonuses<br/>
|
||||
|
||||
Example: `[p]ecoset rolebonus @role 0.1` - Adds a 10% bonus to the user's payday if they have the role.<br/>
|
||||
|
||||
To remove a bonus, set the bonus to 0.<br/>
|
||||
- Usage: `[p]extendedeconomy rolebonus <role> <bonus>`
|
||||
## [p]extendedeconomy autoclaimchannel
|
||||
Set the auto claim channel<br/>
|
||||
- Usage: `[p]extendedeconomy autoclaimchannel [channel]`
|
||||
## [p]extendedeconomy deleteafter
|
||||
Set the delete after time for cost check messages<br/>
|
||||
|
||||
- Set to 0 to disable (Recommended for public bots)<br/>
|
||||
- Default is 0 (disabled)<br/>
|
||||
- Usage: `[p]extendedeconomy deleteafter <seconds>`
|
||||
- Restricted to: `BOT_OWNER`
|
||||
# [p]addcost
|
||||
Add a cost to a command<br/>
|
||||
- Usage: `[p]addcost [command=] [cost=0] [duration=3600] [level=all] [prompt=notify] [modifier=static] [value=0.0]`
|
||||
- Restricted to: `ADMIN`
|
||||
- Checks: `server_only`
|
||||
# [p]banksetrole
|
||||
Set the balance of all user accounts that have a specific role<br/>
|
||||
|
||||
Putting + or - signs before the amount will add/remove currency on the user's bank account instead.<br/>
|
||||
|
||||
Examples:<br/>
|
||||
- `[p]banksetrole @everyone 420` - Sets everyones balance to 420<br/>
|
||||
- `[p]banksetrole @role +69` - Increases balance by 69 for everyone with the role<br/>
|
||||
- `[p]banksetrole @role -42` - Decreases balance by 42 for everyone with the role<br/>
|
||||
|
||||
**Arguments**<br/>
|
||||
|
||||
- `<role>` The role to set the currency of for each user that has it.<br/>
|
||||
- `<creds>` The amount of currency to set their balance to.<br/>
|
||||
- Usage: `[p]banksetrole <role> <creds>`
|
||||
- Restricted to: `ADMIN`
|
||||
- Checks: `is_owner_if_bank_global`
|
11
extendedeconomy/__init__.py
Normal file
11
extendedeconomy/__init__.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from redbot.core.bot import Red
|
||||
from redbot.core.utils import get_end_user_data_statement
|
||||
|
||||
from .main import ExtendedEconomy
|
||||
|
||||
__red_end_user_data_statement__ = get_end_user_data_statement(__file__)
|
||||
|
||||
|
||||
async def setup(bot: Red):
|
||||
cog = ExtendedEconomy(bot)
|
||||
await bot.add_cog(cog)
|
46
extendedeconomy/abc.py
Normal file
46
extendedeconomy/abc.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
import typing as t
|
||||
from abc import ABC, ABCMeta, abstractmethod
|
||||
|
||||
import discord
|
||||
from discord.ext.commands.cog import CogMeta
|
||||
from redbot.core import commands
|
||||
from redbot.core.bot import Red
|
||||
|
||||
from .common.models import DB
|
||||
|
||||
|
||||
class CompositeMetaClass(CogMeta, ABCMeta):
|
||||
"""Type detection"""
|
||||
|
||||
|
||||
class MixinMeta(ABC):
|
||||
"""Type hinting"""
|
||||
|
||||
def __init__(self, *_args):
|
||||
self.bot: Red
|
||||
self.db: DB
|
||||
|
||||
self.checks: set
|
||||
self.charged: t.Dict[str, int]
|
||||
|
||||
self.payday_callback: t.Optional[t.Callable]
|
||||
|
||||
@abstractmethod
|
||||
async def save(self) -> None:
|
||||
raise NotImplementedError()
|
||||
|
||||
@abstractmethod
|
||||
async def cost_check(self, ctx: commands.Context):
|
||||
raise NotImplementedError()
|
||||
|
||||
@abstractmethod
|
||||
async def slash_cost_check(self, interaction: discord.Interaction):
|
||||
raise NotImplementedError()
|
||||
|
||||
@abstractmethod
|
||||
async def transfer_tax_check(self, ctx: commands.Context):
|
||||
raise NotImplementedError()
|
||||
|
||||
@abstractmethod
|
||||
async def send_payloads(self):
|
||||
raise NotImplementedError()
|
7
extendedeconomy/commands/__init__.py
Normal file
7
extendedeconomy/commands/__init__.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from ..abc import CompositeMetaClass
|
||||
from .admin import Admin
|
||||
from .user import User
|
||||
|
||||
|
||||
class Commands(Admin, User, metaclass=CompositeMetaClass):
|
||||
"""Subclass all command classes"""
|
783
extendedeconomy/commands/admin.py
Normal file
783
extendedeconomy/commands/admin.py
Normal file
|
@ -0,0 +1,783 @@
|
|||
import calendar
|
||||
import io
|
||||
import logging
|
||||
import typing as t
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import discord
|
||||
from discord import app_commands
|
||||
from redbot.core import Config, bank, commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import humanize_number, humanize_timedelta
|
||||
|
||||
from ..abc import MixinMeta
|
||||
from ..common.models import CommandCost
|
||||
from ..common.parser import SetParser
|
||||
from ..views.confirm import ConfirmView
|
||||
from ..views.cost_menu import CostMenu
|
||||
|
||||
log = logging.getLogger("red.vrt.extendedeconomy.admin")
|
||||
_ = Translator("ExtendedEconomy", __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Admin(MixinMeta):
|
||||
@commands.group(aliases=["ecoset", "exteco"])
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@commands.guild_only()
|
||||
async def extendedeconomy(self, ctx: commands.Context):
|
||||
"""
|
||||
Extended Economy settings
|
||||
|
||||
**NOTE**
|
||||
Although setting prices for pure slash commands works, there is no refund mechanism in place for them.
|
||||
|
||||
Should a hybrid or text command fail due to an unhandled exception, the user will be refunded.
|
||||
"""
|
||||
pass
|
||||
|
||||
@extendedeconomy.command(name="diagnose", hidden=True)
|
||||
@commands.guildowner()
|
||||
async def diagnose_issues(self, ctx: commands.Context, *, member: discord.Member):
|
||||
"""
|
||||
Diagnose issues with the cog for a user
|
||||
"""
|
||||
eco = self.bot.get_cog("Economy")
|
||||
is_global = await bank.is_global()
|
||||
|
||||
txt = _("**Global Bank:** `{}`\n").format(is_global)
|
||||
txt += _("**Economy Cog:** `{}`\n").format(_("Loaded") if eco else _("Not Loaded"))
|
||||
txt += _("**Auto Paydays:** `{}`\n").format(self.db.auto_payday_claim)
|
||||
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
if not is_global:
|
||||
txt += _("**Auto Payday Roles:** {}\n").format(
|
||||
", ".join([f"<@&{x}>" for x in conf.auto_claim_roles]) if conf.auto_claim_roles else _("None")
|
||||
)
|
||||
|
||||
cur_time = calendar.timegm(datetime.now(tz=timezone.utc).utctimetuple())
|
||||
|
||||
eco_conf: Config = eco.config
|
||||
if is_global:
|
||||
bankgroup = bank._config._get_base_group(bank._config.USER)
|
||||
ecogroup = eco_conf._get_base_group(eco_conf.USER)
|
||||
accounts: t.Dict[str, dict] = await bankgroup.all()
|
||||
ecousers: t.Dict[str, dict] = await ecogroup.all()
|
||||
# max_bal = await bank.get_max_balance()
|
||||
payday_time = await eco_conf.PAYDAY_TIME()
|
||||
# payday_credits = await eco_conf.PAYDAY_CREDITS()
|
||||
else:
|
||||
bankgroup = bank._config._get_base_group(bank._config.MEMBER, str(ctx.guild.id))
|
||||
ecogroup = eco_conf._get_base_group(eco_conf.MEMBER, str(ctx.guild.id))
|
||||
accounts: t.Dict[str, dict] = await bankgroup.all()
|
||||
ecousers: t.Dict[str, dict] = await ecogroup.all()
|
||||
# max_bal = await bank.get_max_balance(ctx.guild)
|
||||
payday_time = await eco_conf.guild(ctx.guild).PAYDAY_TIME()
|
||||
# payday_credits = await eco_conf.guild(ctx.guild).PAYDAY_CREDITS()
|
||||
# payday_roles: t.Dict[int, dict] = await eco_conf.all_roles()
|
||||
|
||||
uid = str(member.id)
|
||||
if uid not in accounts:
|
||||
txt += _("- {} has not used the bank yet.\n").format(member.display_name)
|
||||
|
||||
if uid not in ecousers:
|
||||
txt += _("- {} has not used the economy commands yet.\n").format(member.display_name)
|
||||
else:
|
||||
next_payday = ecousers[uid].get("next_payday", 0) + payday_time
|
||||
if cur_time < next_payday:
|
||||
time_left = next_payday - cur_time
|
||||
txt += _("- {} has {} seconds left until their next payday.\n").format(member.display_name, time_left)
|
||||
else:
|
||||
txt += _("- {} is ready for their next payday.\n").format(member.display_name)
|
||||
await ctx.send(txt)
|
||||
|
||||
@extendedeconomy.command(name="view")
|
||||
@commands.bot_has_permissions(embed_links=True)
|
||||
async def view_settings(self, ctx: commands.Context):
|
||||
"""
|
||||
View the current settings
|
||||
"""
|
||||
is_global = await bank.is_global()
|
||||
if is_global and ctx.author.id not in self.bot.owner_ids:
|
||||
return await ctx.send(_("You must be a bot owner to view these settings when global bank is enabled."))
|
||||
view = CostMenu(ctx, self, is_global, self.cost_check)
|
||||
await view.refresh()
|
||||
|
||||
@extendedeconomy.command(name="resetcooldown")
|
||||
async def reset_payday_cooldown(self, ctx: commands.Context, *, member: discord.Member):
|
||||
"""Reset the payday cooldown for a user"""
|
||||
cog = self.bot.get_cog("Economy")
|
||||
if not cog:
|
||||
return await ctx.send(_("Economy cog is not loaded."))
|
||||
if await bank.is_global() and ctx.author.id not in self.bot.owner_ids:
|
||||
return await ctx.send(_("You must be a bot owner to reset cooldowns when global bank is enabled!"))
|
||||
cur_time = calendar.timegm(ctx.message.created_at.utctimetuple())
|
||||
if await bank.is_global():
|
||||
payday_time = await cog.config.PAYDAY_TIME()
|
||||
new_time = int(cur_time - payday_time)
|
||||
await cog.config.user(member).next_payday.set(new_time)
|
||||
else:
|
||||
payday_time = await cog.config.guild(ctx.guild).PAYDAY_TIME()
|
||||
new_time = int(cur_time - payday_time)
|
||||
await cog.config.member(member).next_payday.set(new_time)
|
||||
await ctx.send(_("Payday cooldown reset for **{}**.").format(member.display_name))
|
||||
|
||||
@extendedeconomy.command(name="stackpaydays", aliases=["stackpayday"])
|
||||
async def stack_paydays(self, ctx: commands.Context):
|
||||
"""Toggle whether payday roles stack or not"""
|
||||
is_global = await bank.is_global()
|
||||
if is_global:
|
||||
return await ctx.send(_("This setting is not available when global bank is enabled."))
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
conf.stack_paydays = not conf.stack_paydays
|
||||
if conf.stack_paydays:
|
||||
txt = _("Payday role amounts will now stack.")
|
||||
else:
|
||||
txt = _("Payday role amounts will no longer stack.")
|
||||
await ctx.send(txt)
|
||||
await self.save()
|
||||
|
||||
@extendedeconomy.command(name="autopaydayrole")
|
||||
async def autopayday_roles(self, ctx: commands.Context, *, role: discord.Role):
|
||||
"""Add/Remove auto payday roles"""
|
||||
is_global = await bank.is_global()
|
||||
if is_global:
|
||||
txt = _("This setting is not available when global bank is enabled.")
|
||||
if ctx.author.id in self.bot.owner_ids:
|
||||
txt += _("\nUse {} to allow auto-claiming for for all users.").format(
|
||||
f"`{ctx.clean_prefix}ecoset autopayday`"
|
||||
)
|
||||
return await ctx.send(txt)
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
if role.id in conf.auto_claim_roles:
|
||||
conf.auto_claim_roles.remove(role.id)
|
||||
txt = _("This role will no longer recieve paydays automatically.")
|
||||
else:
|
||||
conf.auto_claim_roles.append(role.id)
|
||||
txt = _("This role will now receive paydays automatically.")
|
||||
await ctx.send(txt)
|
||||
await self.save()
|
||||
|
||||
@extendedeconomy.command(name="rolebonus")
|
||||
async def role_bonus(self, ctx: commands.Context, role: discord.Role, bonus: float):
|
||||
"""
|
||||
Add/Remove Payday role bonuses
|
||||
|
||||
Example: `[p]ecoset rolebonus @role 0.1` - Adds a 10% bonus to the user's payday if they have the role.
|
||||
|
||||
To remove a bonus, set the bonus to 0.
|
||||
"""
|
||||
is_global = await bank.is_global()
|
||||
if is_global:
|
||||
return await ctx.send(_("This setting is not available when global bank is enabled."))
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
if bonus <= 0:
|
||||
if role.id in conf.role_bonuses:
|
||||
del conf.role_bonuses[role.id]
|
||||
txt = _("Role bonus removed.")
|
||||
await self.save()
|
||||
else:
|
||||
txt = _("That role does not have a bonus.")
|
||||
return await ctx.send(txt)
|
||||
if role.id in conf.role_bonuses:
|
||||
current = conf.role_bonuses[role.id]
|
||||
if current == bonus:
|
||||
return await ctx.send(_("That role already has that bonus."))
|
||||
txt = _("Role bonus updated.")
|
||||
else:
|
||||
txt = _("Role bonus added.")
|
||||
conf.role_bonuses[role.id] = bonus
|
||||
await ctx.send(txt)
|
||||
await self.save()
|
||||
|
||||
@extendedeconomy.command(name="autopayday")
|
||||
@commands.is_owner()
|
||||
async def autopayday(self, ctx: commands.Context):
|
||||
"""Toggle whether paydays are claimed automatically (Global bank)"""
|
||||
is_global = await bank.is_global()
|
||||
self.db.auto_payday_claim = not self.db.auto_payday_claim
|
||||
if self.db.auto_payday_claim:
|
||||
if is_global:
|
||||
txt = _("Paydays will now be claimed automatically for all users.")
|
||||
else:
|
||||
txt = _("Paydays will now be claimed automatically for set roles.")
|
||||
else:
|
||||
txt = _("Paydays will no longer be claimed automatically.")
|
||||
await ctx.send(txt)
|
||||
await self.save()
|
||||
|
||||
@extendedeconomy.command(name="autoclaimchannel")
|
||||
async def auto_claim_channel(self, ctx: commands.Context, *, channel: t.Optional[discord.TextChannel] = None):
|
||||
"""Set the auto claim channel"""
|
||||
is_global = await bank.is_global()
|
||||
if is_global:
|
||||
return await ctx.send(_("There is no auto claim channel when global bank is enabled!"))
|
||||
txt = _("Auto claim channel set to {}").format(channel.mention) if channel else _("Auto claim channel removed.")
|
||||
if is_global:
|
||||
self.db.logs.auto_claim = channel.id if channel else 0
|
||||
else:
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
conf.logs.auto_claim = channel.id if channel else 0
|
||||
await ctx.send(txt)
|
||||
await self.save()
|
||||
|
||||
@extendedeconomy.command(name="transfertax")
|
||||
async def set_transfertax(self, ctx: commands.Context, tax: float):
|
||||
"""
|
||||
Set the transfer tax percentage as a decimal
|
||||
|
||||
*Example: `0.05` is for 5% tax*
|
||||
|
||||
- Set to 0 to disable
|
||||
- Default is 0
|
||||
"""
|
||||
is_global = await bank.is_global()
|
||||
if is_global and ctx.author.id not in self.bot.owner_ids:
|
||||
return await ctx.send(_("You must be a bot owner to set the transfer tax when global bank is enabled."))
|
||||
if tax < 0 or tax >= 1:
|
||||
return await ctx.send(_("Invalid tax percentage. Must be between 0 and 1."))
|
||||
|
||||
if is_global:
|
||||
self.db.transfer_tax = tax
|
||||
else:
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
conf.transfer_tax = tax
|
||||
await ctx.send(_("Transfer tax set to {}%").format(round(tax * 100, 2)))
|
||||
await self.save()
|
||||
|
||||
@extendedeconomy.command(name="taxwhitelist")
|
||||
async def set_taxwhitelist(self, ctx: commands.Context, *, role: discord.Role):
|
||||
"""
|
||||
Add/Remove roles from the transfer tax whitelist
|
||||
"""
|
||||
is_global = await bank.is_global()
|
||||
if is_global:
|
||||
return await ctx.send(_("This setting is not available when global bank is enabled."))
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
if role.id in conf.transfer_tax_whitelist:
|
||||
conf.transfer_tax_whitelist.remove(role.id)
|
||||
txt = _("Role removed from the transfer tax whitelist.")
|
||||
else:
|
||||
conf.transfer_tax_whitelist.append(role.id)
|
||||
txt = _("Role added to the transfer tax whitelist.")
|
||||
await ctx.send(txt)
|
||||
await self.save()
|
||||
|
||||
@extendedeconomy.command(name="mainlog")
|
||||
async def set_mainlog(self, ctx: commands.Context, channel: t.Optional[discord.TextChannel] = None):
|
||||
"""
|
||||
Set the main log channel
|
||||
"""
|
||||
is_global = await bank.is_global()
|
||||
if is_global and ctx.author.id not in self.bot.owner_ids:
|
||||
return await ctx.send(_("You must be a bot owner to set the main log channel when global bank is enabled."))
|
||||
if is_global:
|
||||
current = self.db.logs.default_log_channel
|
||||
else:
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
current = conf.logs.default_log_channel
|
||||
if not channel and current:
|
||||
txt = _("Removing the main log channel.")
|
||||
elif not channel and not current:
|
||||
return await ctx.send_help()
|
||||
elif channel and current:
|
||||
if channel.id == current:
|
||||
return await ctx.send(_("That is already the main log channel."))
|
||||
txt = _("Main log channel changed to {}").format(channel.mention)
|
||||
else:
|
||||
txt = _("Main log channel set to {}").format(channel.mention)
|
||||
if is_global:
|
||||
self.db.logs.default_log_channel = channel.id if channel else 0
|
||||
else:
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
conf.logs.default_log_channel = channel.id if channel else 0
|
||||
await ctx.send(txt)
|
||||
await self.save()
|
||||
|
||||
@extendedeconomy.command(name="eventlog")
|
||||
async def set_eventlog(
|
||||
self,
|
||||
ctx: commands.Context,
|
||||
event: str,
|
||||
channel: t.Optional[discord.TextChannel] = None,
|
||||
):
|
||||
"""
|
||||
Set an event log channel
|
||||
|
||||
**Events:**
|
||||
- set_balance
|
||||
- transfer_credits
|
||||
- bank_wipe
|
||||
- prune
|
||||
- set_global
|
||||
- payday_claim
|
||||
|
||||
"""
|
||||
is_global = await bank.is_global()
|
||||
if is_global and ctx.author.id not in self.bot.owner_ids:
|
||||
return await ctx.send(_("You must be a bot owner to set an event log channel when global bank is enabled."))
|
||||
if is_global:
|
||||
logs = self.db.logs
|
||||
else:
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
logs = conf.logs
|
||||
valid_events = [
|
||||
"set_balance",
|
||||
"transfer_credits",
|
||||
"bank_wipe",
|
||||
"prune",
|
||||
"set_global",
|
||||
"payday_claim",
|
||||
]
|
||||
if event not in valid_events:
|
||||
return await ctx.send(_("Invalid event. Must be one of: {}").format(", ".join(valid_events)))
|
||||
current = getattr(logs, event)
|
||||
if not current and not channel:
|
||||
return await ctx.send(_("No channel set for this event."))
|
||||
if current and not channel:
|
||||
txt = _("Event log channel for {} removed.").format(event)
|
||||
elif current and channel:
|
||||
if channel.id == current:
|
||||
return await ctx.send(_("That is already the event log channel for {}.").format(event))
|
||||
txt = _("Event log channel for {} changed to {}").format(event, channel.mention)
|
||||
else:
|
||||
txt = _("Event log channel for {} set to {}").format(event, channel.mention)
|
||||
if is_global:
|
||||
setattr(self.db.logs, event, channel.id if channel else 0)
|
||||
else:
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
setattr(conf.logs, event, channel.id if channel else 0)
|
||||
await ctx.send(txt)
|
||||
await self.save()
|
||||
|
||||
@extendedeconomy.command(name="deleteafter")
|
||||
@commands.is_owner()
|
||||
async def set_delete_after(self, ctx: commands.Context, seconds: int):
|
||||
"""
|
||||
Set the delete after time for cost check messages
|
||||
|
||||
- Set to 0 to disable (Recommended for public bots)
|
||||
- Default is 0 (disabled)
|
||||
"""
|
||||
if not seconds:
|
||||
self.db.delete_after = None
|
||||
await ctx.send(_("Delete after time disabled."))
|
||||
else:
|
||||
self.db.delete_after = seconds
|
||||
await ctx.send(_("Delete after time set to {} seconds.").format(seconds))
|
||||
await self.save()
|
||||
|
||||
# @extendedeconomy.command(name="perguildoverride")
|
||||
# @commands.is_owner()
|
||||
# async def per_guild_override(self, ctx: commands.Context):
|
||||
# """Toggle per guild prices when global bank is enabled"""
|
||||
# self.db.per_guild_override = not self.db.per_guild_override
|
||||
# if self.db.per_guild_override:
|
||||
# txt = _("Per guild prices are now enabled.")
|
||||
# else:
|
||||
# txt = _("Per guild prices are now disabled.")
|
||||
# await ctx.send(txt)
|
||||
# await self.save()
|
||||
|
||||
@commands.command(name="addcost")
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@commands.guild_only()
|
||||
async def add_cost(
|
||||
self,
|
||||
ctx: commands.Context,
|
||||
command: str = "",
|
||||
cost: int = 0,
|
||||
duration: int = 3600,
|
||||
level: t.Literal["admin", "mod", "all", "user", "global"] = "all",
|
||||
prompt: t.Literal["text", "reaction", "button", "silent", "notify"] = "notify",
|
||||
modifier: t.Literal["static", "percent", "exponential", "linear"] = "static",
|
||||
value: float = 0.0,
|
||||
):
|
||||
"""
|
||||
Add a cost to a command
|
||||
"""
|
||||
if not command:
|
||||
help_txt = _(
|
||||
"- **cost**: The amount of currency to charge\n"
|
||||
"- **duration**(`default: 3600`): The time in seconds before the cost resets\n"
|
||||
"- **level**(`default: all`): The minimum permission level to apply the cost\n"
|
||||
" - admin: Admins and above can use the command for free\n"
|
||||
" - mod: Mods and above can use the command for free\n"
|
||||
" - all: Everyone must pay the cost to use the command\n"
|
||||
" - user: All users must pay the cost to use the command unless they are mod or admin\n"
|
||||
" - global: The cost is applied to all users globally\n"
|
||||
"- **prompt**(`default: notify`): How the user will be prompted to confirm the cost\n"
|
||||
" - text: The bot will send a text message asking the user to confirm the cost with yes or no\n"
|
||||
" - reaction: The bot will send a message with emoji reactions to confirm the cost\n"
|
||||
" - button: The bot will send a message with buttons to confirm the cost\n"
|
||||
" - silent: The bot will not prompt the user to confirm the cost\n"
|
||||
" - notify: The bot will simply notify the user of the cost without asking for confirmation\n"
|
||||
"- **modifier**(`default: static`): The type of cost modifier\n"
|
||||
" - static: The cost is a fixed amount\n"
|
||||
" - percent: The cost is a percentage of the user's balance on top of the base cost\n"
|
||||
" - exponential: The cost increases exponentially based on how frequently the command is used\n"
|
||||
" - Ex: `Cost = cost + (value * uses over the duration^2)`\n"
|
||||
" - linear: The cost increases linearly based on how frequently the command is used\n"
|
||||
" - Ex: `Cost = cost + (value * uses over the duration)`\n"
|
||||
"- **value**(`default: 0.0`): The value of the cost modifier depends on the modifier type\n"
|
||||
" - static: This will be 0 and does nothing\n"
|
||||
" - percent: Value will be the percentage of the user's balance to add to the base cost\n"
|
||||
" - exponential: Value will be the base cost multiplier\n"
|
||||
" - linear: Value will be multiplied by the number of uses in the last hour to get the cost increase\n"
|
||||
)
|
||||
await ctx.send_help()
|
||||
return await ctx.send(help_txt)
|
||||
|
||||
if command == "addcost":
|
||||
return await ctx.send(_("You can't add a cost to the addcost command."))
|
||||
|
||||
is_global = await bank.is_global()
|
||||
if is_global:
|
||||
if ctx.author.id not in ctx.bot.owner_ids:
|
||||
return await ctx.send(_("You must be a bot owner to use this command while global bank is active."))
|
||||
if level != "global":
|
||||
return await ctx.send(_("Global bank is active, you must use the global level."))
|
||||
else:
|
||||
if level == "global":
|
||||
if ctx.author.id not in ctx.bot.owner_ids:
|
||||
return await ctx.send(_("You must be a bot owner to use the global level."))
|
||||
return await ctx.send(_("You must enable global bank to use the global level."))
|
||||
|
||||
command_obj: commands.Command = self.bot.get_command(command)
|
||||
if not command_obj:
|
||||
command_obj: app_commands.Command = self.bot.tree.get_command(command)
|
||||
if not command_obj:
|
||||
return await ctx.send(_("Command not found."))
|
||||
if not isinstance(command_obj, app_commands.Command):
|
||||
return await ctx.send(_("That is not a valid app command"))
|
||||
|
||||
if isinstance(command_obj, commands.commands._AlwaysAvailableCommand):
|
||||
return await ctx.send(_("You can't add costs to commands that are always available!"))
|
||||
if isinstance(command_obj, (commands.Command, commands.HybridCommand)):
|
||||
if (command_obj.requires.privilege_level or 0) > await commands.requires.PrivilegeLevel.from_ctx(ctx):
|
||||
return await ctx.send(_("You can't add costs to commands you don't have permission to run!"))
|
||||
|
||||
cost_obj = CommandCost(
|
||||
cost=cost,
|
||||
duration=duration,
|
||||
level=level,
|
||||
prompt=prompt,
|
||||
modifier=modifier,
|
||||
value=value,
|
||||
)
|
||||
overwrite_warning = _("This will overwrite the existing cost for this command. Continue?")
|
||||
costs = self.db.command_costs if is_global else self.db.get_conf(ctx.guild).command_costs
|
||||
if command in costs:
|
||||
view = ConfirmView(ctx.author)
|
||||
msg = await ctx.send(overwrite_warning, view=view)
|
||||
await view.wait()
|
||||
if not view.value:
|
||||
return await msg.edit(content=_("Not adding cost."), view=None)
|
||||
await msg.edit(content=_("{} cost updated.").format(command), view=None)
|
||||
else:
|
||||
await ctx.send(_("{} cost added.").format(command))
|
||||
|
||||
if is_global:
|
||||
self.db.command_costs[command] = cost_obj
|
||||
else:
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
conf.command_costs[command] = cost_obj
|
||||
await self.save()
|
||||
|
||||
@commands.command(name="banksetrole")
|
||||
@bank.is_owner_if_bank_global()
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
async def bank_set_role(self, ctx: commands.Context, role: discord.Role, creds: SetParser):
|
||||
"""Set the balance of all user accounts that have a specific role
|
||||
|
||||
Putting + or - signs before the amount will add/remove currency on the user's bank account instead.
|
||||
|
||||
Examples:
|
||||
- `[p]banksetrole @everyone 420` - Sets everyones balance to 420
|
||||
- `[p]banksetrole @role +69` - Increases balance by 69 for everyone with the role
|
||||
- `[p]banksetrole @role -42` - Decreases balance by 42 for everyone with the role
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `<role>` The role to set the currency of for each user that has it.
|
||||
- `<creds>` The amount of currency to set their balance to.
|
||||
"""
|
||||
async with ctx.typing():
|
||||
if await bank.is_global():
|
||||
group = bank._config._get_base_group(bank._config.USER)
|
||||
else:
|
||||
group = bank._config._get_base_group(bank._config.MEMBER, str(ctx.guild.id))
|
||||
|
||||
currency = await bank.get_currency_name(ctx.guild)
|
||||
max_bal = await bank.get_max_balance(ctx.guild)
|
||||
try:
|
||||
default_balance = await bank.get_default_balance(ctx.guild)
|
||||
except AttributeError:
|
||||
default_balance = await bank.get_default_balance()
|
||||
members: t.List[discord.Member] = [user for user in ctx.guild.members if role in user.roles]
|
||||
if not members:
|
||||
return await ctx.send(_("No users found with that role."))
|
||||
|
||||
users_affected = 0
|
||||
total = 0
|
||||
async with group.all() as accounts:
|
||||
for mem in members:
|
||||
uid = str(mem.id)
|
||||
if uid in accounts:
|
||||
wallet = accounts[uid]
|
||||
else:
|
||||
wallet = {"name": mem.display_name, "balance": default_balance, "created_at": 0}
|
||||
accounts[uid] = wallet
|
||||
|
||||
match creds.operation:
|
||||
case "deposit":
|
||||
amount = min(max_bal - wallet["balance"], creds.sum)
|
||||
case "withdraw":
|
||||
amount = -min(wallet["balance"], creds.sum)
|
||||
case _: # set
|
||||
amount = creds.sum - wallet["balance"]
|
||||
|
||||
accounts[uid]["balance"] += amount
|
||||
total += amount
|
||||
users_affected += 1
|
||||
|
||||
if not users_affected:
|
||||
return await ctx.send(_("No users were affected."))
|
||||
if not total:
|
||||
return await ctx.send(_("No balances were changed."))
|
||||
grammar = _("user was") if users_affected == 1 else _("users were")
|
||||
msg = _("Balances for {} updated, total change was {}.").format(
|
||||
f"{users_affected} {grammar}", f"{total} {currency}"
|
||||
)
|
||||
await ctx.send(msg)
|
||||
|
||||
@commands.command(name="backpay")
|
||||
@bank.is_owner_if_bank_global()
|
||||
@commands.admin_or_permissions(manage_guild=True)
|
||||
@commands.guild_only()
|
||||
async def backpay_cmd(self, ctx: commands.Context, duration: commands.TimedeltaConverter, confirm: bool = False):
|
||||
"""Calculate and award missed paydays for all members within a time period.
|
||||
|
||||
This will calculate how many paydays each member could have claimed within the
|
||||
specified time period and award them accordingly.
|
||||
|
||||
By default, this command will only show a preview. Use `confirm=True` to apply changes.
|
||||
|
||||
Examples:
|
||||
- `[p]backpay 48h` - Preview paydays missed in the last 48 hours
|
||||
- `[p]backpay 7d True` - Calculate and give paydays missed in the last 7 days
|
||||
|
||||
**Arguments**
|
||||
- `<duration>` How far back to check for missed paydays. Use time abbreviations like 1d, 12h, etc.
|
||||
- `[confirm]` Set to True to actually apply the changes. Default: False (preview only)
|
||||
"""
|
||||
if await bank.is_global() and ctx.author.id not in self.bot.owner_ids:
|
||||
return await ctx.send(_("You must be a bot owner to use this command while global bank is active."))
|
||||
|
||||
if duration.total_seconds() <= 0:
|
||||
return await ctx.send(_("Duration must be positive!"))
|
||||
|
||||
async with ctx.typing():
|
||||
eco_cog = self.bot.get_cog("Economy")
|
||||
if not eco_cog:
|
||||
return await ctx.send(_("Economy cog is not loaded."))
|
||||
|
||||
eco_conf: Config = eco_cog.config
|
||||
is_global = await bank.is_global()
|
||||
currency = await bank.get_currency_name(ctx.guild)
|
||||
max_bal = await bank.get_max_balance(ctx.guild)
|
||||
|
||||
# Get current time and the time to look back to
|
||||
current_time = calendar.timegm(datetime.now(tz=timezone.utc).utctimetuple())
|
||||
|
||||
# Get the payday cooldown period
|
||||
if is_global:
|
||||
payday_time = await eco_conf.PAYDAY_TIME()
|
||||
payday_credits = await eco_conf.PAYDAY_CREDITS()
|
||||
else:
|
||||
payday_time = await eco_conf.guild(ctx.guild).PAYDAY_TIME()
|
||||
payday_credits = await eco_conf.guild(ctx.guild).PAYDAY_CREDITS()
|
||||
|
||||
# Calculate total possible paydays in the lookback period
|
||||
# This ensures everyone gets the same number of paydays for the same duration
|
||||
total_possible_paydays = int(duration.total_seconds() // payday_time)
|
||||
|
||||
if total_possible_paydays <= 0:
|
||||
return await ctx.send(_("The specified duration is too short for any paydays."))
|
||||
|
||||
# Create a list to store the report data
|
||||
report_data = []
|
||||
users_updated = 0
|
||||
total_credits = 0
|
||||
|
||||
if is_global:
|
||||
bankgroup = bank._config._get_base_group(bank._config.USER)
|
||||
ecogroup = eco_conf._get_base_group(eco_conf.USER)
|
||||
accounts: t.Dict[str, dict] = await bankgroup.all()
|
||||
ecousers: t.Dict[str, dict] = await ecogroup.all()
|
||||
|
||||
for member in ctx.guild.members:
|
||||
uid = str(member.id)
|
||||
|
||||
# Skip users with no bank accounts or economy data
|
||||
if uid not in accounts or uid not in ecousers:
|
||||
continue
|
||||
|
||||
# All eligible users get the same number of paydays
|
||||
potential_paydays = total_possible_paydays
|
||||
|
||||
# Calculate amount to give (base amount * number of paydays)
|
||||
amount_to_give = payday_credits * potential_paydays
|
||||
|
||||
# Don't exceed max balance
|
||||
current_balance = accounts[uid]["balance"]
|
||||
new_balance = min(current_balance + amount_to_give, max_bal)
|
||||
added_amount = new_balance - current_balance
|
||||
|
||||
# Add to report even if no credits are added due to max balance
|
||||
report_data.append(
|
||||
{
|
||||
"name": member.display_name,
|
||||
"id": member.id,
|
||||
"paydays": potential_paydays,
|
||||
"amount": added_amount,
|
||||
"current_balance": current_balance,
|
||||
"new_balance": new_balance,
|
||||
"max_hit": added_amount < amount_to_give,
|
||||
}
|
||||
)
|
||||
|
||||
# Track stats
|
||||
total_credits += added_amount
|
||||
users_updated += 1
|
||||
|
||||
# Only update the account if confirm is True
|
||||
if confirm:
|
||||
accounts[uid]["balance"] = new_balance
|
||||
ecousers[uid]["next_payday"] = current_time
|
||||
|
||||
# Save changes if any and confirmation is True
|
||||
if users_updated > 0 and confirm:
|
||||
await bankgroup.set(accounts)
|
||||
await ecogroup.set(ecousers)
|
||||
|
||||
else:
|
||||
# Per-guild logic
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
bankgroup = bank._config._get_base_group(bank._config.MEMBER, str(ctx.guild.id))
|
||||
ecogroup = eco_conf._get_base_group(eco_conf.MEMBER, str(ctx.guild.id))
|
||||
accounts: t.Dict[str, dict] = await bankgroup.all()
|
||||
ecousers: t.Dict[str, dict] = await ecogroup.all()
|
||||
payday_roles: t.Dict[int, dict] = await eco_conf.all_roles()
|
||||
|
||||
for member in ctx.guild.members:
|
||||
uid = str(member.id)
|
||||
|
||||
# Skip users with no bank accounts or economy data
|
||||
if uid not in accounts or uid not in ecousers:
|
||||
continue
|
||||
|
||||
# All eligible users get the same number of paydays
|
||||
potential_paydays = total_possible_paydays
|
||||
|
||||
# Calculate per-payday amount with role bonuses
|
||||
base_amount = payday_credits
|
||||
for role in member.roles:
|
||||
if role.id in payday_roles:
|
||||
role_credits = payday_roles[role.id]["PAYDAY_CREDITS"]
|
||||
if conf.stack_paydays:
|
||||
base_amount += role_credits
|
||||
elif role_credits > base_amount:
|
||||
base_amount = role_credits
|
||||
|
||||
# Apply role bonus multipliers if configured
|
||||
if conf.role_bonuses and any(role.id in conf.role_bonuses for role in member.roles):
|
||||
highest_bonus = max(conf.role_bonuses.get(role.id, 0) for role in member.roles)
|
||||
base_amount += round(base_amount * highest_bonus)
|
||||
|
||||
# Calculate total amount to give
|
||||
amount_to_give = base_amount * potential_paydays
|
||||
|
||||
# Don't exceed max balance
|
||||
current_balance = accounts[uid]["balance"]
|
||||
new_balance = min(current_balance + amount_to_give, max_bal)
|
||||
added_amount = new_balance - current_balance
|
||||
|
||||
# Add to report even if no credits are added due to max balance
|
||||
report_data.append(
|
||||
{
|
||||
"name": member.display_name,
|
||||
"id": member.id,
|
||||
"paydays": potential_paydays,
|
||||
"amount": added_amount,
|
||||
"current_balance": current_balance,
|
||||
"new_balance": new_balance,
|
||||
"max_hit": added_amount < amount_to_give,
|
||||
"payday_value": base_amount,
|
||||
}
|
||||
)
|
||||
|
||||
# Track stats
|
||||
total_credits += added_amount
|
||||
users_updated += 1
|
||||
|
||||
# Only update the account if confirm is True
|
||||
if confirm:
|
||||
accounts[uid]["balance"] = new_balance
|
||||
ecousers[uid]["next_payday"] = current_time
|
||||
|
||||
# Save changes if any and confirmation is True
|
||||
if users_updated > 0 and confirm:
|
||||
await bankgroup.set(accounts)
|
||||
await ecogroup.set(ecousers)
|
||||
|
||||
# Generate report
|
||||
if users_updated > 0:
|
||||
# Sort by amount in descending order
|
||||
report_data.sort(key=lambda x: x["amount"], reverse=True)
|
||||
|
||||
report_lines = [
|
||||
f"# Backpay Report for {humanize_timedelta(seconds=int(duration.total_seconds()))}\n",
|
||||
f"Total Users: {users_updated}",
|
||||
f"Total Credits: {humanize_number(total_credits)} {currency}\n",
|
||||
"Details:",
|
||||
]
|
||||
|
||||
for entry in report_data:
|
||||
max_note = " (Max balance hit)" if entry.get("max_hit") else ""
|
||||
per_payday = (
|
||||
f" ({humanize_number(entry.get('payday_value', payday_credits))}/payday)"
|
||||
if "payday_value" in entry
|
||||
else ""
|
||||
)
|
||||
report_lines.append(
|
||||
f"{entry['name']} (ID: {entry['id']}): "
|
||||
f"{humanize_number(entry['amount'])} {currency} for {entry['paydays']} paydays{per_payday}{max_note}"
|
||||
)
|
||||
|
||||
report_text = "\n".join(report_lines)
|
||||
report_file = discord.File(io.StringIO(report_text), filename=f"backpay_report_{ctx.guild.id}.txt")
|
||||
|
||||
if confirm:
|
||||
msg = _(
|
||||
"Backpay complete for {duration}!\n{users} users received a total of {credits} {currency}."
|
||||
).format(
|
||||
duration=humanize_timedelta(seconds=int(duration.total_seconds())),
|
||||
users=humanize_number(users_updated),
|
||||
credits=humanize_number(total_credits),
|
||||
currency=currency,
|
||||
)
|
||||
await ctx.send(msg, file=report_file)
|
||||
else:
|
||||
msg = _(
|
||||
"Backpay preview for {duration}:\n{users} users would receive a total of {credits} {currency}.\n"
|
||||
"Run with `confirm=True` to apply these changes."
|
||||
).format(
|
||||
duration=humanize_timedelta(seconds=int(duration.total_seconds())),
|
||||
users=humanize_number(users_updated),
|
||||
credits=humanize_number(total_credits),
|
||||
currency=currency,
|
||||
)
|
||||
await ctx.send(msg, file=report_file)
|
||||
else:
|
||||
await ctx.send(_("No users were eligible for backpay in that time period."))
|
71
extendedeconomy/commands/user.py
Normal file
71
extendedeconomy/commands/user.py
Normal file
|
@ -0,0 +1,71 @@
|
|||
import asyncio
|
||||
import logging
|
||||
|
||||
from redbot.core import bank, commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
|
||||
from ..abc import MixinMeta
|
||||
from ..common.generator import generate_pie_chart
|
||||
|
||||
log = logging.getLogger("red.vrt.extendedeconomy.admin")
|
||||
_ = Translator("ExtendedEconomy", __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class User(MixinMeta):
|
||||
@commands.command(name="idbalance")
|
||||
async def id_balance(self, ctx: commands.Context, user_id: int):
|
||||
"""Get the balance of a user by ID.
|
||||
|
||||
Helpful for checking a user's balance if they are not in the server.
|
||||
"""
|
||||
if await bank.is_global():
|
||||
all_accounts = await bank._config.all_users()
|
||||
else:
|
||||
all_accounts = await bank._config.all_members(ctx.guild)
|
||||
|
||||
if user_id in all_accounts:
|
||||
balance = all_accounts[user_id]["balance"]
|
||||
await ctx.send(f"User ID: {user_id} has a balance of `{balance}`")
|
||||
else:
|
||||
await ctx.send(_("User ID not found."))
|
||||
|
||||
@commands.command(name="bankpie")
|
||||
@commands.bot_has_permissions(attach_files=True)
|
||||
async def bank_pie(self, ctx: commands.Context, amount: int = 10):
|
||||
"""View a pie chart of the top X bank balances."""
|
||||
is_global = await bank.is_global()
|
||||
if is_global:
|
||||
members = await bank._config.all_users()
|
||||
else:
|
||||
members = await bank._config.all_members(ctx.guild)
|
||||
|
||||
user_balances = []
|
||||
|
||||
for user_id, wallet in members.items():
|
||||
user = ctx.guild.get_member(user_id)
|
||||
if user:
|
||||
user_balances.append((user.display_name, wallet["balance"]))
|
||||
|
||||
if not user_balances:
|
||||
return await ctx.send(_("No users found."))
|
||||
|
||||
# Sort users by balance in descending order and take the top X amount
|
||||
user_balances.sort(key=lambda x: x[1], reverse=True)
|
||||
top_users = user_balances[:amount]
|
||||
other_balance = sum(balance for _, balance in user_balances[amount:])
|
||||
|
||||
labels = [user for user, _ in top_users]
|
||||
sizes = [balance for _, balance in top_users]
|
||||
|
||||
if other_balance > 0:
|
||||
labels.append("Other")
|
||||
sizes.append(other_balance)
|
||||
|
||||
file = await asyncio.to_thread(
|
||||
generate_pie_chart,
|
||||
labels,
|
||||
sizes,
|
||||
_("Bank Balances for {}").format(ctx.guild.name),
|
||||
)
|
||||
await ctx.send(file=file)
|
28
extendedeconomy/common/__init__.py
Normal file
28
extendedeconomy/common/__init__.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
import orjson
|
||||
from pydantic import VERSION, BaseModel
|
||||
|
||||
|
||||
class Base(BaseModel):
|
||||
def model_dump_json(self, *args, **kwargs):
|
||||
if VERSION >= "2.0.1":
|
||||
return super().model_dump_json(*args, **kwargs)
|
||||
return super().json(*args, **kwargs)
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
if VERSION >= "2.0.1":
|
||||
return super().model_dump(*args, **kwargs)
|
||||
if kwargs.pop("mode", "") == "json":
|
||||
return orjson.loads(super().json(*args, **kwargs))
|
||||
return super().dict(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def model_validate_json(cls, obj, *args, **kwargs):
|
||||
if VERSION >= "2.0.1":
|
||||
return super().model_validate_json(obj, *args, **kwargs)
|
||||
return super().parse_raw(obj, *args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def model_validate(cls, obj, *args, **kwargs):
|
||||
if VERSION >= "2.0.1":
|
||||
return super().model_validate(obj, *args, **kwargs)
|
||||
return super().parse_obj(obj, *args, **kwargs)
|
151
extendedeconomy/common/checks.py
Normal file
151
extendedeconomy/common/checks.py
Normal file
|
@ -0,0 +1,151 @@
|
|||
import asyncio
|
||||
import logging
|
||||
import math
|
||||
import typing as t
|
||||
|
||||
import discord
|
||||
from redbot.core import bank, commands
|
||||
from redbot.core.i18n import Translator
|
||||
from redbot.core.utils.chat_formatting import humanize_number
|
||||
|
||||
from ..abc import MixinMeta
|
||||
from ..views.confirm import ConfirmView
|
||||
from .utils import (
|
||||
confirm_msg,
|
||||
confirm_msg_reaction,
|
||||
ctx_to_dict,
|
||||
ctx_to_id,
|
||||
edit_delete_delay,
|
||||
get_cached_credits_name,
|
||||
)
|
||||
|
||||
log = logging.getLogger("red.vrt.extendedeconomy.checks")
|
||||
_ = Translator("ExtendedEconomy", __file__)
|
||||
|
||||
|
||||
class Checks(MixinMeta):
|
||||
async def cost_check(self, ctx: t.Union[commands.Context, discord.Interaction]):
|
||||
return await self._cost_check(ctx, ctx.author if isinstance(ctx, commands.Context) else ctx.user)
|
||||
|
||||
async def slash_cost_check(self, interaction: discord.Interaction):
|
||||
return await self._cost_check(interaction, interaction.user)
|
||||
|
||||
async def _cost_check(
|
||||
self,
|
||||
ctx: t.Union[commands.Context, discord.Interaction],
|
||||
user: t.Union[discord.Member, discord.User],
|
||||
):
|
||||
if isinstance(ctx, discord.Interaction):
|
||||
user = ctx.guild.get_member(ctx.user.id) if ctx.guild else ctx.user
|
||||
else:
|
||||
user = ctx.author
|
||||
command_name = ctx.command.qualified_name
|
||||
is_global = await bank.is_global()
|
||||
if not is_global and ctx.guild is None:
|
||||
# Command run in DMs and bank is not global, cant apply cost so just return
|
||||
return True
|
||||
|
||||
if is_global:
|
||||
cost_obj = self.db.command_costs.get(command_name)
|
||||
elif ctx.guild is not None:
|
||||
conf = self.db.get_conf(ctx.guild)
|
||||
cost_obj = conf.command_costs.get(command_name)
|
||||
else:
|
||||
log.error(f"Unknown condition in '{command_name}' cost check for {user.name}: {ctx_to_dict(ctx)}")
|
||||
return True
|
||||
if not cost_obj:
|
||||
return True
|
||||
|
||||
# At this point we know that the command has a cost associated with it
|
||||
log.debug(f"Priced command '{ctx.command.qualified_name}' invoked by {user.name} - ({type(ctx)})")
|
||||
|
||||
cost = await cost_obj.get_cost(self.bot, user)
|
||||
if cost == 0:
|
||||
cost_obj.update_usage(user.id)
|
||||
return True
|
||||
|
||||
currency = await get_cached_credits_name(ctx.guild)
|
||||
is_broke = _("You do not have enough {} to run that command! (Need {})").format(currency, humanize_number(cost))
|
||||
notify = _("{}, you spent {} to run this command").format(
|
||||
user.display_name, f"{humanize_number(cost)} {currency}"
|
||||
)
|
||||
del_delay = self.db.delete_after if self.db.delete_after else None
|
||||
|
||||
interaction = ctx if isinstance(ctx, discord.Interaction) else ctx.interaction
|
||||
if interaction is None and cost_obj.prompt != "silent":
|
||||
# For text commands only
|
||||
if not await bank.can_spend(user, cost):
|
||||
raise commands.UserFeedbackCheckFailure(is_broke)
|
||||
message: discord.Message = None
|
||||
if cost_obj.prompt != "notify":
|
||||
txt = _("Do you want to spend {} {} to run this command?").format(humanize_number(cost), currency)
|
||||
if cost_obj.prompt == "text":
|
||||
message = await ctx.send(txt)
|
||||
yes = await confirm_msg(ctx)
|
||||
elif cost_obj.prompt == "reaction":
|
||||
message = await ctx.send(txt)
|
||||
yes = await confirm_msg_reaction(message, user, self.bot)
|
||||
elif cost_obj.prompt == "button":
|
||||
view = ConfirmView(user)
|
||||
message = await ctx.send(txt, view=view)
|
||||
await view.wait()
|
||||
yes = view.value
|
||||
else:
|
||||
raise ValueError(f"Invalid prompt type: {cost_obj.prompt}")
|
||||
if not yes:
|
||||
txt = _("Not running `{}`.").format(command_name)
|
||||
asyncio.create_task(edit_delete_delay(message, txt, del_delay))
|
||||
raise commands.UserFeedbackCheckFailure()
|
||||
if message:
|
||||
asyncio.create_task(edit_delete_delay(message, notify, del_delay))
|
||||
else:
|
||||
asyncio.create_task(ctx.send(notify, delete_after=del_delay))
|
||||
|
||||
try:
|
||||
await bank.withdraw_credits(user, cost)
|
||||
cost_obj.update_usage(user.id)
|
||||
if isinstance(ctx, commands.Context):
|
||||
self.charged[ctx_to_id(ctx)] = cost
|
||||
elif cost_obj.prompt != "silent":
|
||||
asyncio.create_task(ctx.channel.send(notify, delete_after=del_delay))
|
||||
return True
|
||||
except ValueError:
|
||||
log.debug(f"Failed to charge {user.name} for '{command_name}' - cost: {cost} {currency}")
|
||||
if isinstance(ctx, commands.Context):
|
||||
self.charged.pop(ctx_to_id(ctx), None)
|
||||
if isinstance(ctx, discord.Interaction):
|
||||
await interaction.response.send_message(is_broke, ephemeral=True)
|
||||
return False
|
||||
# asyncio.create_task(ctx.send(is_broke, delete_after=del_delay, ephemeral=True))
|
||||
raise commands.UserFeedbackCheckFailure()
|
||||
|
||||
async def transfer_tax_check(self, ctx: commands.Context):
|
||||
if ctx.command.qualified_name != "bank transfer":
|
||||
return True
|
||||
is_global = await bank.is_global()
|
||||
conf = self.db if is_global else self.db.get_conf(ctx.guild)
|
||||
tax = conf.transfer_tax
|
||||
if tax == 0:
|
||||
log.debug("No transfer tax set")
|
||||
return True
|
||||
|
||||
if not is_global and getattr(conf, "transfer_tax_whitelist", None):
|
||||
whitelist = conf.transfer_tax_whitelist
|
||||
if any(r.id in whitelist for r in ctx.author.roles):
|
||||
# log.debug(f"{ctx.author} is in the transfer tax whitelist")
|
||||
return True
|
||||
|
||||
# Args: EconomyCog, ctx, to, amount
|
||||
amount: int = ctx.args[-1]
|
||||
|
||||
deduction = math.ceil(amount * tax)
|
||||
asyncio.create_task(bank.withdraw_credits(ctx.author, deduction))
|
||||
# Modify the amount to be transferred
|
||||
ctx.args[-1] = amount - deduction
|
||||
|
||||
currency = await get_cached_credits_name(ctx.guild)
|
||||
txt = _("{}% transfer tax applied, {} deducted from transfer").format(
|
||||
f"{round(tax * 100)}", f"{humanize_number(deduction)} {currency}"
|
||||
)
|
||||
await ctx.send(txt)
|
||||
return True
|
27
extendedeconomy/common/generator.py
Normal file
27
extendedeconomy/common/generator.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
from io import BytesIO
|
||||
|
||||
import discord
|
||||
import plotly.express as px
|
||||
|
||||
|
||||
def generate_pie_chart(labels: list, sizes: list, title: str) -> discord.File:
|
||||
fig = px.pie(
|
||||
names=labels,
|
||||
values=sizes,
|
||||
title=title,
|
||||
hole=0.3,
|
||||
)
|
||||
|
||||
marker = dict(line=dict(color="#ffffff", width=2))
|
||||
fig.update_traces(textposition="inside", textinfo="percent+label", marker=marker)
|
||||
fig.update_layout(
|
||||
font_color="rgb(255,255,255)",
|
||||
font_size=20,
|
||||
plot_bgcolor="rgba(0,0,0,0)",
|
||||
paper_bgcolor="rgba(0,0,0,0)",
|
||||
)
|
||||
|
||||
buffer = BytesIO()
|
||||
fig.write_image(buffer, format="webp", scale=2)
|
||||
buffer.seek(0)
|
||||
return discord.File(buffer, filename="pie.webp")
|
247
extendedeconomy/common/listeners.py
Normal file
247
extendedeconomy/common/listeners.py
Normal file
|
@ -0,0 +1,247 @@
|
|||
import logging
|
||||
import typing as t
|
||||
from contextlib import suppress
|
||||
from datetime import datetime
|
||||
|
||||
import discord
|
||||
from discord.ext import tasks
|
||||
from redbot.core import bank, commands, errors
|
||||
from redbot.core.i18n import Translator
|
||||
from redbot.core.utils.chat_formatting import humanize_number
|
||||
|
||||
from ..abc import MixinMeta
|
||||
from ..common.utils import ctx_to_id, has_cost_check
|
||||
|
||||
log = logging.getLogger("red.vrt.extendedeconomy.listeners")
|
||||
_ = Translator("ExtendedEconomy", __file__)
|
||||
|
||||
|
||||
class Listeners(MixinMeta):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.payloads: t.Dict[int, t.List[discord.Embed]] = {}
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_command_error(self, ctx: commands.Context, error: Exception, *args, **kwargs):
|
||||
if not ctx.command:
|
||||
return
|
||||
# log.debug(f"Command error in '{ctx.command.qualified_name}' for {ctx.author.name}:({type(error)}) {error}")
|
||||
runtime_id = ctx_to_id(ctx)
|
||||
if runtime_id not in self.charged:
|
||||
# User wasn't charged for this command
|
||||
return
|
||||
# We need to refund the user if the command failed
|
||||
amount = self.charged.pop(runtime_id)
|
||||
try:
|
||||
await bank.deposit_credits(ctx.author, amount)
|
||||
except errors.BalanceTooHigh as e:
|
||||
await bank.set_balance(ctx.author, e.max_balance)
|
||||
cmd = ctx.command.qualified_name
|
||||
log.info(f"{ctx.author.name} has been refunded {amount} since the '{cmd}' command failed.")
|
||||
txt = _("You have been refunded since this command failed.")
|
||||
await ctx.send(txt)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_command_completion(self, ctx: commands.Context):
|
||||
if not ctx.command:
|
||||
return
|
||||
self.charged.pop(ctx_to_id(ctx), None)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_cog_add(self, cog: commands.Cog):
|
||||
if cog.qualified_name == "BankEvents":
|
||||
log.debug("BankEvents cog loaded 'after' ExtendedEconomy, overriding payday command.")
|
||||
payday: commands.Command = self.bot.get_command("payday")
|
||||
if payday:
|
||||
self.payday_callback = payday.callback
|
||||
payday.callback = self._extendedeconomy_payday_override.callback
|
||||
if cog.qualified_name in self.checks:
|
||||
return
|
||||
for cmd in cog.walk_app_commands():
|
||||
if isinstance(cmd, discord.app_commands.Group):
|
||||
continue
|
||||
if has_cost_check(cmd):
|
||||
continue
|
||||
cmd.add_check(self.cost_check)
|
||||
self.checks.add(cog.qualified_name)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_cog_remove(self, cog: commands.Cog):
|
||||
self.checks.discard(cog.qualified_name)
|
||||
|
||||
async def log_event(self, event: str, payload: t.NamedTuple):
|
||||
is_global = await bank.is_global()
|
||||
guild = (
|
||||
payload.member.guild
|
||||
if event == "payday_claim" and isinstance(payload.member, discord.Member)
|
||||
else getattr(payload, "guild", None)
|
||||
)
|
||||
if not is_global and not guild:
|
||||
log.error(f"Guild is None for non-global bank event: {event}\n{payload}")
|
||||
return
|
||||
logs = self.db.logs if is_global else self.db.get_conf(guild).logs
|
||||
channel_id = getattr(logs, event, 0) or logs.default_log_channel
|
||||
if not channel_id:
|
||||
return
|
||||
channel: discord.TextChannel = self.bot.get_channel(channel_id)
|
||||
if not channel:
|
||||
return
|
||||
event_map = {
|
||||
"set_balance": _("Set Balance"),
|
||||
"transfer_credits": _("Transfer Credits"),
|
||||
"bank_wipe": _("Bank Wipe"),
|
||||
"prune": _("Prune Accounts"),
|
||||
"set_global": _("Set Global"),
|
||||
"payday_claim": _("Payday Claim"),
|
||||
}
|
||||
currency = await bank.get_currency_name(guild)
|
||||
title = _("Bank Event: {}").format(event_map[event])
|
||||
color = await self.bot.get_embed_color(channel)
|
||||
embed = discord.Embed(title=title, color=color, timestamp=datetime.now())
|
||||
if event == "set_balance":
|
||||
embed.add_field(name=_("Recipient"), value=f"{payload.recipient.mention}\n`{payload.recipient.id}`")
|
||||
embed.add_field(name=_("Old Balance"), value=humanize_number(payload.recipient_old_balance))
|
||||
embed.add_field(name=_("New Balance"), value=humanize_number(payload.recipient_new_balance))
|
||||
if guild and is_global:
|
||||
embed.add_field(name=_("Guild"), value=guild.name)
|
||||
elif event == "transfer_credits":
|
||||
embed.add_field(name=_("Sender"), value=f"{payload.sender.mention}\n`{payload.sender.id}`")
|
||||
embed.add_field(name=_("Recipient"), value=f"{payload.recipient.mention}\n`{payload.recipient.id}`")
|
||||
embed.add_field(name=_("Transfer Amount"), value=f"{humanize_number(payload.transfer_amount)} {currency}")
|
||||
if guild and is_global:
|
||||
embed.add_field(name=_("Guild"), value=guild.name)
|
||||
elif event == "prune":
|
||||
if payload.user_id:
|
||||
embed.add_field(name=_("User ID"), value=payload.user_id)
|
||||
else:
|
||||
embed.add_field(name=_("Pruned Users"), value=humanize_number(len(payload.pruned_users)))
|
||||
if guild and is_global:
|
||||
embed.add_field(name=_("Guild"), value=guild.name)
|
||||
elif event == "payday_claim":
|
||||
embed.add_field(name=_("Recipient"), value=f"{payload.member.mention}\n`{payload.member.id}`")
|
||||
embed.add_field(name=_("Amount"), value=f"{humanize_number(payload.amount)} {currency}")
|
||||
embed.add_field(name=_("Old Balance"), value=humanize_number(payload.old_balance))
|
||||
embed.add_field(name=_("New Balance"), value=humanize_number(payload.new_balance))
|
||||
if is_global:
|
||||
embed.add_field(name=_("Guild"), value=guild.name if guild else _("Unknown"))
|
||||
else:
|
||||
embed.add_field(name=_("Channel"), value=payload.channel.mention)
|
||||
if message := getattr(payload, "message", None):
|
||||
embed.add_field(name=_("Message"), value=f"[Jump]({message.jump_url})")
|
||||
else:
|
||||
log.error(f"Unknown event type: {event}")
|
||||
return
|
||||
if channel.id in self.payloads:
|
||||
self.payloads[channel.id].append(embed)
|
||||
else:
|
||||
self.payloads[channel.id] = [embed]
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_set_balance(self, payload: t.NamedTuple):
|
||||
"""Payload attributes:
|
||||
- recipient: Union[discord.Member, discord.User]
|
||||
- guild: Union[discord.Guild, None]
|
||||
- recipient_old_balance: int
|
||||
- recipient_new_balance: int
|
||||
"""
|
||||
await self.log_event("set_balance", payload)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_transfer_credits(self, payload: t.NamedTuple):
|
||||
"""Payload attributes:
|
||||
- sender: Union[discord.Member, discord.User]
|
||||
- recipient: Union[discord.Member, discord.User]
|
||||
- guild: Union[discord.Guild, None]
|
||||
- transfer_amount: int
|
||||
- sender_new_balance: int
|
||||
- recipient_new_balance: int
|
||||
"""
|
||||
await self.log_event("transfer_credits", payload)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_wipe(self, scope: t.Optional[int] = None):
|
||||
"""scope: int (-1 for global, None for all members, guild_id for server bank)"""
|
||||
if scope == -1 or scope is None:
|
||||
log_channel_id = self.db.logs.bank_wipe or self.db.logs.default_log_channel
|
||||
txt = _("Global bank has been wiped!")
|
||||
elif scope is None:
|
||||
log_channel_id = self.db.logs.bank_wipe or self.db.logs.default_log_channel
|
||||
txt = _("All bank accounts for all guilds have been wiped!")
|
||||
else:
|
||||
# Scope is a guild ID
|
||||
guild: discord.Guild = self.bot.get_guild(scope)
|
||||
if not guild:
|
||||
return
|
||||
conf = self.db.get_conf(guild)
|
||||
log_channel_id = conf.logs.bank_wipe or conf.logs.default_log_channel
|
||||
txt = _("Bank accounts have been wiped!")
|
||||
|
||||
if not log_channel_id:
|
||||
return
|
||||
log_channel: discord.TextChannel = self.bot.get_channel(log_channel_id)
|
||||
if not log_channel:
|
||||
return
|
||||
|
||||
embed = discord.Embed(
|
||||
title=_("Bank Wipe"),
|
||||
description=txt,
|
||||
color=await self.bot.get_embed_color(log_channel),
|
||||
)
|
||||
with suppress(discord.HTTPException, discord.Forbidden):
|
||||
await log_channel.send(embed=embed)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_prune(self, payload: t.NamedTuple):
|
||||
"""Payload attributes:
|
||||
- guild: Union[discord.Guild, None]
|
||||
- user_id: Union[int, None]
|
||||
- scope: int (1 for global, 2 for server, 3 for user)
|
||||
- pruned_users: list[int(user_id)] or dict[int(guild_id), list[int(user_id)]]
|
||||
"""
|
||||
await self.log_event("prune", payload)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_bank_set_global(self, is_global: bool):
|
||||
"""is_global: True if global bank, False if server bank"""
|
||||
txt = _("Bank has been set to Global!") if is_global else _("Bank has been set to per-server!")
|
||||
log_channel_id = self.db.logs.set_global or self.db.logs.default_log_channel
|
||||
if not log_channel_id:
|
||||
return
|
||||
log_channel: discord.TextChannel = self.bot.get_channel(log_channel_id)
|
||||
if not log_channel:
|
||||
return
|
||||
embed = discord.Embed(
|
||||
title=_("Set Global Bank"),
|
||||
description=txt,
|
||||
color=await self.bot.get_embed_color(log_channel),
|
||||
)
|
||||
# with suppress(discord.HTTPException, discord.Forbidden):
|
||||
await log_channel.send(embed=embed)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_economy_payday_claim(self, payload: t.NamedTuple):
|
||||
"""Payload attributes:
|
||||
- member: discord.Member
|
||||
- channel: Union[discord.TextChannel, discord.Thread, discord.ForumChannel]
|
||||
- amount: int
|
||||
- old_balance: int
|
||||
- new_balance: int
|
||||
"""
|
||||
await self.log_event("payday_claim", payload)
|
||||
|
||||
@tasks.loop(seconds=4)
|
||||
async def send_payloads(self):
|
||||
"""Send embeds in chunks to avoid rate limits"""
|
||||
if not self.payloads:
|
||||
return
|
||||
tmp = self.payloads.copy()
|
||||
self.payloads.clear()
|
||||
for channel_id, embeds in tmp.items():
|
||||
channel = self.bot.get_channel(channel_id)
|
||||
if not channel:
|
||||
continue
|
||||
# Group the embeds into 5 per message
|
||||
for i in range(0, len(embeds), 5):
|
||||
chunk = embeds[i : i + 5]
|
||||
with suppress(discord.HTTPException, discord.Forbidden):
|
||||
await channel.send(embeds=chunk)
|
145
extendedeconomy/common/models.py
Normal file
145
extendedeconomy/common/models.py
Normal file
|
@ -0,0 +1,145 @@
|
|||
import json
|
||||
import math
|
||||
import typing as t
|
||||
from datetime import datetime
|
||||
|
||||
import discord
|
||||
from redbot.core import bank
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.i18n import Translator
|
||||
|
||||
from . import Base
|
||||
|
||||
_ = Translator("ExtendedEconomy", __file__)
|
||||
|
||||
|
||||
class PaydayClaimInformation(t.NamedTuple):
|
||||
member: discord.Member
|
||||
channel: t.Union[discord.TextChannel, discord.Thread, discord.ForumChannel]
|
||||
message: discord.Message
|
||||
amount: int
|
||||
old_balance: int
|
||||
new_balance: int
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"member": self.member.id,
|
||||
"channel": self.channel.id,
|
||||
"message": self.message.id,
|
||||
"amount": self.amount,
|
||||
"old_balance": self.old_balance,
|
||||
"new_balance": self.new_balance,
|
||||
}
|
||||
|
||||
def to_json(self) -> str:
|
||||
return json.dumps(self.to_dict())
|
||||
|
||||
|
||||
class CommandCost(Base):
|
||||
"""
|
||||
- cost: the base cost of the command
|
||||
- duration: the time period in seconds in which the command usage is tracked and used to calculate the cost
|
||||
- level: the minimum permission level of the command in which the cost is applied
|
||||
- admin: admins and above can use the command for free
|
||||
- mod: mods and above can use the command for free
|
||||
- all: everyone must pay the cost to use the command
|
||||
- user: all users must pay the cost to use the command unless they are mod or admin
|
||||
- global: the cost is applied to all users globally
|
||||
- prompt: how will the user be prompted to confirm the cost (Slash commands will always use silent mode)
|
||||
- text: the bot will send a text message asking the user to confirm the cost with yes or no
|
||||
- reaction: the bot will send a message with emoji reactions to confirm the cost
|
||||
- button: the bot will send a message with buttons to confirm the cost
|
||||
- silent: the bot will not prompt the user to confirm the cost
|
||||
- notify: the bot will simply notify the user of the cost without asking for confirmation
|
||||
- modifier: the type of cost modifier
|
||||
- static: the cost is a fixed amount
|
||||
- percent: the cost is a percentage of the user's balance on top of the base cost
|
||||
- exponential: the cost increases exponentially based on how frequenty the command is used
|
||||
- Ex: cost gets doubled every time the command is used within a set time period
|
||||
- linear: the cost increases linearly based on how frequently the command is used
|
||||
- Ex: cost gets increased by a fixed amount every time the command is used within a set time period
|
||||
- value: the value of the cost modifier depends on the modifier type
|
||||
- static: this will be 0 and does nothing
|
||||
- percent: value will be the percentage of the user's balance to add to the base cost
|
||||
- exponential: value will be the base cost multiplier
|
||||
- linear: value will multiplied by the number of uses in the last hour to get the cost increase
|
||||
- uses: a list of lists containing the user ID and the timestamp of the command usage
|
||||
"""
|
||||
|
||||
cost: int
|
||||
duration: int
|
||||
level: t.Literal["admin", "mod", "all", "user", "global"]
|
||||
prompt: t.Literal["text", "reaction", "button", "silent", "notify"]
|
||||
modifier: t.Literal["static", "percent", "exponential", "linear"]
|
||||
value: float
|
||||
uses: t.List[t.List[t.Union[int, float]]] = []
|
||||
|
||||
async def get_cost(self, bot: Red, user: t.Union[discord.Member, discord.User]) -> int:
|
||||
if self.level == "global" and user.id in bot.owner_ids:
|
||||
return 0
|
||||
elif self.level != "global":
|
||||
free = [
|
||||
await bot.is_admin(user) and self.level in ["admin", "mod"],
|
||||
await bot.is_mod(user) and self.level == "mod",
|
||||
]
|
||||
if any(free):
|
||||
return 0
|
||||
if self.modifier == "static":
|
||||
return self.cost
|
||||
if self.modifier == "percent":
|
||||
bal = await bank.get_balance(user)
|
||||
return math.ceil(self.cost + (bal * self.value))
|
||||
min_time = datetime.now().timestamp() - self.duration
|
||||
uses_in_duration = len([u for u in self.uses if u[0] == user.id and u[1] > min_time])
|
||||
if self.modifier == "exponential":
|
||||
return math.ceil(self.cost + self.value * (2**uses_in_duration))
|
||||
if self.modifier == "linear":
|
||||
return math.ceil(self.cost + (self.value * uses_in_duration))
|
||||
raise ValueError(f"Invalid cost modifier: {self.modifier}")
|
||||
|
||||
def update_usage(self, user_id: int):
|
||||
self.uses.append([user_id, datetime.now().timestamp()])
|
||||
self.uses = [u for u in self.uses if u[1] > datetime.now().timestamp() - self.duration]
|
||||
|
||||
|
||||
class LogChannels(Base):
|
||||
default_log_channel: int = 0
|
||||
# Event log channel overrides
|
||||
set_balance: int = 0
|
||||
transfer_credits: int = 0
|
||||
bank_wipe: int = 0
|
||||
prune: int = 0
|
||||
set_global: int = 0
|
||||
payday_claim: int = 0
|
||||
|
||||
auto_claim: int = 0
|
||||
|
||||
|
||||
class GuildSettings(Base):
|
||||
logs: LogChannels = LogChannels()
|
||||
command_costs: t.Dict[str, CommandCost] = {}
|
||||
transfer_tax: float = 0.0
|
||||
transfer_tax_whitelist: t.List[int] = [] # Role IDs that are exempt from transfer tax
|
||||
|
||||
# Unique to GuildSettings (local bank only)
|
||||
stack_paydays: bool = False
|
||||
auto_claim_roles: t.List[int] = [] # Role IDs that auto claim paydays
|
||||
role_bonuses: t.Dict[int, float] = {} # Role ID: bonus multiplier
|
||||
|
||||
|
||||
class DB(Base):
|
||||
configs: t.Dict[int, GuildSettings] = {}
|
||||
delete_after: t.Union[int, None] = None
|
||||
|
||||
logs: LogChannels = LogChannels()
|
||||
command_costs: t.Dict[str, CommandCost] = {}
|
||||
transfer_tax: float = 0.0
|
||||
|
||||
auto_payday_claim: bool = False # If True, guilds that set auto_claim_roles will auto claim paydays
|
||||
|
||||
# Allow prices per guild when global bank is enabled
|
||||
# per_guild_override: bool = False
|
||||
|
||||
def get_conf(self, guild: discord.Guild | int) -> GuildSettings:
|
||||
gid = guild if isinstance(guild, int) else guild.id
|
||||
return self.configs.setdefault(gid, GuildSettings())
|
30
extendedeconomy/common/parser.py
Normal file
30
extendedeconomy/common/parser.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator
|
||||
|
||||
_ = Translator("ExtendedEconomy", __file__)
|
||||
|
||||
|
||||
class SetParser:
|
||||
def __init__(self, argument):
|
||||
allowed = ("+", "-")
|
||||
try:
|
||||
self.sum = int(argument)
|
||||
except ValueError:
|
||||
raise commands.BadArgument(
|
||||
_("Invalid value, the argument must be an integer, optionally preceded with a `+` or `-` sign.")
|
||||
)
|
||||
if argument and argument[0] in allowed:
|
||||
if self.sum < 0:
|
||||
self.operation = "withdraw"
|
||||
elif self.sum > 0:
|
||||
self.operation = "deposit"
|
||||
else:
|
||||
raise commands.BadArgument(
|
||||
_(
|
||||
"Invalid value, the amount of currency to increase or decrease"
|
||||
" must be an integer different from zero."
|
||||
)
|
||||
)
|
||||
self.sum = abs(self.sum)
|
||||
else:
|
||||
self.operation = "set"
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue