Merge branch 'master' into cogguide_develop
This commit is contained in:
		
						commit
						f6d3f2c4ea
					
				| @ -95,7 +95,8 @@ pip install --no-deps "chatterbot>=1.1" | ||||
| #### Step 1: Built-in Downloader | ||||
| 
 | ||||
| ``` | ||||
| [p]cog install <Fox> Chatter | ||||
| [p]repo add Fox https://github.com/bobloy/Fox-V3 | ||||
| [p]cog install Fox chatter | ||||
| ``` | ||||
| 
 | ||||
| #### Step 2: Install Requirements | ||||
|  | ||||
| @ -10,7 +10,7 @@ from chatterbot import ChatBot | ||||
| from chatterbot.comparisons import JaccardSimilarity, LevenshteinDistance, SpacySimilarity | ||||
| from chatterbot.response_selection import get_random_response | ||||
| from chatterbot.trainers import ChatterBotCorpusTrainer, ListTrainer, UbuntuCorpusTrainer | ||||
| from redbot.core import Config, commands | ||||
| from redbot.core import Config, checks, commands | ||||
| from redbot.core.commands import Cog | ||||
| from redbot.core.data_manager import cog_data_path | ||||
| from redbot.core.utils.predicates import MessagePredicate | ||||
| @ -159,7 +159,9 @@ class Chatter(Cog): | ||||
|         return out | ||||
| 
 | ||||
|     def _train_ubuntu(self): | ||||
|         trainer = UbuntuCorpusTrainer(self.chatbot) | ||||
|         trainer = UbuntuCorpusTrainer( | ||||
|             self.chatbot, ubuntu_corpus_data_directory=cog_data_path(self) / "ubuntu_data" | ||||
|         ) | ||||
|         trainer.train() | ||||
|         return True | ||||
| 
 | ||||
| @ -191,6 +193,7 @@ class Chatter(Cog): | ||||
|         if ctx.invoked_subcommand is None: | ||||
|             pass | ||||
| 
 | ||||
|     @checks.admin() | ||||
|     @chatter.command(name="channel") | ||||
|     async def chatter_channel( | ||||
|         self, ctx: commands.Context, channel: Optional[discord.TextChannel] = None | ||||
| @ -210,6 +213,7 @@ class Chatter(Cog): | ||||
|             await self.config.guild(ctx.guild).chatchannel.set(channel.id) | ||||
|             await ctx.maybe_send_embed(f"Chat channel is now {channel.mention}") | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @chatter.command(name="cleardata") | ||||
|     async def chatter_cleardata(self, ctx: commands.Context, confirm: bool = False): | ||||
|         """ | ||||
| @ -242,6 +246,7 @@ class Chatter(Cog): | ||||
| 
 | ||||
|         await ctx.tick() | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @chatter.command(name="algorithm", aliases=["algo"]) | ||||
|     async def chatter_algorithm( | ||||
|         self, ctx: commands.Context, algo_number: int, threshold: float = None | ||||
| @ -275,6 +280,7 @@ class Chatter(Cog): | ||||
| 
 | ||||
|             await ctx.tick() | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @chatter.command(name="model") | ||||
|     async def chatter_model(self, ctx: commands.Context, model_number: int): | ||||
|         """ | ||||
| @ -312,6 +318,7 @@ class Chatter(Cog): | ||||
|                 f"Model has been switched to {self.tagger_language.ISO_639_1}" | ||||
|             ) | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @chatter.command(name="minutes") | ||||
|     async def minutes(self, ctx: commands.Context, minutes: int): | ||||
|         """ | ||||
| @ -327,6 +334,7 @@ class Chatter(Cog): | ||||
| 
 | ||||
|         await ctx.tick() | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @chatter.command(name="age") | ||||
|     async def age(self, ctx: commands.Context, days: int): | ||||
|         """ | ||||
| @ -341,6 +349,7 @@ class Chatter(Cog): | ||||
|         await self.config.guild(ctx.guild).days.set(days) | ||||
|         await ctx.tick() | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @chatter.command(name="backup") | ||||
|     async def backup(self, ctx, backupname): | ||||
|         """ | ||||
| @ -362,6 +371,7 @@ class Chatter(Cog): | ||||
|         else: | ||||
|             await ctx.maybe_send_embed("Error occurred :(") | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @chatter.command(name="trainubuntu") | ||||
|     async def chatter_train_ubuntu(self, ctx: commands.Context, confirmation: bool = False): | ||||
|         """ | ||||
| @ -383,6 +393,7 @@ class Chatter(Cog): | ||||
|         else: | ||||
|             await ctx.send("Error occurred :(") | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @chatter.command(name="trainenglish") | ||||
|     async def chatter_train_english(self, ctx: commands.Context): | ||||
|         """ | ||||
| @ -396,6 +407,7 @@ class Chatter(Cog): | ||||
|         else: | ||||
|             await ctx.maybe_send_embed("Error occurred :(") | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @chatter.command() | ||||
|     async def train(self, ctx: commands.Context, channel: discord.TextChannel): | ||||
|         """ | ||||
|  | ||||
							
								
								
									
										54
									
								
								fifo/fifo.py
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								fifo/fifo.py
									
									
									
									
									
								
							| @ -1,5 +1,6 @@ | ||||
