Skip to content

Commit

Permalink
Most of VIP system and RCall
Browse files Browse the repository at this point in the history
  • Loading branch information
SunburntRock89 committed May 11, 2023
1 parent ef76232 commit 4a126bd
Show file tree
Hide file tree
Showing 23 changed files with 1,194 additions and 705 deletions.
1,231 changes: 572 additions & 659 deletions package-lock.json

Large diffs are not rendered by default.

34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,41 +33,41 @@
"delay": 100
},
"dependencies": {
"@prisma/client": "^4.8.0",
"@prisma/client": "^4.12.0",
"bufferutil": "^4.0.7",
"cli-progress": "^3.11.2",
"cli-progress": "^3.12.0",
"dayjs": "^1.11.7",
"discord-api-types": "^0.37.24",
"discord.js": "^14.7.1",
"discord-api-types": "^0.37.38",
"discord.js": "^14.9.0",
"erlpack": "github:discordapp/erlpack",
"i18next": "^21.10.0",
"node-schedule": "^2.1.0",
"node-schedule": "^2.1.1",
"re2": "^1.18.0",
"url-regex-safe": "^3.0.0",
"utf-8-validate": "^5.0.10",
"utf-8-validate": "^6.0.3",
"uuid": "^9.0.0",
"winston": "^3.8.2",
"winston-daily-rotate-file": "^4.7.1",
"zlib-sync": "^0.1.7",
"zlib-sync": "^0.1.8",
"zucc": "^0.1.2"
},
"devDependencies": {
"@mermaid-js/mermaid-cli": "^9.2.2",
"@mermaid-js/mermaid-cli": "^10.0.2",
"@tsconfig/node18": "^1.0.1",
"@types/cli-progress": "^3.11.0",
"@types/node": "^18.11.17",
"@types/node": "^18.15.11",
"@types/node-schedule": "^2.1.0",
"@types/uuid": "^9.0.0",
"@typescript-eslint/eslint-plugin": "^5.47.0",
"@typescript-eslint/parser": "^5.47.0",
"@types/uuid": "^9.0.1",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
"ansi-colors": "^4.1.3",
"cross-env": "^7.0.3",
"eslint": "^8.30.0",
"prisma": "^4.8.0",
"prisma-erd-generator": "^1.2.4",
"rethinkdb-ts": "^2.5.0",
"eslint": "^8.38.0",
"prisma": "^4.12.0",
"prisma-erd-generator": "^1.5.4",
"rethinkdb-ts": "^2.5.4",
"safe-regex": "^2.1.1",
"transformer": "^1.2.8",
"typescript": "^4.9.4"
"typescript": "^5.0.4"
}
}
87 changes: 87 additions & 0 deletions src/commands/maintainer/addvip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { EmbedBuilder, User } from "discord.js";
import { PermissionLevel } from "../../interfaces/commandData";
import Command from "../../internals/commandProcessor";

export default class AddCredit extends Command {
async run(): Promise<void> {
const userID = this.interaction.options.getString("user", true);

let user: User;
try {
user = await this.client.getUser(userID);
} catch {
this.targetUserNotFound();
return;
}

const perms = await this.client.getPerms(userID);

if (userID === this.client.user.id) {
this.interaction.reply({
ephemeral: true,
embeds: [this.client.errorEmbed("I am *the* VIP, don't forget that!")],
});
return;
} else if (user.bot) {
this.interaction.reply({
ephemeral: true,
embeds: [this.client.errorEmbed("Not sure, but I think it'll break stuff", { title: "Probably shouldn't do that." })],
});
return;
}

let account = await this.fetchAccount(userID);
const monthsToAdd = this.interaction.options.getInteger("months", true);

if (monthsToAdd < 0 && (account.vipMonthsRemaining + monthsToAdd) < 0) {
this.interaction.reply({
ephemeral: true,
embeds: [this.client.errorEmbed("That would make this user a negative VIP!", { title: "Are you insane?", footer: { text: "User does not have enough months to remove this many" } })],
});
return;
}

account = await this.db.accounts.update({
where: {
id: account.id,
},
data: {
vipMonthsRemaining: account.vipMonthsRemaining + monthsToAdd,
},
});

const monthsAdded = monthsToAdd > 0;
const addedOrRemoved = monthsAdded ? "Added" : "Removed";

const embed = EmbedBuilder.from({
color: this.config.colors.vip,
title: `${addedOrRemoved} VIP months!`,
description: `${addedOrRemoved} ${monthsToAdd} month${monthsToAdd == 1 ? "" : "s"} ${monthsAdded ? "to" : "from"} <@${userID}> (${userID})`,
footer: {
icon_url: this.interaction.user.displayAvatarURL(),
text: `${this.interaction.user.tag} (${this.interaction.user.id})`,
},
}).setTimestamp(new Date());

if (this.interaction.channelId != this.config.supportGuild.channels.management) {
this.client.sendCrossShard({
embeds: [embed],
}, this.config.supportGuild.channels.management);
}

this.interaction.reply({
embeds: [embed],
});

user.send({
embeds: [{
color: this.config.colors.vip,
title: monthsAdded ? "💸 You're a real VIP!" : "VIP Update",
description: `A support member has ${addedOrRemoved.toLowerCase()} ${Math.abs(monthsToAdd).toLocaleString()} VIP month${monthsToAdd == 1 ? "" : "s"} ${monthsAdded ? "to" : "from"} your account.\nYou now have ${account.vipMonthsRemaining} month${monthsToAdd == 1 ? "" : "s"} remaining.\nCall \`*411\` to spend your VIP months.`,
footer: {
text: "Thank you for supporting DTel!",
},
}],
}).catch(() => null);
}
}
4 changes: 2 additions & 2 deletions src/commands/standard/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ export default class Call extends Command {
}

