diff --git a/ccrole/ccrole.py b/ccrole/ccrole.py index 5d1e40b..1f90a80 100644 --- a/ccrole/ccrole.py +++ b/ccrole/ccrole.py @@ -3,6 +3,7 @@ import logging import re import discord +from discord.ext.commands import RoleConverter, Greedy, CommandError, ArgumentParsingError from discord.ext.commands.view import StringView from redbot.core import Config, checks, commands from redbot.core.bot import Red @@ -13,15 +14,38 @@ log = logging.getLogger("red.fox_v3.ccrole") async def _get_roles_from_content(ctx, content): - 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 + # greedy = Greedy[RoleConverter] + view = StringView(content) + rc = RoleConverter() + + # "Borrowed" from discord.ext.commands.Command._transform_greedy_pos + result = [] + while not view.eof: + # for use with a manual undo + previous = view.index + + 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): @@ -84,7 +108,7 @@ class CCRole(commands.Cog): # Roles to add await ctx.send( - "What roles should it add? (Must be **comma separated**)\n" + "What roles should it add?\n" "Say `None` to skip adding roles" ) @@ -106,7 +130,7 @@ class CCRole(commands.Cog): # Roles to remove await ctx.send( - "What roles should it remove? (Must be comma separated)\n" + "What roles should it remove?\n" "Say `None` to skip removing roles" ) try: @@ -124,7 +148,7 @@ class CCRole(commands.Cog): # Roles to use await ctx.send( - "What roles are allowed to use this command? (Must be comma separated)\n" + "What roles are allowed to use this command?\n" "Say `None` to allow all roles" ) diff --git a/chatter/info.json b/chatter/info.json index a9bb96b..27db873 100644 --- a/chatter/info.json +++ b/chatter/info.json @@ -8,7 +8,9 @@ "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": [ "git+git://github.com/bobloy/ChatterBot@fox#egg=ChatterBot", - "kaggle" + "kaggle", + "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", + "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" ], "short": "Local Chatbot run on machine learning", "end_user_data_statement": "This cog only stores anonymous conversations data; no End User Data is stored.", diff --git a/conquest/conquest.py b/conquest/conquest.py index fa70911..2c3772c 100644 --- a/conquest/conquest.py +++ b/conquest/conquest.py @@ -1,5 +1,6 @@ import asyncio import json +import logging import os import pathlib from abc import ABC @@ -13,6 +14,8 @@ from redbot.core import Config, commands from redbot.core.bot import Red from redbot.core.data_manager import bundled_data_path, cog_data_path +log = logging.getLogger("red.fox_v3.conquest") + class Conquest(commands.Cog): """ @@ -53,14 +56,20 @@ class Conquest(commands.Cog): self.current_map = await self.config.current_map() if self.current_map: - await self.current_map_load() + if not await self.current_map_load(): + await self.config.current_map.clear() async def current_map_load(self): 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: self.map_data: dict = json.load(mapdata) self.ext = self.map_data["extension"] self.ext_format = "JPEG" if self.ext.upper() == "JPG" else self.ext.upper() + return True @commands.group() async def conquest(self, ctx: commands.Context): diff --git a/conquest/data/assets/maps.json b/conquest/data/assets/maps.json index a7d1c03..671a807 100644 --- a/conquest/data/assets/maps.json +++ b/conquest/data/assets/maps.json @@ -1,7 +1,7 @@ { "maps": [ - "simple_blank_map", - "test", - "test2" + "simple", + "ck2", + "HoI" ] } \ No newline at end of file diff --git a/fifo/task.py b/fifo/task.py index 34df8e2..9bf3ffd 100644 --- a/fifo/task.py +++ b/fifo/task.py @@ -90,6 +90,7 @@ things_for_fakemessage_to_steal = [ "content", "nonce", "reference", + "_edited_timestamp" # New 7/23/21 ] things_fakemessage_sets_by_default = { diff --git a/infochannel/infochannel.py b/infochannel/infochannel.py index c196e20..e8ea91b 100644 --- a/infochannel/infochannel.py +++ b/infochannel/infochannel.py @@ -28,9 +28,12 @@ async def get_channel_counts(category, guild): online_num = members - offline_num # Gets count of actual users human_num = members - bot_num + # count amount of premium subs/nitro subs. + boosters = guild.premium_subscription_count return { "members": members, "humans": human_num, + "boosters": boosters, "bots": bot_num, "roles": roles_num, "channels": channels_num, @@ -58,6 +61,7 @@ class InfoChannel(Cog): self.default_channel_names = { "members": "Members: {count}", "humans": "Humans: {count}", + "boosters": "Boosters: {count}", "bots": "Bots: {count}", "roles": "Roles: {count}", "channels": "Channels: {count}", @@ -170,6 +174,7 @@ class InfoChannel(Cog): Valid Types are: - `members`: Total members on the server - `humans`: Total members that aren't bots + - `boosters`: Total amount of boosters - `bots`: Total bots - `roles`: Total number of roles - `channels`: Total number of channels excluding infochannels, @@ -224,6 +229,7 @@ class InfoChannel(Cog): Valid Types are: - `members`: Total members on the server - `humans`: Total members that aren't bots + - `boosters`: Total amount of boosters - `bots`: Total bots - `roles`: Total number of roles - `channels`: Total number of channels excluding infochannels @@ -441,6 +447,7 @@ class InfoChannel(Cog): guild, members=True, humans=True, + boosters=True, bots=True, roles=True, channels=True, @@ -497,14 +504,16 @@ class InfoChannel(Cog): guild_data = await self.config.guild(guild).all() to_update = ( - kwargs.keys() & guild_data["enabled_channels"].keys() + kwargs.keys() & [key for key, value in guild_data["enabled_channels"].items() if value] ) # Value in kwargs doesn't matter - log.debug(f"{to_update=}") - if to_update or extra_roles: + log.debug(f"{to_update=}\n" + f"{extra_roles=}") + category = guild.get_channel(guild_data["category_id"]) if category is None: + log.debug('Channel category is missing, updating must be off') return # Nothing to update, must be off channel_data = await get_channel_counts(category, guild) diff --git a/lovecalculator/lovecalculator.py b/lovecalculator/lovecalculator.py index d6ae4fe..7473f74 100644 --- a/lovecalculator/lovecalculator.py +++ b/lovecalculator/lovecalculator.py @@ -40,12 +40,12 @@ class LoveCalculator(Cog): log.debug(f"{resp=}") soup_object = BeautifulSoup(resp, "html.parser") - description = soup_object.find("div", class_="result__score").get_text() + description = soup_object.find("div", class_="result__score") if description is None: description = "Dr. Love is busy right now" else: - description = description.strip() + description = description.get_text().strip() result_image = soup_object.find("img", class_="result__image").get("src") diff --git a/lseen/lseen.py b/lseen/lseen.py index 2ddb0e1..f77fbca 100644 --- a/lseen/lseen.py +++ b/lseen/lseen.py @@ -77,11 +77,13 @@ class LastSeen(Cog): return last_seen = self.get_date_time(last_seen) - # embed = discord.Embed( - # description="{} was last seen at this date and time".format(member.display_name), - # timestamp=last_seen) + embed = discord.Embed( + description="{} was last seen at this date and time".format(member.display_name), + 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) @commands.Cog.listener() diff --git a/timerole/timerole.py b/timerole/timerole.py index 0d62cf0..14a0bb4 100644 --- a/timerole/timerole.py +++ b/timerole/timerole.py @@ -37,7 +37,7 @@ class Timerole(Cog): self.bot = bot self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True) default_global = {} - default_guild = {"announce": None, "reapply": True, "roles": {}} + default_guild = {"announce": None, "reapply": True, "roles": {}, "skipbots": True} default_rolemember = {"had_role": False, "check_again_time": None} self.config.register_global(**default_global) @@ -92,6 +92,9 @@ class Timerole(Cog): await ctx.maybe_send_embed("Error: Invalid time string.") return + if parsed_time is None: + return await ctx.maybe_send_embed("Error: Invalid time string.") + days = parsed_time.days hours = parsed_time.seconds // 60 // 60 @@ -151,6 +154,14 @@ class Timerole(Cog): 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}") + @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() async def delrole(self, ctx: commands.Context, role: discord.Role): """Deletes a role from being added/removed after specified time""" @@ -199,6 +210,7 @@ class Timerole(Cog): remove_results = "" reapply = all_guilds[guild_id]["reapply"] role_dict = all_guilds[guild_id]["roles"] + skipbots = all_guilds[guild_id]["skipbots"] if not any(role_dict.values()): # No roles log.debug(f"No roles are configured for guild: {guild}") @@ -208,6 +220,10 @@ class Timerole(Cog): # log.debug(f"{all_mr=}") async for member in AsyncIter(guild.members, steps=10): + + if member.bot and skipbots: + continue + addlist = [] removelist = []