Merge branch 'master' into hangman-develop

pull/20/head
bobloy 6 years ago committed by GitHub
commit 3a9befe411
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

3
.gitignore vendored

@ -1,2 +1,5 @@
.idea/
*.pyc
venv/
v-data/
database.sqlite3

@ -4,20 +4,24 @@ Cog Function
| Name | Status | Description (Click to see full status)
| --- | --- | --- |
| announcedaily | **Alpha** | <details><summary>Send daily announcements to all servers at a specified times</summary>Commissioned release, so suggestions will not be accepted</details> |
| ccrole | **Beta** | <details><summary>Create custom commands that also assign roles</summary>May have some bugs, please create an issue if you find any</details> |
| chatter | **Alpha** | <details><summary>Chat-bot trained to talk like your guild</summary>Missing some key features, but currently functional</details> |
| coglint | **Alpha** | <details><summary>Error check code in python syntax posted to discord</summary>Works, but probably needs more turning to work for cogs</details> |
| fight | **Incomplete** | <details><summary>Organize bracket tournaments within discord</summary>Still in-progress, a massive project</details> |
| flag | **Incomplete** | <details><summary>Create temporary marks on users that expire after specified time</summary>Not yet ported to v3</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 | **Alpha** | <details><summary>Play a game of hangman</summary>Some visual glitches and needs more customization</details> |
| howdoi | **Incomplete** | <details><summary>Create temporary marks on users that expire after specified time</summary>Not yet ported to v3</details> |
| leaver | **Incomplete** | <details><summary>Send a message in a channel when a user leaves the server</summary>Not yet ported to v3</details> |
| howdoi | **Incomplete** | <details><summary>Ask coding questions and get results from StackExchange</summary>Not yet functional</details> |
| leaver | **Alpha** | <details><summary>Send a message in a channel when a user leaves the server</summary>Just released, please report bugs</details> |
| lseen | **Alpha** | <details><summary>Track when a member was last online</summary>Alpha release, please report bugs</details> |
| reactrestrict | **Alpha** | <details><summary>Removes reactions by role per channel</summary>A bit clunky, but functional</details> |
| sayurl | **Alpha** | <details><summary>Convert any URL into text and post to discord</summary>No error checking and pretty spammy</details> |
| secrethitler | **Incomplete** | <details><summary>Play the Secret Hitler game</summary>Concept, no work done yet</details> |
| stealemoji | **Alpha** | <details><summary>Steals any custom emoji it sees in a reaction</summary>Some planned upgrades for server generation</details> |
| timerole | **Alpha** | <details><summary>Add roles to members after specified time on the server</summary>Upgraded from V2, please report any bugs</details> |
| tts | **Alpha** | <details><summary>Send a Text-to-Speech message as an uploaded mp3</summary>Alpha release, please report any bugs</details> |
| qrinvite | **Alpha** | <details><summary>Create a QR code invite for the server</summary>Alpha release, please report any bugs</details> |
| werewolf | **Alpha** | <details><summary>Play the classic party game Werewolf within discord</summary>Another massive project currently being developed, will be fully customizable</details> |

@ -0,0 +1,9 @@
from redbot.core.bot import Red
from .announcedaily import AnnounceDaily
def setup(bot: Red):
daily = AnnounceDaily(bot)
bot.add_cog(daily)
bot.loop.create_task(daily.check_day())

@ -0,0 +1,250 @@
import asyncio
import random
from datetime import datetime, timedelta
import discord
from redbot.core import Config, checks, commands
from redbot.core.bot import Red
from redbot.core.data_manager import cog_data_path
from redbot.core.utils.chat_formatting import pagify, box
DEFAULT_MESSAGES = [
# "Example message. Uncomment and overwrite to use",
# "Example message 2. Each message is in quotes and separated by a comma"
]
class AnnounceDaily:
"""
Send daily announcements
"""
def __init__(self, bot: Red):
self.bot = bot
self.path = str(cog_data_path(self)).replace('\\', '/')
self.image_path = self.path + "/"
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
default_global = {
'messages': [],
'images': [],
'time': {'hour': 0, 'minute': 0, 'second': 0}
}
default_guild = {
"channelid": None
}
self.config.register_global(**default_global)
self.config.register_guild(**default_guild)
async def _get_msgs(self):
return DEFAULT_MESSAGES + await self.config.messages()
@commands.group(name="announcedaily", aliases=['annd'])
@checks.mod_or_permissions(administrator=True)
@commands.guild_only()
async def _ad(self, ctx: commands.Context):
"""
Base command for managing AnnounceDaily settings
Do `[p]help annd <subcommand>` for more details
"""
if ctx.invoked_subcommand is None:
pass
@commands.command()
@checks.guildowner()
@commands.guild_only()
async def runannounce(self, ctx: commands.Context):
"""Manually run the daily announcement"""
await self.send_announcements()
await ctx.send("Success")
@_ad.command()
async def setchannel(self, ctx: commands.Context, channel: discord.TextChannel = None):
"""
Set the announcement channel for this server
Don't pass a channel to clear this server of receiving announcements
"""
if channel is not None:
await self.config.guild(ctx.guild).channelid.set(channel.id)
await ctx.send("Announcement channel has been set to {}".format(channel.mention))
else:
await self.config.guild(ctx.guild).channelid.set(None)
await ctx.send("Announcement channel has been cleared")
@_ad.command()
async def addmsg(self, ctx: commands.Context, *, msg):
"""
Add a message to the pool of announcement messages
"""
async with self.config.messages() as msgs:
msgs.append(msg)
await ctx.send("Message successfully added!")
@_ad.command()
async def addimg(self, ctx: commands.Context, filename=None):
"""
Add an image to the pool of announcement images
You must attach an image while executing this command
"""
if ctx.message.attachments:
att_ = ctx.message.attachments[0]
try:
h = att_.height
except AttributeError:
await ctx.send("You must attach an image, no other file will be accepted")
return
if filename is None:
filename = att_.filename
try:
# with open(self.image_path + filename, 'w') as f:
# await att_.save(f)
await att_.save(self.image_path + filename)
except discord.NotFound:
await ctx.send("Did you delete the message? Cause I couldn't download the attachment")
except discord.HTTPException:
await ctx.send("Failed to download the attachment, please try again")
else:
async with self.config.images() as images:
if filename in images:
await ctx.send("Image {} has been overwritten!".format(filename))
else:
images.append(filename)
await ctx.send("Image {} has been added!".format(filename))
else:
await ctx.send("You must attach an image when sending this command")
@_ad.command()
async def listmsg(self, ctx: commands.Context):
"""
List all registered announcement messages
"""
messages = await self.config.messages()
for page in pagify("\n".join("{} - {}".format(key, image) for key, image in enumerate(messages))):
await ctx.send(box(page))
await ctx.send("Done!")
@_ad.command()
async def listimg(self, ctx: commands.Context):
"""
List all registered announcement immages
"""
images = await self.config.images()
for page in pagify("\n".join(images)):
await ctx.send(box(page))
await ctx.send("Done!")
@_ad.command()
async def delmsg(self, ctx: commands.Context, index: int):
"""
Remove a message from the announcement pool
Must provide the index of the message, which can be found by using `[p]annd listmsg`
"""
async with self.config.messages() as messages:
try:
out = messages.pop(index)
except IndexError:
await ctx.send("Invalid index, check valid indexes with `listmsg` command")
return
await ctx.send("The following message was removed:\n```{}```".format(out))
@_ad.command()
async def delimg(self, ctx: commands.Context, filename: str):
"""
Remove an image from the announcement pool
Does not delete the file from the disk, so you may have to clean it up occasionally
"""
async with self.config.images() as images:
if filename not in images:
await ctx.send("This file doesn't exist")
else:
images.remove(filename)
await ctx.send("Successfully removed {}".format(filename))
@_ad.command()
async def settime(self, ctx: commands.Context, minutes_from_now: int):
"""
Set the daily announcement time
It will first announce at the time you provided, then it will repeat every 24 hours
"""
ann_time = datetime.now() + timedelta(minutes=minutes_from_now)
h = ann_time.hour
m = ann_time.minute
s = ann_time.second
await self.config.time.set({'hour': h, 'minute': m, 'second': s})
await ctx.send("Announcements time has been set to {}::{}::{} every day\n"
"**Changes will apply after next scheduled announcement or reload**".format(h, m, s))
async def send_announcements(self):
messages = await self._get_msgs()
images = await self.config.images()
total = len(messages) + len(images)
if total < 1:
return
x = random.randint(0, total - 1)
if x >= len(messages):
x -= len(messages)
choice = images[x]
choice = open(self.image_path + choice, 'rb')
is_image = True
else:
choice = messages[x]
is_image = False
for guild in self.bot.guilds:
channel = await self.config.guild(guild).channelid()
if channel is None:
continue
channel = guild.get_channel(channel)
if channel is None:
continue
if is_image:
await channel.send(file=discord.File(choice))
else:
await channel.send(choice)
async def check_day(self):
while self is self.bot.get_cog("AnnounceDaily"):
tomorrow = datetime.now() + timedelta(days=1)
time = await self.config.time()
h, m, s = time['hour'], time['minute'], time['second']
midnight = datetime(year=tomorrow.year, month=tomorrow.month,
day=tomorrow.day, hour=h, minute=m, second=s)
print("Sleeping for {} seconds".format((midnight - datetime.now()).seconds))
await asyncio.sleep((midnight - datetime.now()).seconds)
if self is not self.bot.get_cog("AnnounceDaily"):
print("Announce canceled, cog has been lost")
return
await self.send_announcements()
await asyncio.sleep(3)
# [p]setchannel #channelname - Set the announcement channel per server
# [p]addmsg <message goes here> - Adds a msg to the pool
# [p]addimg http://imgurl.com/image.jpg - Adds an image to the pool
# [p]listmsg - Lists all messages in the pool
# [p]listimg - Unsure about this one, but would probably just post all the images
# [p]delmsg - Remove msg from pool
# [p]delimg - Remove image from pool
# [p]settime <x> - S