// TODO: Remove fromNum and have this be standalone?
static async call(interaction: ChatInputCommandInteraction | MessageComponentInteraction, toNum: string, fromNum: Numbers): Promise<CallClient> {
static async call(interaction: ChatInputCommandInteraction | MessageComponentInteraction, toNum: string, fromNum: Numbers, alreadyReplied = false): Promise<CallClient> {
const t = getFixedT(interaction.locale, undefined, `commands.call`);
await interaction.deferReply();
if (!alreadyReplied) await interaction.deferReply();

const callObject = new CallClient(client, {
from: fromNum.number,
Expand Down
2 changes: 1 addition & 1 deletion src/commands/standard/pay common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default abstract class PayCommonFunctions extends Command {
const senderPerms = await this.client.getPerms(this.interaction.user.id);
const recipientPerms = await this.client.getPerms(user.id);

const transferRate = recipientPerms >= PermissionLevel.donator || senderPerms >= PermissionLevel.donator ? this.config.vipTransferRate : this.config.normalTransferRate;
const transferRate = recipientPerms as PermissionLevel >= PermissionLevel.donator || senderPerms as PermissionLevel >= PermissionLevel.donator ? this.config.vipTransferRate : this.config.normalTransferRate;

const totalReceived = transferRate * totalCost;
const fee = Math.round(totalCost - totalReceived);
Expand Down
88 changes: 88 additions & 0 deletions src/commands/standard/rcall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import Command from "../../internals/commandProcessor";
import config from "../../config/config";
import { APIEmbed } from "discord.js";
import { Numbers, Phonebook, Prisma } from "@prisma/client";
import CallCommand from "./call";

export default class RCall extends Command {
async run(): Promise<void> {
await this.interaction.deferReply();

let toCall: Numbers | null = null;

let cycle = 0;
// Presume the Phonebook always has at least 1 number
while (!toCall) {
cycle++;
if (cycle > 100) {
this.interaction.editReply("❌ Couldn't find a number to call.");
return;
}

const randomEntry = (await this.db.phonebook.aggregateRaw({
pipeline: [{
$match: {
number: {
$ne: this.number!.number,
}, // Don't get this channel's number
},
}, {
$sample: {
size: 1,
},
}],
}) as unknown as Prisma.JsonObject[])[0];


const number = await this.db.numbers.findUnique({
where: {
number: randomEntry._id as string,
},
include: {
incomingCalls: {
where: {
active: true,
},
},
outgoingCalls: {
where: {
active: true,
},
},
},
});

// If this number doesn't exist then delete it's Yellowbook entry and try again.
if (!number) {
await this.db.phonebook.delete({
where: {
number: randomEntry._id as string,
},
});
continue;
}

// Number is in a call, try again
if (number?.outgoingCalls.length > 0 || number.incomingCalls.length > 0) continue;

const channel = await this.client.getChannel(number.channelID);
if (!channel) {
await this.db.phonebook.delete({
where: {
number: number.number,
},
});
continue;
}

console.log(number.channelID);
if (number.expiry < new Date() || (this.number?.blocked && this.number.blocked.includes(number.number))) continue;

toCall = number;
}

this.interaction.editReply("☎️ Found a number! Dialling...");

CallCommand.call(this.interaction, toCall.number, this.number!, true);
}
}
2 changes: 1 addition & 1 deletion src/commands/standard/strikes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default class Strikes extends Command {
async run() {
const offender = this.interaction.options.getString("offender", false) || this.interaction.user.id;

if (offender != this.interaction.user.id && await this.client.getPerms(this.interaction.user.id) < PermissionLevel.customerSupport) {
if (offender != this.interaction.user.id && await this.client.getPerms(this.interaction.user.id) as number < PermissionLevel.customerSupport) {
this.interaction.reply({
embeds: [this.client.errorEmbed("You don't have permission to check the strikes of others!")],
});
Expand Down
2 changes: 1 addition & 1 deletion src/commands/support/addcredit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default class AddCredit extends Command {
embeds: [this.client.errorEmbed("Are you sure you want to give them more money?", { title: "AI will destroy humans!!!" })],
});
return;
} else if (perms >= PermissionLevel.customerSupport && perms != PermissionLevel.maintainer) {
} else if (perms as number >= PermissionLevel.customerSupport && perms != PermissionLevel.maintainer) {
this.interaction.reply({
ephemeral: true,
embeds: [this.client.errorEmbed("That's not something you should be trying on the job!", { title: "Seriously?" })],
Expand Down
2 changes: 1 addition & 1 deletion src/commands/support/blacklist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class Blacklist extends Command {
return;
}

if (await this.client.getPerms(possibilities.user.id) >= PermissionLevel.customerSupport) {
if (await this.client.getPerms(possibilities.user.id) as number >= PermissionLevel.customerSupport) {
this.interaction.reply({
embeds: [this.client.errorEmbed("You can't get rid of someone that easily...", { title: "❌ Unfair competition" })],
ephemeral: true,
Expand Down
2 changes: 1 addition & 1 deletion src/commands/support/strike add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default class StrikeAdd extends Command {
return;
}

if (await this.client.getPerms(possibilities.user.id) >= PermissionLevel.customerSupport) {
if (await this.client.getPerms(possibilities.user.id) as number >= PermissionLevel.customerSupport) {
this.interaction.reply({
embeds: [this.client.errorEmbed("You can't get rid of someone that easily...", { title: "❌ Unfair competition" })],
});
Expand Down
29 changes: 29 additions & 0 deletions src/config/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,17 @@ const commands: Command[] = [
permissionLevel: PermissionLevel.none,
useType: CommandType.standard,
},
{
name: "rcall",
description: `Call a random number in the Yellowbook`,
guildOnly: false,
numberRequired: true,
accountRequired: true,
notExecutableInCall: true,

permissionLevel: PermissionLevel.none,
useType: CommandType.standard,
},
{
name: "hangup",
description: `End the call in your channel`,
Expand Down Expand Up @@ -406,6 +417,24 @@ const commands: Command[] = [
permissionLevel: PermissionLevel.maintainer,
useType: CommandType.maintainer,
},
{
name: "addvip",
description: "Give VIP months to a user following their donation. [Maintainer Only]",
permissionLevel: PermissionLevel.maintainer,
useType: CommandType.maintainer,

options: [{
name: "user",
description: "The ID of the user you want to add months to",
required: true,
type: ApplicationCommandOptionType.String,
}, {
name: "months",
description: "The number of months you wish to add (use negative number to remove)",
required: true,
type: ApplicationCommandOptionType.Integer,
}],
},
];

export default commands;
2 changes: 1 addition & 1 deletion src/events/interactionCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export default async(client: DTelClient, _interaction: Interaction): Promise<voi
break;
}
case PermissionLevel.customerSupport: {
if (userPermissions < PermissionLevel.customerSupport) {
if (userPermissions as number < PermissionLevel.customerSupport) {
processorClass.permCheckFail();
return;
}
Expand Down
3 changes: 2 additions & 1 deletion src/interactions/call/233-renew.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export default class TwoThreeThreeRenewModal extends MessageComponentProcessor<S
},
});

const newExpiry = dayjs(this.number!.expiry).add(amount, monthYear === "y" ? "year" : "month");
let newExpiry = dayjs(this.number!.expiry).add(amount, monthYear === "y" ? "year" : "month");
if (this.number!.expiry < new Date()) newExpiry = dayjs().add(amount, monthYear === "y" ? "year" : "month");

await this.db.numbers.update({
where: {
Expand Down
9 changes: 9 additions & 0 deletions src/interactions/call/411-manage-delete-cancel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import ComponentProcessor from "../../internals/componentProcessor";

export default class Call411EditDeleteConfirm extends ComponentProcessor<ButtonInteraction> {
async run(): Promise<void> {
if (this.interaction.message.interaction?.user.id != this.interaction.user.id) {
this.interaction.reply({
ephemeral: true,
content: "❌ You can't use this menu as you didn't open it.",
});

return;
}

const embed = new EmbedBuilder()
.setColor(this.config.colors.error)
.setTitle("❌ Cancelled!");
Expand Down
9 changes: 9 additions & 0 deletions src/interactions/call/411-manage-delete-confirm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import ComponentProcessor from "../../internals/componentProcessor";

export default class Call411EditDeleteConfirm extends ComponentProcessor<ButtonInteraction> {
async run(): Promise<void> {
if (this.interaction.message.interaction?.user.id != this.interaction.user.id) {
this.interaction.reply({
ephemeral: true,
content: "❌ You can't use this menu as you didn't open it.",
});

return;
}

this.interaction.deferUpdate();

await this.db.phonebook.delete({
Expand Down
Loading

0 comments on commit 4a126bd

Please sign in to comment.