Merge branch 'v1.0.0' into 'main'

V1.0.0

Closes #53, #51, #45, #55, #46, #50, #48, #44, #56, #52, and #49

See merge request stark-industries/j.a.r.v.i.s.!8
This commit is contained in:
Zeva Rose 2021-07-19 19:46:22 +00:00
commit 9c3d68970f
14 changed files with 310 additions and 219 deletions

View file

@ -9,12 +9,13 @@ from discord.ext import commands
from discord.ext.tasks import loop
from discord.utils import find, get
from discord_slash import SlashCommand
from psutil import Process
from jarvis import logo, utils
from jarvis.config import get_config
from jarvis.utils import build_embed
from jarvis.utils.db import DBManager
from jarvis.utils.field import Field
from psutil import Process
if asyncio.get_event_loop().is_closed():
asyncio.set_event_loop(asyncio.new_event_loop())
@ -28,10 +29,15 @@ invites = re.compile(
)
jarvis = commands.Bot(command_prefix=utils.get_prefix, intents=intents)
jarvis = commands.Bot(
command_prefix=utils.get_prefix, intents=intents, help_command=None
)
slash = SlashCommand(jarvis, sync_commands=True, sync_on_cog_reload=True)
jarvis_self = Process()
__version__ = "0.9.9"
__version__ = "1.0.0"
db = DBManager(get_config().mongo).mongo
@jarvis.event
@ -84,8 +90,10 @@ async def on_member_join(user: Member):
@jarvis.event
async def on_message(message: Message):
if not isinstance(message.channel, DMChannel):
db = DBManager(get_config().mongo).mongo
if (
not isinstance(message.channel, DMChannel)
and not message.author.id == jarvis.client.id
):
autoreact = db.jarvis.autoreact.find_one(
{"guild": message.guild.id, "channel": message.channel.id}
)
@ -97,9 +105,10 @@ async def on_message(message: Message):
)
if (
massmention["value"] > 0
and len(message.mentions) > massmention["value"]
and len(message.mentions)
- (1 if message.author in message.mentions else 0)
> massmention["value"]
):
await message.delete()
db.jarvis.warns.insert_one(
{
"user": message.author.id,
@ -137,7 +146,13 @@ async def on_message(message: Message):
for mention in message.mentions:
for role in mention.roles:
roles.append(role.id)
if roleping and any(x.id in roleping["value"] for x in roles):
if (
roleping
and any(x in roleping["value"] for x in roles)
and not any(
x.id in roleping["value"] for x in message.author.roles
)
):
db.jarvis.warns.insert_one(
{
"user": message.author.id,

View file

@ -31,7 +31,6 @@ class AdminCog(commands.Cog):
@cog_ext.cog_slash(
name="ban",
description="Ban a user",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="user",
@ -71,7 +70,7 @@ class AdminCog(commands.Cog):
user: User = None,
reason: str = None,
type: str = "perm",
length: int = 4,
duration: int = 4,
):
if not user or user == ctx.author:
await ctx.send("You cannot ban yourself.", hidden=True)
@ -79,11 +78,14 @@ class AdminCog(commands.Cog):
if user == self.bot.user:
await ctx.send("I'm afraid I can't let you do that", hidden=True)
return
if type == "temp" and length < 0:
if type == "temp" and duration < 0:
await ctx.send(
"You cannot set a temp ban to < 0 hours.", hidden=True
)
return
if len(reason) > 100:
await ctx.send("Reason must be < 100 characters", hidden=True)
return
if not reason:
reason = (
"Mr. Stark is displeased with your presence. Please leave."
@ -101,11 +103,15 @@ class AdminCog(commands.Cog):
time = datetime.now()
expiry = None
if mtype == "temp":
user_message += f"\nDuration: {length} hours"
expiry = time + timedelta(hours=length)
user_message += f"\nDuration: {duration} hours"
expiry = time + timedelta(hours=duration)
try:
await ctx.guild.ban(user, reason=reason)
except Exception as e:
await ctx.send(f"Failed to ban user:\n```\n{e}\n```", hidden=True)
return
await user.send(user_message)
await ctx.guild.ban(user, reason=reason)
if mtype == "soft":
await ctx.guild.unban(user, reason="Ban was softban")
await ctx.send(
@ -113,7 +119,7 @@ class AdminCog(commands.Cog):
+ f" Reason:\n{reason}"
)
if type != "temp":
length = None
duration = None
active = True
if type == "soft":
active = False
@ -128,7 +134,7 @@ class AdminCog(commands.Cog):
"time": datetime.now(),
"guild": ctx.guild.id,
"type": type,
"length": length,
"duration": duration,
"expiry": expiry,
"active": active,
}
@ -158,7 +164,6 @@ class AdminCog(commands.Cog):
@cog_ext.cog_slash(
name="unban",
description="Unban a user",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="user",
@ -181,7 +186,9 @@ class AdminCog(commands.Cog):
user: str,
reason: str,
):
await ctx.defer()
if len(reason) > 100:
await ctx.send("Reason must be < 100 characters", hidden=True)
return
orig_user = user
discrim = None
@ -246,7 +253,7 @@ class AdminCog(commands.Cog):
database_ban_info = self.db.jarvis.bans.find_one(search)
if not discord_ban_info and not database_ban_info:
await ctx.send(f"Unable to find user {orig_user}")
await ctx.send(f"Unable to find user {orig_user}", hidden=True)
elif discord_ban_info:
await self.discord_apply_unban(ctx, discord_ban_info.user, reason)
@ -283,7 +290,6 @@ class AdminCog(commands.Cog):
base="bans",
name="list",
description="List bans",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="type",
@ -314,7 +320,6 @@ class AdminCog(commands.Cog):
self, ctx: SlashContext, type: int = 0, active: int = 1
):
active = bool(active)
await ctx.defer()
types = [0, "perm", "temp", "soft"]
search = {"guild": ctx.guild.id}
if active:
@ -358,7 +363,6 @@ class AdminCog(commands.Cog):
@cog_ext.cog_slash(
name="kick",
description="Kick a user",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="user",
@ -382,6 +386,9 @@ class AdminCog(commands.Cog):
if user == self.bot.user:
await ctx.send("I'm afraid I can't let you do that", hidden=True)
return
if len(reason) > 100:
await ctx.send("Reason must be < 100 characters", hidden=True)
return
if not reason:
reason = (
"Mr. Stark is displeased with your presence. Please leave."
@ -411,7 +418,6 @@ class AdminCog(commands.Cog):
@cog_ext.cog_slash(
name="purge",
description="Purge messages from channel",
guild_ids=[578757004059738142, 862402786116763668],
options=[
create_option(
name="amount",
@ -445,7 +451,6 @@ class AdminCog(commands.Cog):
@cog_ext.cog_slash(
name="mute",
description="Mute a user",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="user",
@ -460,8 +465,8 @@ class AdminCog(commands.Cog):
required=True,
),
create_option(
name="length",
description="Mute length",
name="duration",
description="Mute duration",
option_type=4,
required=False,
),
@ -469,15 +474,17 @@ class AdminCog(commands.Cog):
)
@admin_or_permissions(mute_members=True)
async def _mute(
self, ctx: SlashContext, user: Member, reason: str, length: int = 30
self, ctx: SlashContext, user: Member, reason: str, duration: int = 30
):
await ctx.defer()
if user == ctx.author:
await ctx.send("You cannot mute yourself.", hidden=True)
return
if user == self.bot.user:
await ctx.send("I'm afraid I can't let you do that", hidden=True)
return
if len(reason) > 100:
await ctx.send("Reason must be < 100 characters", hidden=True)
return
mute_setting = self.db.jarvis.settings.find_one(
{"guild": ctx.guild.id, "setting": "mute"}
)
@ -488,13 +495,15 @@ class AdminCog(commands.Cog):
)
return
role = get(ctx.guild.roles, id=mute_setting["value"])
if role in user.roles:
await ctx.send("User already muted", hidden=True)
await user.add_roles(role, reason=reason)
time = datetime.now()
expiry = None
if length < 0:
length = -1
if length >= 0:
expiry = time + timedelta(minutes=length)
if duration < 0:
duration = -1
if duration >= 0:
expiry = time + timedelta(minutes=duration)
self.db.jarvis.mutes.insert_one(
{
"user": user.id,
@ -502,9 +511,9 @@ class AdminCog(commands.Cog):
"admin": ctx.author.id,
"time": time,
"guild": ctx.guild.id,
"length": length,
"duration": duration,
"expiry": expiry,
"active": True if length >= 0 else False,
"active": True if duration >= 0 else False,
}
)
self.db.jarvis.mutes.update_many(
@ -520,7 +529,6 @@ class AdminCog(commands.Cog):
@cog_ext.cog_slash(
name="unmute",
description="Unmute a user",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="user",
@ -532,7 +540,6 @@ class AdminCog(commands.Cog):
)
@admin_or_permissions(mute_members=True)
async def _unmute(self, ctx: SlashContext, user: Member):
await ctx.defer()
mute_setting = self.db.jarvis.settings.find_one(
{"guild": ctx.guild.id, "setting": "mute"}
)
@ -591,7 +598,6 @@ class AdminCog(commands.Cog):
@cog_ext.cog_slash(
name="lock",
description="Locks a channel",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="reason",
@ -621,7 +627,10 @@ class AdminCog(commands.Cog):
duration: int = 10,
channel: Union[TextChannel, VoiceChannel] = None,
):
await ctx.defer()
await ctx.defer(hidden=True)
if len(reason) > 100:
await ctx.send("Reason must be < 100 characters", hidden=True)
return
if not channel:
channel = ctx.channel
for role in ctx.guild.roles:
@ -645,7 +654,6 @@ class AdminCog(commands.Cog):
@cog_ext.cog_slash(
name="unlock",
description="Unlocks a channel",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="channel",
@ -661,7 +669,6 @@ class AdminCog(commands.Cog):
ctx: SlashContext,
channel: Union[TextChannel, VoiceChannel] = None,
):
await ctx.defer()
if not channel:
channel = ctx.channel
lock = self.db.jarvis.locks.find_one(
@ -688,7 +695,6 @@ class AdminCog(commands.Cog):
base="lockdown",
name="start",
description="Locks a server",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="reason",
@ -742,14 +748,12 @@ class AdminCog(commands.Cog):
base="lockdown",
name="end",
description="Unlocks a server",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
)
@commands.has_permissions(administrator=True)
async def _lockdown_end(
self,
ctx: SlashContext,
):
await ctx.defer()
channels = ctx.guild.channels
roles = ctx.guild.roles
updates = []
@ -759,6 +763,7 @@ class AdminCog(commands.Cog):
if not locks:
await ctx.send("No lockdown detected.", hidden=True)
return
await ctx.defer()
for channel in channels:
for role in roles:
try:
@ -782,7 +787,6 @@ class AdminCog(commands.Cog):
@cog_ext.cog_slash(
name="warn",
description="Warn a user",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="user",
@ -808,6 +812,9 @@ class AdminCog(commands.Cog):
async def _warn(
self, ctx: SlashContext, user: User, reason: str, duration: int = 24
):
if len(reason) > 100:
await ctx.send("Reason must be < 100 characters", hidden=True)
return
await ctx.defer()
self.db.jarvis.warns.insert_one(
{
@ -844,7 +851,6 @@ class AdminCog(commands.Cog):
@cog_ext.cog_slash(
name="warnings",
description="Get count of user warnings",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="user",
@ -865,9 +871,20 @@ class AdminCog(commands.Cog):
}
)
)
active = len(list(filter(lambda x: x["active"], warnings)))
active = (
[
y["reason"]
for y in list(filter(lambda x: x["active"], warnings))
]
if warnings
else ["None"]
)
total = len(warnings)
fields = [Field("Active", active), Field("Total", total)]
fields = [
Field(f"{len(active)} Active", "\n".join(active)),
Field("Total", total),
]
embed = build_embed(
title="Warnings",
description=f"{user.mention} active and total warnings",
@ -885,7 +902,6 @@ class AdminCog(commands.Cog):
base="roleping",
name="block",
description="Add a role to the roleping blocklist",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="role",
@ -920,7 +936,6 @@ class AdminCog(commands.Cog):
base="roleping",
name="allow",
description="Remove a role from the roleping blocklist",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="role",
@ -956,7 +971,6 @@ class AdminCog(commands.Cog):
base="roleping",
name="list",
description="List all blocklisted roles",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
)
async def _roleping_list(self, ctx: SlashContext):
roles = self.db.jarvis.settings.find_one(
@ -982,7 +996,6 @@ class AdminCog(commands.Cog):
base="autopurge",
name="add",
description="Automatically purge messages after x seconds",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="channel",
@ -1002,6 +1015,9 @@ class AdminCog(commands.Cog):
async def _autopurge_add(
self, ctx: SlashContext, channel: TextChannel, delay: int = 30
):
if not isinstance(channel, TextChannel):
await ctx.send("Channel must be a TextChannel", hidden=True)
return
autopurge = self.db.jarvis.autopurge.find(
{"guild": ctx.guild.id, "channel": channel.id}
)
@ -1025,7 +1041,6 @@ class AdminCog(commands.Cog):
base="autopurge",
name="remove",
description="Remove an autopurge",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="channel",
@ -1050,7 +1065,6 @@ class AdminCog(commands.Cog):
base="autopurge",
name="update",
description="Update autopurge on a channel",
guild_ids=[418094694325813248, 578757004059738142, 862402786116763668],
options=[
create_option(
name="channel",
@ -1070,7 +1084,7 @@ class AdminCog(commands.Cog):
async def _autopurge_update(
self, ctx: SlashContext, channel: TextChannel, delay: int
):
autopurge = self.db.jarvis.autopurge.find(
autopurge = self.db.jarvis.autopurge.find_one(
{"guild": ctx.guild.id, "channel": channel.id}
)
if not autopurge:

View file

@ -24,7 +24,6 @@ class AutoReactCog(commands.Cog):
base="autoreact",
name="create",
description="Add an autoreact to a channel",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="channel",
@ -62,7 +61,6 @@ class AutoReactCog(commands.Cog):
base="autoreact",
name="delete",
description="Delete an autoreact from a channel",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="channel",
@ -87,7 +85,6 @@ class AutoReactCog(commands.Cog):
base="autoreact",
name="add",
description="Add an autoreact emote to an existing autoreact",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="channel",
@ -154,7 +151,6 @@ class AutoReactCog(commands.Cog):
base="autoreact",
name="remove",
description="Remove an autoreact emote from an existing autoreact",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="channel",
@ -199,7 +195,6 @@ class AutoReactCog(commands.Cog):
base="autoreact",
name="list",
description="List all autoreacts on a channel",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="channel",

View file

@ -6,6 +6,8 @@ import jarvis
from jarvis.config import get_config
from jarvis.utils.db import DBManager
guild_ids = [578757004059738142, 520021794380447745, 862402786116763668]
class CTCCog(commands.Cog):
def __init__(self, bot):
@ -19,7 +21,7 @@ class CTCCog(commands.Cog):
base="ctc2",
name="about",
description="CTC2 related commands",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
)
async def _about(self, ctx):
await ctx.send("See https://completethecode.com for more information")
@ -28,7 +30,7 @@ class CTCCog(commands.Cog):
base="ctc2",
name="pw",
description="Guess a password for https://completethecodetwo.cards",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
)
async def _pw(self, ctx, guess: str):
guessed = self.db.ctc2.guesses.find_one({"guess": guess})

View file

@ -1,15 +1,18 @@
import re
import aiohttp
import jarvis
from discord.ext import commands
from discord_slash import cog_ext
from discord_slash.utils.manage_commands import create_option
import jarvis
from jarvis.config import get_config
from jarvis.data.dbrand import shipping_lookup
from jarvis.utils import build_embed
from jarvis.utils.field import Field
guild_ids = [578757004059738142, 520021794380447745, 862402786116763668]
class DbrandCog(commands.Cog):
"""
@ -29,7 +32,7 @@ class DbrandCog(commands.Cog):
@cog_ext.cog_subcommand(
base="db",
name="skin",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
description="See what skins are available",
)
async def _skin(self, ctx):
@ -38,7 +41,7 @@ class DbrandCog(commands.Cog):
@cog_ext.cog_subcommand(
base="db",
name="robotcamo",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
description="Get some robot camo. Make Tony Stark proud",
)
async def _camo(self, ctx):
@ -47,7 +50,7 @@ class DbrandCog(commands.Cog):
@cog_ext.cog_subcommand(
base="db",
name="grip",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
description="See devices with Grip support",
)
async def _grip(self, ctx):
@ -56,7 +59,7 @@ class DbrandCog(commands.Cog):
@cog_ext.cog_subcommand(
base="db",
name="contact",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
description="Contact support",
)
async def _contact(self, ctx):
@ -67,7 +70,7 @@ class DbrandCog(commands.Cog):
@cog_ext.cog_subcommand(
base="db",
name="support",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
description="Contact support",
)
async def _support(self, ctx):
@ -78,7 +81,7 @@ class DbrandCog(commands.Cog):
@cog_ext.cog_subcommand(
base="db",
name="orderstat",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
description="Get your order status",
)
async def _orderstat(self, ctx):
@ -87,7 +90,7 @@ class DbrandCog(commands.Cog):
@cog_ext.cog_subcommand(
base="db",
name="orders",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
description="Get your order status",
)
async def _orders(self, ctx):
@ -96,7 +99,7 @@ class DbrandCog(commands.Cog):
@cog_ext.cog_subcommand(
base="db",
name="status",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
description="dbrand status",
)
async def _status(self, ctx):
@ -105,7 +108,7 @@ class DbrandCog(commands.Cog):
@cog_ext.cog_subcommand(
base="db",
name="buy",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
description="Give us your money!",
)
async def _buy(self, ctx):
@ -114,7 +117,7 @@ class DbrandCog(commands.Cog):
@cog_ext.cog_subcommand(
base="db",
name="extortion",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
description="(not) extortion",
)
async def _extort(self, ctx):
@ -126,7 +129,7 @@ class DbrandCog(commands.Cog):
base="db",
name="ship",
description="Get shipping information for your country",
guild_ids=[862402786116763668, 578757004059738142],
guild_ids=guild_ids,
options=[
(
create_option(

View file

@ -1,13 +1,8 @@
import base64
import hashlib
import os
import re
import subprocess
import sys
import traceback
import uuid
from inspect import getsource
from time import time
import discord
import ulid
@ -18,7 +13,6 @@ from discord_slash import cog_ext
import jarvis
from jarvis.utils import build_embed, convert_bytesize
from jarvis.utils.field import Field
from jarvis.utils.permissions import user_is_bot_admin
supported_hashes = {
x for x in hashlib.algorithms_guaranteed if "shake" not in x
@ -113,7 +107,6 @@ class DevCog(commands.Cog):
@cog_ext.cog_slash(
name="hash",
description="Hash some data",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _hash_slash(self, ctx, method: str, *, data: str = None):
await self._hash(ctx, method, data=data)
@ -150,7 +143,6 @@ class DevCog(commands.Cog):
@cog_ext.cog_slash(
name="uuid",
description="Generate a UUID",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _uuid_slash(self, ctx, version: str = None, data: str = None):
await self._uuid(ctx, version, data)
@ -166,7 +158,6 @@ class DevCog(commands.Cog):
@cog_ext.cog_slash(
name="objectid",
description="Generate an ObjectID",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _objectid_slash(self, ctx):
await self._objectid(ctx)
@ -182,7 +173,6 @@ class DevCog(commands.Cog):
@cog_ext.cog_slash(
name="ulid",
description="Generate a ULID",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _ulid_slash(self, ctx):
await self._ulid(ctx)
@ -202,7 +192,6 @@ class DevCog(commands.Cog):
@cog_ext.cog_slash(
name="uuid2ulid",
description="Convert a UUID to a ULID",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _uuid2ulid_slash(self, ctx, u: str):
await self._uuid2ulid(ctx, u)
@ -222,7 +211,6 @@ class DevCog(commands.Cog):
@cog_ext.cog_slash(
name="ulid2uuid",
description="Convert a ULID to a UUID",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _ulid2uuid_slash(self, ctx, u):
await self._ulid2uuid(ctx, u)
@ -249,7 +237,6 @@ class DevCog(commands.Cog):
@cog_ext.cog_slash(
name="encode",
description="Encode using the base64 module",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _encode_slash(self, ctx, method: str, *, data: str):
await self._encode(ctx, method, data)
@ -274,7 +261,6 @@ class DevCog(commands.Cog):
@cog_ext.cog_slash(
name="decode",
description="Decode using the base64 module",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _decode_slash(self, ctx, method: str, *, data: str):
await self._decode(ctx, method, data)
@ -292,73 +278,11 @@ class DevCog(commands.Cog):
@cog_ext.cog_slash(
name="cloc",
description="Get J.A.R.V.I.S. lines of code",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _cloc_slash(self, ctx):
await ctx.defer()
await self._cloc(ctx)
def resolve_variable(self, variable):
if hasattr(variable, "__iter__"):
var_length = len(list(variable))
if (var_length > 100) and (not isinstance(variable, str)):
return f"<a {type(variable).__name__} iterable with more than 100 values ({var_length})>"
elif not var_length:
return f"<an empty {type(variable).__name__} iterable>"
if (not variable) and (not isinstance(variable, bool)):
return f"<an empty {type(variable).__name__} object>"
return (
variable
if (len(f"{variable}") <= 1000)
else f"<a long {type(variable).__name__} object with the length of {len(f'{variable}'):,}>"
)
def prepare(self, string):
arr = (
string.strip("```")
.replace("py\n", "")
.replace("python\n", "")
.split("\n")
)
if not arr[::-1][0].replace(" ", "").startswith("return"):
arr[len(arr) - 1] = "return " + arr[::-1][0]
return "".join(f"\n\t{i}" for i in arr)
@commands.command(pass_context=True, aliases=["eval", "exec", "evaluate"])
@user_is_bot_admin()
async def _eval(self, ctx, *, code: str):
code = self.prepare(code)
args = {
"discord": discord,
"sauce": getsource,
"sys": sys,
"os": os,
"imp": __import__,
"this": self,
"ctx": ctx,
}
try:
exec(f"async def func():{code}", globals().update(args), locals())
a = time()
response = await eval("func()", globals().update(args), locals())
if response is None or isinstance(response, discord.Message):
del args, code
return
if isinstance(response, str):
response = response.replace("`", "")
await ctx.send(
f"```py\n{self.resolve_variable(response)}```"
+ f"`{type(response).__name__} | {(time() - a) / 1000} ms`"
)
except Exception:
await ctx.send(f"Error occurred:```\n{traceback.format_exc()}```")
del args, code
def setup(bot):
bot.add_cog(DevCog(bot))

View file

@ -12,9 +12,7 @@ class ErrorHandlerCog(commands.Cog):
if isinstance(error, commands.errors.MissingPermissions):
await ctx.send("I'm afraid I can't let you do that.")
elif isinstance(error, commands.errors.CommandNotFound):
await ctx.send(
"Command does not exist. Run `>help` to get a list of commands"
)
return
else:
await ctx.send(f"Error processing command:\n```{error}```")
@ -23,13 +21,13 @@ class ErrorHandlerCog(commands.Cog):
if isinstance(error, commands.errors.MissingPermissions) or isinstance(
error, commands.errors.CheckFailure
):
await ctx.send("I'm afraid I can't let you do that.")
await ctx.send("I'm afraid I can't let you do that.", hidden=True)
elif isinstance(error, commands.errors.CommandNotFound):
await ctx.send(
"Command does not exist. Run `>help` to get a list of commands"
)
return
else:
await ctx.send(f"Error processing command:\n```{error}```")
await ctx.send(
f"Error processing command:\n```{error}```", hidden=True
)
def setup(bot):

View file

@ -131,7 +131,6 @@ class JokeCog(commands.Cog):
@cog_ext.cog_slash(
name="joke",
description="Hear a joke",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _joke_slash(self, ctx, id: str = None):
await self._joke(ctx, id)

View file

@ -2,12 +2,13 @@ import asyncio
from datetime import datetime, timedelta
import discord
import jarvis
import pymongo
from discord import DMChannel
from discord.ext import commands
from discord.utils import find
from discord_slash import SlashContext
import jarvis
from jarvis.config import get_config
from jarvis.utils import build_embed
from jarvis.utils.db import DBManager
@ -356,43 +357,44 @@ class ModlogCog(commands.Cog):
async def on_message_edit(
self, before: discord.Message, after: discord.Message
):
modlog = self.db.jarvis.settings.find_one(
{"guild": after.guild.id, "setting": "modlog"}
)
if modlog:
if before.content == after.content or before.content is None:
return
channel = before.guild.get_channel(modlog["value"])
fields = [
Field(
"Original Message",
before.content if before.content else "N/A",
False,
),
Field(
"New Message",
after.content if after.content else "N/A",
False,
),
]
embed = build_embed(
title="Message Edited",
description=f"{before.author.mention} edited a message",
fields=fields,
color="#fc9e3f",
timestamp=after.edited_at,
url=after.jump_url,
if before.author != self.bot.client.id:
modlog = self.db.jarvis.settings.find_one(
{"guild": after.guild.id, "setting": "modlog"}
)
embed.set_author(
name=before.author.name,
icon_url=before.author.avatar_url,
url=after.jump_url,
)
embed.set_footer(
text=f"{before.author.name}#{before.author.discriminator}"
+ f" | {before.author.id}"
)
await channel.send(embed=embed)
if modlog:
if before.content == after.content or before.content is None:
return
channel = before.guild.get_channel(modlog["value"])
fields = [
Field(
"Original Message",
before.content if before.content else "N/A",
False,
),
Field(
"New Message",
after.content if after.content else "N/A",
False,
),
]
embed = build_embed(
title="Message Edited",
description=f"{before.author.mention} edited a message",
fields=fields,
color="#fc9e3f",
timestamp=after.edited_at,
url=after.jump_url,
)
embed.set_author(
name=before.author.name,
icon_url=before.author.avatar_url,
url=after.jump_url,
)
embed.set_footer(
text=f"{before.author.name}#{before.author.discriminator}"
+ f" | {before.author.id}"
)
await channel.send(embed=embed)
@commands.Cog.listener()
async def on_message_delete(self, message: discord.Message):

View file

@ -1,5 +1,11 @@
import os
import sys
import traceback
from inspect import getsource
from time import time
import discord
from discord import User
from discord import DMChannel, User
from discord.ext import commands
import jarvis
@ -192,6 +198,79 @@ class OwnerCog(commands.Cog):
reload_config()
await ctx.send(f"{user.mention} is no longer an admin.")
def resolve_variable(self, variable):
if hasattr(variable, "__iter__"):
var_length = len(list(variable))
if (var_length > 100) and (not isinstance(variable, str)):
return f"<a {type(variable).__name__} iterable with more than 100 values ({var_length})>"
elif not var_length:
return f"<an empty {type(variable).__name__} iterable>"
if (not variable) and (not isinstance(variable, bool)):
return f"<an empty {type(variable).__name__} object>"
return (
variable
if (len(f"{variable}") <= 1000)
else f"<a long {type(variable).__name__} object with the length of {len(f'{variable}'):,}>"
)
def prepare(self, string):
arr = (
string.strip("```")
.replace("py\n", "")
.replace("python\n", "")
.split("\n")
)
if not arr[::-1][0].replace(" ", "").startswith("return"):
arr[len(arr) - 1] = "return " + arr[::-1][0]
return "".join(f"\n\t{i}" for i in arr)
@commands.command(
pass_context=True, aliases=["eval", "exec", "evaluate"]
)
@user_is_bot_admin()
async def _eval(self, ctx, *, code: str):
if not isinstance(ctx.message.channel, DMChannel):
return
code = self.prepare(code)
args = {
"discord": discord,
"sauce": getsource,
"sys": sys,
"os": os,
"imp": __import__,
"this": self,
"ctx": ctx,
}
try:
exec(
f"async def func():{code}",
globals().update(args),
locals(),
)
a = time()
response = await eval(
"func()", globals().update(args), locals()
)
if response is None or isinstance(response, discord.Message):
del args, code
return
if isinstance(response, str):
response = response.replace("`", "")
await ctx.send(
f"```py\n{self.resolve_variable(response)}```"
+ f"`{type(response).__name__} | {(time() - a) / 1000} ms`"
)
except Exception:
await ctx.send(
f"Error occurred:```\n{traceback.format_exc()}```"
)
del args, code
def setup(bot):
bot.add_cog(OwnerCog(bot))

View file

@ -31,7 +31,6 @@ class SettingsCog(commands.Cog):
base="settings",
name="mute",
description="Set mute role",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="role",
@ -51,7 +50,6 @@ class SettingsCog(commands.Cog):
base="settings",
name="modlog",
description="Set modlog channel",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="channel",
@ -63,7 +61,9 @@ class SettingsCog(commands.Cog):
)
@commands.has_permissions(administrator=True)
async def _modlog(self, ctx, channel: TextChannel):
await ctx.defer()
if not isinstance(channel, TextChannel):
await ctx.send("Channel must be a TextChannel", hidden=True)
return
self.update_settings("modlog", channel.id, ctx.guild.id)
await ctx.send(
f"Settings applied. New modlog channel is {channel.mention}"
@ -73,7 +73,6 @@ class SettingsCog(commands.Cog):
base="settings",
name="userlog",
description="Set userlog channel",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="channel",
@ -85,7 +84,9 @@ class SettingsCog(commands.Cog):
)
@commands.has_permissions(administrator=True)
async def _userlog(self, ctx, channel: TextChannel):
await ctx.defer()
if not isinstance(channel, TextChannel):
await ctx.send("Channel must be a TextChannel", hidden=True)
return
self.update_settings("userlog", channel.id, ctx.guild.id)
await ctx.send(
f"Settings applied. New userlog channel is {channel.mention}"
@ -95,7 +96,6 @@ class SettingsCog(commands.Cog):
base="settings",
name="massmention",
description="Set massmention amount",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="amount",
@ -115,7 +115,6 @@ class SettingsCog(commands.Cog):
base="settings",
name="verified",
description="Set verified role",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="role",
@ -135,7 +134,6 @@ class SettingsCog(commands.Cog):
base="settings",
name="unverified",
description="Set unverified role",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="role",

View file

@ -2,12 +2,13 @@ from datetime import datetime
import aiohttp
import discord
import jarvis
from discord import Message, TextChannel
from discord.ext import commands
from discord.utils import find
from discord_slash import SlashContext, cog_ext
from discord_slash.utils.manage_commands import create_option
import jarvis
from jarvis.config import get_config
from jarvis.utils import build_embed
from jarvis.utils.db import DBManager
@ -32,7 +33,6 @@ class StarboardCog(commands.Cog):
base="starboard",
name="list",
description="Lists all Starboards",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
)
@commands.has_permissions(administrator=True)
async def _list(self, ctx):
@ -51,7 +51,6 @@ class StarboardCog(commands.Cog):
base="starboard",
name="create",
description="Create a starboard",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="target",
@ -69,6 +68,9 @@ class StarboardCog(commands.Cog):
hidden=True,
)
return
if not isinstance(target, TextChannel):
await ctx.send("Target must be a TextChannel", hidden=True)
return
exists = self.db.jarvis.starboard.find_one(
{"target": target.id, "guild": ctx.guild.id}
)
@ -92,7 +94,6 @@ class StarboardCog(commands.Cog):
base="starboard",
name="delete",
description="Delete a starboard",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="channel",
@ -103,28 +104,27 @@ class StarboardCog(commands.Cog):
],
)
@commands.has_permissions(administrator=True)
async def _delete(self, ctx, target: TextChannel):
async def _delete(self, ctx, channel: TextChannel):
deleted = self.db.jarvis.starboard.delete_one(
{
"target": target.id,
"target": channel.id,
"guild": ctx.guild.id,
}
)
if deleted:
self.db.jarvis.stars.delete_many({"starboard": target.id})
self.db.jarvis.stars.delete_many({"starboard": channel.id})
await ctx.send(
f"Starboard deleted from {target.mention}.", hidden=True
f"Starboard deleted from {channel.mention}.", hidden=True
)
else:
await ctx.send(
f"Starboard not found in {target.mention}.", hidden=True
f"Starboard not found in {channel.mention}.", hidden=True
)
@cog_ext.cog_subcommand(
base="star",
name="add",
description="Star a message",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
options=[
create_option(
name="message",
@ -238,6 +238,70 @@ class StarboardCog(commands.Cog):
"Message saved to Starboard.\n" + f"See it in {starboard.mention}"
)
@cog_ext.cog_subcommand(
base="star",
name="delete",
description="Delete a starred message",
guild_ids=[
862402786116763668,
418094694325813248,
578757004059738142,
],
options=[
create_option(
name="id",
description="Star to delete",
option_type=4,
required=True,
),
create_option(
name="starboard",
description="Starboard to delete star from",
option_type=7,
required=True,
),
],
)
async def _star_get(
self,
ctx: SlashContext,
id: int,
starboard: TextChannel,
):
exists = self.db.jarvis.starboard.find_one(
{"target": starboard.id, "guild": ctx.guild.id}
)
if not exists:
await ctx.send(
f"Starboard does not exist in {starboard.mention}. "
+ "Please create it first",
hidden=True,
)
return
star = self.db.jarvis.stars.find_one(
{
"starboard": starboard.id,
"id": id,
"guild": ctx.guild.id,
"active": True,
}
)
if not star:
await ctx.send(f"No star exists with id {id}", hidden=True)
return
message = await starboard.fetch_message(star["star"])
if message:
await message.delete()
self.db.jarvis.stars.update_one(
{"starboard": starboard.id, "id": id, "guild": ctx.guild.id},
{"$set": {"active": False}},
)
await ctx.send(f"Star {id} deleted")
def setup(bot):
bot.add_cog(StarboardCog(bot))

View file

@ -25,7 +25,6 @@ class UtilCog(commands.Cog):
@cog_ext.cog_slash(
name="status",
description="Retrieve J.A.R.V.I.S. status",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _status(self, ctx):
title = "J.A.R.V.I.S. Status"
@ -51,7 +50,6 @@ class UtilCog(commands.Cog):
@cog_ext.cog_slash(
name="logo",
description="Get the current logo",
guild_ids=[862402786116763668, 578757004059738142],
)
async def _logo(self, ctx):
lo = logo.get_logo(self.config.logo)
@ -60,7 +58,6 @@ class UtilCog(commands.Cog):
@cog_ext.cog_slash(
name="rcauto",
description="Automates robot camo letters",
guild_ids=[862402786116763668, 578757004059738142],
options=[
create_option(
name="text",
@ -72,7 +69,9 @@ class UtilCog(commands.Cog):
)
async def _rcauto(self, ctx: SlashContext, text: str):
to_send = ""
if len(text) == 1 and not re.match(r"^[A-Z0-9-()$@!?^'#. ]$", text):
if len(text) == 1 and not re.match(
r"^[A-Z0-9-()$@!?^'#. ]$", text.upper()
):
await ctx.send("Please use ASCII characters.", hidden=True)
return
for letter in text.upper():

View file

@ -38,7 +38,6 @@ class VerifyCog(commands.Cog):
@cog_ext.cog_slash(
name="verify",
description="Verify that you've read the rules",
guild_ids=[862402786116763668, 418094694325813248, 578757004059738142],
)
async def _verify(self, ctx: SlashContext):
await ctx.defer()