Update to main

This commit is contained in:
Die Antwoord 2023-01-24 09:31:38 +02:00
parent 6226f61a05
commit a26c17bcd8
2 changed files with 571 additions and 4 deletions

566
bot.py
View File

@ -0,0 +1,566 @@
import asyncio
import json
import os
import os.path
import platform
import random
import sys
import aiohttp
import aiosqlite
import random
from random import randint
import requests
from requests import get
import time
import datetime
from datetime import datetime, timedelta, timezone
import discord
from discord.ext import commands, tasks
from discord.ext.commands import Bot, Context
from discord.utils import get
import exceptions
from helpers import checks
# ---------------------------------------------------------------------------------------
# Loads config.json
# ---------------------------------------------------------------------------------------
if not os.path.isfile("config.json"):
sys.exit("'config.json' not found! Please add it and try again.")
else:
with open("config.json") as file:
config = json.load(file)
# ---------------------------------------------------------------------------------------
# Intents Listing
# ---------------------------------------------------------------------------------------
intents = discord.Intents.all()
intents.members = True
intents.message_content = True
intents.messages = True # `message_content` is required to get the content of the messages
intents.presences = True
intents.bans = True
intents.dm_messages = True
intents.dm_reactions = True
intents.dm_typing = True
intents.emojis = True
intents.emojis_and_stickers = True
intents.guild_messages = True
intents.guild_reactions = True
intents.guild_scheduled_events = True
intents.guild_typing = True
intents.guilds = True
intents.integrations = True
intents.invites = True
intents.reactions = True
intents.typing = True
intents.voice_states = True
intents.webhooks = True
# ---------------------------------------------------------------------------------------
# Def what happend on mention or msg
# ---------------------------------------------------------------------------------------
bot = Bot(command_prefix=commands.when_mentioned_or(
config["prefix"]), intents=intents, help_command=None)
bot.config = config
# ---------------------------------------------------------------------------------------
# DB Set
# ---------------------------------------------------------------------------------------
async def init_db():
async with aiosqlite.connect(f"{os.path.realpath(os.path.dirname(__file__))}/database/database.db") as db:
with open(f"{os.path.realpath(os.path.dirname(__file__))}/database/schema.sql") as file:
await db.executescript(file.read())
await db.commit()
# ---------------------------------------------------------------------------------------
# Webhook Logs
# ---------------------------------------------------------------------------------------
url = config["webhook"]
def weblogsend(msg):
data = {
"content" : msg,
"username": {context.author}
}
result = requests.post(url, json = data)
try:
result.raise_for_status()
except requests.exceptions.HTTPError as err:
print(err)
else:
print("Payload delivered successfully, code {}.".format(result.status_code))
# ---------------------------------------------------------------------------------------
# Bot Ready Start
# ---------------------------------------------------------------------------------------
@bot.event
async def on_ready() -> None:
guilds = [guild.id for guild in bot.guilds]
print("--------------------------------------")
print(f"Logged in as {bot.user.name}")
print(f"discord.py API version: {discord.__version__}")
print(f"Python version: {platform.python_version()}")
print(f"Running on: {platform.system()} {platform.release()} ({os.name})")
print("--------------------------------------")
print(f"The {bot.user.name} bot is in {len(guilds)} Guilds.\nThe guilds ids list : {guilds}")
print("--------------------------------------")
status_task.start()
if config["sync_commands_globally"]:
print("Syncing commands globally...")
await bot.tree.sync()
# ---------------------------------------------------------------------------------------
# Presence Loop
# ---------------------------------------------------------------------------------------
@tasks.loop(minutes=5)
async def status_task() -> None:
activity = discord.Activity(name=f"over {len(bot.guilds)} guilds\nand {len(bot.users)} users!", type=discord.ActivityType.watching)
await bot.change_presence(activity=activity)
# ---------------------------------------------------------------------------------------
# User joins guild events
# ---------------------------------------------------------------------------------------
@bot.event
async def on_member_join(member) -> None:
role = member.guild.get_role(1061402091542806648) #
await member.add_roles(role, reason="Automatic role by bot")
embed = (
(f"|| <@&MENTION_ROLE_ID> ||\nHello {member.mention}") # MENTION_ROLE_ID = ID of role the will be mentioned on [member.guild_join]
)
discord.Embed(
description=(f"Welcome to 🐱‍🚀{member.guild.name}!\nHope you enjoy your time here."),
color=0x9C84EF
)
embed.set_author(
name="Welcome"
)
embed.add_field(
name="Embed Field Name",
value="``\n> **Frostbite Hosting**\n`🔗` [DISCORD SERVER](<https://discord.gg/uj9QFBuqCx>)\n``\n> **Frostbite Hosting**\n`🔗` [Free Bot Hosting](<https://dashboard.fb-hosting.ga/register?ref=nMHytd8d>)\n``",
inline=False
)
channel = await bot.fetch_channel(GUILD_WELCOME_CHANNEL_ID) # Replace GUILD_WELCOME_CHANNEL_ID with to the channel ID where it should announce the embed.
await channel.send(embed=embed)
await member.send(embed=embed)
# ---------------------------------------------------------------------------------------
# The code in this event is executed every time someone sends a message, with or without the prefix
# ---------------------------------------------------------------------------------------
@bot.event
async def on_message(message: discord.Message):
if message.author.id == bot.user.id or message.author.bot:
return
if not message.guild:
logchannel = bot.get_guild(guild_id).get_channel(channel_id) # Define the log channel when someone DM's the bot with [guild ID] and [channel ID]
embed = discord.Embed(
title="User MSG BOT DMs ",
colour=0x000,
description=f"**From:** {message.author.mention}\n\n*{message.content}*"
)
embed.set_footer(
text=message.author,
icon_url=message.author.avatar.url
)
await logchannel.send(embed=embed)
await bot.process_commands(message)
# ---------------------------------------------------------------------------------------
# Error handling
# This is global error handling, if you for instance want to except every CommandOnCooldown exception, you can do it like this
# ---------------------------------------------------------------------------------------
# on_command_completion
# ---------------------------------------------------------------------------------------
@bot.event
async def on_command_completion(context: Context) -> None:
full_command_name = context.command.qualified_name
split = full_command_name.split(" ")
executed_command = str(split[0])
if context.guild is not None:
print(
f"Executed {executed_command} command in {context.guild.name} (ID: {context.guild.id}) by {context.author} (ID: {context.author.id})")
else:
print(
f"Executed {executed_command} command by {context.author} (ID: {context.author.id}) in DMs")
# ---------------------------------------------------------------------------------------
# on_command_error
# ---------------------------------------------------------------------------------------
@bot.event
async def on_command_error(context: Context, error) -> None:
if isinstance(error, commands.CommandOnCooldown):
minutes, seconds = divmod(error.retry_after, 60)
hours, minutes = divmod(minutes, 60)
hours = hours % 24
embed = discord.Embed(
title="Hey, Stop that . you will break me",
description=f"You can use this command again in {f'{round(hours)} hours' if round(hours) > 0 else ''} {f'{round(minutes)} minutes' if round(minutes) > 0 else ''} {f'{round(seconds)} seconds' if round(seconds) > 0 else ''}.",
color=0xE02B2B
)
await context.send(embed=embed)
elif isinstance(error, exceptions.UserBlacklisted):
embed = discord.Embed(
title="Error!",
description="You are blacklisted from using the bot.",
color=0xE02B2B
)
await context.send(embed=embed)
elif isinstance(error, exceptions.UserNotOwner):
embed = discord.Embed(
title="Error!",
description="You are not the owner of the bot!",
color=0xE02B2B
)
await context.send(embed=embed)
elif isinstance(error, commands.MissingPermissions):
embed = discord.Embed(
title="Error!",
description="You are missing the permission(s) `" + ", ".join(
error.missing_permissions) + "` to execute this command!",
color=0xE02B2B
)
await context.send(embed=embed)
elif isinstance(error, commands.MissingRequiredArgument):
embed = discord.Embed(
title="Error!",
# We need to capitalize because the command arguments have no capital letter in the code.
description=str(error).capitalize(),
color=0xE02B2B
)
await context.send(embed=embed)
raise error
# ---------------------------------------------------------------------------------------
# Load COGS for this bot
# ---------------------------------------------------------------------------------------
async def load_cogs() -> None:
for file in os.listdir(f"./cogs"):
if file.endswith(".py"):
extension = file[:-3]
try:
await bot.load_extension(f"cogs.{extension}")
print(f"Loaded extension '{extension}'")
except Exception as e:
exception = f"{type(e).__name__}: {e}"
print(f"Failed to load extension {extension}\n{exception}")
# ---------------------------------------------------------------------------------------
# LEGACY BOT COMMANDS
# ---------------------------------------------------------------------------------------
# [perfix]groupDM {<@&role>} (message)
# ---------------------------------------------------------------------------------------
@bot.command()
@checks.is_owner()
async def groupDM(context, role: discord.Role, *, message: str) -> None:
for member in role.members:
await member.send(message)
# ---------------------------------------------------------------------------------------
# LIST categories, text channels, voice channels, all channels + categories
# ---------------------------------------------------------------------------------------
# Categories
# ---------------------------------------------------------------------------------------
@bot.command()
@checks.is_owner()
async def cata(context) -> None: # async def cat(context):
for category in context.message.guild.categories: # for category in context.message.guild.categories:
await context.send(f"`{category.id}` - <#{category.id}>") # print(category.name)
# ---------------------------------------------------------------------------------------
# Text channels
# ---------------------------------------------------------------------------------------
@bot.command()
@checks.is_owner()
async def txtChannel(context) -> None:
for text_channel in context.message.guild.text_channels:
await context.send(f"`{text_channel.id}` - <#{text_channel.id}>")
# ---------------------------------------------------------------------------------------
# Voice channels
# ---------------------------------------------------------------------------------------
@bot.command()
@checks.is_owner()
async def vc(context) -> None:
for voice_channel in context.message.guild.voice_channels:
await context.send(f"`{voice_channel.id}` - <#{voice_channel.id}>")
# ---------------------------------------------------------------------------------------
# All Channels + Categories
# ---------------------------------------------------------------------------------------
@bot.command()
@checks.is_owner()
async def channels(context) -> None:
for channel in context.message.guild.channels:
await context.send(f"`{channel.id}` - <#{channel.id}>")
# ---------------------------------------------------------------------------------------
# BOT logs on_guild_join
# ---------------------------------------------------------------------------------------
@bot.event
async def on_guild_join(guild) -> None:
print(guild.name)
print(guild.id)
# ---------------------------------------------------------------------------------------
# BOT logs on_guild_leave
# ---------------------------------------------------------------------------------------
@bot.event
async def on_guild_leave(guild) -> None:
print(guild.name)
print(guild.id)
# ---------------------------------------------------------------------------------------
# verify into the server
# ---------------------------------------------------------------------------------------
@bot.command()
async def verifyme(context, member=None) -> None:
verifyrole = discord.utils.get(context.guild.roles, name="ROLE_NAME") # YOU MUST SPECIFY THE ROLE NAME
try:
await context.author.add_roles(verifyrole)
except Exception as errortoaddroles:
await context.send(f'Error in add roles\n```py\n{errortoaddroles}```')
await context.message.delete()
await member.send(f'{context.author} | {context.author.id} Should now be verified.')
# ---------------------------------------------------------------------------------------
# Countdown/timer
# ---------------------------------------------------------------------------------------
@bot.command()
async def countdown(ctx, t: int):
await ctx.send(f"Counting down from {t}s")
while t > 0:
t -= 1
# Sleep for 1 second
await asyncio.sleep(1)
await ctx.send("Countdown end reached")
# ---------------------------------------------------------------------------------------
# Creating a role, only specifying it's name
# ---------------------------------------------------------------------------------------
@bot.command()
async def create_role(ctx, *, name):
# Create the role
await ctx.guild.create_role(name=name)
await ctx.send(f"Created role with name {name}")
# ---------------------------------------------------------------------------------------
# Adding a role to everybody in the server
# ---------------------------------------------------------------------------------------
@bot.command()
async def addroles(ctx, *, role: discord.Role):
for m in ctx.guild.members:
await m.add_roles(role)
await asyncio.sleep(1)
await ctx.send("Added roles")
# ---------------------------------------------------------------------------------------
# You can also specify specific users to add a role to:
# ---------------------------------------------------------------------------------------
@bot.command()
async def addrole(ctx, role: discord.Role, *members: discord.Member):
for m in members:
await m.add_roles(role)
print(f":white_check_mark: Role {role} added to {m.mention}")
# ---------------------------------------------------------------------------------------
# Sending messages *, arg is useful if you want to consume all as a string
# ---------------------------------------------------------------------------------------
@bot.command()
async def echo(ctx, *, message):
# Delete message that invokes command
await ctx.delete()
# Repeat back the input and auto delete after 20 seconds
await ctx.send(message, delete_after=20)
# ---------------------------------------------------------------------------------------
# Sending messages You can loop over each text channel in a guild, and send a message
# ---------------------------------------------------------------------------------------
@bot.command()
async def sendToAll(ctx, *, message):
for channel in ctx.guild.text_channels:
await channel.send(message)
# ---------------------------------------------------------------------------------------
# User info
# ---------------------------------------------------------------------------------------
def getstatus(m):
if str(m.status) == "dnd":
return "do not disturb"
return m.status
@bot.command()
async def userinfo(ctx, member: discord.Member):
c_delta = datetime.utcnow()
c_at = member.created_at.strftime("%c")
join_pos = sorted(ctx.guild.members, key=lambda member: member.joined_at).index(member) + 1
embed = discord.Embed(
title=f"{member.name}#{member.discriminator}",
timestamp=datetime.utcnow(),
colour=0x000
)
embed.add_field(
name="Status:",
value=getstatus(member),
inline=True
)
embed.add_field(
name="Guild name:",
value=member.display_name,
inline=True
)
embed.add_field(
name="Join position:",
value=f"{join_pos}/{len(ctx.guild.members)}",
inline=True
)
embed.add_field(
name="Created at:",
value=f"{c_at}",
inline=True
)
embed.add_field(
name="ID:",
value=member.id,
inline=True
)
embed.add_field(
name="Bot:",
value="✅ Yes" if member.bot else "❌ No",
inline=True
)
# Setting the thumbnail as the users profile picture
embed.set_thumbnail(
url=member.avatar
)
# Setting a footer
embed.set_footer(
text=f"Requested by {ctx.author.name}",
icon_url=ctx.author.avatar
)
await ctx.send(embed=embed)
# ---------------------------------------------------------------------------------------
# Background task and command group
# We can make command groups which will allow us make subcommands
# ---------------------------------------------------------------------------------------
@tasks.loop(seconds=60) # Loop every 60 seconds
async def loop_function(ctx, message):
await ctx.send(message)
@bot.group(invoke_without_command=True) # Specify that we don't want the 'first' command called when we use a subcommand
async def loop(ctx):
await ctx.send("**1.** Start loop: `.loop start {message}`\n**2.** Stop loop: `.loop stop`")
@loop.command() # Subcommand named 'start', so called like this: "PREFIXloop start message goes here"
async def start(ctx, *, message):
await ctx.send("**Starting loop...**")
# Starting the loop function
loop_function.start(ctx, message)
@loop.command() # Subcommand named stop
async def stop(ctx):
await ctx.send("**Stopping loop...**")
# Stopping the loop
loop_function.stop()
# ---------------------------------------------------------------------------------------
# Getting online members/offline members
# ---------------------------------------------------------------------------------------
@bot.command()
async def online(ctx):
online_m, offline_m = [], []
# Loop over each member in guild.members
for m in ctx.guild.members:
# Add to list of online members (online_m) if status is online/dnd, else add to offline_m
(online_m if str(m.status) in ("online", "dnd") else offline_m).append(str(m))
await ctx.send(f"Online: {', '.join(online_m)}\nOffline: {', '.join(offline_m)}")
# ---------------------------------------------------------------------------------------
# Fetching audit log
# ---------------------------------------------------------------------------------------
@bot.command()
async def logs(ctx):
actions = []
async for entry in ctx.guild.audit_logs(limit = 10):
time = entry.created_at.strftime("%d-%m-%Y %H:%M:%S")
actions.append(f"`{entry.user}` did `{entry.action}` at `{time}` to `{entry.target}`\n\n")
embed = discord.Embed(
title="Audit log",
description=''.join(actions),
colour=0x000
)
await ctx.send(embed=embed)
# ---------------------------------------------------------------------------------------
# Evaluates customized code
# ---------------------------------------------------------------------------------------
@bot.command(aliases=['e', 'evaluate'])
@commands.is_owner()
async def eval(context, *, code):
"""Evaluates customized code"""
language_specifiers = ["python", "py", "javascript", "js", "html", "css", "php", "md", "markdown", "go", "golang", "c", "c++", "cpp", "c#", "cs", "csharp", "java", "ruby", "rb", "coffee-script", "coffeescript", "coffee", "bash", "shell", "sh", "json", "http", "pascal", "perl", "rust", "sql", "swift", "vim", "xml", "yaml"]
loops = 0
while code.startswith("`"):
code = "".join(list(code)[1:])
loops += 1
if loops == 3:
loops = 0
break
for language_specifier in language_specifiers:
if code.startswith(language_specifier):
code = code.lstrip(language_specifier)
try:
while code.endswith("`"):
code = "".join(list(code)[0:-1])
loops += 1
if loops == 3:
break
code = "\n".join(f" {i}" for i in code.splitlines())
code = f"async def eval_expr():\n{code}"
def send(text):
bot.loop.create_task(context.send(text))
env = {
"bot": bot,
"client": bot,
"context": context,
"print": send,
"_author": context.author,
"_message": context.message,
"_channel": context.channel,
"_guild": context.guild,
"_me": context.me
}
env.update(globals())
exec(code, env)
eval_expr = env["eval_expr"]
result = await eval_expr()
await context.message.add_reaction("\N{WHITE HEAVY CHECK MARK}")
if result:
await context.send(result)
except Exception as learntofuckingcode:
await context.message.add_reaction("\N{WARNING SIGN}")
await context.send(f'**Error**```py\n{learntofuckingcode}```')
# ---------------------------------------------------------------------------------------
# RUN BOT
# ---------------------------------------------------------------------------------------
asyncio.run(init_db())
asyncio.run(load_cogs())
bot.run(config["token"])

