Merge branch 'master' into fifo_develop

pull/145/head
bobloy 4 years ago
commit bed6cf8bb7

@ -14,11 +14,13 @@ Cog Function
| exclusiverole | **Alpha** | <details><summary>Prevent certain roles from getting any other roles</summary>Fully functional, but pretty simple</details> |
| fifo | **Alpha** | <details><summary>Schedule commands to be run at certain times or intervals</summary>Just released, please report bugs as you find them. Only works for bot owner for now</details> |
| fight | **Incomplete** | <details><summary>Organize bracket tournaments within discord</summary>Still in-progress, a massive project</details> |
| firstmessage | **Release** | <details><summary>Simple cog to provide a jump link to the first message in a channel/summary>Just released, please report bugs as you find them.</details> |
| flag | **Alpha** | <details><summary>Create temporary marks on users that expire after specified time</summary>Ported, will not import old data. Please report bugs</details> |
| forcemention | **Alpha** | <details><summary>Mentions unmentionable roles</summary>Very simple cog, mention doesn't persist</details> |
| hangman | **Beta** | <details><summary>Play a game of hangman</summary>Some visual glitches and needs more customization</details> |
| howdoi | **Incomplete** | <details><summary>Ask coding questions and get results from StackExchange</summary>Not yet functional</details> |
| infochannel | **Beta** | <details><summary>Create a channel to display server info</summary>Just released, please report bugs</details> |
| infochannel | **Beta** | <details><summary>Create a channel to display server info</summary>Due to rate limits, this does not update as often as it once did</details> |
| isitdown | **Beta** | <details><summary>Check if a website/url is down</summary>Just released, please report bugs</details> |
| launchlib | **Beta** | <details><summary>Access rocket launch data</summary>Just released, please report bugs</details> |
| leaver | **Beta** | <details><summary>Send a message in a channel when a user leaves the server</summary>Seems to be functional, please report any bugs or suggestions</details> |
| lovecalculator | **Alpha** | <details><summary>Calculate the love between two users</summary>[Snap-Ons] Just updated to V3</details> |
@ -38,7 +40,7 @@ Cog Function
| unicode | **Alpha** | <details><summary>Encode and Decode unicode characters</summary>[Snap-Ons] Just updated to V3</details> |
| werewolf | **Pre-Alpha** | <details><summary>Play the classic party game Werewolf within discord</summary>Another massive project currently being developed, will be fully customizable</details> |
Check out my V2 cogs at [Fox-Cogs v2](https://github.com/bobloy/Fox-Cogs)
Check out *Deprecated* my V2 cogs at [Fox-Cogs v2](https://github.com/bobloy/Fox-Cogs)
# Installation
### Recommended - Built-in Downloader

@ -1,8 +1,13 @@
"""Module to manage audio trivia sessions."""
import asyncio
import logging
import lavalink
from lavalink.enums import LoadType
from redbot.cogs.trivia import TriviaSession
from redbot.core.utils.chat_formatting import bold
log = logging.getLogger("red.fox_v3.audiotrivia.audiosession")
class AudioSession(TriviaSession):
@ -23,9 +28,9 @@ class AudioSession(TriviaSession):
async def run(self):
"""Run the audio trivia session.
In order for the trivia session to be stopped correctly, this should
only be called internally by `TriviaSession.start`.
"""
In order for the trivia session to be stopped correctly, this should
only be called internally by `TriviaSession.start`.
"""
await self._send_startup_msg()
max_score = self.settings["max_score"]
delay = self.settings["delay"]
@ -36,8 +41,9 @@ class AudioSession(TriviaSession):
self.count += 1
await self.player.stop()
msg = "**Question number {}!**\n\nName this audio!".format(self.count)
await self.ctx.send(msg)
msg = bold(f"Question number {self.count}!") + "\n\nName this audio!"
await self.ctx.maybe_send_embed(msg)
log.debug(f"Audio question: {question}")
# print("Audio question: {}".format(question))
# await self.ctx.invoke(self.audio.play(ctx=self.ctx, query=question))
@ -45,18 +51,28 @@ class AudioSession(TriviaSession):
# await self.ctx.invoke(self.player.play, query=question)
query = question.strip("<>")
tracks = await self.player.get_tracks(query)
seconds = tracks[0].length / 1000
load_result = await self.player.load_tracks(query)
log.debug(f"{load_result.load_type=}")
if load_result.has_error or load_result.load_type != LoadType.TRACK_LOADED:
await self.ctx.maybe_send_embed(f"Track has error, skipping. See logs for details")
log.info(f"Track has error: {load_result.exception_message}")
continue # Skip tracks with error
tracks = load_result.tracks
track = tracks[0]
seconds = track.length / 1000
if self.settings["repeat"] and seconds < delay:
# Append it until it's longer than the delay
tot_length = seconds + 0
while tot_length < delay:
self.player.add(self.ctx.author, tracks[0])
self.player.add(self.ctx.author, track)
tot_length += seconds
else:
self.player.add(self.ctx.author, tracks[0])
self.player.add(self.ctx.author, track)
if not self.player.current:
log.debug("Pressing play")
await self.player.play()
continue_ = await self.wait_for_answer(answers, delay, timeout)

@ -1,4 +1,5 @@
import datetime
import logging
import pathlib
from typing import List
@ -15,7 +16,7 @@ from redbot.core.utils.chat_formatting import box
from .audiosession import AudioSession
# from redbot.cogs.audio.utils import userlimit
log = logging.getLogger("red.fox_v3.audiotrivia")
class AudioTrivia(Trivia):
@ -83,24 +84,24 @@ class AudioTrivia(Trivia):
self.audio: Audio = self.bot.get_cog("Audio")
if self.audio is None:
await ctx.send("Audio is not loaded. Load it and try again")
await ctx.maybe_send_embed("Audio is not loaded. Load it and try again")
return
categories = [c.lower() for c in categories]
session = self._get_trivia_session(ctx.channel)
if session is not None:
await ctx.send("There is already an ongoing trivia session in this channel.")
await ctx.maybe_send_embed("There is already an ongoing trivia session in this channel.")
return
status = await self.audio.config.status()
notify = await self.audio.config.guild(ctx.guild).notify()
if status:
await ctx.send(
await ctx.maybe_send_embed(
f"It is recommended to disable audio status with `{ctx.prefix}audioset status`"
)
if notify:
await ctx.send(
await ctx.maybe_send_embed(
f"It is recommended to disable audio notify with `{ctx.prefix}audioset notify`"
)
@ -109,12 +110,12 @@ class AudioTrivia(Trivia):
if not ctx.author.voice.channel.permissions_for(
ctx.me
).connect or self.audio.is_vc_full(ctx.author.voice.channel):
return await ctx.send("I don't have permission to connect to your channel.")
return await ctx.maybe_send_embed("I don't have permission to connect to your channel.")
await lavalink.connect(ctx.author.voice.channel)
lavaplayer = lavalink.get_player(ctx.guild.id)
lavaplayer.store("connect", datetime.datetime.utcnow())
except AttributeError:
return await ctx.send("Connect to a voice channel first.")
return await ctx.maybe_send_embed("Connect to a voice channel first.")
lavaplayer = lavalink.get_player(ctx.guild.id)
lavaplayer.store("channel", ctx.channel.id) # What's this for? I dunno
@ -122,7 +123,7 @@ class AudioTrivia(Trivia):
await self.audio.set_player_settings(ctx)
if not ctx.author.voice or ctx.author.voice.channel != lavaplayer.channel:
return await ctx.send(
return await ctx.maybe_send_embed(
"You must be in the voice channel to use the audiotrivia command."
)
@ -134,13 +135,13 @@ class AudioTrivia(Trivia):
try:
dict_ = self.get_audio_list(category)
except FileNotFoundError:
await ctx.send(
await ctx.maybe_send_embed(
"Invalid category `{0}`. See `{1}audiotrivia list`"
" for a list of trivia categories."
"".format(category, ctx.prefix)
)
except InvalidListError:
await ctx.send(
await ctx.maybe_send_embed(
"There was an error parsing the trivia list for"
" the `{}` category. It may be formatted"
" incorrectly.".format(category)
@ -151,7 +152,7 @@ class AudioTrivia(Trivia):
continue
return
if not trivia_dict:
await ctx.send(
await ctx.maybe_send_embed(
"The trivia list was parsed successfully, however it appears to be empty!"
)
return
@ -166,7 +167,10 @@ class AudioTrivia(Trivia):
# Delay in audiosettings overwrites delay in settings
combined_settings = {**settings, **audiosettings}
session = AudioSession.start(
ctx=ctx, question_list=trivia_dict, settings=combined_settings, player=lavaplayer,
ctx=ctx,
question_list=trivia_dict,
settings=combined_settings,
player=lavaplayer,
)
self.trivia_sessions.append(session)
LOG.debug("New audio trivia session; #%s in %d", ctx.channel, ctx.guild.id)

@ -1,13 +1,13 @@
AUTHOR: Plab
https://www.youtube.com/watch?v=--bWm9hhoZo:
https://www.youtube.com/watch?v=f9O2Rjn1azc:
- Transistor
https://www.youtube.com/watch?v=-4nCbgayZNE:
https://www.youtube.com/watch?v=PgUhYFkVdSY:
- Dark Cloud 2
- Dark Cloud II
https://www.youtube.com/watch?v=-64NlME4lJU:
https://www.youtube.com/watch?v=1T1RZttyMwU:
- Mega Man 7
- Mega Man VII
https://www.youtube.com/watch?v=-AesqnudNuw:
https://www.youtube.com/watch?v=AdDbbzuq1vY:
- Mega Man 9
- Mega Man IX
https://www.youtube.com/watch?v=-BmGDtP2t7M:

@ -7,6 +7,7 @@ from discord.ext.commands.view import StringView
from redbot.core import Config, checks, commands
from redbot.core.bot import Red
from redbot.core.utils.chat_formatting import box, pagify
from redbot.core.utils.mod import get_audit_reason
log = logging.getLogger("red.fox_v3.ccrole")
@ -358,23 +359,24 @@ class CCRole(commands.Cog):
else:
target = message.author
reason = get_audit_reason(message.author)
if cmd["aroles"]:
arole_list = [
discord.utils.get(message.guild.roles, id=roleid) for roleid in cmd["aroles"]
]
try:
await target.add_roles(*arole_list)
await target.add_roles(*arole_list, reason=reason)
except discord.Forbidden:
log.exception(f"Permission error: Unable to add roles")
await ctx.send("Permission error: Unable to add roles")
await asyncio.sleep(1)
if cmd["rroles"]:
rrole_list = [
discord.utils.get(message.guild.roles, id=roleid) for roleid in cmd["rroles"]
]
try:
await target.remove_roles(*rrole_list)
await target.remove_roles(*rrole_list, reason=reason)
except discord.Forbidden:
log.exception(f"Permission error: Unable to remove roles")
await ctx.send("Permission error: Unable to remove roles")

@ -29,7 +29,7 @@ Chatter by default uses spaCy's `en_core_web_md` training model, which is ~50 MB
Chatter can potential use spaCy's `en_core_web_lg` training model, which is ~800 MB
Chatter uses as sqlite database that can potentially take up a large amount os disk space,
Chatter uses as sqlite database that can potentially take up a large amount of disk space,
depending on how much training Chatter has done.
The sqlite database can be safely deleted at any time. Deletion will only erase training data.
@ -50,7 +50,9 @@ Linux is a bit easier, but only tested on Debian and Ubuntu.
## Windows Prerequisites
Install these on your windows machine before attempting the installation
**Requires 64 Bit Python to continue on Windows.**
Install these on your windows machine before attempting the installation:
[Visual Studio C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
@ -83,6 +85,7 @@ pip install --no-deps "chatterbot>=1.1"
#### Step 3: Load Chatter
```
[p]repo add Fox https://github.com/bobloy/Fox-V3 # If you didn't already do this in step 1
[p]cog install Fox chatter
[p]load chatter
```
@ -92,7 +95,7 @@ pip install --no-deps "chatterbot>=1.1"
#### Step 1: Built-in Downloader
```
[p]cog install Chatter
[p]cog install <Fox> Chatter
```
#### Step 2: Install Requirements

@ -463,7 +463,7 @@ class Chatter(Cog):
# Thank you Cog-Creators
channel: discord.TextChannel = message.channel
if channel.id == await self.config.guild(guild).chatchannel():
if guild is not None and channel.id == await self.config.guild(guild).chatchannel():
pass # good to go
else:
when_mentionables = commands.when_mentioned(self.bot, message)

@ -10,6 +10,7 @@ from apscheduler.schedulers.base import STATE_PAUSED, STATE_RUNNING
from redbot.core import Config, checks, commands
from redbot.core.bot import Red
from redbot.core.commands import TimedeltaConverter
from redbot.core.utils.chat_formatting import pagify
from .datetime_cron_converters import CronConverter, DatetimeConverter, TimezoneConverter
from .task import Task
@ -306,7 +307,11 @@ class FIFO(commands.Cog):
out += f"{task_name}: {task_data}\n"
if out:
await ctx.maybe_send_embed(out)
if len(out) > 2000:
for page in pagify(out):
await ctx.maybe_send_embed(page)
else:
await ctx.maybe_send_embed(out)
else:
await ctx.maybe_send_embed("No tasks to list")

@ -16,6 +16,7 @@
"bobloy",
"utilities",
"tool",
"tools",
"roles",
"schedule",
"cron",

@ -0,0 +1,5 @@
from .firstmessage import FirstMessage
async def setup(bot):
bot.add_cog(FirstMessage(bot))

@ -0,0 +1,49 @@
import logging
import discord
from redbot.core import Config, commands
from redbot.core.bot import Red
log = logging.getLogger("red.fox_v3.firstmessage")
class FirstMessage(commands.Cog):
"""
Provides a link to the first message in the provided channel
"""
def __init__(self, bot: Red):
super().__init__()
self.bot = bot
self.config = Config.get_conf(
self, identifier=701051141151167710111511597103101, force_registration=True
)
default_guild = {}
self.config.register_guild(**default_guild)
async def red_delete_data_for_user(self, **kwargs):
"""Nothing to delete"""
return
@commands.command()
async def firstmessage(self, ctx: commands.Context, channel: discord.TextChannel = None):
"""
Provide a link to the first message in current or provided channel.
"""
if channel is None:
channel = ctx.channel
try:
message: discord.Message = (
await channel.history(limit=1, oldest_first=True).flatten()
)[0]
except (discord.Forbidden, discord.HTTPException):
log.exception(f"Unable to read message history for {channel.id=}")
await ctx.maybe_send_embed("Unable to read message history for that channel")
return
em = discord.Embed(description=f"[First Message in {channel.mention}]({message.jump_url})")
em.set_author(name=message.author.display_name, icon_url=message.author.avatar_url)
await ctx.send(embed=em)

@ -0,0 +1,17 @@
{
"author": [
"Bobloy"
],
"min_bot_version": "3.4.0",
"description": "Simple cog to jump to the first message of a channel easily",
"hidden": false,
"install_msg": "Thank you for installing FirstMessage.\nGet started with `[p]load firstmessage`, then `[p]help FirstMessage`",
"short": "Simple cog to jump to first message of a channel",
"end_user_data_statement": "This cog does not store any End User Data",
"tags": [
"bobloy",
"utilities",
"tool",
"tools"
]
}

@ -6,4 +6,3 @@ def setup(bot):
n = Hangman(bot)
data_manager.bundled_data_path(n)
bot.add_cog(n)
bot.add_listener(n.on_react, "on_reaction_add")

@ -50,27 +50,27 @@ class Hangman(Cog):
theface = await self.config.guild(guild).theface()
self.hanglist[guild] = (
""">
\_________
\\_________
|/
|
|
|
|
|
|\___
|\\___
""",
""">
\_________
\\_________
|/ |
|
|
|
|
|
|\___
|\\___
H""",
""">
\_________
\\_________
|/ |
| """
+ theface
@ -79,10 +79,10 @@ class Hangman(Cog):
|
|
|
|\___
|\\___
HA""",
""">
\________
\\________
|/ |
| """
+ theface
@ -91,10 +91,10 @@ class Hangman(Cog):
| |
|
|
|\___
|\\___
HAN""",
""">
\_________
\\_________
|/ |
| """
+ theface
@ -103,43 +103,43 @@ class Hangman(Cog):
| |
|
|
|\___
|\\___
HANG""",
""">
\_________
\\_________
|/ |
| """
+ theface
+ """
| /|\
| /|\\
| |
|
|
|\___
|\\___
HANGM""",
""">
\________
\\________
|/ |
| """
+ theface
+ """
| /|\
| /|\\
| |
| /
|
|\___
|\\___
HANGMA""",
""">
\________
\\________
|/ |
| """
+ theface
+ """
| /|\
| /|\\
| |
| / \
| / \\
|
|\___
|\\___
HANGMAN""",
)
@ -255,7 +255,7 @@ class Hangman(Cog):
elif i in self.the_data[guild]["guesses"] or i not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
out_str += "__" + i + "__ "
else:
out_str += "**\_** "
out_str += "**\\_** "
self.winbool[guild] = False
return out_str
@ -286,10 +286,10 @@ class Hangman(Cog):
await self._reprintgame(message)
@commands.Cog.listener()
@commands.Cog.listener("on_reaction_add")
async def on_react(self, reaction, user: Union[discord.User, discord.Member]):
""" Thanks to flapjack reactpoll for guidelines
https://github.com/flapjax/FlapJack-Cogs/blob/master/reactpoll/reactpoll.py"""
"""Thanks to flapjack reactpoll for guidelines
https://github.com/flapjax/FlapJack-Cogs/blob/master/reactpoll/reactpoll.py"""
guild: discord.Guild = getattr(user, "guild", None)
if guild is None:
return

@ -0,0 +1,5 @@
from .isitdown import IsItDown
async def setup(bot):
bot.add_cog(IsItDown(bot))

@ -0,0 +1,17 @@
{
"author": [
"Bobloy"
],
"min_bot_version": "3.4.0",
"description": "Check if a website/url is down using the https://isitdown.site/ api",
"hidden": false,
"install_msg": "Thank you for installing IsItDown.\nGet started with `[p]load isitdown`, then `[p]help IsItDown`",
"short": "Check if a website/url is down",
"end_user_data_statement": "This cog does not store any End User Data",
"tags": [
"bobloy",
"utilities",
"tool",
"tools"
]
}

@ -0,0 +1,58 @@
import logging
import re
import aiohttp
from redbot.core import Config, commands
from redbot.core.bot import Red
log = logging.getLogger("red.fox_v3.isitdown")
class IsItDown(commands.Cog):
"""
Cog Description
Less important information about the cog
"""
def __init__(self, bot: Red):
super().__init__()
self.bot = bot
self.config = Config.get_conf(self, identifier=0, force_registration=True)
default_guild = {"iids": []} # List of tuple pairs (channel_id, website)
self.config.register_guild(**default_guild)
async def red_delete_data_for_user(self, **kwargs):
"""Nothing to delete"""
return
@commands.command(alias=["iid"])
async def isitdown(self, ctx: commands.Context, url_to_check):
"""
Check if the provided url is down
Alias: iid
"""
try:
resp = await self._check_if_down(url_to_check)
except AssertionError:
await ctx.maybe_send_embed("Invalid URL provided. Make sure not to include `http://`")
return
if resp["isitdown"]:
await ctx.maybe_send_embed(f"{url_to_check} is DOWN!")
else:
await ctx.maybe_send_embed(f"{url_to_check} is UP!")
async def _check_if_down(self, url_to_check):
url = re.compile(r"https?://(www\.)?")
url.sub("", url_to_check).strip().strip("/")
url = f"https://isitdown.site/api/v3/{url}"
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
assert response.status == 200
resp = await response.json()
return resp

@ -22,7 +22,9 @@ class LaunchLib(commands.Cog):
def __init__(self, bot: Red):
super().__init__()
self.bot = bot
self.config = Config.get_conf(self, identifier=0, force_registration=True)
self.config = Config.get_conf(
self, identifier=7697117110991047610598, force_registration=True
)
default_guild = {}

@ -75,9 +75,7 @@ class LastSeen(Cog):
else:
last_seen = await self.config.member(member).seen()
if last_seen is None:
await ctx.maybe_send_embed(
embed=discord.Embed(description="I've never seen this user")
)
await ctx.maybe_send_embed("I've never seen this user")
return
last_seen = self.get_date_time(last_seen)

@ -360,7 +360,9 @@ class PlantTycoon(commands.Cog):
``{0}prune``: Prune your plant.\n"""
em = discord.Embed(
title=title, description=description.format(prefix), color=discord.Color.green(),
title=title,
description=description.format(prefix),
color=discord.Color.green(),
)
em.set_thumbnail(url="https://image.prntscr.com/image/AW7GuFIBSeyEgkR2W3SeiQ.png")
em.set_footer(
@ -525,7 +527,8 @@ class PlantTycoon(commands.Cog):
if t:
em = discord.Embed(
title="Plant statistics of {}".format(plant["name"]), color=discord.Color.green(),
title="Plant statistics of {}".format(plant["name"]),
color=discord.Color.green(),
)
em.set_thumbnail(url=plant["image"])
em.add_field(name="**Name**", value=plant["name"])
@ -583,7 +586,8 @@ class PlantTycoon(commands.Cog):
author = ctx.author
if product is None:
em = discord.Embed(
title="All gardening supplies that you can buy:", color=discord.Color.green(),
title="All gardening supplies that you can buy:",
color=discord.Color.green(),
)
for pd in self.products:
em.add_field(
@ -616,8 +620,11 @@ class PlantTycoon(commands.Cog):
await gardener.save_gardener()
message = "You bought {}.".format(product.lower())
else:
message = "You don't have enough Thneeds. You have {}, but need {}.".format(
gardener.points, self.products[product.lower()]["cost"] * amount,
message = (
"You don't have enough Thneeds. You have {}, but need {}.".format(
gardener.points,
self.products[product.lower()]["cost"] * amount,
)
)
else:
message = "I don't have this product."

@ -1,3 +1,4 @@
import logging
from typing import List, Union
import discord
@ -5,6 +6,8 @@ from redbot.core import Config, commands
from redbot.core.bot import Red
from redbot.core.commands import Cog
log = logging.getLogger("red.fox_v3.reactrestrict")
class ReactRestrictCombo:
def __init__(self, message_id, role_id):
@ -131,10 +134,12 @@ class ReactRestrict(Cog):
If no such channel or member can be found.
"""
channel = self.bot.get_channel(channel_id)
if channel is None:
raise LookupError("no channel found.")
try:
member = channel.guild.get_member(user_id)
except AttributeError as e:
raise LookupError("No channel found.") from e
raise LookupError("No member found.") from e
if member is None:
raise LookupError("No member found.")
@ -168,7 +173,7 @@ class ReactRestrict(Cog):
"""
channel = self.bot.get_channel(channel_id)
try:
return await channel.get_message(message_id)
return await channel.fetch_message(message_id)
except discord.NotFound:
pass
except AttributeError: # VoiceChannel object has no attribute 'get_message'
@ -186,9 +191,11 @@ class ReactRestrict(Cog):
:param message_id:
:return:
"""
for channel in ctx.guild.channels:
guild: discord.Guild = ctx.guild
for channel in guild.text_channels:
try:
return await channel.get_message(message_id)
return await channel.fetch_message(message_id)
except discord.NotFound:
pass
except AttributeError: # VoiceChannel object has no attribute 'get_message'
@ -232,7 +239,7 @@ class ReactRestrict(Cog):
# noinspection PyTypeChecker
await self.add_reactrestrict(message_id, role)
await ctx.maybe_send_embed("Message|Role combo added.")
await ctx.maybe_send_embed("Message|Role restriction added.")
@reactrestrict.command()
async def remove(self, ctx: commands.Context, message_id: int, role: discord.Role):
@ -248,37 +255,38 @@ class ReactRestrict(Cog):
# noinspection PyTypeChecker
await self.remove_react(message_id, role)
await ctx.send("Reaction removed.")
await ctx.send("React restriction removed.")
@commands.Cog.listener()
async def on_raw_reaction_add(
self, emoji: discord.PartialEmoji, message_id: int, channel_id: int, user_id: int
):
async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent):
"""
Event handler for long term reaction watching.
:param discord.PartialReactionEmoji emoji:
:param int message_id:
:param int channel_id:
:param int user_id:
:return:
"""
if emoji.is_custom_emoji():
emoji_id = emoji.id
else:
emoji_id = emoji.name
emoji = payload.emoji
message_id = payload.message_id
channel_id = payload.channel_id
user_id = payload.user_id
# if emoji.is_custom_emoji():
# emoji_id = emoji.id
# else:
# emoji_id = emoji.name
has_reactrestrict, combos = await self.has_reactrestrict_combo(message_id)
if not has_reactrestrict:
log.debug("Message not react restricted")
return
try:
member = self._get_member(channel_id, user_id)
except LookupError:
log.exception("Unable to get member from guild")
return
if member.bot:
log.debug("Won't remove reactions added by bots")
return
if await self.bot.cog_disabled_in_guild(self, member.guild):
@ -287,14 +295,19 @@ class ReactRestrict(Cog):
try:
roles = [self._get_role(member.guild, c.role_id) for c in combos]
except LookupError:
log.exception("Couldn't get approved roles from combos")
return
for apprrole in roles:
if apprrole in member.roles:
log.debug("Has approved role")
return
message = await self._get_message_from_channel(channel_id, message_id)
await message.remove_reaction(emoji, member)
try:
await message.remove_reaction(emoji, member)
except (discord.Forbidden, discord.NotFound, discord.HTTPException):
log.exception("Unable to remove reaction")
# try:
# await member.add_roles(*roles)

Loading…
Cancel
Save