Skip to content

Commit

Permalink
Merge pull request #38 from Chiissu/dev
Browse files Browse the repository at this point in the history
0.2.0
  • Loading branch information
MrSerge01 authored Dec 21, 2024
2 parents 5140246 + 2b5d5ef commit 90e5d10
Show file tree
Hide file tree
Showing 50 changed files with 715 additions and 452 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules/
.env
.DS_Store
data.db
data.db
bun.lockb
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
- Run `bun run setup` and our cli tool will install dependencies and write .env for you

### Running
- Run `bun start`.
- Run `bun dev`.

Be sure to open a pull request when you're ready to push your changes. Be descriptive of the changes you've made.

Expand Down
Binary file modified bun.lockb
Binary file not shown.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"The Sokora team",
"The GitHub contributors"
],
"version": "0.1.0",
"version": "0.2.0",
"main": "./src/index.ts",
"type": "module",
"scripts": {
Expand All @@ -21,7 +21,7 @@
},
"devDependencies": {
"@types/ms": "^0.7.34",
"bun-types": "^1.1.34",
"typescript": "^5.6.3"
"bun-types": "^1.1.41",
"typescript": "^5.7.2"
}
}
14 changes: 9 additions & 5 deletions src/bot.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ActivityType, Client } from "discord.js";
import { Commands } from "./handlers/commands";
import { Events } from "./handlers/events";
import { registerCommands } from "./handlers/commands";
import { loadEvents } from "./handlers/events";
import { leavePlease } from "./utils/leavePlease";
import { rescheduleUnbans } from "./utils/unbanScheduler";