| import itertools | ||||
| import logging | ||||
| from datetime import datetime, timedelta, tzinfo | ||||
| from datetime import datetime, timedelta, tzinfo, MAXYEAR | ||||
| from typing import Optional, Union | ||||
| 
 | ||||
| import discord | ||||
| @ -10,7 +11,7 @@ from apscheduler.schedulers.base import STATE_PAUSED, STATE_RUNNING | ||||
| from redbot.core import Config, checks, commands | ||||
| from redbot.core.bot import Red | ||||
| from redbot.core.commands import TimedeltaConverter | ||||
| from redbot.core.utils.chat_formatting import pagify | ||||
| from redbot.core.utils.chat_formatting import humanize_list, humanize_timedelta, pagify | ||||
| 
 | ||||
| from .datetime_cron_converters import CronConverter, DatetimeConverter, TimezoneConverter | ||||
| from .task import Task | ||||
| @ -26,6 +27,7 @@ async def _execute_task(task_state): | ||||
|     task = Task(**task_state) | ||||
|     if await task.load_from_config(): | ||||
|         return await task.execute() | ||||
|     log.warning(f"Failed to load data on {task_state=}") | ||||
|     return False | ||||
| 
 | ||||
| 
 | ||||
| @ -37,6 +39,27 @@ def _disassemble_job_id(job_id: str): | ||||
|     return job_id.split("_") | ||||
| 
 | ||||
| 
 | ||||
| def _get_run_times(job: Job, now: datetime = None): | ||||
|     """ | ||||
|     Computes the scheduled run times between ``next_run_time`` and ``now`` (inclusive). | ||||
| 
 | ||||
|     Modified to be asynchronous and yielding instead of all-or-nothing | ||||
| 
 | ||||
|     """ | ||||
|     if not job.next_run_time: | ||||
|         raise StopIteration() | ||||
| 
 | ||||
|     if now is None: | ||||
|         now = datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, tzinfo=job.next_run_time.tzinfo) | ||||
|         yield from _get_run_times(job, now) | ||||
|         raise StopIteration() | ||||
| 
 | ||||
|     next_run_time = job.next_run_time | ||||
|     while next_run_time and next_run_time <= now: | ||||
|         yield next_run_time | ||||
|         next_run_time = job.trigger.get_next_fire_time(next_run_time, now) | ||||
| 
 | ||||
| 
 | ||||
