Skip to content

Commit 43d9dd0

Browse files
authored
(update): tip command fix + new command (#73)
* (update): Version 4.0.4 update (#71) * (feat): create Continuous Integration (#72) * (update): Remove old node versions * (feat): add test file * Update README.md * (update): add dev branch to workflow * (fix): tip throwing error when tipping unregistered users * (feat): new command -> creditslb * (fix): string truncation * (update): rename coins to credits on bal command. * (refactor): add streak on bal command
1 parent 956f76b commit 43d9dd0

File tree

9 files changed

+258
-39
lines changed

9 files changed

+258
-39
lines changed

.github/workflows/node.js.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3+
4+
name: Node.js CI
5+
6+
on:
7+
push:
8+
branches: [ master, dev ]
9+
pull_request:
10+
branches: [ master, dev ]
11+
12+
jobs:
13+
build:
14+
15+
runs-on: ubuntu-latest
16+
17+
strategy:
18+
matrix:
19+
node-version: [14.x]
20+
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
21+
22+
steps:
23+
- uses: actions/checkout@v2
24+
- name: Use Node.js ${{ matrix.node-version }}
25+
uses: actions/setup-node@v1
26+
with:
27+
node-version: ${{ matrix.node-version }}
28+
- run: npm ci
29+
- run: npm run build --if-present
30+
- run: npm test

README.md

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,72 @@
1-
##  [Mai](https://invite.mai-san.ml/) - A Discord Bot Based Around Anime
2-
3-
[![Online](https://img.shields.io/discord/703922441768009731?color=%237289DA&label=Support&logo=discord&logoColor=white)](https://support.mai-san.ml/)
4-
[![App Version](https://img.shields.io/github/package-json/v/maisans-maid/mai/master?color=pink&label=Current%20Version)](https://github.com/maisans-maid/Mai)
5-
[![Node](https://img.shields.io/static/v1?label=node&message=>=14.0.0&color=success&logo=Node.js&logoColor=white)](https://nodejs.org/dist/latest-v14.x/)
6-
[![heroku](https://img.shields.io/static/v1?label=heroku&message=ready%20to%20deploy&color=purple&logo=heroku)](https://herokuapp.com)
7-
[![DJS](https://img.shields.io/github/package-json/dependency-version/maisans-maid/Mai/discord.js?logo=github)](https://discord.js.org/)
8-
[![License](https://img.shields.io/github/license/maisans-maid/Mai?color=pink&label=License)](https://github.com/maisans-maid/Mai/blob/master/LICENSE)
9-
[![Dependencies Status](https://david-dm.org/maisans-maid/Mai/status.svg)](https://david-dm.org/maisans-maid/Mai)
10-
######   A multifunctional **Discord Bot**, written in **Discord.js V12**~
1+
<h1 align="center"> <img src='https://cdn.discordapp.com/emojis/757869043117064223.png?v=1' height='50'> Mai</h1>
2+
3+
<p align="center"> A Discord Bot Based Around Anime, and Mai </p>
4+
5+
<p align="center">
6+
<a href="http://forthebadge.com/">
7+
<img src="http://forthebadge.com/images/badges/built-with-love.svg"/>
8+
</a>
9+
</p>
10+
11+
<p align="center">
12+
<a href="https://standardjs.com/">
13+
<img src="https://cdn.rawgit.com/feross/standard/master/badge.svg" />
14+
</a>
15+
</p>
16+
17+
<p align="center">
18+
<a href="https://github.com/maisans-maid/Mai">
19+
<img src="https://img.shields.io/github/package-json/v/maisans-maid/mai/master?color=pink&label=Current%20Version" alt="App Version" />
20+
</a>
21+
<a href="https://nodejs.org/dist/latest-v14.x/">
22+
<img src="https://img.shields.io/static/v1?label=node&message=>=14.0.0&color=success&logo=Node.js&logoColor=white" alt="Node Requirements">
23+
</a>
24+
<a href="https://github.com/maisans-maid/Mai">
25+
<img src="https://img.shields.io/github/workflow/status/maisans-maid/mai/Node.js%20CI" alt="build">
26+
</a>
27+
<a href="https://github.com/maisans-maid/Mai/blob/master/LICENSE">
28+
<img src="https://img.shields.io/github/license/maisans-maid/Mai?color=pink&label=License" alt="LICENSE">
29+
</a>
30+
<a href="https://david-dm.org/maisans-maid/Mai">
31+
<img src="https://david-dm.org/maisans-maid/Mai/status.svg" alt="LICENSE">
32+
</a>
33+
<a href="https://support.mai-san.ml/">
34+
<img src="https://img.shields.io/discord/703922441768009731?color=%237289DA&label=Support&logo=discord&logoColor=white" alt="Online">
35+
</a>
36+
</p>
37+
<p align="center">
38+
39+
</p>
40+
1141
---
42+
1243
<br />
1344

1445
Check the docs on https://mai-san.ml/
1546

47+
### Host
48+
Create Env file:
49+
50+
*Refer to .env_example file for other usable environment variables*
51+
```
52+
DISCORD_TOKEN=
53+
```
54+
55+
Run the following command on your CLI
56+
```
57+
npm install
58+
59+
npm start
60+
```
61+
1662
### Why should you invite Mai?
1763
Mai is a simple yet powerful Discord Bot that aims to give discord users an enhanced "Discord Experience". Mai provides a variety of fun and informative commands that you can use with your friends.
1864

1965
Mai can:
2066
- Spice up chat environment with the use of roleplay/action commands such as pat, hug, slap, and more! </font> <br />
2167
- Search through the internet for information resources through various functions such as anime information lookup (series, characters, and even seiyuus!), games (via steam), or even time on some cities. </font> <br />
2268
- Ease the work of moderators by managing the server through various single commands. </font> <br />
23-
- Provide Airing Information automagically, implement user experience system, as well as server-based economy system. </font> <br />
69+
- Provide Airing Information automagically, implement user experience system, as well as economy system. </font> <br />
2470
- Acquire totally random fun facts from various sources Mai has access to. </font> <br />
2571

2672

@@ -31,34 +77,15 @@ You may invite Mai through https://invite.mai-san.ml.
3177
If you have questions regarding the bot and it's use, please do join our support server at https://support.mai-san.ml/.
3278

3379
### Contribute
34-
Contribution includes, but is not limited to making a Pull Request. For reference, I have been struggling on proper implementation of the economy command. I am expecting that most contributors will probably be coming from there.
80+
Contribution includes, but is not limited to making a Pull Request.
3581

3682
Pull Requests regarding totally new commands without foretelling the developer via creating issue will automatically be rejected.
3783

3884
If you love this work and wish to contribute in another manner, please do join our support server (which isn't much) and ping/mention **Sakurajimai#6742** there.
3985

40-
### Credits
41-
"Give Credit when it's Due" - is a phrase that i love so much. Therefore, i will be mentioning here the projects/people that helped Mai grow as a powerful Discord Bot.
42-
43-
- [Discord.js](https://github.com/discordjs/discord.js/) by [discordjs](https://github.com/discordjs/) - a powerful javascript library for interacting with the [Discord API](https://discord.com/developers/docs/intro).
44-
- [AniList](https://github.com/TehNut/AniSchedule) by [TehNut](https://github.com/TehNut) - an anime announcer made purely on javascript that became the basis for one of Mai's main feature in the present.
45-
- [Komugari](https://github.com/Mitorisia/Komugari) by [Mitorisia](https://github.com/Mitorisia) - a discord bot written in [Discord.js@Commando](https://github.com/discordjs/Commando) that has been the basis for most of Mai's current commands.
46-
- The kind people on Discord.js Official, Coding Den, Programmer's Hangout, and Discord API servers that helped me debug errors on my code whenever I fail to solve it myself.
47-
48-
Hey you! Yes You! If you've been using Mai as a reference, please give her due credit.
4986

5087
### License
5188
Mai is Licensed under MIT.
52-
>MIT License
53-
>
54-
>Copyright (c) 2020 Sakurajimai#6742
55-
>
56-
>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57-
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
58-
>
59-
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
60-
>
61-
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6289

6390

6491
### Disclaimer

commands/social/bal.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ module.exports = {
2525
new MessageEmbed().setDescription(
2626
`\u200B\n💰 **${
2727
text.commatize(doc.data.economy.wallet)
28-
}** coins in posession.\n\n${
28+
}** credits in posession.\n\n${
2929
doc.data.economy.bank !== null
30-
? `💰 **${text.commatize(doc.data.economy.bank)}** coins in bank!`
30+
? `💰 **${text.commatize(doc.data.economy.bank)}** credits in bank!`
3131
: `Seems like you don't have a bank yet. Create one now by typing \`${
3232
client.config.prefix
3333
}bank\``
34-
}`
34+
}\n\nDaily Streak: **${doc.data.economy.streak.current}** (All time best: **${doc.data.economy.streak.alltime}**)`
3535
).setAuthor(`${message.member.displayName}'s wallet`)
3636
.setColor('GREY')
3737
.setThumbnail(message.author.displayAvatarURL({dynamic: 'true'}))

commands/social/creditslb.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
const { MessageEmbed } = require('discord.js');
2+
const profile = require(`${process.cwd()}/models/Profile`);
3+
const text = require(`${process.cwd()}/util/string`);
4+
5+
module.exports = {
6+
name: 'creditslb',
7+
aliases: [ 'richlb', 'richleaderboard', 'creditsleaderboard' ],
8+
guildOnly: true,
9+
rankcommand: true,
10+
group: 'social',
11+
description: 'Shows the top credit earners for this server',
12+
requiresDatabase: true,
13+
clientPermissions: [ 'EMBED_LINKS' ],
14+
get examples(){ return [this.name, ...this.aliases ];},
15+
run: (client, message) => {
16+
17+
const { exceptions, isActive } = client.guildProfiles.get(message.guild.id).xp;
18+
const embed = new MessageEmbed()
19+
.setFooter(`XP Leaderboard | \©️${new Date().getFullYear()} Mai`)
20+
.setThumbnail('https://i.imgur.com/qkBQB8V.png')
21+
.setColor('RED');
22+
23+
if (!isActive){
24+
return message.channel.send(
25+
embed.setDescription([
26+
`**${message.member.displayName}**, XP is currently disabled in this server.\n`,
27+
`If you are the server Administrator, you may enable it by typing \`${client.config.prefix}xptoggle\`.`,
28+
`[Learn More](https://mai-san.ml/docs/features/XP_System) about Mai's XP System.`
29+
].join('\n'))
30+
.setAuthor('XP Systems Disabled','https://cdn.discordapp.com/emojis/767062250279927818.png?v=1')
31+
);
32+
};
33+
34+
if (exceptions.includes(message.channel.id)){
35+
return message.channel.send(
36+
embed.setDescription([
37+
`**${message.member.displayName}**, XP is currently disabled in this channel.\n`,
38+
`To see which channels are xp-disabled, use the command \`${client.config.prefix}nonxpchannels\``,
39+
`If you are the server Administrator, you may reenable it here by typing \`${client.config.prefix}xpenable #${message.channel.name}\``,
40+
`[Learn More](https://mai-san.ml/docs/features/XP_System) about Mai's XP System.`
41+
].join('\n'))
42+
.setAuthor('Channel Blacklisted','https://cdn.discordapp.com/emojis/767062250279927818.png?v=1')
43+
);
44+
};
45+
46+
return profile.find({ 'data.xp.id': message.guild.id }, async (err, docs) => {
47+
if (err) {
48+
return message.channel.send(
49+
embed.setAuthor('Database Error','https://cdn.discordapp.com/emojis/767062250279927818.png?v=1')
50+
.setDescription('Mai\'s Database Provider responded with an error: ' + err.name)
51+
);
52+
};
53+
54+
docs = docs.map(x => { return { id: x._id, wallet: x.data.economy.wallet, bank: x.data.economy.bank};})
55+
.sort((A,B) => ((B.wallet || 0) + (B.bank || 0)) - ((A.wallet || 0) + (A.bank || 0))) // Arrange by credits, descending.
56+
.filter(x => Boolean(x.wallet || 0 + x.bank || 0)); // Remove document where total credits is 0.
57+
58+
console.log(docs)
59+
60+
if (!docs.length){
61+
return message.channel.send(
62+
embed.setDescription([
63+
`**${message.member.displayName}**, No credit documents found.\n\n`,
64+
'Users in this server have not started earning credits yet!\n',
65+
'[Learn More](https://mai-san.ml/) about Mai\'s Economy System.'
66+
].join('\n'))
67+
.setAuthor('No Credits','https://cdn.discordapp.com/emojis/767062250279927818.png?v=1')
68+
);
69+
};
70+
71+
const members = await message.guild.members
72+
.fetch({ user: docs.slice(0,10).map(x => x.id) })
73+
.catch(() => null)
74+
75+
return message.channel.send(
76+
new MessageEmbed()
77+
.setColor('GREY')
78+
.setFooter(`Credits Leaderboard | \©️${new Date().getFullYear()} Mai`)
79+
.setAuthor(`🏆 ${message.guild.name} Credits Leaderboard`, message.guild.iconURL({format: 'png', dynamic: true }) || null)
80+
.addField(`**${members.get(docs[0].id)?.displayName || '<Unknown User>'}** ranked the highest with **${text.commatize(docs[0].wallet + docs[0].bank)} **Credits!`,
81+
[
82+
'```properties',
83+
'╭═══════╤════════╤═════════╤════════════════════════════╮',
84+
'┃ Rank ┃ Wallet ┃ Bank ┃ User ┃',
85+
'╞═══════╪════════╪═════════╪════════════════════════════╡',
86+
docs.slice(0,10).map((u,i) => {
87+
const rank = String(i+1);
88+
return [
89+
'┃' + ' '.repeat(6-rank.length) + rank,
90+
' '.repeat(6-text.compactNum(u.wallet).length) + text.compactNum(u.wallet),
91+
' '.repeat(7-text.compactNum(u.bank).length) + text.compactNum(u.bank),
92+
members.get(u.id)?.user.tag || '<Unknown User>'
93+
].join(' ┃ ')
94+
}).join('\n'),
95+
'╞═══════╪════════╪═════════╪════════════════════════════╡',
96+
docs.filter(x => x.id === message.author.id).map((u,i,a) => {
97+
const user = a.find(x => x.id === message.author.id);
98+
const rank = docs.findIndex(x => x.id === message.author.id) + 1;
99+
return [
100+
'┃' + ' '.repeat(6-text.ordinalize(rank).length) + text.ordinalize(rank),
101+
' '.repeat(6-text.compactNum(u.wallet).length) + text.compactNum(u.wallet),
102+
' '.repeat(7-text.compactNum(u.bank).length) + text.compactNum(u.bank),
103+
text.truncate('You (' + message.author.tag + ')', 26) + ' '.repeat(27-text.truncate('You (' + message.author.tag + ')', 26).length) + '┃'
104+
].join(' ┃ ')
105+
}).join(''),
106+
'╰═══════╧════════╧═════════╧════════════════════════════╯',
107+
'```'
108+
].join('\n'))
109+
);
110+
});
111+
}
112+
};

commands/social/leaderboard.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ module.exports = {
9898
'┃' + ' '.repeat(6-text.ordinalize(rank).length) + text.ordinalize(rank),
9999
' '.repeat(5-String(u.data.level).length) + u.data.level,
100100
' '.repeat(6-text.compactNum(u.data.xp).length) + text.compactNum(u.data.xp),
101-
text.truncate('You (' + message.author.tag + ')', 27) + ' '.repeat(27-text.truncate('You (' + message.author.tag + ')', 27).length) + '┃'
101+
text.truncate('You (' + message.author.tag + ')', 26) + ' '.repeat(27-text.truncate('You (' + message.author.tag + ')', 26).length) + '┃'
102102
].join(' ┃ ')
103103
}).join(''),
104104
'╰═══════╧═══════╧════════╧════════════════════════════╯',

commands/social/tip.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ module.exports = {
6666
.then(() => message.channel.send([
6767
`\\✔️ **${message.author.tag}**, tipped **${amount}** to **${member.user.tag}**.`,
6868
overflow ? `\n\\⚠️ **Overflow Warning**: **${member.user.tag}**'s wallet just overflowed! You need to transfer some of your credits to your bank!` : '',
69-
unregistered ? `\n\\⚠️ **Unregistered**: **${member.user,tag}** is unregistered, the bonus credits will not be added.` : ''
69+
unregistered ? `\n\\⚠️ **Unregistered**: **${member.user.tag}** is unregistered, the bonus credits will not be added.` : ''
7070
].join('')))
7171
.catch(() => message.channel.send(`\`❌ [DATABASE_ERR]:\` Unable to save the document to the database, please try again later!`))
7272
});

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "mai",
3-
"version": "4.0.3",
3+
"version": "4.0.4",
44
"description": "Discordbot written in discord.js",
55
"main": "index.js",
66
"scripts": {
7-
"test": "echo \"Error: no test specified\" && exit 1",
7+
"test": "node test.js",
88
"start": "node index.js"
99
},
1010
"engines": {

test.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// NOTE: ./struct not included on test
2+
3+
const options = {
4+
paths: [
5+
'action', 'anime', 'bot',
6+
'core', 'fun', 'moderation',
7+
'owner', 'setup', 'social','utility'
8+
]
9+
};
10+
11+
const { readdir } = require('fs');
12+
13+
// Test events
14+
for (const path of options.paths){
15+
readdir(`./commands/${path}`, (err, files) => {
16+
files.filter(file => file.split('.').pop === 'js').forEach(file => {
17+
require(`./commands/${path}/${file}`);
18+
});
19+
});
20+
};
21+
22+
// Test events
23+
readdir(`./events`, (err, files) => {
24+
files.filter(file => file.split('.').pop() === 'js').forEach(file => {
25+
require(`./events/${file}`);
26+
});
27+
});
28+
29+
// Test JSON assets
30+
readdir('./assets/json', (err, files) => {
31+
files.filter(file => file.split('.').pop() === 'json').forEach(file => {
32+
require(`./assets/json/${file}`);
33+
});
34+
});
35+
36+
// Test utils
37+
readdir('./util', (err, files) => {
38+
files.filter(file => file.split('.').pop() === 'js').forEach(file => {
39+
require(`./util/${file}`);
40+
});
41+
});
42+
43+
// Test ./utils/games
44+
readdir('./util/games', (err, files) => {
45+
files.filter(file => file.split('.').pop() === 'js').forEach(file => {
46+
require(`./util/games/${file}`);
47+
});
48+
});
49+
50+
// End of Test

0 commit comments

Comments
 (0)