├── .github ├── FUNDING.yml ├── workflows │ ├── stale.yml │ └── codeql-analysis.yml └── stale.yml ├── events ├── disconnect.js ├── reconnecting.js ├── guildMemberRemove.js ├── guildMemberAdd.js ├── interactionCreate.js ├── ready.js └── messageCreate.js ├── model ├── card.js └── xp.js ├── commandhandler file exemple.txt ├── botconfig.json copy.exemple ├── slash └── commands │ └── ping.js ├── commands ├── music │ ├── volume.js │ ├── join.js │ ├── pause.js │ ├── resume.js │ ├── leave.js │ ├── skip.js │ ├── queue.js │ └── play.js ├── info │ ├── invit.js │ ├── game.js │ ├── wink.js │ ├── uptime.js │ ├── ping.js │ ├── serverinfo.js │ ├── reddit.js │ ├── whois.js │ ├── botInfo.js │ ├── addcard.js │ ├── help.js │ ├── lbtop10.js │ ├── wow.js │ └── rank.js ├── moderation │ ├── say.js │ ├── clear.js │ ├── mute.js │ ├── kick.js │ └── ban.js └── dev │ └── eval.js ├── handler └── command.js ├── deploy-commands.js ├── .circleci └── config.yml ├── function.js ├── package.json ├── .gitignore ├── .eslintrc.json ├── LICENSE ├── CHANGELOGS.md ├── CODE_OF_CONDUCT.md ├── index.js ├── README.md └── Cards.js /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | patreon: Asthriona 4 | ko_fi: Asthriona 5 | -------------------------------------------------------------------------------- /events/disconnect.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "disconnect", 3 | once: false, 4 | execute() { 5 | console.log("Bot has been disconnected from discord..."); 6 | }, 7 | }; -------------------------------------------------------------------------------- /events/reconnecting.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "reconnecting", 3 | once: false, 4 | execute() { 5 | console.log("The bot is reconnecting to discord..."); 6 | }, 7 | }; -------------------------------------------------------------------------------- /model/card.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const cardsSchema = new mongoose.Schema({ 4 | did: String, 5 | link: String, 6 | }); 7 | module.exports = mongoose.model("Cards", cardsSchema); -------------------------------------------------------------------------------- /commandhandler file exemple.txt: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: " ", 3 | category: "info", 4 | description: " ", 5 | run: async (bot, message, args) => { 6 | message.channel.send(`POG`) 7 | } 8 | } -------------------------------------------------------------------------------- /botconfig.json copy.exemple: -------------------------------------------------------------------------------- 1 | { 2 | "token": "Bot tokken", 3 | "prefix": "a!", 4 | "dbLink": "mongodb://yukiko:127.0.0.1", 5 | "lavaHost": "localhost", 6 | "lavaPort": "2333", 7 | "lavaPasswd": "youshallnotpass" 8 | } 9 | -------------------------------------------------------------------------------- /slash/commands/ping.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName("ping") 6 | .setDescription("Pong!"), 7 | async execute(interaction) { 8 | interaction.reply("Pong!"); 9 | }, 10 | }; -------------------------------------------------------------------------------- /commands/music/volume.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "volume", 3 | category: "music", 4 | description: "change the volume of the video.", 5 | run: async (bot, message, args) => { 6 | // Just so my linter shut up. I'll make the command later. 7 | console.log(bot, message, args); 8 | }, 9 | }; -------------------------------------------------------------------------------- /model/xp.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const userSchema = new mongoose.Schema({ 4 | did: String, 5 | username: String, 6 | serverID: String, 7 | xp: Number, 8 | level: Number, 9 | message: Number, 10 | warns: Number, 11 | avatarURL: String, 12 | }); 13 | module.exports = mongoose.model("Users", userSchema); -------------------------------------------------------------------------------- /commands/info/invit.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "invite", 3 | category: "info", 4 | description: "Create an invitation to this server", 5 | run: async (bot, message) => { 6 | message.channel.createInvite() 7 | .then(invite => message.channel.send(`Here is your invitation! => \n ${invite}`)) 8 | .catch(console.error); 9 | }, 10 | }; -------------------------------------------------------------------------------- /events/guildMemberRemove.js: -------------------------------------------------------------------------------- 1 | const { farewell } = require("../Cards"); 2 | module.exports = { 3 | name: "guildMemberRemove", 4 | once: false, 5 | async execute(member) { 6 | const farewellChannel = member.guild.channels.find(channel => channel.name === "welcome"); 7 | if (!farewellChannel) return; 8 | return await farewell(member, farewellChannel); 9 | }, 10 | }; -------------------------------------------------------------------------------- /commands/music/join.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "join", 3 | category: "music", 4 | description: "Let the bot join your VC waiting for music.", 5 | run: async (bot, message) => { 6 | const player = bot.manager.create({ 7 | guild: message.guild.id, 8 | voiceChannel: message.member.voice.channel.id, 9 | textChannel: message.channel.id, 10 | }); 11 | player.connect(); 12 | message.reply("Here I am :D"); 13 | }, 14 | }; -------------------------------------------------------------------------------- /commands/info/game.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "game", 3 | category: "info", 4 | description: "change what bot is actually playing.", 5 | aliases: ["setgame"], 6 | run: async (bot, message, args) => { 7 | if(message.member.permissions.has("BAN_MEMBERS")) { 8 | bot.user.setPresence({ activities: [{ name: args.join(" ") }] }); 9 | } 10 | else{ 11 | return message.reply("Oy! You can't tell me what to do! "); 12 | } 13 | 14 | }, 15 | }; -------------------------------------------------------------------------------- /events/guildMemberAdd.js: -------------------------------------------------------------------------------- 1 | // remember to make a command for the welcome channel as this bot is not set to run with a website. 2 | const { WelcomeCad } = require("../Cards"); 3 | module.exports = { 4 | name: "guildMemberAdd", 5 | once: false, 6 | async execute(member) { 7 | const welcomeChannel = member.guild.channels.find(channel => channel.name === "welcome"); 8 | if (!welcomeChannel) return; 9 | return await WelcomeCad(member, welcomeChannel); 10 | }, 11 | }; -------------------------------------------------------------------------------- /commands/music/pause.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "pause", 3 | category: "music", 4 | description: "Pause the current video.", 5 | run: async (bot, message) => { 6 | const player = bot.manager.get(message.guild.id); 7 | if(!player) return message.reply("Im not playing at the moment, please use the `play` command."); 8 | if(player.playing != false || player.pause != false) return message.reply("Player is already paused."); 9 | player.pause(true); 10 | message.reply("Music has been paused!"); 11 | }, 12 | }; -------------------------------------------------------------------------------- /commands/music/resume.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "resume", 3 | category: "music", 4 | description: "Resume the current video.", 5 | run: async (bot, message) => { 6 | const player = bot.manager.get(message.guild.id); 7 | if(!player) return message.reply("Im not playing at the moment, please use the `play` command."); 8 | if(player.playing != true || player.pause != true) return message.reply("Player is not paused."); 9 | player.pause(false); 10 | message.reply("Music has been resumed!"); 11 | }, 12 | }; -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues and pull requests 2 | 3 | on: 4 | schedule: 5 | - cron: "30 1 * * *" 6 | 7 | jobs: 8 | stale: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/stale@v1 14 | with: 15 | repo-token: ${{ secrets.GITHUB_TOKEN }} 16 | stale-issue-message: 'Stale issue message' 17 | stale-pr-message: 'Stale pull request message' 18 | stale-issue-label: 'no-issue-activity' 19 | stale-pr-label: 'no-pr-activity' 20 | -------------------------------------------------------------------------------- /commands/info/wink.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const { MessageEmbed } = require("discord.js"); 3 | module.exports = { 4 | name: "wink", 5 | category: "info", 6 | description: "send a Winky face!", 7 | run: async (bot, message) => { 8 | const { body } = await axios 9 | .get("https://some-random-api.ml/animu/wink"); 10 | const winkembed = new MessageEmbed() 11 | .setColor("#800080") 12 | .setTitle("winky Face! ;)") 13 | .setImage(body.link); 14 | 15 | message.channel.send({ embeds: [winkembed] }); 16 | }, 17 | }; -------------------------------------------------------------------------------- /commands/music/leave.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "stop", 3 | category: "music", 4 | description: "stop playing music and leave the channel.", 5 | run: async (bot, message) => { 6 | const player = bot.manager.get(message.guild.id); 7 | if(!player) return message.reply("There is no active player at the moment."); 8 | if (!player.playing) { 9 | player.destroy(); 10 | message.channel.send("👉🚪 Leaving the channel."); 11 | } 12 | else { 13 | player.destroy(); 14 | message.channel.send("🎵 Player has been destroyed. 👉🚪 Leaving the channel."); 15 | } 16 | }, 17 | }; -------------------------------------------------------------------------------- /events/interactionCreate.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "interactionCreate", 3 | once: false, 4 | async execute(interaction, bot) { 5 | console.log(interaction); 6 | // check if command. 7 | if(!interaction.isChatInputCommand()) return; 8 | // check if command is run in DMs. 9 | if(interaction.commandGuildId === null || interaction.channel.type === "DM") return; 10 | 11 | // Build Data for command. 12 | const cmd = interaction.commandName; 13 | const Slashes = bot.slash.get(cmd); 14 | if(!Slashes) return; 15 | // Executhe command. 16 | Slashes.execute(interaction, bot); 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /commands/info/uptime.js: -------------------------------------------------------------------------------- 1 | // Geez. I had no idea how time works. 2 | // Message to Future Asthriona. use Day.js or moment for that pls. 3 | module.exports = { 4 | name: "uptime", 5 | category: "info", 6 | description: "Show bot's uptime", 7 | run: async (bot, message) => { 8 | let totalSeconds = (bot.uptime / 1000); 9 | const days = Math.floor(totalSeconds / 86400); 10 | const hours = Math.floor(totalSeconds / 3600); 11 | totalSeconds %= 3600; 12 | const minutes = Math.floor(totalSeconds / 60); 13 | const seconds = Math.floor(totalSeconds / 60); 14 | const uptime = `${days} days, ${hours} hours, ${minutes} minutes and ${seconds} seconds`; 15 | message.channel.send(uptime); 16 | }, 17 | }; -------------------------------------------------------------------------------- /commands/music/skip.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "skip", 3 | category: "music", 4 | description: "Skip the current video.", 5 | run: async (bot, message) => { 6 | const player = bot.manager.get(message.guild.id); 7 | if(!player || player.playing == false) return message.reply("Nothing is playing at the moment"); 8 | if(player.trackRepeat == true) { 9 | player.setTrackRepeat(false); 10 | await player.stop(); 11 | message.channel.send(`${player.queue.current.title} has been skiped, repeat is disabled. \`${this.client.prefix}repeat\` to re-enable `); 12 | } 13 | else{ 14 | player.stop(); 15 | message.channel.send(`${player.queue.current.title} has been skiped.`); 16 | } 17 | }, 18 | }; -------------------------------------------------------------------------------- /events/ready.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "ready", 3 | once: false, 4 | execute(bot) { 5 | console.log("Setting bot presence..."); 6 | const statues = ["Persona 4 Golden", "Twitter: @YukikoApp", "W/ @Asthriona's Feelings", "w/ Rise", "in my castle", "Bummer! an error happened!"]; 7 | setInterval(function() { 8 | const status = statues[Math.floor(Math.random() * statues.length)]; 9 | bot.user.setStatus("dnd"); 10 | bot.user.setPresence({ game: { name: status, type: "PLAYING" }, 11 | }); 12 | }, 600000); 13 | console.log("waiting for ready event..."); 14 | console.log(`\x1b[32m${bot.user.username}\x1b[0m is now started and running.`); 15 | console.log("Init Player manager..."); 16 | bot.manager.init(bot.user.id); 17 | }, 18 | }; -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 7 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 5 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: true 18 | -------------------------------------------------------------------------------- /handler/command.js: -------------------------------------------------------------------------------- 1 | const { readdirSync } = require("fs"); 2 | 3 | const ascii = require("ascii-table"); 4 | 5 | const table = new ascii("Commands"); 6 | table.setHeading("Command", "Load status"); 7 | 8 | module.exports = (bot) => { 9 | readdirSync("./commands/").forEach(dir => { 10 | const commands = readdirSync(`./commands/${dir}/`).filter(file => file.endsWith(".js")); 11 | for (const file of commands) { 12 | const pull = require(`../commands/${dir}/${file}`); 13 | 14 | if (pull.name) { 15 | bot.Commands.set(pull.name, pull); 16 | table.addRow(file, "✔️ Ok!"); 17 | } 18 | else { 19 | table.addRow(file, "❌ -> missing a help.name, or help.name is not a string."); 20 | continue; 21 | } 22 | 23 | // If there's an aliases key, read the aliases. 24 | if (pull.aliases && Array.isArray(pull.aliases)) pull.aliases.forEach(alias => bot.Aliases.set(alias, pull.name)); 25 | } 26 | }); 27 | // Log the table 28 | console.log(table.toString()); 29 | }; -------------------------------------------------------------------------------- /commands/info/ping.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-useless-escape */ 2 | module.exports = { 3 | name: "ping", 4 | category: "info", 5 | description: "return bot latency and API ping.", 6 | run: async (bot, message) => { 7 | const spells = [ 8 | "Agi", "Maragi", "Agilao", "Maragion", 9 | "Agidyne", "Maragidyne", 10 | ]; 11 | const shadows = [ 12 | "Lying Hablerie", "Calm Pesce", "Trance Twins", "Black Raven", 13 | "Magic Hand", "Secret Bambino", "Positive King", "Brinze Dice", 14 | "Burning Beetle", "Phantom Mage", "Heat Balance", "Laughing Table", 15 | "Avenger knight", 16 | ]; 17 | const randomSpell = spells[Math.floor(Math.random() * spells.length)]; 18 | const randomShadow = shadows[Math.floor(Math.random() * shadows.length)]; 19 | const msg = await message.reply(`\* Yukiko cast ${randomSpell} against ${randomShadow} \*`); 20 | msg.edit(`**Pong!** \n Gateway latency: ${Math.floor(msg.createdAt - message.createdAt)}ms. \n API latency: ${Math.round(bot.ws.ping)}ms.`); 21 | }, 22 | }; -------------------------------------------------------------------------------- /deploy-commands.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const { REST, Routes } = require("discord.js"); 4 | const { clientId, guildId, token } = require("./botconfig.json"); 5 | 6 | const commands = []; 7 | const commandPath = path.join(__dirname, "slash/commands"); 8 | const commandFiles = fs.readdirSync(commandPath).filter(file => file.endsWith(".js")); 9 | for(const file of commandFiles) { 10 | const filePath = path.join(commandPath, file); 11 | const command = require(filePath); 12 | commands.push(command.data.toJSON()); 13 | } 14 | 15 | const rest = new REST({ version: "9" }).setToken(token); 16 | (async () => { 17 | try{ 18 | console.log("Updating commands..."); 19 | await rest.put( 20 | Routes.applicationGuildCommands(clientId, guildId), 21 | { body: commands }, 22 | ); 23 | console.log("Commands updated!"); 24 | } 25 | catch(err) { 26 | console.error("an error happened while trying to refresh commands the commands:"); 27 | console.error(err); 28 | } 29 | })(); -------------------------------------------------------------------------------- /commands/moderation/say.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | module.exports = { 3 | name: "say", 4 | category: "Moderation", 5 | description: "Let the bot speak for you", 6 | run: async (bot, message, args) => { 7 | if(!message.member.permissions.has("BAN_MEMBERS")) return message.reply("Oy! dont tell me what to say!"); 8 | if(message.deletable) message.delete(); 9 | if(args.length < 1) {return message.reply("Nothing to say? Please TALK TO ME! 😢");} 10 | 11 | const roleColor = message.guild.me.displayHexColor === "#000" ? "#fff" : message.guild.me.displayHexColor ; 12 | if(args[0].toLowerCase() === "embed") { 13 | const embed = new Discord.MessageEmbed() 14 | .setColor(roleColor) 15 | .setAuthor({ name: message.author.username, iconURL: message.author.displayAvatarURL()}) 16 | .setDescription(args.slice(1).join(" ")) 17 | .setTimestamp() 18 | .setFooter({ name: `Powered by: ${bot.user.username}`, iconURL: bot.user.displayAvatarURL()}); 19 | message.channel.send({ embeds:[embed] }); 20 | } 21 | else{ 22 | message.channel.send(args.join(" ")); 23 | } 24 | }, 25 | }; -------------------------------------------------------------------------------- /commands/info/serverinfo.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | const moment = require("moment"); 3 | module.exports = { 4 | name: "server", 5 | aliases: ["server-info", "serverinfo"], 6 | category: "info", 7 | description: "Return server infos.", 8 | run: async (bot, message) => { 9 | const guildOwner = bot.users.cache.get(message.guild.ownerId); 10 | const serverembed = new MessageEmbed() 11 | .setDescription("Server Information") 12 | .setColor("#800080") 13 | .setThumbnail(message.guild.iconURL()) 14 | .addField("Server name", `${message.guild.name}`) 15 | .addField("Created at", `${moment(message.guild.createdAt).format("MMMM Do YYYY, h:mm:ss a")} (${moment(message.guild.createdAt).fromNow()})`) 16 | .addField("Joined at: ", `${moment(message.member.joinedAt).format("MMMM Do YYYY, h:mm:ss a")} (${moment(message.member.joinedAt).fromNow()})`) 17 | .addField("Owner: ", `${guildOwner}`) 18 | .addField("Total members: ", `${message.guild.memberCount}`) 19 | .setFooter(bot.user.username, bot.user.displayAvatarURL()) 20 | .setTimestamp(); 21 | return message.channel.send({ embeds: [serverembed] }); 22 | }, 23 | }; -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # JavaScript Node CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details 4 | # 5 | version: 2 6 | jobs: 7 | build: 8 | docker: 9 | # specify the version you desire here 10 | - image: circleci/node:7.10 11 | 12 | # Specify service dependencies here if necessary 13 | # CircleCI maintains a library of pre-built images 14 | # documented at https://circleci.com/docs/2.0/circleci-images/ 15 | # - image: circleci/mongo:3.4.4 16 | 17 | working_directory: ~/repo 18 | 19 | steps: 20 | - checkout 21 | 22 | # Download and cache dependencies 23 | - restore_cache: 24 | keys: 25 | - v1-dependencies-{{ checksum "package.json" }} 26 | # fallback to using the latest cache if no exact match is found 27 | - v1-dependencies- 28 | 29 | - run: npm install 30 | - run: mv botconfig.json.exemple botconfig.json 31 | 32 | - save_cache: 33 | paths: 34 | - node_modules 35 | key: v1-dependencies-{{ checksum "package.json" }} 36 | 37 | # run tests! 38 | - run: npm start 39 | -------------------------------------------------------------------------------- /commands/moderation/clear.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "clear", 3 | category: "Moderation", 4 | aliases: ["delete", "suppr", "remove"], 5 | description: "delete a lot of message :O", 6 | usage: "!clear [1 - 100]", 7 | run: async (bot, message, args) => { 8 | if(message.deletable) { 9 | message.delete(); 10 | } 11 | if (!message.member.permissions.has("MANAGE_MESSAGES")) { 12 | return message.reply("you dont have the permissions to delete those message!"); 13 | } 14 | if (isNaN(args[0]) || parseInt(args[0]) <= 0) { 15 | return message.reply("Oh my... Is this even a number?! Please use a number between 0 and 100 in numeric value."); 16 | } 17 | if(!message.guild.me.permissions.has("MANAGE_MESSAGES")) { 18 | return message.reply("I dont have the permissions to do that. Please add 'MANAGE_MESSAGES' to my permissions."); 19 | } 20 | let deleteAmount; 21 | if(parseInt(args[0]) > 100) { 22 | deleteAmount = 100; 23 | } 24 | else{ 25 | deleteAmount = parseInt(args[0]); 26 | } 27 | message.channel.bulkDelete(deleteAmount, true) 28 | .then(deleted => message.channel.send(`I deleted ${deleted.size} messages.`)).then(m => m.delete({ timeout: 20000 })) 29 | .catch(err => message.reply("Yikes! An error sucessfully happened! " + err)); 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /function.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | getMember: function(message, toFind = "") { 3 | toFind = toFind.toLowerCase(); 4 | let target = message.guild.members.cache.get(toFind); 5 | if (!target && message.mentions.members) {target = message.mentions.members.first();} 6 | if (!target && toFind) { 7 | target = message.guild.members.find(member => { 8 | return member.displayName.toLowerCase().includes(toFind) || 9 | member.user.tag.toLowerCase().includes(toFind); 10 | }); 11 | } 12 | if (!target) {target = message.member;} 13 | 14 | return target; 15 | }, 16 | formatDate: function(date) { 17 | return new Intl.DateTimeFormat("en-US").format(date); 18 | }, 19 | promptMessage: async function(message, author, time, validReactions) { 20 | time *= 1000; 21 | for(const reaction of validReactions) await message.react(reaction); 22 | const filter = (reaction, user) => validReactions.includes(reaction.emoji.name) && user.id === author.id; 23 | return message 24 | .awaitReactions(filter, { max: 1, time: time }) 25 | .then(collected => collected.first() && collected.first().emoji.name); 26 | }, 27 | // for later use. 28 | loadSlashCommands() { 29 | return; 30 | }, 31 | loadEvents() { 32 | return; 33 | }, 34 | loadCommands() { 35 | return; 36 | }, 37 | }; -------------------------------------------------------------------------------- /commands/info/reddit.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const { MessageEmbed } = require("discord.js"); 3 | 4 | module.exports = { 5 | name: "reddit", 6 | category: "info", 7 | description: "Send an image from a sub reddit!", 8 | usage: "$reddit [sub-reddit]", 9 | run: async (bot, message, args) => { 10 | const { body } = await axios 11 | .get(`https://www.reddit.com/r/${args}.json?sort=top&t=week`) 12 | .query({ limit: 800 }); 13 | 14 | const allowed = message.channel.nsfw ? body.data.children : body.data.children.filter(post => !post.data.over_18); 15 | if(!allowed.length) return message.reply("We are running out of dank meme. 😂😂😂"); 16 | const randomNumber = Math.floor(Math.random() * allowed.length); 17 | const embed = new MessageEmbed() 18 | .setColor("PURPLE") 19 | .setTitle(allowed[randomNumber].data.title) 20 | .setDescription(allowed[randomNumber].data.author) 21 | .setImage(allowed[randomNumber].data.url) 22 | .addField("Information: ", "Up vote:" + allowed[randomNumber].data.ups + " / Comment: " + allowed[randomNumber].data.num_comments) 23 | .setURL("https://reddit.com" + allowed[randomNumber].data.permalink) 24 | .setTimestamp() 25 | .setFooter(bot.user.username, bot.user.displayAvatarURL()); 26 | return message.channel.send({ embeds: [embed] }); 27 | }, 28 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yukiko-opensource", 3 | "version": "2.0.0", 4 | "description": "As Yukiko 2.0 (Closed sources) grow I don't have much time to work and update this version. if you need a great bot to help with your Discord guilds please use [Yukiko.app](https://Yukiko.app)", 5 | "main": "index.js", 6 | "dependencies": { 7 | "ascii-table": "0.0.9", 8 | "axios": "^0.21.4", 9 | "beautify": "0.0.8", 10 | "canvas": "^2.10.1", 11 | "common-tags": "^1.8.2", 12 | "discord.js": "^14.6.0", 13 | "erela.js": "^2.4.0", 14 | "fast-sort": "^3.2.0", 15 | "moment": "^2.29.4", 16 | "mongoose": "^5.13.15", 17 | "ms": "^2.1.3", 18 | "snyk": "^1.1033.0" 19 | }, 20 | "scripts": { 21 | "test": "echo \"Error: no test specified\" && exit 1", 22 | "dev": "nodemon start" 23 | }, 24 | "keywords": [ 25 | "Discord", 26 | "bot", 27 | "Asthri", 28 | "Asthriona", 29 | "NodeJS", 30 | "NPM" 31 | ], 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/Asthriona/Yukiko.git" 35 | }, 36 | "author": "", 37 | "license": "ISC", 38 | "bugs": { 39 | "url": "https://github.com/Asthriona/Yukiko/issues" 40 | }, 41 | "homepage": "https://github.com/Asthriona/Yukiko#readme", 42 | "devDependencies": { 43 | "eslint": "^8.25.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /commands/dev/eval.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | const beautify = require("beautify"); 3 | const Config = require("../../botconfig.json"); 4 | module.exports = { 5 | name: "eval", 6 | category: "dev", 7 | description: "Run some code directly in discord! (developper only!)", 8 | run: async (bot, message, args) => { 9 | if(!Config.owners.includes(message.author.id)) return message.reply("You are not a developper! you can't run code just like that!"); 10 | if(!args[0]) return message.channel.send("Please gimme some good code!"); 11 | 12 | try { 13 | if(args.join(" ").toLowerCase().includes("token")) { 14 | return message.channel.send("No, I'm not gonna give you my token! Nice try tho!"); 15 | } 16 | const toEval = args.join(" "); 17 | const evaluated = eval(toEval); 18 | 19 | const embed = new MessageEmbed() 20 | .setColor("PURPLE") 21 | .setTimestamp() 22 | .setFooter(bot.user.username, bot.user.displayAvatarURL()) 23 | .setTitle("Elva") 24 | .addField("To Evaluate:", `\`\`\`js\n${beautify(args.join(" "), { format: "js" })}\n\`\`\``) 25 | .addField("Evaluated:", evaluated) 26 | .addField("Type of:", typeof (evaluated)); 27 | 28 | message.channel.send({ embeds: [embed] }); 29 | } 30 | catch (e) { 31 | message.channel.send("ERROR! \n ```" + e + "```"); 32 | } 33 | }, 34 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | botconfig.json 64 | .env 65 | ./node_modules 66 | 67 | package-lock.json 68 | 69 | test.js 70 | IbeatYou.js 71 | createinvite.js 72 | commands/dev/fetch.js 73 | commands/dev/create.js 74 | package-lock.json 75 | -------------------------------------------------------------------------------- /commands/music/queue.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | const ms = require("ms"); 3 | 4 | module.exports = { 5 | name: "queue", 6 | category: "music", 7 | description: "Show the queue", 8 | run: async (bot, message) => { 9 | const player = bot.manager.get(message.guild.id); 10 | if(!player) return message.reply("Noting playing at the moment."); 11 | try { 12 | if(!player.playing) return message.reply("Nothing is playing at the moment."); 13 | let total = 0; 14 | player.queue.forEach(queue => { 15 | total = total + queue.duration; 16 | }); 17 | const queueEmbed = new MessageEmbed()() 18 | .setAuthor({name: "Playlist " + ms(total, { long: true }), iconURL: message.author.displayAvatarURL() }) 19 | .setTitle(`Now Playing: ${player.queue.current.title} requested by: ${player.queue.current.requester.username}`) 20 | .setFooter({ text: `${bot.user.username} - Yukiko Dev Team`, iconURL: bot.user.displayAvatarURL() }); 21 | queueEmbed.addField("Last Song:", player.queue.previous ? `${player.queue.previous.title} | ${player.queue.previous.requester.username}` : "No previously played songs."); 22 | for (let i = 0; i < player.queue.length; i += 10) {queueEmbed.splitFields(player.queue.map(track => `${++i}) 『${track.title}』 | Requested by <@${track.requester.id}>`).join(("\n")));} 23 | message.channel.send(queueEmbed); 24 | } 25 | catch (error) { 26 | console.log(error); 27 | message.channel.send(`Oops! an error happened...\n\`\`\`${error.message}\`\`\``); 28 | } 29 | }, 30 | }; -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "env": { 4 | "node": true, 5 | "es6": true 6 | }, 7 | "parserOptions": { 8 | "ecmaVersion": 2019 9 | }, 10 | "rules": { 11 | "brace-style": ["warn", "stroustrup", { "allowSingleLine": true }], 12 | "comma-dangle": ["warn", "always-multiline"], 13 | "comma-spacing": "warn", 14 | "comma-style": "warn", 15 | "curly": ["warn", "multi-line", "consistent"], 16 | "dot-location": ["warn", "property"], 17 | "handle-callback-err": "off", 18 | "indent": ["warn", "tab"], 19 | "max-nested-callbacks": ["warn", { "max": 4 }], 20 | "max-statements-per-line": ["warn", { "max": 2 }], 21 | "no-console": "off", 22 | "no-empty-function": "warn", 23 | "no-floating-decimal": "warn", 24 | "no-inline-comments": "warn", 25 | "no-inner-declarations": "off", 26 | "no-lonely-if": "warn", 27 | "no-multi-spaces": "warn", 28 | "no-multiple-empty-lines": ["warn", { "max": 2, "maxEOF": 1, "maxBOF": 0 }], 29 | "no-shadow": ["warn", { "allow": ["err", "resolve", "reject"] }], 30 | "no-trailing-spaces": ["warn"], 31 | "no-var": "warn", 32 | "object-curly-spacing": ["warn", "always"], 33 | "prefer-const": "warn", 34 | "quotes": ["warn", "double"], 35 | "semi": ["warn", "always"], 36 | "space-before-blocks": "warn", 37 | "space-before-function-paren": ["warn", { 38 | "anonymous": "never", 39 | "named": "never", 40 | "asyncArrow": "always" 41 | }], 42 | "space-in-parens": "warn", 43 | "space-infix-ops": "warn", 44 | "space-unary-ops": "warn", 45 | "spaced-comment": "warn", 46 | "yoda": "warn" 47 | } 48 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Asthriona 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /commands/info/whois.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | const { stripIndents } = require("common-tags"); 3 | const { getMember, formatDate } = require("../../function"); 4 | 5 | module.exports = { 6 | name: "whois", 7 | aliases: ["who", "user", "info", "tamer"], 8 | description: "Returns user information", 9 | category: "info", 10 | usage: "[username | id | mention]", 11 | run: (bot, message, args) => { 12 | const member = getMember(message, args.join(" ")); 13 | 14 | // Member variables 15 | const joined = formatDate(member.joinedAt); 16 | const roles = member.roles.cache 17 | .filter(r => r.id !== message.guild.id) 18 | .map(r => r).join(", ") || "none"; 19 | 20 | // User variables 21 | const created = formatDate(member.user.createdAt); 22 | 23 | const embed = new MessageEmbed() 24 | .setAuthor({ name: message.author.username, iconURL: message.author.displayAvatarURL() }) 25 | .setThumbnail(member.user.displayAvatarURL({ dynamic: true })) 26 | .setColor(member.displayHexColor === "#000000" ? "#ffffff" : member.displayHexColor) 27 | .setFooter({ text: bot.user.username, iconURL: bot.user.displayAvatarURL() }) 28 | 29 | .addField("Member information:", stripIndents`**=> Display name:** ${member.displayName} 30 | **=> Joined at:** ${joined} 31 | **=> Roles:** ${roles}`, true) 32 | 33 | .addField("User information:", stripIndents`**=> ID:** ${member.user.id} 34 | **=> Username:** ${member.user.username} 35 | **=> Tag:** ${member.user.tag} 36 | **=> Created at:** ${created}`, true) 37 | 38 | .setTimestamp(); 39 | message.channel.send({ embeds: [embed] }); 40 | }, 41 | }; -------------------------------------------------------------------------------- /commands/info/botInfo.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | const pjson = require("../../package.json"); 3 | module.exports = { 4 | name: "botinfo", 5 | category: "info", 6 | description: "show you information about this bot.", 7 | run: async (bot, message) => { 8 | const botembed = new MessageEmbed() 9 | .setThumbnail(bot.user.displayAvatarURL) 10 | .setTitle("About this bot:") 11 | .setAuthor({ name: bot.user.username, iconURL: bot.user.displayAvatarURL() }) 12 | .setDescription("this bot can make your cat explode, Mount the DOGO, burn your egg and clean your house. (but not your room. we tested all of this.(RIP my cat...))") 13 | .setColor("#800080") 14 | .addField("Bot name:", bot.user.username, true) 15 | .addField("Version:", `${pjson.version} ${pjson.codeName}`, true) 16 | .addField("Developped by:", "[Asthriona](https://Asthriona.com) / [RiseDev](https://twitter.com/_RiseDev)", true) 17 | .addField("Developpers Website", "[Yukiko Dev Team](https://team.yukiko.app/), [Asthriona](https://Asthriona.com), [RiseDev](https://twitter.com/_RiseDev)", true) 18 | // Please DO NOT un-credit us. feel free to un-comment the line below to credit yourself :) 19 | // .addField("Edited by", "[Your Name](https://YourWebsiteOrLink.com)") 20 | .addField("Created on", bot.user.createdAt, true) 21 | .addField("On the server since:", bot.user.joinedAt, true) 22 | .addField("Git:", "https://github.com/Asthriona/Yukiko", true) 23 | .addField("Site: ", "http://yukiko.nishikino.me/", true) 24 | .addField("Guilds Using this bot: ", bot.guilds.size, true) 25 | .setTimestamp() 26 | .setFooter({ text: bot.user.username, iconURL: bot.user.displayAvatarURL() }); 27 | return message.reply({ embeds: [botembed] }); 28 | }, 29 | }; -------------------------------------------------------------------------------- /commands/info/addcard.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const botConfig = require("../../botconfig.json"); 3 | mongoose.connect(botConfig.dbLink, { 4 | useNewUrlParser: true, 5 | useUnifiedTopology: true, 6 | }); 7 | 8 | const Cards = require("../../model/card.js"); 9 | module.exports = { 10 | name: "card", 11 | aliases: ["cards", "rankcards", "changeCards", "newcards"], 12 | category: "info", 13 | description: "give you the possibility to change your card background!", 14 | usage: " | ", 15 | run: async (bot, message, args) => { 16 | if(args[0] === "info") { 17 | message.reply("You can send a custom image to use as a rank card.\n Your image must be in **934x282**. if it's not it will be stretched to this resolution. \n you must send a link to an image in ***.jpg*** or ***.png***. Any other link will be refused."); 18 | } 19 | console.log(args[0]); 20 | if(!args[0]) return message.reply("Please send a link to your image!"); 21 | if(!args[0].startsWith("http" || "https")) return message.reply("please send a valid link."); 22 | // fix this. 23 | // aaah. I cant remember the issue. well test and fix this future me please. 24 | if(!args[0].endsWith(".png") || !args[0].endsWith(".jpg")) return message.reply("please send a link to an image in jpg or png."); 25 | Cards.findOne({ 26 | did: message.author.id, 27 | }, (err, cards)=>{ 28 | if(err) console.log(err); 29 | if (!cards) { 30 | const newCards = new Cards({ 31 | did: message.author.id, 32 | link: args[0], 33 | }); 34 | newCards.save().catch(error => console.log(error)); 35 | message.reply("Your card has been saved!"); 36 | } 37 | else { 38 | cards.link = args[0]; 39 | cards.save().catch(error => console.log(error)); 40 | message.reply("Your card has been saved!"); 41 | } 42 | }); 43 | }, 44 | 45 | }; -------------------------------------------------------------------------------- /commands/info/help.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | const { stripIndents } = require("common-tags"); 3 | // var { botConfig } = require("../../botconfig.json") 4 | module.exports = { 5 | name: "help", 6 | category: "info", 7 | description: "Return all the commands for this bot.", 8 | usage: "[command | alias]", 9 | run: async (bot, message, args) => { 10 | if(args[0]) { 11 | return getCMD(bot, message, args[0]); 12 | } 13 | else { 14 | return getAll(bot, message); 15 | } 16 | }, 17 | }; 18 | // var prefix = botConfig.prefix; 19 | 20 | function getAll(bot, message) { 21 | const embed = new MessageEmbed() 22 | .setColor("RANDOM"); 23 | const commands = (category) => { 24 | return bot.Commands 25 | .filter(cmd => cmd.category === category) 26 | .map(cmd => `\`${cmd.name}\``) 27 | .join(", "); 28 | }; 29 | const info = bot.Categories 30 | .map(cat => stripIndents`**${cat[0].toUpperCase() + cat.slice(1)}** \n ${commands(cat)}`) 31 | .reduce((string, category) => string + "\n" + category); 32 | embed.setDescription(info); 33 | return message.reply({ embeds: [embed] }); 34 | } 35 | function getCMD(bot, message, input) { 36 | const embed = new MessageEmbed(); 37 | const cmd = bot.Commands.get(input.toLowerCase()) || bot.commands.get(bot.alias.get(input.toLowerCase())); 38 | let info = `No information for the commands ***${input.toLowerCase}`; 39 | embed.setColor("RED") 40 | .setDescription(info); 41 | if(!cmd) { 42 | return message.reply({ embeds: [embed] }); 43 | } 44 | if(cmd.name) info = `**command name** ${cmd.name}`; 45 | if(cmd.alias) info += `\n**Alialses** ${cmd.aliases.map(a => `\`${a}\``).join(", ")}`; 46 | if(cmd.description) info += `\n**Description**: ${cmd.description}`; 47 | if(cmd.usage) { 48 | info += `\n**Usage**: ${cmd.usage}`; 49 | embed.setFooter("Syntax: <> = Is required, [] = is optional") 50 | .setColor("PURPLE") 51 | .setDescription(info); 52 | } 53 | return message.reply({ embeds: [embed] }); 54 | } -------------------------------------------------------------------------------- /CHANGELOGS.md: -------------------------------------------------------------------------------- 1 | # Change Logs 2 | Cette page me sert a noter l'avancement du bot au file des mise a jours, j'y note tout les Add, les bug fix (réparation de bug), les supressions, et modification. 3 | 4 | # 1.0 5 | ## ***It's alive!*** 6 | + Add ban 7 | + Add kick 8 | + Add Mute 9 | + Add warn 10 | + Add report 11 | + Add ping 12 | + Add Présence personalisé 13 | + Add help (WIP) 14 | + Add help-commands (WIP) 15 | + Add help-game (WIP) 16 | + Add uptime 17 | + Add Clear (1 - 100) 18 | 19 | # 1.0.1 20 | ## ***[OwO]?*** 21 | + Fix: permission warn/unwarn 22 | + Fix: Erreur Ban sans raison 23 | + Fix: Erreur Kick sans raison 24 | + Fix: Permission command Watch, Play, stream 25 | + Edit: changed the link of a!help commands 26 | + Edit: Traduction francaise a!server-info 27 | + Edit: Traduction francaise a!info 28 | + Update: Change logs 29 | + Deleted: Weebness de Ash. 30 | 31 | # 1.1.0 32 | ## ***[UwU Music? OwO]*** 33 | + add: Music module [BETA] used with a!play a!skip a!stop 34 | + Edit: a!play has been changed to /game 35 | + Update: Change logs 36 | + deleted: Weebness de Ash. 37 | ## 1.1.1 38 | + Add: Queue system 39 | ## 1.1.2 40 | + Add: Better youtube support 41 | ## 1.1.3 42 | + Add: System play/pause 43 | + Add: volume commands 44 | + Add: Send music title when playing 45 | + Add: Now Playing command 46 | ## 1.1.4 47 | + Add: a!play now support playlists 48 | + Add: a!play now support youtube search 49 | + Add: Server Info 50 | + Add: User info 51 | + Update: Change logs 52 | + Deleted: Weebness de Ash. 53 | ## 2.0.0 [i'm Back to rules them all!] 54 | + Bot completely rewrited. 55 | + deleted: Mute commands [Temp] 56 | + Add: better commands handler 57 | + Add: a!animeFM is now playing [AnimeFM](https://Animefm.co) Main station 58 | + Update: Dynamic help commands 59 | + Update: a!help can now take argument like a command name to get more information on the commands. 60 | 61 | 62 | ### Bug 63 | + Warn reason can't contain only one word (fix in progress) 64 | + Uptime command is using his own time system. 65 | 66 | 67 | ## Road-Map 68 | + Custom rank cards -------------------------------------------------------------------------------- /commands/info/lbtop10.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | const mongoose = require("mongoose"); 3 | const botConfig = require("../../botconfig.json"); 4 | 5 | mongoose.connect(botConfig.dbLink, { 6 | useNewUrlParser: true, 7 | useUnifiedTopology: true, 8 | }); 9 | const Users = require("../../model/xp.js"); 10 | 11 | module.exports = { 12 | name: "top", 13 | category: "info", 14 | description: "Show the top 10 leaderboard!", 15 | run: async (bot, message) => { 16 | Users.find({ 17 | serverID: message.guild.id, 18 | }).sort([ 19 | ["xp", "descending"], 20 | ]).exec((err, res) => { 21 | if(err) console.log(err); 22 | const embed = new MessageEmbed() 23 | .setTitle("Yukiko's Leaderboard!") 24 | .setThumbnail(message.guild.iconURL()) 25 | .setDescription("Here is our top10!") 26 | .setFooter(`Powered by ${bot.user.username}`, bot.user.displayAvatarURL()); 27 | if(res.length === 0) { 28 | // if no result 29 | embed.setColor("red"); 30 | embed.addField("No Data :c"); 31 | } 32 | else if(res.length < 10) { 33 | // if less than 10 34 | embed.setColor("#351B96"); 35 | let i; 36 | for(i = 0; i < res.length; i++) { 37 | const member = message.guild.members.cache.get(res[i].did) || "User is gone :/"; 38 | if(member === "User is gone :/") { 39 | embed.addField(`${i + 1}. ${member}`, `**Level**: ${res[i].level} || **XP**: ${res[i].xp}`); 40 | 41 | } 42 | else{ 43 | embed.addField(`${i + 1}. ${member.user.username}`, `**Level**: ${res[i].level} || **XP**: ${res[i].xp}`); 44 | } 45 | } 46 | } 47 | else{ 48 | // if more than 10 49 | embed.setColor("#351B96"); 50 | let i; 51 | for(i = 0; i < 10; i++) { 52 | const member = message.guild.members.get(res[i].did) || "User is gone :/"; 53 | if(member === "User is gone :/") { 54 | embed.addField(`${i + 1}. ${member}`, `**Level**: ${res[i].level} || **XP**: ${res[i].xp}`); 55 | 56 | } 57 | else{ 58 | embed.addField(`${i + 1}. ${member.user.username}`, `**Level**: ${res[i].level} || **XP**: ${res[i].xp}`, true); 59 | } 60 | } 61 | } 62 | message.reply({ embeds: [embed] }); 63 | }); 64 | 65 | }, 66 | }; -------------------------------------------------------------------------------- /events/messageCreate.js: -------------------------------------------------------------------------------- 1 | // Holy fuck. Lots of work to do here. 2 | const Config = require("../botconfig.json"); 3 | const Users = require("../model/xp.js"); 4 | const Cards = require("../model/card.js"); 5 | const { lvlupimg } = require("../Cards.js"); 6 | module.exports = { 7 | name: "messageCreate", 8 | once: false, 9 | async execute(message, bot) { 10 | // ignore types of messages or without prefix. 11 | if (message.channel.type === "dm") return; 12 | if(message.author.bot) return; 13 | // DA NEW XP SYSTEM 2.0 14 | const xpAdd = Math.ceil(Math.random() * 15); 15 | const messageAdd = +1; 16 | 17 | 18 | Users.findOne({ 19 | did: message.author.id, 20 | serverID: message.guild.id, 21 | }, (err, users) => { 22 | if (err) console.log(err); 23 | if (!users) { 24 | const newUsers = new Users({ 25 | did: message.author.id, 26 | username: message.author.username, 27 | serverID: message.guild.id, 28 | xp: xpAdd, 29 | level: 0, 30 | message: messageAdd, 31 | warns: 0, 32 | avatarURL: message.author.displayAvatarURL(), 33 | }); 34 | 35 | newUsers.save().catch(error => console.log(error)); 36 | } 37 | else { 38 | users.xp = users.xp + xpAdd; 39 | users.message = users.message + messageAdd; 40 | users.username = message.author.username; 41 | users.avatarURL = message.author.displayAvatarURL(); 42 | 43 | const nxtlvl = 300 * Math.pow(2, users.level); 44 | if (users.xp >= nxtlvl) { 45 | users.level = users.level + 1; 46 | 47 | // lvl up image 48 | const sendimg = async function sendimg() { 49 | await lvlupimg(message, users); 50 | 51 | }; 52 | sendimg(); 53 | } 54 | users.save().catch(error => console.log(error)); 55 | } 56 | }); 57 | 58 | // Add default cards to new users 59 | Cards.findOne({ 60 | did: message.author.id, 61 | }, (err, cards) => { 62 | if (err) console.log(err); 63 | if (!cards) { 64 | const newCards = new Cards({ 65 | did: message.author.id, 66 | link: "https://cdn.yukiko.app/Cards/DefaultYukikocard.jpg", 67 | }); 68 | newCards.save().catch(error => console.log(error)); 69 | } 70 | }); 71 | 72 | // Setup Prefix and args 73 | const prefix = Config.prefix; 74 | const messageArray = message.content.split(" "); 75 | const args = messageArray.slice(1); 76 | const cmd = messageArray[0]; 77 | 78 | if(!prefix) return; 79 | // Commands Handler 80 | const commandfile = bot.Commands.get(messageArray[0].slice(prefix.length)); 81 | if (commandfile) commandfile.run(bot, message, args, cmd); 82 | }, 83 | }; -------------------------------------------------------------------------------- /commands/info/wow.js: -------------------------------------------------------------------------------- 1 | // Well... I got this commands working on another bot (private commission) but I think i never finished it here. 2 | // Naw worries, its on my todo list :) 3 | const { MessageEmbed } = require("discord.js"); 4 | const axios = require("axios"); 5 | const botConfig = require("../../botconfig.json"); 6 | 7 | module.exports = { 8 | name: "wow", 9 | category: "info", 10 | description: "Return your World of warcraft character!", 11 | usage: "", 12 | run: async (bot, message, args) => { 13 | const char = args[0]; 14 | const realm = args[1]; 15 | let region = args[2]; 16 | if(!region) region = "eu"; 17 | console.log(args[0] + " " + args[1]); 18 | axios.get("https://" + region + ".api.blizzard.com/wow/character/" + realm + "/" + char + "?locale=en_US&access_token=" + botConfig.wowAT).then(function(res) { 19 | 20 | if(message.author.id === "186195458182479874") { 21 | if(res.data.faction === 0) { 22 | const wowembed = new MessageEmbed()() 23 | .setTitle("Infos for: " + args) 24 | .addField("Name:", res.data.name, true) 25 | .addField("Realm", res.data.realm, true) 26 | .addField("Battlegroup", res.data.battlegroup, true) 27 | .addField("Class:", res.data.class, true) 28 | .addField("Race", res.data.race, true) 29 | .addField("Gender", res.data.gender, true) 30 | .addField("level", res.data.level, true) 31 | .addField("Achievement Points", res.data.achievementPoints, true) 32 | .addField("Calc Class", res.data.calcClass, true) 33 | .addField("faction", "Alliance", true) 34 | .addField("Total Honorable Kills", res.data.totalHonorableKills, true) 35 | .addField("ID", res.data.id, true); 36 | message.channel.send({ embeds: [wowembed] }); 37 | } 38 | else{ 39 | const wowembed = new MessageEmbed()() 40 | .setTitle("Infos for: " + args) 41 | .addField("Name:", res.data.name, true) 42 | .addField("Realm", res.data.realm, true) 43 | .addField("Battlegroup", res.data.battlegroup, true) 44 | .addField("Class:", res.data.class, true) 45 | .addField("Race", res.data.race, true) 46 | .addField("Gender", res.data.gender, true) 47 | .addField("level", res.data.level, true) 48 | .addField("Achievement Points", res.data.achievementPoints, true) 49 | .addField("Calc Class", res.data.calcClass, true) 50 | .addField("faction", "Horde", true) 51 | .addField("Total Honorable Kills", res.data.totalHonorableKills, true) 52 | .addField("ID", res.data.id, true); 53 | message.channel.send({ embeds: [wowembed] }); 54 | } 55 | } 56 | }).catch(err => message.channel.send("WAW! an error sucessfully happened! ```" + err + "```")); 57 | }, 58 | }; -------------------------------------------------------------------------------- /commands/music/play.js: -------------------------------------------------------------------------------- 1 | const ms = require("ms"); 2 | 3 | module.exports = { 4 | name: "play", 5 | category: "music", 6 | description: "Play music from youtube", 7 | run: async (bot, message, args) => { 8 | const { channel } = message.member.voice; 9 | if (!channel) return message.reply("You must be in a voice channel."); 10 | let player = bot.manager.get(message.guild.id); 11 | if(!player) { 12 | player = bot.manager.create({ 13 | guild: message.guild.id, 14 | voiceChannel: message.member.voice.channel.id, 15 | textChannel: message.channel.id, 16 | }); 17 | player.connect(); 18 | } 19 | try { 20 | bot.manager.search(args.join(" "), message.author).then(async res =>{ 21 | switch (res.loadType) { 22 | case "TRACK_LOADED": 23 | player.queue.add(res.tracks[0]); 24 | message.channel.send(`${res.tracks[0].title} has been added to the queue.`); 25 | if(player.playing == true) { 26 | return; 27 | } 28 | else{ 29 | player.play(); 30 | } 31 | break; 32 | case "SEARCH_RESULT": 33 | // Music search not working anymore for whatever reason. 34 | // if someone wanna fix it, go ahead and PR :) 35 | player.queue.add(res.tracks[0]); 36 | message.reply(`${res.tracks[0].title} has been added to the queue.`); 37 | if (player.playing == true) { 38 | return; 39 | } 40 | else { 41 | player.play(); 42 | } 43 | break; 44 | // let index = 1; 45 | // const tracks = res.tracks.slice(0, 5); 46 | // const embed = new MessageEmbed() 47 | // .setAuthor("Song Selection", bot.user.displayAvatarURL()) 48 | // .setDescription(tracks.map(video => `**${index++} - ** ${video.title}`)) 49 | // .setFooter("Your response time close within 30 seconds."); 50 | 51 | // await message.channel.send(embed); 52 | // const collector = message.channel.createMessageCollector(m =>{ 53 | // return m.author.id === message.author.id && new RegExp("^([1-5|cancel])$", "i").test(m.content); 54 | // }, { time: 30000, max: 1 }); 55 | // collector.on("collect", m =>{ 56 | // const track = tracks[Number(m.content) - 1]; 57 | // player.queue.add(track); 58 | // if(player.playing) { 59 | // return; 60 | // } 61 | // else{ 62 | // player.play(); 63 | // } 64 | // }); 65 | // break; 66 | case "PLAYLIST_LOADED": 67 | res.tracks.forEach(track => player.queue.add(track)); 68 | message.reply(`Enqueuing \`${res.tracks.length}\` tracks from the playlist \`${res.playlist.name}\` total time: \`${ms(res.playlist.duration, { long: true })}\``); 69 | if(player.playing) { 70 | return; 71 | } 72 | else{ 73 | player.play(); 74 | } 75 | break; 76 | } 77 | }); 78 | } 79 | catch (error) { 80 | message.channel.send("Oops! an error happened..."); 81 | console.log(error); 82 | } 83 | }, 84 | }; -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "dev" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "dev" ] 20 | schedule: 21 | - cron: '26 19 * * 6' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /commands/moderation/mute.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unreachable */ 2 | const { MessageEmbed } = require("discord.js"); 3 | const ms = require("ms"); 4 | 5 | module.exports = { 6 | name: "mute", 7 | category: "Moderation", 8 | description: "Create a new role!", 9 | usage: "!mute <@mention>