| class FIFO(commands.Cog): | ||||
|     """ | ||||
|     Simple Scheduling Cog | ||||
| @ -173,6 +196,30 @@ class FIFO(commands.Cog): | ||||
|         if ctx.invoked_subcommand is None: | ||||
|             pass | ||||
| 
 | ||||
|     @fifo.command(name="checktask", aliases=["checkjob", "check"]) | ||||
|     async def fifo_checktask(self, ctx: commands.Context, task_name: str): | ||||
|         """Returns the next 10 scheduled executions of the task""" | ||||
|         task = Task(task_name, ctx.guild.id, self.config, bot=self.bot) | ||||
|         await task.load_from_config() | ||||
| 
 | ||||
|         if task.data is None: | ||||
|             await ctx.maybe_send_embed( | ||||
|                 f"Task by the name of {task_name} is not found in this guild" | ||||
|             ) | ||||
|             return | ||||
| 
 | ||||
|         job = await self._get_job(task) | ||||
|         if job is None: | ||||
|             await ctx.maybe_send_embed("No job scheduled for this task") | ||||
|             return | ||||
|         now = datetime.now(job.next_run_time.tzinfo) | ||||
| 
 | ||||
|         times = [ | ||||
|             humanize_timedelta(timedelta=x - now) | ||||
|             for x in itertools.islice(_get_run_times(job), 10) | ||||
|         ] | ||||
|         await ctx.maybe_send_embed("\n\n".join(times)) | ||||
| 
 | ||||
|     @fifo.command(name="set") | ||||
|     async def fifo_set( | ||||
|         self, | ||||
| @ -324,7 +371,7 @@ class FIFO(commands.Cog): | ||||
|             out = "" | ||||
|             all_tasks = await self.config.guild(ctx.guild).tasks() | ||||
|             for task_name, task_data in all_tasks.items(): | ||||
|                 out += f"{task_name}: {task_data}\n" | ||||
|                 out += f"{task_name}: {task_data}\n\n" | ||||
| 
 | ||||
|             if out: | ||||
|                 if len(out) > 2000: | ||||
| @ -394,6 +441,7 @@ class FIFO(commands.Cog): | ||||
|             return | ||||
| 
 | ||||
|         await task.clear_triggers() | ||||
|         await self._remove_job(task) | ||||
|         await ctx.tick() | ||||
| 
 | ||||
|     @fifo.group(name="addtrigger", aliases=["trigger"]) | ||||
|  | ||||
							
								
								
									
										48
									
								
								fifo/task.py
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								fifo/task.py
									
									
									
									
									
								
							| @ -39,7 +39,7 @@ def parse_triggers(data: Union[Dict, None]): | ||||
|         return None | ||||
| 
 | ||||
|     if len(data["triggers"]) > 1:  # Multiple triggers | ||||
|         return OrTrigger(get_trigger(t_data) for t_data in data["triggers"]) | ||||
|         return OrTrigger([get_trigger(t_data) for t_data in data["triggers"]]) | ||||
| 
 | ||||
|     return get_trigger(data["triggers"][0]) | ||||
| 
 | ||||
| @ -108,20 +108,6 @@ class Task: | ||||
|                         "tzinfo": getattr(t["tzinfo"], "zone", None), | ||||
|                     } | ||||
|                 ) | ||||
|                 # triggers.append( | ||||
|                 #     { | ||||
|                 #         "type": t["type"], | ||||
|                 #         "time_data": { | ||||
|                 #             "year": dt.year, | ||||
|                 #             "month": dt.month, | ||||
|                 #             "day": dt.day, | ||||
|                 #             "hour": dt.hour, | ||||
|                 #             "minute": dt.minute, | ||||
|                 #             "second": dt.second, | ||||
|                 #             "tzinfo": dt.tzinfo, | ||||
|                 #         }, | ||||
|                 #     } | ||||
|                 # ) | ||||
|                 continue | ||||
| 
 | ||||
|             if t["type"] == "cron": | ||||
| @ -239,20 +225,26 @@ class Task: | ||||
| 
 | ||||
|     async def execute(self): | ||||
|         if not self.data or not self.get_command_str(): | ||||
|             log.warning(f"Could not execute task due to data problem: {self.data=}") | ||||
|             log.warning(f"Could not execute Task[{self.name}] due to data problem: {self.data=}") | ||||
|             return False | ||||
| 
 | ||||
|         guild: discord.Guild = self.bot.get_guild(self.guild_id)  # used for get_prefix | ||||
|         if guild is None: | ||||
|             log.warning(f"Could not execute task due to missing guild: {self.guild_id}") | ||||
|             log.warning( | ||||
|                 f"Could not execute Task[{self.name}] due to missing guild: {self.guild_id}" | ||||
|             ) | ||||
|             return False | ||||
|         channel: discord.TextChannel = guild.get_channel(self.channel_id) | ||||
|         if channel is None: | ||||
|             log.warning(f"Could not execute task due to missing channel: {self.channel_id}") | ||||
|             log.warning( | ||||
|                 f"Could not execute Task[{self.name}] due to missing channel: {self.channel_id}" | ||||
|             ) | ||||
|             return False | ||||
|         author: discord.User = guild.get_member(self.author_id) | ||||
|         if author is None: | ||||
|             log.warning(f"Could not execute task due to missing author: {self.author_id}") | ||||
|             log.warning( | ||||
|                 f"Could not execute Task[{self.name}] due to missing author: {self.author_id}" | ||||
|             ) | ||||
|             return False | ||||
| 
 | ||||
|         actual_message: discord.Message = channel.last_message | ||||
| @ -267,15 +259,15 @@ class Task: | ||||
|                     actual_message = await author.history(limit=1).flatten() | ||||
|                     if not actual_message:  # Okay, the *author* has never sent a message? | ||||
|                         log.warning("No message found in channel cache yet, skipping execution") | ||||
|                         return | ||||
|                         return False | ||||
|                 actual_message = actual_message[0] | ||||
| 
 | ||||
|         message = FakeMessage(actual_message) | ||||
|         # message = FakeMessage2 | ||||
|         message.author = author | ||||
|         message.guild = guild  # Just in case we got desperate | ||||
|         message.guild = guild  # Just in case we got desperate, see above | ||||
|         message.channel = channel | ||||
|         message.id = time_snowflake(datetime.now())  # Pretend to be now | ||||
|         message.id = time_snowflake(datetime.utcnow(), high=False)  # Pretend to be now | ||||
|         message = neuter_message(message) | ||||
| 
 | ||||
|         # absolutely weird that this takes a message object instead of guild | ||||
| @ -287,15 +279,21 @@ class Task: | ||||
| 
 | ||||
|         message.content = f"{prefix}{self.get_command_str()}" | ||||
| 
 | ||||
|         if not message.guild or not message.author or not message.content: | ||||
|             log.warning(f"Could not execute task due to message problem: {message}") | ||||
|         if ( | ||||
|             not message.guild | ||||
|             or not message.author | ||||
|             or not message.content | ||||
|             or message.content == prefix | ||||
|         ): | ||||
|             log.warning(f"Could not execute Task[{self.name}] due to message problem: {message}") | ||||
|             return False | ||||
| 
 | ||||
|         new_ctx: commands.Context = await self.bot.get_context(message) | ||||
|         new_ctx.assume_yes = True | ||||
|         if not new_ctx.valid: | ||||
|             log.warning( | ||||
|                 f"Could not execute Task[{self.name}] due invalid context: {new_ctx.invoked_with}" | ||||
|                 f"Could not execute Task[{self.name}] due invalid context: " | ||||
|                 f"{new_ctx.invoked_with=} {new_ctx.prefix=} {new_ctx.command=}" | ||||
|             ) | ||||
|             return False | ||||
| 
 | ||||
|  | ||||
| @ -8,9 +8,7 @@ from redbot.core.data_manager import cog_data_path | ||||
| 
 | ||||
| 
 | ||||
| class Nudity(commands.Cog): | ||||
|     """ | ||||
|     V3 Cog Template | ||||
|     """ | ||||
|     """Monitor images for NSFW content and moves them to a nsfw channel if possible""" | ||||
| 
 | ||||
|     def __init__(self, bot: Red): | ||||
|         super().__init__() | ||||
|  | ||||
| @ -793,7 +793,7 @@ class PlantTycoon(commands.Cog): | ||||
|                             pass | ||||
|             await asyncio.sleep(self.defaults["timers"]["notification"] * 60) | ||||
| 
 | ||||
|     def __unload(self): | ||||
|     def cog_unload(self): | ||||
|         self.completion_task.cancel() | ||||
|         # self.degradation_task.cancel() | ||||
|         self.notification_task.cancel() | ||||
|  | ||||
| @ -50,6 +50,7 @@ class StealEmoji(Cog): | ||||
|         default_global = { | ||||
|             "stolemoji": {}, | ||||
|             "guildbanks": [], | ||||
|             "autobanked_guilds": [], | ||||
|             "on": False, | ||||
|             "notify": 0, | ||||
|             "autobank": False, | ||||
| @ -145,11 +146,54 @@ class StealEmoji(Cog): | ||||
| 
 | ||||
|         await ctx.maybe_send_embed("AutoBanking is now " + str(not curr_setting)) | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @commands.guild_only() | ||||
|     @stealemoji.command(name="deleteserver", aliases=["deleteguild"]) | ||||
|     async def se_deleteserver(self, ctx: commands.Context, guild_id=None): | ||||
|         """Delete servers the bot is the owner of. | ||||
| 
 | ||||
