232 lines
8.5 KiB
Python
232 lines
8.5 KiB
Python
from typing import Optional
|
|
import asyncio
|
|
from collections import defaultdict
|
|
|
|
from settings.groups import SettingGroup
|
|
from settings.data import ModelData, ListData
|
|
from settings.setting_types import ChannelListSetting, IntegerSetting
|
|
|
|
from meta.config import conf
|
|
from meta.sharding import THIS_SHARD
|
|
from meta.logger import log_wrap
|
|
from core.data import CoreData
|
|
from babel.translator import ctx_translator
|
|
|
|
from . import babel, logger
|
|
from .data import TextTrackerData
|
|
|
|
_p = babel._p
|
|
|
|
|
|
class TextTrackerSettings(SettingGroup):
|
|
"""
|
|
Guild settings:
|
|
xp per period (guild_config.period_xp)
|
|
additional xp per hundred words (guild_config.word_xp)
|
|
coins per hundred xp (guild_config.xp_coins)
|
|
untracked channels (untracked_text_channels(channelid PK, guildid FK))
|
|
"""
|
|
class XPPerPeriod(ModelData, IntegerSetting):
|
|
setting_id = 'xp_per_period'
|
|
_set_cmd = 'configure message_exp'
|
|
|
|
_display_name = _p('guildset:xp_per_period', "xp_per_5min")
|
|
_desc = _p(
|
|
'guildset:xp_per_period|desc',
|
|
"How much XP members will be given every 5 minute period they are active."
|
|
)
|
|
_long_desc = _p(
|
|
'guildset:xp_per_period|long_desc',
|
|
"Amount of message XP to give members for each 5 minute period in which they are active (send a message). "
|
|
"Note that this XP is only given *once* per period."
|
|
)
|
|
_accepts = _p(
|
|
'guildset:xp_per_period|accepts',
|
|
"Number of message XP to reward per 5 minute active period."
|
|
)
|
|
_default = 101 # TODO: Make a dynamic default based on the global setting?
|
|
|
|
_model = CoreData.Guild
|
|
_column = CoreData.Guild.xp_per_period.name
|
|
|
|
@property
|
|
def update_message(self):
|
|
t = ctx_translator.get().t
|
|
return t(_p(
|
|
'guildset:xp_per_period|set_response',
|
|
"For every **5** minutes they are active (i.e. in which they send a message), "
|
|
"members will now be given **{amount}** XP."
|
|
)).format(amount=self.value)
|
|
|
|
class WordXP(ModelData, IntegerSetting):
|
|
setting_id = 'word_xp'
|
|
_set_cmd = 'configure message_exp'
|
|
|
|
_display_name = _p('guildset:word_xp', "xp_per_100words")
|
|
_desc = _p(
|
|
'guildset:word_xp|desc',
|
|
"How much XP members will be given per hundred words they write."
|
|
)
|
|
_long_desc = _p(
|
|
'guildset:word_xp|long_desc',
|
|
"Amount of message XP to be given (additionally to the XP per period) for each hundred words. "
|
|
"Useful for rewarding communication."
|
|
)
|
|
_accepts = _p(
|
|
'guildset:word_xp|accepts',
|
|
"Number of XP to reward per hundred words sent."
|
|
)
|
|
_default = 50
|
|
|
|
_model = CoreData.Guild
|
|
_column = CoreData.Guild.xp_per_centiword.name
|
|
|
|
@property
|
|
def update_message(self):
|
|
t = ctx_translator.get().t
|
|
return t(_p(
|
|
'guildset:word_xp|set_response',
|
|
"For every **100** words they send, members will now be rewarded an additional **{amount}** XP."
|
|
)).format(amount=self.value)
|
|
|
|
class UntrackedTextChannels(ListData, ChannelListSetting):
|
|
setting_id = 'untracked_text_channels'
|
|
|
|
_display_name = _p('guildset:untracked_text_channels', "untracked_text_channels")
|
|
_desc = _p(
|
|
'guildset:untracked_text_channels|desc',
|
|
"Channels in which Message XP will not be given."
|
|
)
|
|
_long_desc = _p(
|
|
'guildset:untracked_text_channels|long_desc',
|
|
"Messages sent in these channels will not count towards a member's message XP. "
|
|
"If a category is selected, then all channels under the category will also be untracked."
|
|
)
|
|
_accepts = _p(
|
|
'guildset:untracked_text_channels|accepts',
|
|
"Comma separated list of untracked text channel names or ids."
|
|
)
|
|
_notset_str = _p(
|
|
'guildset:untracked_text_channels|notset',
|
|
"Not Set (all text channels will be tracked.)"
|
|
)
|
|
|
|
_default = None
|
|
_table_interface = TextTrackerData.untracked_channels
|
|
_id_column = 'guildid'
|
|
_data_column = 'channelid'
|
|
_order_column = 'channelid'
|
|
|
|
_cache = {}
|
|
|
|
@property
|
|
def update_message(self):
|
|
t = ctx_translator.get().t
|
|
if self.data:
|
|
resp = t(_p(
|
|
'guildset:untracked_text_channels|set_response|set',
|
|
"Messages in or under the following channels will be ignored: {channels}"
|
|
)).format(channels=self.formatted)
|
|
else:
|
|
resp = t(_p(
|
|
'guildset:untracked_text_channels|set_response|notset',
|
|
"Message XP will now be tracked in every channel."
|
|
))
|
|
return resp
|
|
|
|
@property
|
|
def set_str(self) -> str:
|
|
t = ctx_translator.get().t
|
|
return t(_p(
|
|
'guildset:untracked_text_channels|set_using',
|
|
"Channel selector below"
|
|
))
|
|
|
|
@classmethod
|
|
@log_wrap(action='Cache Untracked Text Channels')
|
|
async def setup(cls, bot):
|
|
"""
|
|
Pre-load untracked text channels for every guild on the current shard.
|
|
"""
|
|
data: TextTrackerData = bot.db.registries['TextTrackerData']
|
|
# TODO: Filter by joining on guild_config with last_left = NULL
|
|
# Otherwise we are also caching all the guilds we left
|
|
rows = await data.untracked_channels.select_where(THIS_SHARD)
|
|
new_cache = defaultdict(list)
|
|
count = 0
|
|
for row in rows:
|
|
new_cache[row['guildid']].append(row['channelid'])
|
|
count += 1
|
|
cls._cache.clear()
|
|
cls._cache.update(new_cache)
|
|
logger.info(f"Loaded {count} untracked text channels on this shard.")
|
|
|
|
|
|
class TextTrackerGlobalSettings(SettingGroup):
|
|
"""
|
|
Configure global XP rates for the text tracker.
|
|
"""
|
|
class XPPerPeriod(ModelData, IntegerSetting):
|
|
setting_id = 'xp_per_period'
|
|
_set_cmd = 'leo configure experience_rates'
|
|
|
|
_display_name = _p('botset:xp_per_period', "xp_per_5min")
|
|
_desc = _p(
|
|
'botset:xp_per_period|desc',
|
|
"How much global XP members will be given every 5 minute period they are active."
|
|
)
|
|
_long_desc = _p(
|
|
'botset:xp_per_period|long_desc',
|
|
"Amount of global message XP to give members "
|
|
"for each 5 minute period in which they are active (send a message). "
|
|
"Note that this XP is only given *once* per period."
|
|
)
|
|
_accepts = _p(
|
|
'botset:xp_per_period|accepts',
|
|
"Number of message XP to reward per 5 minute active period."
|
|
)
|
|
_default = 101
|
|
|
|
_model = TextTrackerData.BotConfigText
|
|
_column = TextTrackerData.BotConfigText.xp_per_period.name
|
|
|
|
@property
|
|
def update_message(self):
|
|
t = ctx_translator.get().t
|
|
return t(_p(
|
|
'leoset:xp_per_period|set_response',
|
|
"For every **5** minutes they are active (i.e. in which they send a message), "
|
|
"all users will now be given **{amount}** global XP."
|
|
)).format(amount=self.value)
|
|
|
|
class WordXP(ModelData, IntegerSetting):
|
|
setting_id = 'word_xp'
|
|
_set_cmd = 'leo configure experience_rates'
|
|
|
|
_display_name = _p('botset:word_xp', "xp_per_100words")
|
|
_desc = _p(
|
|
'botset:word_xp|desc',
|
|
"How much global XP members will be given per hundred words they write."
|
|
)
|
|
_long_desc = _p(
|
|
'botset:word_xp|long_desc',
|
|
"Amount of global message XP to be given (additionally to the XP per period) for each hundred words. "
|
|
"Useful for rewarding communication."
|
|
)
|
|
_accepts = _p(
|
|
'botset:word_xp|accepts',
|
|
"Number of XP to reward per hundred words sent."
|
|
)
|
|
_default = 50
|
|
|
|
_model = TextTrackerData.BotConfigText
|
|
_column = TextTrackerData.BotConfigText.xp_per_centiword.name
|
|
|
|
@property
|
|
def update_message(self):
|
|
t = ctx_translator.get().t
|
|
return t(_p(
|
|
'leoset:word_xp|set_response',
|
|
"For every **100** words they send, users will now be rewarded an additional **{amount}** global XP."
|
|
)).format(amount=self.value)
|