management

This commit is contained in:
koneko 2025-04-29 00:41:55 +02:00
parent 766923bbe1
commit fef546b23f
9 changed files with 473 additions and 0 deletions

View File

@ -0,0 +1,35 @@
name: Deploy bot
on:
push:
branches:
- main
jobs:
build-and-deploy:
env:
TOKEN: ${{ secrets.TOKEN }}
GUILDID: ${{ secrets.GUILDID }}
CLIENTID: ${{ secrets.CLIENTID }}
steps:
- name: Checkout code
uses: actions/checkout@v3
# use this as template if you need to build
#- name: Build project
# run: |
# echo "Running build..."
# ./build.sh
- name: Store artifact
run: |
echo "Storing artifact..."
mkdir -p /opt/artifacts/koneko-static-site
cp -r . /opt/artifacts/koneko-static-site/
- name: Deploy with Docker Compose
run: |
echo "Deploying with docker-compose..."
cd /opt/artifacts/koneko-static-site
docker compose down
docker compose up -d --build

26
Dockerfile Normal file
View File

@ -0,0 +1,26 @@
# syntax=docker/dockerfile:1
# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Dockerfile reference guide at
# https://docs.docker.com/go/dockerfile-reference/
# Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7
ARG NODE_VERSION=18.0.0
FROM node:${NODE_VERSION}-alpine
WORKDIR /usr/src/app
COPY package.json .
# Download dependencies.
RUN npm install
# Run the application as a non-root user.
USER node
# Copy the rest of the source files into the image.
COPY . .
# Run the application.
CMD node index.js

43
commands/howlucky.js Normal file
View File

@ -0,0 +1,43 @@
const { SlashCommandBuilder, SlashCommandNumberOption } = require("discord.js");
let tries = (module.exports = {
data: new SlashCommandBuilder()
.setName("howlucky")
.setDescription("How lucky are you?")
.addNumberOption(
new SlashCommandNumberOption()
.setName("tries")
.setDescription("how many tries you have")
.setRequired(true)
.setMinValue(1)
)
.addStringOption((option) =>
option
.setName("probability")
.setDescription("you can guess")
.setRequired(true)
),
async execute(interaction) {
let probabilitylowernum;
if (interaction.options.getString("probability").split("/")[1] == null) {
probabilitylowernum = parseInt(
interaction.options.getString("probability")
);
} else {
probabilitylowernum = parseInt(
interaction.options.getString("probability").split("/")[1]
);
}
let result =
(interaction.options.getNumber("tries") / probabilitylowernum) * 100;
await interaction.reply(
`With a drop chance of ${interaction.options.getString(
"probability"
)}, getting a drop within ${interaction.options.getNumber(
"tries"
)} tries has a **${
Math.round(result * 100) / 100
}%** chance of happening.`
);
},
});

65
commands/howmanyruns.js Normal file
View File

@ -0,0 +1,65 @@
const { SlashCommandBuilder, SlashCommandNumberOption } = require("discord.js");
function calculate(desiredPercent, probability, itemsPerRun, minutesPerRun) {
let result = [];
//const numberOfRuns = Math.round(
// Math.log(1 - desiredPercent) / Math.log(1 - probability)
//);
const numberOfItems = Math.log(1 - desiredPercent) / Math.log(1 - probability);
const numberOfRuns = numberOfItems / itemsPerRun;
const hoursToGetPercent = (numberOfRuns * minutesPerRun) / 60;
result.push(`${Math.round(desiredPercent * 100)}%`.padEnd(7, " ")); // prob
result.push(`${Math.ceil(numberOfItems)}`.padEnd(7, " ")); // items
result.push(`${Math.ceil(numberOfRuns)}`.padEnd(7, " ")); // runs
result.push(`${Math.round(hoursToGetPercent)}`.padEnd(7, " ")); // hours
return result.join("\t") + "\n";
}
let tries = (module.exports = {
data: new SlashCommandBuilder()
.setName("howmanyruns")
.setDescription("How lucky are you?")
.addStringOption((option) =>
option
.setName("probability")
.setDescription("you can guess")
.setRequired(true)
)
.addNumberOption(
new SlashCommandNumberOption()
.setName("items-per-run")
.setDescription("how many items every run")
.setRequired(true)
.setMinValue(1)
)
.addNumberOption((option) =>
option
.setName("minutes-per-run")
.setDescription("how long each run takes")
.setRequired(true)
.setMinValue(1)
),
async execute(interaction) {
let strprobability;
if (interaction.options.getString("probability").split("/")[1] == null) {
strprobability = parseInt(interaction.options.getString("probability"));
} else {
strprobability = parseInt(
interaction.options.getString("probability").split("/")[1]
);
}
const items = interaction.options.getNumber("items-per-run");
const probability = 1 / strprobability;
const minutes = interaction.options.getNumber("minutes-per-run");
let result = "";
result += calculate(0.1, probability, items, minutes);
result += calculate(0.25, probability, items, minutes);
result += calculate(0.5, probability, items, minutes);
result += calculate(0.75, probability, items, minutes);
result += calculate(0.9, probability, items, minutes);
result += calculate(0.95, probability, items, minutes);
await interaction.reply(
`Assuming you get ${items} item(s) per run.\nYou spend ${minutes} minute(s) per run and probability is 1/${strprobability}.\n\`\`\`${"Prob".padEnd(7, " ")}\t${"Items".padEnd(7, " ")}\t${"Runs".padEnd(7, " ")}\tHours\n${result}\`\`\``
);
},
});