View File

@ -18,7 +18,7 @@ $ cd ./Discord-Bot-Python
## Create .env enviroment
- NOTE: If you going to use .env environment you will need to make the necessary changes to the bots code inorder for it to work
- Using .env files can be [found here](https://dev.to/jakewitcher/using-env-files-for-environment-variables-in-python-applications-55a1
- Using .env files can be found [here](https://dev.to/jakewitcher/using-env-files-for-environment-variables-in-python-applications-55a1
)
- Create [.env](.env) file in the root director.
- Here is an explanation of what the values should look like: [env_demo.env](env_demo.env)
@ -32,6 +32,7 @@ TOMORROWIO_TOKEN=WEATHER_API_TOKEN
## Create config.json
- Create [config.json](config.json) file in the root directory.
- Here is an explanation of what the values should look like: [demo.config.json](demo.config.json)
- Example:
@ -73,17 +74,17 @@ $ pip install -r requirements.txt
- If you have just installed python today, then you just need to use the following command:
```shell
$ python bot.py
$ python main.py
```
- If you have multiple versions of python installed (2.x and 3.x) then you will need to use the following command:
```shell
$ python3 bot.py
$ python3 main.py
```
- or eventually
```shell
$ python3.x bot.py
$ python3.x main.py
```
- Replace `x` with the version of Python you have installed.