|         Useful for auto-generated guildbanks.""" | ||||
|         if guild_id is None: | ||||
|             guild = ctx.guild | ||||
|         else: | ||||
|             guild = await self.bot.get_guild(guild_id) | ||||
| 
 | ||||
|         if guild is None: | ||||
|             await ctx.maybe_send_embed("Failed to get guild, cancelling") | ||||
|             return | ||||
|         guild: discord.Guild | ||||
|         await ctx.maybe_send_embed( | ||||
|             f"Will attempt to delete {guild.name} ({guild.id})\n" f"Okay to continue? (yes/no)" | ||||
|         ) | ||||
| 
 | ||||
|         def check(m): | ||||
|             return m.author == ctx.author and m.channel == ctx.channel | ||||
| 
 | ||||
|         try: | ||||
|             answer = await self.bot.wait_for("message", timeout=120, check=check) | ||||
|         except asyncio.TimeoutError: | ||||
|             await ctx.send("Timed out, canceling") | ||||
|             return | ||||
| 
 | ||||
|         if answer.content.upper() not in ["Y", "YES"]: | ||||
|             await ctx.maybe_send_embed("Cancelling") | ||||
|             return | ||||
|         try: | ||||
|             await guild.delete() | ||||
|         except discord.Forbidden: | ||||
|             log.exception("No permission to delete. I'm probably not the guild owner") | ||||
|             await ctx.maybe_send_embed("No permission to delete. I'm probably not the guild owner") | ||||
|         except discord.HTTPException: | ||||
|             log.exception("Unexpected error when deleting guild") | ||||
|             await ctx.maybe_send_embed("Unexpected error when deleting guild") | ||||
|         else: | ||||
|             await self.bot.send_to_owners(f"Guild {guild.name} deleted") | ||||
| 
 | ||||
|     @checks.is_owner() | ||||
|     @commands.guild_only() | ||||
|     @stealemoji.command(name="bank") | ||||
|     async def se_bank(self, ctx): | ||||
|         """Add current server as emoji bank""" | ||||
|         """Add or remove current server as emoji bank""" | ||||
| 
 | ||||
|         def check(m): | ||||
|             return ( | ||||
| @ -235,6 +279,9 @@ class StealEmoji(Cog): | ||||
|                     return | ||||
|                 async with self.config.guildbanks() as guildbanks: | ||||
|                     guildbanks.append(guildbank.id) | ||||
|                 # Track generated guilds for easier deletion | ||||
|                 async with self.config.autobanked_guilds() as autobanked_guilds: | ||||
|                     autobanked_guilds.append(guildbank.id) | ||||
| 
 | ||||
|                 await asyncio.sleep(2) | ||||
| 
 | ||||
|  | ||||
| @ -235,8 +235,8 @@ class Timerole(Cog): | ||||
|                     has_roles = set(r.id for r in member.roles) | ||||
| 
 | ||||
|                     # Stop if they currently have or don't have the role, and mark had_role | ||||
|                     if (role_id in has_roles and not role_data["remove"]) or ( | ||||
|                         role_id not in has_roles and role_data["remove"] | ||||
|                     if (int(role_id) in has_roles and not role_data["remove"]) or ( | ||||
|                         int(role_id) not in has_roles and role_data["remove"] | ||||
|                     ): | ||||
|                         if not mr_dict["had_role"]: | ||||
|                             await self.config.custom( | ||||
|  | ||||
| @ -56,7 +56,7 @@ class Werewolf(Cog): | ||||
|         """Nothing to delete""" | ||||
|         return | ||||
| 
 | ||||
|     def __unload(self): | ||||
|     def cog_unload(self): | ||||
|         log.debug("Unload called") | ||||
|         for game in self.games.values(): | ||||
|             del game | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 bobloy
						bobloy