@ -0,0 +1,18 @@
{
"author": [
"Bobloy"
],
"bot_version": [
3,
0,
0
],
"description": "Send daily announcements to all servers at a specified times",
"hidden": true,
"install_msg": "Thank you for installing AnnounceDaily! Get started with `[p]help AnnounceDaily`",
"requirements": [],
"short": "Send daily announcements",
"tags": [
"bobloy"
]
}

@ -2,7 +2,6 @@ import asyncio
import re
import discord
from redbot.core import Config, checks
from redbot.core import commands
from redbot.core.utils.chat_formatting import pagify, box
@ -30,7 +29,7 @@ class CCRole:
Highly customizable custom commands with role management."""
if not ctx.invoked_subcommand:
await ctx.send_help()
pass
@ccrole.command(name="add")
@checks.mod_or_permissions(administrator=True)
@ -106,7 +105,7 @@ class CCRole:
return
# Selfrole
await ctx.send('Is this a targeted command?(yes/no)\nNo will make this a selfrole command')
await ctx.send('Is this a targeted command?(yes//no)\nNo will make this a selfrole command')
try:
answer = await self.bot.wait_for('message', timeout=120, check=check)
@ -191,7 +190,7 @@ class CCRole:
"""Shows custom commands list"""
guild = ctx.guild
cmd_list = await self.config.guild(guild).cmdlist()
cmd_list = {k: v for k,v in cmd_list.items() if v}
cmd_list = {k: v for k, v in cmd_list.items() if v}
if not cmd_list:
await ctx.send(
"There are no custom commands in this server. Use `{}ccrole add` to start adding some.".format(

@ -1,10 +1,22 @@
{
"author" : ["Bobloy"],
"bot_version" : [3,0,0],
"description" : "[Incomplete] Creates custom commands to adjust roles and send custom messages",
"hidden" : false,
"install_msg" : "Thank you for installing Custom Commands w/ Roles.",
"requirements" : [],
"short" : "[Incomplete] Creates commands that adjust roles",
"tags" : ["fox", "bobloy", "utility", "tools", "roles"]
"author": [
"Bobloy"
],
"bot_version": [
3,
0,
0
],
"description": "[Incomplete] Creates custom commands to adjust roles and send custom messages",
"hidden": false,
"install_msg": "Thank you for installing Custom Commands w/ Roles.",
"requirements": [],
"short": "[Incomplete] Creates commands that adjust roles",
"tags": [
"fox",
"bobloy",
"utility",
"tools",
"roles"
]
}

@ -1,16 +1,18 @@
import asyncio
import pathlib
from datetime import datetime, timedelta
import discord
from redbot.core import Config
from redbot.core import commands
from redbot.core.data_manager import cog_data_path
from chatter.chatterbot import ChatBot
from chatter.chatterbot.comparisons import levenshtein_distance
from chatter.chatterbot.response_selection import get_first_response
from chatter.chatterbot.trainers import ListTrainer
class Chatter:
"""
This cog trains a chatbot that will talk like members of your Guild
@ -24,11 +26,23 @@ class Chatter:
"whitelist": None,
"days": 1
}
path: pathlib.Path = cog_data_path(self)
data_path = path / ("database.sqlite3")
self.chatbot = ChatBot(
"ChatterBot",
storage_adapter='chatter.chatterbot.storage.SQLStorageAdapter',
database='./database.sqlite3'
database=str(data_path),
statement_comparison_function=levenshtein_distance,
response_selection_method=get_first_response,
logic_adapters=[
'chatter.chatterbot.logic.BestMatch',
{
'import_path': 'chatter.chatterbot.logic.LowConfidenceAdapter',
'threshold': 0.65,
'default_response': ':thinking:'
}
]
)
self.chatbot.set_trainer(ListTrainer)
@ -43,21 +57,42 @@ class Chatter:
Currently takes a stupid long time
Returns a list of text
"""
out = []
out = [[]]
after = datetime.today() - timedelta(days=(await self.config.guild(ctx.guild).days()))
def new_message(msg, sent, out_in):
if sent is None:
return False
if len(out_in) < 2:
return False
return msg.created_at - sent >= timedelta(hours=3) # This should be configurable perhaps
for channel in ctx.guild.text_channels:
if in_channel:
channel = in_channel
await ctx.send("Gathering {}".format(channel.mention))
user = None
i = 0
send_time = None
try:
async for message in channel.history(limit=None, reverse=True, after=after):
# if message.author.bot: # Skip bot messages
# continue
if new_message(message, send_time, out[i]):
out.append([])
i += 1
user = None
else:
send_time = message.created_at + timedelta(seconds=1)
if user == message.author:
out[-1] += "\n" + message.clean_content
out[i][-1] += "\n" + message.clean_content
else:
user = message.author
out.append(message.clean_content)
out[i].append(message.clean_content)
except discord.Forbidden:
pass
except discord.HTTPException:
@ -70,18 +105,19 @@ class Chatter:
def _train(self, data):
try:
self.chatbot.train(data)
for convo in data:
self.chatbot.train(convo)
except:
return False
return True
@commands.group()
@commands.group(invoke_without_command=False)
async def chatter(self, ctx: commands.Context):
"""
Base command for this cog. Check help for the commands list.
"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
@chatter.command()
async def age(self, ctx: commands.Context, days: int):
@ -99,7 +135,8 @@ class Chatter:
Backup your training data to a json for later use
"""
await ctx.send("Backing up data, this may take a while")
future = await self.loop.run_in_executor(None, self.chatbot.trainer.export_for_training, './{}.json'.format(backupname))
future = await self.loop.run_in_executor(None, self.chatbot.trainer.export_for_training,
'./{}.json'.format(backupname))
if future:
await ctx.send("Backup successful!")
@ -134,17 +171,21 @@ class Chatter:
else:
await ctx.send("Error occurred :(")
async def on_message(self, message):
async def on_message(self, message: discord.Message):
"""
Credit to https://github.com/Twentysix26/26-Cogs/blob/master/cleverbot/cleverbot.py
for on_message recognition of @bot
"""
author = message.author
channel = message.channel
try:
guild: discord.Guild = message.guild
except AttributeError: # Not a guild message
return
channel: discord.TextChannel = message.channel
if message.author.id != self.bot.user.id:
to_strip = "@" + author.guild.me.display_name + " "
if author.id != self.bot.user.id:
to_strip = "@" + guild.me.display_name + " "
text = message.clean_content
if not text.startswith(to_strip):
return
@ -152,7 +193,7 @@ class Chatter:
async with channel.typing():
future = await self.loop.run_in_executor(None, self.chatbot.get_response, text)
if future:
if future and str(future):
await channel.send(str(future))
else:
await channel.send(':thinking:')

@ -2,10 +2,7 @@ from __future__ import unicode_literals
import logging
from . import utils
from .input import InputAdapter
from .output import OutputAdapter
from .storage import StorageAdapter
from chatter.chatterbot import utils
class ChatBot(object):
@ -14,7 +11,7 @@ class ChatBot(object):
"""
def __init__(self, name, **kwargs):
from .logic import MultiLogicAdapter
from chatter.chatterbot.logic import MultiLogicAdapter
self.name = name
kwargs['name'] = name
@ -33,9 +30,9 @@ class ChatBot(object):
output_adapter = kwargs.get('output_adapter', 'chatter.chatterbot.output.OutputAdapter')
# Check that each adapter is a valid subclass of it's respective parent
utils.validate_adapter_class(storage_adapter, StorageAdapter)
utils.validate_adapter_class(input_adapter, InputAdapter)
utils.validate_adapter_class(output_adapter, OutputAdapter)
# utils.validate_adapter_class(storage_adapter, StorageAdapter)
# utils.validate_adapter_class(input_adapter, InputAdapter)
# utils.validate_adapter_class(output_adapter, OutputAdapter)
self.logic = MultiLogicAdapter(**kwargs)
self.storage = utils.initialize_class(storage_adapter, **kwargs)
@ -139,7 +136,7 @@ class ChatBot(object):
"""
Learn that the statement provided is a valid response.
"""
from .conversation import Response
from chatter.chatterbot.conversation import Response
if previous_statement:
statement.add_response(

@ -92,7 +92,7 @@ class SynsetDistance(Comparator):
"""
Download required NLTK corpora if they have not already been downloaded.
"""
from .utils import nltk_download_corpus
from chatter.chatterbot.utils import nltk_download_corpus
nltk_download_corpus('corpora/wordnet')
@ -100,7 +100,7 @@ class SynsetDistance(Comparator):
"""
Download required NLTK corpora if they have not already been downloaded.
"""
from .utils import nltk_download_corpus
from chatter.chatterbot.utils import nltk_download_corpus
nltk_download_corpus('tokenizers/punkt')
@ -108,7 +108,7 @@ class SynsetDistance(Comparator):
"""
Download required NLTK corpora if they have not already been downloaded.
"""
from .utils import nltk_download_corpus
from chatter.chatterbot.utils import nltk_download_corpus
nltk_download_corpus('corpora/stopwords')
@ -177,7 +177,7 @@ class SentimentComparison(Comparator):
Download the NLTK vader lexicon for sentiment analysis
that is required for this algorithm to run.
"""
from .utils import nltk_download_corpus
from chatter.chatterbot.utils import nltk_download_corpus
nltk_download_corpus('sentiment/vader_lexicon')
@ -252,7 +252,7 @@ class JaccardSimilarity(Comparator):
Download the NLTK wordnet corpora that is required for this algorithm
to run only if the corpora has not already been downloaded.
"""
from .utils import nltk_download_corpus
from chatter.chatterbot.utils import nltk_download_corpus
nltk_download_corpus('corpora/wordnet')

@ -1,5 +1,5 @@
from .best_match import BestMatch
from .logic_adapter import LogicAdapter
from .best_match import BestMatch
from .low_confidence import LowConfidenceAdapter
from .mathematical_evaluation import MathematicalEvaluation
from .multi_adapter import MultiLogicAdapter

@ -1,6 +1,6 @@
from __future__ import unicode_literals
from .logic_adapter import LogicAdapter
from chatter.chatterbot.logic import LogicAdapter
class BestMatch(LogicAdapter):

@ -1,7 +1,7 @@
from __future__ import unicode_literals
from chatter.chatterbot.conversation import Statement
from .best_match import BestMatch
from chatter.chatterbot.logic import BestMatch
class LowConfidenceAdapter(BestMatch):

@ -3,7 +3,7 @@ from __future__ import unicode_literals
from collections import Counter
from chatter.chatterbot import utils
from .logic_adapter import LogicAdapter
from chatter.chatterbot.logic import LogicAdapter
class MultiLogicAdapter(LogicAdapter):

@ -1,6 +1,6 @@
from __future__ import unicode_literals
from .logic_adapter import LogicAdapter
from chatter.chatterbot.logic import LogicAdapter
class NoKnowledgeAdapter(LogicAdapter):

@ -1,6 +1,6 @@
from __future__ import unicode_literals
from .logic_adapter import LogicAdapter
from chatter.chatterbot.logic import LogicAdapter
class SpecificResponseAdapter(LogicAdapter):

@ -2,7 +2,7 @@ from __future__ import unicode_literals
from datetime import datetime
from .logic_adapter import LogicAdapter
from chatter.chatterbot.logic import LogicAdapter
class TimeLogicAdapter(LogicAdapter):

@ -1,8 +1,8 @@
from .output_adapter import OutputAdapter
from .gitter import Gitter
from .hipchat import HipChat
from .mailgun import Mailgun
from .microsoft import Microsoft
from .output_adapter import OutputAdapter
from .terminal import TerminalAdapter
__all__ = (

@ -1,6 +1,6 @@
from __future__ import unicode_literals
from .output_adapter import OutputAdapter
from chatter.chatterbot.output import OutputAdapter
class Gitter(OutputAdapter):

@ -2,7 +2,7 @@ from __future__ import unicode_literals
import json
from .output_adapter import OutputAdapter
from chatter.chatterbot.output import OutputAdapter
class HipChat(OutputAdapter):

@ -1,6 +1,6 @@
from __future__ import unicode_literals
from .output_adapter import OutputAdapter
from chatter.chatterbot.output import OutputAdapter
class Mailgun(OutputAdapter):

@ -2,7 +2,7 @@ from __future__ import unicode_literals
import json
from .output_adapter import OutputAdapter
from chatter.chatterbot.output import OutputAdapter
class Microsoft(OutputAdapter):

@ -1,6 +1,6 @@
from __future__ import unicode_literals
from .output_adapter import OutputAdapter
from chatter.chatterbot.output import OutputAdapter
class TerminalAdapter(OutputAdapter):

@ -158,7 +158,9 @@ class StorageAdapter(object):
class EmptyDatabaseException(Exception):
def __init__(self,
value='The database currently contains no entries. At least one entry is expected. You may need to train your chat bot to populate your database.'):
value='The database currently contains no entries. '
'At least one entry is expected. '
'You may need to train your chat bot to populate your database.'):
self.value = value
def __str__(self):

@ -2,8 +2,8 @@ import logging
import os
import sys
from . import utils
from .conversation import Statement, Response
from chatter.chatterbot import utils
from chatter.chatterbot.conversation import Statement, Response
class Trainer(object):
@ -127,7 +127,7 @@ class ChatterBotCorpusTrainer(Trainer):
def __init__(self, storage, **kwargs):
super(ChatterBotCorpusTrainer, self).__init__(storage, **kwargs)
from .corpus import Corpus
from chatter.chatterbot.corpus import Corpus
self.corpus = Corpus()

@ -46,7 +46,7 @@ def validate_adapter_class(validate_class, adapter_class):
:raises: Adapter.InvalidAdapterTypeException
"""
from .adapters import Adapter
from chatter.chatterbot.adapters import Adapter
# If a dictionary was passed in, check if it has an import_path attribute
if isinstance(validate_class, dict):

@ -1,11 +1,8 @@
import discord
from redbot.core import Config, checks
from redbot.core.bot import Red
from pylint import epylint as lint
from redbot.core import Config
from redbot.core import commands
from redbot.core.bot import Red
from redbot.core.data_manager import cog_data_path

@ -1,10 +1,11 @@
import asyncio
import os
import math
# from typing import Union
import discord
from redbot.core import commands
from redbot.core.utils.chat_formatting import pagify
from redbot.core.utils.chat_formatting import box
@ -102,7 +103,7 @@ class Fight:
await ctx.send("Current tournament ID: " + await self._activefight(ctx))
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
# await ctx.send("I can do stuff!")
@fight.command(name="join")
@ -198,10 +199,10 @@ class Fight:
async def fadmin(self, ctx):
"""Admin command for managing the current tournament"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
@fadmin.command(name="score")
async def fadmin_score(self, ctx, mID, score1, score2):
async def fadmin_score(self, ctx: commands.Context, mID, score1, score2):
"""Set's the score for matchID and clears disputes"""
currFight = await self._getcurrentfight(ctx)
tID = await self._activefight(ctx)
@ -213,11 +214,11 @@ class Fight:
await ctx.send("Tournament currently not accepting new players")
return
if await self._infight(ctx, tID, user.id):
if await self._infight(ctx, tID, ctx.user.id):
await ctx.send("You are already in this tournament!")
return
currFight["PLAYERS"].append(user.id)
currFight["PLAYERS"].append(ctx.user.id)
await self._save_fight(ctx, tID, currFight)
@ -256,7 +257,7 @@ class Fight:
# self.save_data()
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
# await ctx.send("I can do stuff!")
@fightset.command(name="emoji")
@ -548,7 +549,7 @@ class Fight:
async def fightset_guild(self, ctx):
"""Adjust guild wide settings"""
if ctx.invoked_subcommand is None or isinstance(ctx.invoked_subcommand, commands.Group):
await ctx.send_help()
pass
@fightset_guild.command(name="selfreport")
async def fightset_guild_selfreport(self, ctx):
@ -711,11 +712,13 @@ class Fight:
async def _embed_tourney(self, ctx, tID):
"""Prints a pretty embed of the tournament"""
await ctx.send("_placeholder Todo")
#_placeholder Todo
pass
async def _comparescores(self):
"""Checks user submitted scores for inconsistancies"""
await ctx.send("_comparescores Todo")
# _comparescores Todo
pass
async def _parseuser(self, guild: discord.Guild, tID, userid):
"""Finds user in the tournament"""
@ -821,8 +824,8 @@ class Fight:
"""Reports a win for member in match"""
theT = await self._getfight(guild, tID)
if member.id not in theT["PLAYERS"]: # Shouldn't happen
return False
# if member.id not in theT["PLAYERS"]: # Shouldn't happen
# return False
if theT["RULES"]["TYPE"] == 0:
return await self._rr_report_dispute(guild, tID, mID)
@ -833,13 +836,16 @@ class Fight:
# **********************Single Elimination***************************
async def _elim_setup(self, tID):
await ctx.send("Elim setup todo")
# ToDo Elim setup
pass
async def _elim_start(self, tID):
await ctx.send("Elim start todo")
# ToDo Elim start
pass
async def _elim_update(self, matchID):
await ctx.send("Elim update todo")
# ToDo Elim update
pass
# **********************Round-Robin**********************************

@ -2,7 +2,7 @@
"author" : ["Bobloy"],
"bot_version" : [3,0,0],
"description" : "[Incomplete] Cog to organize tournaments within Discord",
"hidden" : false,
"hidden" : true,
"install_msg" : "Thank you for installing Fight. Run with [p]fight or [p]fightset",
"requirements" : [],
"short" : "[Incomplete] Cog to organize tournaments",

@ -0,0 +1,5 @@
from .flag import Flag
def setup(bot):
bot.add_cog(Flag(bot))

@ -0,0 +1,184 @@
from datetime import date, timedelta
import discord
from redbot.core import Config, checks, commands
from redbot.core.bot import Red
from redbot.core.utils.chat_formatting import pagify
class Flag:
"""
Set expiring flags on members
"""
def __init__(self, bot: Red):
self.bot = bot
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
default_global = {}
default_guild = {
"days": 31,
"dm": True,
"flags": {}
}
self.config.register_global(**default_global)
self.config.register_guild(**default_guild)
@checks.is_owner()
@commands.command()
async def clearallflag(self, ctx: commands.Context):
"""Clears all flags for all members in this server"""
await self.config.guild(ctx.guild).flags.clear()
await ctx.send("Done")
@checks.mod_or_permissions(manage_roles=True)
@commands.guild_only()
@commands.group()
async def flagset(self, ctx: commands.Context):
"""
My custom cog
Extra information goes here
"""
if ctx.invoked_subcommand is None:
pass
@flagset.command(name="expire")
async def flagset_expire(self, ctx: commands.Context, days: int):
"""
Set the number of days for flags to expire after for server
"""
await self.config.guild(ctx.guild).days.set(days)
await ctx.send("Number of days for new flags to expire is now {} days".format(days))
@flagset.command(name="dm")
async def flagset_dm(self, ctx: commands.Context):
"""Toggles DM-ing the flags"""
dm = await self.config.guild(ctx.guild).dm()
await self.config.guild(ctx.guild).dm.set(not dm)
await ctx.send("DM-ing members when they get a flag is now set to **{}**".format(not dm))
@staticmethod
def _flag_template():
return {
'reason': "",
'expireyear': 0,
'expiremonth': 0,
'expireday': 0
}
# ************************Flag command group start************************
@checks.mod_or_permissions(manage_roles=True)
@commands.command()
async def flag(self, ctx: commands.Context, member: discord.Member, *, reason):
"""Flag a member"""
guild = ctx.guild
await self._check_flags(guild)
# clashroyale = self.bot.get_cog('clashroyale')
# if clashroyale is None:
# await ctx.send("Requires clashroyale cog installed")
# return
flag = self._flag_template()
expiredate = date.today()
expiredate += timedelta(days=await self.config.guild(guild).days())
flag['reason'] = reason
flag['expireyear'] = expiredate.year
flag['expiremonth'] = expiredate.month
flag['expireday'] = expiredate.day
# flags = await self.config.guild(guild).flags.get_raw(str(member.id), default=[])
# flags.append(flag)
# await self.config.guild(guild).flags.set_raw(str(member.id), value=flags)
async with self.config.guild(guild).flags() as flags:
flags[str(member.id)].append(flag)
outembed = await self._list_flags(member)
if outembed:
await ctx.send(embed=outembed)
if await self.config.guild(guild).dm():
await member.send(embed=outembed)
else:
await ctx.send("This member has no flags.. somehow..")
@checks.mod_or_permissions(manage_roles=True)
@commands.command(pass_context=True, no_pm=True, aliases=['flagclear'])
async def clearflag(self, ctx: commands.Context, member: discord.Member):
"""Clears flags for a member"""
guild = ctx.guild
await self._check_flags(guild)
await self.config.guild(guild).flags.set_raw(str(member.id), value=[])
await ctx.send("Success!")
@commands.command(pass_context=True, no_pm=True, aliases=['flaglist'])
async def listflag(self, ctx: commands.Context, member: discord.Member):
"""Lists flags for a member"""
server = ctx.guild
await self._check_flags(server)
outembed = await self._list_flags(member)
if outembed:
await ctx.send(embed=outembed)
else:
await ctx.send("This member has no flags!")
@commands.command(pass_context=True, no_pm=True, aliases=['flagall'])
async def allflag(self, ctx: commands.Context):
"""Lists all flags for the server"""
guild = ctx.guild
await self._check_flags(guild)
out = "All flags for {}\n".format(ctx.guild.name)
flags = await self.config.guild(guild).flags()
flag_d = {}
for memberid, flag_data in flags.items():
if len(flag_data) > 0:
member = guild.get_member(int(memberid))
flag_d[member.display_name + member.discriminator] = len(flag_data)
for display_name, flag_count in sorted(flag_d.items()):
out += "{} - **{}** flags".format(display_name, flag_count)
for page in pagify(out):
await ctx.send(page)
async def _list_flags(self, member: discord.Member):
"""Returns a pretty embed of flags on a member"""
flags = await self.config.guild(member.guild).flags.get_raw(str(member.id), default=[])
embed = discord.Embed(title="Flags for " + member.display_name,
description="User has {} active flags".format(len(flags)), color=0x804040)
for flag in flags:
embed.add_field(name="Reason: " + flag['reason'],
value="Expires on " + str(date(flag['expireyear'], flag['expiremonth'], flag['expireday'])),
inline=True)
embed.set_thumbnail(url=member.avatar_url)
return embed
async def _check_flags(self, guild: discord.Guild):
"""Updates and removes expired flags"""
flag_data = await self.config.guild(guild).flags()
flag_d = {}
for memberid, flags in flag_data.items():
# for member in guild.members:
# flags = await self.config.guild(guild).flags.get_raw(str(member.id), default=[])
x = 0
while x < len(flags):
flag = flags[x]
if date.today() >= date(flag['expireyear'], flag['expiremonth'], flag['expireday']):
del flags[x]
else:
x += 1
await self.config.guild(guild).flags.set_raw(memberid, value=flags)

@ -0,0 +1,23 @@
{
"author": [
"Bobloy"
],
"bot_version": [
3,
0,
0
],
"description": "Add expiring flags on members to track warnings or incidents",
"hidden": true,
"install_msg": "Thank you for installing Flag! Get started with `[p]help Flag`",
"requirements": [],
"short": "Add expiring flags to members",
"tags": [
"bobloy",
"warning",
"warn",
"temp",
"tools",
"warning"
]
}

@ -0,0 +1,5 @@
from .forcemention import ForceMention
def setup(bot):
bot.add_cog(ForceMention(bot))

@ -0,0 +1,38 @@
from discord.utils import get
from redbot.core import Config, checks, commands
from redbot.core.bot import Red
class ForceMention:
"""
Mention the unmentionables
"""
def __init__(self, bot: Red):
self.bot = bot
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
default_global = {}
default_guild = {}
self.config.register_global(**default_global)
self.config.register_guild(**default_guild)
@checks.admin_or_permissions(manage_roles=True)
@commands.command()
async def forcemention(self, ctx: commands.Context, role: str, *, message=''):
"""
Mentions that role, regardless if it's unmentionable
"""
role_obj = get(ctx.guild.roles, name=role)
if role_obj is None:
await ctx.maybe_send_embed("Couldn't find role named {}".format(role))
return
if not role_obj.mentionable:
await role_obj.edit(mentionable=True)
await ctx.send("{}\n{}".format(role_obj.mention, message))
await role_obj.edit(mentionable=False)
else:
await ctx.send("{}\n{}".format(role_obj.mention, message))

@ -0,0 +1,19 @@
{
"author": [
"Bobloy"
],
"bot_version": [
3,
0,
0
],
"description": "Mentions roles that are unmentionable",
"hidden": false,
"install_msg": "Thank you for installing ForceMention! Get started with `[p]forcemention`",
"requirements": [],
"short": "Mention unmentionables",
"tags": [
"bobloy",
"utils"
]
}

@ -127,7 +127,7 @@ class Hangman:
@checks.mod_or_permissions(administrator=True)
async def hangset(self, ctx):
"""Adjust hangman settings"""
if not ctx.invoked_subcommand:
if ctx.invoked_subcommand is None:
pass
@hangset.command(pass_context=True)

@ -33,7 +33,7 @@ class Howdoi:
"""Adjust howdoi settings
Settings are reset on reload"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
@howdoiset.command(pass_context=True, name="answers")
async def howdoiset_answers(self, ctx, num_answers: int=1):

@ -1,7 +1,7 @@
{
"AUTHOR": "Bobloy",
"INSTALL_MSG": "Thank you for installing Fox-Cogs by Bobloy",
"NAME": "Fox-Cogs",
"INSTALL_MSG": "Thank you for installing Fox-V3 by Bobloy",
"NAME": "Fox-V3",
"SHORT": "Cogs by Bobloy",
"DESCRIPTION": "Cogs for RED Discord Bot by Bobloy"
}

@ -0,0 +1,5 @@
from .leaver import Leaver
def setup(bot):
bot.add_cog(Leaver(bot))

@ -1,9 +1,20 @@
{
"AUTHOR": "Bobloy",
"INSTALL_MSG": "Thank you for installing leaver",
"NAME": "Leaver",
"SHORT": "Sends message on leave",
"DESCRIPTION": "Keeps track of when people leave the server, and posts a message notifying",
"TAGS": ["fox", "bobloy", "utilities", "tools", "tool"],
"HIDDEN": false
"author": [
"Bobloy"
],
"bot_version": [
3,
0,
0
],
"description": "Keeps track of when people leave the server, and posts a message notifying",
"hidden": false,
"install_msg": "Thank you for installing Leaver. Get started with `[p]help Leaver`",
"requirements": [],
"short": "Send message on leave",
"tags": [
"bobloy",
"utils",
"tools"
]
}

@ -1,78 +1,42 @@
import discord
import os
from datetime import datetime
from .utils.dataIO import dataIO
from .utils import checks
from redbot.core import Config, checks, commands
from redbot.core.commands import Context
class Leaver:
"""Creates a goodbye message when people leave"""
"""
Creates a goodbye message when people leave
"""
def __init__(self, bot):
self.bot = bot
self.path = "data/Fox-Cogs/leaver"
self.file_path = "data/Fox-Cogs/leaver/leaver.json"
self.the_data = dataIO.load_json(self.file_path)
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
default_guild = {
"channel": ''
}
def save_data(self):
"""Saves the json"""
dataIO.save_json(self.file_path, self.the_data)
self.config.register_guild(**default_guild)
@commands.group(aliases=['setleaver'], pass_context=True, no_pm=True)
@commands.group(aliases=['setleaver'])
@checks.mod_or_permissions(administrator=True)
async def leaverset(self, ctx):
"""Adjust leaver settings"""
server = ctx.message.server
if server.id not in self.the_data:
self.the_data[server.id] = {}
self.save_data()
if ctx.invoked_subcommand is None:
await self.bot.send_cmd_help(ctx)
pass
@leaverset.command(pass_context=True, no_pm=True)
async def channel(self, ctx):
server = ctx.message.server
if 'CHANNEL' not in self.the_data[server.id]:
self.the_data[server.id]['CHANNEL'] = ''
@leaverset.command()
async def channel(self, ctx: Context):
guild = ctx.guild
await self.config.guild(guild).channel.set(ctx.channel.id)
await ctx.send("Channel set to " + ctx.channel.name)
async def on_member_remove(self, member: discord.Member):
guild = member.guild
channel = await self.config.guild(guild).channel()
self.the_data[server.id]['CHANNEL'] = ctx.message.channel.id
self.save_data()
await self.bot.say("Channel set to "+ctx.message.channel.name)
async def when_leave(self, member):
server = member.server
if server.id in self.the_data:
await self.bot.send_message(server.get_channel(self.the_data[server.id]['CHANNEL']),
str(member) + "(*" + str(member.nick) +"*) has left the server!")
if channel != '':
channel = guild.get_channel(channel)
await channel.send(str(member) + "(*" + str(member.nick) + "*) has left the server!")
else:
await self.bot.send_message(server.default_channel.id, str(member) + " (*" + str(member.nick) +"*) has left the server!")
def check_folders():
if not os.path.exists("data/Fox-Cogs"):
print("Creating data/Fox-Cogs folder...")
os.makedirs("data/Fox-Cogs")
if not os.path.exists("data/Fox-Cogs/leaver"):
print("Creating data/Fox-Cogs/leaver folder...")
os.makedirs("data/Fox-Cogs/leaver")
def check_files():
if not dataIO.is_valid_json("data/Fox-Cogs/leaver/leaver.json"):
dataIO.save_json("data/Fox-Cogs/leaver/leaver.json", {})
def setup(bot):
check_folders()
check_files()
q = Leaver(bot)
bot.add_listener(q.when_leave, "on_member_remove")
bot.add_cog(q)
pass

@ -0,0 +1,20 @@
{
"author": [
"Bobloy"
],
"bot_version": [
3,
0,
0
],
"description": "Keep track of when users were last seen online",
"hidden": true,
"install_msg": "Thank you for installing LastSeen. Get started with `[p]help LastSeen`",
"requirements": [],
"short": "Last seen tracker",
"tags": [
"bobloy",
"utils",
"tools"
]
}

@ -10,7 +10,7 @@ from redbot.core import commands
class LastSeen:
"""
V3 Cog Template
Report when a user was last seen online
"""
online_status = discord.Status.online
@ -41,7 +41,7 @@ class LastSeen:
async def lset(self, ctx: commands.Context):
"""Change settings for lseen"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
@lset.command(name="toggle")
async def lset_toggle(self, ctx: commands.Context):
@ -58,8 +58,6 @@ class LastSeen:
async def lseen(self, ctx: commands.Context, member: discord.Member):
"""
Just says the time the user was last seen
:param member:
"""
if member.status != self.offline_status:

@ -0,0 +1,5 @@
from .nudity import Nudity
def setup(bot):
bot.add_cog(Nudity(bot))

@ -0,0 +1,20 @@
{
"author": [
"Bobloy"
],
"bot_version": [
3,
0,
0
],
"description": "Keep track of when users were last seen online",
"hidden": true,
"install_msg": "Thank you for installing LastSeen. Get started with `[p]help LastSeen`",
"requirements": ["nudepy"],
"short": "Last seen tracker",
"tags": [
"bobloy",
"utils",
"tools"
]
}

@ -0,0 +1,45 @@
from datetime import datetime
import discord
import nude
from nude import Nude
from redbot.core import Config
from redbot.core import commands
from redbot.core.bot import Red
class Nudity:
"""
V3 Cog Template
"""
online_status = discord.Status.online
offline_status = discord.Status.offline
def __init__(self, bot: Red):
self.bot = bot
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
default_guild = {
"enabled": False
}
self.config.register_guild(**default_guild)
@commands.command(aliases=['togglenudity'], name='nudity')
async def nudity(self, ctx: commands.Context):
"""Toggle nude-checking on or off"""
is_on = await self.config.guild(ctx.guild).enabled()
await self.config.guild(ctx.guild).enabled.set(not is_on)
await ctx.send("Nude checking is now set to {}".format(not is_on))
async def on_message(self, message: discord.Message):
is_on = await self.config.guild(message.guild).enabled()
if not is_on:
return
if not message.attachments:
return

@ -0,0 +1,5 @@
from .qrinvite import QRInvite
def setup(bot):
bot.add_cog(QRInvite(bot))

@ -0,0 +1,23 @@
{
"author": [
"Bobloy"
],
"bot_version": [
3,
0,
0
],
"description": "Create a QR code invite for the server",
"hidden": true,
"install_msg": "Thank you for installing QRInvite! Get started with `[p]help QRInvite`",
"requirements": [
"MyQR"
],
"short": "Create a QR code invite",
"tags": [
"bobloy",
"tools",
"qr",
"code"
]
}

@ -0,0 +1,81 @@
import pathlib
import aiohttp
import discord
from PIL import Image
from redbot.core import Config, checks, commands
from redbot.core.bot import Red
from MyQR import myqr
from redbot.core.data_manager import cog_data_path
class QRInvite:
"""
V3 Cog Template
"""
def __init__(self, bot: Red):
self.bot = bot
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
default_global = {}
default_guild = {}
self.config.register_global(**default_global)
self.config.register_guild(**default_guild)
@commands.command()
async def qrinvite(self, ctx: commands.Context, invite: str=None, colorized: bool=False, image_url: str=None):
"""
Create a custom QR code invite for this server
"""
if invite is None:
try:
invite = await ctx.channel.create_invite()
except discord.Forbidden:
try:
invite = await ctx.channel.invites()
invite = invite[0]
except discord.Forbidden:
await ctx.send("No permission to get an invite, please provide one")
return
invite = invite.code
if image_url is None:
image_url = ctx.guild.icon_url
extension = pathlib.Path(image_url).parts[-1].replace('.','?').split('?')[1]
path: pathlib.Path = cog_data_path(self)
image_path = path / (ctx.guild.icon+"."+extension)
async with aiohttp.ClientSession() as session:
async with session.get(image_url) as response:
image = await response.read()
with image_path.open("wb") as file:
file.write(image)
if extension == "webp":
new_path = convert_png(str(image_path))
else:
new_path = str(image_path)
myqr.run(invite,picture=new_path,save_name=ctx.guild.icon+"_qrcode.png",
save_dir=str(cog_data_path(self)),colorized=colorized,)
png_path: pathlib.Path = path / (ctx.guild.icon+"_qrcode.png")
with png_path.open("rb") as png_fp:
await ctx.send(file=discord.File(png_fp.read(), "qrcode.png"))
def convert_png(path):
im = Image.open(path)
im.load()
alpha = im.split()[-1]
im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
mask = Image.eval(alpha, lambda a: 255 if a <=128 else 0)
im.paste(255, mask)
newPath = path.replace(".webp",".png")
im.save(newPath, transparency=255)
return newPath

@ -1,12 +1,9 @@
import asyncio
from typing import List, Union
import discord
from redbot.core import Config
from redbot.core.bot import Red
from redbot.core import commands
from redbot.core.bot import Red
class ReactRestrictCombo:
@ -16,8 +13,8 @@ class ReactRestrictCombo:
def __eq__(self, other: "ReactRestrictCombo"):
return (
self.message_id == other.message_id and
self.role_id == other.role_id
self.message_id == other.message_id and
self.role_id == other.role_id
)
def to_json(self):
@ -83,7 +80,7 @@ class ReactRestrict:
"""
# is_custom = True
# if isinstance(emoji, str):
# is_custom = False
# is_custom = False
combo = ReactRestrictCombo(message_id, role.id)
@ -95,10 +92,10 @@ class ReactRestrict:
async def remove_react(self, message_id: int, role: discord.Role):
"""
Removes a given reaction.
Removes a given reaction
:param int message_id:
:param str or int emoji:
:param message_id:
:param role:
:return:
"""
current_combos = await self.combo_list()
@ -109,14 +106,13 @@ class ReactRestrict:
if to_keep != current_combos:
await self.set_combo_list(to_keep)
async def has_reactrestrict_combo(self, message_id: int)\
async def has_reactrestrict_combo(self, message_id: int) \
-> (bool, List[ReactRestrictCombo]):
"""
Determines if there is an existing role combo for a given message
Determines if there is an existing role combo for a given message
and emoji ID.
:param int message_id:
:param str or int emoji:
:param message_id:
:return:
"""
if not await self.is_registered(message_id):
@ -170,7 +166,7 @@ class ReactRestrict:
return role
async def _get_message_from_channel(self, channel_id: int, message_id: int)\
async def _get_message_from_channel(self, channel_id: int, message_id: int) \
-> Union[discord.Message, None]:
"""
Tries to find a message by ID in the current guild context.
@ -180,12 +176,12 @@ class ReactRestrict:
return await channel.get_message(message_id)
except discord.NotFound:
pass
except AttributeError: # VoiceChannel object has no attribute 'get_message'
except AttributeError: # VoiceChannel object has no attribute 'get_message'
pass
return None
async def _get_message(self, ctx: commands.Context, message_id: int)\
async def _get_message(self, ctx: commands.Context, message_id: int) \
-> Union[discord.Message, None]:
"""
Tries to find a message by ID in the current guild context.
@ -199,13 +195,11 @@ class ReactRestrict:
return await channel.get_message(message_id)
except discord.NotFound:
pass
except AttributeError: # VoiceChannel object has no attribute 'get_message'
except AttributeError: # VoiceChannel object has no attribute 'get_message'
pass
except discord.Forbidden: # No access to channel, skip
pass
return None
@commands.group()
@ -214,7 +208,7 @@ class ReactRestrict:
Base command for this cog. Check help for the commands list.
"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
@reactrestrict.command()
async def add(self, ctx: commands.Context, message_id: int, *, role: discord.Role):
@ -228,18 +222,18 @@ class ReactRestrict:
return
# try:
# emoji, actual_emoji = await self._wait_for_emoji(ctx)
# emoji, actual_emoji = await self._wait_for_emoji(ctx)
# except asyncio.TimeoutError:
# await ctx.send("You didn't respond in time, please redo this command.")
# return
# await ctx.send("You didn't respond in time, please redo this command.")
# return
#
# try:
# await message.add_reaction(actual_emoji)
# await message.add_reaction(actual_emoji)
# except discord.HTTPException:
# await ctx.send("I can't add that emoji because I'm not in the guild that"
# " owns it.")
# return
# await ctx.send("I can't add that emoji because I'm not in the guild that"
# " owns it.")
# return
#
# noinspection PyTypeChecker
await self.add_reactrestrict(message_id, role)
@ -251,10 +245,10 @@ class ReactRestrict:
Removes role associated with a given reaction.
"""
# try:
# emoji, actual_emoji = await self._wait_for_emoji(ctx)
# emoji, actual_emoji = await self._wait_for_emoji(ctx)
# except asyncio.TimeoutError:
# await ctx.send("You didn't respond in time, please redo this command.")
# return
# await ctx.send("You didn't respond in time, please redo this command.")
# return
# noinspection PyTypeChecker
await self.remove_react(message_id, role)
@ -302,46 +296,46 @@ class ReactRestrict:
message = await self._get_message_from_channel(channel_id, message_id)
await message.remove_reaction(emoji, member)
# try:
# await member.add_roles(*roles)
# except discord.Forbidden:
# pass
# try:
# await member.add_roles(*roles)
# except discord.Forbidden:
# pass
#
# async def on_raw_reaction_remove(self, emoji: discord.PartialReactionEmoji,
# message_id: int, channel_id: int, user_id: int):
# """
# 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
# has_reactrestrict, combos = await self.has_reactrestrict_combo(message_id, emoji_id)
# if not has_reactrestrict:
# return
# try:
# member = self._get_member(channel_id, user_id)
# except LookupError:
# return
# if member.bot:
# return
# try:
# roles = [self._get_role(member.guild, c.role_id) for c in combos]
# except LookupError:
# return
# try:
# await member.remove_roles(*roles)
# except discord.Forbidden:
# pass
# message_id: int, channel_id: int, user_id: int):
# """
# 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
#
# has_reactrestrict, combos = await self.has_reactrestrict_combo(message_id, emoji_id)
#
# if not has_reactrestrict:
# return
#
# try:
# member = self._get_member(channel_id, user_id)
# except LookupError:
# return
#
# if member.bot:
# return
#
# try:
# roles = [self._get_role(member.guild, c.role_id) for c in combos]
# except LookupError:
# return
#
# try:
# await member.remove_roles(*roles)
# except discord.Forbidden:
# pass

@ -1,7 +1,7 @@
import aiohttp
import html2text
from redbot.core import Config
from redbot.core import Config, commands
from redbot.core.bot import Red
from redbot.core.utils.chat_formatting import pagify
@ -32,8 +32,7 @@ class SayUrl:
"""
Converts a URL to something readable
:param url:
:return:
Works better on smaller websites
"""
h = html2text.HTML2Text()

@ -3,7 +3,7 @@ import asyncio
import discord
from redbot.core import Config
from redbot.core import Config, commands
from datetime import datetime, timedelta
@ -33,7 +33,7 @@ class Werewolf:
Base command for this cog. Check help for the commands list.
"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
@ww.command()
async def new(self, ctx, game_code):

@ -45,7 +45,7 @@ class StealEmoji:
Base command for this cog. Check help for the commands list.
"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
@stealemoji.command(name="collect")
async def se_collect(self, ctx):
@ -58,7 +58,7 @@ class StealEmoji:
async def se_bank(self, ctx):
"""Add current server as emoji bank"""
await ctx.send("This will upload custom emojis to this server\n"
"Are you sure you want to make the current server an emoji bank? (y/n)")
"Are you sure you want to make the current server an emoji bank? (y//n)")
def check(m):
return m.content.upper() in ["Y", "YES", "N", "NO"] and m.channel == ctx.channel and m.author == ctx.author

