├── .circleci
└── config.yml
├── .eslintrc.json
├── .github
├── FUNDING.yml
├── stale.yml
└── workflows
│ ├── codeql-analysis.yml
│ └── stale.yml
├── .gitignore
├── CHANGELOGS.md
├── CODE_OF_CONDUCT.md
├── Cards.js
├── LICENSE
├── README.md
├── botconfig.json copy.exemple
├── commandhandler file exemple.txt
├── commands
├── dev
│ └── eval.js
├── info
│ ├── addcard.js
│ ├── botInfo.js
│ ├── game.js
│ ├── help.js
│ ├── invit.js
│ ├── lbtop10.js
│ ├── ping.js
│ ├── rank.js
│ ├── reddit.js
│ ├── serverinfo.js
│ ├── uptime.js
│ ├── whois.js
│ ├── wink.js
│ └── wow.js
├── moderation
│ ├── ban.js
│ ├── clear.js
│ ├── kick.js
│ ├── mute.js
│ └── say.js
└── music
│ ├── join.js
│ ├── leave.js
│ ├── pause.js
│ ├── play.js
│ ├── queue.js
│ ├── resume.js
│ ├── skip.js
│ └── volume.js
├── deploy-commands.js
├── events
├── disconnect.js
├── guildMemberAdd.js
├── guildMemberRemove.js
├── interactionCreate.js
├── messageCreate.js
├── ready.js
└── reconnecting.js
├── function.js
├── handler
└── command.js
├── index.js
├── model
├── card.js
└── xp.js
├── package.json
└── slash
└── commands
└── ping.js
/.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 |
--------------------------------------------------------------------------------
/.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 | }
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | patreon: Asthriona
4 | ko_fi: Asthriona
5 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at im@asthriona.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/Cards.js:
--------------------------------------------------------------------------------
1 | const { MessageAttachment } = require("discord.js");
2 | const { getMember } = require("./function");
3 | const Canvas = require("canvas");
4 | const Cards = require("./model/card");
5 |
6 | module.exports = {
7 | // Level up image
8 | async lvlupimg(message, users) {
9 | const applyText = (canvas, text) => {
10 | const ctx = canvas.getContext("2d");
11 | let fontSize = 70;
12 | do {
13 | ctx.font = `${fontSize -= 10}px sans-serif`;
14 | } while (ctx.measureText(text).width > canvas.width - 300);
15 | return ctx.font;
16 | };
17 | const canvas = Canvas.createCanvas(934, 282);
18 | const ctx = canvas.getContext("2d");
19 | Cards.findOne({
20 | did: message.author.id,
21 | }, async (err, cards)=>{
22 | const cardbg = cards.link;
23 | const member = getMember(message);
24 | const background = await Canvas.loadImage(cardbg);
25 | ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
26 | // Draw rectangle
27 | ctx.beginPath();
28 | ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
29 | ctx.fillRect(260, 80, 650, 160);
30 | ctx.closePath();
31 | ctx.stroke();
32 | // show Username
33 | ctx.font = applyText(canvas, member.displayName);
34 | ctx.fillStyle = "#fff";
35 | ctx.fillText(member.displayName + " Level up!", 280, 136);
36 | // Show Level & XP
37 | const nxtlvl = 300 * Math.pow(2, users.level);
38 | const xpleft = nxtlvl - users.xp;
39 | ctx.font = "40px sans-serif";
40 | ctx.fillStyle = "#fff";
41 | ctx.fillText("You are level now " + users.level + " - " + users.xp + " XP", 280, 180);
42 | // xp Left
43 | ctx.font = "50px sans-serif";
44 | ctx.fillStyle = "#fff";
45 | ctx.fillText("Next Level in " + xpleft + " xp", 280, 225);
46 | // Get avatar
47 | const avatar = await Canvas.loadImage(message.author.displayAvatarURL({ format: "jpg" }));
48 | ctx.beginPath();
49 | ctx.arc(125, 140, 100, 0, Math.PI * 2);
50 | ctx.closePath();
51 | ctx.clip();
52 | ctx.drawImage(avatar, 25, 40, 200, 200);
53 | // put image together and send it
54 | const lvlupimg = new MessageAttachment(canvas.toBuffer(), "lvlup-image.png");
55 | message.channel.send(lvlupimg);
56 | });
57 | },
58 |
59 | // Welcome Cards
60 | async WelcomeCad(member, channel) {
61 | const applyText = (canvas, text) => {
62 | const ctx = canvas.getContext("2d");
63 | let fontSize = 70;
64 | do {
65 | ctx.font = `${fontSize -= 10}px sans-serif`;
66 | } while (ctx.measureText(text).width > canvas.width - 300);
67 | return ctx.font;
68 | };
69 | Cards.findOne({
70 | did: member.user.id,
71 | }, async (err, cards)=>{
72 | const canvas = Canvas.createCanvas(934, 282);
73 | const ctx = canvas.getContext("2d");
74 | const cardbg = cards.link;
75 | const background = await Canvas.loadImage(cardbg);
76 | ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
77 | ctx.beginPath();
78 | ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
79 | ctx.fillRect(260, 80, 650, 130);
80 | ctx.stroke();
81 | // get username
82 | ctx.font = applyText(canvas, member.user.username);
83 | ctx.fillStyle = "#fff";
84 | ctx.fillText(member.user.username, 280, 141);
85 | // Get guild name
86 | ctx.font = applyText(canvas, member.guild.name);
87 | ctx.fillStyle = "#fff";
88 | ctx.fillText("Joined the server! ", 280, 195);
89 | // Get avatar
90 | const avatar = await Canvas.loadImage(member.user.displayAvatarURL({ format: "jpg" }));
91 | ctx.beginPath();
92 | ctx.arc(140, 128, 110, 0, Math.PI * 2);
93 | ctx.closePath();
94 | ctx.clip();
95 | ctx.drawImage(avatar, 25, 15, 256, 256);
96 | const attachment = new MessageAttachment(canvas.toBuffer(), "welcome-image.png");
97 | channel.send(`Welcome ${member.user}`, attachment);
98 | });
99 | },
100 | // Farewell Cards
101 | async farewell(member, channel) {
102 | const applyText = (canvas, text) => {
103 | const ctx = canvas.getContext("2d");
104 | let fontSize = 70;
105 | do {
106 | ctx.font = `${fontSize -= 10}px sans-serif`;
107 | } while (ctx.measureText(text).width > canvas.width - 300);
108 | return ctx.font;
109 | };
110 | Cards.findOne({
111 | did: member.user.id,
112 | }, async (err, cards) =>{
113 | if(err) return console.log(err);
114 | const canvas = Canvas.createCanvas(934, 282);
115 | const ctx = canvas.getContext("2d");
116 | const background = await Canvas.loadImage(cards.link);
117 | ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
118 | ctx.beginPath();
119 | ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
120 | ctx.fillRect(260, 80, 650, 130);
121 | ctx.stroke();
122 | // get username
123 | ctx.font = applyText(canvas, member.user.username);
124 | ctx.fillStyle = "#fff";
125 | ctx.fillText(member.user.username, 280, 141);
126 | // Get guild name
127 | ctx.font = applyText(canvas, member.guild.name);
128 | ctx.fillStyle = "#fff";
129 | ctx.fillText("Left the server! ", 280, 195);
130 | // Get avatar
131 | const avatar = await Canvas.loadImage(member.user.displayAvatarURL({ format: "jpg" }));
132 | ctx.beginPath();
133 | ctx.arc(140, 128, 110, 0, Math.PI * 2);
134 | ctx.closePath();
135 | ctx.clip();
136 | ctx.drawImage(avatar, 25, 15, 256, 256);
137 | const attachment = new MessageAttachment(canvas.toBuffer(), "farewell-image.png");
138 | channel.send(attachment);
139 | });
140 | },
141 | };
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PROJECT NO LONGER SUPPORTED!
2 | 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)
3 |
4 | [](https://top.gg/bot/641626560457342987)
5 |
6 | ## Edit (21/04/21)
7 | You are a lot to still star this thing so I updated it, should be working fine now, and updated to djs 12 and better music system. I didnt put as much work or code quality than on Yukiko.app but its working. You are very welcome :)
8 |
9 | # Yukiko
10 | Yukiko is a powerfull Discord bot that include XP system, Leaderboard, Music, Welcome and farewell message, Moderation, and much more!
11 |
12 | This bot is in developement state and actively updated, Feel free to come back take a look to our change logs!
13 |
14 |
15 | # I want to use it!
16 | Nice! Let me help you!
17 | ### I don't want / don't know how to host it.
18 | In that case feel free to add the Official Yukiko bot to your Discord server via this [Check on our website to invite Yukiko](https://yukiko.app/) to your server!
19 |
20 | ### I want to host it myself!
21 | Okay cool! you save me few bucks for the hosting :3
22 | Here is the tutorial on how to install and configure the bot!
23 |
24 | # Install
25 | To install and use this bot you need few things first.
26 | ## If you are on debian/ubuntu
27 | ```
28 | curl -fsSL https://deb.nodesource.com/setup_14.x | bash -
29 | apt-get install -y nodejs
30 | apt install build-essential
31 | ```
32 | ## for Windows:
33 | Install nodeJS from this [link](https://nodejs.org/en/)
34 | Open a powershell in admin mode `win+x`
35 | You can install gitbash or download the code via [this link](https://github.com/Asthriona/Yukiko/archive/master.zip)
36 | ```
37 | npm install --global windows-build-tools
38 | ```
39 | Then your system should be ready.
40 | ```
41 | git clone https://github.com/Asthriona/Yukiko.git
42 | cd Yukiko
43 | npm install
44 | npm run start
45 | ```
46 | For Linux you should install "screen" package to be able to keep the bot running in the background. you can also use [PM2](https://pm2.io/)
47 |
48 | # Lavalink
49 | I switched the Music bot to Lavalink and Erela.js for practical reasons (Youtube-DL was a pain to set up in the code and require a lot of ressources.)
50 | Please find [Lavalink](https://github.com/freyacodes/Lavalink-Client) on the Author repo and follow their install instruction (Don't worry thats very easy.)
51 | ## Update
52 | The author changed their name to Freyacodes and someone else too their old name, if you google 'Lavalink' you'll find the old name repo, Follow the link upthere to get the right one.
53 | The [Yukiko Dev Team](https://github.com/Yukiko-Dev-Team) forked it you can follow that link too.
54 |
55 | # Configuration
56 | Yukiko's configuration is pretty simple.
57 | You need a MongoDB database, and a Discord bot
58 | [Discord Developper portal](https://discordapp.com/developers/applications/)
59 | [Free mongoDB Database Culsters](https://www.mongodb.com/cloud/atlas)
60 |
61 | copy the exemple file
62 | ```
63 | cp botconfig.json.exemple botconfig.json
64 | ```
65 | `token` is your Discord bot token
66 | `prefix` a! by default you can change it for whatever you want.
67 | `dbLink` The login link of your database.
68 |
69 | # Official Discord Server.
70 | For now Yukiko don't have any public place. Just a nice little home called "Dev Bot Zone." This is a private server dedicated to my developement bot.
71 | If you want to contact me to get some help, or having an idea, please feel free to open an issue, or contact me on Twitter [@Asthriona](https://twitter.com/Asthriona)
72 | for bug report, please open an issue, and give me all the information you have!
73 | (She have very quite room mate, one of them is a [wall](https://github.com/Asthriona/TheWallDiscordBot)!)
74 | 
75 |
76 | # Modification
77 | You can modify the bos as you pleased. But you have to credit me, and my collaborator.
78 | Please leave the credit in the "bot info" commands.
79 |
80 | # Help me
81 | Hi, I'am [Asthriona](https://Asthriona.com) Full time WoW player, and some kind of developper. i'm doing stuff on internet for quite a long time... a decade now, and I love making stuff that can be usefull or help other.
82 | But if you want to help me, Feel free to take a look at the code, Create issue for idea/bugs, or pull request.
83 |
84 | As I said, i'm full time doing this, and now days, being indie developper don't really pay the bills (not even talking about server bill.), so if you really want to help, and have some bucks to spare, Feel free to pay me a ko-fi
85 |
86 | [](https://ko-fi.com/C0C61FCVH)
87 |
88 | Thanks for your interest in Yukiko! <3
89 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/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 | };
--------------------------------------------------------------------------------
/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/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/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 | };
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/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 | };
--------------------------------------------------------------------------------
/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 | };
--------------------------------------------------------------------------------
/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 | };
--------------------------------------------------------------------------------
/commands/info/rank.js:
--------------------------------------------------------------------------------
1 | const discord = require("discord.js");
2 | const mongoose = require("mongoose");
3 | const Canvas = require("canvas");
4 |
5 | const botConfig = require("../../botconfig.json");
6 | const { getMember } = require("../../function");
7 |
8 | mongoose.connect(botConfig.dbLink, {
9 | useNewUrlParser: true,
10 | useUnifiedTopology: true,
11 | });
12 | const Users = require("../../model/xp.js");
13 | const Cards = require("../../model/card.js");
14 |
15 | module.exports = {
16 | name: "rank",
17 | aliases: ["level", "card"],
18 | description: "Show you your XP Card.",
19 | category: "info",
20 | usage: "[username | id | mention]",
21 | run: async (bot, message, args) => {
22 | const canvas = Canvas.createCanvas(934, 282);
23 | const ctx = canvas.getContext("2d");
24 | // Get Background Image
25 | Cards.findOne({
26 | did: message.author.id,
27 | }, (err, cards) => {
28 | if (err) {
29 | console.log(err);
30 | return message.reply("An error happened. ```" + err + "```");
31 | }
32 | const cardBg = cards.link;
33 | Users.findOne({
34 | did: message.author.id,
35 | serverID: message.guild.id,
36 | }, async (err, users) => {
37 | if (err) {
38 | console.log(err);
39 | return message.reply("An error happened. ```" + err + "```");
40 | }
41 | const member = getMember(message, args.join(" "));
42 | const background = await Canvas.loadImage(cardBg);
43 | ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
44 | // Draw rectangle
45 | ctx.beginPath();
46 | ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
47 | ctx.fillRect(260, 80, 650, 160);
48 | ctx.closePath();
49 | ctx.stroke();
50 | // Get Username
51 | ctx.font = "60px sans-serif";
52 | ctx.fillStyle = "#fff";
53 | ctx.fillText(member.displayName, 280, 136);
54 | // Show XP and levels
55 | const nxtlvl = 300 * Math.pow(2, users.level);
56 | ctx.font = "40px sans-serif";
57 | ctx.fillStyle = "#fff";
58 | ctx.fillText("You are level " + users.level + " - " + users.xp + " XP", 280, 180);
59 | // xp left
60 | const xpLeft = nxtlvl - users.xp;
61 | ctx.font = "50px sans-serif";
62 | ctx.fillStyle = "#fff";
63 | ctx.fillText(`next level in ${xpLeft} XP`, 280, 225);
64 | // Get avatar
65 | console.log("pog");
66 | await GetAvatar(message, ctx);
67 | // Put all the things together and send it in a nice package.
68 | const lvlimg = new discord.MessageAttachment(canvas.toBuffer(), "rank-cards.png");
69 | message.reply({ files: [lvlimg] });
70 | });
71 | });
72 | },
73 | };
74 |
75 | async function GetAvatar(message, ctx) {
76 | // I HATE this part. I think here at the Yukiko Dev Team Incorporation ltd llc Group we all hate this part.
77 | // If Anyone know how to use canvas and this part better than us, please feel free to PR :)
78 | // (or if you are a dev of node-canvas please contact me on Twitter/Github @Asthriona )
79 |
80 | // EDIT: We did it better on Yukiko :) (https://Yukiko.app) - Asthriona.
81 | // EDIT2: I should seriously update that ahah!
82 |
83 | // Avatar function
84 | // get user in the database.
85 | Users.findOne({
86 | did: message.author.id,
87 | }, async (err, users)=>{
88 | // XP bar calculus. (Help)
89 | const nxtlvl = 300 * Math.pow(2, users.level);
90 | const n = ((users.xp - nxtlvl) / nxtlvl) * -100;
91 | const member = getMember(message);
92 | const arc = (100 - n) / 100 * Math.PI;
93 | // Image arc draw (Cry in js)
94 | ctx.strokeStyle = member.displayHexColor;
95 | ctx.beginPath();
96 | ctx.lineWidth = 15;
97 | ctx.arc(125, 140, 102, Math.PI * 1.5, arc);
98 | ctx.stroke();
99 | });
100 | // lvlbar background
101 | ctx.strokeStyle = "rgba(0, 0, 0, 0.8)";
102 | ctx.beginPath();
103 | ctx.lineWidth = 20;
104 | ctx.arc(125, 140, 102, 0, Math.PI * 2);
105 | ctx.stroke();
106 | // Print the profile picture.
107 | const avatar = await Canvas.loadImage(message.author.displayAvatarURL({ format: "jpg" }));
108 | ctx.beginPath();
109 | ctx.arc(125, 140, 100, 0, Math.PI * 2);
110 | ctx.closePath();
111 | ctx.clip();
112 | ctx.drawImage(avatar, 25, 40, 200, 200);
113 | }
114 |
--------------------------------------------------------------------------------
/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 | };
--------------------------------------------------------------------------------
/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 | };
--------------------------------------------------------------------------------
/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/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/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/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/moderation/ban.js:
--------------------------------------------------------------------------------
1 | const { MessageEmbed } = require("discord.js");
2 | const { stripIndents } = require("common-tags");
3 | const { promptMessage } = require("../../function");
4 | module.exports = {
5 | name: "ban",
6 | category: "moderation",
7 | description: "Ban a user that break the law!",
8 | usage: "",
9 | run: async (bot, message, args) => {
10 | const logChannel = message.guild.channels.find(c => c.name === "incident") || message.channel;
11 | if(!args[0]) {
12 | return message.reply(" ❌ You forgot to tell me wich user you want to ban.");
13 | }
14 | if(!args[1]) {
15 | return message.reply(" ❌ Please provide a reason to ban someone.");
16 | }
17 | if(!message.member.permissions.has("BAN_MEMBERS")) {
18 | return message.reply(" ❌ You don't have the permission to ban somebody. Please use a!report.");
19 | }
20 | if(!message.guild.me.permissions.has("BAN_MEMBERS")) {
21 | return message.reply(" ❌ I don't have to permissions to ban.");
22 | }
23 |
24 | const toban = message.mentions.members.first() || message.guild.members.get(args[0]);
25 | if(!toban) {
26 | return message.reply(" ❌ Cannot find that user :/");
27 | }
28 | if(toban.id === "186195458182479874") {
29 | return message.reply(" ❌ Dont you dare ban my dad?! D:<");
30 | }
31 | if(toban.id === "635422418424299521") {
32 | return message.reply(" ❌ Dont you dare ban my mum?! D:<");
33 | }
34 | if(message.author.id === toban.id) {
35 | return message.reply(" ❌ You can't ban yourself you smart ass... 🤷♀️🤷♂️");
36 | }
37 | if(bot.user.id === toban.id) {
38 | return message.reply(" ❌ Dont you dare try to ban me?!");
39 | }
40 | if(!toban.bannable) {
41 | return message.reply("You can't ban this user because he/she is better than u **:)**");
42 | }
43 |
44 | const embed = new MessageEmbed()()
45 | .setAuthor({ name: "~Ban!~", iconURL: message.author.displayAvatarURL()})
46 | .setColor("#FF0000")
47 | .setThumbnail(toban.user.displayAvatarURL())
48 | .setFooter(bot.user.username, bot.user.displayAvatarURL())
49 | .setTimestamp()
50 | .setDescription(stripIndents`**=> baned Member:** ${toban} (${toban.id})
51 | ***=> baned by:*** ${message.author} (${message.author.id})
52 | ***=> Reason:*** ${args.slice(1).join(" ")}`, true);
53 |
54 | const promptEmbed = new MessageEmbed()()
55 | .setColor("GREEN")
56 | .setAuthor({ name: "This verification becomes invalid after 30s." })
57 | .setDescription(`Do you want to ban ${toban}?`)
58 | .setTimestamp();
59 |
60 | const publicEmbed = new MessageEmbed()()
61 | .setColor("PURLPLE")
62 | .setAuthor({ name: bot.user.username, iconURL: bot.user.displayAvatarURL() })
63 | .setDescription(`${toban} Just got baned by ${message.author}!`)
64 | .setImage("https://media.giphy.com/media/xUO4t2gkWBxDi/giphy.gif")
65 | .setTimestamp()
66 | .setFooter({ text: bot.user.username, iconURL: bot.user.displayAvatarURL() });
67 |
68 | await message.channel.send({ embeds: [promptEmbed] }).then(async msg =>{
69 | const emoji = await promptMessage(msg, message.author, 30, ["✔️", "❌"]);
70 | if(emoji === "✔️") {
71 | msg.delete();
72 | logChannel.send({ embeds: [embed] });
73 | message.channel.send({ embeds: [publicEmbed] });
74 | toban.ban(args.slice(1).join(" ") + " by " + message.author.username)
75 | .catch(err => {
76 | if(err) return message.channel.send("Error: \n ```" + err + "```");
77 | });
78 | }
79 | else if (emoji === "❌") {
80 | msg.delete();
81 | message.reply(`ban cancelled. \n You got lucky this time ${toban}!`);
82 | }
83 | });
84 | },
85 | };
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/commands/moderation/kick.js:
--------------------------------------------------------------------------------
1 | const { MessageEmbed } = require("discord.js");
2 | const { stripIndents } = require("common-tags");
3 | const { promptMessage } = require("../../function");
4 | module.exports = {
5 | name: "kick",
6 | category: "moderation",
7 | description: "Kick a user that break the law!",
8 | usage: "",
9 | run: async (bot, message, args) => {
10 | const logChannel = message.guild.channels.find(c => c.name === "incident") || message.channel;
11 | if(!args[0]) {
12 | return message.reply(" ❌ You forgot to tell me wich user you want to kick.");
13 | }
14 | if(!args[1]) {
15 | return message.reply(" ❌ Please provide a reason to kick someone.");
16 | }
17 | if(!message.member.permissions.has("KICK_MEMBERS")) {
18 | return message.reply(" ❌ You don't have the permission to kick somebody. Please use a!report.");
19 | }
20 | if(!message.guild.me.permissions.has("KICK_MEMBERS")) {
21 | return message.reply(" ❌ I don't have to permissions to Kick.");
22 | }
23 |
24 | const toKick = message.mentions.members.first() || message.guild.members.get(args[0]);
25 | if(!toKick) {
26 | return message.reply(" ❌ Cannot find that user :/");
27 | }
28 | if(toKick.id === "186195458182479874") {
29 | return message.reply(" ❌ Dont you dare kick my dad?! D:<");
30 | }
31 | if(toKick.id === "635422418424299521") {
32 | return message.reply(" ❌ Dont you dare kick my mum?! D:<");
33 | }
34 | if(message.author.id === toKick.id) {
35 | return message.reply(" ❌ You can't kick yourself you smart ass... 🤷♀️🤷♂️");
36 | }
37 | if(bot.user.id === toKick.id) {
38 | return message.reply(" ❌ Dont you dare try to kick me?!");
39 | }
40 | if(!toKick.kickable) {
41 | return message.reply("You can't kick this user because he/she is better than u **:)**");
42 | }
43 |
44 | const embed = new MessageEmbed()()
45 | .setAuthor({ name: "~Kick!~"})
46 | .setColor("#FF0000")
47 | .setThumbnail(toKick.user.displayAvatarURL())
48 | .setFooter(bot.user.username, bot.user.displayAvatarURL())
49 | .setTimestamp()
50 | .setDescription(stripIndents`**=> Kicked Member:** ${toKick} (${toKick.id})
51 | ***=> Kicked by:*** ${message.author} (${message.author.id})
52 | ***=> Reason:*** ${args.slice(1).join(" ")}`, true);
53 |
54 | const promptEmbed = new MessageEmbed()()
55 | .setColor("GREEN")
56 | .setAuthor({ name: "This verification becomes invalid after 30s."})
57 | .setDescription(`Do you want to kick ${toKick}?`)
58 | .setTimestamp();
59 |
60 | const publicEmbed = new MessageEmbed()()
61 | .setColor("PURLPLE")
62 | .setAuthor({ name: bot.user.username, iconURL: bot.user.displayAvatarURL() })
63 | .setDescription(`${toKick} Just got kicked by ${message.author}!`)
64 | .setImage("https://cdn.asthriona.com/kick.gif")
65 | .setTimestamp()
66 | .setFooter({ text: "Kick Sponsored by Asthriona LLC!", iconURL: bot.user.displayAvatarURL() });
67 |
68 | await message.channel.send(promptEmbed).then(async msg =>{
69 | const emoji = await promptMessage(msg, message.author, 30, ["✔️", "❌"]);
70 | if(emoji === "✔️") {
71 | msg.delete();
72 | logChannel.send(embed);
73 | message.channel.send(publicEmbed);
74 | toKick.kick(args.slice(1).join(" "))
75 | .catch(err => {
76 | if(err) return message.channel.send("Error: \n ```" + err + "```");
77 | });
78 | }
79 | else if (emoji === "❌") {
80 | msg.delete();
81 | message.reply(`Kick cancelled. \n You got lucky this time ${toKick}!`);
82 | }
83 | });
84 | },
85 | };
--------------------------------------------------------------------------------
/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>