updated repo to sample nextcord project.

This commit is contained in:
alwayscompiling
2022-06-22 22:13:15 -04:00
parent 692d43f8ae
commit b58e28aa6e
21 changed files with 300 additions and 2371 deletions
-49
View File
@@ -1,49 +0,0 @@
{
"extends": "eslint:recommended",
"env": {
"node": true,
"es6": true
},
"parserOptions": {
"ecmaVersion": 2021
},
"rules": {
"arrow-spacing": ["warn", { "before": true, "after": true }],
"brace-style": ["error", "stroustrup", { "allowSingleLine": true }],
"comma-dangle": ["error", "always-multiline"],
"comma-spacing": "error",
"comma-style": "error",
"curly": ["error", "multi-line", "consistent"],
"dot-location": ["error", "property"],
"handle-callback-err": "off",
"indent": ["error", 4],
"keyword-spacing": "error",
"max-nested-callbacks": ["error", { "max": 4 }],
"max-statements-per-line": ["error", { "max": 2 }],
"no-console": "off",
"no-empty-function": "error",
"no-floating-decimal": "error",
"no-inline-comments": "error",
"no-lonely-if": "error",
"no-multi-spaces": "error",
"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }],
"no-shadow": ["error", { "allow": ["err", "resolve", "reject"] }],
"no-trailing-spaces": ["error"],
"no-var": "error",
"object-curly-spacing": ["error", "always"],
"prefer-const": "error",
"quotes": ["error", "single"],
"semi": ["error", "always"],
"space-before-blocks": "error",
"space-before-function-paren": ["error", {
"anonymous": "never",
"named": "never",
"asyncArrow": "always"
}],
"space-in-parens": "error",
"space-infix-ops": "error",
"space-unary-ops": "error",
"spaced-comment": "error",
"yoda": "error"
}
}
+2 -2
View File
@@ -2,6 +2,6 @@
node_modules/
config.json
.env
.vscode
discord.log
nextcord.log
+62
View File
@@ -0,0 +1,62 @@
"""
main file for pvm-highscores bot
"""
import os
import logging
import nextcord
from nextcord.ext import commands
import config
logger = logging.getLogger('nextcord')
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(
filename='nextcord.log', encoding='utf-8', mode='w')
handler.setFormatter(logging.Formatter(
'%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
logger.addHandler(handler)
def main():
# Allows privledged intents for monitoring members joining, roles editing, and role assignments
# These need to be enabled in the developer portal as well
intents = nextcord.Intents.default()
# Required in order to read messages (eg. prefix commands)
intents.message_content = True
# To enable the guilds priveleged intent:
# intents.guilds = True
# To enable the members priveleged intent:
# intents.members = True
# Set custom status to "Listening to ?help"
activity = nextcord.Activity(
type=nextcord.ActivityType.listening, name=f"{config.BOT_PREFIX}help"
)
bot = commands.Bot(
commands.when_mentioned_or(config.BOT_PREFIX),
intents=intents,
activity=activity,
)
# Get the modules of all cogs whose directory structure is ./cogs/<module_name>
for folder in os.listdir("cogs"):
bot.load_extension(f"cogs.{folder}")
@bot.listen()
async def on_ready():
"""When Discord is connected"""
assert bot.user is not None
print(f"{bot.user.name} has connected to Discord!")
# Run Discord bot
bot.run(config.DISCORD_TOKEN)
if __name__ == "__main__":
main()
+30
View File
@@ -0,0 +1,30 @@
import nextcord
from nextcord.ext import commands
from utils import embed_success
class ApplicationCommandsExample(commands.Cog, name="App Commands"):
def __init__(self, bot: commands.Bot):
self.bot = bot
@nextcord.slash_command(description="Slash command that responds with 'Hello World'")
async def my_slash_cmd(self, interaction: nextcord.Interaction):
await interaction.send(embed=embed_success("Hello World!"))
@nextcord.slash_command(description="Slash command that repeats an argument")
async def my_slash_cmd_2(self, interaction: nextcord.Interaction, my_arg: str):
await interaction.send(embed=embed_success(f"You said: {my_arg}"))
@nextcord.user_command()
async def my_user_cmd(self, interaction: nextcord.Interaction, member: nextcord.Member):
await interaction.send(f"Hello, {member.mention}!")
@nextcord.message_command()
async def my_message_cmd(self, interaction: nextcord.Interaction, message: nextcord.Message):
await interaction.send(f"Hello, {message.author.mention}!")
# This function will be called when this extension is loaded.
# It is necessary to add these functions to the bot.
def setup(bot: commands.Bot):
bot.add_cog(ApplicationCommandsExample(bot))
+19
View File
@@ -0,0 +1,19 @@
from nextcord.ext import commands
from .help_command import NewHelpCommand
class HelpCog(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
self._original_help_command = bot.help_command
bot.help_command = NewHelpCommand()
bot.help_command.cog = self
def cog_unload(self):
self.bot.help_command = self._original_help_command
# setup functions for bot
def setup(bot: commands.Bot):
bot.add_cog(HelpCog(bot))
+80
View File
@@ -0,0 +1,80 @@
import config
import nextcord
from nextcord.embeds import EmptyEmbed
from nextcord.ext import commands
class NewHelpCommand(commands.MinimalHelpCommand):
"""Custom help command override using embeds"""
COLOUR = nextcord.Colour.blurple()
def get_ending_note(self):
"""Returns note to display at the bottom"""
invoked_with = self.invoked_with
return f"Use {config.BOT_PREFIX}{invoked_with} [command] for more info on a command."
def get_command_signature(self, command: commands.core.Command):
"""Retrieves the signature portion of the help page."""
return f"{command.qualified_name} {command.signature}"
async def send_bot_help(self, mapping: dict):
"""implements bot command help page"""
embed = nextcord.Embed(title="Bot Commands", colour=self.COLOUR)
avatar = self.context.bot.user.avatar
avatar_url = avatar.url if avatar else EmptyEmbed
embed.set_author(name=self.context.bot.user.name, icon_url=avatar_url)
description = self.context.bot.description
if description:
embed.description = description
for cog, commands in mapping.items():
name = "No Category" if cog is None else cog.qualified_name
filtered = await self.filter_commands(commands, sort=True)
if filtered:
# \u2002 = middle dot
value = "\u2002".join(f"{config.BOT_PREFIX}{c.name}" for c in filtered)
if cog and cog.description:
value = f"{cog.description}\n{value}"
embed.add_field(name=name, value=value)
embed.set_footer(text=self.get_ending_note())
await self.get_destination().send(embed=embed)
async def send_cog_help(self, cog: commands.Cog):
"""implements cog help page"""
embed = nextcord.Embed(title=f"{cog.qualified_name} Commands", colour=self.COLOUR)
if cog.description:
embed.description = cog.description
filtered = await self.filter_commands(cog.get_commands(), sort=True)
for command in filtered:
embed.add_field(
name=self.get_command_signature(command),
value=command.short_doc or "...",
inline=False,
)
embed.set_footer(text=self.get_ending_note())
await self.get_destination().send(embed=embed)
async def send_group_help(self, group: commands.Group):
"""implements group help page and command help page"""
embed = nextcord.Embed(title=group.qualified_name, colour=self.COLOUR)
if group.help:
embed.description = group.help
if isinstance(group, commands.Group):
filtered = await self.filter_commands(group.commands, sort=True)
for command in filtered:
embed.add_field(
name=self.get_command_signature(command),
value=command.short_doc or "...",
inline=False,
)
embed.set_footer(text=self.get_ending_note())
await self.get_destination().send(embed=embed)
# Use the same function as group help for command help
send_command_help = send_group_help # type: ignore
+26
View File
@@ -0,0 +1,26 @@
from nextcord.ext import commands
from utils import embed_success
class Ping(commands.Cog, name="Ping"):
def __init__(self, bot: commands.Bot):
self.bot = bot
@commands.command(name="ping")
async def ping(self, ctx: commands.Context):
"""A command which simply acknowledges the user's ping.
Usage:
```
?ping
```
"""
# log in console that a ping was received
print("Received ping")
# respond to the message
await ctx.send(embed=embed_success("Pong!"))
# This function will be called when this extension is loaded.
# It is necessary to add these functions to the bot.
def setup(bot: commands.Bot):
bot.add_cog(Ping(bot))
-10
View File
@@ -1,10 +0,0 @@
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('ping')
.setDescription('Pings caller!'),
async execute(interaction) {
await interaction.reply(`Ping! <@${interaction.user.id}>`);
},
};
-10
View File
@@ -1,10 +0,0 @@
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('server')
.setDescription('Provides server information.'),
async execute(interaction) {
await interaction.reply(`Server name: ${interaction.guild.name}\nTotal members: ${interaction.guild.memberCount}`);
},
};
-10
View File
@@ -1,10 +0,0 @@
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('user')
.setDescription('Provides user information.'),
async execute(interaction) {
await interaction.reply(`Your tag: ${interaction.user.tag}\nYour id: ${interaction.user.id}`);
},
};
+5
View File
@@ -0,0 +1,5 @@
{
"clientId": "988152685834412183",
"guildId": "988153881999585352",
"token": "OTg4MTUyNjg1ODM0NDEyMTgz.GJyBN3.bIa0LL03XwtjwFTOnUUCSgNbKKaXVDwE0_zIFE"
}
-21
View File
@@ -1,21 +0,0 @@
const fs = require('node:fs');
const path = require('node:path');
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
const { clientId, guildId, token } = require('./config.json');
const commands = [];
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
commands.push(command.data.toJSON());
}
const rest = new REST({ version: '9' }).setToken(token);
rest.put(Routes.applicationGuildCommands(clientId, guildId), { body: commands })
.then(() => console.log('Successfully registered application commands.'))
.catch(console.error);
-6
View File
@@ -1,6 +0,0 @@
module.exports = {
name: 'interactionCreate',
execute(interaction) {
console.log(`${interaction.user.tag} in #${interaction.channel.name} triggered an interaction.`);
},
};
-7
View File
@@ -1,7 +0,0 @@
module.exports = {
name: 'ready',
once: true,
execute(client) {
console.log(`Ready! Logged in as ${client.user.tag}`);
},
};
-10
View File
@@ -1,10 +0,0 @@
module.exports = {
name: 'messageCreate',
execute(client) {
console.log('user has sent a message');
if (client.messageCreate.content.includes('reee')) {
const channel = client.channels.cache.get('id');
channel.send('reee');
}
},
};
-59
View File
@@ -1,59 +0,0 @@
const fs = require('node:fs');
const path = require('node:path');
// Require the necessary discord.js classes
const { Client, Collection, Intents } = require('discord.js');
const { token } = require('./config.json');
// Create a new client instance
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
client.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
// Set a new item in the Collection
// With the key as the command name and the value as the exported module
client.commands.set(command.data.name, command);
}
// When the client is ready, run this code (only once)
client.once('ready', () => {
console.log('Ready!');
});
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
}
catch (error) {
console.error(error);
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
});
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));
for (const file of eventFiles) {
const filePath = path.join(eventsPath, file);
const event = require(filePath);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
}
else {
client.on(event.name, (...args) => event.execute(...args));
}
}
// Login to Discord with your client's token
client.login(token);
-2119
View File
File diff suppressed because it is too large Load Diff
-28
View File
@@ -1,28 +0,0 @@
{
"name": "pvm-highscores",
"version": "1.0.0",
"description": "A high scores bot for discord. Features will include automatically updating high scores in a discord channel and users being able to submit using bot commands.",
"main": "index.js",
"dependencies": {
"@discordjs/builders": "^0.15.0",
"@discordjs/rest": "^0.5.0",
"discord-api-types": "^0.34.0",
"discord.js": "^13.8.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/alwayscompiling/pvm-highscores.git"
},
"author": "alwayscompiling",
"license": "MIT",
"bugs": {
"url": "https://github.com/alwayscompiling/pvm-highscores/issues"
},
"homepage": "https://github.com/alwayscompiling/pvm-highscores#readme",
"devDependencies": {
"eslint": "^8.18.0"
}
}
-40
View File
@@ -1,40 +0,0 @@
"""
pvm_highscores discord bot
"""
import json
import logging
import discord
logger = logging.getLogger('discord')
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(
filename='discord.log', encoding='utf-8', mode='w')
handler.setFormatter(logging.Formatter(
'%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
logger.addHandler(handler)
client = discord.Client()
with open("config.json", encoding='utf-8', mode='r') as file:
config_data = json.load(file)
@client.event
async def on_ready():
""""reports when bot logs in"""
print(f'We have logged in as {client.user}')
@client.event
async def on_message(message):
""""runs when message is sent on server"""
print("message get")
if message.author == client.user:
return
if message.content.startswith('reee'):
await message.channel.send('reee!')
client.run(config_data["token"])
+1
View File
@@ -0,0 +1 @@
from .embedder import *
+75
View File
@@ -0,0 +1,75 @@
from typing import Optional, Union
import nextcord
from nextcord.embeds import EmptyEmbed, _EmptyEmbed
DEFAULT_COLOR = nextcord.Colour.blurple()
MAX_EMBED_DESCRIPTION_LENGTH = 4096
MAX_EMBED_FIELD_TITLE_LENGTH = 256
MAX_EMBED_FIELD_FOOTER_LENGTH = 2048
def __trim(text: str, limit: int) -> str:
"""limit text to a certain number of characters"""
return text[: limit - 3].strip() + "..." if len(text) > limit else text
def embed_success(
title: str,
description: Optional[str] = None,
footer: Optional[str] = None,
url: Union[str, _EmptyEmbed] = EmptyEmbed,
image: Optional[str] = None,
thumbnail: Optional[str] = None,
) -> nextcord.Embed:
"""Embed a success message and an optional description, footer, and url"""
return build_embed(title, description, footer, url, nextcord.Colour.green(), image, thumbnail)
def embed_warning(
title: str,
description: Optional[str] = None,
footer: Optional[str] = None,
url: Union[str, _EmptyEmbed] = EmptyEmbed,
image: Optional[str] = None,
thumbnail: Optional[str] = None,
) -> nextcord.Embed:
"""Embed a warning message and an optional description, footer, and url"""
return build_embed(title, description, footer, url, nextcord.Colour.gold(), image, thumbnail)
def embed_error(
title: str,
description: Optional[str] = None,
footer: Optional[str] = None,
url: Union[str, _EmptyEmbed] = EmptyEmbed,
image: Optional[str] = None,
thumbnail: Optional[str] = None,
) -> nextcord.Embed:
"""Embed an error message and an optional description, footer, and url"""
return build_embed(title, description, footer, url, nextcord.Colour.red(), image, thumbnail)
def build_embed(
title: str,
description: Optional[str] = None,
footer: Optional[str] = None,
url: Union[str, _EmptyEmbed] = EmptyEmbed,
colour: nextcord.Colour = DEFAULT_COLOR,
image: Optional[str] = None,
thumbnail: Optional[str] = None,
) -> nextcord.Embed:
"""Embed a message and an optional description, footer, and url"""
# create the embed
embed = nextcord.Embed(
title=__trim(title, MAX_EMBED_FIELD_TITLE_LENGTH), url=url, colour=colour
)
if description:
embed.description = __trim(description, MAX_EMBED_DESCRIPTION_LENGTH)
if footer:
embed.set_footer(text=__trim(footer, MAX_EMBED_FIELD_FOOTER_LENGTH))
if image:
embed.set_image(url=image)
if thumbnail:
embed.set_thumbnail(url=thumbnail)
return embed