mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 11:18:54 -05:00
* Add files via upload * Update predicates.py Changed sender from a discord.Member object to ctx. Added a channel check. Combined the same method and channel method into a validator and applied through-out. valid_role and has_role methods now check for either an id or a name. contained now uses string.lower() when testing for membership in a collection. Signed-off-by: Redjumpman <redjumpman@users.noreply.github.com>
150 lines
5.6 KiB
Python
150 lines
5.6 KiB
Python
import discord
|
|
from collections import Iterable
|
|
|
|
|
|
class MessagePredicate:
|
|
"""A simple collection of predicates.
|
|
|
|
These predicates were made to help simplify checks in message events and
|
|
reduce boilerplate code.
|
|
|
|
For examples:
|
|
# valid yes or no response
|
|
`ctx.bot.wait_for('message', timeout=15.0, check=Predicate(ctx).confirm)`
|
|
|
|
# check if message content in under 2000 characters
|
|
`check = Predicate(ctx, length=2000).length_under
|
|
ctx.bot.wait_for('message', timeout=15.0, check=check)`
|
|
|
|
|
|
Attributes
|
|
----------
|
|
ctx
|
|
Context object.
|
|
collection : `Iterable`
|
|
Optional argument used for checking if the message content is inside the
|
|
declared collection.
|
|
length : `int`
|
|
Optional argument for comparing message lengths.
|
|
value
|
|
Optional argument that can be either a string, int, float, or object.
|
|
Used for comparison and equality.
|
|
|
|
Returns
|
|
-------
|
|
Boolean or it will raise a ValueError if you use a certain methods without an argument or
|
|
the value argument is set to an invalid type for a particular method.
|
|
|
|
"""
|
|
|
|
def __init__(self, ctx, collection: Iterable = None, length: int = None, value=None):
|
|
self.ctx = ctx
|
|
self.collection = collection
|
|
self.length = length
|
|
self.value = value
|
|
|
|
def valid_source(self, m):
|
|
return self.same(m) and self.channel(m)
|
|
|
|
def same(self, m):
|
|
"""Checks if the author of the message is the same as the command issuer."""
|
|
return self.ctx.author == m.author
|
|
|
|
def channel(self, m):
|
|
"""Verifies the message was sent from the same channel."""
|
|
return self.ctx.channel == m.channel
|
|
|
|
def cancelled(self, m):
|
|
if self.valid_source(m) and m.content.lower() == f"{self.ctx.prefix}cancel":
|
|
raise RuntimeError
|
|
|
|
def confirm(self, m):
|
|
"""Checks if the author of the message is the same as the command issuer."""
|
|
return self.valid_source(m) and m.content.lower() in ("yes", "no", "y", "n")
|
|
|
|
def valid_int(self, m):
|
|
"""Returns true if the message content is an integer."""
|
|
return self.valid_source(m) and m.content.isdigit()
|
|
|
|
def valid_float(self, m):
|
|
"""Returns true if the message content is a float."""
|
|
try:
|
|
return self.valid_source(m) and float(m.content) >= 1
|
|
except ValueError:
|
|
return False
|
|
|
|
def positive(self, m):
|
|
"""Returns true if the message content is an integer and is positive"""
|
|
return self.valid_source(m) and m.content.isdigit() and int(m.content) >= 0
|
|
|
|
def valid_role(self, m):
|
|
"""Returns true if the message content is an existing role on the server."""
|
|
if self.valid_source(m):
|
|
if discord.utils.get(self.ctx.guild.roles, name=m.content) is not None:
|
|
return True
|
|
elif discord.utils.get(self.ctx.guild.roles, id=m.content) is not None:
|
|
return True
|
|
else:
|
|
return False
|
|
else:
|
|
return False
|
|
|
|
def has_role(self, m):
|
|
"""Returns true if the message content is a role the message sender has."""
|
|
if self.valid_source(m):
|
|
if discord.utils.get(self.ctx.roles, name=m.content) is not None:
|
|
return True
|
|
elif discord.utils.get(self.ctx.roles, id=m.content) is not None:
|
|
return True
|
|
else:
|
|
return False
|
|
else:
|
|
return False
|
|
|
|
def equal(self, m):
|
|
"""Returns true if the message content is equal to the value set."""
|
|
return self.valid_source(m) and m.content.lower() == self.value.lower()
|
|
|
|
def greater(self, m):
|
|
"""Returns true if the message content is greater than the value set."""
|
|
try:
|
|
return self.valid_int(m) or self.valid_float(m) and float(m.content) > int(self.value)
|
|
except TypeError:
|
|
raise ValueError("Value argument in Predicate() must be an integer or float.")
|
|
|
|
def less(self, m):
|
|
"""Returns true if the message content is less than the value set."""
|
|
try:
|
|
return self.valid_int(m) or self.valid_float(m) and float(m.content) < int(self.value)
|
|
except TypeError:
|
|
raise ValueError("Value argument in Predicate() must be an integer or float.")
|
|
|
|
def member(self, m):
|
|
"""Returns true if the message content is the name of a member in the server."""
|
|
return (
|
|
self.valid_source(m)
|
|
and discord.utils.get(self.ctx.guild.members, name=m.content) is not None
|
|
)
|
|
|
|
def length_less(self, m):
|
|
"""Returns true if the message content length is less than the provided length."""
|
|
try:
|
|
return self.valid_source(m) and len(m.content) <= self.length
|
|
except TypeError:
|
|
raise ValueError("A length must be specified in Predicate().")
|
|
|
|
def length_greater(self, m):
|
|
"""Returns true if the message content length is greater than or equal
|
|
to the provided length."""
|
|
try:
|
|
return self.valid_source(m) and len(m.content) >= self.length
|
|
except TypeError:
|
|
raise ValueError("A length must be specified in Predicate().")
|
|
|
|
def contained(self, m):
|
|
"""Returns true if the message content is a member of the provided collection."""
|
|
try:
|
|
return self.valid_source(m) and m.content.lower() in self.collection
|
|
except TypeError:
|
|
raise ValueError("An iterable was not specified in Predicate().")
|