const client = new Client({
Expand All @@ -12,15 +13,18 @@ const client = new Client({
"GuildMembers",
"GuildMessages",
"GuildEmojisAndStickers",
"GuildPresences",
"GuildBans",
"MessageContent"
]
});

client.on("ready", async () => {
await new Events(client).loadEvents();
await new Commands(client).registerCommands();
const guilds = client.guilds.cache;
for (const id of guilds.keys())
await leavePlease(guilds.get(id)!, await guilds.get(id)?.fetchOwner()!, "Not like that.");

await loadEvents(client);
await registerCommands(client);
console.log("ちーっす!");
rescheduleUnbans(client);
});
Expand Down
35 changes: 15 additions & 20 deletions src/commands/About.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import {
SlashCommandBuilder,
type ChatInputCommandInteraction
} from "discord.js";
import { version } from "../../package.json";
import { genColor } from "../utils/colorGen";
import { imageColor } from "../utils/imageColor";
import { randomise } from "../utils/randomise";
import { pluralOrNot } from "../utils/pluralOrNot";
import { replace } from "../utils/replace";

export default class About {
data: SlashCommandBuilder;
Expand All @@ -25,8 +27,6 @@ export default class About {
const members = guilds.map(guild => guild.memberCount).reduce((a, b) => a + b);
const shards = client.shard?.count;
const avatar = user.displayAvatarURL();
let emojis = ["💖", "💝", "💓", "💗", "💘", "💟", "💕", "💞"];
if (Math.round(Math.random() * 100) <= 5) emojis = ["⌨️", "💻", "🖥️"];

const embed = new EmbedBuilder()
.setAuthor({ name: "• About Sokora", iconURL: avatar })
Expand All @@ -37,35 +37,30 @@ export default class About {
{
name: "📃 • General",
value: [
"Version **0.1.1**, *Kaishi*",
`**${members}** members • **${guilds.size}** guild${guilds.size == 1 ? "" : "s"} ${
!shards ? "" : `• **${shards}** shard${shards == 1 ? "" : "s"}`
`Version **${version}**, *Kaishi*`,
`**${members}** ${pluralOrNot("member", members)} • **${guilds.size}** ${pluralOrNot("guild", guilds.size)} ${
!shards ? "" : `• **${shards}** ${pluralOrNot("shard", shards)}`
}`
].join("\n")
},
{
name: "🌌Entities involved",
name: "🔗Links",
value: [
"**Founder**: Goos",
"**Developers**: Dimkauzh, Froxcey, Golem64, Koslz, MQuery, Nikkerudon, Spectrum, ThatBOI",
"**Designers**: ArtyH, ZakaHaceCosas, Pjanda",
"**Translator Lead**: ThatBOI",
"**Translators**: Dimkauzh, flojo, Golem64, GraczNet, Nikkerudon, ZakaHaceCosas, SaFire, TrulyBlue",
"**Testers**: Blaze, fishy, Trynera",
"And **YOU**, for using Sokora."
"[Discord](https://discord.gg/c6C25P4BuY) • [GitHub](https://www.github.com/SokoraDesu) • [YouTube](https://www.youtube.com/@SokoraDesu) • [Instagram](https://instagram.com/NebulaTheBot) • [Mastodon](https://mastodon.online/@[email protected]) • [Matrix](https://matrix.to/#/#sokora:matrix.org) • [Revolt](https://rvlt.gg/28TS9aXy)",
"Also, please read the [ToS](https://sokora.org/terms) and the [privacy policy](https://sokora.org/privacy)."
].join("\n")
},
{
name: "🔗 • Links",
value:
"[GitHub](https://www.github.com/SokoraDesu) • [YouTube](https://www.youtube.com/@SokoraDesu) • [Instagram](https://instagram.com/NebulaTheBot) • [Mastodon](https://mastodon.online/@[email protected]) • [Revolt](https://rvlt.gg/28TS9aXy)"
}
)
.setFooter({ text: `Made with ${randomise(emojis)} by the Sokora team` })
.setFooter({ text: replace("(madeWith)") })
.setThumbnail(avatar)
.setColor(user.hexAccentColor ?? (await imageColor(undefined, avatar)) ?? genColor(270));

const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setLabel("• Vote")
.setURL("https://top.gg/bot/873918300726394960/vote")
.setEmoji("🗳️")
.setStyle(ButtonStyle.Link),
new ButtonBuilder()
.setLabel("• Donate")
.setURL("https://paypal.me/SokoraTheBot")
Expand Down
65 changes: 65 additions & 0 deletions src/commands/Changelog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { EmbedBuilder, SlashCommandBuilder, type ChatInputCommandInteraction } from "discord.js";
import { version } from "../../package.json";
import { genColor } from "../utils/colorGen";
import { imageColor } from "../utils/imageColor";
import { replace } from "../utils/replace";

export default class Changelog {
data: SlashCommandBuilder;
constructor() {
this.data = new SlashCommandBuilder()
.setName("changelog")
.setDescription("Shows the changelog of Sokora's most recent update.");
}

async run(interaction: ChatInputCommandInteraction) {
const user = interaction.client.user;
const avatar = user.displayAvatarURL();
const text = [
["## Added", "### Commands", "- /changelog", "- /credits", "- /moderation notes"].join("\n"),
[
"## Changed",
"- The bot will remove levels when an admin changed the leveling difficulty",
"- /leaderboard shows 6 users per page instead of 5",
"- When you add the bot, it sends a message in the system channel",
"- Remade the message logs",
" - Edit logs will let you jump to the message that got edited"
].join("\n"),
[
"### /settings",
"- Autocompletes with channels/users/roles (you don't have to copy IDs now :tada:)",
"- In the embed it will show links to channels/users/roles instead of showing IDs"
].join("\n"),
[
"### /about",
"- Vote button added",
"- Removed credits and put them in a different command to reduce the height of the embed"
].join("\n"),
[
"## Fixed",
"### News",
"- Major issue related to the database, where the guild wasn't provided to ensure that news would be unique to every server, **thank you @Golem642!!!!**",
"- /news edit's modal errored when sending"
].join("\n"),
[
"### Moderation commands",
"- /moderation clear removed one more message than the user provided",
'- /moderation unban errored internally (it should send an error embed) when the user didn\'t have the "Ban Members" permission'
].join("\n"),
[
"## Typos",
'- "warn" mentions in /moderation warn are now "warning" to be more consistent',
"- Removed old markdown remnants from /moderation slowdown"
].join("\n")
].join("\n");

const embed = new EmbedBuilder()
.setAuthor({ name: `• Changelog for ${version}`, iconURL: avatar })
.setDescription(text)
.setFooter({ text: replace("(madeWith)") })
.setThumbnail(avatar)
.setColor(user.hexAccentColor ?? (await imageColor(undefined, avatar)) ?? genColor(270));

await interaction.reply({ embeds: [embed] });
}
}
35 changes: 35 additions & 0 deletions src/commands/Credits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { EmbedBuilder, SlashCommandBuilder, type ChatInputCommandInteraction } from "discord.js";
import { genColor } from "../utils/colorGen";
import { imageColor } from "../utils/imageColor";
import { replace } from "../utils/replace";

export default class Credits {
data: SlashCommandBuilder;
constructor() {
this.data = new SlashCommandBuilder()
.setName("credits")
.setDescription("Shows everyone who worked on Sokora.");
}

async run(interaction: ChatInputCommandInteraction) {
const user = interaction.client.user;
const avatar = user.displayAvatarURL();
const embed = new EmbedBuilder()
.setAuthor({ name: "• Entities involved", iconURL: avatar })
.setDescription(
[
"**Founder**: Goos",
"**Developers**: Dimkauzh, Froxcey, Golem64, Koslz, Littie, MQuery, Nikkerudon, Spectrum, ThatBOI",
"**Designers**: ArtyH, ZakaHaceCosas, Pjanda",
"**Translator Lead**: ThatBOI",
"**Translators**: Dimkauzh, flojo, Golem64, GraczNet, Nikkerudon, ZakaHaceCosas, SaFire, TrulyBlue",
"**Testers**: Blaze, fishy, Trynera"
].join("\n")
)
.setFooter({ text: replace("(madeWith)") })
.setThumbnail(avatar)
.setColor(user.hexAccentColor ?? (await imageColor(undefined, avatar)) ?? genColor(270));

await interaction.reply({ embeds: [embed] });
}
}
6 changes: 3 additions & 3 deletions src/commands/Leaderboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ export default class Leaderboard {
else return b.xp - a.xp;
});

const totalPages = Math.ceil(leaderboardData.length / 5);
const totalPages = Math.ceil(leaderboardData.length / 6);
let page = interaction.options.getNumber("page") || 1;
page = Math.max(1, Math.min(page, totalPages));
const generateEmbed = async () => {
const start = (page - 1) * 5;
const end = start + 5;
const start = (page - 1) * 6;
const end = start + 6;
const pageData = leaderboardData.slice(start, end);

const embed = new EmbedBuilder()
Expand Down
71 changes: 59 additions & 12 deletions src/commands/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default class Settings {
.setDescription(settingsDefinition[key].description);

Object.keys(settingsDefinition[key].settings).forEach(sub => {
switch (settingsDefinition[key].settings[sub]["type"] as string) {
switch (settingsDefinition[key].settings[sub].type as string) {
case "BOOL":
subcommand.addBooleanOption(option =>
option
Expand All @@ -47,6 +47,14 @@ export default class Settings {
.setRequired(false)
);
break;
case "CHANNEL":
subcommand.addChannelOption(option =>
option
.setName(sub)
.setDescription(settingsDefinition[key].settings[sub]["desc"])
.setRequired(false)
);
break;
case "USER":
subcommand.addUserOption(option =>
option
Expand All @@ -55,6 +63,14 @@ export default class Settings {
.setRequired(false)
);
break;
case "ROLE":
subcommand.addRoleOption(option =>
option
.setName(sub)
.setDescription(settingsDefinition[key].settings[sub]["desc"])
.setRequired(false)
);
break;
default: // Also includes "TEXT"
subcommand.addStringOption(option =>
option
Expand All @@ -71,11 +87,7 @@ export default class Settings {

async run(interaction: ChatInputCommandInteraction) {
const guild = interaction.guild!;
if (
!guild.members.cache
?.get(interaction.user.id)
?.permissions.has(PermissionsBitField.Flags.Administrator)
)
if (!guild.members.cache?.get(interaction.user.id)?.permissions.has("Administrator"))
return await errorEmbed(
interaction,
"You can't execute this command.",
Expand All @@ -84,11 +96,31 @@ export default class Settings {

const key = interaction.options.getSubcommand() as keyof typeof settingsDefinition;
const values = interaction.options.data[0].options!;
const settingsDef = settingsDefinition[key];
const settingText = (name: string) => {
const setting = getSetting(guild.id, key, name)?.toString();
let text;
switch (settingsDef.settings[name].type) {
case "CHANNEL":
text = setting ? `<#${setting}>` : "Not set";
break;
case "USER":
text = setting ? `<@${setting}>` : "Not set";
break;
case "ROLE":
text = setting ? `<@&${setting}>` : "Not set";
break;
default:
text = setting || "Not set";
break;
}
return text;
};

if (!values.length) {
const settingsDef = settingsDefinition[key];
const field: string[] = [];
Object.keys(settingsDef.settings).forEach(name =>
field.push(`**${name}**: ${getSetting(guild.id, key, name)?.toString() || "Not set"}`)
field.push(`**${name}**: ${settingText(name)}`)
);

const embed = new EmbedBuilder()
Expand All @@ -101,16 +133,31 @@ export default class Settings {
}

const embed = new EmbedBuilder()
.setAuthor({ name: "Parameters changed" })
.setAuthor({ name: "Parameters changed." })
.setColor(genColor(100));

values.forEach(option => {
for (let i = 0; i < values.length; i++) {
const option = values[i];

if (
option.type == 7 &&
!guild.channels.cache
.get(option.value as string)
?.permissionsFor(interaction.client.user)
?.has("ViewChannel")
)
return await errorEmbed(
interaction,
"Can't view this channel.",
"You can either give the **View Channel** permission for Sokora or use a channel from the dropdown menu."
);

setSetting(guild.id, key, option.name, option.value as string);
embed.addFields({
name: option.name,
value: option.value?.toString() || "Not set"
value: settingText(option.name.toString()!)
});
});
}

await interaction.reply({ embeds: [embed] });
}
Expand Down
Loading

0 comments on commit 90e5d10

Please sign in to comment.