49
deploy.js Normal file
View File

@ -0,0 +1,49 @@
// const { REST, Routes } = require("discord.js");
// const { clientId, guildId, token } = require("./config.json");
// // const clientId
// const fs = require("node:fs");
// const path = require("node:path");
// const commands = [];
// const commandsPath = path.join(__dirname, "commands");
// fs.readdirSync(commandsPath).forEach((file) => {
// if (file.endsWith(".js")) {
// const filePath = path.join(commandsPath, file);
// const command = require(filePath);
// if ("data" in command && "execute" in command) {
// console.log(command.data);
// commands.push(command.data.toJSON());
// } else {
// console.log(
// `[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`
// );
// }
// }
// });
// // Construct and prepare an instance of the REST module
// const rest = new REST().setToken(token);
// // and deploy your commands!
// (async () => {
// try {
// console.log(
// `Started refreshing ${commands.length} application (/) commands.`
// );
// // The put method is used to fully refresh all commands in the guild with the current set
// const data = await rest.put(
// Routes.applicationGuildCommands(clientId, guildId),
// {
// body: commands,
// }
// );
// console.log(
// `Successfully reloaded ${data.length} application (/) commands.`
// );
// } catch (error) {
// // And of course, make sure you catch and log any errors!
// console.error(error);
// }
// })();

11
docker-compose.yml Normal file
View File

@ -0,0 +1,11 @@
services:
shiroprob:
container_name: shiroprob-discord-bot
restart: unless-stopped
build:
context: .
dockerfile: Dockerfile
environment:
- TOKEN=${TOKEN}
- GUILDID=${GUILDID}
- CLIENTID=${CLIENTID}

57
index.js Normal file
View File

@ -0,0 +1,57 @@
const fs = require("node:fs");
const path = require("node:path");
const { Client, Collection, Events, GatewayIntentBits } = require("discord.js");
const token = process.env.TOKEN;
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.commands = new Collection();
const commandsPath = path.join(__dirname, "commands");
fs.readdirSync(commandsPath).forEach((file) => {
if (file.endsWith(".js")) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
if ("data" in command && "execute" in command) {
client.commands.set(command.data.name, command);
} else {
console.log(
`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`
);
}
}
});
client.once(Events.ClientReady, (readyClient) => {
console.log(`Ready! Logged in as ${readyClient.user.tag}`);
});
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(
`No command matching ${interaction.commandName} was found.`
);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
if (interaction.replied || interaction.deferred) {
await interaction.followUp({
content:
"There was an error while executing this command! contact shiro or something",
ephemeral: true,
});
} else {
await interaction.reply({
content:
"There was an error while executing this command! contact shiro or something",
ephemeral: true,
});
}
}
});
client.login(token);

9
package.json Normal file
View File

@ -0,0 +1,9 @@
{
"name": "shiroprobability",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"discord.js": "^14.15.3"
}
}

178
yarn.lock Normal file
View File

