1
Fork 0
mirror of https://github.com/RGBCube/minearchy-bot synced 2025-07-27 17:07:45 +00:00

add suggestions and do cleanup

This commit is contained in:
RGBCube 2022-06-21 10:33:28 +03:00
parent 2322dec868
commit a3a3d7b966
9 changed files with 113 additions and 92 deletions

View file

@ -1,3 +0,0 @@
run="python3 bot.py"
language="python3"
onBoot="pip3 install -r requirements.txt"

64
bot.py
View file

@ -1,46 +1,47 @@
import discord
import time
import aiohttp
from discord.ext import commands
import os
import json
import asyncio import asyncio
from mcstatus import MinecraftServer import itertools
import traceback import json
import os
import pathlib import pathlib
import time
import traceback
import aiohttp
import discord
import mcstatus
from discord.ext import commands
class MinearchyBot(commands.Bot): class MinearchyBot(commands.Bot):
session: aiohttp.ClientSession session: aiohttp.ClientSession
suggestions_channel: discord.TextChannel
log_webhook: discord.Webhook log_webhook: discord.Webhook
up_ts: float up_ts: float
embed_color = 0x3500FF embed_color = 0x3500FF
def __init__(self, token: str, webhook_url: str, /) -> None: def __init__(
self, *, token: str, webhook_url: str, suggestions_channel_id: int
) -> None:
ip = "play.landsofminearchy.com" ip = "play.landsofminearchy.com"
self.mc_server = MinecraftServer.lookup(ip) self.mc_server = mcstatus.JavaServer.lookup(ip)
self.mc_server.ip = ip self.mc_server.ip = ip
self.mc_server.bedrock_ip = "bedrock.landsofminearchy.com" self.mc_server.bedrock_ip = "bedrock.landsofminearchy.com"
self.token = token self.token = token
self.webhook_url = webhook_url self.webhook_url = webhook_url
self.suggestions_channel_id = suggestions_channel_id
intents = discord.Intents(
guilds=True,
members=True,
messages=True,
message_content=True,
)
stuff_to_cache = discord.MemberCacheFlags.from_intents(intents)
super().__init__( super().__init__(
command_prefix="=", command_prefix="=",
owner_ids=set([512640455834337290]), owner_ids=set([512640455834337290]),
intents=intents, intents=discord.Intents(
guilds=True,
members=True,
messages=True,
message_content=True,
),
case_insensitive=True, case_insensitive=True,
allowed_mentions=discord.AllowedMentions.none(), allowed_mentions=discord.AllowedMentions.none(),
member_cache_flags=stuff_to_cache,
max_messages=1000, max_messages=1000,
strip_after_prefix=True, strip_after_prefix=True,
help_attrs=dict( help_attrs=dict(
@ -51,13 +52,17 @@ class MinearchyBot(commands.Bot):
async def on_ready(self) -> None: async def on_ready(self) -> None:
self.up_ts = time.time() self.up_ts = time.time()
self.suggestions_channel = self.get_channel(self.suggestions_channel_id)
print(f"\nConnected to Discord!\nUser: {self.user}\nID: {self.user.id}") print(f"\nConnected to Discord!\nUser: {self.user}\nID: {self.user.id}")
await self.log_webhook.send("Bot is now online!") await self.log_webhook.send("Bot is now online!")
async def load_extensions(self) -> None: async def load_extensions(self) -> None:
for fn in map( for fn in itertools.chain(
lambda file_path: str(file_path).replace("/", ".")[:-3], map(
pathlib.Path("./cogs").rglob("*.py"), lambda file_path: str(file_path).replace("/", ".")[:-3],
pathlib.Path("./cogs").rglob("*.py"),
),
["jishaku"],
): ):
try: try:
await self.load_extension(fn) await self.load_extension(fn)
@ -87,11 +92,10 @@ with open("./config.json") as f:
for key in ["BOT_TOKEN", "WEBHOOK_URL"]: for key in ["BOT_TOKEN", "WEBHOOK_URL"]:
config.setdefault(key, os.getenv(key)) config.setdefault(key, os.getenv(key))
bot = MinearchyBot(config["BOT_TOKEN"], config["WEBHOOK_URL"]) bot = MinearchyBot(
token=config["BOT_TOKEN"],
if os.getenv("USING_REPLIT"): webhook_url=config["WEBHOOK_URL"],
import webserver suggestions_channel_id=config["SUGGESTIONS_CHANNEL_ID"],
)
webserver.keep_alive()
bot.run() bot.run()

View file

@ -1,22 +1,22 @@
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING
from discord.ext import commands
import discord
import sys
import traceback import traceback
from typing import TYPE_CHECKING
import discord
from discord.ext import commands
if TYPE_CHECKING: if TYPE_CHECKING:
from bot import MinearchyBot from bot import MinearchyBot
class ErrorHandler(commands.Cog): class ErrorHandler(commands.Cog):
def __init__(self, bot: MinearchyBot, /) -> None: def __init__(self, bot: MinearchyBot) -> None:
self.bot = bot self.bot = bot
@commands.Cog.listener() @commands.Cog.listener()
async def on_command_error( async def on_command_error(
self, ctx: commands.Context, error: commands.CommandError, / self, ctx: commands.Context, error: commands.CommandError
) -> None: ) -> None:
if hasattr(ctx.command, "on_error"): if hasattr(ctx.command, "on_error"):
return return
@ -42,18 +42,17 @@ class ErrorHandler(commands.Cog):
elif isinstance(error, commands.MissingPermissions): elif isinstance(error, commands.MissingPermissions):
await ctx.reply("You can't use this command!") await ctx.reply("You can't use this command!")
elif isinstance(error, commands.MissingRequiredArgument):
await ctx.reply(f"Missing a required argument: `{error.param.name}`")
elif isinstance(error, commands.ChannelNotFound): elif isinstance(error, commands.ChannelNotFound):
await ctx.reply("Invalid channel.") await ctx.reply("Invalid channel.")
else: else:
trace = traceback.format_exception( trace = traceback.format_exception(type(error), error, error.__traceback__)
type(error), error, error.__traceback__ print(f"Ignoring exception in command {ctx.command}:\n{''.join(trace)}")
) await self.bot.log_webhook.send(f"<@512640455834337290>```{trace}```")
print(f"Ignoring exception in command {ctx.command}:\n{trace}")
await self.bot.log_webhook.send(
f"<@512640455834337290>```{trace}```"
)
async def setup(bot: MinearchyBot, /) -> None: async def setup(bot: MinearchyBot) -> None:
await bot.add_cog(ErrorHandler(bot)) await bot.add_cog(ErrorHandler(bot))

View file

@ -1,8 +1,9 @@
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from discord.ext import commands
import discord import discord
from discord.ext import commands
if TYPE_CHECKING: if TYPE_CHECKING:
from bot import MinearchyBot from bot import MinearchyBot
@ -13,7 +14,7 @@ class MinecraftServer(
name="Minecraft Server", name="Minecraft Server",
description="Utilites for the Minecraft server.", description="Utilites for the Minecraft server.",
): ):
def __init__(self, bot: MinearchyBot, /) -> None: def __init__(self, bot: MinearchyBot) -> None:
self.bot = bot self.bot = bot
@commands.group( @commands.group(
@ -21,15 +22,13 @@ class MinecraftServer(
brief="Sends the server IP.", brief="Sends the server IP.",
help="Sends the server IP.", help="Sends the server IP.",
) )
async def ip(self, ctx: commands.Context, /) -> None: async def ip(self, ctx: commands.Context) -> None:
await ctx.reply( await ctx.reply(
f"Java edition IP: `{self.bot.mc_server.ip}`\nBedrock edition IP: `{self.bot.mc_server.bedrock_ip}` (Port: 19132)\nNote: Minecraft 1.18+ is required to join." f"Java edition IP: `{self.bot.mc_server.ip}`\nBedrock edition IP: `{self.bot.mc_server.bedrock_ip}` (Port: 19132)\nNote: Minecraft 1.18+ is required to join."
) )
@ip.command( @ip.command(brief="Sends the Java edition IP.", help="Sends the Java edition IP.")
brief="Sends the Java edition IP.", help="Sends the Java edition IP." async def java(self, ctx: commands.Context) -> None:
)
async def java(self, ctx: commands.Context, /) -> None:
await ctx.reply( await ctx.reply(
f"The IP to connect on Minecraft Java edition is `{self.bot.mc_server.ip}`\nNote: Minecraft 1.18+ is required to join." f"The IP to connect on Minecraft Java edition is `{self.bot.mc_server.ip}`\nNote: Minecraft 1.18+ is required to join."
) )
@ -38,7 +37,7 @@ class MinecraftServer(
brief="Sends the Bedrock edition IP.", brief="Sends the Bedrock edition IP.",
help="Sends the Bedrock edition IP.", help="Sends the Bedrock edition IP.",
) )
async def bedrock(self, ctx: commands.Context, /) -> None: async def bedrock(self, ctx: commands.Context) -> None:
await ctx.reply( await ctx.reply(
f"The IP to connect on Minecraft Bedrock edition is `{self.bot.mc_server.bedrock_ip}` (Port: 19132)\nNote: Minecraft 1.18+ is required to join." f"The IP to connect on Minecraft Bedrock edition is `{self.bot.mc_server.bedrock_ip}` (Port: 19132)\nNote: Minecraft 1.18+ is required to join."
) )
@ -47,7 +46,7 @@ class MinecraftServer(
brief="Shows information about the Minecraft server.", brief="Shows information about the Minecraft server.",
help="Shows the total player count, the Minecraft server IP and the server latency.", help="Shows the total player count, the Minecraft server IP and the server latency.",
) )
async def status(self, ctx: commands.Context, /) -> None: async def status(self, ctx: commands.Context) -> None:
server = self.bot.mc_server server = self.bot.mc_server
status = server.status() status = server.status()
await ctx.reply( await ctx.reply(
@ -58,7 +57,7 @@ class MinecraftServer(
@commands.command( @commands.command(
brief="Sends the link to the wiki.", help="Sends the link to the wiki." brief="Sends the link to the wiki.", help="Sends the link to the wiki."
) )
async def wiki(self, ctx: commands.Context, /) -> None: async def wiki(self, ctx: commands.Context) -> None:
view = discord.ui.View() view = discord.ui.View()
view.add_item( view.add_item(
discord.ui.Button( discord.ui.Button(
@ -72,7 +71,7 @@ class MinecraftServer(
brief="Sends the link to the store.", brief="Sends the link to the store.",
help="Sends the link to the store.", help="Sends the link to the store.",
) )
async def store(self, ctx: commands.Context, /) -> None: async def store(self, ctx: commands.Context) -> None:
view = discord.ui.View() view = discord.ui.View()
view.add_item( view.add_item(
discord.ui.Button( discord.ui.Button(

View file

@ -1,15 +1,15 @@
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING
from discord.ext import commands
import datetime import datetime
from collections import defaultdict, deque
import discord
import inspect import inspect
from discord.utils import escape_markdown as es_md
import platform import platform
import time import time
from collections import defaultdict, deque
from typing import TYPE_CHECKING
import discord
from discord.ext import commands
from discord.utils import escape_markdown as es_md
if TYPE_CHECKING: if TYPE_CHECKING:
from bot import MinearchyBot from bot import MinearchyBot
@ -20,7 +20,7 @@ class Miscellanious(
name="Miscellanious", name="Miscellanious",
description="Various utilities.", description="Various utilities.",
): ):
def __init__(self, bot: MinearchyBot, /) -> None: def __init__(self, bot: MinearchyBot) -> None:
self.bot = bot self.bot = bot
self.bot.help_command.cog = self self.bot.help_command.cog = self
self.sniped = defaultdict(deque) self.sniped = defaultdict(deque)
@ -30,7 +30,7 @@ class Miscellanious(
self.bot.help_command.hidden = True self.bot.help_command.hidden = True
@commands.command(brief="Sends the bots ping.", help="Sends the bots ping.") @commands.command(brief="Sends the bots ping.", help="Sends the bots ping.")
async def ping(self, ctx: commands.Context, /) -> None: async def ping(self, ctx: commands.Context) -> None:
ts = time.time() ts = time.time()
message = await ctx.reply("Pong!") message = await ctx.reply("Pong!")
ts = time.time() - ts ts = time.time() - ts
@ -39,7 +39,7 @@ class Miscellanious(
@commands.command( @commands.command(
brief="Sends info about the bot.", help="Sends info about the bot." brief="Sends info about the bot.", help="Sends info about the bot."
) )
async def info(self, ctx: commands.Context, /) -> None: async def info(self, ctx: commands.Context) -> None:
embed = discord.Embed(title="Bot Info", color=self.bot.embed_color) embed = discord.Embed(title="Bot Info", color=self.bot.embed_color)
embed.add_field( embed.add_field(
name="Python Version", value=f"```v{platform.python_version()}```" name="Python Version", value=f"```v{platform.python_version()}```"
@ -51,21 +51,19 @@ class Miscellanious(
await ctx.reply(embed=embed) await ctx.reply(embed=embed)
@commands.command(brief="Hello!", help="Hello!") @commands.command(brief="Hello!", help="Hello!")
async def hello(self, ctx: commands.Context, /) -> None: async def hello(self, ctx: commands.Context) -> None:
await ctx.reply( await ctx.reply(f"Hi {es_md(ctx.author.name)}, yes the bot is running :)")
f"Hi {es_md(ctx.author.name)}, yes the bot is running :)"
)
@commands.command( @commands.command(
aliases=["server_count", "server-count"], aliases=["server_count", "server-count"],
brief="Sends how many servers the bot is in.", brief="Sends how many servers the bot is in.",
help="Sends how many servers the bot is in.", help="Sends how many servers the bot is in.",
) )
async def count(self, ctx: commands.Context, /) -> None: async def count(self, ctx: commands.Context) -> None:
await ctx.reply(f"Currently in `{len(self.bot.guilds)}` servers.") await ctx.reply(f"Currently in `{len(self.bot.guilds)}` servers.")
@commands.Cog.listener() @commands.Cog.listener()
async def on_message_delete(self, message: discord.Message, /) -> None: async def on_message_delete(self, message: discord.Message) -> None:
if not message.guild: if not message.guild:
return return
@ -84,7 +82,7 @@ class Miscellanious(
manage_messages=True manage_messages=True
) # needs to be able to delete messages to run the command ) # needs to be able to delete messages to run the command
async def snipe( async def snipe(
self, ctx: commands.Context, channel: discord.TextChannel = None, / self, ctx: commands.Context, channel: discord.TextChannel = None
) -> None: ) -> None:
if channel is None: if channel is None:
channel = ctx.channel channel = ctx.channel

39
cogs/suggestions.py Normal file
View file

@ -0,0 +1,39 @@
from __future__ import annotations
from typing import TYPE_CHECKING
import discord
from discord.ext import commands
if TYPE_CHECKING:
from bot import MinearchyBot
class Suggestions(commands.Cog):
def __init__(self, bot: MinearchyBot) -> None:
self.bot = bot
@commands.command(brief="Make a suggestion.", help="Make a suggestion.")
async def suggest(self, ctx: commands.Context, *, suggestion: str) -> None:
embed = (
discord.Embed(
title=f"Suggestion from {ctx.author}",
description=suggestion,
color=self.bot.embed_color,
)
.set_thumbnail(url=ctx.author.display_avatar.url)
.set_footer(text="=suggest <suggestion>")
)
message = await self.bot.suggestions_channel.send(embed=embed)
await message.add_reaction("")
await message.add_reaction("")
await ctx.reply(
f"Suggestion submitted!\nYou can view it at {self.bot.suggestions_channel.mention}"
)
async def setup(bot: MinearchyBot) -> None:
await bot.add_cog(Suggestions(bot))

View file

@ -3,5 +3,6 @@
"JAVA_IP": "play.landsofminearchy.com", "JAVA_IP": "play.landsofminearchy.com",
"BOT_PREFIX": "=", "BOT_PREFIX": "=",
"BOT_TOKEN": "XXX(ENV works too)", "BOT_TOKEN": "XXX(ENV works too)",
"WEBHOOK_URL": "XXX(ENV works too)" "WEBHOOK_URL": "XXX(ENV works too)",
"SUGGESTIONS_CHANNEL_ID": 955972394885984276
} }

View file

@ -1,2 +1,3 @@
discord.py @ git+https://github.com/Rapptz/discord.py discord.py @ git+https://github.com/Rapptz/discord.py
jishaku==2.5.0
mcstatus mcstatus

View file

@ -1,17 +0,0 @@
from flask import Flask
from threading import Thread
app = Flask(__name__)
@app.route("/")
def root() -> str:
return "Online!"
def run() -> None:
app.run(host="0.0.0.0", port=8080)
def keep_alive() -> None:
Thread(target=run).start()