154 lines
5.5 KiB
Python
154 lines
5.5 KiB
Python
import logging
|
|
import random
|
|
from time import perf_counter
|
|
|
|
import discord
|
|
from redbot.core import commands
|
|
|
|
from ..abc import MixinMeta
|
|
|
|
log = logging.getLogger("red.vrt.levelup.listeners.messages")
|
|
|
|
|
|
class MessageListener(MixinMeta):
|
|
@commands.Cog.listener()
|
|
async def on_message(self, message: discord.Message):
|
|
# If message object is None for some reason
|
|
if not message:
|
|
return
|
|
# If message wasn't sent in a guild
|
|
if not message.guild:
|
|
return
|
|
# If message was from a bot
|
|
if message.author.bot and self.db.ignore_bots:
|
|
return
|
|
# Check if guild is in the master ignore list
|
|
if str(message.guild.id) in self.db.ignored_guilds:
|
|
return
|
|
# Ignore webhooks
|
|
if not isinstance(message.author, discord.Member):
|
|
return
|
|
# Check if cog is disabled
|
|
if await self.bot.cog_disabled_in_guild(self, message.guild):
|
|
return
|
|
try:
|
|
roles = list(message.author.roles)
|
|
role_ids = [role.id for role in roles]
|
|
except AttributeError:
|
|
# User sent messange and left immediately?
|
|
return
|
|
conf = self.db.get_conf(message.guild)
|
|
if not conf.enabled:
|
|
return
|
|
|
|
user_id = message.author.id
|
|
if user_id in conf.ignoredusers:
|
|
# If we're specifically ignoring a user we don't want to see them anywhere
|
|
return
|
|
|
|
profile = conf.get_profile(user_id).add_message()
|
|
weekly = None
|
|
if conf.weeklysettings.on:
|
|
weekly = conf.get_weekly_profile(message.author).add_message()
|
|
|
|
if perf_counter() - self.last_save > 300:
|
|
# Save at least every 5 minutes
|
|
self.save()
|
|
|
|
prefixes = await self.bot.get_valid_prefixes(guild=message.guild)
|
|
if not conf.command_xp and message.content.startswith(tuple(prefixes)):
|
|
# Don't give XP for commands
|
|
return
|
|
|
|
if conf.allowedchannels:
|
|
# Make sure the channel is allowed
|
|
if message.channel.id not in conf.allowedchannels:
|
|
# See if its category or parent channel is allowed then
|
|
if isinstance(message.channel, (discord.Thread, discord.ForumChannel)):
|
|
channel_id = message.channel.parent_id
|
|
if channel_id not in conf.allowedchannels:
|
|
# Mabe the parent channel's category is allowed?
|
|
category_id = message.channel.parent.category_id
|
|
if category_id not in conf.allowedchannels:
|
|
# Nope, not allowed
|
|
return
|
|
else:
|
|
channel_id = message.channel.category_id
|
|
if channel_id and channel_id not in conf.allowedchannels:
|
|
return
|
|
|
|
if message.channel.id in conf.ignoredchannels:
|
|
return
|
|
if (
|
|
isinstance(
|
|
message.channel,
|
|
(
|
|
discord.Thread,
|
|
discord.ForumChannel,
|
|
),
|
|
)
|
|
and message.channel.parent_id in conf.ignoredchannels
|
|
):
|
|
return
|
|
elif message.channel.category_id and message.channel.category_id in conf.ignoredchannels:
|
|
return
|
|
|
|
if conf.allowedroles:
|
|
# Make sure the user has at least one allowed role
|
|
if not any(role in conf.allowedroles for role in role_ids):
|
|
return
|
|
|
|
if any(role in conf.ignoredroles for role in role_ids):
|
|
return
|
|
now = perf_counter()
|
|
last_messages = self.lastmsg.setdefault(message.guild.id, {})
|
|
addxp = False
|
|
if len(message.content) > conf.min_length:
|
|
if user_id not in last_messages:
|
|
addxp = True
|
|
elif now - last_messages[user_id] > conf.cooldown:
|
|
addxp = True
|
|
|
|
if not addxp:
|
|
return
|
|
|
|
self.lastmsg[message.guild.id][user_id] = now
|
|
|
|
xp_to_add = random.randint(conf.xp[0], conf.xp[1])
|
|
# Add channel bonus if it exists
|
|
channel_bonuses = conf.channelbonus.msg
|
|
category = None
|
|
if isinstance(message.channel, discord.Thread):
|
|
parent = message.channel.parent
|
|
if parent:
|
|
category = parent.category
|
|
else:
|
|
category = message.channel.category
|
|
cat_id = category.id if category else 0
|
|
|
|
if message.channel.id in channel_bonuses:
|
|
xp_to_add += random.randint(*channel_bonuses[message.channel.id])
|
|
elif cat_id in channel_bonuses:
|
|
xp_to_add += random.randint(*channel_bonuses[cat_id])
|
|
# Stack all role bonuses
|
|
for role_id, (bonus_min, bonus_max) in conf.rolebonus.msg.items():
|
|
if role_id in role_ids:
|
|
xp_to_add += random.randint(bonus_min, bonus_max)
|
|
# Add the xp to the role groups
|
|
for role_id in role_ids:
|
|
if role_id in conf.role_groups:
|
|
conf.role_groups[role_id] += xp_to_add
|
|
# Add the xp to the user's profile
|
|
log.debug(f"Adding {xp_to_add} xp to {message.author.name} in {message.guild.name}")
|
|
profile.xp += xp_to_add
|
|
if weekly:
|
|
weekly.xp += xp_to_add
|
|
# Check for levelups
|
|
await self.check_levelups(
|
|
guild=message.guild,
|
|
member=message.author,
|
|
profile=profile,
|
|
conf=conf,
|
|
message=message,
|
|
channel=message.channel,
|
|
)
|