-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathCtrlPanelAPI.ts
118 lines (95 loc) · 3 KB
/
CtrlPanelAPI.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import axios, { AxiosInstance } from "axios";
import { Guild } from "discord.js";
import prisma from "../handlers/prisma";
import { upsertApiCredentials } from "../helpers/upsertApiCredentials";
import Encryption, { EncryptedData } from "../utils/encryption";
const encryption = new Encryption();
interface ApiCredentials {
url: EncryptedData;
token: EncryptedData;
[key: string]: EncryptedData | unknown;
}
export class CtrlPanelAPIError extends Error {
constructor(message: string) {
super(message);
this.name = "CtrlPanelAPIError";
}
}
class CtrlPanelAPI {
private guild: Guild;
private apiCredentials: ApiCredentials | null;
private api: AxiosInstance;
constructor(guild: Guild) {
this.guild = guild;
this.apiCredentials = null;
this.api = axios.create();
}
private async fetchApiCredentials(): Promise<void> {
const apiCredentials = await prisma.apiCredentials.findUnique({
where: {
guildId_apiName: {
guildId: this.guild.id,
apiName: "Ctrlpanel.gg",
},
},
});
if (!apiCredentials || !apiCredentials.credentials) {
throw new CtrlPanelAPIError(
"API credentials are required for this functionality. Please configure the CtrlPanel.gg API credentials for this guild.",
);
}
this.apiCredentials = apiCredentials.credentials as ApiCredentials;
}
private async getPlainUrl(): Promise<string> {
if (!this.apiCredentials) {
throw new CtrlPanelAPIError("API credentials not fetched");
}
const { url } = this.apiCredentials;
return await encryption.decrypt(url);
}
private async getPlainToken(): Promise<string> {
if (!this.apiCredentials) {
throw new CtrlPanelAPIError("API credentials not fetched");
}
const { token } = this.apiCredentials;
return await encryption.decrypt(token);
}
public async generateVoucher(
code: string,
amount: number,
uses: number,
): Promise<{ redeemUrl: string }> {
await this.fetchApiCredentials();
const plainUrl = await this.getPlainUrl();
const plainToken = await this.getPlainToken();
this.api.defaults.baseURL = `${plainUrl}/api`;
this.api.defaults.headers.common["Authorization"] = plainToken
? `Bearer ${plainToken}`
: undefined;
const shopUrl = `${plainUrl}/store`;
await this.api.post("vouchers", {
uses,
code,
credits: amount,
memo: `Generated by Discord Bot: ${this.guild.client.user.tag}`,
});
return { redeemUrl: `${shopUrl}?voucher=${code}` };
}
public async updateApiCredentials(
scheme: string,
domain: string,
tokenData: string,
): Promise<void> {
const url = await encryption.encrypt(`${scheme}://${domain}`);
const token = await encryption.encrypt(tokenData);
if (!url || !token) {
throw new Error("URL and token must be set");
}
const credentials = {
url,
token,
};
await upsertApiCredentials(this.guild, "Ctrlpanel.gg", credentials);
}
}
export default CtrlPanelAPI;