@ -0,0 +1,178 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@discordjs/builders@^1.8.2":
version "1.8.2"
resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-1.8.2.tgz#535d970331ee40f20dec9ef8079e43092f323ce9"
integrity sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g==
dependencies:
"@discordjs/formatters" "^0.4.0"
"@discordjs/util" "^1.1.0"
"@sapphire/shapeshift" "^3.9.7"
discord-api-types "0.37.83"
fast-deep-equal "^3.1.3"
ts-mixer "^6.0.4"
tslib "^2.6.2"
"@discordjs/collection@1.5.3":
version "1.5.3"
resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-1.5.3.tgz#5a1250159ebfff9efa4f963cfa7e97f1b291be18"
integrity sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==
"@discordjs/collection@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-2.1.0.tgz#f327d944ab2dcf9a1f674470a481f78a120a5e3b"
integrity sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==
"@discordjs/formatters@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@discordjs/formatters/-/formatters-0.4.0.tgz#066a2c2163b26ac066e6f621f17445be9690c6a9"
integrity sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==
dependencies:
discord-api-types "0.37.83"
"@discordjs/rest@^2.3.0":
version "2.3.0"
resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-2.3.0.tgz#06d37c7fb54a9be61134b5bbb201abd760343472"
integrity sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==
dependencies:
"@discordjs/collection" "^2.1.0"
"@discordjs/util" "^1.1.0"
"@sapphire/async-queue" "^1.5.2"
"@sapphire/snowflake" "^3.5.3"
"@vladfrangu/async_event_emitter" "^2.2.4"
discord-api-types "0.37.83"
magic-bytes.js "^1.10.0"
tslib "^2.6.2"
undici "6.13.0"
"@discordjs/util@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@discordjs/util/-/util-1.1.0.tgz#dcffd2b61aab8eadd66bea67811bc34fc769bb2a"
integrity sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==
"@discordjs/ws@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@discordjs/ws/-/ws-1.1.1.tgz#bffbfd46838258ab09054ed98ddef1a36f6507a3"
integrity sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==
dependencies:
"@discordjs/collection" "^2.1.0"
"@discordjs/rest" "^2.3.0"
"@discordjs/util" "^1.1.0"
"@sapphire/async-queue" "^1.5.2"
"@types/ws" "^8.5.10"
"@vladfrangu/async_event_emitter" "^2.2.4"
discord-api-types "0.37.83"
tslib "^2.6.2"
ws "^8.16.0"
"@sapphire/async-queue@^1.5.2":
version "1.5.3"
resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.5.3.tgz#03cd2a2f3665068f314736bdc56eee2025352422"
integrity sha512-x7zadcfJGxFka1Q3f8gCts1F0xMwCKbZweM85xECGI0hBTeIZJGGCrHgLggihBoprlQ/hBmDR5LKfIPqnmHM3w==
"@sapphire/shapeshift@^3.9.7":
version "3.9.7"
resolved "https://registry.yarnpkg.com/@sapphire/shapeshift/-/shapeshift-3.9.7.tgz#43e23243cac8a0c046bf1e73baf3dbf407d33a0c"
integrity sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==
dependencies:
fast-deep-equal "^3.1.3"
lodash "^4.17.21"
"@sapphire/snowflake@3.5.3", "@sapphire/snowflake@^3.5.3":
version "3.5.3"
resolved "https://registry.yarnpkg.com/@sapphire/snowflake/-/snowflake-3.5.3.tgz#0c102aa2ec5b34f806e9bc8625fc6a5e1d0a0c6a"
integrity sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==
"@types/node@*":
version "22.3.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.3.0.tgz#7f8da0e2b72c27c4f9bd3cb5ef805209d04d4f9e"
integrity sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g==
dependencies:
undici-types "~6.18.2"
"@types/ws@^8.5.10":
version "8.5.12"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e"
integrity sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==
dependencies:
"@types/node" "*"
"@vladfrangu/async_event_emitter@^2.2.4":
version "2.4.5"
resolved "https://registry.yarnpkg.com/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.5.tgz#7bc35026fdc3398a5e1aac801edd21b28cdf4cfa"
integrity sha512-J7T3gUr3Wz0l7Ni1f9upgBZ7+J22/Q1B7dl0X6fG+fTsD+H+31DIosMHj4Um1dWQwqbcQ3oQf+YS2foYkDc9cQ==
discord-api-types@0.37.83:
version "0.37.83"
resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.37.83.tgz#a22a799729ceded8176ea747157837ddf4708b1f"
integrity sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==
discord.js@^14.15.3:
version "14.15.3"
resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.15.3.tgz#b2a67a1a4ef192be498fb8b6784224a42906f1be"
integrity sha512-/UJDQO10VuU6wQPglA4kz2bw2ngeeSbogiIPx/TsnctfzV/tNf+q+i1HlgtX1OGpeOBpJH9erZQNO5oRM2uAtQ==
dependencies:
"@discordjs/builders" "^1.8.2"
"@discordjs/collection" "1.5.3"
"@discordjs/formatters" "^0.4.0"
"@discordjs/rest" "^2.3.0"
"@discordjs/util" "^1.1.0"
"@discordjs/ws" "^1.1.1"
"@sapphire/snowflake" "3.5.3"
discord-api-types "0.37.83"
fast-deep-equal "3.1.3"
lodash.snakecase "4.1.1"
tslib "2.6.2"
undici "6.13.0"
fast-deep-equal@3.1.3, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
lodash.snakecase@4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
magic-bytes.js@^1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz#c41cf4bc2f802992b05e64962411c9dd44fdef92"
integrity sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==
ts-mixer@^6.0.4:
version "6.0.4"
resolved "https://registry.yarnpkg.com/ts-mixer/-/ts-mixer-6.0.4.tgz#1da39ceabc09d947a82140d9f09db0f84919ca28"
integrity sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==
tslib@2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
tslib@^2.6.2:
version "2.6.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
undici-types@~6.18.2:
version "6.18.2"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.18.2.tgz#8b678cf939d4fc9ec56be3c68ed69c619dee28b0"
integrity sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ==
undici@6.13.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/undici/-/undici-6.13.0.tgz#7edbf4b7f3aac5f8a681d515151bf55cb3589d72"
integrity sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==
ws@^8.16.0:
version "8.18.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==