diff --git a/README.md b/README.md
index 2f53825..a264b4b 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Cog Function
| chatter | **Alpha** | Chat-bot trained to talk like your guild
Missing some key features, but currently functional |
| coglint | **Alpha** | Error check code in python syntax posted to discord
Works, but probably needs more turning to work for cogs |
| fight | **Incomplete** | Organize bracket tournaments within discord
Still in-progress, a massive project |
-| flag | **Incomplete** | Create temporary marks on users that expire after specified time
Not yet ported to v3 |
+| flag | **Alpha** | Create temporary marks on users that expire after specified time
Ported, will not import old data. Please report bugs |
| forcemention | **Alpha** | Mentions unmentionable roles
Very simple cog, mention doesn't persist |
| hangman | **Alpha** | Play a game of hangman
Some visual glitches and needs more customization |
| howdoi | **Incomplete** | Create temporary marks on users that expire after specified time
Not yet ported to v3 |
diff --git a/flag/__init__.py b/flag/__init__.py
new file mode 100644
index 0000000..0184952
--- /dev/null
+++ b/flag/__init__.py
@@ -0,0 +1,5 @@
+from .flag import Flag
+
+
+def setup(bot):
+ bot.add_cog(Flag(bot))
diff --git a/flag/flag.py b/flag/flag.py
new file mode 100644
index 0000000..7fe1b30
--- /dev/null
+++ b/flag/flag.py
@@ -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:
+ await ctx.send_help()
+
+ @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)
diff --git a/flag/info..json b/flag/info..json
new file mode 100644
index 0000000..b5908b9
--- /dev/null
+++ b/flag/info..json
@@ -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"
+ ]
+}
\ No newline at end of file