Ruby-Cogs/extendedeconomy/common/tasks.py
2025-05-23 02:30:00 -04:00

130 lines
5.9 KiB
Python

import calendar
import logging
import typing as t
from contextlib import suppress
from datetime import datetime, timezone
import discord
from discord.ext import tasks
from redbot.core import Config, bank
from redbot.core.i18n import Translator
from redbot.core.utils.chat_formatting import humanize_number, text_to_file
from ..abc import MixinMeta
log = logging.getLogger("red.vrt.extendedeconomy.tasks")
_ = Translator("ExtendedEconomy", __file__)
class Tasks(MixinMeta):
@tasks.loop(seconds=60)
async def auto_paydays(self):
if not self.db.auto_payday_claim:
return
cog = self.bot.get_cog("Economy")
if cog is None:
return
eco_conf: Config = cog.config
is_global = await bank.is_global()
cur_time = calendar.timegm(datetime.now(tz=timezone.utc).utctimetuple())
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()
updated = []
for user in self.bot.users:
uid = str(user.id)
if uid not in accounts or uid not in ecousers:
# Reduce unnecessary writes for users that havent used economy
continue
next_payday = ecousers[uid].get("next_payday", 0) + payday_time
if cur_time < next_payday:
# Not ready yet
continue
accounts[uid]["balance"] = min(max_bal, accounts[uid]["balance"] + payday_credits)
ecousers[uid]["next_payday"] = cur_time
updated.append((f"{user.name} ({user.id}): {humanize_number(payday_credits)}\n", payday_credits))
if updated:
await bankgroup.set(accounts)
await ecogroup.set(ecousers)
if self.db.logs.auto_claim:
log.info(f"Claimed {len(updated)} global paydays")
ordered = sorted(updated, key=lambda x: x[1], reverse=True)
claimed = "\n".join([x[0] for x in ordered])
channel = self.bot.get_channel(self.db.logs.auto_claim)
if channel is not None:
with suppress(discord.HTTPException):
await channel.send(
f"Claimed {len(updated)} global paydays",
file=text_to_file(claimed, "paydays.txt"),
)
else:
keys = list(self.db.configs.keys())
for guild_id in keys:
guild = self.bot.get_guild(guild_id)
if guild is None:
continue
conf = self.db.configs[guild_id]
if not conf.auto_claim_roles:
continue
bankgroup = bank._config._get_base_group(bank._config.MEMBER, str(guild_id))
ecogroup = eco_conf._get_base_group(eco_conf.MEMBER, str(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(guild)
payday_time = await eco_conf.guild(guild).PAYDAY_TIME()
payday_credits = await eco_conf.guild(guild).PAYDAY_CREDITS()
payday_roles: t.Dict[int, dict] = await eco_conf.all_roles()
updated = []
for member in guild.members:
uid = str(member.id)
if uid not in accounts or uid not in ecousers:
# Reduce unnecessary writes for members that havent used economy
continue
next_payday = ecousers[uid].get("next_payday", 0) + payday_time
if cur_time < next_payday:
# Not ready yet
continue
to_give = payday_credits
can_autoclaim = False
for role in member.roles:
if role.id in payday_roles:
role_credits = payday_roles[role.id]["PAYDAY_CREDITS"]
if conf.stack_paydays:
to_give += role_credits
elif role_credits > to_give:
to_give = role_credits
if role.id in conf.auto_claim_roles:
can_autoclaim = True
if not can_autoclaim:
continue
accounts[uid]["balance"] = min(max_bal, accounts[uid]["balance"] + to_give)
ecousers[uid]["next_payday"] = cur_time
updated.append((f"{member.name} ({member.id}): {humanize_number(to_give)}\n", to_give))
if updated:
await bankgroup.set(accounts)
await ecogroup.set(ecousers)
if conf.logs.auto_claim:
log.debug(f"Claimed {len(updated)} paydays in {guild.name}")
ordered = sorted(updated, key=lambda x: x[1], reverse=True)
claimed = "\n".join([x[0] for x in ordered])
channel = guild.get_channel(conf.logs.auto_claim)
if channel is not None:
with suppress(discord.HTTPException):
await channel.send(
f"Claimed {len(updated)} paydays",
file=text_to_file(claimed, "paydays.txt"),
)