@ -37,7 +37,7 @@ class Timerole:
async def timerole(self, ctx):
"""Adjust timerole settings"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
@timerole.command()
async def addrole(self, ctx: commands.Context, role: discord.Role, days: int, *requiredroles: discord.Role):

@ -0,0 +1,5 @@
from .tts import TTS
def setup(bot):
bot.add_cog(TTS(bot))

@ -0,0 +1,22 @@
{
"author": [
"Bobloy"
],
"bot_version": [
3,
0,
0
],
"description": "Send Text2Speech messages as an uploaded mp3",
"hidden": true,
"install_msg": "Thank you for installing TTS. Get started with `[p]tts`",
"requirements": [
"gTTS"
],
"short": "Send TTS messages as uploaded mp3",
"tags": [
"bobloy",
"utils",
"audio"
]
}

@ -0,0 +1,34 @@
import io
import discord
from gtts import gTTS
from redbot.core import Config, commands
from redbot.core.bot import Red
class TTS:
"""
V3 Cog Template
"""
def __init__(self, bot: Red):
self.bot = bot
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
default_global = {}
default_guild = {}
self.config.register_global(**default_global)
self.config.register_guild(**default_guild)
@commands.command(aliases=["t2s", "text2"])
async def tts(self, ctx: commands.Context, *, text: str):
"""
My custom cog
Extra information goes here
"""
mp3_fp = io.BytesIO()
tts = gTTS(text, 'en')
tts.write_to_fp(mp3_fp)
await ctx.send(file=discord.File(mp3_fp.getvalue(), "text.mp3"))

@ -120,8 +120,6 @@ async def parse_code(code, game):
digits += 1
continue
try:
idx = int(built)
except ValueError:
@ -146,7 +144,6 @@ async def parse_code(code, game):
built = ""
return decode

@ -16,7 +16,6 @@ class Seer(Role):
description = "A mystic in search of answers in a chaotic town.\n" \
"Calls upon the cosmos to discern those of Lycan blood"
def __init__(self, game):
super().__init__(game)
# self.game = game

@ -53,7 +53,7 @@ class Werewolf:
Base command to adjust settings. Check help for command list.
"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
@commands.guild_only()
@wwset.command(name="list")
@ -136,7 +136,7 @@ class Werewolf:
Base command for this cog. Check help for the commands list.
"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
pass
@commands.guild_only()
@ww.command(name="new")

Loading…
Cancel
Save