Merge branch 'mongoengine'
This commit is contained in:
commit
a2dba0d437
34 changed files with 690 additions and 1121 deletions
|
@ -5,11 +5,11 @@ from discord import Intents
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord.utils import find
|
from discord.utils import find
|
||||||
from discord_slash import SlashCommand
|
from discord_slash import SlashCommand
|
||||||
|
from mongoengine import connect
|
||||||
from psutil import Process
|
from psutil import Process
|
||||||
|
|
||||||
from jarvis import logo, tasks, utils
|
from jarvis import logo, tasks, utils
|
||||||
from jarvis.config import get_config
|
from jarvis.config import get_config
|
||||||
from jarvis.db import DBManager
|
|
||||||
from jarvis.events import guild, member, message
|
from jarvis.events import guild, member, message
|
||||||
|
|
||||||
if asyncio.get_event_loop().is_closed():
|
if asyncio.get_event_loop().is_closed():
|
||||||
|
@ -25,11 +25,9 @@ jarvis = commands.Bot(
|
||||||
)
|
)
|
||||||
slash = SlashCommand(jarvis, sync_commands=True, sync_on_cog_reload=True)
|
slash = SlashCommand(jarvis, sync_commands=True, sync_on_cog_reload=True)
|
||||||
jarvis_self = Process()
|
jarvis_self = Process()
|
||||||
__version__ = "1.9.6"
|
__version__ = "1.10.0"
|
||||||
|
|
||||||
jconfig = get_config()
|
jconfig = get_config()
|
||||||
db = DBManager(jconfig.mongo["connect"]).mongo
|
|
||||||
jarvis_db = db[jconfig.mongo["database"]]
|
|
||||||
|
|
||||||
|
|
||||||
@jarvis.event
|
@jarvis.event
|
||||||
|
@ -59,28 +57,39 @@ def run(ctx=None):
|
||||||
global restart_ctx
|
global restart_ctx
|
||||||
if ctx:
|
if ctx:
|
||||||
restart_ctx = ctx
|
restart_ctx = ctx
|
||||||
|
connect(
|
||||||
|
db="ctc2",
|
||||||
|
alias="ctc2",
|
||||||
|
authentication_source="admin",
|
||||||
|
**jconfig.mongo["connect"],
|
||||||
|
)
|
||||||
|
connect(
|
||||||
|
db=jconfig.mongo["database"],
|
||||||
|
alias="main",
|
||||||
|
authentication_source="admin",
|
||||||
|
**jconfig.mongo["connect"],
|
||||||
|
)
|
||||||
|
jconfig.get_db_config()
|
||||||
for extension in utils.get_extensions():
|
for extension in utils.get_extensions():
|
||||||
jarvis.load_extension(extension)
|
jarvis.load_extension(extension)
|
||||||
config = get_config()
|
|
||||||
print(
|
print(
|
||||||
" https://discord.com/api/oauth2/authorize?client_id="
|
" https://discord.com/api/oauth2/authorize?client_id="
|
||||||
+ "{}&permissions=8&scope=bot%20applications.commands".format(
|
+ "{}&permissions=8&scope=bot%20applications.commands".format(
|
||||||
config.client_id
|
jconfig.client_id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
jarvis.max_messages = config.max_messages
|
jarvis.max_messages = jconfig.max_messages
|
||||||
tasks.init()
|
tasks.init()
|
||||||
|
|
||||||
# Add event listeners
|
# Add event listeners
|
||||||
if config.events:
|
if jconfig.events:
|
||||||
listeners = [
|
listeners = [
|
||||||
guild.GuildEventHandler(jarvis),
|
guild.GuildEventHandler(jarvis),
|
||||||
member.MemberEventHandler(jarvis),
|
member.MemberEventHandler(jarvis),
|
||||||
message.MessageEventHandler(jarvis),
|
message.MessageEventHandler(jarvis),
|
||||||
]
|
]
|
||||||
|
jarvis.run(jconfig.token, bot=True, reconnect=True)
|
||||||
jarvis.run(config.token, bot=True, reconnect=True)
|
|
||||||
for cog in jarvis.cogs:
|
for cog in jarvis.cogs:
|
||||||
session = getattr(cog, "_session", None)
|
session = getattr(cog, "_session", None)
|
||||||
if session:
|
if session:
|
||||||
|
|
|
@ -9,7 +9,7 @@ from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.model import ButtonStyle
|
from discord_slash.model import ButtonStyle
|
||||||
from discord_slash.utils.manage_commands import create_choice, create_option
|
from discord_slash.utils.manage_commands import create_choice, create_option
|
||||||
|
|
||||||
from jarvis.db.types import Ban, Unban
|
from jarvis.db.models import Ban, Unban
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.cachecog import CacheCog
|
from jarvis.utils.cachecog import CacheCog
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
@ -40,7 +40,7 @@ class BanCog(CacheCog):
|
||||||
type=type,
|
type=type,
|
||||||
duration=duration,
|
duration=duration,
|
||||||
active=active,
|
active=active,
|
||||||
).insert()
|
).save()
|
||||||
|
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="User Banned",
|
title="User Banned",
|
||||||
|
@ -68,7 +68,7 @@ class BanCog(CacheCog):
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
admin=ctx.author.id,
|
admin=ctx.author.id,
|
||||||
reason=reason,
|
reason=reason,
|
||||||
).insert()
|
).save()
|
||||||
|
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="User Unbanned",
|
title="User Unbanned",
|
||||||
|
@ -280,9 +280,9 @@ class BanCog(CacheCog):
|
||||||
# We take advantage of the previous checks to save CPU cycles
|
# We take advantage of the previous checks to save CPU cycles
|
||||||
if not discord_ban_info:
|
if not discord_ban_info:
|
||||||
if isinstance(user, int):
|
if isinstance(user, int):
|
||||||
database_ban_info = Ban.get(
|
database_ban_info = Ban.objects(
|
||||||
guild=ctx.guild.id, user=user, active=True
|
guild=ctx.guild.id, user=user, active=True
|
||||||
)
|
).first()
|
||||||
else:
|
else:
|
||||||
search = {
|
search = {
|
||||||
"guild": ctx.guild.id,
|
"guild": ctx.guild.id,
|
||||||
|
@ -291,7 +291,7 @@ class BanCog(CacheCog):
|
||||||
}
|
}
|
||||||
if discrim:
|
if discrim:
|
||||||
search["discrim"] = discrim
|
search["discrim"] = discrim
|
||||||
database_ban_info = Ban.get(**search)
|
database_ban_info = Ban.objects(**search).first()
|
||||||
|
|
||||||
if not discord_ban_info and not database_ban_info:
|
if not discord_ban_info and not database_ban_info:
|
||||||
await ctx.send(f"Unable to find user {orig_user}", hidden=True)
|
await ctx.send(f"Unable to find user {orig_user}", hidden=True)
|
||||||
|
@ -308,7 +308,7 @@ class BanCog(CacheCog):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
database_ban_info.active = False
|
database_ban_info.active = False
|
||||||
database_ban_info.update()
|
database_ban_info.save()
|
||||||
_ = Unban(
|
_ = Unban(
|
||||||
user=database_ban_info.user,
|
user=database_ban_info.user,
|
||||||
username=database_ban_info.username,
|
username=database_ban_info.username,
|
||||||
|
@ -316,7 +316,7 @@ class BanCog(CacheCog):
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
admin=ctx.author.id,
|
admin=ctx.author.id,
|
||||||
reason=reason,
|
reason=reason,
|
||||||
).insert()
|
).save()
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"Unable to find user in Discord, "
|
"Unable to find user in Discord, "
|
||||||
+ "but removed entry from database."
|
+ "but removed entry from database."
|
||||||
|
@ -371,8 +371,7 @@ class BanCog(CacheCog):
|
||||||
search["active"] = True
|
search["active"] = True
|
||||||
if type > 0:
|
if type > 0:
|
||||||
search["type"] = types[type]
|
search["type"] = types[type]
|
||||||
bans = Ban.get_many(**search)
|
bans = Ban.objects(**search).order_by("-created_at")
|
||||||
bans.sort(key=lambda x: x.created_at, reverse=True)
|
|
||||||
db_bans = []
|
db_bans = []
|
||||||
fields = []
|
fields = []
|
||||||
for ban in bans:
|
for ban in bans:
|
||||||
|
|
|
@ -2,7 +2,7 @@ from discord import User
|
||||||
from discord_slash import SlashContext, cog_ext
|
from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.utils.manage_commands import create_option
|
from discord_slash.utils.manage_commands import create_option
|
||||||
|
|
||||||
from jarvis.db.types import Kick
|
from jarvis.db.models import Kick
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.cachecog import CacheCog
|
from jarvis.utils.cachecog import CacheCog
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
@ -86,4 +86,4 @@ class KickCog(CacheCog):
|
||||||
reason=reason,
|
reason=reason,
|
||||||
admin=ctx.author.id,
|
admin=ctx.author.id,
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
).insert()
|
).save()
|
||||||
|
|
|
@ -5,7 +5,7 @@ from discord.ext import commands
|
||||||
from discord_slash import SlashContext, cog_ext
|
from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.utils.manage_commands import create_option
|
from discord_slash.utils.manage_commands import create_option
|
||||||
|
|
||||||
from jarvis.db.types import Lock
|
from jarvis.db.models import Lock
|
||||||
from jarvis.utils.cachecog import CacheCog
|
from jarvis.utils.cachecog import CacheCog
|
||||||
from jarvis.utils.permissions import admin_or_permissions
|
from jarvis.utils.permissions import admin_or_permissions
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ class LockCog(CacheCog):
|
||||||
admin=ctx.author.id,
|
admin=ctx.author.id,
|
||||||
reason=reason,
|
reason=reason,
|
||||||
duration=duration,
|
duration=duration,
|
||||||
).insert()
|
).save()
|
||||||
await ctx.send(f"{channel.mention} locked for {duration} minute(s)")
|
await ctx.send(f"{channel.mention} locked for {duration} minute(s)")
|
||||||
|
|
||||||
@cog_ext.cog_slash(
|
@cog_ext.cog_slash(
|
||||||
|
@ -120,7 +120,9 @@ class LockCog(CacheCog):
|
||||||
):
|
):
|
||||||
if not channel:
|
if not channel:
|
||||||
channel = ctx.channel
|
channel = ctx.channel
|
||||||
lock = Lock.get(guild=ctx.guild.id, channel=channel.id, active=True)
|
lock = Lock.objects(
|
||||||
|
guild=ctx.guild.id, channel=channel.id, active=True
|
||||||
|
).first()
|
||||||
if not lock:
|
if not lock:
|
||||||
await ctx.send(f"{channel.mention} not locked.", hidden=True)
|
await ctx.send(f"{channel.mention} not locked.", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -130,5 +132,5 @@ class LockCog(CacheCog):
|
||||||
except Exception:
|
except Exception:
|
||||||
continue # Just continue on error
|
continue # Just continue on error
|
||||||
lock.active = False
|
lock.active = False
|
||||||
lock.update()
|
lock.save()
|
||||||
await ctx.send(f"{channel.mention} unlocked")
|
await ctx.send(f"{channel.mention} unlocked")
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
import pymongo
|
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord_slash import SlashContext, cog_ext
|
from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.utils.manage_commands import create_option
|
from discord_slash.utils.manage_commands import create_option
|
||||||
|
|
||||||
from jarvis.config import get_config
|
from jarvis.db.models import Lock
|
||||||
from jarvis.db import DBManager
|
|
||||||
from jarvis.db.types import Lock
|
|
||||||
from jarvis.utils.cachecog import CacheCog
|
from jarvis.utils.cachecog import CacheCog
|
||||||
from jarvis.utils.permissions import admin_or_permissions
|
from jarvis.utils.permissions import admin_or_permissions
|
||||||
|
|
||||||
|
@ -15,10 +12,6 @@ from jarvis.utils.permissions import admin_or_permissions
|
||||||
class LockdownCog(CacheCog):
|
class LockdownCog(CacheCog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
super().__init__(bot)
|
super().__init__(bot)
|
||||||
config = get_config()
|
|
||||||
self.db = DBManager(config.mongo["connect"]).mongo[
|
|
||||||
config.mongo["database"]
|
|
||||||
]
|
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
base="lockdown",
|
base="lockdown",
|
||||||
|
@ -63,20 +56,18 @@ class LockdownCog(CacheCog):
|
||||||
except Exception:
|
except Exception:
|
||||||
continue # Just continue on error
|
continue # Just continue on error
|
||||||
updates.append(
|
updates.append(
|
||||||
pymongo.InsertOne(
|
Lock(
|
||||||
{
|
channel=channel.id,
|
||||||
"channel": channel.id,
|
guild=ctx.guild.id,
|
||||||
"guild": ctx.guild.id,
|
admin=ctx.author.id,
|
||||||
"admin": ctx.author.id,
|
reason=reason,
|
||||||
"reason": reason,
|
duration=duration,
|
||||||
"duration": duration,
|
active=True,
|
||||||
"active": True,
|
created_at=datetime.utcnow(),
|
||||||
"created_at": datetime.utcnow(),
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if updates:
|
if updates:
|
||||||
self.db.locks.bulk_write(updates)
|
Lock.objects().insert(updates)
|
||||||
await ctx.send(f"Server locked for {duration} minute(s)")
|
await ctx.send(f"Server locked for {duration} minute(s)")
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
|
@ -91,8 +82,8 @@ class LockdownCog(CacheCog):
|
||||||
):
|
):
|
||||||
channels = ctx.guild.channels
|
channels = ctx.guild.channels
|
||||||
roles = ctx.guild.roles
|
roles = ctx.guild.roles
|
||||||
updates = []
|
update = False
|
||||||
locks = Lock.get_many(guild=ctx.guild.id, active=True)
|
locks = Lock.objects(guild=ctx.guild.id, active=True)
|
||||||
if not locks:
|
if not locks:
|
||||||
await ctx.send("No lockdown detected.", hidden=True)
|
await ctx.send("No lockdown detected.", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -103,16 +94,9 @@ class LockdownCog(CacheCog):
|
||||||
await self._unlock_channel(channel, role, ctx.author)
|
await self._unlock_channel(channel, role, ctx.author)
|
||||||
except Exception:
|
except Exception:
|
||||||
continue # Just continue on error
|
continue # Just continue on error
|
||||||
updates.append(
|
update = True
|
||||||
pymongo.UpdateOne(
|
if update:
|
||||||
{
|
Lock.objects(guild=ctx.guild.id, active=True).update(
|
||||||
"channel": channel.id,
|
set__active=False
|
||||||
"guild": ctx.guild.id,
|
|
||||||
"admin": ctx.author.id,
|
|
||||||
},
|
|
||||||
{"$set": {"active": False}},
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if updates:
|
|
||||||
self.db.locks.bulk_write(updates)
|
|
||||||
await ctx.send("Server unlocked")
|
await ctx.send("Server unlocked")
|
||||||
|
|
|
@ -4,7 +4,7 @@ from discord.utils import get
|
||||||
from discord_slash import SlashContext, cog_ext
|
from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.utils.manage_commands import create_option
|
from discord_slash.utils.manage_commands import create_option
|
||||||
|
|
||||||
from jarvis.db.types import Mute, Setting
|
from jarvis.db.models import Mute, Setting
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
from jarvis.utils.permissions import admin_or_permissions
|
from jarvis.utils.permissions import admin_or_permissions
|
||||||
|
@ -32,7 +32,7 @@ class MuteCog(commands.Cog):
|
||||||
),
|
),
|
||||||
create_option(
|
create_option(
|
||||||
name="duration",
|
name="duration",
|
||||||
description="Mute duration",
|
description="Duration of mute in minutes, default 30",
|
||||||
option_type=4,
|
option_type=4,
|
||||||
required=False,
|
required=False,
|
||||||
),
|
),
|
||||||
|
@ -73,7 +73,7 @@ class MuteCog(commands.Cog):
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
duration=duration,
|
duration=duration,
|
||||||
active=True if duration >= 0 else False,
|
active=True if duration >= 0 else False,
|
||||||
).insert()
|
).save()
|
||||||
|
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="User Muted",
|
title="User Muted",
|
||||||
|
@ -102,7 +102,9 @@ class MuteCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(mute_members=True)
|
@admin_or_permissions(mute_members=True)
|
||||||
async def _unmute(self, ctx: SlashContext, user: Member):
|
async def _unmute(self, ctx: SlashContext, user: Member):
|
||||||
mute_setting = Setting.get(guild=ctx.guild.id, setting="mute")
|
mute_setting = Setting.objects(
|
||||||
|
guild=ctx.guild.id, setting="mute"
|
||||||
|
).first()
|
||||||
if not mute_setting:
|
if not mute_setting:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"Please configure a mute role with "
|
"Please configure a mute role with "
|
||||||
|
@ -118,12 +120,11 @@ class MuteCog(commands.Cog):
|
||||||
await ctx.send("User is not muted.", hidden=True)
|
await ctx.send("User is not muted.", hidden=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
mutes = Mute.get_many(guild=ctx.guild.id, user=user.id)
|
_ = Mute.objects(guild=ctx.guild.id, user=user.id).update(
|
||||||
for mute in mutes:
|
set__active=False
|
||||||
mute.active = False
|
)
|
||||||
mute.update()
|
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="User Unmwaruted",
|
title="User Unmuted",
|
||||||
description=f"{user.mention} has been unmuted",
|
description=f"{user.mention} has been unmuted",
|
||||||
fields=[],
|
fields=[],
|
||||||
)
|
)
|
||||||
|
|
|
@ -39,7 +39,7 @@ class PurgeCog(commands.Cog):
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
admin=ctx.author.id,
|
admin=ctx.author.id,
|
||||||
count=amount,
|
count=amount,
|
||||||
).insert()
|
).save()
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
base="autopurge",
|
base="autopurge",
|
||||||
|
@ -73,17 +73,18 @@ class PurgeCog(commands.Cog):
|
||||||
elif delay > 300:
|
elif delay > 300:
|
||||||
await ctx.send("Delay must be < 5 minutes", hidden=True)
|
await ctx.send("Delay must be < 5 minutes", hidden=True)
|
||||||
return
|
return
|
||||||
autopurge = Autopurge.get(guild=ctx.guild.id, channel=channel.id)
|
autopurge = Autopurge.objects(
|
||||||
|
guild=ctx.guild.id, channel=channel.id
|
||||||
|
).first()
|
||||||
if autopurge:
|
if autopurge:
|
||||||
await ctx.send("Autopurge already exists.", hidden=True)
|
await ctx.send("Autopurge already exists.", hidden=True)
|
||||||
return
|
return
|
||||||
autopurge = Autopurge(
|
_ = Autopurge(
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
channel=channel.id,
|
channel=channel.id,
|
||||||
admin=ctx.author.id,
|
admin=ctx.author.id,
|
||||||
delay=delay,
|
delay=delay,
|
||||||
)
|
).save()
|
||||||
autopurge.insert()
|
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Autopurge set up on {channel.mention}, "
|
f"Autopurge set up on {channel.mention}, "
|
||||||
+ f"delay is {delay} seconds"
|
+ f"delay is {delay} seconds"
|
||||||
|
@ -104,7 +105,7 @@ class PurgeCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_messages=True)
|
@admin_or_permissions(manage_messages=True)
|
||||||
async def _autopurge_remove(self, ctx: SlashContext, channel: TextChannel):
|
async def _autopurge_remove(self, ctx: SlashContext, channel: TextChannel):
|
||||||
autopurge = Autopurge.get(guild=ctx.guild.id, channel=channel.id)
|
autopurge = Autopurge.objects(guild=ctx.guild.id, channel=channel.id)
|
||||||
if not autopurge:
|
if not autopurge:
|
||||||
await ctx.send("Autopurge does not exist.", hidden=True)
|
await ctx.send("Autopurge does not exist.", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -134,12 +135,12 @@ class PurgeCog(commands.Cog):
|
||||||
async def _autopurge_update(
|
async def _autopurge_update(
|
||||||
self, ctx: SlashContext, channel: TextChannel, delay: int
|
self, ctx: SlashContext, channel: TextChannel, delay: int
|
||||||
):
|
):
|
||||||
autopurge = Autopurge.get(guild=ctx.guild.id, channel=channel.id)
|
autopurge = Autopurge.objects(guild=ctx.guild.id, channel=channel.id)
|
||||||
if not autopurge:
|
if not autopurge:
|
||||||
await ctx.send("Autopurge does not exist.", hidden=True)
|
await ctx.send("Autopurge does not exist.", hidden=True)
|
||||||
return
|
return
|
||||||
autopurge.delay = delay
|
autopurge.delay = delay
|
||||||
autopurge.update()
|
autopurge.save()
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Autopurge delay updated to {delay} seconds on {channel.mention}."
|
f"Autopurge delay updated to {delay} seconds on {channel.mention}."
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,12 +2,11 @@ from datetime import datetime, timedelta
|
||||||
|
|
||||||
from ButtonPaginator import Paginator
|
from ButtonPaginator import Paginator
|
||||||
from discord import Member, Role
|
from discord import Member, Role
|
||||||
from discord.ext import commands
|
|
||||||
from discord_slash import SlashContext, cog_ext
|
from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.model import ButtonStyle
|
from discord_slash.model import ButtonStyle
|
||||||
from discord_slash.utils.manage_commands import create_option
|
from discord_slash.utils.manage_commands import create_option
|
||||||
|
|
||||||
from jarvis.db.types import Roleping
|
from jarvis.db.models import Roleping
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.cachecog import CacheCog
|
from jarvis.utils.cachecog import CacheCog
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
@ -33,23 +32,19 @@ class RolepingCog(CacheCog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _roleping_add(self, ctx: SlashContext, role: Role):
|
async def _roleping_add(self, ctx: SlashContext, role: Role):
|
||||||
roleping = Roleping.get(guild=ctx.guild.id, role=role.id)
|
roleping = Roleping.objects(guild=ctx.guild.id, role=role.id).first()
|
||||||
if not roleping:
|
if roleping:
|
||||||
roleping = Roleping(
|
|
||||||
role=role.id,
|
|
||||||
guild=ctx.guild.id,
|
|
||||||
admin=ctx.author.id,
|
|
||||||
active=True,
|
|
||||||
bypass={"roles": [], "users": []},
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Role `{role.name}` already in roleping.", hidden=True
|
f"Role `{role.name}` already in roleping.", hidden=True
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
_ = Roleping(
|
||||||
roleping.insert()
|
role=role.id,
|
||||||
|
guild=ctx.guild.id,
|
||||||
|
admin=ctx.author.id,
|
||||||
|
active=True,
|
||||||
|
bypass={"roles": [], "users": []},
|
||||||
|
).save()
|
||||||
await ctx.send(f"Role `{role.name}` added to roleping.")
|
await ctx.send(f"Role `{role.name}` added to roleping.")
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
|
@ -67,7 +62,7 @@ class RolepingCog(CacheCog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _roleping_remove(self, ctx: SlashContext, role: Role):
|
async def _roleping_remove(self, ctx: SlashContext, role: Role):
|
||||||
roleping = Roleping.get(guild=ctx.guild.id, role=role.id)
|
roleping = Roleping.objects(guild=ctx.guild.id, role=role.id)
|
||||||
if not roleping:
|
if not roleping:
|
||||||
await ctx.send("Roleping does not exist", hidden=True)
|
await ctx.send("Roleping does not exist", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -91,7 +86,7 @@ class RolepingCog(CacheCog):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
rolepings = Roleping.get_many(guild=ctx.guild.id)
|
rolepings = Roleping.objects(guild=ctx.guild.id)
|
||||||
if not rolepings:
|
if not rolepings:
|
||||||
await ctx.send("No rolepings configured", hidden=True)
|
await ctx.send("No rolepings configured", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -199,7 +194,7 @@ class RolepingCog(CacheCog):
|
||||||
async def _roleping_bypass_user(
|
async def _roleping_bypass_user(
|
||||||
self, ctx: SlashContext, user: Member, rping: Role
|
self, ctx: SlashContext, user: Member, rping: Role
|
||||||
):
|
):
|
||||||
roleping = Roleping.get(guild=ctx.guild.id, role=rping.id)
|
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||||
if not roleping:
|
if not roleping:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Roleping not configured for {rping.mention}", hidden=True
|
f"Roleping not configured for {rping.mention}", hidden=True
|
||||||
|
@ -231,7 +226,7 @@ class RolepingCog(CacheCog):
|
||||||
return
|
return
|
||||||
|
|
||||||
roleping.bypass["users"].append(user.id)
|
roleping.bypass["users"].append(user.id)
|
||||||
roleping.update()
|
roleping.save()
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"{user.nick or user.name} user bypass added for `{rping.name}`"
|
f"{user.nick or user.name} user bypass added for `{rping.name}`"
|
||||||
)
|
)
|
||||||
|
@ -262,7 +257,7 @@ class RolepingCog(CacheCog):
|
||||||
async def _roleping_bypass_role(
|
async def _roleping_bypass_role(
|
||||||
self, ctx: SlashContext, role: Role, rping: Role
|
self, ctx: SlashContext, role: Role, rping: Role
|
||||||
):
|
):
|
||||||
roleping = Roleping.get(guild=ctx.guild.id, role=rping.id)
|
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||||
if not roleping:
|
if not roleping:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Roleping not configured for {rping.mention}", hidden=True
|
f"Roleping not configured for {rping.mention}", hidden=True
|
||||||
|
@ -282,7 +277,7 @@ class RolepingCog(CacheCog):
|
||||||
return
|
return
|
||||||
|
|
||||||
roleping.bypass["roles"].append(role.id)
|
roleping.bypass["roles"].append(role.id)
|
||||||
roleping.update()
|
roleping.save()
|
||||||
await ctx.send(f"{role.name} role bypass added for `{rping.name}`")
|
await ctx.send(f"{role.name} role bypass added for `{rping.name}`")
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
|
@ -311,7 +306,7 @@ class RolepingCog(CacheCog):
|
||||||
async def _roleping_restore_user(
|
async def _roleping_restore_user(
|
||||||
self, ctx: SlashContext, user: Member, rping: Role
|
self, ctx: SlashContext, user: Member, rping: Role
|
||||||
):
|
):
|
||||||
roleping = Roleping.get(guild=ctx.guild.id, role=rping.id)
|
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||||
if not roleping:
|
if not roleping:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Roleping not configured for {rping.mention}", hidden=True
|
f"Roleping not configured for {rping.mention}", hidden=True
|
||||||
|
@ -323,7 +318,7 @@ class RolepingCog(CacheCog):
|
||||||
return
|
return
|
||||||
|
|
||||||
roleping.bypass["users"].delete(user.id)
|
roleping.bypass["users"].delete(user.id)
|
||||||
roleping.update()
|
roleping.save()
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"{user.nick or user.name} user bypass removed for `{rping.name}`"
|
f"{user.nick or user.name} user bypass removed for `{rping.name}`"
|
||||||
)
|
)
|
||||||
|
@ -354,7 +349,7 @@ class RolepingCog(CacheCog):
|
||||||
async def _roleping_restore_role(
|
async def _roleping_restore_role(
|
||||||
self, ctx: SlashContext, role: Role, rping: Role
|
self, ctx: SlashContext, role: Role, rping: Role
|
||||||
):
|
):
|
||||||
roleping = Roleping.get(guild=ctx.guild.id, role=rping.id)
|
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||||
if not roleping:
|
if not roleping:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Roleping not configured for {rping.mention}", hidden=True
|
f"Roleping not configured for {rping.mention}", hidden=True
|
||||||
|
@ -374,5 +369,5 @@ class RolepingCog(CacheCog):
|
||||||
return
|
return
|
||||||
|
|
||||||
roleping.bypass["roles"].append(role.id)
|
roleping.bypass["roles"].append(role.id)
|
||||||
roleping.update()
|
roleping.save()
|
||||||
await ctx.send(f"{role.name} role bypass added for `{rping.name}`")
|
await ctx.send(f"{role.name} role bypass added for `{rping.name}`")
|
||||||
|
|
|
@ -2,12 +2,11 @@ from datetime import datetime, timedelta
|
||||||
|
|
||||||
from ButtonPaginator import Paginator
|
from ButtonPaginator import Paginator
|
||||||
from discord import User
|
from discord import User
|
||||||
from discord.ext import commands
|
|
||||||
from discord_slash import SlashContext, cog_ext
|
from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.model import ButtonStyle
|
from discord_slash.model import ButtonStyle
|
||||||
from discord_slash.utils.manage_commands import create_choice, create_option
|
from discord_slash.utils.manage_commands import create_choice, create_option
|
||||||
|
|
||||||
from jarvis.db.types import MongoSort, Warning
|
from jarvis.db.models import Warning
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.cachecog import CacheCog
|
from jarvis.utils.cachecog import CacheCog
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
@ -63,7 +62,7 @@ class WarningCog(CacheCog):
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
duration=duration,
|
duration=duration,
|
||||||
active=True,
|
active=True,
|
||||||
).insert()
|
).save()
|
||||||
fields = [Field("Reason", reason, False)]
|
fields = [Field("Reason", reason, False)]
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="Warning",
|
title="Warning",
|
||||||
|
@ -112,19 +111,20 @@ class WarningCog(CacheCog):
|
||||||
hidden=True,
|
hidden=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
warnings = Warning.get_many(
|
warnings = Warning.objects(
|
||||||
user=user.id,
|
user=user.id,
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
sort=MongoSort(direction="desc", key="created_at"),
|
).order_by("-created_at")
|
||||||
)
|
active_warns = Warning.objects(
|
||||||
active_warns = list(filter(lambda x: x.active, warnings))
|
user=user.id, guild=ctx.guild.id, active=False
|
||||||
|
).order_by("-created_at")
|
||||||
|
|
||||||
pages = []
|
pages = []
|
||||||
if active:
|
if active:
|
||||||
if len(active_warns) == 0:
|
if active_warns.count() == 0:
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="Warnings",
|
title="Warnings",
|
||||||
description=f"{len(warnings)} total | 0 currently active",
|
description=f"{warnings.count()} total | 0 currently active",
|
||||||
fields=[],
|
fields=[],
|
||||||
)
|
)
|
||||||
embed.set_author(name=user.name, icon_url=user.avatar_url)
|
embed.set_author(name=user.name, icon_url=user.avatar_url)
|
||||||
|
@ -151,8 +151,8 @@ class WarningCog(CacheCog):
|
||||||
for i in range(0, len(fields), 5):
|
for i in range(0, len(fields), 5):
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="Warnings",
|
title="Warnings",
|
||||||
description=f"{len(warnings)} total | "
|
description=f"{warnings.count()} total | "
|
||||||
+ f"{len(active_warns)} currently active",
|
+ f"{active_warns.count()} currently active",
|
||||||
fields=fields[i : i + 5],
|
fields=fields[i : i + 5],
|
||||||
)
|
)
|
||||||
embed.set_author(
|
embed.set_author(
|
||||||
|
@ -179,8 +179,8 @@ class WarningCog(CacheCog):
|
||||||
for i in range(0, len(fields), 5):
|
for i in range(0, len(fields), 5):
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="Warnings",
|
title="Warnings",
|
||||||
description=f"{len(warnings)} total | "
|
description=f"{warnings.count()} total | "
|
||||||
+ f"{len(active_warns)} currently active",
|
+ f"{active_warns.count()} currently active",
|
||||||
fields=fields[i : i + 5],
|
fields=fields[i : i + 5],
|
||||||
)
|
)
|
||||||
embed.set_author(
|
embed.set_author(
|
||||||
|
|
|
@ -7,7 +7,7 @@ from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.utils.manage_commands import create_option
|
from discord_slash.utils.manage_commands import create_option
|
||||||
|
|
||||||
from jarvis.data.unicode import emoji_list
|
from jarvis.data.unicode import emoji_list
|
||||||
from jarvis.db.types import Autoreact
|
from jarvis.db.models import Autoreact
|
||||||
from jarvis.utils.permissions import admin_or_permissions
|
from jarvis.utils.permissions import admin_or_permissions
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,20 +34,21 @@ class AutoReactCog(commands.Cog):
|
||||||
if not isinstance(channel, TextChannel):
|
if not isinstance(channel, TextChannel):
|
||||||
await ctx.send("Channel must be a text channel", hidden=True)
|
await ctx.send("Channel must be a text channel", hidden=True)
|
||||||
return
|
return
|
||||||
exists = Autoreact.get(guild=ctx.guild.id, channel=channel.id)
|
exists = Autoreact.objects(
|
||||||
|
guild=ctx.guild.id, channel=channel.id
|
||||||
|
).first()
|
||||||
if exists:
|
if exists:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Autoreact already exists for {channel.mention}.", hidden=True
|
f"Autoreact already exists for {channel.mention}.", hidden=True
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
autoreact = Autoreact(
|
_ = Autoreact(
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
channel=channel.id,
|
channel=channel.id,
|
||||||
reactions=[],
|
reactions=[],
|
||||||
admin=ctx.author.id,
|
admin=ctx.author.id,
|
||||||
)
|
).save()
|
||||||
autoreact.insert()
|
|
||||||
await ctx.send(f"Autoreact created for {channel.mention}!")
|
await ctx.send(f"Autoreact created for {channel.mention}!")
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
|
@ -65,7 +66,9 @@ class AutoReactCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _autoreact_delete(self, ctx, channel: TextChannel):
|
async def _autoreact_delete(self, ctx, channel: TextChannel):
|
||||||
exists = Autoreact.get(guild=ctx.guild.id, channel=channel.id).delete()
|
exists = Autoreact.objects(
|
||||||
|
guild=ctx.guild.id, channel=channel.id
|
||||||
|
).delete()
|
||||||
if exists:
|
if exists:
|
||||||
await ctx.send(f"Autoreact removed from {channel.mention}")
|
await ctx.send(f"Autoreact removed from {channel.mention}")
|
||||||
else:
|
else:
|
||||||
|
@ -111,7 +114,9 @@ class AutoReactCog(commands.Cog):
|
||||||
"Please use a custom emote from this server.", hidden=True
|
"Please use a custom emote from this server.", hidden=True
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
exists = Autoreact.get(guild=ctx.guild.id, channel=channel.id)
|
exists = Autoreact.objects(
|
||||||
|
guild=ctx.guild.id, channel=channel.id
|
||||||
|
).first()
|
||||||
if not exists:
|
if not exists:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"Please create autoreact first with "
|
"Please create autoreact first with "
|
||||||
|
@ -132,7 +137,7 @@ class AutoReactCog(commands.Cog):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
exists.reactions.append(emote)
|
exists.reactions.append(emote)
|
||||||
exists.update()
|
exists.save()
|
||||||
await ctx.send(f"Added {emote} to {channel.mention} autoreact.")
|
await ctx.send(f"Added {emote} to {channel.mention} autoreact.")
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
|
@ -156,7 +161,9 @@ class AutoReactCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _autoreact_remove(self, ctx, channel: TextChannel, emote: str):
|
async def _autoreact_remove(self, ctx, channel: TextChannel, emote: str):
|
||||||
exists = Autoreact.get(guild=ctx.guild.id, channel=channel.id)
|
exists = Autoreact.objects(
|
||||||
|
guild=ctx.guild.id, channel=channel.id
|
||||||
|
).first()
|
||||||
if not exists:
|
if not exists:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"Please create autoreact first with "
|
"Please create autoreact first with "
|
||||||
|
@ -171,7 +178,7 @@ class AutoReactCog(commands.Cog):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
exists.reactions.remove(emote)
|
exists.reactions.remove(emote)
|
||||||
exists.update()
|
exists.save()
|
||||||
await ctx.send(f"Removed {emote} from {channel.mention} autoreact.")
|
await ctx.send(f"Removed {emote} from {channel.mention} autoreact.")
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
|
@ -189,7 +196,9 @@ class AutoReactCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _autoreact_list(self, ctx, channel: TextChannel):
|
async def _autoreact_list(self, ctx, channel: TextChannel):
|
||||||
exists = Autoreact.get(guild=ctx.guild.id, channel=channel.id)
|
exists = Autoreact.objects(
|
||||||
|
guild=ctx.guild.id, channel=channel.id
|
||||||
|
).first()
|
||||||
if not exists:
|
if not exists:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"Please create autoreact first with "
|
"Please create autoreact first with "
|
||||||
|
|
|
@ -11,8 +11,7 @@ from discord.utils import find
|
||||||
from discord_slash import SlashContext, cog_ext
|
from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.model import ButtonStyle
|
from discord_slash.model import ButtonStyle
|
||||||
|
|
||||||
from jarvis.config import get_config
|
from jarvis.db.models import Guess
|
||||||
from jarvis.db import DBManager
|
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.cachecog import CacheCog
|
from jarvis.utils.cachecog import CacheCog
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
@ -29,8 +28,6 @@ invites = re.compile(
|
||||||
class CTCCog(CacheCog):
|
class CTCCog(CacheCog):
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
super().__init__(bot)
|
super().__init__(bot)
|
||||||
mconf = get_config().mongo
|
|
||||||
self.db = DBManager(mconf["connect"]).mongo
|
|
||||||
self._session = aiohttp.ClientSession()
|
self._session = aiohttp.ClientSession()
|
||||||
self.url = "https://completethecodetwo.cards/pw"
|
self.url = "https://completethecodetwo.cards/pw"
|
||||||
|
|
||||||
|
@ -73,7 +70,7 @@ class CTCCog(CacheCog):
|
||||||
hidden=True,
|
hidden=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
guessed = self.db.ctc2.guesses.find_one({"guess": guess})
|
guessed = Guess.objects(guess=guess).first()
|
||||||
if guessed:
|
if guessed:
|
||||||
await ctx.send("Already guessed, dipshit.", hidden=True)
|
await ctx.send("Already guessed, dipshit.", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -86,9 +83,7 @@ class CTCCog(CacheCog):
|
||||||
correct = True
|
correct = True
|
||||||
else:
|
else:
|
||||||
await ctx.send("Nope.", hidden=True)
|
await ctx.send("Nope.", hidden=True)
|
||||||
self.db.ctc2.guesses.insert_one(
|
_ = Guess(guess=guess, user=ctx.author.id, correct=correct).save()
|
||||||
{"guess": guess, "user": ctx.author.id, "correct": correct}
|
|
||||||
)
|
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
base="ctc2",
|
base="ctc2",
|
||||||
|
@ -107,17 +102,16 @@ class CTCCog(CacheCog):
|
||||||
hidden=True,
|
hidden=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
guesses = self.db.ctc2.guesses.find().sort(
|
|
||||||
[("correct", pymongo.DESCENDING), ("_id", pymongo.DESCENDING)]
|
guesses = Guess.objects().order_by("-correct", "-id")
|
||||||
)
|
|
||||||
fields = []
|
fields = []
|
||||||
for guess in guesses:
|
for guess in guesses:
|
||||||
user = ctx.guild.get_member(guess["user"])
|
user = ctx.guild.get_member(guess["user"])
|
||||||
if not user:
|
if not user:
|
||||||
user = self.bot.fetch_user(guess["user"])
|
user = await self.bot.fetch_user(guess["user"])
|
||||||
if not user:
|
if not user:
|
||||||
user = "[redacted]"
|
user = "[redacted]"
|
||||||
if isinstance(user, User) or isinstance(user, Member):
|
if isinstance(user, (Member, User)):
|
||||||
user = user.name + "#" + user.discriminator
|
user = user.name + "#" + user.discriminator
|
||||||
name = "Correctly" if guess["correct"] else "Incorrectly"
|
name = "Correctly" if guess["correct"] else "Incorrectly"
|
||||||
name += " guessed by: " + user
|
name += " guessed by: " + user
|
||||||
|
|
|
@ -2,12 +2,13 @@ import base64
|
||||||
import hashlib
|
import hashlib
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import uuid
|
import uuid as uuidpy
|
||||||
|
|
||||||
import ulid
|
import ulid as ulidpy
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord_slash import cog_ext
|
from discord_slash import cog_ext
|
||||||
|
from discord_slash.utils.manage_commands import create_choice, create_option
|
||||||
|
|
||||||
from jarvis.utils import build_embed, convert_bytesize
|
from jarvis.utils import build_embed, convert_bytesize
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
@ -39,7 +40,12 @@ UUID_VERIFY = re.compile(
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
)
|
)
|
||||||
|
|
||||||
UUID_GET = {3: uuid.uuid3, 5: uuid.uuid5}
|
invites = re.compile(
|
||||||
|
r"(?:https?://)?(?:www.)?(?:discord.(?:gg|io|me|li)|discord(?:app)?.com/invite)/([^\s/]+?)(?=\b)",
|
||||||
|
flags=re.IGNORECASE,
|
||||||
|
)
|
||||||
|
|
||||||
|
UUID_GET = {3: uuidpy.uuid3, 5: uuidpy.uuid5}
|
||||||
|
|
||||||
|
|
||||||
def hash_obj(hash, data, text: bool = True) -> str:
|
def hash_obj(hash, data, text: bool = True) -> str:
|
||||||
|
@ -64,24 +70,36 @@ class DevCog(commands.Cog):
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
async def _hash(self, ctx, method: str, *, data: str = None):
|
@cog_ext.cog_slash(
|
||||||
if method not in supported_hashes:
|
name="hash",
|
||||||
algo_txt = ", ".join(f"`{x}`" for x in supported_hashes)
|
description="Hash some data",
|
||||||
|
options=[
|
||||||
|
create_option(
|
||||||
|
name="method",
|
||||||
|
description="Hash method",
|
||||||
|
option_type=3,
|
||||||
|
required=True,
|
||||||
|
choices=[
|
||||||
|
create_choice(name=x, value=x) for x in supported_hashes
|
||||||
|
],
|
||||||
|
),
|
||||||
|
create_option(
|
||||||
|
name="data",
|
||||||
|
description="Data to hash",
|
||||||
|
option_type=3,
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||||
|
async def _hash(self, ctx, method: str, data: str):
|
||||||
|
if not data:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"Unsupported hash algorithm. Supported:\n" + algo_txt,
|
"No data to hash",
|
||||||
hidden=True,
|
hidden=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
if not data and len(ctx.message.attachments) == 0:
|
|
||||||
await ctx.send(
|
|
||||||
"No data to hash. Either attach a file or send text to hash"
|
|
||||||
)
|
|
||||||
return
|
|
||||||
text = True
|
text = True
|
||||||
if len(ctx.message.attachments) > 0:
|
|
||||||
text = False
|
|
||||||
data = await ctx.message.attachments[0].read()
|
|
||||||
|
|
||||||
# Default to sha256, just in case
|
# Default to sha256, just in case
|
||||||
hash = getattr(hashlib, method, hashlib.sha256)()
|
hash = getattr(hashlib, method, hashlib.sha256)()
|
||||||
hex = hash_obj(hash, data, text)
|
hex = hash_obj(hash, data, text)
|
||||||
|
@ -98,206 +116,161 @@ class DevCog(commands.Cog):
|
||||||
)
|
)
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
@commands.command(name="hash")
|
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _hash_pref(self, ctx, method: str, *, data: str = None):
|
|
||||||
await self._hash(ctx, method, data=data)
|
|
||||||
|
|
||||||
@cog_ext.cog_slash(
|
@cog_ext.cog_slash(
|
||||||
name="hash",
|
name="uuid",
|
||||||
description="Hash some data",
|
description="Generate a UUID",
|
||||||
|
options=[
|
||||||
|
create_option(
|
||||||
|
name="version",
|
||||||
|
description="UUID version",
|
||||||
|
option_type=3,
|
||||||
|
required=True,
|
||||||
|
choices=[
|
||||||
|
create_choice(name=x, value=x) for x in ["3", "4", "5"]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
create_option(
|
||||||
|
name="data",
|
||||||
|
description="Data for UUID version 3,5",
|
||||||
|
option_type=3,
|
||||||
|
required=False,
|
||||||
|
),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
async def _uuid(self, ctx, version: str, data: str = None):
|
||||||
async def _hash_slash(self, ctx, method: str, *, data: str = None):
|
|
||||||
await self._hash(ctx, method, data=data)
|
|
||||||
|
|
||||||
async def _uuid(self, ctx, version: str = None, data: str = None):
|
|
||||||
if not version:
|
|
||||||
await ctx.send("Supported UUID versions: 3, 4, 5", hidden=True)
|
|
||||||
return
|
|
||||||
if version not in ["3", "4", "5"]:
|
|
||||||
await ctx.send("Supported UUID versions: 3, 4, 5", hidden=True)
|
|
||||||
return
|
|
||||||
version = int(version)
|
version = int(version)
|
||||||
if version in [3, 5] and not data:
|
if version in [3, 5] and not data:
|
||||||
await ctx.send(f"UUID{version} requires data.", hidden=True)
|
await ctx.send(f"UUID{version} requires data.", hidden=True)
|
||||||
return
|
return
|
||||||
if version == 4:
|
if version == 4:
|
||||||
await ctx.send(f"UUID4: `{uuid.uuid4()}`")
|
await ctx.send(f"UUID4: `{uuidpy.uuid4()}`")
|
||||||
else:
|
else:
|
||||||
to_send = None
|
to_send = None
|
||||||
if OID_VERIFY.match(data):
|
if OID_VERIFY.match(data):
|
||||||
to_send = UUID_GET[version](uuid.NAMESPACE_OID, data)
|
to_send = UUID_GET[version](uuidpy.NAMESPACE_OID, data)
|
||||||
elif URL_VERIFY.match(data):
|
elif URL_VERIFY.match(data):
|
||||||
to_send = UUID_GET[version](uuid.NAMESPACE_URL, data)
|
to_send = UUID_GET[version](uuidpy.NAMESPACE_URL, data)
|
||||||
elif DN_VERIFY.match(data):
|
elif DN_VERIFY.match(data):
|
||||||
to_send = UUID_GET[version](uuid.NAMESPACE_X500, data)
|
to_send = UUID_GET[version](uuidpy.NAMESPACE_X500, data)
|
||||||
else:
|
else:
|
||||||
to_send = UUID_GET[version](uuid.NAMESPACE_DNS, data)
|
to_send = UUID_GET[version](uuidpy.NAMESPACE_DNS, data)
|
||||||
await ctx.send(f"UUID{version}: `{to_send}`")
|
await ctx.send(f"UUID{version}: `{to_send}`")
|
||||||
|
|
||||||
@commands.command(name="uuid")
|
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _uuid_pref(self, ctx, version: str = None, data: str = None):
|
|
||||||
await self._uuid(ctx, version, data)
|
|
||||||
|
|
||||||
@cog_ext.cog_slash(
|
|
||||||
name="uuid",
|
|
||||||
description="Generate a UUID",
|
|
||||||
)
|
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _uuid_slash(self, ctx, version: str = None, data: str = None):
|
|
||||||
await self._uuid(ctx, version, data)
|
|
||||||
|
|
||||||
async def _objectid(self, ctx):
|
|
||||||
"""Generates new bson.ObjectId"""
|
|
||||||
await ctx.send(f"ObjectId: `{str(ObjectId())}`")
|
|
||||||
|
|
||||||
@commands.command(name="objectid")
|
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _objectid_pref(self, ctx):
|
|
||||||
await self._objectid(ctx)
|
|
||||||
|
|
||||||
@cog_ext.cog_slash(
|
@cog_ext.cog_slash(
|
||||||
name="objectid",
|
name="objectid",
|
||||||
description="Generate an ObjectID",
|
description="Generate an ObjectID",
|
||||||
)
|
)
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||||
async def _objectid_slash(self, ctx):
|
async def _objectid(self, ctx):
|
||||||
await self._objectid(ctx)
|
"""Generates new bson.ObjectId"""
|
||||||
|
await ctx.send(f"ObjectId: `{str(ObjectId())}`")
|
||||||
async def _ulid(self, ctx):
|
|
||||||
"""Generates a new ULID"""
|
|
||||||
await ctx.send(f"ULID: `{ulid.new().str}`")
|
|
||||||
|
|
||||||
@commands.command(name="ulid")
|
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _ulid_pref(self, ctx):
|
|
||||||
await self._ulid(ctx)
|
|
||||||
|
|
||||||
@cog_ext.cog_slash(
|
@cog_ext.cog_slash(
|
||||||
name="ulid",
|
name="ulid",
|
||||||
description="Generate a ULID",
|
description="Generate a ULID",
|
||||||
)
|
)
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||||
async def _ulid_slash(self, ctx):
|
async def _ulid(self, ctx):
|
||||||
await self._ulid(ctx)
|
"""Generates a new ULID"""
|
||||||
|
await ctx.send(f"ULID: `{ulidpy.new().str}`")
|
||||||
async def _uuid2ulid(self, ctx: commands.Context, u):
|
|
||||||
"""Converts a UUID to a ULID"""
|
|
||||||
if UUID_VERIFY.match(u):
|
|
||||||
u = ulid.parse(u)
|
|
||||||
await ctx.send(f"ULID: `{u.str}`")
|
|
||||||
else:
|
|
||||||
await ctx.send("Invalid UUID")
|
|
||||||
|
|
||||||
@commands.command(name="uuid2ulid")
|
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _uuid2ulid_pref(self, ctx, u: str):
|
|
||||||
await self._uuid2ulid(ctx, u)
|
|
||||||
|
|
||||||
@cog_ext.cog_slash(
|
@cog_ext.cog_slash(
|
||||||
name="uuid2ulid",
|
name="uuid2ulid",
|
||||||
description="Convert a UUID to a ULID",
|
description="Convert a UUID to a ULID",
|
||||||
)
|
)
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||||
async def _uuid2ulid_slash(self, ctx, u: str):
|
async def _uuid2ulid(self, ctx: commands.Context, uuid):
|
||||||
await self._uuid2ulid(ctx, u)
|
"""Converts a UUID to a ULID"""
|
||||||
|
if UUID_VERIFY.match(uuid):
|
||||||
async def _ulid2uuid(self, ctx: commands.Context, u):
|
u = ulidpy.parse(uuid)
|
||||||
"""Converts a ULID to a UUID"""
|
await ctx.send(f"ULID: `{u.str}`")
|
||||||
if ULID_VERIFY.match(u):
|
|
||||||
u = ulid.parse(u)
|
|
||||||
await ctx.send(f"UUID: `{u.uuid}`")
|
|
||||||
else:
|
else:
|
||||||
await ctx.send("Invalid ULID.")
|
await ctx.send("Invalid UUID")
|
||||||
|
|
||||||
@commands.command(name="ulid2uuid")
|
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _ulid2uuid_pref(self, ctx, u):
|
|
||||||
await self._ulid2uuid(ctx, u)
|
|
||||||
|
|
||||||
@cog_ext.cog_slash(
|
@cog_ext.cog_slash(
|
||||||
name="ulid2uuid",
|
name="ulid2uuid",
|
||||||
description="Convert a ULID to a UUID",
|
description="Convert a ULID to a UUID",
|
||||||
)
|
)
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||||
async def _ulid2uuid_slash(self, ctx, u):
|
async def _ulid2uuid(self, ctx: commands.Context, ulid):
|
||||||
await self._ulid2uuid(ctx, u)
|
"""Converts a ULID to a UUID"""
|
||||||
|
if ULID_VERIFY.match(ulid):
|
||||||
|
ulid = ulidpy.parse(ulid)
|
||||||
|
await ctx.send(f"UUID: `{ulid.uuid}`")
|
||||||
|
else:
|
||||||
|
await ctx.send("Invalid ULID.")
|
||||||
|
|
||||||
base64_methods = ["b64", "b16", "b32", "a85", "b85"]
|
base64_methods = ["b64", "b16", "b32", "a85", "b85"]
|
||||||
|
|
||||||
|
@cog_ext.cog_slash(
|
||||||
|
name="encode",
|
||||||
|
description="Encode some data",
|
||||||
|
options=[
|
||||||
|
create_option(
|
||||||
|
name="method",
|
||||||
|
description="Encode method",
|
||||||
|
option_type=3,
|
||||||
|
required=True,
|
||||||
|
choices=[
|
||||||
|
create_choice(name=x, value=x) for x in base64_methods
|
||||||
|
],
|
||||||
|
),
|
||||||
|
create_option(
|
||||||
|
name="data",
|
||||||
|
description="Data to encode",
|
||||||
|
option_type=3,
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
async def _encode(self, ctx, method: str, data: str):
|
async def _encode(self, ctx, method: str, data: str):
|
||||||
"""Encodes text with specified encoding method"""
|
"""Encodes text with specified encoding method"""
|
||||||
if method not in self.base64_methods:
|
|
||||||
methods = ", ".join(f"`{x}`" for x in self.base64_methods)
|
|
||||||
await ctx.send(
|
|
||||||
"Usage: encode <method> <data>\nSupported methods:\n"
|
|
||||||
+ methods,
|
|
||||||
hidden=True,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
method = getattr(base64, method + "encode")
|
method = getattr(base64, method + "encode")
|
||||||
await ctx.send(f"`{method(data.encode('UTF-8')).decode('UTF-8')}`")
|
await ctx.send(f"`{method(data.encode('UTF-8')).decode('UTF-8')}`")
|
||||||
|
|
||||||
@commands.command(name="encode")
|
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _encode_pref(self, ctx, method: str, *, data: str):
|
|
||||||
await self._encode(ctx, method, data)
|
|
||||||
|
|
||||||
@cog_ext.cog_slash(
|
@cog_ext.cog_slash(
|
||||||
name="encode",
|
name="decode",
|
||||||
description="Encode using the base64 module",
|
description="Decode some data",
|
||||||
|
options=[
|
||||||
|
create_option(
|
||||||
|
name="method",
|
||||||
|
description="Decode method",
|
||||||
|
option_type=3,
|
||||||
|
required=True,
|
||||||
|
choices=[
|
||||||
|
create_choice(name=x, value=x) for x in base64_methods
|
||||||
|
],
|
||||||
|
),
|
||||||
|
create_option(
|
||||||
|
name="data",
|
||||||
|
description="Data to encode",
|
||||||
|
option_type=3,
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _encode_slash(self, ctx, method: str, *, data: str):
|
|
||||||
await self._encode(ctx, method, data)
|
|
||||||
|
|
||||||
async def _decode(self, ctx, method: str, data: str):
|
async def _decode(self, ctx, method: str, data: str):
|
||||||
"""Decodes text with specified encoding method"""
|
"""Decodes text with specified encoding method"""
|
||||||
if method not in self.base64_methods:
|
method = getattr(base64, method + "decode")
|
||||||
methods = ", ".join(f"`{x}`" for x in self.base64_methods)
|
decoded = method(data.encode("UTF-8")).decode("UTF-8")
|
||||||
|
if invites.search(decoded):
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"Usage: decode <method> <data>\nSupported methods:\n"
|
"Please don't use this to bypass invite restrictions",
|
||||||
+ methods,
|
|
||||||
hidden=True,
|
hidden=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
method = getattr(base64, method + "decode")
|
await ctx.send(f"`{decoded}`")
|
||||||
await ctx.send(f"`{method(data.encode('UTF-8')).decode('UTF-8')}`")
|
|
||||||
|
|
||||||
@commands.command(name="decode")
|
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _decode_pref(self, ctx, method: str, *, data: str):
|
|
||||||
await self._decode(ctx, method, data)
|
|
||||||
|
|
||||||
@cog_ext.cog_slash(
|
|
||||||
name="decode",
|
|
||||||
description="Decode using the base64 module",
|
|
||||||
)
|
|
||||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
|
||||||
async def _decode_slash(self, ctx, method: str, *, data: str):
|
|
||||||
await self._decode(ctx, method, data)
|
|
||||||
|
|
||||||
async def _cloc(self, ctx):
|
|
||||||
output = subprocess.check_output(
|
|
||||||
["tokei", "-C", "--sort", "code"]
|
|
||||||
).decode("UTF-8")
|
|
||||||
await ctx.send(f"```\n{output}\n```")
|
|
||||||
|
|
||||||
@commands.command(name="cloc", help="Get J.A.R.V.I.S. lines of code")
|
|
||||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
|
||||||
async def _cloc_pref(self, ctx):
|
|
||||||
await self._cloc(ctx)
|
|
||||||
|
|
||||||
@cog_ext.cog_slash(
|
@cog_ext.cog_slash(
|
||||||
name="cloc",
|
name="cloc",
|
||||||
description="Get J.A.R.V.I.S. lines of code",
|
description="Get J.A.R.V.I.S. lines of code",
|
||||||
)
|
)
|
||||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||||
async def _cloc_slash(self, ctx):
|
async def _cloc(self, ctx):
|
||||||
await ctx.defer()
|
output = subprocess.check_output(
|
||||||
await self._cloc(ctx)
|
["tokei", "-C", "--sort", "code"]
|
||||||
|
).decode("UTF-8")
|
||||||
|
await ctx.send(f"```\n{output}\n```")
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord_slash import SlashContext
|
from discord_slash import SlashContext
|
||||||
|
|
||||||
|
from jarvis import slash
|
||||||
|
|
||||||
|
|
||||||
class ErrorHandlerCog(commands.Cog):
|
class ErrorHandlerCog(commands.Cog):
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
|
@ -40,7 +42,7 @@ class ErrorHandlerCog(commands.Cog):
|
||||||
f"Error processing command:\n```{error}```",
|
f"Error processing command:\n```{error}```",
|
||||||
hidden=True,
|
hidden=True,
|
||||||
)
|
)
|
||||||
ctx.slash.commands[ctx.command].reset_cooldown(ctx)
|
slash.commands[ctx.command].reset_cooldown(ctx)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
|
|
|
@ -8,8 +8,7 @@ from discord.ext import commands
|
||||||
from discord_slash import cog_ext
|
from discord_slash import cog_ext
|
||||||
|
|
||||||
import jarvis
|
import jarvis
|
||||||
from jarvis.config import get_config
|
from jarvis.db.models import Joke
|
||||||
from jarvis.db import DBManager
|
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
|
||||||
|
@ -23,10 +22,6 @@ class JokeCog(commands.Cog):
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
config = get_config()
|
|
||||||
self.db = DBManager(config.mongo["connect"]).mongo[
|
|
||||||
config.mongo["database"]
|
|
||||||
]
|
|
||||||
|
|
||||||
# TODO: Make this a command group with subcommands
|
# TODO: Make this a command group with subcommands
|
||||||
async def _joke(self, ctx, id: str = None):
|
async def _joke(self, ctx, id: str = None):
|
||||||
|
@ -36,48 +31,35 @@ class JokeCog(commands.Cog):
|
||||||
return
|
return
|
||||||
# TODO: Add this as a parameter that can be passed in
|
# TODO: Add this as a parameter that can be passed in
|
||||||
threshold = 500 # Minimum score
|
threshold = 500 # Minimum score
|
||||||
coll = self.db.jokes
|
|
||||||
result = None
|
result = None
|
||||||
if id:
|
if id:
|
||||||
result = coll.find_one({"id": id})
|
result = Joke.objects(rid=id).first()
|
||||||
else:
|
else:
|
||||||
result = list(
|
pipeline = [
|
||||||
coll.aggregate(
|
{"$match": {"score": {"$gt": threshold}}},
|
||||||
[
|
{"$sample": {"size": 1}},
|
||||||
{"$match": {"score": {"$gt": threshold}}},
|
]
|
||||||
{"$sample": {"size": 1}},
|
result = Joke.objects().aggregate(pipeline)
|
||||||
]
|
while result.body in ["[removed]", "[deleted]"]:
|
||||||
)
|
result = Joke.objects().aggregate(pipeline)
|
||||||
)[0]
|
|
||||||
while result["body"] in ["[removed]", "[deleted]"]:
|
|
||||||
result = list(
|
|
||||||
coll.aggregate(
|
|
||||||
[
|
|
||||||
{"$match": {"score": {"$gt": threshold}}},
|
|
||||||
{"$sample": {"size": 1}},
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)[0]
|
|
||||||
|
|
||||||
if result is None:
|
if result is None:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"Humor module failed. Please try again later.", hidden=True
|
"Humor module failed. Please try again later.", hidden=True
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
emotes = re.findall(r"(&#x[a-fA-F0-9]*;)", result["body"])
|
emotes = re.findall(r"(&#x[a-fA-F0-9]*;)", result.body)
|
||||||
for match in emotes:
|
for match in emotes:
|
||||||
result["body"] = result["body"].replace(
|
result.body = result.body.replace(match, html.unescape(match))
|
||||||
match, html.unescape(match)
|
emotes = re.findall(r"(&#x[a-fA-F0-9]*;)", result.title)
|
||||||
)
|
|
||||||
emotes = re.findall(r"(&#x[a-fA-F0-9]*;)", result["title"])
|
|
||||||
for match in emotes:
|
for match in emotes:
|
||||||
result["title"] = result["title"].replace(
|
result.title = result.title.replace(
|
||||||
match, html.unescape(match)
|
match, html.unescape(match)
|
||||||
)
|
)
|
||||||
body_chunks = []
|
body_chunks = []
|
||||||
|
|
||||||
body = ""
|
body = ""
|
||||||
for word in result["body"].split(" "):
|
for word in result.body.split(" "):
|
||||||
if len(body) + 1 + len(word) > 1024:
|
if len(body) + 1 + len(word) > 1024:
|
||||||
body_chunks.append(Field("", body, False))
|
body_chunks.append(Field("", body, False))
|
||||||
body = ""
|
body = ""
|
||||||
|
@ -89,7 +71,7 @@ class JokeCog(commands.Cog):
|
||||||
body += " " + word
|
body += " " + word
|
||||||
|
|
||||||
desc = ""
|
desc = ""
|
||||||
title = result["title"]
|
title = result.title
|
||||||
if len(title) > 256:
|
if len(title) > 256:
|
||||||
new_title = ""
|
new_title = ""
|
||||||
limit = False
|
limit = False
|
||||||
|
@ -106,18 +88,18 @@ class JokeCog(commands.Cog):
|
||||||
body_chunks.append(Field("", body, False))
|
body_chunks.append(Field("", body, False))
|
||||||
|
|
||||||
fields = body_chunks
|
fields = body_chunks
|
||||||
fields.append(Field("Score", result["score"]))
|
fields.append(Field("Score", result.score))
|
||||||
# Field(
|
# Field(
|
||||||
# "Created At",
|
# "Created At",
|
||||||
# str(datetime.fromtimestamp(result["created_utc"])),
|
# str(datetime.fromtimestamp(result["created_utc"])),
|
||||||
# ),
|
# ),
|
||||||
fields.append(Field("ID", result["id"]))
|
fields.append(Field("ID", result.id))
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title=title,
|
title=title,
|
||||||
description=desc,
|
description=desc,
|
||||||
fields=fields,
|
fields=fields,
|
||||||
url=f"https://reddit.com/r/jokes/comments/{result['id']}",
|
url=f"https://reddit.com/r/jokes/comments/{result.rid}",
|
||||||
timestamp=datetime.fromtimestamp(result["created_utc"]),
|
timestamp=datetime.fromtimestamp(result.created_utc),
|
||||||
)
|
)
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
@ -7,7 +7,7 @@ from discord.utils import find
|
||||||
|
|
||||||
from jarvis.cogs.modlog.utils import get_latest_log, modlog_embed
|
from jarvis.cogs.modlog.utils import get_latest_log, modlog_embed
|
||||||
from jarvis.config import get_config
|
from jarvis.config import get_config
|
||||||
from jarvis.db.types import Ban, Kick, MongoSort, Mute, Setting
|
from jarvis.db.models import Ban, Kick, Mute, Setting, Unban
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class ModlogMemberCog(commands.Cog):
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_member_ban(self, guild: discord.Guild, user: discord.User):
|
async def on_member_ban(self, guild: discord.Guild, user: discord.User):
|
||||||
modlog = Setting.get(guild=guild.id, setting="modlog")
|
modlog = Setting.objects(guild=guild.id, setting="modlog").first()
|
||||||
if modlog:
|
if modlog:
|
||||||
channel = guild.get_channel(modlog.value)
|
channel = guild.get_channel(modlog.value)
|
||||||
await asyncio.sleep(0.5) # Need to wait for audit log
|
await asyncio.sleep(0.5) # Need to wait for audit log
|
||||||
|
@ -31,11 +31,14 @@ class ModlogMemberCog(commands.Cog):
|
||||||
log: discord.AuditLogEntry = get_latest_log(auditlog, user)
|
log: discord.AuditLogEntry = get_latest_log(auditlog, user)
|
||||||
admin: discord.User = log.user
|
admin: discord.User = log.user
|
||||||
if admin.id == get_config().client_id:
|
if admin.id == get_config().client_id:
|
||||||
ban = Ban.get(
|
ban = (
|
||||||
guild=guild.id,
|
Ban.objects(
|
||||||
user=user.id,
|
guild=guild.id,
|
||||||
active=True,
|
user=user.id,
|
||||||
sort=MongoSort(key="created_at", direction="desc"),
|
active=True,
|
||||||
|
)
|
||||||
|
.sort("-created_at")
|
||||||
|
.first()
|
||||||
)
|
)
|
||||||
admin = guild.get_member(ban.admin)
|
admin = guild.get_member(ban.admin)
|
||||||
embed = modlog_embed(
|
embed = modlog_embed(
|
||||||
|
@ -50,7 +53,7 @@ class ModlogMemberCog(commands.Cog):
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_member_unban(self, guild: discord.Guild, user: discord.User):
|
async def on_member_unban(self, guild: discord.Guild, user: discord.User):
|
||||||
modlog = Setting.get(guild=guild.id, setting="modlog")
|
modlog = Setting.objects(guild=guild.id, setting="modlog").first()
|
||||||
if modlog:
|
if modlog:
|
||||||
channel = guild.get_channel(modlog.value)
|
channel = guild.get_channel(modlog.value)
|
||||||
await asyncio.sleep(0.5) # Need to wait for audit log
|
await asyncio.sleep(0.5) # Need to wait for audit log
|
||||||
|
@ -63,13 +66,15 @@ class ModlogMemberCog(commands.Cog):
|
||||||
log: discord.AuditLogEntry = get_latest_log(auditlog, user)
|
log: discord.AuditLogEntry = get_latest_log(auditlog, user)
|
||||||
admin: discord.User = log.user
|
admin: discord.User = log.user
|
||||||
if admin.id == get_config().client_id:
|
if admin.id == get_config().client_id:
|
||||||
ban = Ban.get(
|
unban = (
|
||||||
guild=guild.id,
|
Unban.objects(
|
||||||
user=user.id,
|
guild=guild.id,
|
||||||
active=True,
|
user=user.id,
|
||||||
sort=MongoSort(key="created_at", direction="desc"),
|
)
|
||||||
|
.sort("-created_at")
|
||||||
|
.first()
|
||||||
)
|
)
|
||||||
admin = guild.get_member(ban.admin)
|
admin = guild.get_member(unban.admin)
|
||||||
embed = modlog_embed(
|
embed = modlog_embed(
|
||||||
user,
|
user,
|
||||||
admin,
|
admin,
|
||||||
|
@ -82,7 +87,7 @@ class ModlogMemberCog(commands.Cog):
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_member_remove(self, user: discord.User):
|
async def on_member_remove(self, user: discord.User):
|
||||||
modlog = Setting.get(guild=user.guild.id, setting="modlog")
|
modlog = Setting.objects(guild=user.guild.id, setting="modlog").first()
|
||||||
if modlog:
|
if modlog:
|
||||||
channel = user.guild.get_channel(modlog.value)
|
channel = user.guild.get_channel(modlog.value)
|
||||||
await asyncio.sleep(0.5) # Need to wait for audit log
|
await asyncio.sleep(0.5) # Need to wait for audit log
|
||||||
|
@ -95,10 +100,13 @@ class ModlogMemberCog(commands.Cog):
|
||||||
log: discord.AuditLogEntry = get_latest_log(auditlog, user)
|
log: discord.AuditLogEntry = get_latest_log(auditlog, user)
|
||||||
admin: discord.User = log.user
|
admin: discord.User = log.user
|
||||||
if admin.id == get_config().client_id:
|
if admin.id == get_config().client_id:
|
||||||
kick = Kick.get(
|
kick = (
|
||||||
guild=user.guild.id,
|
Kick.objects(
|
||||||
user=user.id,
|
guild=user.guild.id,
|
||||||
sort=MongoSort(key="created_at", direction="desc"),
|
user=user.id,
|
||||||
|
)
|
||||||
|
.sort("-created_at")
|
||||||
|
.first()
|
||||||
)
|
)
|
||||||
admin = user.guild.get_member(kick.admin)
|
admin = user.guild.get_member(kick.admin)
|
||||||
embed = modlog_embed(
|
embed = modlog_embed(
|
||||||
|
@ -122,11 +130,14 @@ class ModlogMemberCog(commands.Cog):
|
||||||
log: discord.AuditLogEntry = get_latest_log(auditlog, before)
|
log: discord.AuditLogEntry = get_latest_log(auditlog, before)
|
||||||
admin: discord.User = log.user
|
admin: discord.User = log.user
|
||||||
if admin.id == get_config().client_id:
|
if admin.id == get_config().client_id:
|
||||||
mute = Mute.get(
|
mute = (
|
||||||
guild=before.guild.id,
|
Mute.objects(
|
||||||
user=before.id,
|
guild=before.guild.id,
|
||||||
active=True,
|
user=before.id,
|
||||||
sort=MongoSort(key="created_at", direction="desc"),
|
active=True,
|
||||||
|
)
|
||||||
|
.sort("-created_at")
|
||||||
|
.first()
|
||||||
)
|
)
|
||||||
admin = before.guild.get_member(mute.admin)
|
admin = before.guild.get_member(mute.admin)
|
||||||
return modlog_embed(
|
return modlog_embed(
|
||||||
|
@ -148,13 +159,15 @@ class ModlogMemberCog(commands.Cog):
|
||||||
log: discord.AuditLogEntry = get_latest_log(auditlog, before)
|
log: discord.AuditLogEntry = get_latest_log(auditlog, before)
|
||||||
admin: discord.User = log.user
|
admin: discord.User = log.user
|
||||||
if admin.id == get_config().client_id:
|
if admin.id == get_config().client_id:
|
||||||
mute = Mute.get(
|
mute = (
|
||||||
guild=before.guild.id,
|
Mute.objects(
|
||||||
user=before.id,
|
guild=before.guild.id,
|
||||||
active=True,
|
user=before.id,
|
||||||
sort=MongoSort(key="created_at", direction="desc"),
|
active=True,
|
||||||
|
)
|
||||||
|
.sort("-created_at")
|
||||||
|
.first()
|
||||||
)
|
)
|
||||||
mute = Mute(**mute)
|
|
||||||
admin = before.guild.get_member(mute.admin)
|
admin = before.guild.get_member(mute.admin)
|
||||||
return modlog_embed(
|
return modlog_embed(
|
||||||
member=before,
|
member=before,
|
||||||
|
@ -214,21 +227,41 @@ class ModlogMemberCog(commands.Cog):
|
||||||
async def on_member_update(
|
async def on_member_update(
|
||||||
self, before: discord.User, after: discord.User
|
self, before: discord.User, after: discord.User
|
||||||
):
|
):
|
||||||
modlog = Setting.get(guild=before.guild.id, setting="modlog")
|
modlog = Setting.objects(
|
||||||
|
guild=before.guild.id, setting="modlog"
|
||||||
|
).first()
|
||||||
if modlog:
|
if modlog:
|
||||||
channel = after.guild.get_channel(modlog.value)
|
channel = after.guild.get_channel(modlog.value)
|
||||||
await asyncio.sleep(0.5) # Need to wait for audit log
|
await asyncio.sleep(0.5) # Need to wait for audit log
|
||||||
embed = None
|
embed = None
|
||||||
mute = Setting.get(guild=before.guild.id, setting="mute")
|
mute = Setting.objects(
|
||||||
verified = Setting.get(guild=before.guild.id, setting="verified")
|
guild=before.guild.id, setting="mute"
|
||||||
if mute and before.guild.get_role(mute.value) in after.roles:
|
).first()
|
||||||
|
verified = Setting.objects(
|
||||||
|
guild=before.guild.id, setting="verified"
|
||||||
|
).first()
|
||||||
|
mute_role = None
|
||||||
|
verified_role = None
|
||||||
|
if mute:
|
||||||
|
mute_role = before.guild.get_role(mute.value)
|
||||||
|
if verified:
|
||||||
|
verified_role = before.guild.get_role(verified.value)
|
||||||
|
if (
|
||||||
|
mute
|
||||||
|
and mute_role in after.roles
|
||||||
|
and mute_role not in before.roles
|
||||||
|
):
|
||||||
embed = await self.process_mute(before, after)
|
embed = await self.process_mute(before, after)
|
||||||
elif mute and before.guild.get_role(mute.value) in before.roles:
|
elif (
|
||||||
|
mute
|
||||||
|
and mute_role in before.roles
|
||||||
|
and mute_role not in after.roles
|
||||||
|
):
|
||||||
embed = await self.process_unmute(before, after)
|
embed = await self.process_unmute(before, after)
|
||||||
elif (
|
elif (
|
||||||
verified
|
verified
|
||||||
and before.guild.get_role(verified.value) not in before.roles
|
and verified_role not in before.roles
|
||||||
and after.guild.get_role(verified.value) in after.roles
|
and verified_role in after.roles
|
||||||
):
|
):
|
||||||
embed = await self.process_verify(before, after)
|
embed = await self.process_verify(before, after)
|
||||||
elif before.nick != after.nick:
|
elif before.nick != after.nick:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
|
||||||
from jarvis.db.types import Setting
|
from jarvis.db.models import Setting
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
|
||||||
|
@ -15,7 +15,9 @@ class ModlogMessageCog(commands.Cog):
|
||||||
self, before: discord.Message, after: discord.Message
|
self, before: discord.Message, after: discord.Message
|
||||||
):
|
):
|
||||||
if not before.author.bot:
|
if not before.author.bot:
|
||||||
modlog = Setting.get(guild=after.guild.id, setting="modlog")
|
modlog = Setting.objects(
|
||||||
|
guild=after.guild.id, setting="modlog"
|
||||||
|
).first()
|
||||||
if modlog:
|
if modlog:
|
||||||
if before.content == after.content or before.content is None:
|
if before.content == after.content or before.content is None:
|
||||||
return
|
return
|
||||||
|
@ -53,7 +55,9 @@ class ModlogMessageCog(commands.Cog):
|
||||||
|
|
||||||
@commands.Cog.listener()
|
@commands.Cog.listener()
|
||||||
async def on_message_delete(self, message: discord.Message):
|
async def on_message_delete(self, message: discord.Message):
|
||||||
modlog = Setting.get(guild=message.guild.id, setting="modlog")
|
modlog = Setting.objects(
|
||||||
|
guild=message.guild.id, setting="modlog"
|
||||||
|
).first()
|
||||||
if modlog:
|
if modlog:
|
||||||
fields = [
|
fields = [
|
||||||
Field("Original Message", message.content or "N/A", False)
|
Field("Original Message", message.content or "N/A", False)
|
||||||
|
|
|
@ -10,7 +10,7 @@ from discord.ext import commands
|
||||||
|
|
||||||
import jarvis
|
import jarvis
|
||||||
from jarvis.config import reload_config
|
from jarvis.config import reload_config
|
||||||
from jarvis.db.types import Config
|
from jarvis.db.models import Config
|
||||||
from jarvis.utils import update
|
from jarvis.utils import update
|
||||||
from jarvis.utils.permissions import user_is_bot_admin
|
from jarvis.utils.permissions import user_is_bot_admin
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ class OwnerCog(commands.Cog):
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.admins = Config.get(key="admins")
|
self.admins = Config.objects(key="admins").first()
|
||||||
|
|
||||||
@commands.command(name="load", hidden=True)
|
@commands.command(name="load", hidden=True)
|
||||||
@user_is_bot_admin()
|
@user_is_bot_admin()
|
||||||
|
@ -32,7 +32,7 @@ class OwnerCog(commands.Cog):
|
||||||
info = await self.bot.application_info()
|
info = await self.bot.application_info()
|
||||||
if (
|
if (
|
||||||
ctx.message.author == info.owner
|
ctx.message.author == info.owner
|
||||||
or ctx.message.author.id in self.admins
|
or ctx.message.author.id in self.admins.value
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
if "jarvis.cogs." not in cog:
|
if "jarvis.cogs." not in cog:
|
||||||
|
@ -58,7 +58,7 @@ class OwnerCog(commands.Cog):
|
||||||
info = await self.bot.application_info()
|
info = await self.bot.application_info()
|
||||||
if (
|
if (
|
||||||
ctx.message.author == info.owner
|
ctx.message.author == info.owner
|
||||||
or ctx.message.author.id in self.admins
|
or ctx.message.author.id in self.admins.value
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
if "jarvis.cogs." not in cog:
|
if "jarvis.cogs." not in cog:
|
||||||
|
@ -84,7 +84,7 @@ class OwnerCog(commands.Cog):
|
||||||
info = await self.bot.application_info()
|
info = await self.bot.application_info()
|
||||||
if (
|
if (
|
||||||
ctx.message.author == info.owner
|
ctx.message.author == info.owner
|
||||||
or ctx.message.author.id in self.admins
|
or ctx.message.author.id in self.admins.value
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
if "jarvis.cogs." not in cog:
|
if "jarvis.cogs." not in cog:
|
||||||
|
@ -118,7 +118,7 @@ class OwnerCog(commands.Cog):
|
||||||
info = await self.bot.application_info()
|
info = await self.bot.application_info()
|
||||||
if (
|
if (
|
||||||
ctx.message.author == info.owner
|
ctx.message.author == info.owner
|
||||||
or ctx.message.author.id in self.admins
|
or ctx.message.author.id in self.admins.value
|
||||||
):
|
):
|
||||||
await ctx.send("Restarting core systems...")
|
await ctx.send("Restarting core systems...")
|
||||||
if isinstance(ctx.channel, discord.channel.DMChannel):
|
if isinstance(ctx.channel, discord.channel.DMChannel):
|
||||||
|
@ -141,7 +141,7 @@ class OwnerCog(commands.Cog):
|
||||||
info = await self.bot.application_info()
|
info = await self.bot.application_info()
|
||||||
if (
|
if (
|
||||||
ctx.message.author == info.owner
|
ctx.message.author == info.owner
|
||||||
or ctx.message.author.id in self.admins
|
or ctx.message.author.id in self.admins.value
|
||||||
):
|
):
|
||||||
await ctx.send("Updating core systems...")
|
await ctx.send("Updating core systems...")
|
||||||
status = update()
|
status = update()
|
||||||
|
@ -189,7 +189,7 @@ class OwnerCog(commands.Cog):
|
||||||
await ctx.send(f"{user.mention} is already an admin.")
|
await ctx.send(f"{user.mention} is already an admin.")
|
||||||
return
|
return
|
||||||
self.admins.value.append(user.id)
|
self.admins.value.append(user.id)
|
||||||
self.admins.update()
|
self.admins.save()
|
||||||
reload_config()
|
reload_config()
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"{user.mention} is now an admin. Use this power carefully."
|
f"{user.mention} is now an admin. Use this power carefully."
|
||||||
|
@ -202,7 +202,7 @@ class OwnerCog(commands.Cog):
|
||||||
await ctx.send(f"{user.mention} is not an admin.")
|
await ctx.send(f"{user.mention} is not an admin.")
|
||||||
return
|
return
|
||||||
self.admins.value.remove(user.id)
|
self.admins.value.remove(user.id)
|
||||||
self.admins.update()
|
self.admins.save()
|
||||||
reload_config()
|
reload_config()
|
||||||
await ctx.send(f"{user.mention} is no longer an admin.")
|
await ctx.send(f"{user.mention} is no longer an admin.")
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ from discord_slash.utils.manage_components import (
|
||||||
wait_for_component,
|
wait_for_component,
|
||||||
)
|
)
|
||||||
|
|
||||||
from jarvis.db.types import Reminder
|
from jarvis.db.models import Reminder
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.cachecog import CacheCog
|
from jarvis.utils.cachecog import CacheCog
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
@ -124,8 +124,8 @@ class RemindmeCog(CacheCog):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
reminders = Reminder.get_active(user=ctx.author.id)
|
reminders = Reminder.objects(user=ctx.author.id, active=True).count()
|
||||||
if len(reminders) >= 5:
|
if reminders >= 5:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"You already have 5 (or more) active reminders. "
|
"You already have 5 (or more) active reminders. "
|
||||||
+ "Please either remove an old one, or wait for one to pass",
|
+ "Please either remove an old one, or wait for one to pass",
|
||||||
|
@ -147,7 +147,7 @@ class RemindmeCog(CacheCog):
|
||||||
message=message,
|
message=message,
|
||||||
remind_at=remind_at,
|
remind_at=remind_at,
|
||||||
active=True,
|
active=True,
|
||||||
).insert()
|
).save()
|
||||||
|
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="Reminder Set",
|
title="Reminder Set",
|
||||||
|
@ -210,7 +210,7 @@ class RemindmeCog(CacheCog):
|
||||||
hidden=True,
|
hidden=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
reminders = Reminder.get_active(user=ctx.author.id)
|
reminders = Reminder.objects(user=ctx.author.id, active=True)
|
||||||
if not reminders:
|
if not reminders:
|
||||||
await ctx.send("You have no reminders set.", hidden=True)
|
await ctx.send("You have no reminders set.", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -225,7 +225,7 @@ class RemindmeCog(CacheCog):
|
||||||
description="Delete a reminder",
|
description="Delete a reminder",
|
||||||
)
|
)
|
||||||
async def _delete(self, ctx: SlashContext):
|
async def _delete(self, ctx: SlashContext):
|
||||||
reminders = Reminder.get_active(user=ctx.author.id)
|
reminders = Reminder.objects(user=ctx.author.id, active=True)
|
||||||
if not reminders:
|
if not reminders:
|
||||||
await ctx.send("You have no reminders set", hidden=True)
|
await ctx.send("You have no reminders set", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -263,8 +263,8 @@ class RemindmeCog(CacheCog):
|
||||||
timeout=60 * 5,
|
timeout=60 * 5,
|
||||||
)
|
)
|
||||||
for to_delete in context.selected_options:
|
for to_delete in context.selected_options:
|
||||||
_ = Reminder.get(
|
_ = Reminder.objects(
|
||||||
user=ctx.author.id, _id=ObjectId(to_delete)
|
user=ctx.author.id, id=ObjectId(to_delete)
|
||||||
).delete()
|
).delete()
|
||||||
|
|
||||||
for row in components:
|
for row in components:
|
||||||
|
@ -307,8 +307,8 @@ class RemindmeCog(CacheCog):
|
||||||
|
|
||||||
@loop(seconds=15)
|
@loop(seconds=15)
|
||||||
async def _remind(self):
|
async def _remind(self):
|
||||||
reminders = Reminder.get_active(
|
reminders = Reminder.objects(
|
||||||
remind_at={"$lt": datetime.utcnow() + timedelta(seconds=30)}
|
remind_at__lte=datetime.utcnow() + timedelta(seconds=30)
|
||||||
)
|
)
|
||||||
for reminder in reminders:
|
for reminder in reminders:
|
||||||
if reminder.remind_at <= datetime.utcnow():
|
if reminder.remind_at <= datetime.utcnow():
|
||||||
|
|
|
@ -3,7 +3,7 @@ from discord.ext import commands
|
||||||
from discord_slash import SlashContext, cog_ext
|
from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.utils.manage_commands import create_option
|
from discord_slash.utils.manage_commands import create_option
|
||||||
|
|
||||||
from jarvis.db.types import Setting
|
from jarvis.db.models import Setting
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
from jarvis.utils.permissions import admin_or_permissions
|
from jarvis.utils.permissions import admin_or_permissions
|
||||||
|
@ -28,7 +28,9 @@ class RolegiverCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _rolegiver_add(self, ctx: SlashContext, role: Role):
|
async def _rolegiver_add(self, ctx: SlashContext, role: Role):
|
||||||
setting = Setting.get(guild=ctx.guild.id, setting="rolegiver")
|
setting = Setting.objects(
|
||||||
|
guild=ctx.guild.id, setting="rolegiver"
|
||||||
|
).first()
|
||||||
if setting and role.id in setting.value:
|
if setting and role.id in setting.value:
|
||||||
await ctx.send("Role already in rolegiver", hidden=True)
|
await ctx.send("Role already in rolegiver", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -51,7 +53,7 @@ class RolegiverCog(commands.Cog):
|
||||||
Field(name="Existing Role(s)", value=value),
|
Field(name="Existing Role(s)", value=value),
|
||||||
]
|
]
|
||||||
setting.value.append(role.id)
|
setting.value.append(role.id)
|
||||||
setting.update()
|
setting.save()
|
||||||
|
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="Rolegiver Updated",
|
title="Rolegiver Updated",
|
||||||
|
@ -87,7 +89,9 @@ class RolegiverCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _rolegiver_remove(self, ctx: SlashContext, role: Role):
|
async def _rolegiver_remove(self, ctx: SlashContext, role: Role):
|
||||||
setting = Setting.get(guild=ctx.guild.id, setting="rolegiver")
|
setting = Setting.objects(
|
||||||
|
guild=ctx.guild.id, setting="rolegiver"
|
||||||
|
).first()
|
||||||
if not setting or (setting and not setting.value):
|
if not setting or (setting and not setting.value):
|
||||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -96,7 +100,7 @@ class RolegiverCog(commands.Cog):
|
||||||
return
|
return
|
||||||
|
|
||||||
setting.value.remove(role.id)
|
setting.value.remove(role.id)
|
||||||
setting.update()
|
setting.save()
|
||||||
|
|
||||||
roles = []
|
roles = []
|
||||||
for role_id in setting.value:
|
for role_id in setting.value:
|
||||||
|
@ -137,7 +141,9 @@ class RolegiverCog(commands.Cog):
|
||||||
description="List roles rolegiver",
|
description="List roles rolegiver",
|
||||||
)
|
)
|
||||||
async def _rolegiver_list(self, ctx: SlashContext):
|
async def _rolegiver_list(self, ctx: SlashContext):
|
||||||
setting = Setting.get(guild=ctx.guild.id, setting="rolegiver")
|
setting = Setting.objects(
|
||||||
|
guild=ctx.guild.id, setting="rolegiver"
|
||||||
|
).first()
|
||||||
if not setting or (setting and not setting.value):
|
if not setting or (setting and not setting.value):
|
||||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -186,7 +192,9 @@ class RolegiverCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@commands.cooldown(1, 10, commands.BucketType.user)
|
@commands.cooldown(1, 10, commands.BucketType.user)
|
||||||
async def _role_get(self, ctx: SlashContext, role: Role):
|
async def _role_get(self, ctx: SlashContext, role: Role):
|
||||||
setting = Setting.get(guild=ctx.guild.id, setting="rolegiver")
|
setting = Setting.objects(
|
||||||
|
guild=ctx.guild.id, setting="rolegiver"
|
||||||
|
).first()
|
||||||
if not setting or (setting and not setting.value):
|
if not setting or (setting and not setting.value):
|
||||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -244,7 +252,9 @@ class RolegiverCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@commands.cooldown(1, 10, commands.BucketType.user)
|
@commands.cooldown(1, 10, commands.BucketType.user)
|
||||||
async def _role_forfeit(self, ctx: SlashContext, role: Role):
|
async def _role_forfeit(self, ctx: SlashContext, role: Role):
|
||||||
setting = Setting.get(guild=ctx.guild.id, setting="rolegiver")
|
setting = Setting.objects(
|
||||||
|
guild=ctx.guild.id, setting="rolegiver"
|
||||||
|
).first()
|
||||||
if not setting or (setting and not setting.value):
|
if not setting or (setting and not setting.value):
|
||||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||||
return
|
return
|
||||||
|
|
|
@ -4,7 +4,7 @@ from discord.utils import find
|
||||||
from discord_slash import SlashContext, cog_ext
|
from discord_slash import SlashContext, cog_ext
|
||||||
from discord_slash.utils.manage_commands import create_option
|
from discord_slash.utils.manage_commands import create_option
|
||||||
|
|
||||||
from jarvis.db.types import Setting
|
from jarvis.db.models import Setting
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
from jarvis.utils.permissions import admin_or_permissions
|
from jarvis.utils.permissions import admin_or_permissions
|
||||||
|
@ -15,13 +15,15 @@ class SettingsCog(commands.Cog):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
def update_settings(self, setting, value, guild):
|
def update_settings(self, setting, value, guild):
|
||||||
setting = Setting(setting=setting, value=value, guild=guild)
|
setting = Setting.objects(setting=setting, guild=guild).first()
|
||||||
updated = setting.update()
|
if not setting:
|
||||||
|
setting = Setting(setting=setting, guild=guild, value=value)
|
||||||
|
updated = setting.save()
|
||||||
|
|
||||||
return updated is not None
|
return updated is not None
|
||||||
|
|
||||||
def delete_settings(self, setting, guild):
|
def delete_settings(self, setting, guild):
|
||||||
return Setting.delete_many(setting=setting, guild=guild)
|
return Setting.objects(setting=setting, guild=guild).delete()
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
base="settings",
|
base="settings",
|
||||||
|
@ -231,7 +233,7 @@ class SettingsCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _view(self, ctx: SlashContext):
|
async def _view(self, ctx: SlashContext):
|
||||||
settings = Setting.get_many(guild=ctx.guild.id)
|
settings = Setting.objects(guild=ctx.guild.id)
|
||||||
|
|
||||||
fields = []
|
fields = []
|
||||||
for setting in settings:
|
for setting in settings:
|
||||||
|
@ -261,8 +263,8 @@ class SettingsCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _clear(self, ctx: SlashContext):
|
async def _clear(self, ctx: SlashContext):
|
||||||
deleted = Setting.delete_many(guild=ctx.guild.id)
|
deleted = Setting.objects(guild=ctx.guild.id).delete()
|
||||||
await ctx.send(f"Guild settings cleared: `{deleted}`")
|
await ctx.send(f"Guild settings cleared: `{deleted is not None}`")
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
|
|
|
@ -10,7 +10,7 @@ from discord_slash.utils.manage_components import (
|
||||||
wait_for_component,
|
wait_for_component,
|
||||||
)
|
)
|
||||||
|
|
||||||
from jarvis.db.types import Star, Starboard
|
from jarvis.db.models import Star, Starboard
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.permissions import admin_or_permissions
|
from jarvis.utils.permissions import admin_or_permissions
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class StarboardCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _list(self, ctx):
|
async def _list(self, ctx):
|
||||||
starboards = Starboard.get_many(guild=ctx.guild.id)
|
starboards = Starboard.objects(guild=ctx.guild.id)
|
||||||
if starboards != []:
|
if starboards != []:
|
||||||
message = "Available Starboards:\n"
|
message = "Available Starboards:\n"
|
||||||
for s in starboards:
|
for s in starboards:
|
||||||
|
@ -68,15 +68,17 @@ class StarboardCog(commands.Cog):
|
||||||
await ctx.send("Channel must be a TextChannel", hidden=True)
|
await ctx.send("Channel must be a TextChannel", hidden=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
exists = Starboard.get(channel=channel.id, guild=ctx.guild.id)
|
exists = Starboard.objects(
|
||||||
|
channel=channel.id, guild=ctx.guild.id
|
||||||
|
).first()
|
||||||
if exists:
|
if exists:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Starboard already exists at {channel.mention}.", hidden=True
|
f"Starboard already exists at {channel.mention}.", hidden=True
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
count = Starboard.get_many(guild=ctx.guild.id)
|
count = Starboard.objects(guild=ctx.guild.id).count()
|
||||||
if count and len(count) >= 25:
|
if count >= 25:
|
||||||
await ctx.send("25 starboard limit reached", hidden=True)
|
await ctx.send("25 starboard limit reached", hidden=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -84,7 +86,7 @@ class StarboardCog(commands.Cog):
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
channel=channel.id,
|
channel=channel.id,
|
||||||
admin=ctx.author.id,
|
admin=ctx.author.id,
|
||||||
).insert()
|
).save()
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Starboard created. Check it out at {channel.mention}."
|
f"Starboard created. Check it out at {channel.mention}."
|
||||||
)
|
)
|
||||||
|
@ -104,11 +106,11 @@ class StarboardCog(commands.Cog):
|
||||||
)
|
)
|
||||||
@admin_or_permissions(manage_guild=True)
|
@admin_or_permissions(manage_guild=True)
|
||||||
async def _delete(self, ctx, channel: TextChannel):
|
async def _delete(self, ctx, channel: TextChannel):
|
||||||
deleted = Starboard.get(
|
deleted = Starboard.objects(
|
||||||
channel=channel.id, guild=ctx.guild.id
|
channel=channel.id, guild=ctx.guild.id
|
||||||
).delete()
|
).delete()
|
||||||
if deleted:
|
if deleted:
|
||||||
_ = Star.delete_many(starboard=channel.id)
|
_ = Star.objects(starboard=channel.id).delete()
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Starboard deleted from {channel.mention}.", hidden=True
|
f"Starboard deleted from {channel.mention}.", hidden=True
|
||||||
)
|
)
|
||||||
|
@ -146,7 +148,7 @@ class StarboardCog(commands.Cog):
|
||||||
):
|
):
|
||||||
if not channel:
|
if not channel:
|
||||||
channel = ctx.channel
|
channel = ctx.channel
|
||||||
starboards = Starboard.get_many(guild=ctx.guild.id)
|
starboards = Starboard.objects(guild=ctx.guild.id)
|
||||||
if not starboards:
|
if not starboards:
|
||||||
await ctx.send("No starboards exist.", hidden=True)
|
await ctx.send("No starboards exist.", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -189,12 +191,12 @@ class StarboardCog(commands.Cog):
|
||||||
|
|
||||||
message = await channel.fetch_message(int(message))
|
message = await channel.fetch_message(int(message))
|
||||||
|
|
||||||
exists = Star.get(
|
exists = Star.objects(
|
||||||
message=message.id,
|
message=message.id,
|
||||||
channel=message.channel.id,
|
channel=message.channel.id,
|
||||||
guild=message.guild.id,
|
guild=message.guild.id,
|
||||||
starboard=starboard.id,
|
starboard=starboard.id,
|
||||||
)
|
).first()
|
||||||
|
|
||||||
if exists:
|
if exists:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
|
@ -247,7 +249,7 @@ class StarboardCog(commands.Cog):
|
||||||
admin=ctx.author.id,
|
admin=ctx.author.id,
|
||||||
star=star.id,
|
star=star.id,
|
||||||
active=True,
|
active=True,
|
||||||
).insert()
|
).save()
|
||||||
|
|
||||||
components[0]["components"][0]["disabled"] = True
|
components[0]["components"][0]["disabled"] = True
|
||||||
|
|
||||||
|
@ -286,7 +288,9 @@ class StarboardCog(commands.Cog):
|
||||||
if not isinstance(starboard, TextChannel):
|
if not isinstance(starboard, TextChannel):
|
||||||
await ctx.send("Channel must be a TextChannel", hidden=True)
|
await ctx.send("Channel must be a TextChannel", hidden=True)
|
||||||
return
|
return
|
||||||
exists = Starboard.get(channel=starboard.id, guild=ctx.guild.id)
|
exists = Starboard.objects(
|
||||||
|
channel=starboard.id, guild=ctx.guild.id
|
||||||
|
).first()
|
||||||
if not exists:
|
if not exists:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"Starboard does not exist in {starboard.mention}. "
|
f"Starboard does not exist in {starboard.mention}. "
|
||||||
|
@ -295,12 +299,12 @@ class StarboardCog(commands.Cog):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
star = Star.get(
|
star = Star.objects(
|
||||||
starboard=starboard.id,
|
starboard=starboard.id,
|
||||||
index=id,
|
index=id,
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
active=True,
|
active=True,
|
||||||
)
|
).first()
|
||||||
if not star:
|
if not star:
|
||||||
await ctx.send(f"No star exists with id {id}", hidden=True)
|
await ctx.send(f"No star exists with id {id}", hidden=True)
|
||||||
return
|
return
|
||||||
|
@ -310,7 +314,7 @@ class StarboardCog(commands.Cog):
|
||||||
await message.delete()
|
await message.delete()
|
||||||
|
|
||||||
star.active = False
|
star.active = False
|
||||||
star.update()
|
star.save()
|
||||||
|
|
||||||
await ctx.send(f"Star {id} deleted")
|
await ctx.send(f"Star {id} deleted")
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ from discord_slash import ComponentContext, SlashContext, cog_ext
|
||||||
from discord_slash.model import ButtonStyle
|
from discord_slash.model import ButtonStyle
|
||||||
from discord_slash.utils import manage_components
|
from discord_slash.utils import manage_components
|
||||||
|
|
||||||
from jarvis.db.types import Setting
|
from jarvis.db.models import Setting
|
||||||
|
|
||||||
|
|
||||||
def create_layout():
|
def create_layout():
|
||||||
|
@ -37,7 +37,7 @@ class VerifyCog(commands.Cog):
|
||||||
@commands.cooldown(1, 15, commands.BucketType.user)
|
@commands.cooldown(1, 15, commands.BucketType.user)
|
||||||
async def _verify(self, ctx: SlashContext):
|
async def _verify(self, ctx: SlashContext):
|
||||||
await ctx.defer()
|
await ctx.defer()
|
||||||
role = Setting.get(guild=ctx.guild.id, setting="verified")
|
role = Setting.objects(guild=ctx.guild.id, setting="verified").first()
|
||||||
if not role:
|
if not role:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"This guild has not enabled verification", delete_after=5
|
"This guild has not enabled verification", delete_after=5
|
||||||
|
@ -68,10 +68,14 @@ class VerifyCog(commands.Cog):
|
||||||
for c in components:
|
for c in components:
|
||||||
for c2 in c["components"]:
|
for c2 in c["components"]:
|
||||||
c2["disabled"] = True
|
c2["disabled"] = True
|
||||||
setting = Setting.get(guild=ctx.guild.id, setting="verified")
|
setting = Setting.objects(
|
||||||
|
guild=ctx.guild.id, setting="verified"
|
||||||
|
).first()
|
||||||
role = ctx.guild.get_role(setting.value)
|
role = ctx.guild.get_role(setting.value)
|
||||||
await ctx.author.add_roles(role, reason="Verification passed")
|
await ctx.author.add_roles(role, reason="Verification passed")
|
||||||
setting = Setting.get(guild=ctx.guild.id, setting="unverified")
|
setting = Setting.objects(
|
||||||
|
guild=ctx.guild.id, setting="unverified"
|
||||||
|
).first()
|
||||||
if setting:
|
if setting:
|
||||||
role = ctx.guild.get_role(setting.value)
|
role = ctx.guild.get_role(setting.value)
|
||||||
await ctx.author.remove_roles(
|
await ctx.author.remove_roles(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from yaml import load
|
from yaml import load
|
||||||
|
|
||||||
from jarvis.db import DBManager
|
from jarvis.db.models import Config as DBConfig
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from yaml import CLoader as Loader
|
from yaml import CLoader as Loader
|
||||||
|
@ -38,10 +38,11 @@ class Config(object):
|
||||||
self.events = events
|
self.events = events
|
||||||
self.max_messages = max_messages
|
self.max_messages = max_messages
|
||||||
self.gitlab_token = gitlab_token
|
self.gitlab_token = gitlab_token
|
||||||
db = DBManager(config=mongo["connect"]).mongo[mongo["database"]].config
|
|
||||||
db_config = db.find()
|
def get_db_config(self):
|
||||||
for item in db_config:
|
config = DBConfig.objects()
|
||||||
setattr(self, item["key"], item["value"])
|
for item in config:
|
||||||
|
setattr(self, item.key, item.value)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_yaml(cls, y):
|
def from_yaml(cls, y):
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
from pymongo import MongoClient
|
|
||||||
|
|
||||||
|
|
||||||
class DBManager(object):
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
it = cls.__dict__.get("it")
|
|
||||||
if it is not None:
|
|
||||||
return it
|
|
||||||
cls.__it__ = it = object.__new__(cls)
|
|
||||||
it.init(*args, **kwargs)
|
|
||||||
return it
|
|
||||||
|
|
||||||
def init(self, config: dict):
|
|
||||||
self.mongo = MongoClient(**config)
|
|
197
jarvis/db/models.py
Normal file
197
jarvis/db/models.py
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from mongoengine import Document
|
||||||
|
from mongoengine.fields import (
|
||||||
|
BooleanField,
|
||||||
|
DateTimeField,
|
||||||
|
DictField,
|
||||||
|
DynamicField,
|
||||||
|
IntField,
|
||||||
|
ListField,
|
||||||
|
LongField,
|
||||||
|
StringField,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SnowflakeField(LongField):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Autopurge(Document):
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
channel = SnowflakeField(required=True)
|
||||||
|
delay = IntField(min_value=1, max_value=300, default=30)
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Autoreact(Document):
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
channel = SnowflakeField(required=True)
|
||||||
|
reactions = ListField(field=StringField())
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Ban(Document):
|
||||||
|
active = BooleanField(default=True)
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
user = SnowflakeField(required=True)
|
||||||
|
username = StringField(required=True)
|
||||||
|
discrim = IntField(min_value=1, max_value=9999, required=True)
|
||||||
|
duration = IntField(min_value=1, max_value=744, required=False)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
type = StringField(default="perm", max_length=4, required=True)
|
||||||
|
reason = StringField(max_length=100, required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Config(Document):
|
||||||
|
key = StringField(required=True)
|
||||||
|
value = DynamicField(required=True)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Guess(Document):
|
||||||
|
correct = BooleanField(default=False)
|
||||||
|
guess = StringField(max_length=800, required=True)
|
||||||
|
user = SnowflakeField(required=True)
|
||||||
|
|
||||||
|
meta = {"db_alias": "ctc2"}
|
||||||
|
|
||||||
|
|
||||||
|
class Joke(Document):
|
||||||
|
rid = StringField()
|
||||||
|
body = StringField()
|
||||||
|
title = StringField()
|
||||||
|
created_utc = DateTimeField()
|
||||||
|
over_18 = BooleanField()
|
||||||
|
score = IntField()
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Kick(Document):
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
reason = StringField(max_length=100, required=True)
|
||||||
|
user = SnowflakeField(required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Lock(Document):
|
||||||
|
active = BooleanField(default=True)
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
channel = SnowflakeField(required=True)
|
||||||
|
duration = IntField(min_value=1, max_value=300, default=10)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
reason = StringField(max_length=100, required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Mute(Document):
|
||||||
|
active = BooleanField(default=True)
|
||||||
|
user = SnowflakeField(required=True)
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
duration = IntField(min_value=1, max_value=300, default=10)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
reason = StringField(max_length=100, required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Purge(Document):
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
channel = SnowflakeField(required=True)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
count = IntField(min_value=1, default=10)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Reminder(Document):
|
||||||
|
active = BooleanField(default=True)
|
||||||
|
user = SnowflakeField(required=True)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
message = StringField(max_length=100, required=True)
|
||||||
|
remind_at = DateTimeField(required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Roleping(Document):
|
||||||
|
active = BooleanField(default=True)
|
||||||
|
role = SnowflakeField(required=True)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
bypass = DictField()
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Setting(Document):
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
setting = StringField(required=True)
|
||||||
|
value = DynamicField()
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Star(Document):
|
||||||
|
index = IntField(required=True)
|
||||||
|
message = SnowflakeField(required=True)
|
||||||
|
starboard = SnowflakeField(required=True)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
star = SnowflakeField(required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Starboard(Document):
|
||||||
|
channel = SnowflakeField(required=True)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Unban(Document):
|
||||||
|
user = SnowflakeField(required=True)
|
||||||
|
username = StringField(required=True)
|
||||||
|
discrim = IntField(min_value=1, max_value=9999, required=True)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
reason = StringField(max_length=100, required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
||||||
|
class Warning(Document):
|
||||||
|
active = BooleanField(default=True)
|
||||||
|
admin = SnowflakeField(required=True)
|
||||||
|
user = SnowflakeField(required=True)
|
||||||
|
guild = SnowflakeField(required=True)
|
||||||
|
duration = IntField(min_value=1, max_value=120, default=24)
|
||||||
|
reason = StringField(max_length=100, required=True)
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
|
||||||
|
meta = {"db_alias": "main"}
|
|
@ -1,594 +0,0 @@
|
||||||
import logging
|
|
||||||
from dataclasses import asdict, dataclass, field
|
|
||||||
from datetime import datetime
|
|
||||||
from typing import Any, Optional
|
|
||||||
|
|
||||||
from bson import ObjectId
|
|
||||||
from pymongo import ASCENDING, DESCENDING
|
|
||||||
|
|
||||||
from jarvis.config import get_config
|
|
||||||
from jarvis.db import DBManager
|
|
||||||
|
|
||||||
logger = logging.getLogger("mongodb")
|
|
||||||
|
|
||||||
sort_lookup = {
|
|
||||||
"asc": ASCENDING,
|
|
||||||
"ascending": ASCENDING,
|
|
||||||
"desc": DESCENDING,
|
|
||||||
"descending": DESCENDING,
|
|
||||||
}
|
|
||||||
|
|
||||||
coll_lookup = {
|
|
||||||
"Autoreact": "autoreact",
|
|
||||||
"Autopurge": "autopurges",
|
|
||||||
"Ban": "bans",
|
|
||||||
"Config": "config",
|
|
||||||
"Lock": "locks",
|
|
||||||
"Kick": "kicks",
|
|
||||||
"Mute": "mutes",
|
|
||||||
"Purge": "purges",
|
|
||||||
"Reminder": "reminders",
|
|
||||||
"Roleping": "rolepings",
|
|
||||||
"Setting": "settings",
|
|
||||||
"Starboard": "starboard",
|
|
||||||
"Star": "stars",
|
|
||||||
"Unban": "unbans",
|
|
||||||
"Warning": "warns",
|
|
||||||
}
|
|
||||||
|
|
||||||
m_config = get_config().mongo
|
|
||||||
|
|
||||||
db_instance = DBManager(m_config["connect"]).mongo[m_config["database"]]
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
# Core Classes #
|
|
||||||
#################
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class MongoSort:
|
|
||||||
direction: int
|
|
||||||
key: Any
|
|
||||||
|
|
||||||
def __init__(self, direction, key):
|
|
||||||
if type(direction) is str:
|
|
||||||
direction = sort_lookup[direction]
|
|
||||||
self.direction = direction
|
|
||||||
self.key = key
|
|
||||||
|
|
||||||
def as_tuple(self):
|
|
||||||
return (self.key, self.direction)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class MongoObject:
|
|
||||||
"""
|
|
||||||
A MongoDB object
|
|
||||||
|
|
||||||
:param _id: MongoDB ObjectId, not initialized by default
|
|
||||||
"""
|
|
||||||
|
|
||||||
_id: ObjectId = field(default=None, init=False)
|
|
||||||
|
|
||||||
def __post_init__(self):
|
|
||||||
self.coll = db_instance[coll_lookup[type(self).__name__]]
|
|
||||||
|
|
||||||
def to_dict(self):
|
|
||||||
return asdict(self)
|
|
||||||
|
|
||||||
def insert(self) -> ObjectId:
|
|
||||||
"""
|
|
||||||
Inserts the object into the database
|
|
||||||
|
|
||||||
:param collection: Collection to insert object into
|
|
||||||
:return: Inserted object ObjectId
|
|
||||||
"""
|
|
||||||
to_insert = self.to_dict()
|
|
||||||
if not to_insert["_id"]:
|
|
||||||
_ = to_insert.pop("_id")
|
|
||||||
try:
|
|
||||||
result = self.coll.insert_one(to_insert)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to insert {type(self).__name__}", e)
|
|
||||||
else:
|
|
||||||
id = result.inserted_id
|
|
||||||
self._id = id
|
|
||||||
return id
|
|
||||||
|
|
||||||
def delete(self) -> bool:
|
|
||||||
"""
|
|
||||||
Deletes an object from the database
|
|
||||||
|
|
||||||
:param collection: Collection to delete object from
|
|
||||||
:return: If delete was successful
|
|
||||||
"""
|
|
||||||
to_delete = self.to_dict()
|
|
||||||
search = {"_id": to_delete["_id"]}
|
|
||||||
try:
|
|
||||||
result = self.coll.delete_one(search)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to delete {type(self).__name__}", e)
|
|
||||||
else:
|
|
||||||
return result.deleted_count > 0
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def delete_many(cls, **kwargs) -> bool:
|
|
||||||
try:
|
|
||||||
coll = db_instance[coll_lookup[cls.__name__]]
|
|
||||||
result = coll.delete_many(kwargs)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to delete {cls.__name__}s", e)
|
|
||||||
else:
|
|
||||||
return result.deleted_count > 0
|
|
||||||
|
|
||||||
def update(self) -> bool:
|
|
||||||
"""
|
|
||||||
Updates an object in the database
|
|
||||||
|
|
||||||
:param collection: Collection to update
|
|
||||||
:return: If update was successful
|
|
||||||
"""
|
|
||||||
to_update = self.to_dict()
|
|
||||||
if self._id:
|
|
||||||
search = {"_id": to_update["_id"]}
|
|
||||||
try:
|
|
||||||
result = self.coll.update_one(
|
|
||||||
search, {"$set": to_update}, upsert=True
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to update {type(self).__name__}", e)
|
|
||||||
else:
|
|
||||||
return result.modified_count > 0
|
|
||||||
else:
|
|
||||||
self.insert()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get(cls, **kwargs) -> Optional[object]:
|
|
||||||
"""
|
|
||||||
Get an object from MongoDB
|
|
||||||
|
|
||||||
:param collection: Collection to query
|
|
||||||
:return: Optional object
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
sort = None
|
|
||||||
if "sort" in kwargs:
|
|
||||||
sort = kwargs.pop("sort")
|
|
||||||
if type(sort) is list:
|
|
||||||
sort = [x.as_tuple() for x in sort]
|
|
||||||
else:
|
|
||||||
sort = [sort.as_tuple()]
|
|
||||||
coll = db_instance[coll_lookup[cls.__name__]]
|
|
||||||
result = coll.find_one(kwargs, sort=sort)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to get {cls.__name__}", e)
|
|
||||||
else:
|
|
||||||
if result:
|
|
||||||
_id = result.pop("_id")
|
|
||||||
r = cls(**result)
|
|
||||||
r._id = _id
|
|
||||||
return r
|
|
||||||
return None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_many(cls, **kwargs) -> Optional[list]:
|
|
||||||
"""
|
|
||||||
Gets objects from MongoDB
|
|
||||||
|
|
||||||
:param collection: Collection to query
|
|
||||||
:return: Optional object
|
|
||||||
"""
|
|
||||||
global db_instance
|
|
||||||
try:
|
|
||||||
sort = None
|
|
||||||
if "sort" in kwargs:
|
|
||||||
sort = kwargs.pop("sort")
|
|
||||||
if type(sort) is list:
|
|
||||||
sort = [x.as_tuple() for x in sort]
|
|
||||||
else:
|
|
||||||
sort = [sort.as_tuple()]
|
|
||||||
coll = db_instance[coll_lookup[cls.__name__]]
|
|
||||||
result = coll.find(kwargs, sort=sort)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to get {cls.__name__}", e)
|
|
||||||
else:
|
|
||||||
if result:
|
|
||||||
r_list = []
|
|
||||||
for r_item in result:
|
|
||||||
_id = r_item.pop("_id")
|
|
||||||
r = cls(**r_item)
|
|
||||||
r._id = _id
|
|
||||||
r_list.append(r)
|
|
||||||
return r_list
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class ActiveObject:
|
|
||||||
"""
|
|
||||||
A type of Mongo object that can be active
|
|
||||||
|
|
||||||
:param active: If object is active
|
|
||||||
"""
|
|
||||||
|
|
||||||
active: bool
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_active(cls, **kwargs) -> list:
|
|
||||||
"""
|
|
||||||
Gets a list of active objects
|
|
||||||
|
|
||||||
:param collection: Collection to query
|
|
||||||
:return: List of active objects
|
|
||||||
"""
|
|
||||||
kwargs.update({"active": True})
|
|
||||||
try:
|
|
||||||
sort = None
|
|
||||||
if "sort" in kwargs:
|
|
||||||
sort = kwargs.pop("sort")
|
|
||||||
if type(sort) is list:
|
|
||||||
sort = [x.as_tuple() for x in sort]
|
|
||||||
else:
|
|
||||||
sort = [sort.as_tuple()]
|
|
||||||
coll = db_instance[coll_lookup[cls.__name__]]
|
|
||||||
result = coll.find(kwargs, sort=sort)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to get {cls.__name__}", e)
|
|
||||||
else:
|
|
||||||
if result:
|
|
||||||
r_list = []
|
|
||||||
for r_item in result:
|
|
||||||
_id = r_item.pop("_id")
|
|
||||||
r = cls(**r_item)
|
|
||||||
r._id = _id
|
|
||||||
r_list.append(r)
|
|
||||||
return r_list
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
|
||||||
# Database Objects #
|
|
||||||
####################
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Autopurge(MongoObject):
|
|
||||||
"""
|
|
||||||
Channel Autoreact object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param guild: ID of guild
|
|
||||||
:param channel: ID of channel
|
|
||||||
:param delay: Purge delay
|
|
||||||
:param admin: ID of admin who added autoreact
|
|
||||||
:param created_at: Time the autoreact was created
|
|
||||||
"""
|
|
||||||
|
|
||||||
guild: int
|
|
||||||
channel: int
|
|
||||||
delay: int
|
|
||||||
admin: int
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Autoreact(MongoObject):
|
|
||||||
"""
|
|
||||||
Channel Autoreact object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param guild: ID of guild
|
|
||||||
:param channel: ID of channel
|
|
||||||
:param reactions: List of reactions
|
|
||||||
:param admin: ID of admin who added autoreact
|
|
||||||
:param created_at: Time the autoreact was created
|
|
||||||
"""
|
|
||||||
|
|
||||||
guild: int
|
|
||||||
channel: int
|
|
||||||
reactions: list
|
|
||||||
admin: int
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Ban(MongoObject, ActiveObject):
|
|
||||||
"""
|
|
||||||
User Ban object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param active: If the ban is active
|
|
||||||
:param admin: ID of admin who banned the user
|
|
||||||
:param user: ID of banned user
|
|
||||||
:param username: Username of banned user
|
|
||||||
:param discrim: Discriminator of banned user
|
|
||||||
:param duration: Duration of ban
|
|
||||||
:param guild: ID of guild that user belonged to
|
|
||||||
:param type: Type of ban
|
|
||||||
:param reason: Reason for the ban
|
|
||||||
:param created_at: Time the ban happened
|
|
||||||
"""
|
|
||||||
|
|
||||||
admin: int
|
|
||||||
user: int
|
|
||||||
username: str
|
|
||||||
discrim: int
|
|
||||||
duration: int
|
|
||||||
guild: int
|
|
||||||
type: str
|
|
||||||
reason: str
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Config(MongoObject):
|
|
||||||
"""
|
|
||||||
J.A.R.V.I.S. Config object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param key: Config key
|
|
||||||
:param value: Config value
|
|
||||||
"""
|
|
||||||
|
|
||||||
key: str
|
|
||||||
value: any
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Joke(MongoObject):
|
|
||||||
"""
|
|
||||||
Joke object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param id: Reddit ID
|
|
||||||
:param body: Joke Body
|
|
||||||
:param title: Joke Title
|
|
||||||
:param created_utc: Created at
|
|
||||||
:param over_18: Is NSFW
|
|
||||||
:param score: Reddit Score
|
|
||||||
"""
|
|
||||||
|
|
||||||
id: str
|
|
||||||
body: str
|
|
||||||
title: str
|
|
||||||
created_utc: datetime
|
|
||||||
over_18: bool
|
|
||||||
score: int
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Kick(MongoObject):
|
|
||||||
"""
|
|
||||||
User Kick object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param user: Kicked User ID
|
|
||||||
:param reason: Kick reason
|
|
||||||
:param admin: ID of admin who kicked user
|
|
||||||
:param created_at: Time user was kicked
|
|
||||||
:param guild: Guild ID
|
|
||||||
"""
|
|
||||||
|
|
||||||
admin: int
|
|
||||||
guild: int
|
|
||||||
reason: str
|
|
||||||
user: int
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Lock(MongoObject, ActiveObject):
|
|
||||||
"""
|
|
||||||
Channel Lock object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param active: If the lock is active
|
|
||||||
:param admin: ID of admin who locked channel
|
|
||||||
:param channel: ID of locked channel
|
|
||||||
:param duration: Duration of lock
|
|
||||||
:param guild: ID of guild that channel belongs to
|
|
||||||
:param reason: Reason for the lock
|
|
||||||
:param created_at: Time the lock happened
|
|
||||||
"""
|
|
||||||
|
|
||||||
admin: int
|
|
||||||
channel: int
|
|
||||||
duration: int
|
|
||||||
guild: int
|
|
||||||
reason: str
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Mute(MongoObject, ActiveObject):
|
|
||||||
"""
|
|
||||||
User Mute object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param active: If the mute is active
|
|
||||||
:param admin: ID of admin who muted the user
|
|
||||||
:param user: ID of muted user
|
|
||||||
:param duration: Duration of mute
|
|
||||||
:param guild: ID of guild that user belongs to
|
|
||||||
:param reason: Reason for the mute
|
|
||||||
:param created_at: Time the mute happened
|
|
||||||
"""
|
|
||||||
|
|
||||||
admin: int
|
|
||||||
user: int
|
|
||||||
duration: int
|
|
||||||
guild: int
|
|
||||||
reason: str
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Purge(MongoObject):
|
|
||||||
"""
|
|
||||||
Channel Purge object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param admin: ID of admin who purged messages
|
|
||||||
:param channel: ID of purged channel
|
|
||||||
:param guild: ID of guild that channel belongs to
|
|
||||||
:param count: Number of purged messages
|
|
||||||
:param created_at: Time the purge happened
|
|
||||||
"""
|
|
||||||
|
|
||||||
admin: int
|
|
||||||
channel: int
|
|
||||||
guild: int
|
|
||||||
count: int
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Reminder(MongoObject, ActiveObject):
|
|
||||||
"""
|
|
||||||
User Reminder object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param user: User who wanted reminded
|
|
||||||
:param channel: ID of origin channel
|
|
||||||
:param guild: ID of origin guild
|
|
||||||
:param remind_at: Datetime delay to send message
|
|
||||||
:param active: If reminder is active
|
|
||||||
:param message: Reminder message
|
|
||||||
:param created_at: Time the reminder was created
|
|
||||||
"""
|
|
||||||
|
|
||||||
user: int
|
|
||||||
channel: int
|
|
||||||
guild: int
|
|
||||||
remind_at: datetime
|
|
||||||
message: str
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Roleping(MongoObject, ActiveObject):
|
|
||||||
"""
|
|
||||||
Guild Roleping object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param role: Blocked role
|
|
||||||
:param guild: ID of origin guild
|
|
||||||
:param admin: Admin who added roleping
|
|
||||||
:param bypass: Roles/users who may bypass this roleping
|
|
||||||
:param active: If the roleping is disabled
|
|
||||||
:param created_at: Time the roleping was created
|
|
||||||
"""
|
|
||||||
|
|
||||||
role: int
|
|
||||||
guild: int
|
|
||||||
admin: int
|
|
||||||
bypass: dict
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Setting(MongoObject):
|
|
||||||
"""
|
|
||||||
Guild Setting object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param guild: ID of guild
|
|
||||||
:param setting: Setting key
|
|
||||||
:param value: Setting value
|
|
||||||
"""
|
|
||||||
|
|
||||||
guild: int
|
|
||||||
setting: str
|
|
||||||
value: any
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Star(MongoObject, ActiveObject):
|
|
||||||
"""
|
|
||||||
Starboard Star object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param index: Starboard star index
|
|
||||||
:param message: Star Message ID
|
|
||||||
:param channel: Star Channel ID
|
|
||||||
:param starboard: Starboard Channel ID
|
|
||||||
:param guild: Starboard Guild ID
|
|
||||||
:param admin: ID of admin who created star
|
|
||||||
:param star: ID of the star message
|
|
||||||
:param created_at: Time created
|
|
||||||
"""
|
|
||||||
|
|
||||||
index: int
|
|
||||||
message: int
|
|
||||||
channel: int
|
|
||||||
starboard: int
|
|
||||||
guild: int
|
|
||||||
admin: int
|
|
||||||
star: int
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Starboard(MongoObject):
|
|
||||||
"""
|
|
||||||
Channel Starboard object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param channel: Starboard Channel ID
|
|
||||||
:param guild: Starboard Guild ID
|
|
||||||
:param admin: ID of admin who created starboard
|
|
||||||
:param created_at: Time created
|
|
||||||
"""
|
|
||||||
|
|
||||||
channel: int
|
|
||||||
guild: int
|
|
||||||
admin: int
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Unban(MongoObject):
|
|
||||||
"""
|
|
||||||
Guild Unban object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param user: User ID
|
|
||||||
:param username: User Username
|
|
||||||
:param discrim: User Discriminator
|
|
||||||
:param guild: Guild ID
|
|
||||||
:param admin: Admin who unbanned user
|
|
||||||
:param reason: Reason for unban
|
|
||||||
:param created_at: Time created
|
|
||||||
"""
|
|
||||||
|
|
||||||
user: int
|
|
||||||
username: str
|
|
||||||
discrim: int
|
|
||||||
guild: int
|
|
||||||
admin: int
|
|
||||||
reason: str
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Warning(MongoObject, ActiveObject):
|
|
||||||
"""
|
|
||||||
User Warning object
|
|
||||||
|
|
||||||
:param _id: MongoDB ID
|
|
||||||
:param active: If the warning is active
|
|
||||||
:param admin: ID of admin who warned the user
|
|
||||||
:param created_at: Time the warning happened
|
|
||||||
:param duration: Duration of warning
|
|
||||||
:param guild: ID of guild that user belongs to
|
|
||||||
:param reason: Reason for the warning
|
|
||||||
:param user: ID of warned user
|
|
||||||
"""
|
|
||||||
|
|
||||||
admin: int
|
|
||||||
user: int
|
|
||||||
duration: int
|
|
||||||
guild: int
|
|
||||||
reason: str
|
|
||||||
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
|
@ -2,7 +2,7 @@ import asyncio
|
||||||
|
|
||||||
from discord.utils import find
|
from discord.utils import find
|
||||||
|
|
||||||
from jarvis.db.types import Setting
|
from jarvis.db.models import Setting
|
||||||
|
|
||||||
|
|
||||||
class GuildEventHandler(object):
|
class GuildEventHandler(object):
|
||||||
|
@ -26,7 +26,6 @@ class GuildEventHandler(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set some default settings
|
# Set some default settings
|
||||||
setting = Setting(guild=guild.id, setting="massmention", value=5)
|
_ = Setting(guild=guild.id, setting="massmention", value=5).save()
|
||||||
setting.insert()
|
|
||||||
|
|
||||||
await general.send("Systems are now fully operational")
|
await general.send("Systems are now fully operational")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from discord import Member
|
from discord import Member
|
||||||
|
|
||||||
from jarvis.db.types import Mute, Setting
|
from jarvis.db.models import Mute, Setting
|
||||||
|
|
||||||
|
|
||||||
class MemberEventHandler(object):
|
class MemberEventHandler(object):
|
||||||
|
@ -10,14 +10,16 @@ class MemberEventHandler(object):
|
||||||
|
|
||||||
async def on_member_join(self, user: Member):
|
async def on_member_join(self, user: Member):
|
||||||
guild = user.guild
|
guild = user.guild
|
||||||
mutes = Mute.get_active(guild=guild.id)
|
mute = Mute.objects(guild=guild.id, user=user.id, active=True).first()
|
||||||
if mutes and len(mutes) >= 1:
|
if mute:
|
||||||
mute_role = Setting.get(guild=guild.id, setting="mute")
|
mute_role = Setting.objects(guild=guild.id, setting="mute").first()
|
||||||
role = guild.get_role(mute_role.value)
|
role = guild.get_role(mute_role.value)
|
||||||
await user.add_roles(
|
await user.add_roles(
|
||||||
role, reason="User is muted still muted from prior mute"
|
role, reason="User is muted still muted from prior mute"
|
||||||
)
|
)
|
||||||
unverified = Setting.get(guild=guild.id, setting="unverified")
|
unverified = Setting.objects(
|
||||||
|
guild=guild.id, setting="unverified"
|
||||||
|
).first()
|
||||||
if unverified:
|
if unverified:
|
||||||
role = guild.get_role(unverified.value)
|
role = guild.get_role(unverified.value)
|
||||||
if role not in user.roles:
|
if role not in user.roles:
|
||||||
|
|
|
@ -4,7 +4,7 @@ from discord import DMChannel, Message
|
||||||
from discord.utils import find
|
from discord.utils import find
|
||||||
|
|
||||||
from jarvis.config import get_config
|
from jarvis.config import get_config
|
||||||
from jarvis.db.types import Autopurge, Autoreact, Roleping, Setting, Warning
|
from jarvis.db.models import Autopurge, Autoreact, Roleping, Setting, Warning
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
from jarvis.utils.field import Field
|
from jarvis.utils.field import Field
|
||||||
|
|
||||||
|
@ -21,17 +21,17 @@ class MessageEventHandler(object):
|
||||||
self.bot.add_listener(self.on_message_edit)
|
self.bot.add_listener(self.on_message_edit)
|
||||||
|
|
||||||
async def autopurge(self, message: Message):
|
async def autopurge(self, message: Message):
|
||||||
autopurge = Autopurge.get(
|
autopurge = Autopurge.objects(
|
||||||
guild=message.guild.id, channel=message.channel.id
|
guild=message.guild.id, channel=message.channel.id
|
||||||
)
|
).first()
|
||||||
if autopurge:
|
if autopurge:
|
||||||
await message.delete(delay=autopurge.delay)
|
await message.delete(delay=autopurge.delay)
|
||||||
|
|
||||||
async def autoreact(self, message: Message):
|
async def autoreact(self, message: Message):
|
||||||
autoreact = Autoreact.get(
|
autoreact = Autoreact.objects(
|
||||||
guild=message.guild.id,
|
guild=message.guild.id,
|
||||||
channel=message.channel.id,
|
channel=message.channel.id,
|
||||||
)
|
).first()
|
||||||
if autoreact:
|
if autoreact:
|
||||||
for reaction in autoreact.reactions:
|
for reaction in autoreact.reactions:
|
||||||
await message.add_reaction(reaction)
|
await message.add_reaction(reaction)
|
||||||
|
@ -57,15 +57,14 @@ class MessageEventHandler(object):
|
||||||
]
|
]
|
||||||
if match.group(1) not in allowed:
|
if match.group(1) not in allowed:
|
||||||
await message.delete()
|
await message.delete()
|
||||||
warning = Warning(
|
_ = Warning(
|
||||||
active=True,
|
active=True,
|
||||||
admin=get_config().client_id,
|
admin=get_config().client_id,
|
||||||
duration=24,
|
duration=24,
|
||||||
guild=message.guild.id,
|
guild=message.guild.id,
|
||||||
reason="Sent an invite link",
|
reason="Sent an invite link",
|
||||||
user=message.author.id,
|
user=message.author.id,
|
||||||
)
|
).save()
|
||||||
warning.insert()
|
|
||||||
fields = [
|
fields = [
|
||||||
Field(
|
Field(
|
||||||
"Reason",
|
"Reason",
|
||||||
|
@ -92,10 +91,10 @@ class MessageEventHandler(object):
|
||||||
await message.channel.send(embed=embed)
|
await message.channel.send(embed=embed)
|
||||||
|
|
||||||
async def massmention(self, message: Message):
|
async def massmention(self, message: Message):
|
||||||
massmention = Setting.get(
|
massmention = Setting.objects(
|
||||||
guild=message.guild.id,
|
guild=message.guild.id,
|
||||||
setting="massmention",
|
setting="massmention",
|
||||||
)
|
).first()
|
||||||
if (
|
if (
|
||||||
massmention
|
massmention
|
||||||
and massmention.value > 0
|
and massmention.value > 0
|
||||||
|
@ -103,15 +102,14 @@ class MessageEventHandler(object):
|
||||||
- (1 if message.author in message.mentions else 0)
|
- (1 if message.author in message.mentions else 0)
|
||||||
> massmention.value
|
> massmention.value
|
||||||
):
|
):
|
||||||
warning = Warning(
|
_ = Warning(
|
||||||
active=True,
|
active=True,
|
||||||
admin=get_config().client_id,
|
admin=get_config().client_id,
|
||||||
duration=24,
|
duration=24,
|
||||||
guild=message.guild.id,
|
guild=message.guild.id,
|
||||||
reason="Mass Mention",
|
reason="Mass Mention",
|
||||||
user=message.author.id,
|
user=message.author.id,
|
||||||
)
|
).save()
|
||||||
warning.insert()
|
|
||||||
fields = [Field("Reason", "Mass Mention", False)]
|
fields = [Field("Reason", "Mass Mention", False)]
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="Warning",
|
title="Warning",
|
||||||
|
@ -131,7 +129,7 @@ class MessageEventHandler(object):
|
||||||
await message.channel.send(embed=embed)
|
await message.channel.send(embed=embed)
|
||||||
|
|
||||||
async def roleping(self, message: Message):
|
async def roleping(self, message: Message):
|
||||||
rolepings = Roleping.get_active(guild=message.guild.id)
|
rolepings = Roleping.objects(guild=message.guild.id, active=True)
|
||||||
|
|
||||||
if not rolepings:
|
if not rolepings:
|
||||||
return
|
return
|
||||||
|
@ -180,15 +178,14 @@ class MessageEventHandler(object):
|
||||||
and not user_is_admin
|
and not user_is_admin
|
||||||
and not user_has_bypass
|
and not user_has_bypass
|
||||||
):
|
):
|
||||||
warning = Warning(
|
_ = Warning(
|
||||||
active=True,
|
active=True,
|
||||||
admin=get_config().client_id,
|
admin=get_config().client_id,
|
||||||
duration=24,
|
duration=24,
|
||||||
guild=message.guild.id,
|
guild=message.guild.id,
|
||||||
reason="Pinged a blocked role/user with a blocked role",
|
reason="Pinged a blocked role/user with a blocked role",
|
||||||
user=message.author.id,
|
user=message.author.id,
|
||||||
)
|
).save()
|
||||||
warning.insert()
|
|
||||||
fields = [
|
fields = [
|
||||||
Field(
|
Field(
|
||||||
"Reason",
|
"Reason",
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import pymongo
|
|
||||||
from discord.ext.tasks import loop
|
from discord.ext.tasks import loop
|
||||||
|
|
||||||
import jarvis
|
import jarvis
|
||||||
from jarvis.db.types import Ban
|
from jarvis.config import get_config
|
||||||
|
from jarvis.db.models import Ban, Unban
|
||||||
|
|
||||||
|
jarvis_id = get_config().client_id
|
||||||
|
|
||||||
|
|
||||||
@loop(minutes=10)
|
@loop(minutes=10)
|
||||||
async def unban():
|
async def unban():
|
||||||
bans = Ban.get_active(type="temp")
|
bans = Ban.objects(type="temp", active=True)
|
||||||
updates = []
|
unbans = []
|
||||||
for ban in bans:
|
for ban in bans:
|
||||||
if ban.created_at + timedelta(
|
if ban.created_at + timedelta(
|
||||||
hours=ban.duration
|
hours=ban.duration
|
||||||
|
@ -19,16 +21,17 @@ async def unban():
|
||||||
user = await jarvis.jarvis.fetch_user(ban.user)
|
user = await jarvis.jarvis.fetch_user(ban.user)
|
||||||
if user:
|
if user:
|
||||||
guild.unban(user)
|
guild.unban(user)
|
||||||
updates.append(
|
ban.active = False
|
||||||
pymongo.UpdateOne(
|
ban.save()
|
||||||
{
|
unbans.append(
|
||||||
"user": user.id,
|
Unban(
|
||||||
"guild": guild.id,
|
user=user.id,
|
||||||
"created_at": ban.created_at,
|
guild=guild.id,
|
||||||
"type": "temp",
|
username=user.name,
|
||||||
},
|
discrim=user.discriminator,
|
||||||
{"$set": {"active": False}},
|
admin=jarvis_id,
|
||||||
|
reason="Ban expired",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if updates:
|
if unbans:
|
||||||
jarvis.jarvis_db.bans.bulk_write(updates)
|
Ban.objects().insert(unbans)
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import pymongo
|
|
||||||
from discord.ext.tasks import loop
|
from discord.ext.tasks import loop
|
||||||
|
|
||||||
import jarvis
|
import jarvis
|
||||||
from jarvis.db.types import Lock
|
from jarvis.db.models import Lock
|
||||||
|
|
||||||
|
|
||||||
@loop(minutes=1)
|
@loop(minutes=1)
|
||||||
async def unlock():
|
async def unlock():
|
||||||
locks = Lock.get_active()
|
locks = Lock.objects(active=True)
|
||||||
updates = []
|
|
||||||
for lock in locks:
|
for lock in locks:
|
||||||
if (
|
if (
|
||||||
lock.created_at + timedelta(minutes=lock.duration)
|
lock.created_at + timedelta(minutes=lock.duration)
|
||||||
|
@ -26,15 +24,5 @@ async def unlock():
|
||||||
await channel.set_permissions(
|
await channel.set_permissions(
|
||||||
role, overwrite=overrides, reason="Lock expired"
|
role, overwrite=overrides, reason="Lock expired"
|
||||||
)
|
)
|
||||||
updates.append(
|
lock.active = False
|
||||||
pymongo.UpdateOne(
|
lock.save()
|
||||||
{
|
|
||||||
"channel": channel.id,
|
|
||||||
"guild": guild.id,
|
|
||||||
"created_at": lock.created_at,
|
|
||||||
},
|
|
||||||
{"$set": {"active": False}},
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if updates:
|
|
||||||
jarvis.jarvis_db.locks.bulk_write(updates)
|
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import pymongo
|
|
||||||
from discord.ext.tasks import loop
|
from discord.ext.tasks import loop
|
||||||
|
|
||||||
import jarvis
|
import jarvis
|
||||||
from jarvis.db.types import Mute, Setting
|
from jarvis.db.models import Mute, Setting
|
||||||
|
|
||||||
|
|
||||||
@loop(minutes=1)
|
@loop(minutes=1)
|
||||||
async def unmute():
|
async def unmute():
|
||||||
mutes = Mute.get_active(duration={"$gt": 0})
|
mutes = Mute.objects(duration__gt=0, active=True)
|
||||||
mute_roles = Setting.get_many(setting="mute")
|
mute_roles = Setting.objects(setting="mute")
|
||||||
updates = []
|
|
||||||
for mute in mutes:
|
for mute in mutes:
|
||||||
if (
|
if (
|
||||||
mute.created_at + timedelta(minutes=mute.duration)
|
mute.created_at + timedelta(minutes=mute.duration)
|
||||||
|
@ -28,15 +26,5 @@ async def unmute():
|
||||||
await user.remove_roles(role, reason="Mute expired")
|
await user.remove_roles(role, reason="Mute expired")
|
||||||
|
|
||||||
# Objects can't handle bulk_write, so handle it via raw methods
|
# Objects can't handle bulk_write, so handle it via raw methods
|
||||||
updates.append(
|
mute.active = False
|
||||||
pymongo.UpdateOne(
|
mute.save
|
||||||
{
|
|
||||||
"user": user.id,
|
|
||||||
"guild": guild.id,
|
|
||||||
"created_at": mute.created_at,
|
|
||||||
},
|
|
||||||
{"$set": {"active": False}},
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if updates:
|
|
||||||
jarvis.jarvis_db.mutes.bulk_write(updates)
|
|
||||||
|
|
|
@ -1,25 +1,18 @@
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import pymongo
|
|
||||||
from discord.ext.tasks import loop
|
from discord.ext.tasks import loop
|
||||||
|
|
||||||
import jarvis
|
import jarvis
|
||||||
from jarvis.db.types import Warning
|
from jarvis.db.models import Warning
|
||||||
|
|
||||||
|
|
||||||
@loop(hours=1)
|
@loop(hours=1)
|
||||||
async def unwarn():
|
async def unwarn():
|
||||||
warns = Warning.get_active()
|
warns = Warning.objects(active=True)
|
||||||
updates = []
|
|
||||||
for warn in warns:
|
for warn in warns:
|
||||||
if (
|
if (
|
||||||
warn.created_at + timedelta(hours=warn.duration)
|
warn.created_at + timedelta(hours=warn.duration)
|
||||||
< datetime.utcnow()
|
< datetime.utcnow()
|
||||||
):
|
):
|
||||||
updates.append(
|
warn.active = False
|
||||||
pymongo.UpdateOne(
|
warn.save()
|
||||||
{"_id": warn._id}, {"$set": {"active": False}}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if updates:
|
|
||||||
jarvis.jarvis_db.warns.bulk_write(updates)
|
|
||||||
|
|
|
@ -9,3 +9,4 @@ ButtonPaginator>=0.0.3
|
||||||
Pillow>=8.2.0, <9
|
Pillow>=8.2.0, <9
|
||||||
python-gitlab>=2.9.0, <3
|
python-gitlab>=2.9.0, <3
|
||||||
ulid-py>=1.1.0, <2
|
ulid-py>=1.1.0, <2
|
||||||
|
mongoengine>=0.23, <1
|
||||||
|
|
Loading…
Add table
Reference in a new issue