Merge branch 'master' into hangman-develop
This commit is contained in:
commit
3a9befe411
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,5 @@
|
|||||||
.idea/
|
.idea/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
venv/
|
||||||
|
v-data/
|
||||||
|
database.sqlite3
|
||||||
|
12
README.md
12
README.md
@ -3,21 +3,25 @@
|
|||||||
Cog Function
|
Cog Function
|
||||||
|
|
||||||
| Name | Status | Description (Click to see full status)
|
| 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> |
|
| 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> |
|
| 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> |
|
| 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> |
|
| 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> |
|
| 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> |
|
| howdoi | **Incomplete** | <details><summary>Ask coding questions and get results from StackExchange</summary>Not yet functional</details> |
|
||||||
| leaver | **Incomplete** | <details><summary>Send a message in a channel when a user leaves the server</summary>Not yet ported to v3</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> |
|
| 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> |
|
| 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> |
|
| 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> |
|
| 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> |
|
| 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> |
|
| 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> |
|
| werewolf | **Alpha** | <details><summary>Play the classic party game Werewolf within discord</summary>Another massive project currently being developed, will be fully customizable</details> |
|
||||||
|
|
||||||
|
|
||||||
|
9
announcedaily/__init__.py
Normal file
9
announcedaily/__init__.py
Normal file
@ -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())
|
250
announcedaily/announcedaily.py
Normal file
250
announcedaily/announcedaily.py
Normal file
@ -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
|
18
announcedaily/info..json
Normal file
18
announcedaily/info..json
Normal file
@ -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 re
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
from redbot.core import Config, checks
|
from redbot.core import Config, checks
|
||||||
from redbot.core import commands
|
from redbot.core import commands
|
||||||
from redbot.core.utils.chat_formatting import pagify, box
|
from redbot.core.utils.chat_formatting import pagify, box
|
||||||
@ -30,7 +29,7 @@ class CCRole:
|
|||||||
|
|
||||||
Highly customizable custom commands with role management."""
|
Highly customizable custom commands with role management."""
|
||||||
if not ctx.invoked_subcommand:
|
if not ctx.invoked_subcommand:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@ccrole.command(name="add")
|
@ccrole.command(name="add")
|
||||||
@checks.mod_or_permissions(administrator=True)
|
@checks.mod_or_permissions(administrator=True)
|
||||||
@ -106,7 +105,7 @@ class CCRole:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Selfrole
|
# 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:
|
try:
|
||||||
answer = await self.bot.wait_for('message', timeout=120, check=check)
|
answer = await self.bot.wait_for('message', timeout=120, check=check)
|
||||||
@ -191,7 +190,7 @@ class CCRole:
|
|||||||
"""Shows custom commands list"""
|
"""Shows custom commands list"""
|
||||||
guild = ctx.guild
|
guild = ctx.guild
|
||||||
cmd_list = await self.config.guild(guild).cmdlist()
|
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:
|
if not cmd_list:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"There are no custom commands in this server. Use `{}ccrole add` to start adding some.".format(
|
"There are no custom commands in this server. Use `{}ccrole add` to start adding some.".format(
|
||||||
|
@ -1,10 +1,22 @@
|
|||||||
{
|
{
|
||||||
"author" : ["Bobloy"],
|
"author": [
|
||||||
"bot_version" : [3,0,0],
|
"Bobloy"
|
||||||
"description" : "[Incomplete] Creates custom commands to adjust roles and send custom messages",
|
],
|
||||||
"hidden" : false,
|
"bot_version": [
|
||||||
"install_msg" : "Thank you for installing Custom Commands w/ Roles.",
|
3,
|
||||||
"requirements" : [],
|
0,
|
||||||
"short" : "[Incomplete] Creates commands that adjust roles",
|
0
|
||||||
"tags" : ["fox", "bobloy", "utility", "tools", "roles"]
|
],
|
||||||
|
"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 asyncio
|
||||||
|
import pathlib
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
from redbot.core import Config
|
from redbot.core import Config
|
||||||
from redbot.core import commands
|
from redbot.core import commands
|
||||||
|
from redbot.core.data_manager import cog_data_path
|
||||||
|
|
||||||
from chatter.chatterbot import ChatBot
|
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
|
from chatter.chatterbot.trainers import ListTrainer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Chatter:
|
class Chatter:
|
||||||
"""
|
"""
|
||||||
This cog trains a chatbot that will talk like members of your Guild
|
This cog trains a chatbot that will talk like members of your Guild
|
||||||
@ -24,11 +26,23 @@ class Chatter:
|
|||||||
"whitelist": None,
|
"whitelist": None,
|
||||||
"days": 1
|
"days": 1
|
||||||
}
|
}
|
||||||
|
path: pathlib.Path = cog_data_path(self)
|
||||||
|
data_path = path / ("database.sqlite3")
|
||||||
|
|
||||||
self.chatbot = ChatBot(
|
self.chatbot = ChatBot(
|
||||||
"ChatterBot",
|
"ChatterBot",
|
||||||
storage_adapter='chatter.chatterbot.storage.SQLStorageAdapter',
|
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)
|
self.chatbot.set_trainer(ListTrainer)
|
||||||
|
|
||||||
@ -43,21 +57,42 @@ class Chatter:
|
|||||||
Currently takes a stupid long time
|
Currently takes a stupid long time
|
||||||
Returns a list of text
|
Returns a list of text
|
||||||
"""
|
"""
|
||||||
out = []
|
out = [[]]
|
||||||
after = datetime.today() - timedelta(days=(await self.config.guild(ctx.guild).days()))
|
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:
|
for channel in ctx.guild.text_channels:
|
||||||
if in_channel:
|
if in_channel:
|
||||||
channel = in_channel
|
channel = in_channel
|
||||||
await ctx.send("Gathering {}".format(channel.mention))
|
await ctx.send("Gathering {}".format(channel.mention))
|
||||||
user = None
|
user = None
|
||||||
|
i = 0
|
||||||
|
send_time = None
|
||||||
try:
|
try:
|
||||||
|
|
||||||
async for message in channel.history(limit=None, reverse=True, after=after):
|
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:
|
if user == message.author:
|
||||||
out[-1] += "\n" + message.clean_content
|
out[i][-1] += "\n" + message.clean_content
|
||||||
else:
|
else:
|
||||||
user = message.author
|
user = message.author
|
||||||
out.append(message.clean_content)
|
out[i].append(message.clean_content)
|
||||||
|
|
||||||
except discord.Forbidden:
|
except discord.Forbidden:
|
||||||
pass
|
pass
|
||||||
except discord.HTTPException:
|
except discord.HTTPException:
|
||||||
@ -70,18 +105,19 @@ class Chatter:
|
|||||||
|
|
||||||
def _train(self, data):
|
def _train(self, data):
|
||||||
try:
|
try:
|
||||||
self.chatbot.train(data)
|
for convo in data:
|
||||||
|
self.chatbot.train(convo)
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@commands.group()
|
@commands.group(invoke_without_command=False)
|
||||||
async def chatter(self, ctx: commands.Context):
|
async def chatter(self, ctx: commands.Context):
|
||||||
"""
|
"""
|
||||||
Base command for this cog. Check help for the commands list.
|
Base command for this cog. Check help for the commands list.
|
||||||
"""
|
"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@chatter.command()
|
@chatter.command()
|
||||||
async def age(self, ctx: commands.Context, days: int):
|
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
|
Backup your training data to a json for later use
|
||||||
"""
|
"""
|
||||||
await ctx.send("Backing up data, this may take a while")
|
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:
|
if future:
|
||||||
await ctx.send("Backup successful!")
|
await ctx.send("Backup successful!")
|
||||||
@ -134,17 +171,21 @@ class Chatter:
|
|||||||
else:
|
else:
|
||||||
await ctx.send("Error occurred :(")
|
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
|
Credit to https://github.com/Twentysix26/26-Cogs/blob/master/cleverbot/cleverbot.py
|
||||||
for on_message recognition of @bot
|
for on_message recognition of @bot
|
||||||
"""
|
"""
|
||||||
author = message.author
|
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:
|
if author.id != self.bot.user.id:
|
||||||
to_strip = "@" + author.guild.me.display_name + " "
|
to_strip = "@" + guild.me.display_name + " "
|
||||||
text = message.clean_content
|
text = message.clean_content
|
||||||
if not text.startswith(to_strip):
|
if not text.startswith(to_strip):
|
||||||
return
|
return
|
||||||
@ -152,7 +193,7 @@ class Chatter:
|
|||||||
async with channel.typing():
|
async with channel.typing():
|
||||||
future = await self.loop.run_in_executor(None, self.chatbot.get_response, text)
|
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))
|
await channel.send(str(future))
|
||||||
else:
|
else:
|
||||||
await channel.send(':thinking:')
|
await channel.send(':thinking:')
|
||||||
|
@ -2,10 +2,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from . import utils
|
from chatter.chatterbot import utils
|
||||||
from .input import InputAdapter
|
|
||||||
from .output import OutputAdapter
|
|
||||||
from .storage import StorageAdapter
|
|
||||||
|
|
||||||
|
|
||||||
class ChatBot(object):
|
class ChatBot(object):
|
||||||
@ -14,7 +11,7 @@ class ChatBot(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, **kwargs):
|
def __init__(self, name, **kwargs):
|
||||||
from .logic import MultiLogicAdapter
|
from chatter.chatterbot.logic import MultiLogicAdapter
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
kwargs['name'] = name
|
kwargs['name'] = name
|
||||||
@ -33,9 +30,9 @@ class ChatBot(object):
|
|||||||
output_adapter = kwargs.get('output_adapter', 'chatter.chatterbot.output.OutputAdapter')
|
output_adapter = kwargs.get('output_adapter', 'chatter.chatterbot.output.OutputAdapter')
|
||||||
|
|
||||||
# Check that each adapter is a valid subclass of it's respective parent
|
# Check that each adapter is a valid subclass of it's respective parent
|
||||||
utils.validate_adapter_class(storage_adapter, StorageAdapter)
|
# utils.validate_adapter_class(storage_adapter, StorageAdapter)
|
||||||
utils.validate_adapter_class(input_adapter, InputAdapter)
|
# utils.validate_adapter_class(input_adapter, InputAdapter)
|
||||||
utils.validate_adapter_class(output_adapter, OutputAdapter)
|
# utils.validate_adapter_class(output_adapter, OutputAdapter)
|
||||||
|
|
||||||
self.logic = MultiLogicAdapter(**kwargs)
|
self.logic = MultiLogicAdapter(**kwargs)
|
||||||
self.storage = utils.initialize_class(storage_adapter, **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.
|
Learn that the statement provided is a valid response.
|
||||||
"""
|
"""
|
||||||
from .conversation import Response
|
from chatter.chatterbot.conversation import Response
|
||||||
|
|
||||||
if previous_statement:
|
if previous_statement:
|
||||||
statement.add_response(
|
statement.add_response(
|
||||||
|
@ -92,7 +92,7 @@ class SynsetDistance(Comparator):
|
|||||||
"""
|
"""
|
||||||
Download required NLTK corpora if they have not already been downloaded.
|
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')
|
nltk_download_corpus('corpora/wordnet')
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ class SynsetDistance(Comparator):
|
|||||||
"""
|
"""
|
||||||
Download required NLTK corpora if they have not already been downloaded.
|
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')
|
nltk_download_corpus('tokenizers/punkt')
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ class SynsetDistance(Comparator):
|
|||||||
"""
|
"""
|
||||||
Download required NLTK corpora if they have not already been downloaded.
|
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')
|
nltk_download_corpus('corpora/stopwords')
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ class SentimentComparison(Comparator):
|
|||||||
Download the NLTK vader lexicon for sentiment analysis
|
Download the NLTK vader lexicon for sentiment analysis
|
||||||
that is required for this algorithm to run.
|
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')
|
nltk_download_corpus('sentiment/vader_lexicon')
|
||||||
|
|
||||||
@ -252,7 +252,7 @@ class JaccardSimilarity(Comparator):
|
|||||||
Download the NLTK wordnet corpora that is required for this algorithm
|
Download the NLTK wordnet corpora that is required for this algorithm
|
||||||
to run only if the corpora has not already been downloaded.
|
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')
|
nltk_download_corpus('corpora/wordnet')
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from .best_match import BestMatch
|
|
||||||
from .logic_adapter import LogicAdapter
|
from .logic_adapter import LogicAdapter
|
||||||
|
from .best_match import BestMatch
|
||||||
from .low_confidence import LowConfidenceAdapter
|
from .low_confidence import LowConfidenceAdapter
|
||||||
from .mathematical_evaluation import MathematicalEvaluation
|
from .mathematical_evaluation import MathematicalEvaluation
|
||||||
from .multi_adapter import MultiLogicAdapter
|
from .multi_adapter import MultiLogicAdapter
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from .logic_adapter import LogicAdapter
|
from chatter.chatterbot.logic import LogicAdapter
|
||||||
|
|
||||||
|
|
||||||
class BestMatch(LogicAdapter):
|
class BestMatch(LogicAdapter):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from chatter.chatterbot.conversation import Statement
|
from chatter.chatterbot.conversation import Statement
|
||||||
from .best_match import BestMatch
|
from chatter.chatterbot.logic import BestMatch
|
||||||
|
|
||||||
|
|
||||||
class LowConfidenceAdapter(BestMatch):
|
class LowConfidenceAdapter(BestMatch):
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import unicode_literals
|
|||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
|
||||||
from chatter.chatterbot import utils
|
from chatter.chatterbot import utils
|
||||||
from .logic_adapter import LogicAdapter
|
from chatter.chatterbot.logic import LogicAdapter
|
||||||
|
|
||||||
|
|
||||||
class MultiLogicAdapter(LogicAdapter):
|
class MultiLogicAdapter(LogicAdapter):
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from .logic_adapter import LogicAdapter
|
from chatter.chatterbot.logic import LogicAdapter
|
||||||
|
|
||||||
|
|
||||||
class NoKnowledgeAdapter(LogicAdapter):
|
class NoKnowledgeAdapter(LogicAdapter):
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from .logic_adapter import LogicAdapter
|
from chatter.chatterbot.logic import LogicAdapter
|
||||||
|
|
||||||
|
|
||||||
class SpecificResponseAdapter(LogicAdapter):
|
class SpecificResponseAdapter(LogicAdapter):
|
||||||
|
@ -2,7 +2,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from .logic_adapter import LogicAdapter
|
from chatter.chatterbot.logic import LogicAdapter
|
||||||
|
|
||||||
|
|
||||||
class TimeLogicAdapter(LogicAdapter):
|
class TimeLogicAdapter(LogicAdapter):
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
from .output_adapter import OutputAdapter
|
||||||
from .gitter import Gitter
|
from .gitter import Gitter
|
||||||
from .hipchat import HipChat
|
from .hipchat import HipChat
|
||||||
from .mailgun import Mailgun
|
from .mailgun import Mailgun
|
||||||
from .microsoft import Microsoft
|
from .microsoft import Microsoft
|
||||||
from .output_adapter import OutputAdapter
|
|
||||||
from .terminal import TerminalAdapter
|
from .terminal import TerminalAdapter
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from .output_adapter import OutputAdapter
|
from chatter.chatterbot.output import OutputAdapter
|
||||||
|
|
||||||
|
|
||||||
class Gitter(OutputAdapter):
|
class Gitter(OutputAdapter):
|
||||||
|
@ -2,7 +2,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from .output_adapter import OutputAdapter
|
from chatter.chatterbot.output import OutputAdapter
|
||||||
|
|
||||||
|
|
||||||
class HipChat(OutputAdapter):
|
class HipChat(OutputAdapter):
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from .output_adapter import OutputAdapter
|
from chatter.chatterbot.output import OutputAdapter
|
||||||
|
|
||||||
|
|
||||||
class Mailgun(OutputAdapter):
|
class Mailgun(OutputAdapter):
|
||||||
|
@ -2,7 +2,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from .output_adapter import OutputAdapter
|
from chatter.chatterbot.output import OutputAdapter
|
||||||
|
|
||||||
|
|
||||||
class Microsoft(OutputAdapter):
|
class Microsoft(OutputAdapter):
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from .output_adapter import OutputAdapter
|
from chatter.chatterbot.output import OutputAdapter
|
||||||
|
|
||||||
|
|
||||||
class TerminalAdapter(OutputAdapter):
|
class TerminalAdapter(OutputAdapter):
|
||||||
|
@ -158,7 +158,9 @@ class StorageAdapter(object):
|
|||||||
class EmptyDatabaseException(Exception):
|
class EmptyDatabaseException(Exception):
|
||||||
|
|
||||||
def __init__(self,
|
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
|
self.value = value
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -2,8 +2,8 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from . import utils
|
from chatter.chatterbot import utils
|
||||||
from .conversation import Statement, Response
|
from chatter.chatterbot.conversation import Statement, Response
|
||||||
|
|
||||||
|
|
||||||
class Trainer(object):
|
class Trainer(object):
|
||||||
@ -127,7 +127,7 @@ class ChatterBotCorpusTrainer(Trainer):
|
|||||||
|
|
||||||
def __init__(self, storage, **kwargs):
|
def __init__(self, storage, **kwargs):
|
||||||
super(ChatterBotCorpusTrainer, self).__init__(storage, **kwargs)
|
super(ChatterBotCorpusTrainer, self).__init__(storage, **kwargs)
|
||||||
from .corpus import Corpus
|
from chatter.chatterbot.corpus import Corpus
|
||||||
|
|
||||||
self.corpus = Corpus()
|
self.corpus = Corpus()
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ def validate_adapter_class(validate_class, adapter_class):
|
|||||||
|
|
||||||
:raises: Adapter.InvalidAdapterTypeException
|
: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 a dictionary was passed in, check if it has an import_path attribute
|
||||||
if isinstance(validate_class, dict):
|
if isinstance(validate_class, dict):
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import discord
|
import discord
|
||||||
|
|
||||||
from redbot.core import Config, checks
|
|
||||||
|
|
||||||
from redbot.core.bot import Red
|
|
||||||
|
|
||||||
from pylint import epylint as lint
|
from pylint import epylint as lint
|
||||||
|
from redbot.core import Config
|
||||||
from redbot.core import commands
|
from redbot.core import commands
|
||||||
|
from redbot.core.bot import Red
|
||||||
from redbot.core.data_manager import cog_data_path
|
from redbot.core.data_manager import cog_data_path
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
import asyncio
|
||||||
import os
|
import os
|
||||||
import math
|
import math
|
||||||
|
|
||||||
# from typing import Union
|
# from typing import Union
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
from redbot.core import commands
|
||||||
|
|
||||||
from redbot.core.utils.chat_formatting import pagify
|
from redbot.core.utils.chat_formatting import pagify
|
||||||
from redbot.core.utils.chat_formatting import box
|
from redbot.core.utils.chat_formatting import box
|
||||||
@ -102,7 +103,7 @@ class Fight:
|
|||||||
await ctx.send("Current tournament ID: " + await self._activefight(ctx))
|
await ctx.send("Current tournament ID: " + await self._activefight(ctx))
|
||||||
|
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
# await ctx.send("I can do stuff!")
|
# await ctx.send("I can do stuff!")
|
||||||
|
|
||||||
@fight.command(name="join")
|
@fight.command(name="join")
|
||||||
@ -198,10 +199,10 @@ class Fight:
|
|||||||
async def fadmin(self, ctx):
|
async def fadmin(self, ctx):
|
||||||
"""Admin command for managing the current tournament"""
|
"""Admin command for managing the current tournament"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@fadmin.command(name="score")
|
@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"""
|
"""Set's the score for matchID and clears disputes"""
|
||||||
currFight = await self._getcurrentfight(ctx)
|
currFight = await self._getcurrentfight(ctx)
|
||||||
tID = await self._activefight(ctx)
|
tID = await self._activefight(ctx)
|
||||||
@ -213,11 +214,11 @@ class Fight:
|
|||||||
await ctx.send("Tournament currently not accepting new players")
|
await ctx.send("Tournament currently not accepting new players")
|
||||||
return
|
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!")
|
await ctx.send("You are already in this tournament!")
|
||||||
return
|
return
|
||||||
|
|
||||||
currFight["PLAYERS"].append(user.id)
|
currFight["PLAYERS"].append(ctx.user.id)
|
||||||
|
|
||||||
await self._save_fight(ctx, tID, currFight)
|
await self._save_fight(ctx, tID, currFight)
|
||||||
|
|
||||||
@ -256,7 +257,7 @@ class Fight:
|
|||||||
# self.save_data()
|
# self.save_data()
|
||||||
|
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
# await ctx.send("I can do stuff!")
|
# await ctx.send("I can do stuff!")
|
||||||
|
|
||||||
@fightset.command(name="emoji")
|
@fightset.command(name="emoji")
|
||||||
@ -548,7 +549,7 @@ class Fight:
|
|||||||
async def fightset_guild(self, ctx):
|
async def fightset_guild(self, ctx):
|
||||||
"""Adjust guild wide settings"""
|
"""Adjust guild wide settings"""
|
||||||
if ctx.invoked_subcommand is None or isinstance(ctx.invoked_subcommand, commands.Group):
|
if ctx.invoked_subcommand is None or isinstance(ctx.invoked_subcommand, commands.Group):
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@fightset_guild.command(name="selfreport")
|
@fightset_guild.command(name="selfreport")
|
||||||
async def fightset_guild_selfreport(self, ctx):
|
async def fightset_guild_selfreport(self, ctx):
|
||||||
@ -711,11 +712,13 @@ class Fight:
|
|||||||
|
|
||||||
async def _embed_tourney(self, ctx, tID):
|
async def _embed_tourney(self, ctx, tID):
|
||||||
"""Prints a pretty embed of the tournament"""
|
"""Prints a pretty embed of the tournament"""
|
||||||
await ctx.send("_placeholder Todo")
|
#_placeholder Todo
|
||||||
|
pass
|
||||||
|
|
||||||
async def _comparescores(self):
|
async def _comparescores(self):
|
||||||
"""Checks user submitted scores for inconsistancies"""
|
"""Checks user submitted scores for inconsistancies"""
|
||||||
await ctx.send("_comparescores Todo")
|
# _comparescores Todo
|
||||||
|
pass
|
||||||
|
|
||||||
async def _parseuser(self, guild: discord.Guild, tID, userid):
|
async def _parseuser(self, guild: discord.Guild, tID, userid):
|
||||||
"""Finds user in the tournament"""
|
"""Finds user in the tournament"""
|
||||||
@ -821,8 +824,8 @@ class Fight:
|
|||||||
"""Reports a win for member in match"""
|
"""Reports a win for member in match"""
|
||||||
theT = await self._getfight(guild, tID)
|
theT = await self._getfight(guild, tID)
|
||||||
|
|
||||||
if member.id not in theT["PLAYERS"]: # Shouldn't happen
|
# if member.id not in theT["PLAYERS"]: # Shouldn't happen
|
||||||
return False
|
# return False
|
||||||
|
|
||||||
if theT["RULES"]["TYPE"] == 0:
|
if theT["RULES"]["TYPE"] == 0:
|
||||||
return await self._rr_report_dispute(guild, tID, mID)
|
return await self._rr_report_dispute(guild, tID, mID)
|
||||||
@ -833,13 +836,16 @@ class Fight:
|
|||||||
|
|
||||||
# **********************Single Elimination***************************
|
# **********************Single Elimination***************************
|
||||||
async def _elim_setup(self, tID):
|
async def _elim_setup(self, tID):
|
||||||
await ctx.send("Elim setup todo")
|
# ToDo Elim setup
|
||||||
|
pass
|
||||||
|
|
||||||
async def _elim_start(self, tID):
|
async def _elim_start(self, tID):
|
||||||
await ctx.send("Elim start todo")
|
# ToDo Elim start
|
||||||
|
pass
|
||||||
|
|
||||||
async def _elim_update(self, matchID):
|
async def _elim_update(self, matchID):
|
||||||
await ctx.send("Elim update todo")
|
# ToDo Elim update
|
||||||
|
pass
|
||||||
|
|
||||||
# **********************Round-Robin**********************************
|
# **********************Round-Robin**********************************
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"author" : ["Bobloy"],
|
"author" : ["Bobloy"],
|
||||||
"bot_version" : [3,0,0],
|
"bot_version" : [3,0,0],
|
||||||
"description" : "[Incomplete] Cog to organize tournaments within Discord",
|
"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",
|
"install_msg" : "Thank you for installing Fight. Run with [p]fight or [p]fightset",
|
||||||
"requirements" : [],
|
"requirements" : [],
|
||||||
"short" : "[Incomplete] Cog to organize tournaments",
|
"short" : "[Incomplete] Cog to organize tournaments",
|
||||||
|
5
flag/__init__.py
Normal file
5
flag/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from .flag import Flag
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(Flag(bot))
|
184
flag/flag.py
Normal file
184
flag/flag.py
Normal file
@ -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)
|
23
flag/info..json
Normal file
23
flag/info..json
Normal file
@ -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"
|
||||||
|
]
|
||||||
|
}
|
5
forcemention/__init__.py
Normal file
5
forcemention/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from .forcemention import ForceMention
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(ForceMention(bot))
|
38
forcemention/forcemention.py
Normal file
38
forcemention/forcemention.py
Normal file
@ -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))
|
19
forcemention/info..json
Normal file
19
forcemention/info..json
Normal file
@ -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)
|
@checks.mod_or_permissions(administrator=True)
|
||||||
async def hangset(self, ctx):
|
async def hangset(self, ctx):
|
||||||
"""Adjust hangman settings"""
|
"""Adjust hangman settings"""
|
||||||
if not ctx.invoked_subcommand:
|
if ctx.invoked_subcommand is None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@hangset.command(pass_context=True)
|
@hangset.command(pass_context=True)
|
||||||
|
@ -33,7 +33,7 @@ class Howdoi:
|
|||||||
"""Adjust howdoi settings
|
"""Adjust howdoi settings
|
||||||
Settings are reset on reload"""
|
Settings are reset on reload"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@howdoiset.command(pass_context=True, name="answers")
|
@howdoiset.command(pass_context=True, name="answers")
|
||||||
async def howdoiset_answers(self, ctx, num_answers: int=1):
|
async def howdoiset_answers(self, ctx, num_answers: int=1):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"AUTHOR": "Bobloy",
|
"AUTHOR": "Bobloy",
|
||||||
"INSTALL_MSG": "Thank you for installing Fox-Cogs by Bobloy",
|
"INSTALL_MSG": "Thank you for installing Fox-V3 by Bobloy",
|
||||||
"NAME": "Fox-Cogs",
|
"NAME": "Fox-V3",
|
||||||
"SHORT": "Cogs by Bobloy",
|
"SHORT": "Cogs by Bobloy",
|
||||||
"DESCRIPTION": "Cogs for RED Discord Bot by Bobloy"
|
"DESCRIPTION": "Cogs for RED Discord Bot by Bobloy"
|
||||||
}
|
}
|
5
leaver/__init__.py
Normal file
5
leaver/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from .leaver import Leaver
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(Leaver(bot))
|
@ -1,9 +1,20 @@
|
|||||||
{
|
{
|
||||||
"AUTHOR": "Bobloy",
|
"author": [
|
||||||
"INSTALL_MSG": "Thank you for installing leaver",
|
"Bobloy"
|
||||||
"NAME": "Leaver",
|
],
|
||||||
"SHORT": "Sends message on leave",
|
"bot_version": [
|
||||||
"DESCRIPTION": "Keeps track of when people leave the server, and posts a message notifying",
|
3,
|
||||||
"TAGS": ["fox", "bobloy", "utilities", "tools", "tool"],
|
0,
|
||||||
"HIDDEN": false
|
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 discord
|
||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
|
from redbot.core import Config, checks, commands
|
||||||
from .utils.dataIO import dataIO
|
from redbot.core.commands import Context
|
||||||
from .utils import checks
|
|
||||||
|
|
||||||
|
|
||||||
class Leaver:
|
class Leaver:
|
||||||
"""Creates a goodbye message when people leave"""
|
"""
|
||||||
|
Creates a goodbye message when people leave
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.path = "data/Fox-Cogs/leaver"
|
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
|
||||||
self.file_path = "data/Fox-Cogs/leaver/leaver.json"
|
default_guild = {
|
||||||
self.the_data = dataIO.load_json(self.file_path)
|
"channel": ''
|
||||||
|
}
|
||||||
|
|
||||||
def save_data(self):
|
self.config.register_guild(**default_guild)
|
||||||
"""Saves the json"""
|
|
||||||
dataIO.save_json(self.file_path, self.the_data)
|
|
||||||
|
|
||||||
@commands.group(aliases=['setleaver'], pass_context=True, no_pm=True)
|
@commands.group(aliases=['setleaver'])
|
||||||
@checks.mod_or_permissions(administrator=True)
|
@checks.mod_or_permissions(administrator=True)
|
||||||
async def leaverset(self, ctx):
|
async def leaverset(self, ctx):
|
||||||
"""Adjust leaver settings"""
|
"""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:
|
if ctx.invoked_subcommand is None:
|
||||||
await self.bot.send_cmd_help(ctx)
|
pass
|
||||||
|
|
||||||
@leaverset.command(pass_context=True, no_pm=True)
|
@leaverset.command()
|
||||||
async def channel(self, ctx):
|
async def channel(self, ctx: Context):
|
||||||
server = ctx.message.server
|
guild = ctx.guild
|
||||||
if 'CHANNEL' not in self.the_data[server.id]:
|
await self.config.guild(guild).channel.set(ctx.channel.id)
|
||||||
self.the_data[server.id]['CHANNEL'] = ''
|
await ctx.send("Channel set to " + ctx.channel.name)
|
||||||
|
|
||||||
|
|
||||||
self.the_data[server.id]['CHANNEL'] = ctx.message.channel.id
|
async def on_member_remove(self, member: discord.Member):
|
||||||
self.save_data()
|
guild = member.guild
|
||||||
await self.bot.say("Channel set to "+ctx.message.channel.name)
|
channel = await self.config.guild(guild).channel()
|
||||||
|
|
||||||
async def when_leave(self, member):
|
if channel != '':
|
||||||
server = member.server
|
channel = guild.get_channel(channel)
|
||||||
if server.id in self.the_data:
|
await channel.send(str(member) + "(*" + str(member.nick) + "*) has left the server!")
|
||||||
await self.bot.send_message(server.get_channel(self.the_data[server.id]['CHANNEL']),
|
|
||||||
str(member) + "(*" + str(member.nick) +"*) has left the server!")
|
|
||||||
else:
|
else:
|
||||||
await self.bot.send_message(server.default_channel.id, str(member) + " (*" + str(member.nick) +"*) has left the server!")
|
pass
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
20
lseen/info..json
Normal file
20
lseen/info..json
Normal file
@ -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:
|
class LastSeen:
|
||||||
"""
|
"""
|
||||||
V3 Cog Template
|
Report when a user was last seen online
|
||||||
"""
|
"""
|
||||||
|
|
||||||
online_status = discord.Status.online
|
online_status = discord.Status.online
|
||||||
@ -41,7 +41,7 @@ class LastSeen:
|
|||||||
async def lset(self, ctx: commands.Context):
|
async def lset(self, ctx: commands.Context):
|
||||||
"""Change settings for lseen"""
|
"""Change settings for lseen"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@lset.command(name="toggle")
|
@lset.command(name="toggle")
|
||||||
async def lset_toggle(self, ctx: commands.Context):
|
async def lset_toggle(self, ctx: commands.Context):
|
||||||
@ -58,8 +58,6 @@ class LastSeen:
|
|||||||
async def lseen(self, ctx: commands.Context, member: discord.Member):
|
async def lseen(self, ctx: commands.Context, member: discord.Member):
|
||||||
"""
|
"""
|
||||||
Just says the time the user was last seen
|
Just says the time the user was last seen
|
||||||
|
|
||||||
:param member:
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if member.status != self.offline_status:
|
if member.status != self.offline_status:
|
||||||
|
5
nudity/__init__.py
Normal file
5
nudity/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from .nudity import Nudity
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(Nudity(bot))
|
20
nudity/info..json
Normal file
20
nudity/info..json
Normal file
@ -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"
|
||||||
|
]
|
||||||
|
}
|
45
nudity/nudity.py
Normal file
45
nudity/nudity.py
Normal file
@ -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
|
||||||
|
|
||||||
|
|
5
qrinvite/__init__.py
Normal file
5
qrinvite/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from .qrinvite import QRInvite
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(QRInvite(bot))
|
23
qrinvite/info..json
Normal file
23
qrinvite/info..json
Normal file
@ -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"
|
||||||
|
]
|
||||||
|
}
|
81
qrinvite/qrinvite.py
Normal file
81
qrinvite/qrinvite.py
Normal file
@ -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
|
from typing import List, Union
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
|
|
||||||
from redbot.core import Config
|
from redbot.core import Config
|
||||||
from redbot.core.bot import Red
|
|
||||||
from redbot.core import commands
|
from redbot.core import commands
|
||||||
|
from redbot.core.bot import Red
|
||||||
|
|
||||||
|
|
||||||
class ReactRestrictCombo:
|
class ReactRestrictCombo:
|
||||||
@ -16,8 +13,8 @@ class ReactRestrictCombo:
|
|||||||
|
|
||||||
def __eq__(self, other: "ReactRestrictCombo"):
|
def __eq__(self, other: "ReactRestrictCombo"):
|
||||||
return (
|
return (
|
||||||
self.message_id == other.message_id and
|
self.message_id == other.message_id and
|
||||||
self.role_id == other.role_id
|
self.role_id == other.role_id
|
||||||
)
|
)
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
@ -83,7 +80,7 @@ class ReactRestrict:
|
|||||||
"""
|
"""
|
||||||
# is_custom = True
|
# is_custom = True
|
||||||
# if isinstance(emoji, str):
|
# if isinstance(emoji, str):
|
||||||
# is_custom = False
|
# is_custom = False
|
||||||
|
|
||||||
combo = ReactRestrictCombo(message_id, role.id)
|
combo = ReactRestrictCombo(message_id, role.id)
|
||||||
|
|
||||||
@ -95,10 +92,10 @@ class ReactRestrict:
|
|||||||
|
|
||||||
async def remove_react(self, message_id: int, role: discord.Role):
|
async def remove_react(self, message_id: int, role: discord.Role):
|
||||||
"""
|
"""
|
||||||
Removes a given reaction.
|
Removes a given reaction
|
||||||
|
|
||||||
:param int message_id:
|
:param message_id:
|
||||||
:param str or int emoji:
|
:param role:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
current_combos = await self.combo_list()
|
current_combos = await self.combo_list()
|
||||||
@ -109,14 +106,13 @@ class ReactRestrict:
|
|||||||
if to_keep != current_combos:
|
if to_keep != current_combos:
|
||||||
await self.set_combo_list(to_keep)
|
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]):
|
-> (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.
|
and emoji ID.
|
||||||
|
|
||||||
:param int message_id:
|
:param message_id:
|
||||||
:param str or int emoji:
|
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if not await self.is_registered(message_id):
|
if not await self.is_registered(message_id):
|
||||||
@ -169,8 +165,8 @@ class ReactRestrict:
|
|||||||
raise LookupError("No role found.")
|
raise LookupError("No role found.")
|
||||||
|
|
||||||
return role
|
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]:
|
-> Union[discord.Message, None]:
|
||||||
"""
|
"""
|
||||||
Tries to find a message by ID in the current guild context.
|
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)
|
return await channel.get_message(message_id)
|
||||||
except discord.NotFound:
|
except discord.NotFound:
|
||||||
pass
|
pass
|
||||||
except AttributeError: # VoiceChannel object has no attribute 'get_message'
|
except AttributeError: # VoiceChannel object has no attribute 'get_message'
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return None
|
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]:
|
-> Union[discord.Message, None]:
|
||||||
"""
|
"""
|
||||||
Tries to find a message by ID in the current guild context.
|
Tries to find a message by ID in the current guild context.
|
||||||
@ -199,12 +195,10 @@ class ReactRestrict:
|
|||||||
return await channel.get_message(message_id)
|
return await channel.get_message(message_id)
|
||||||
except discord.NotFound:
|
except discord.NotFound:
|
||||||
pass
|
pass
|
||||||
except AttributeError: # VoiceChannel object has no attribute 'get_message'
|
except AttributeError: # VoiceChannel object has no attribute 'get_message'
|
||||||
pass
|
pass
|
||||||
except discord.Forbidden: # No access to channel, skip
|
except discord.Forbidden: # No access to channel, skip
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -214,7 +208,7 @@ class ReactRestrict:
|
|||||||
Base command for this cog. Check help for the commands list.
|
Base command for this cog. Check help for the commands list.
|
||||||
"""
|
"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@reactrestrict.command()
|
@reactrestrict.command()
|
||||||
async def add(self, ctx: commands.Context, message_id: int, *, role: discord.Role):
|
async def add(self, ctx: commands.Context, message_id: int, *, role: discord.Role):
|
||||||
@ -228,18 +222,18 @@ class ReactRestrict:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# try:
|
# try:
|
||||||
# emoji, actual_emoji = await self._wait_for_emoji(ctx)
|
# emoji, actual_emoji = await self._wait_for_emoji(ctx)
|
||||||
# except asyncio.TimeoutError:
|
# except asyncio.TimeoutError:
|
||||||
# await ctx.send("You didn't respond in time, please redo this command.")
|
# await ctx.send("You didn't respond in time, please redo this command.")
|
||||||
# return
|
# return
|
||||||
|
#
|
||||||
# try:
|
# try:
|
||||||
# await message.add_reaction(actual_emoji)
|
# await message.add_reaction(actual_emoji)
|
||||||
# except discord.HTTPException:
|
# except discord.HTTPException:
|
||||||
# await ctx.send("I can't add that emoji because I'm not in the guild that"
|
# await ctx.send("I can't add that emoji because I'm not in the guild that"
|
||||||
# " owns it.")
|
# " owns it.")
|
||||||
# return
|
# return
|
||||||
|
#
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
await self.add_reactrestrict(message_id, role)
|
await self.add_reactrestrict(message_id, role)
|
||||||
|
|
||||||
@ -251,10 +245,10 @@ class ReactRestrict:
|
|||||||
Removes role associated with a given reaction.
|
Removes role associated with a given reaction.
|
||||||
"""
|
"""
|
||||||
# try:
|
# try:
|
||||||
# emoji, actual_emoji = await self._wait_for_emoji(ctx)
|
# emoji, actual_emoji = await self._wait_for_emoji(ctx)
|
||||||
# except asyncio.TimeoutError:
|
# except asyncio.TimeoutError:
|
||||||
# await ctx.send("You didn't respond in time, please redo this command.")
|
# await ctx.send("You didn't respond in time, please redo this command.")
|
||||||
# return
|
# return
|
||||||
|
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
await self.remove_react(message_id, role)
|
await self.remove_react(message_id, role)
|
||||||
@ -298,50 +292,50 @@ class ReactRestrict:
|
|||||||
for apprrole in roles:
|
for apprrole in roles:
|
||||||
if apprrole in member.roles:
|
if apprrole in member.roles:
|
||||||
return
|
return
|
||||||
|
|
||||||
message = await self._get_message_from_channel(channel_id, message_id)
|
message = await self._get_message_from_channel(channel_id, message_id)
|
||||||
await message.remove_reaction(emoji, member)
|
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,
|
# async def on_raw_reaction_remove(self, emoji: discord.PartialReactionEmoji,
|
||||||
# message_id: int, channel_id: int, user_id: int):
|
# message_id: int, channel_id: int, user_id: int):
|
||||||
# """
|
# """
|
||||||
# Event handler for long term reaction watching.
|
# Event handler for long term reaction watching.
|
||||||
|
#
|
||||||
# :param discord.PartialReactionEmoji emoji:
|
# :param discord.PartialReactionEmoji emoji:
|
||||||
# :param int message_id:
|
# :param int message_id:
|
||||||
# :param int channel_id:
|
# :param int channel_id:
|
||||||
# :param int user_id:
|
# :param int user_id:
|
||||||
# :return:
|
# :return:
|
||||||
# """
|
# """
|
||||||
# if emoji.is_custom_emoji():
|
# if emoji.is_custom_emoji():
|
||||||
# emoji_id = emoji.id
|
# emoji_id = emoji.id
|
||||||
# else:
|
# else:
|
||||||
# emoji_id = emoji.name
|
# emoji_id = emoji.name
|
||||||
|
#
|
||||||
# has_reactrestrict, combos = await self.has_reactrestrict_combo(message_id, emoji_id)
|
# has_reactrestrict, combos = await self.has_reactrestrict_combo(message_id, emoji_id)
|
||||||
|
#
|
||||||
# if not has_reactrestrict:
|
# if not has_reactrestrict:
|
||||||
# return
|
# return
|
||||||
|
#
|
||||||
# try:
|
# try:
|
||||||
# member = self._get_member(channel_id, user_id)
|
# member = self._get_member(channel_id, user_id)
|
||||||
# except LookupError:
|
# except LookupError:
|
||||||
# return
|
# return
|
||||||
|
#
|
||||||
# if member.bot:
|
# if member.bot:
|
||||||
# return
|
# return
|
||||||
|
#
|
||||||
# try:
|
# try:
|
||||||
# roles = [self._get_role(member.guild, c.role_id) for c in combos]
|
# roles = [self._get_role(member.guild, c.role_id) for c in combos]
|
||||||
# except LookupError:
|
# except LookupError:
|
||||||
# return
|
# return
|
||||||
|
#
|
||||||
# try:
|
# try:
|
||||||
# await member.remove_roles(*roles)
|
# await member.remove_roles(*roles)
|
||||||
# except discord.Forbidden:
|
# except discord.Forbidden:
|
||||||
# pass
|
# pass
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
import html2text
|
import html2text
|
||||||
|
|
||||||
from redbot.core import Config
|
from redbot.core import Config, commands
|
||||||
from redbot.core.bot import Red
|
from redbot.core.bot import Red
|
||||||
from redbot.core.utils.chat_formatting import pagify
|
from redbot.core.utils.chat_formatting import pagify
|
||||||
|
|
||||||
@ -32,8 +32,7 @@ class SayUrl:
|
|||||||
"""
|
"""
|
||||||
Converts a URL to something readable
|
Converts a URL to something readable
|
||||||
|
|
||||||
:param url:
|
Works better on smaller websites
|
||||||
:return:
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
h = html2text.HTML2Text()
|
h = html2text.HTML2Text()
|
||||||
|
@ -3,7 +3,7 @@ import asyncio
|
|||||||
import discord
|
import discord
|
||||||
|
|
||||||
|
|
||||||
from redbot.core import Config
|
from redbot.core import Config, commands
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ class Werewolf:
|
|||||||
Base command for this cog. Check help for the commands list.
|
Base command for this cog. Check help for the commands list.
|
||||||
"""
|
"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@ww.command()
|
@ww.command()
|
||||||
async def new(self, ctx, game_code):
|
async def new(self, ctx, game_code):
|
||||||
|
@ -45,7 +45,7 @@ class StealEmoji:
|
|||||||
Base command for this cog. Check help for the commands list.
|
Base command for this cog. Check help for the commands list.
|
||||||
"""
|
"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@stealemoji.command(name="collect")
|
@stealemoji.command(name="collect")
|
||||||
async def se_collect(self, ctx):
|
async def se_collect(self, ctx):
|
||||||
@ -58,7 +58,7 @@ class StealEmoji:
|
|||||||
async def se_bank(self, ctx):
|
async def se_bank(self, ctx):
|
||||||
"""Add current server as emoji bank"""
|
"""Add current server as emoji bank"""
|
||||||
await ctx.send("This will upload custom emojis to this server\n"
|
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):
|
def check(m):
|
||||||
return m.content.upper() in ["Y", "YES", "N", "NO"] and m.channel == ctx.channel and m.author == ctx.author
|
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):
|
async def timerole(self, ctx):
|
||||||
"""Adjust timerole settings"""
|
"""Adjust timerole settings"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@timerole.command()
|
@timerole.command()
|
||||||
async def addrole(self, ctx: commands.Context, role: discord.Role, days: int, *requiredroles: discord.Role):
|
async def addrole(self, ctx: commands.Context, role: discord.Role, days: int, *requiredroles: discord.Role):
|
||||||
|
5
tts/__init__.py
Normal file
5
tts/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from .tts import TTS
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(TTS(bot))
|
22
tts/info..json
Normal file
22
tts/info..json
Normal file
@ -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"
|
||||||
|
]
|
||||||
|
}
|
34
tts/tts.py
Normal file
34
tts/tts.py
Normal file
@ -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
|
digits += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
idx = int(built)
|
idx = int(built)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -146,7 +144,6 @@ async def parse_code(code, game):
|
|||||||
|
|
||||||
built = ""
|
built = ""
|
||||||
|
|
||||||
|
|
||||||
return decode
|
return decode
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,4 +30,4 @@ class Player:
|
|||||||
try:
|
try:
|
||||||
await self.member.send(message) # Lets do embeds later
|
await self.member.send(message) # Lets do embeds later
|
||||||
except discord.Forbidden:
|
except discord.Forbidden:
|
||||||
await self.role.game.village_channel.send("Couldn't DM {}, uh oh".format(self.mention))
|
await self.role.game.village_channel.send("Couldn't DM {}, uh oh".format(self.mention))
|
||||||
|
@ -16,7 +16,6 @@ class Seer(Role):
|
|||||||
description = "A mystic in search of answers in a chaotic town.\n" \
|
description = "A mystic in search of answers in a chaotic town.\n" \
|
||||||
"Calls upon the cosmos to discern those of Lycan blood"
|
"Calls upon the cosmos to discern those of Lycan blood"
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, game):
|
def __init__(self, game):
|
||||||
super().__init__(game)
|
super().__init__(game)
|
||||||
# self.game = game
|
# self.game = game
|
||||||
|
@ -53,7 +53,7 @@ class Werewolf:
|
|||||||
Base command to adjust settings. Check help for command list.
|
Base command to adjust settings. Check help for command list.
|
||||||
"""
|
"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@wwset.command(name="list")
|
@wwset.command(name="list")
|
||||||
@ -136,7 +136,7 @@ class Werewolf:
|
|||||||
Base command for this cog. Check help for the commands list.
|
Base command for this cog. Check help for the commands list.
|
||||||
"""
|
"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
pass
|
||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@ww.command(name="new")
|
@ww.command(name="new")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user