Compare commits
1 Commits
master
...
flag_devel
Author | SHA1 | Date | |
---|---|---|---|
![]() |
af10493e81 |
@ -3,7 +3,6 @@ import logging
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from discord.ext.commands import RoleConverter, Greedy, CommandError, ArgumentParsingError
|
|
||||||
from discord.ext.commands.view import StringView
|
from discord.ext.commands.view import StringView
|
||||||
from redbot.core import Config, checks, commands
|
from redbot.core import Config, checks, commands
|
||||||
from redbot.core.bot import Red
|
from redbot.core.bot import Red
|
||||||
@ -14,38 +13,15 @@ log = logging.getLogger("red.fox_v3.ccrole")
|
|||||||
|
|
||||||
|
|
||||||
async def _get_roles_from_content(ctx, content):
|
async def _get_roles_from_content(ctx, content):
|
||||||
# greedy = Greedy[RoleConverter]
|
content_list = content.split(",")
|
||||||
view = StringView(content)
|
try:
|
||||||
rc = RoleConverter()
|
role_list = [
|
||||||
|
discord.utils.get(ctx.guild.roles, name=role.strip(" ")).id for role in content_list
|
||||||
# "Borrowed" from discord.ext.commands.Command._transform_greedy_pos
|
]
|
||||||
result = []
|
except (discord.HTTPException, AttributeError): # None.id is attribute error
|
||||||
while not view.eof:
|
return None
|
||||||
# for use with a manual undo
|
else:
|
||||||
previous = view.index
|
return role_list
|
||||||
|
|
||||||
view.skip_ws()
|
|
||||||
try:
|
|
||||||
argument = view.get_quoted_word()
|
|
||||||
value = await rc.convert(ctx, argument)
|
|
||||||
except (CommandError, ArgumentParsingError):
|
|
||||||
view.index = previous
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
result.append(value)
|
|
||||||
|
|
||||||
return [r.id for r in result]
|
|
||||||
|
|
||||||
# Old method
|
|
||||||
# content_list = content.split(",")
|
|
||||||
# try:
|
|
||||||
# role_list = [
|
|
||||||
# discord.utils.get(ctx.guild.roles, name=role.strip(" ")).id for role in content_list
|
|
||||||
# ]
|
|
||||||
# except (discord.HTTPException, AttributeError): # None.id is attribute error
|
|
||||||
# return None
|
|
||||||
# else:
|
|
||||||
# return role_list
|
|
||||||
|
|
||||||
|
|
||||||
class CCRole(commands.Cog):
|
class CCRole(commands.Cog):
|
||||||
@ -108,7 +84,7 @@ class CCRole(commands.Cog):
|
|||||||
|
|
||||||
# Roles to add
|
# Roles to add
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"What roles should it add?\n"
|
"What roles should it add? (Must be **comma separated**)\n"
|
||||||
"Say `None` to skip adding roles"
|
"Say `None` to skip adding roles"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -130,7 +106,7 @@ class CCRole(commands.Cog):
|
|||||||
|
|
||||||
# Roles to remove
|
# Roles to remove
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"What roles should it remove?\n"
|
"What roles should it remove? (Must be comma separated)\n"
|
||||||
"Say `None` to skip removing roles"
|
"Say `None` to skip removing roles"
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
@ -148,7 +124,7 @@ class CCRole(commands.Cog):
|
|||||||
|
|
||||||
# Roles to use
|
# Roles to use
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"What roles are allowed to use this command?\n"
|
"What roles are allowed to use this command? (Must be comma separated)\n"
|
||||||
"Say `None` to allow all roles"
|
"Say `None` to allow all roles"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -74,18 +74,12 @@ If you get an error at this step, stop and skip to one of the manual methods bel
|
|||||||
|
|
||||||
#### Step 2: Install additional dependencies
|
#### Step 2: Install additional dependencies
|
||||||
|
|
||||||
Here you need to decide which training models you want to have available to you.
|
Assuming the previous commands had no error, you can now use `pipinstall` to add the remaining dependencies.
|
||||||
|
|
||||||
Shutdown the bot and run any number of these in the console:
|
NOTE: This method is not the intended use case for `pipinstall` and may stop working in the future.
|
||||||
|
|
||||||
```
|
```
|
||||||
python -m spacy download en_core_web_sm # ~15 MB
|
[p]pipinstall --no-deps chatterbot>=1.1
|
||||||
|
|
||||||
python -m spacy download en_core_web_md # ~50 MB
|
|
||||||
|
|
||||||
python -m spacy download en_core_web_lg # ~750 MB (CPU Optimized)
|
|
||||||
|
|
||||||
python -m spacy download en_core_web_trf # ~500 MB (GPU Optimized)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Step 3: Load the cog and get started
|
#### Step 3: Load the cog and get started
|
||||||
@ -95,14 +89,62 @@ python -m spacy download en_core_web_trf # ~500 MB (GPU Optimized)
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Windows - Manually
|
### Windows - Manually
|
||||||
Deprecated
|
#### Step 1: Built-in Downloader
|
||||||
|
|
||||||
|
You need to get a copy of the requirements.txt provided with chatter, I recommend this method.
|
||||||
|
|
||||||
|
```
|
||||||
|
[p]repo add Fox https://github.com/bobloy/Fox-V3
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 2: Install Requirements
|
||||||
|
|
||||||
|
Make sure you have your virtual environment that you installed Red on activated before starting this step. See the Red Docs for details on how.
|
||||||
|
|
||||||
|
In a terminal running as an admin, navigate to the directory containing this repo.
|
||||||
|
|
||||||
|
I've used my install directory as an example.
|
||||||
|
|
||||||
|
```
|
||||||
|
cd C:\Users\Bobloy\AppData\Local\Red-DiscordBot\Red-DiscordBot\data\bobbot\cogs\RepoManager\repos\Fox\chatter
|
||||||
|
pip install -r requirements.txt
|
||||||
|
pip install --no-deps "chatterbot>=1.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 3: Load Chatter
|
||||||
|
|
||||||
|
```
|
||||||
|
[p]repo add Fox https://github.com/bobloy/Fox-V3 # If you didn't already do this in step 1
|
||||||
|
[p]cog install Fox chatter
|
||||||
|
[p]load chatter
|
||||||
|
```
|
||||||
|
|
||||||
### Linux - Manually
|
### Linux - Manually
|
||||||
Deprecated
|
|
||||||
|
#### Step 1: Built-in Downloader
|
||||||
|
|
||||||
|
```
|
||||||
|
[p]repo add Fox https://github.com/bobloy/Fox-V3
|
||||||
|
[p]cog install Fox chatter
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 2: Install Requirements
|
||||||
|
|
||||||
|
In your console with your virtual environment activated:
|
||||||
|
|
||||||
|
```
|
||||||
|
pip install --no-deps "chatterbot>=1.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Load Chatter
|
||||||
|
|
||||||
|
```
|
||||||
|
[p]load chatter
|
||||||
|
```
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
Chatter works out the box without any training by learning as it goes,
|
Chatter works out the the box without any training by learning as it goes,
|
||||||
but will have very poor and repetitive responses at first.
|
but will have very poor and repetitive responses at first.
|
||||||
|
|
||||||
Initial training is recommended to speed up its learning.
|
Initial training is recommended to speed up its learning.
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
from .chat import Chatter
|
from .chat import Chatter
|
||||||
|
|
||||||
|
|
||||||
async def setup(bot):
|
def setup(bot):
|
||||||
cog = Chatter(bot)
|
bot.add_cog(Chatter(bot))
|
||||||
await cog.initialize()
|
|
||||||
bot.add_cog(cog)
|
|
||||||
|
|
||||||
|
|
||||||
# __all__ = (
|
# __all__ = (
|
||||||
|
@ -19,7 +19,6 @@ from redbot.core.utils.predicates import MessagePredicate
|
|||||||
|
|
||||||
from chatter.trainers import MovieTrainer, TwitterCorpusTrainer, UbuntuCorpusTrainer2
|
from chatter.trainers import MovieTrainer, TwitterCorpusTrainer, UbuntuCorpusTrainer2
|
||||||
|
|
||||||
chatterbot_log = logging.getLogger("red.fox_v3.chatterbot")
|
|
||||||
log = logging.getLogger("red.fox_v3.chatter")
|
log = logging.getLogger("red.fox_v3.chatter")
|
||||||
|
|
||||||
|
|
||||||
@ -30,12 +29,6 @@ def my_local_get_prefix(prefixes, content):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class ENG_TRF:
|
|
||||||
ISO_639_1 = "en_core_web_trf"
|
|
||||||
ISO_639 = "eng"
|
|
||||||
ENGLISH_NAME = "English"
|
|
||||||
|
|
||||||
|
|
||||||
class ENG_LG:
|
class ENG_LG:
|
||||||
ISO_639_1 = "en_core_web_lg"
|
ISO_639_1 = "en_core_web_lg"
|
||||||
ISO_639 = "eng"
|
ISO_639 = "eng"
|
||||||
@ -59,15 +52,12 @@ class Chatter(Cog):
|
|||||||
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
|
||||||
"""
|
"""
|
||||||
|
|
||||||
models = [ENG_SM, ENG_MD, ENG_LG, ENG_TRF]
|
|
||||||
algos = [SpacySimilarity, JaccardSimilarity, LevenshteinDistance]
|
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.config = Config.get_conf(self, identifier=6710497116116101114)
|
self.config = Config.get_conf(self, identifier=6710497116116101114)
|
||||||
default_global = {"learning": True, "model_number": 0, "algo_number": 0, "threshold": 0.90}
|
default_global = {"learning": True}
|
||||||
self.default_guild = {
|
default_guild = {
|
||||||
"whitelist": None,
|
"whitelist": None,
|
||||||
"days": 1,
|
"days": 1,
|
||||||
"convo_delta": 15,
|
"convo_delta": 15,
|
||||||
@ -80,16 +70,16 @@ class Chatter(Cog):
|
|||||||
# TODO: Move training_model and similarity_algo to config
|
# TODO: Move training_model and similarity_algo to config
|
||||||
# TODO: Add an option to see current settings
|
# TODO: Add an option to see current settings
|
||||||
|
|
||||||
self.tagger_language = ENG_SM
|
self.tagger_language = ENG_MD
|
||||||
self.similarity_algo = SpacySimilarity
|
self.similarity_algo = SpacySimilarity
|
||||||
self.similarity_threshold = 0.90
|
self.similarity_threshold = 0.90
|
||||||
self.chatbot = None
|
self.chatbot = self._create_chatbot()
|
||||||
# self.chatbot.set_trainer(ListTrainer)
|
# self.chatbot.set_trainer(ListTrainer)
|
||||||
|
|
||||||
# self.trainer = ListTrainer(self.chatbot)
|
# self.trainer = ListTrainer(self.chatbot)
|
||||||
|
|
||||||
self.config.register_global(**default_global)
|
self.config.register_global(**default_global)
|
||||||
self.config.register_guild(**self.default_guild)
|
self.config.register_guild(**default_guild)
|
||||||
|
|
||||||
self.loop = asyncio.get_event_loop()
|
self.loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
@ -102,18 +92,6 @@ class Chatter(Cog):
|
|||||||
"""Nothing to delete"""
|
"""Nothing to delete"""
|
||||||
return
|
return
|
||||||
|
|
||||||
async def initialize(self):
|
|
||||||
all_config = dict(self.config.defaults["GLOBAL"])
|
|
||||||
all_config.update(await self.config.all())
|
|
||||||
model_number = all_config["model_number"]
|
|
||||||
algo_number = all_config["algo_number"]
|
|
||||||
threshold = all_config["threshold"]
|
|
||||||
|
|
||||||
self.tagger_language = self.models[model_number]
|
|
||||||
self.similarity_algo = self.algos[algo_number]
|
|
||||||
self.similarity_threshold = threshold
|
|
||||||
self.chatbot = self._create_chatbot()
|
|
||||||
|
|
||||||
def _create_chatbot(self):
|
def _create_chatbot(self):
|
||||||
|
|
||||||
return ChatBot(
|
return ChatBot(
|
||||||
@ -126,7 +104,7 @@ class Chatter(Cog):
|
|||||||
logic_adapters=["chatterbot.logic.BestMatch"],
|
logic_adapters=["chatterbot.logic.BestMatch"],
|
||||||
maximum_similarity_threshold=self.similarity_threshold,
|
maximum_similarity_threshold=self.similarity_threshold,
|
||||||
tagger_language=self.tagger_language,
|
tagger_language=self.tagger_language,
|
||||||
logger=chatterbot_log,
|
logger=log,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _get_conversation(self, ctx, in_channels: List[discord.TextChannel]):
|
async def _get_conversation(self, ctx, in_channels: List[discord.TextChannel]):
|
||||||
@ -350,12 +328,15 @@ class Chatter(Cog):
|
|||||||
self, ctx: commands.Context, algo_number: int, threshold: float = None
|
self, ctx: commands.Context, algo_number: int, threshold: float = None
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Switch the active logic algorithm to one of the three. Default is Spacy
|
Switch the active logic algorithm to one of the three. Default after reload is Spacy
|
||||||
|
|
||||||
0: Spacy
|
0: Spacy
|
||||||
1: Jaccard
|
1: Jaccard
|
||||||
2: Levenshtein
|
2: Levenshtein
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
algos = [SpacySimilarity, JaccardSimilarity, LevenshteinDistance]
|
||||||
|
|
||||||
if algo_number < 0 or algo_number > 2:
|
if algo_number < 0 or algo_number > 2:
|
||||||
await ctx.send_help()
|
await ctx.send_help()
|
||||||
return
|
return
|
||||||
@ -368,11 +349,8 @@ class Chatter(Cog):
|
|||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.similarity_threshold = threshold
|
self.similarity_threshold = threshold
|
||||||
await self.config.threshold.set(self.similarity_threshold)
|
|
||||||
|
|
||||||
self.similarity_algo = self.algos[algo_number]
|
|
||||||
await self.config.algo_number.set(algo_number)
|
|
||||||
|
|
||||||
|
self.similarity_algo = algos[algo_number]
|
||||||
async with ctx.typing():
|
async with ctx.typing():
|
||||||
self.chatbot = self._create_chatbot()
|
self.chatbot = self._create_chatbot()
|
||||||
|
|
||||||
@ -382,18 +360,20 @@ class Chatter(Cog):
|
|||||||
@chatter.command(name="model")
|
@chatter.command(name="model")
|
||||||
async def chatter_model(self, ctx: commands.Context, model_number: int):
|
async def chatter_model(self, ctx: commands.Context, model_number: int):
|
||||||
"""
|
"""
|
||||||
Switch the active model to one of the three. Default is Small
|
Switch the active model to one of the three. Default after reload is Medium
|
||||||
|
|
||||||
0: Small
|
0: Small
|
||||||
1: Medium (Requires additional setup)
|
1: Medium
|
||||||
2: Large (Requires additional setup)
|
2: Large (Requires additional setup)
|
||||||
3. Accurate (Requires additional setup)
|
|
||||||
"""
|
"""
|
||||||
if model_number < 0 or model_number > 3:
|
|
||||||
|
models = [ENG_SM, ENG_MD, ENG_LG]
|
||||||
|
|
||||||
|
if model_number < 0 or model_number > 2:
|
||||||
await ctx.send_help()
|
await ctx.send_help()
|
||||||
return
|
return
|
||||||
|
|
||||||
if model_number >= 0:
|
if model_number == 2:
|
||||||
await ctx.maybe_send_embed(
|
await ctx.maybe_send_embed(
|
||||||
"Additional requirements needed. See guide before continuing.\n" "Continue?"
|
"Additional requirements needed. See guide before continuing.\n" "Continue?"
|
||||||
)
|
)
|
||||||
@ -406,8 +386,7 @@ class Chatter(Cog):
|
|||||||
if not pred.result:
|
if not pred.result:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.tagger_language = self.models[model_number]
|
self.tagger_language = models[model_number]
|
||||||
await self.config.model_number.set(model_number)
|
|
||||||
async with ctx.typing():
|
async with ctx.typing():
|
||||||
self.chatbot = self._create_chatbot()
|
self.chatbot = self._create_chatbot()
|
||||||
|
|
||||||
@ -416,13 +395,7 @@ class Chatter(Cog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@commands.is_owner()
|
@commands.is_owner()
|
||||||
@chatter.group(name="trainset")
|
@chatter.command(name="minutes")
|
||||||
async def chatter_trainset(self, ctx: commands.Context):
|
|
||||||
"""Commands for configuring training"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@commands.is_owner()
|
|
||||||
@chatter_trainset.command(name="minutes")
|
|
||||||
async def minutes(self, ctx: commands.Context, minutes: int):
|
async def minutes(self, ctx: commands.Context, minutes: int):
|
||||||
"""
|
"""
|
||||||
Sets the number of minutes the bot will consider a break in a conversation during training
|
Sets the number of minutes the bot will consider a break in a conversation during training
|
||||||
@ -438,7 +411,7 @@ class Chatter(Cog):
|
|||||||
await ctx.tick()
|
await ctx.tick()
|
||||||
|
|
||||||
@commands.is_owner()
|
@commands.is_owner()
|
||||||
@chatter_trainset.command(name="age")
|
@chatter.command(name="age")
|
||||||
async def age(self, ctx: commands.Context, days: int):
|
async def age(self, ctx: commands.Context, days: int):
|
||||||
"""
|
"""
|
||||||
Sets the number of days to look back
|
Sets the number of days to look back
|
||||||
@ -657,7 +630,7 @@ class Chatter(Cog):
|
|||||||
|
|
||||||
guild: discord.Guild = getattr(message, "guild", None)
|
guild: discord.Guild = getattr(message, "guild", None)
|
||||||
|
|
||||||
if guild is None or await self.bot.cog_disabled_in_guild(self, guild):
|
if await self.bot.cog_disabled_in_guild(self, guild):
|
||||||
return
|
return
|
||||||
|
|
||||||
ctx: commands.Context = await self.bot.get_context(message)
|
ctx: commands.Context = await self.bot.get_context(message)
|
||||||
@ -732,9 +705,7 @@ class Chatter(Cog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
replying = None
|
replying = None
|
||||||
if (
|
if self._guild_cache[guild.id]["reply"]:
|
||||||
"reply" not in self._guild_cache[guild.id] and self.default_guild["reply"]
|
|
||||||
) or self._guild_cache[guild.id]["reply"]:
|
|
||||||
if message != ctx.channel.last_message:
|
if message != ctx.channel.last_message:
|
||||||
replying = message
|
replying = message
|
||||||
|
|
||||||
|
@ -7,10 +7,18 @@
|
|||||||
"hidden": false,
|
"hidden": false,
|
||||||
"install_msg": "Thank you for installing Chatter! Please make sure you check the install instructions at https://github.com/bobloy/Fox-V3/blob/master/chatter/README.md\nAfter that, get started ith `[p]load chatter` and `[p]help Chatter`",
|
"install_msg": "Thank you for installing Chatter! Please make sure you check the install instructions at https://github.com/bobloy/Fox-V3/blob/master/chatter/README.md\nAfter that, get started ith `[p]load chatter` and `[p]help Chatter`",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"git+git://github.com/bobloy/ChatterBot@fox#egg=ChatterBot>=1.1.0.dev4",
|
"git+git://github.com/gunthercox/chatterbot-corpus@master#egg=chatterbot_corpus",
|
||||||
"kaggle",
|
"mathparse>=0.1,<0.2",
|
||||||
"https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.1.0/en_core_web_sm-3.1.0.tar.gz#egg=en_core_web_sm",
|
"nltk>=3.2,<4.0",
|
||||||
"https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.1.0/en_core_web_md-3.1.0.tar.gz#egg=en_core_web_md"
|
"pint>=0.8.1",
|
||||||
|
"python-dateutil>=2.8,<2.9",
|
||||||
|
"pyyaml>=5.3,<5.4",
|
||||||
|
"sqlalchemy>=1.3,<1.4",
|
||||||
|
"pytz",
|
||||||
|
"https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.3.1/en_core_web_sm-2.3.1.tar.gz#egg=en_core_web_sm",
|
||||||
|
"https://github.com/explosion/spacy-models/releases/download/en_core_web_md-2.3.1/en_core_web_md-2.3.1.tar.gz#egg=en_core_web_md",
|
||||||
|
"spacy>=2.3,<2.4",
|
||||||
|
"kaggle"
|
||||||
],
|
],
|
||||||
"short": "Local Chatbot run on machine learning",
|
"short": "Local Chatbot run on machine learning",
|
||||||
"end_user_data_statement": "This cog only stores anonymous conversations data; no End User Data is stored.",
|
"end_user_data_statement": "This cog only stores anonymous conversations data; no End User Data is stored.",
|
||||||
|
12
chatter/requirements.txt
Normal file
12
chatter/requirements.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
git+git://github.com/gunthercox/chatterbot-corpus@master#egg=chatterbot_corpus
|
||||||
|
mathparse>=0.1,<0.2
|
||||||
|
nltk>=3.2,<4.0
|
||||||
|
pint>=0.8.1
|
||||||
|
python-dateutil>=2.8,<2.9
|
||||||
|
pyyaml>=5.3,<5.4
|
||||||
|
sqlalchemy>=1.3,<1.4
|
||||||
|
pytz
|
||||||
|
spacy>=2.3,<2.4
|
||||||
|
https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.3.1/en_core_web_sm-2.3.1.tar.gz#egg=en_core_web_sm
|
||||||
|
https://github.com/explosion/spacy-models/releases/download/en_core_web_md-2.3.1/en_core_web_md-2.3.1.tar.gz#egg=en_core_web_md
|
||||||
|
# https://github.com/explosion/spacy-models/releases/download/en_core_web_lg-2.3.1/en_core_web_lg-2.3.1.tar.gz#egg=en_core_web_lg
|
@ -5,7 +5,7 @@ class MyDumbSQLStorageAdapter(SQLStorageAdapter):
|
|||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(SQLStorageAdapter, self).__init__(**kwargs)
|
super(SQLStorageAdapter, self).__init__(**kwargs)
|
||||||
|
|
||||||
from sqlalchemy import create_engine, inspect
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
self.database_uri = kwargs.get("database_uri", False)
|
self.database_uri = kwargs.get("database_uri", False)
|
||||||
@ -18,7 +18,9 @@ class MyDumbSQLStorageAdapter(SQLStorageAdapter):
|
|||||||
if not self.database_uri:
|
if not self.database_uri:
|
||||||
self.database_uri = "sqlite:///db.sqlite3"
|
self.database_uri = "sqlite:///db.sqlite3"
|
||||||
|
|
||||||
self.engine = create_engine(self.database_uri, connect_args={"check_same_thread": False})
|
self.engine = create_engine(
|
||||||
|
self.database_uri, convert_unicode=True, connect_args={"check_same_thread": False}
|
||||||
|
)
|
||||||
|
|
||||||
if self.database_uri.startswith("sqlite://"):
|
if self.database_uri.startswith("sqlite://"):
|
||||||
from sqlalchemy.engine import Engine
|
from sqlalchemy.engine import Engine
|
||||||
@ -29,7 +31,7 @@ class MyDumbSQLStorageAdapter(SQLStorageAdapter):
|
|||||||
dbapi_connection.execute("PRAGMA journal_mode=WAL")
|
dbapi_connection.execute("PRAGMA journal_mode=WAL")
|
||||||
dbapi_connection.execute("PRAGMA synchronous=NORMAL")
|
dbapi_connection.execute("PRAGMA synchronous=NORMAL")
|
||||||
|
|
||||||
if not inspect(self.engine).has_table("Statement"):
|
if not self.engine.dialect.has_table(self.engine, "Statement"):
|
||||||
self.create_database()
|
self.create_database()
|
||||||
|
|
||||||
self.Session = sessionmaker(bind=self.engine, expire_on_commit=True)
|
self.Session = sessionmaker(bind=self.engine, expire_on_commit=True)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
@ -14,8 +13,6 @@ from redbot.core import Config, commands
|
|||||||
from redbot.core.bot import Red
|
from redbot.core.bot import Red
|
||||||
from redbot.core.data_manager import bundled_data_path, cog_data_path
|
from redbot.core.data_manager import bundled_data_path, cog_data_path
|
||||||
|
|
||||||
log = logging.getLogger("red.fox_v3.conquest")
|
|
||||||
|
|
||||||
|
|
||||||
class Conquest(commands.Cog):
|
class Conquest(commands.Cog):
|
||||||
"""
|
"""
|
||||||
@ -56,20 +53,14 @@ class Conquest(commands.Cog):
|
|||||||
self.current_map = await self.config.current_map()
|
self.current_map = await self.config.current_map()
|
||||||
|
|
||||||
if self.current_map:
|
if self.current_map:
|
||||||
if not await self.current_map_load():
|
await self.current_map_load()
|
||||||
await self.config.current_map.clear()
|
|
||||||
|
|
||||||
async def current_map_load(self):
|
async def current_map_load(self):
|
||||||
map_data_path = self.asset_path / self.current_map / "data.json"
|
map_data_path = self.asset_path / self.current_map / "data.json"
|
||||||
if not map_data_path.exists():
|
|
||||||
log.warning(f"{map_data_path} does not exist. Clearing current map")
|
|
||||||
return False
|
|
||||||
|
|
||||||
with map_data_path.open() as mapdata:
|
with map_data_path.open() as mapdata:
|
||||||
self.map_data: dict = json.load(mapdata)
|
self.map_data: dict = json.load(mapdata)
|
||||||
self.ext = self.map_data["extension"]
|
self.ext = self.map_data["extension"]
|
||||||
self.ext_format = "JPEG" if self.ext.upper() == "JPG" else self.ext.upper()
|
self.ext_format = "JPEG" if self.ext.upper() == "JPG" else self.ext.upper()
|
||||||
return True
|
|
||||||
|
|
||||||
@commands.group()
|
@commands.group()
|
||||||
async def conquest(self, ctx: commands.Context):
|
async def conquest(self, ctx: commands.Context):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"maps": [
|
"maps": [
|
||||||
"simple",
|
"simple_blank_map",
|
||||||
"ck2",
|
"test",
|
||||||
"HoI"
|
"test2"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -441,7 +441,6 @@ class FIFO(commands.Cog):
|
|||||||
self.scheduler.print_jobs(out=cp)
|
self.scheduler.print_jobs(out=cp)
|
||||||
|
|
||||||
out = cp.string
|
out = cp.string
|
||||||
out=out.replace("*","\*")
|
|
||||||
|
|
||||||
if out:
|
if out:
|
||||||
if len(out) > 2000:
|
if len(out) > 2000:
|
||||||
|
@ -90,7 +90,6 @@ things_for_fakemessage_to_steal = [
|
|||||||
"content",
|
"content",
|
||||||
"nonce",
|
"nonce",
|
||||||
"reference",
|
"reference",
|
||||||
"_edited_timestamp" # New 7/23/21
|
|
||||||
]
|
]
|
||||||
|
|
||||||
things_fakemessage_sets_by_default = {
|
things_fakemessage_sets_by_default = {
|
||||||
@ -143,7 +142,7 @@ class FakeMessage(discord.Message):
|
|||||||
self._update(
|
self._update(
|
||||||
{
|
{
|
||||||
"mention_roles": self.raw_role_mentions,
|
"mention_roles": self.raw_role_mentions,
|
||||||
"mentions": [{"id": _id} for _id in self.raw_mentions],
|
"mentions": self.raw_mentions,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
51
flag/flag.py
51
flag/flag.py
@ -1,13 +1,17 @@
|
|||||||
|
import logging
|
||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
from typing import Literal
|
from typing import Literal, Optional
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
from redbot.cogs.mutes import Mutes
|
||||||
from redbot.core import Config, checks, commands
|
from redbot.core import Config, checks, commands
|
||||||
from redbot.core.bot import Red
|
from redbot.core.bot import Red
|
||||||
from redbot.core.commands import Cog
|
from redbot.core.commands import Cog
|
||||||
from redbot.core.utils import AsyncIter
|
from redbot.core.utils import AsyncIter
|
||||||
from redbot.core.utils.chat_formatting import pagify
|
from redbot.core.utils.chat_formatting import pagify
|
||||||
|
|
||||||
|
log = logging.getLogger("red.fox_v3.flag")
|
||||||
|
|
||||||
|
|
||||||
class Flag(Cog):
|
class Flag(Cog):
|
||||||
"""
|
"""
|
||||||
@ -19,7 +23,7 @@ class Flag(Cog):
|
|||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
|
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
|
||||||
default_global = {}
|
default_global = {}
|
||||||
default_guild = {"days": 31, "dm": True, "flags": {}}
|
default_guild = {"days": 31, "dm": True, "flags": {}, "mutethreshold": 0}
|
||||||
|
|
||||||
self.config.register_global(**default_global)
|
self.config.register_global(**default_global)
|
||||||
self.config.register_guild(**default_guild)
|
self.config.register_guild(**default_guild)
|
||||||
@ -78,6 +82,29 @@ class Flag(Cog):
|
|||||||
"DM-ing members when they get a flag is now set to **{}**".format(not dm)
|
"DM-ing members when they get a flag is now set to **{}**".format(not dm)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@checks.admin_or_permissions(manage_guild=True)
|
||||||
|
@flagset.command(name="mute")
|
||||||
|
async def flagset_mute(self, ctx: commands.Context, count: int):
|
||||||
|
"""
|
||||||
|
Sets the threshold for flags to mute the user.
|
||||||
|
|
||||||
|
Only works when the core mute cog is configured properly.
|
||||||
|
|
||||||
|
Set to zero to disable.
|
||||||
|
"""
|
||||||
|
if count < 0:
|
||||||
|
await ctx.send_help()
|
||||||
|
return
|
||||||
|
|
||||||
|
await self.config.guild(ctx.guild).mutethreshold.set(count)
|
||||||
|
|
||||||
|
if count:
|
||||||
|
await ctx.maybe_send_embed(
|
||||||
|
"Will now attempt to mute people after **{}** flags".format(count)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await ctx.maybe_send_embed("Muting disabled.")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _flag_template():
|
def _flag_template():
|
||||||
return {"reason": "", "expireyear": 0, "expiremonth": 0, "expireday": 0}
|
return {"reason": "", "expireyear": 0, "expiremonth": 0, "expireday": 0}
|
||||||
@ -91,7 +118,8 @@ class Flag(Cog):
|
|||||||
await self._check_flags(guild)
|
await self._check_flags(guild)
|
||||||
|
|
||||||
flag = self._flag_template()
|
flag = self._flag_template()
|
||||||
expire_date = date.today() + timedelta(days=await self.config.guild(guild).days())
|
mute_days = await self.config.guild(guild).days()
|
||||||
|
expire_date = date.today() + timedelta(mute_days)
|
||||||
|
|
||||||
flag["reason"] = reason
|
flag["reason"] = reason
|
||||||
flag["expireyear"] = expire_date.year
|
flag["expireyear"] = expire_date.year
|
||||||
@ -106,6 +134,12 @@ class Flag(Cog):
|
|||||||
if str(member.id) not in flags:
|
if str(member.id) not in flags:
|
||||||
flags[str(member.id)] = []
|
flags[str(member.id)] = []
|
||||||
flags[str(member.id)].append(flag)
|
flags[str(member.id)].append(flag)
|
||||||
|
flag_count = len(flags[str(member.id)])
|
||||||
|
|
||||||
|
mute_threshold = await self.config.guild(guild).mutethreshold()
|
||||||
|
if 0 < mute_threshold <= flag_count:
|
||||||
|
able_to_mute = await self._attempt_mute(ctx, member, mute_days)
|
||||||
|
log.debug(f"Mute attempt: {able_to_mute}")
|
||||||
|
|
||||||
outembed = await self._list_flags(member)
|
outembed = await self._list_flags(member)
|
||||||
|
|
||||||
@ -166,6 +200,17 @@ class Flag(Cog):
|
|||||||
for page in pagify(out):
|
for page in pagify(out):
|
||||||
await ctx.send(page)
|
await ctx.send(page)
|
||||||
|
|
||||||
|
async def _attempt_mute(self, ctx, member: discord.Member, days):
|
||||||
|
mutes: Optional[Mutes] = self.bot.get_cog("Mutes")
|
||||||
|
if mutes is None:
|
||||||
|
log.info("Mutes cog not loaded, cannot mute")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return await mutes.mute(ctx, member, f'{days} days [Flag] Exceeded mute threshold')
|
||||||
|
# return await mutes.mute_user(
|
||||||
|
# member.guild, author, member, until, "[Flag] Exceeded mute threshold"
|
||||||
|
# )
|
||||||
|
|
||||||
async def _list_flags(self, member: discord.Member):
|
async def _list_flags(self, member: discord.Member):
|
||||||
"""Returns a pretty embed of flags on a member"""
|
"""Returns a pretty embed of flags on a member"""
|
||||||
flags = await self.config.guild(member.guild).flags.get_raw(str(member.id), default=[])
|
flags = await self.config.guild(member.guild).flags.get_raw(str(member.id), default=[])
|
||||||
|
@ -28,12 +28,9 @@ async def get_channel_counts(category, guild):
|
|||||||
online_num = members - offline_num
|
online_num = members - offline_num
|
||||||
# Gets count of actual users
|
# Gets count of actual users
|
||||||
human_num = members - bot_num
|
human_num = members - bot_num
|
||||||
# count amount of premium subs/nitro subs.
|
|
||||||
boosters = guild.premium_subscription_count
|
|
||||||
return {
|
return {
|
||||||
"members": members,
|
"members": members,
|
||||||
"humans": human_num,
|
"humans": human_num,
|
||||||
"boosters": boosters,
|
|
||||||
"bots": bot_num,
|
"bots": bot_num,
|
||||||
"roles": roles_num,
|
"roles": roles_num,
|
||||||
"channels": channels_num,
|
"channels": channels_num,
|
||||||
@ -61,7 +58,6 @@ class InfoChannel(Cog):
|
|||||||
self.default_channel_names = {
|
self.default_channel_names = {
|
||||||
"members": "Members: {count}",
|
"members": "Members: {count}",
|
||||||
"humans": "Humans: {count}",
|
"humans": "Humans: {count}",
|
||||||
"boosters": "Boosters: {count}",
|
|
||||||
"bots": "Bots: {count}",
|
"bots": "Bots: {count}",
|
||||||
"roles": "Roles: {count}",
|
"roles": "Roles: {count}",
|
||||||
"channels": "Channels: {count}",
|
"channels": "Channels: {count}",
|
||||||
@ -174,7 +170,6 @@ class InfoChannel(Cog):
|
|||||||
Valid Types are:
|
Valid Types are:
|
||||||
- `members`: Total members on the server
|
- `members`: Total members on the server
|
||||||
- `humans`: Total members that aren't bots
|
- `humans`: Total members that aren't bots
|
||||||
- `boosters`: Total amount of boosters
|
|
||||||
- `bots`: Total bots
|
- `bots`: Total bots
|
||||||
- `roles`: Total number of roles
|
- `roles`: Total number of roles
|
||||||
- `channels`: Total number of channels excluding infochannels,
|
- `channels`: Total number of channels excluding infochannels,
|
||||||
@ -229,7 +224,6 @@ class InfoChannel(Cog):
|
|||||||
Valid Types are:
|
Valid Types are:
|
||||||
- `members`: Total members on the server
|
- `members`: Total members on the server
|
||||||
- `humans`: Total members that aren't bots
|
- `humans`: Total members that aren't bots
|
||||||
- `boosters`: Total amount of boosters
|
|
||||||
- `bots`: Total bots
|
- `bots`: Total bots
|
||||||
- `roles`: Total number of roles
|
- `roles`: Total number of roles
|
||||||
- `channels`: Total number of channels excluding infochannels
|
- `channels`: Total number of channels excluding infochannels
|
||||||
@ -447,7 +441,6 @@ class InfoChannel(Cog):
|
|||||||
guild,
|
guild,
|
||||||
members=True,
|
members=True,
|
||||||
humans=True,
|
humans=True,
|
||||||
boosters=True,
|
|
||||||
bots=True,
|
bots=True,
|
||||||
roles=True,
|
roles=True,
|
||||||
channels=True,
|
channels=True,
|
||||||
@ -504,16 +497,14 @@ class InfoChannel(Cog):
|
|||||||
guild_data = await self.config.guild(guild).all()
|
guild_data = await self.config.guild(guild).all()
|
||||||
|
|
||||||
to_update = (
|
to_update = (
|
||||||
kwargs.keys() & [key for key, value in guild_data["enabled_channels"].items() if value]
|
kwargs.keys() & guild_data["enabled_channels"].keys()
|
||||||
) # Value in kwargs doesn't matter
|
) # Value in kwargs doesn't matter
|
||||||
|
|
||||||
if to_update or extra_roles:
|
log.debug(f"{to_update=}")
|
||||||
log.debug(f"{to_update=}\n"
|
|
||||||
f"{extra_roles=}")
|
|
||||||
|
|
||||||
|
if to_update or extra_roles:
|
||||||
category = guild.get_channel(guild_data["category_id"])
|
category = guild.get_channel(guild_data["category_id"])
|
||||||
if category is None:
|
if category is None:
|
||||||
log.debug('Channel category is missing, updating must be off')
|
|
||||||
return # Nothing to update, must be off
|
return # Nothing to update, must be off
|
||||||
|
|
||||||
channel_data = await get_channel_counts(category, guild)
|
channel_data = await get_channel_counts(category, guild)
|
||||||
|
@ -40,20 +40,16 @@ class LoveCalculator(Cog):
|
|||||||
log.debug(f"{resp=}")
|
log.debug(f"{resp=}")
|
||||||
soup_object = BeautifulSoup(resp, "html.parser")
|
soup_object = BeautifulSoup(resp, "html.parser")
|
||||||
|
|
||||||
description = soup_object.find("div", class_="result__score")
|
description = soup_object.find("div", class_="result__score").get_text()
|
||||||
|
|
||||||
if description is None:
|
if description is None:
|
||||||
description = "Dr. Love is busy right now"
|
description = "Dr. Love is busy right now"
|
||||||
else:
|
else:
|
||||||
description = description.get_text().strip()
|
description = description.strip()
|
||||||
|
|
||||||
result_image = soup_object.find("img", class_="result__image").get("src")
|
result_image = soup_object.find("img", class_="result__image").get("src")
|
||||||
|
|
||||||
result_text = soup_object.find("div", class_="result-text")
|
result_text = soup_object.find("div", class_="result-text").get_text()
|
||||||
if result_text is None:
|
|
||||||
result_text = f"{x} and {y} aren't compatible 😔"
|
|
||||||
else:
|
|
||||||
result_text = result_text.get_text()
|
|
||||||
result_text = " ".join(result_text.split())
|
result_text = " ".join(result_text.split())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -77,13 +77,11 @@ class LastSeen(Cog):
|
|||||||
return
|
return
|
||||||
last_seen = self.get_date_time(last_seen)
|
last_seen = self.get_date_time(last_seen)
|
||||||
|
|
||||||
embed = discord.Embed(
|
# embed = discord.Embed(
|
||||||
description="{} was last seen at this date and time".format(member.display_name),
|
# description="{} was last seen at this date and time".format(member.display_name),
|
||||||
timestamp=last_seen,
|
# timestamp=last_seen)
|
||||||
color=await self.bot.get_embed_color(ctx),
|
|
||||||
)
|
|
||||||
|
|
||||||
# embed = discord.Embed(timestamp=last_seen, color=await self.bot.get_embed_color(ctx))
|
embed = discord.Embed(timestamp=last_seen, color=await self.bot.get_embed_color(ctx))
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
|
@ -32,7 +32,6 @@ class RecyclingPlant(Cog):
|
|||||||
|
|
||||||
x = 0
|
x = 0
|
||||||
reward = 0
|
reward = 0
|
||||||
timeoutcount = 0
|
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"{0} has signed up for a shift at the Recycling Plant! Type ``exit`` to terminate it early.".format(
|
"{0} has signed up for a shift at the Recycling Plant! Type ``exit`` to terminate it early.".format(
|
||||||
ctx.author.display_name
|
ctx.author.display_name
|
||||||
@ -54,25 +53,14 @@ class RecyclingPlant(Cog):
|
|||||||
return m.author == ctx.author and m.channel == ctx.channel
|
return m.author == ctx.author and m.channel == ctx.channel
|
||||||
|
|
||||||
try:
|
try:
|
||||||
answer = await self.bot.wait_for("message", timeout=20, check=check)
|
answer = await self.bot.wait_for("message", timeout=120, check=check)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
answer = None
|
answer = None
|
||||||
|
|
||||||
if answer is None:
|
if answer is None:
|
||||||
if timeoutcount == 2:
|
await ctx.send(
|
||||||
await ctx.send(
|
"``{}`` fell down the conveyor belt to be sorted again!".format(used["object"])
|
||||||
"{} slacked off at work, so they were sacked with no pay.".format(
|
)
|
||||||
ctx.author.display_name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
await ctx.send(
|
|
||||||
"{} is slacking, and if they carry on not working, they'll be fired.".format(
|
|
||||||
ctx.author.display_name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
timeoutcount += 1
|
|
||||||
elif answer.content.lower().strip() == used["action"]:
|
elif answer.content.lower().strip() == used["action"]:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"Congratulations! You put ``{}`` down the correct chute! (**+50**)".format(
|
"Congratulations! You put ``{}`` down the correct chute! (**+50**)".format(
|
||||||
|
@ -177,3 +177,7 @@ class SCP(Cog):
|
|||||||
|
|
||||||
msg = "http://www.scp-wiki.net/log-of-unexplained-locations"
|
msg = "http://www.scp-wiki.net/log-of-unexplained-locations"
|
||||||
await ctx.maybe_send_embed(msg)
|
await ctx.maybe_send_embed(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(SCP(bot))
|
||||||
|
@ -6,7 +6,6 @@ import discord
|
|||||||
from redbot.core import Config, checks, commands
|
from redbot.core import Config, checks, commands
|
||||||
from redbot.core.bot import Red
|
from redbot.core.bot import Red
|
||||||
from redbot.core.commands import Cog
|
from redbot.core.commands import Cog
|
||||||
from redbot.core.utils.chat_formatting import pagify
|
|
||||||
|
|
||||||
log = logging.getLogger("red.fox_v3.stealemoji")
|
log = logging.getLogger("red.fox_v3.stealemoji")
|
||||||
# Replaced with discord.Asset.read()
|
# Replaced with discord.Asset.read()
|
||||||
@ -100,8 +99,7 @@ class StealEmoji(Cog):
|
|||||||
await ctx.maybe_send_embed("No stolen emojis yet")
|
await ctx.maybe_send_embed("No stolen emojis yet")
|
||||||
return
|
return
|
||||||
|
|
||||||
for page in pagify(emoj, delims=[" "]):
|
await ctx.maybe_send_embed(emoj)
|
||||||
await ctx.maybe_send_embed(page)
|
|
||||||
|
|
||||||
@checks.is_owner()
|
@checks.is_owner()
|
||||||
@stealemoji.command(name="notify")
|
@stealemoji.command(name="notify")
|
||||||
|
@ -37,7 +37,7 @@ class Timerole(Cog):
|
|||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
|
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
|
||||||
default_global = {}
|
default_global = {}
|
||||||
default_guild = {"announce": None, "reapply": True, "roles": {}, "skipbots": True}
|
default_guild = {"announce": None, "reapply": True, "roles": {}}
|
||||||
default_rolemember = {"had_role": False, "check_again_time": None}
|
default_rolemember = {"had_role": False, "check_again_time": None}
|
||||||
|
|
||||||
self.config.register_global(**default_global)
|
self.config.register_global(**default_global)
|
||||||
@ -92,9 +92,6 @@ class Timerole(Cog):
|
|||||||
await ctx.maybe_send_embed("Error: Invalid time string.")
|
await ctx.maybe_send_embed("Error: Invalid time string.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if parsed_time is None:
|
|
||||||
return await ctx.maybe_send_embed("Error: Invalid time string.")
|
|
||||||
|
|
||||||
days = parsed_time.days
|
days = parsed_time.days
|
||||||
hours = parsed_time.seconds // 60 // 60
|
hours = parsed_time.seconds // 60 // 60
|
||||||
|
|
||||||
@ -154,14 +151,6 @@ class Timerole(Cog):
|
|||||||
await self.config.guild(guild).reapply.set(not current_setting)
|
await self.config.guild(guild).reapply.set(not current_setting)
|
||||||
await ctx.maybe_send_embed(f"Reapplying roles is now set to: {not current_setting}")
|
await ctx.maybe_send_embed(f"Reapplying roles is now set to: {not current_setting}")
|
||||||
|
|
||||||
@timerole.command()
|
|
||||||
async def skipbots(self, ctx: commands.Context):
|
|
||||||
"""Toggle skipping bots when adding/removing roles. Defaults to True"""
|
|
||||||
guild = ctx.guild
|
|
||||||
current_setting = await self.config.guild(guild).skipbots()
|
|
||||||
await self.config.guild(guild).skipbots.set(not current_setting)
|
|
||||||
await ctx.maybe_send_embed(f"Skipping bots is now set to: {not current_setting}")
|
|
||||||
|
|
||||||
@timerole.command()
|
@timerole.command()
|
||||||
async def delrole(self, ctx: commands.Context, role: discord.Role):
|
async def delrole(self, ctx: commands.Context, role: discord.Role):
|
||||||
"""Deletes a role from being added/removed after specified time"""
|
"""Deletes a role from being added/removed after specified time"""
|
||||||
@ -210,7 +199,6 @@ class Timerole(Cog):
|
|||||||
remove_results = ""
|
remove_results = ""
|
||||||
reapply = all_guilds[guild_id]["reapply"]
|
reapply = all_guilds[guild_id]["reapply"]
|
||||||
role_dict = all_guilds[guild_id]["roles"]
|
role_dict = all_guilds[guild_id]["roles"]
|
||||||
skipbots = all_guilds[guild_id]["skipbots"]
|
|
||||||
|
|
||||||
if not any(role_dict.values()): # No roles
|
if not any(role_dict.values()): # No roles
|
||||||
log.debug(f"No roles are configured for guild: {guild}")
|
log.debug(f"No roles are configured for guild: {guild}")
|
||||||
@ -220,10 +208,6 @@ class Timerole(Cog):
|
|||||||
# log.debug(f"{all_mr=}")
|
# log.debug(f"{all_mr=}")
|
||||||
|
|
||||||
async for member in AsyncIter(guild.members, steps=10):
|
async for member in AsyncIter(guild.members, steps=10):
|
||||||
|
|
||||||
if member.bot and skipbots:
|
|
||||||
continue
|
|
||||||
|
|
||||||
addlist = []
|
addlist = []
|
||||||
removelist = []
|
removelist = []
|
||||||
|
|
||||||
@ -311,11 +295,8 @@ class Timerole(Cog):
|
|||||||
log.exception("Failed Adding Roles")
|
log.exception("Failed Adding Roles")
|
||||||
add_results += f"{member.display_name} : **(Failed Adding Roles)**\n"
|
add_results += f"{member.display_name} : **(Failed Adding Roles)**\n"
|
||||||
else:
|
else:
|
||||||
add_results += (
|
add_results += " \n".join(
|
||||||
" \n".join(
|
f"{member.display_name} : {role.name}" for role in add_roles
|
||||||
f"{member.display_name} : {role.name}" for role in add_roles
|
|
||||||
)
|
|
||||||
+ "\n"
|
|
||||||
)
|
)
|
||||||
for role_id in addlist:
|
for role_id in addlist:
|
||||||
await self.config.custom(
|
await self.config.custom(
|
||||||
@ -329,11 +310,8 @@ class Timerole(Cog):
|
|||||||
log.exception("Failed Removing Roles")
|
log.exception("Failed Removing Roles")
|
||||||
remove_results += f"{member.display_name} : **(Failed Removing Roles)**\n"
|
remove_results += f"{member.display_name} : **(Failed Removing Roles)**\n"
|
||||||
else:
|
else:
|
||||||
remove_results += (
|
remove_results += " \n".join(
|
||||||
" \n".join(
|
f"{member.display_name} : {role.name}" for role in remove_roles
|
||||||
f"{member.display_name} : {role.name}" for role in remove_roles
|
|
||||||
)
|
|
||||||
+ "\n"
|
|
||||||
)
|
)
|
||||||
for role_id in removelist:
|
for role_id in removelist:
|
||||||
await self.config.custom(
|
await self.config.custom(
|
||||||
|
46
tts/tts.py
46
tts/tts.py
@ -1,35 +1,11 @@
|
|||||||
import io
|
import io
|
||||||
import logging
|
|
||||||
from typing import Optional, TYPE_CHECKING
|
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from discord.ext.commands import BadArgument, Converter
|
|
||||||
from gtts import gTTS
|
from gtts import gTTS
|
||||||
from gtts.lang import _fallback_deprecated_lang, tts_langs
|
|
||||||
from redbot.core import Config, commands
|
from redbot.core import Config, commands
|
||||||
from redbot.core.bot import Red
|
from redbot.core.bot import Red
|
||||||
from redbot.core.commands import Cog
|
from redbot.core.commands import Cog
|
||||||
|
|
||||||
log = logging.getLogger("red.fox_v3.tts")
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
ISO639Converter = str
|
|
||||||
else:
|
|
||||||
|
|
||||||
class ISO639Converter(Converter):
|
|
||||||
async def convert(self, ctx, argument) -> str:
|
|
||||||
lang = _fallback_deprecated_lang(argument)
|
|
||||||
|
|
||||||
try:
|
|
||||||
langs = tts_langs()
|
|
||||||
if lang not in langs:
|
|
||||||
raise BadArgument("Language not supported: %s" % lang)
|
|
||||||
except RuntimeError as e:
|
|
||||||
log.debug(str(e), exc_info=True)
|
|
||||||
log.warning(str(e))
|
|
||||||
|
|
||||||
return lang
|
|
||||||
|
|
||||||
|
|
||||||
class TTS(Cog):
|
class TTS(Cog):
|
||||||
"""
|
"""
|
||||||
@ -42,7 +18,7 @@ class TTS(Cog):
|
|||||||
|
|
||||||
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
|
self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True)
|
||||||
default_global = {}
|
default_global = {}
|
||||||
default_guild = {"language": "en"}
|
default_guild = {}
|
||||||
|
|
||||||
self.config.register_global(**default_global)
|
self.config.register_global(**default_global)
|
||||||
self.config.register_guild(**default_guild)
|
self.config.register_guild(**default_guild)
|
||||||
@ -51,29 +27,13 @@ class TTS(Cog):
|
|||||||
"""Nothing to delete"""
|
"""Nothing to delete"""
|
||||||
return
|
return
|
||||||
|
|
||||||
@commands.mod()
|
|
||||||
@commands.command()
|
|
||||||
async def ttslang(self, ctx: commands.Context, lang: ISO639Converter):
|
|
||||||
"""
|
|
||||||
Sets the default language for TTS in this guild.
|
|
||||||
|
|
||||||
Default is `en` for English
|
|
||||||
"""
|
|
||||||
await self.config.guild(ctx.guild).language.set(lang)
|
|
||||||
await ctx.send(f"Default tts language set to {lang}")
|
|
||||||
|
|
||||||
@commands.command(aliases=["t2s", "text2"])
|
@commands.command(aliases=["t2s", "text2"])
|
||||||
async def tts(
|
async def tts(self, ctx: commands.Context, *, text: str):
|
||||||
self, ctx: commands.Context, lang: Optional[ISO639Converter] = None, *, text: str
|
|
||||||
):
|
|
||||||
"""
|
"""
|
||||||
Send Text to speech messages as an mp3
|
Send Text to speech messages as an mp3
|
||||||
"""
|
"""
|
||||||
if lang is None:
|
|
||||||
lang = await self.config.guild(ctx.guild).language()
|
|
||||||
|
|
||||||
mp3_fp = io.BytesIO()
|
mp3_fp = io.BytesIO()
|
||||||
tts = gTTS(text, lang=lang)
|
tts = gTTS(text, lang="en")
|
||||||
tts.write_to_fp(mp3_fp)
|
tts.write_to_fp(mp3_fp)
|
||||||
mp3_fp.seek(0)
|
mp3_fp.seek(0)
|
||||||
await ctx.send(file=discord.File(mp3_fp, "text.mp3"))
|
await ctx.send(file=discord.File(mp3_fp, "text.mp3"))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user