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:
parent
2322dec868
commit
a3a3d7b966
9 changed files with 113 additions and 92 deletions
3
.replit
3
.replit
|
@ -1,3 +0,0 @@
|
||||||
run="python3 bot.py"
|
|
||||||
language="python3"
|
|
||||||
onBoot="pip3 install -r requirements.txt"
|
|
56
bot.py
56
bot.py
|
@ -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
|
||||||
|
super().__init__(
|
||||||
|
command_prefix="=",
|
||||||
|
owner_ids=set([512640455834337290]),
|
||||||
intents=discord.Intents(
|
intents=discord.Intents(
|
||||||
guilds=True,
|
guilds=True,
|
||||||
members=True,
|
members=True,
|
||||||
messages=True,
|
messages=True,
|
||||||
message_content=True,
|
message_content=True,
|
||||||
)
|
),
|
||||||
stuff_to_cache = discord.MemberCacheFlags.from_intents(intents)
|
|
||||||
|
|
||||||
super().__init__(
|
|
||||||
command_prefix="=",
|
|
||||||
owner_ids=set([512640455834337290]),
|
|
||||||
intents=intents,
|
|
||||||
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(
|
||||||
|
map(
|
||||||
lambda file_path: str(file_path).replace("/", ".")[:-3],
|
lambda file_path: str(file_path).replace("/", ".")[:-3],
|
||||||
pathlib.Path("./cogs").rglob("*.py"),
|
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()
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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(
|
||||||
|
|
30
cogs/misc.py
30
cogs/misc.py
|
@ -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
39
cogs/suggestions.py
Normal 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))
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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
|
17
webserver.py
17
webserver.py
|
@ -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()
|
|
Loading…
Add table
Add a link
Reference in a new issue