First official build of bot!
Co-authored-by: iakrules <64628083+iakrules@noreply.github.com>
This commit is contained in:
parent
953c89ead0
commit
2b8e2345f9
32 changed files with 1164 additions and 383 deletions
|
|
@ -1,162 +1,161 @@
|
|||
import asyncio
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
import youtube_dl
|
||||
import os
|
||||
|
||||
ffmpeg_options = {
|
||||
'options': '-vn'
|
||||
}
|
||||
|
||||
ytdl_format_options = {
|
||||
'format': 'bestaudio/best',
|
||||
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
|
||||
'restrictfilenames': True,
|
||||
'noplaylist': True,
|
||||
'nocheckcertificate': True,
|
||||
'ignoreerrors': False,
|
||||
'logtostderr': False,
|
||||
'quiet': True,
|
||||
'no_warnings': True,
|
||||
'default_search': 'auto',
|
||||
'source_address': '0.0.0.0' # bind to ipv4 since ipv6 addresses cause issues sometimes
|
||||
}
|
||||
|
||||
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
|
||||
|
||||
class YTDLSource(discord.PCMVolumeTransformer):
|
||||
def __init__(self, source, *, data, volume=0.5):
|
||||
super().__init__(source, volume)
|
||||
|
||||
self.data = data
|
||||
|
||||
self.title = data.get('title')
|
||||
self.url = data.get('url')
|
||||
|
||||
@classmethod
|
||||
async def from_url(cls, url, *, loop=None, stream=False):
|
||||
loop = loop or asyncio.get_event_loop()
|
||||
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
|
||||
|
||||
if 'entries' in data:
|
||||
# take first item from a playlist
|
||||
data = data['entries'][0]
|
||||
|
||||
filename = data['url'] if stream else ytdl.prepare_filename(data)
|
||||
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
|
||||
|
||||
class MusicCog(commands.Cog):
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
# Commands
|
||||
|
||||
@commands.command()
|
||||
async def play(self, ctx, url):
|
||||
"""Streams from a url"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
try:
|
||||
channel = ctx.author.voice.channel
|
||||
await channel.connect()
|
||||
except:
|
||||
pass
|
||||
async with ctx.typing():
|
||||
player = await YTDLSource.from_url(url, loop=self.client.loop, stream=True)
|
||||
ctx.voice_client.play(player, after=lambda e: print(f'Player error: {e}') if e else None)
|
||||
await ctx.send(f'Now playing: {player.title}')
|
||||
|
||||
@play.error
|
||||
async def play_error(self, ctx, error):
|
||||
if isinstance(error, commands.MissingRequiredArgument):
|
||||
voice = ctx.voice_client
|
||||
if voice != None and voice.is_paused():
|
||||
voice.resume()
|
||||
else:
|
||||
await ctx.send("Missing URL!")
|
||||
|
||||
@commands.command(aliases=['disconnect, dc'])
|
||||
async def leave(self, ctx):
|
||||
"""Disconnects bot from the voice channel"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
voice = ctx.voice_client
|
||||
if voice is not None:
|
||||
if voice.is_connected():
|
||||
await voice.disconnect()
|
||||
else:
|
||||
await ctx.send("The bot is not connected to a voice channel.")
|
||||
|
||||
@commands.command()
|
||||
async def volume(self, ctx, volume: int):
|
||||
"""Changes the player's volume"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
if ctx.voice_client is None:
|
||||
return await ctx.send("Not connected to a voice channel.")
|
||||
|
||||
ctx.voice_client.source.volume = volume / 100
|
||||
await ctx.send(f"Changed volume to {volume}%")
|
||||
|
||||
@commands.command()
|
||||
async def pause(self, ctx):
|
||||
"""Pauses audio"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
voice = ctx.voice_client
|
||||
if voice.is_playing():
|
||||
voice.pause()
|
||||
else:
|
||||
await ctx.send("Currently no audio is playing.")
|
||||
|
||||
@commands.command()
|
||||
async def resume(self, ctx):
|
||||
"""Resumes currently paused audio"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
voice = ctx.voice_client
|
||||
if voice.is_paused():
|
||||
voice.resume()
|
||||
else:
|
||||
await ctx.send("The audio is not paused.")
|
||||
|
||||
@commands.command()
|
||||
async def stop(self, ctx):
|
||||
"""Stops and disconnects the bot from voice"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
voice = ctx.voice_client
|
||||
if voice:
|
||||
voice.stop()
|
||||
|
||||
@commands.command(aliases=['join'])
|
||||
async def connect(self, ctx):
|
||||
"""Connects bot to currently connected voice channel"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
channel = ctx.author.voice.channel
|
||||
try:
|
||||
await channel.connect()
|
||||
except:
|
||||
voice = ctx.voice_client
|
||||
if voice.is_connected() and voice.channel != channel:
|
||||
await voice.disconnect()
|
||||
await channel.connect()
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(MusicCog(client))
|
||||
import asyncio
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
import youtube_dl
|
||||
import os
|
||||
|
||||
ffmpeg_options = {
|
||||
'options': '-vn'
|
||||
}
|
||||
|
||||
ytdl_format_options = {
|
||||
'format': 'bestaudio/best',
|
||||
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
|
||||
'restrictfilenames': True,
|
||||
'noplaylist': True,
|
||||
'nocheckcertificate': True,
|
||||
'ignoreerrors': False,
|
||||
'logtostderr': False,
|
||||
'quiet': True,
|
||||
'no_warnings': True,
|
||||
'default_search': 'auto',
|
||||
'source_address': '0.0.0.0' # Bind to ipv4 since ipv6 addresses cause issues sometimes
|
||||
}
|
||||
|
||||
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
|
||||
|
||||
class YTDLSource(discord.PCMVolumeTransformer):
|
||||
def __init__(self, source, *, data, volume=0.5):
|
||||
super().__init__(source, volume)
|
||||
|
||||
self.data = data
|
||||
|
||||
self.title = data.get('title')
|
||||
self.url = data.get('url')
|
||||
|
||||
@classmethod
|
||||
async def from_url(cls, url, *, loop=None, stream=False):
|
||||
loop = loop or asyncio.get_event_loop()
|
||||
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
|
||||
|
||||
if 'entries' in data:
|
||||
# Take first item from a playlist
|
||||
data = data['entries'][0]
|
||||
|
||||
filename = data['url'] if stream else ytdl.prepare_filename(data)
|
||||
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
|
||||
|
||||
class AudioCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command()
|
||||
async def play(self, ctx, url):
|
||||
"""Streams from a url"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
try:
|
||||
channel = ctx.author.voice.channel
|
||||
await channel.connect()
|
||||
except:
|
||||
pass
|
||||
async with ctx.typing():
|
||||
player = await YTDLSource.from_url(url, loop=self.bot.loop, stream=True)
|
||||
ctx.voice_client.play(player, after=lambda e: print(f'Player error: {e}') if e else None)
|
||||
await ctx.send(f'Now playing: {player.title}')
|
||||
|
||||
@play.error
|
||||
async def play_error(self, ctx, error):
|
||||
if isinstance(error, commands.MissingRequiredArgument):
|
||||
voice = ctx.voice_client
|
||||
if voice != None and voice.is_paused():
|
||||
voice.resume()
|
||||
else:
|
||||
await ctx.send("Missing URL!")
|
||||
|
||||
@commands.command(aliases=['disconnect, dc'])
|
||||
async def leave(self, ctx):
|
||||
"""Disconnects bot from the voice channel"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
voice = ctx.voice_client
|
||||
if voice is not None:
|
||||
if voice.is_connected():
|
||||
await voice.disconnect()
|
||||
else:
|
||||
await ctx.send("The bot is not connected to a voice channel.")
|
||||
|
||||
@commands.command()
|
||||
async def volume(self, ctx, volume: int):
|
||||
"""Changes the player's volume"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
if ctx.voice_client is None:
|
||||
return await ctx.send("Not connected to a voice channel.")
|
||||
|
||||
ctx.voice_client.source.volume = volume / 100
|
||||
await ctx.send(f"Changed volume to {volume}%")
|
||||
|
||||
@commands.command()
|
||||
async def pause(self, ctx):
|
||||
"""Pauses audio"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
voice = ctx.voice_client
|
||||
if voice.is_playing():
|
||||
voice.pause()
|
||||
else:
|
||||
await ctx.send("Currently no audio is playing.")
|
||||
|
||||
@commands.command()
|
||||
async def resume(self, ctx):
|
||||
"""Resumes currently paused audio"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
voice = ctx.voice_client
|
||||
if voice.is_paused():
|
||||
voice.resume()
|
||||
else:
|
||||
await ctx.send("The audio is not paused.")
|
||||
|
||||
@commands.command()
|
||||
async def stop(self, ctx):
|
||||
"""Stops and disconnects the bot from voice"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
voice = ctx.voice_client
|
||||
if voice:
|
||||
voice.stop()
|
||||
|
||||
@commands.command(aliases=['join'])
|
||||
async def connect(self, ctx):
|
||||
"""Connects bot to currently connected voice channel"""
|
||||
|
||||
if ctx.author.voice is None:
|
||||
return await ctx.send("You're not connected to a voice channel.")
|
||||
|
||||
channel = ctx.author.voice.channel
|
||||
try:
|
||||
await channel.connect()
|
||||
except:
|
||||
voice = ctx.voice_client
|
||||
if voice.is_connected() and voice.channel != channel:
|
||||
await voice.disconnect()
|
||||
await channel.connect()
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(AudioCog(bot))
|
||||
|
|
@ -1,59 +1,56 @@
|
|||
import os
|
||||
import discord
|
||||
import DiscordUtils
|
||||
import datetime
|
||||
from dateutil.parser import parse
|
||||
import requests
|
||||
from discord.ext import commands
|
||||
|
||||
class CalendarCog(commands.Cog):
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
# Commands
|
||||
@commands.command()
|
||||
async def events(self, ctx):
|
||||
"""Gets all upcoming events from Google Calendar"""
|
||||
# Check if environment variable exists
|
||||
if not os.environ.get("GOOGLE_CALENDAR_ENDPOINT"):
|
||||
return await ctx.send("No Google Calendar endpoint specified!")
|
||||
|
||||
# Get upcoming events data from calendar
|
||||
current_time = datetime.datetime.utcnow()
|
||||
formatted_time = current_time.isoformat("T") + "Z"
|
||||
calendar = os.environ.get("GOOGLE_CALENDAR_ENDPOINT") + "&timeMin=" + formatted_time
|
||||
data = requests.get(calendar).json()
|
||||
|
||||
# Check if there are any events
|
||||
if not data["items"]:
|
||||
return await ctx.send("There are no upcoming events!")
|
||||
|
||||
# Get all upcoming events as a list
|
||||
list_of_events = data["items"]
|
||||
embeds = []
|
||||
|
||||
for event in list_of_events:
|
||||
# Create data set
|
||||
title = event["summary"]
|
||||
start_time = event["start"]["dateTime"]
|
||||
description = "No description."
|
||||
if "description" in event:
|
||||
description = event["description"]
|
||||
formatted_start_time = datetime.datetime.strftime(parse(start_time), format="%B %d, %Y")
|
||||
|
||||
# Create embed for single event and add to embeds list
|
||||
embed = discord.Embed(color=ctx.author.color, title=title, description=description)
|
||||
embed.add_field(name="Starts On", value=formatted_start_time, inline=True)
|
||||
embeds.append(embed)
|
||||
|
||||
# Create paginator
|
||||
paginator = DiscordUtils.Pagination.CustomEmbedPaginator(ctx)
|
||||
paginator.add_reaction('⏮️', "first")
|
||||
paginator.add_reaction('⏪', "back")
|
||||
paginator.add_reaction('⏩', "next")
|
||||
paginator.add_reaction('⏭️', "last")
|
||||
await paginator.run(embeds)
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(CalendarCog(client))
|
||||
import os
|
||||
import discord
|
||||
import DiscordUtils
|
||||
import datetime
|
||||
from dateutil.parser import parse
|
||||
import requests
|
||||
from discord.ext import commands
|
||||
|
||||
class CalendarCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command()
|
||||
async def events(self, ctx):
|
||||
"""Gets all upcoming events from Google Calendar"""
|
||||
# Check if environment variable exists
|
||||
if not os.environ.get("GOOGLE_CALENDAR_ENDPOINT"):
|
||||
return await ctx.send("No Google Calendar endpoint specified!")
|
||||
|
||||
# Get upcoming events data from calendar
|
||||
current_time = datetime.datetime.utcnow()
|
||||
formatted_time = current_time.isoformat("T") + "Z"
|
||||
calendar = os.environ.get("GOOGLE_CALENDAR_ENDPOINT") + "&timeMin=" + formatted_time
|
||||
data = requests.get(calendar).json()
|
||||
|
||||
# Check if there are any events
|
||||
if not data["items"]:
|
||||
return await ctx.send("There are no upcoming events!")
|
||||
|
||||
# Get all upcoming events as a list
|
||||
list_of_events = data["items"]
|
||||
embeds = []
|
||||
|
||||
for event in list_of_events:
|
||||
# Create data set
|
||||
title = event["summary"]
|
||||
start_time = event["start"]["dateTime"]
|
||||
description = event["description"] if "description" in event else "No description."
|
||||
formatted_start_time = datetime.datetime.strftime(parse(start_time), format="%B %d, %Y")
|
||||
# Create embed for single event and add to embeds list
|
||||
embed = discord.Embed(color=ctx.author.color, title=title, description=description)
|
||||
embed.add_field(name="Starts On", value=formatted_start_time, inline=True)
|
||||
embeds.append(embed)
|
||||
|
||||
# Create paginator
|
||||
paginator = DiscordUtils.Pagination.CustomEmbedPaginator(ctx)
|
||||
paginator.add_reaction('⏮️', "first")
|
||||
paginator.add_reaction('⏪', "back")
|
||||
paginator.add_reaction('⏩', "next")
|
||||
paginator.add_reaction('⏭️', "last")
|
||||
await paginator.run(embeds)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(CalendarCog(bot))
|
||||
30
cogs/info/infoCog.py
Normal file
30
cogs/info/infoCog.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class InfoCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command(aliases=['botinfo'])
|
||||
async def info(self, ctx):
|
||||
embed = discord.Embed(
|
||||
title=f"Rutgers Esports Bot <:RutgersEsports:608498339192766505>",
|
||||
description=(
|
||||
f'Rutgers Esports Bot is the official Discord bot\n'
|
||||
'for handling all internal Rutgers Esports operations.\n\n'
|
||||
'🔗 Check out Rutgers Esports '
|
||||
'[here](https://linktr.ee/RutgersEsports).\n'
|
||||
'🤖 To add this bot to your server use '
|
||||
'[this link](https://bit.ly/rutgers-esports-bot).\n'
|
||||
"⭐ Star our repo on GitHub [here](https://github.com/rutgersesports/discord-bot)."
|
||||
),
|
||||
color=0xC94949
|
||||
)
|
||||
embed.set_thumbnail(url=ctx.bot.user.avatar_url)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(InfoCog(bot))
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class PingCog(commands.Cog):
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
# Commands
|
||||
@commands.command(aliases=['latency'])
|
||||
async def ping(self, ctx):
|
||||
"""Returns the bot client latency"""
|
||||
await ctx.send(f'Pong! {round(self.client.latency * 1000)}ms')
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(PingCog(client))
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class PingCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command(aliases=['latency'])
|
||||
async def ping(self, ctx):
|
||||
"""Returns the bot bot latency"""
|
||||
await ctx.send(f'Pong! {round(self.bot.latency * 1000)}ms')
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(PingCog(bot))
|
||||
35
cogs/info/serverCog.py
Normal file
35
cogs/info/serverCog.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class ServerCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command(aliases=['server', 'sinfo'])
|
||||
async def serverinfo(self, ctx):
|
||||
"""Get information about the current server"""
|
||||
guild = ctx.guild
|
||||
|
||||
roles = str(len(guild.roles))
|
||||
emojis = str(len(guild.emojis))
|
||||
vchannels = str(len(guild.voice_channels))
|
||||
tchannels = str(len(guild.text_channels))
|
||||
|
||||
embed = discord.Embed(title='Server info', description=guild.name, color=ctx.guild.get_member(ctx.bot.user.id).color)
|
||||
embed.set_thumbnail(url=guild.icon_url)
|
||||
embed.add_field(name='ID', value=guild.id, inline=True)
|
||||
embed.add_field(name='Owner', value=guild.owner, inline=True)
|
||||
embed.add_field(name='Members', value=guild.member_count, inline=True)
|
||||
embed.add_field(name='Text channels', value=tchannels, inline=True)
|
||||
embed.add_field(name='Voice channels', value=vchannels, inline=True)
|
||||
embed.add_field(name='Created on', value=guild.created_at.strftime('%B %d, %Y'), inline=True)
|
||||
embed.add_field(name='Region', value=guild.region, inline=True)
|
||||
embed.add_field(name='Roles', value=roles, inline=True)
|
||||
embed.add_field(name='Verification', value=guild.verification_level, inline=True)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(ServerCog(bot))
|
||||
44
cogs/info/userCog.py
Normal file
44
cogs/info/userCog.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class UserCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command(aliases=['whois'])
|
||||
async def userinfo(self, ctx, member: discord.Member = None):
|
||||
"""Get information about a given user"""
|
||||
# Gather data
|
||||
member = ctx.author if not member else member
|
||||
roles = [role for role in member.roles]
|
||||
default_role = discord.utils.get(member.guild.roles, name='@everyone')
|
||||
role_mentions = [f'{role.mention}' for role in sorted(member.roles, key=lambda x: x.position, reverse=True) if role != default_role]
|
||||
all_perms = [x for x in dir(ctx.channel.permissions_for(member))]
|
||||
permissions = []
|
||||
for perm in all_perms:
|
||||
perm_name = perm
|
||||
if getattr(ctx.channel.permissions_for(member), perm_name) is True:
|
||||
permissions.append(perm_name.title().replace("_", " ").replace("Tts", "TTS"))
|
||||
|
||||
# Create embed
|
||||
embed = discord.Embed(description = member.mention, color = member.color, timestamp = ctx.message.created_at)
|
||||
|
||||
embed.set_author(name = member, icon_url = member.avatar_url)
|
||||
embed.set_thumbnail(url = member.avatar_url)
|
||||
embed.set_footer(text = member.id)
|
||||
|
||||
embed.add_field(name = 'Joined', value = member.joined_at.strftime('%a, %d %B %Y, %I:%M %p UTC'), inline=True)
|
||||
embed.add_field(name = 'Registered', value = member.created_at.strftime('%a, %d %B %Y, %I:%M %p UTC'), inline=True)
|
||||
|
||||
embed.add_field(name=f'Roles [{len(roles)}]', value=", ".join(role_mentions)+f', {default_role}', inline=False)
|
||||
embed.add_field(name=f'Permissions [{len(permissions)}]', value=", ".join(permissions), inline=False)
|
||||
|
||||
|
||||
embed.add_field(name='Nickname', value=member.nick if hasattr(member, 'nick') else 'None', inline=True)
|
||||
|
||||
await ctx.send(embed = embed)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(UserCog(bot))
|
||||
|
|
@ -1,61 +1,61 @@
|
|||
import os
|
||||
import discord
|
||||
import DiscordUtils
|
||||
import asyncio
|
||||
from google.cloud import firestore
|
||||
from discord.ext import commands
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
class InventoryCog(commands.Cog):
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
# Commands
|
||||
|
||||
# Get a single item from inventory
|
||||
@commands.command(aliases=['inv'])
|
||||
@commands.is_owner()
|
||||
async def inventory(self, ctx, arg1):
|
||||
"""Get a single item from the inventory database"""
|
||||
|
||||
# Make single input embed
|
||||
def single_embed(item, id):
|
||||
embed = discord.Embed(title=item["item_name"], description=id)
|
||||
if item["item_type"] != "": embed.add_field(name="Item Type", value=item["item_type"], inline=True)
|
||||
if item["color"] != "": embed.add_field(name="Color", value=item["color"], inline=True)
|
||||
if item["brand"] != "": embed.add_field(name="Brand", value=item["brand"], inline=True)
|
||||
if item["model"] != "": embed.add_field(name="Model", value=item["model"], inline=True)
|
||||
if item["size"] != "": embed.add_field(name="Size", value=item["size"], inline=True)
|
||||
if item["quantity"] != "": embed.add_field(name="Quantity", value=item["quantity"], inline=True)
|
||||
if item["box"] != "": embed.add_field(name="Box", value=item["box"], inline=True)
|
||||
return embed
|
||||
|
||||
# Connect to Firestore DB inventory collection and get the item arg1 as doc
|
||||
if "INVENTORY_PROJECT_ID" in os.environ and "GOOGLE_APPLICATION_CREDENTIALS" in os.environ:
|
||||
try:
|
||||
db = firestore.AsyncClient(project=os.environ.get("INVENTORY_PROJECT_ID"))
|
||||
inventory_ref = db.collection("inventory").document(arg1)
|
||||
doc = await inventory_ref.get()
|
||||
|
||||
if doc.exists:
|
||||
await ctx.send(embed=single_embed(doc.to_dict(), doc.id))
|
||||
else:
|
||||
await ctx.send("That ID doesn't exist!")
|
||||
except:
|
||||
await ctx.send("The DB connection is not working.")
|
||||
elif "INVENTORY_PROJECT_ID" not in os.environ and "GOOGLE_APPLICATION_CREDENTIALS" in os.environ:
|
||||
await ctx.send("Inventory Project ID not found!")
|
||||
elif "GOOGLE_APPLICATION_CREDENTIALS" not in os.environ:
|
||||
await ctx.send("GAPP Credentials not found!")
|
||||
|
||||
@inventory.error
|
||||
async def inventory_error(self, ctx, error):
|
||||
if isinstance(error, commands.MissingRequiredArgument):
|
||||
await ctx.send("Missing required argument! (e.g. d!inventory __10000__)")
|
||||
if isinstance(error, commands.NotOwner):
|
||||
await ctx.send("You do not have permissions to run this command.")
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(InventoryCog(client))
|
||||
import os
|
||||
import discord
|
||||
import DiscordUtils
|
||||
import asyncio
|
||||
from google.cloud import firestore
|
||||
from discord.ext import commands
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
class InventoryCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
# Get a single item from inventory
|
||||
@commands.command(aliases=['inv'])
|
||||
@commands.is_owner()
|
||||
async def inventory(self, ctx, arg1):
|
||||
"""Get a single item from the inventory database"""
|
||||
|
||||
# Make single input embed
|
||||
def single_embed(item, id):
|
||||
embed = discord.Embed(title=item["item_name"], description=id)
|
||||
if item["item_type"] != "": embed.add_field(name="Item Type", value=item["item_type"], inline=True)
|
||||
if item["color"] != "": embed.add_field(name="Color", value=item["color"], inline=True)
|
||||
if item["brand"] != "": embed.add_field(name="Brand", value=item["brand"], inline=True)
|
||||
if item["model"] != "": embed.add_field(name="Model", value=item["model"], inline=True)
|
||||
if item["size"] != "": embed.add_field(name="Size", value=item["size"], inline=True)
|
||||
if item["quantity"] != "": embed.add_field(name="Quantity", value=item["quantity"], inline=True)
|
||||
if item["box"] != "": embed.add_field(name="Box", value=item["box"], inline=True)
|
||||
return embed
|
||||
|
||||
# Connect to Firestore DB inventory collection and get the item arg1 as doc
|
||||
if "INVENTORY_PROJECT_ID" in os.environ and "GOOGLE_APPLICATION_CREDENTIALS" in os.environ:
|
||||
try:
|
||||
db = firestore.AsyncClient(project=os.environ.get("INVENTORY_PROJECT_ID"))
|
||||
inventory_ref = db.collection("inventory").document(arg1)
|
||||
doc = await inventory_ref.get()
|
||||
|
||||
if doc.exists:
|
||||
await ctx.send(embed=single_embed(doc.to_dict(), doc.id))
|
||||
else:
|
||||
await ctx.send("That ID doesn't exist!")
|
||||
except:
|
||||
await ctx.send("The DB connection is not working.")
|
||||
elif "INVENTORY_PROJECT_ID" not in os.environ and "GOOGLE_APPLICATION_CREDENTIALS" in os.environ:
|
||||
await ctx.send("Inventory Project ID not found!")
|
||||
elif "GOOGLE_APPLICATION_CREDENTIALS" not in os.environ:
|
||||
await ctx.send("GAPP Credentials not found!")
|
||||
|
||||
@inventory.error
|
||||
async def inventory_error(self, ctx, error):
|
||||
if isinstance(error, commands.MissingRequiredArgument):
|
||||
await ctx.send("Missing required argument! (e.g. d!inventory __10000__)")
|
||||
if isinstance(error, commands.NotOwner):
|
||||
await ctx.send("You do not have permissions to run this command.")
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(InventoryCog(bot))
|
||||
64
cogs/moderation/embedCog.py
Normal file
64
cogs/moderation/embedCog.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class EmbedCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command()
|
||||
async def embed(self, ctx, *, data):
|
||||
"""Produces a customizable embed"""
|
||||
# Split arguments into a list
|
||||
data = data.split("%%")
|
||||
|
||||
# Set default channel to current channel where command is used
|
||||
channel = ctx.channel
|
||||
|
||||
# Remove [''] surrounding possible channel argument input (slice value to just channel ID)
|
||||
possible_channel = data[0].rstrip()[2:-1]
|
||||
|
||||
# Set channel if channel argument is given
|
||||
try:
|
||||
channel = await commands.TextChannelConverter().convert(ctx, possible_channel)
|
||||
data.pop(0)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
# Check if user has permission to send in given channel
|
||||
if not ctx.guild.get_member(ctx.author.id).permissions_in(channel).send_messages:
|
||||
return await ctx.send(f"You don't have permission to send messages to {channel.mention}!")
|
||||
|
||||
|
||||
# Add possible empty list values to deter IndexError for embed
|
||||
data += [""] * (3-len(data))
|
||||
|
||||
# Create and send embed
|
||||
embed = discord.Embed(
|
||||
title=f"{data[0]}",
|
||||
description=f"{data[1]}",
|
||||
color=ctx.guild.get_member(ctx.bot.user.id).color
|
||||
)
|
||||
embed.set_footer(
|
||||
text=f"{data[2]}"
|
||||
)
|
||||
await channel.send(embed=embed)
|
||||
|
||||
@embed.error
|
||||
async def embed_error(self, ctx, error):
|
||||
await ctx.send(
|
||||
"Type the command in the following format:```.embed #channel_name %% title %% description %% footer```"
|
||||
)
|
||||
embed = discord.Embed(
|
||||
title="Title",
|
||||
description="Description",
|
||||
color=ctx.guild.get_member(ctx.bot.user.id).color
|
||||
)
|
||||
embed.set_footer(
|
||||
text="Footer"
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(EmbedCog(bot))
|
||||
|
|
@ -1,31 +1,31 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class ModerationCog(commands.Cog):
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
# Commands
|
||||
@commands.command()
|
||||
@commands.has_permissions(kick_members = True)
|
||||
async def kick(self, ctx, member : commands.MemberConverter, *, reason="No reason provided."):
|
||||
"""Kick a user from the server"""
|
||||
try:
|
||||
await member.kick(reason=reason)
|
||||
await ctx.send(member.mention + " has been kicked.")
|
||||
except:
|
||||
await ctx.send(f"Unable to kick {member.mention}.\nIs {member.mention} at the same role level or higher than {self.client.user.name}?")
|
||||
|
||||
@commands.command()
|
||||
@commands.has_permissions(ban_members = True)
|
||||
async def ban(self, ctx, member : commands.MemberConverter, *, reason="No reason provided."):
|
||||
"""Ban a user from the server"""
|
||||
try:
|
||||
await member.ban(reason=reason)
|
||||
await ctx.send(member.mention + " has been banned.")
|
||||
except:
|
||||
await ctx.send(f"Unable to ban {member.mention}.\nIs {member.mention} at the same role level or higher than {self.client.user.name}?")
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(ModerationCog(client))
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class ModerationCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command()
|
||||
@commands.has_permissions(kick_members = True)
|
||||
async def kick(self, ctx, member : commands.MemberConverter, *, reason="No reason provided."):
|
||||
"""Kick a user from the server"""
|
||||
try:
|
||||
await member.kick(reason=reason)
|
||||
await ctx.send(member.mention + " has been kicked.")
|
||||
except:
|
||||
await ctx.send(f"Unable to kick {member.mention}.\nIs {member.mention} at the same role level or higher than {self.bot.user.name}?")
|
||||
|
||||
@commands.command()
|
||||
@commands.has_permissions(ban_members = True)
|
||||
async def ban(self, ctx, member : commands.MemberConverter, *, reason="No reason provided."):
|
||||
"""Ban a user from the server"""
|
||||
try:
|
||||
await member.ban(reason=reason)
|
||||
await ctx.send(member.mention + " has been banned.")
|
||||
except:
|
||||
await ctx.send(f"Unable to ban {member.mention}.\nIs {member.mention} at the same role level or higher than {self.bot.user.name}?")
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(ModerationCog(bot))
|
||||
18
cogs/moderation/pruneCog.py
Normal file
18
cogs/moderation/pruneCog.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class PruneCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command(aliases=['clear', 'prune'])
|
||||
@commands.has_permissions(manage_messages=True)
|
||||
async def purge(self, ctx, amount=10):
|
||||
"""Removes a number of messages (10 by default)"""
|
||||
await ctx.channel.purge(limit=amount+1)
|
||||
await ctx.send(f'`{amount}` messages deleted.', delete_after=3)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(PruneCog(bot))
|
||||
23
cogs/owner/loaderCog.py
Normal file
23
cogs/owner/loaderCog.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class LoaderCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.is_owner()
|
||||
@commands.command()
|
||||
async def load(self, ctx, extension):
|
||||
"""Loads a cog"""
|
||||
self.bot.load_extension(f'cogs.{extension}')
|
||||
|
||||
@commands.is_owner()
|
||||
@commands.command()
|
||||
async def unload(self, ctx, extension):
|
||||
"""Unloads a cog"""
|
||||
self.bot.unload_extension(f'cogs.{extension}')
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(LoaderCog(bot))
|
||||
18
cogs/owner/sayCog.py
Normal file
18
cogs/owner/sayCog.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class SayCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command(aliases=['speak'])
|
||||
@commands.is_owner()
|
||||
async def say(self, ctx, *, content):
|
||||
"""Lets the bot say given arguments"""
|
||||
await ctx.message.delete()
|
||||
await ctx.send(content)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(SayCog(bot))
|
||||
29
cogs/owner/statusCog.py
Normal file
29
cogs/owner/statusCog.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class StatusCog(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Commands
|
||||
@commands.command(aliases=['botstatus', 'stat'])
|
||||
@commands.is_owner()
|
||||
async def status(self, ctx):
|
||||
"""Gives bot statistics"""
|
||||
# Total members of all servers bot is in
|
||||
total_guild_users = 0
|
||||
for guild in ctx.bot.guilds:
|
||||
total_guild_users += guild.member_count
|
||||
|
||||
embed = discord.Embed(
|
||||
title=f"Bot Status",
|
||||
description=(f'`{ctx.bot.user.name}` is online.'
|
||||
f'\nBot is in `{len(ctx.bot.guilds)}` guilds.'
|
||||
f'\nGuilds have `{total_guild_users}` members.'),
|
||||
color=ctx.guild.get_member(ctx.bot.user.id).color
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(StatusCog(bot))
|
||||
Loading…
Add table
Add a link
Reference in a new issue