Skip to content

Commit b6ae898

Browse files
author
Eric Trenkel
committed
Use mongodb instead of sqlite
1 parent c965625 commit b6ae898

13 files changed

+1042
-466
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
config.ts
33
config.yaml
44
support.db
5+
support.old.db
56
build/
67
*.rsls
78

docker-compose.yml

+25
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,28 @@ services:
77
- ./config:/bot/config
88
ports:
99
- "8080:8080"
10+
environment:
11+
- MONGO_URI=mongodb://mongodb:27017/support
12+
13+
mongodb:
14+
image: mongo:8.0
15+
restart: unless-stopped
16+
ports:
17+
- "27017:27017"
18+
volumes:
19+
- mongodb_data:/data/db
20+
21+
# mongodb web interface
22+
mongo-express:
23+
image: mongo-express
24+
restart: unless-stopped
25+
ports:
26+
- "8081:8081"
27+
environment:
28+
- ME_CONFIG_MONGODB_SERVER=mongodb
29+
- ME_CONFIG_MONGODB_PORT=27017
30+
- ME_CONFIG_BASICAUTH_USERNAME=admin
31+
- ME_CONFIG_BASICAUTH_PASSWORD=password
32+
33+
volumes:
34+
mongodb_data:

package-lock.json

+821-279
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
"main": "build/src/index.js",
1616
"scripts": {
1717
"tsc": "tsc",
18-
"dev": "ts-node-dev ./src/index.ts",
19-
"prod": "ts-node ./src/index.ts",
18+
"dev": "NODE_ENV=development ts-node-dev ./src/index.ts",
19+
"prod": "NODE_ENV=production ts-node ./src/index.ts",
2020
"build": "tsc",
2121
"test": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha -r ts-node/register 'test/**/*.ts' --exit"
2222
},
@@ -31,6 +31,7 @@
3131
"express": "^4.18.2",
3232
"express-rate-limit": "^6.7.0",
3333
"grammy": "^1.12.0",
34+
"mongoose": "^8.8.1",
3435
"node-fetch": ">=3.3.0",
3536
"node-gyp": "^9.3.1",
3637
"sandwich-stream": "^2.0.2",

src/commands.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ function banCommand(ctx: Context) {
212212
ctx.chat.id,
213213
cache.config.language.usr_with_ticket +
214214
' #T' +
215-
ticket.id.toString().padStart(6, '0') +
215+
ticketId.toString().padStart(6, '0') +
216216
' ' +
217217
cache.config.language.banned,
218218
{ parse_mode: cache.config.parse_mode }, /* .notifications(false) */

src/db.ts

+92-163
Original file line numberDiff line numberDiff line change
@@ -1,183 +1,112 @@
1-
const Database = require('better-sqlite3');
2-
const db = new Database('./config/support.db', {
3-
/* verbose: console.log */
4-
}); // debugging
1+
import mongoose from 'mongoose';
2+
import cache from './cache';
53

6-
try {
7-
db.prepare(`ALTER TABLE supportees ADD category TEXT;`).run();
8-
} catch (e) {}
9-
db.prepare(
10-
`CREATE TABLE IF NOT EXISTS supportees
11-
(id INTEGER PRIMARY KEY AUTOINCREMENT, ` +
12-
`userid TEXT, status TEXT, category TEXT);`,
13-
).run();
4+
const MONGO_URI = cache.config.mongodb_uri || 'mongodb://localhost:27017/support';
5+
const botTokenSuffix = cache.config.bot_token.slice(-5);
6+
const collectionName = `bot_${cache.config.owner_id}_${botTokenSuffix}`;
147

15-
const check = function(
16-
userid: any,
17-
category: any,
18-
callback: (arg0: any) => void,
19-
) {
20-
const searchDB = db
21-
.prepare(
22-
`select * from supportees where (userid = ` +
23-
`${userid} or id = ${userid}) ` +
24-
`${category ? `AND category = '${category}'` : ''}`,
25-
)
26-
.all();
27-
callback(searchDB);
8+
const SupporteeSchema = new mongoose.Schema({
9+
ticketId: { type: Number, required: true, unique: true, alias: 'id' },
10+
userid: { type: String, required: true },
11+
status: { type: String, default: 'open' },
12+
category: { type: String, default: null },
13+
});
14+
15+
const Supportee = mongoose.model(collectionName, SupporteeSchema);
16+
17+
// Connect to MongoDB
18+
mongoose.connect(MONGO_URI);
19+
20+
/** Methods **/
21+
22+
const getNextTicketId = async () => {
23+
const lastEntry = await Supportee.findOne().sort({ ticketId: -1 }).select('ticketId');
24+
return lastEntry ? lastEntry.ticketId + 1 : 1; // Start from 1 if no entries
2825
};
2926

30-
const getOpen = function(
31-
userid: string | number,
32-
category: string | null,
33-
callback: Function,
34-
) {
35-
const searchDB = db
36-
.prepare(
37-
`select * from supportees where (userid = ` +
38-
`'${userid}' or id = '${userid}') AND status='open' ` +
39-
`${category ? `AND category = '${category}'` : ''}`,
40-
)
41-
.get();
42-
callback(searchDB);
27+
const check = async (userid: any, category: any, callback: (arg0: any) => void) => {
28+
const query = {
29+
$or: [{ userid: userid }, { ticketId: userid }],
30+
...(category && { category }),
31+
};
32+
const result = await Supportee.find(query);
33+
callback(result);
4334
};
4435

45-
const getId = function(
46-
userid: number,
47-
callback: {
48-
(ticket: { userid: any; id: { toString: () => string } }): void;
49-
(ticket: {
50-
userid: any;
51-
/* verbose: console.log */
52-
id: /* verbose: console.log */ { toString: () => string };
53-
}): void;
54-
(ticket: { userid: any; id: { toString: () => string } }): void;
55-
(arg0: any): void;
56-
},
57-
) {
58-
const searchDB = db
59-
.prepare(
60-
`select * from supportees where (userid = ` +
61-
`${userid} or id = ${userid})`,
62-
)
63-
.get();
64-
callback(searchDB);
36+
const getTicketById = async (userid: string | number, category: string | null, callback: Function) => {
37+
const query = {
38+
$or: [{ userid: userid }, { ticketId: userid }],
39+
...(category ? { category } : { category: null }),
40+
};
41+
const result = await Supportee.findOne(query);
42+
callback(result);
6543
};
6644

67-
const checkBan = function(
68-
userid: any,
69-
callback: { (ticket: any): any; (arg0: any): void },
70-
) {
71-
const searchDB = db
72-
.prepare(
73-
`select * from supportees where (userid = ` +
74-
`${userid} or id = ${userid}) AND status='banned' `,
75-
)
76-
.get();
77-
callback(searchDB);
45+
const getId = async (userid: string, callback: (ticket: any) => void) => {
46+
const query = { $or: [{ userid: userid }, { ticketId: userid }] };
47+
const result = await Supportee.findOne(query);
48+
callback(result);
7849
};
7950

80-
const closeAll = function() {
81-
db.prepare(`UPDATE supportees SET status='closed'`).run();
51+
const checkBan = async (userid: any, callback: (ticket: any) => void) => {
52+
const query = {
53+
$or: [{ userid: userid }, { ticketId: userid }],
54+
status: 'banned',
55+
};
56+
const result = await Supportee.findOne(query);
57+
callback(result);
8258
};
8359

84-
const reopen = function(userid: any, category: string) {
85-
db.prepare(
86-
`UPDATE supportees SET status='open'` +
87-
`WHERE userid='${userid}' or id='${userid}'` +
88-
`${category ? `AND category = '${category}'` : ''}`,
89-
).run();
60+
const closeAll = async () => {
61+
await Supportee.updateMany({}, { $set: { status: 'closed' } });
9062
};
9163

92-
const add = function(
93-
userid: string | number,
94-
status: string,
95-
category: string | number | null,
96-
) {
97-
let msg;
98-
if (status == 'closed') {
99-
console.log(
100-
`UPDATE supportees SET status='closed' WHERE ` +
101-
`(userid='${userid}' or id='${userid}')` +
102-
`${category ? `AND category = '${category}'` : ''}`,
103-
);
104-
msg = db
105-
.prepare(
106-
`UPDATE supportees SET status='closed' WHERE ` +
107-
`(userid='${userid}' or id='${userid}')` +
108-
`${category ? `AND category = '${category}'` : ''}`,
109-
)
110-
.run();
111-
} else if (status == 'open') {
112-
// db.prepare(`DELETE FROM supportees WHERE userid='${userid}'` +
113-
// ` or id='${userid}'`).run();
114-
msg = db
115-
.prepare(
116-
`REPLACE INTO supportees (userid, ` +
117-
`status ${category ? `,category` : ''}) ` +
118-
`VALUES ('${userid}', '${status}' ${
119-
category ? `,'${category}'` : ''
120-
})`,
121-
)
122-
.run();
123-
} else if ((status = 'banned')) {
124-
msg = db
125-
.prepare(
126-
`REPLACE INTO supportees (userid, status, category)` +
127-
`VALUES ('${userid}', '${status}', 'BANNED')`,
128-
)
129-
.run();
130-
}
131-
return msg.changes;
64+
const reopen = async (userid: any, category: string) => {
65+
const query = {
66+
$or: [{ userid: userid }, { ticketId: userid }],
67+
...(category && { category }),
68+
};
69+
await Supportee.updateMany(query, { $set: { status: 'open' } });
13270
};
13371

134-
const open = function(
135-
callback: {
136-
(userList: {
137-
[x: string]: {
138-
[x: string]: {
139-
toString: () => {
140-
(): any;
141-
new (): any;
142-
indexOf(/* verbose: console.log */ arg0: string): any;
143-
padStart: {
144-
(
145-
// debugging
146-
arg0: number,
147-
arg1: string
148-
): {
149-
(): any;
150-
new (): any;
151-
toString: { (): string; new (): any };
152-
};
153-
new (): any;
154-
};
155-
};
156-
};
157-
};
158-
}): void;
159-
(tickets: string | any[]): void;
160-
(arg0: any): void;
161-
},
162-
category: string | any[],
163-
) {
164-
let searchText = '';
165-
for (let i = 0; i < category.length; i++) {
166-
if (i == 0) {
167-
searchText += `= '${category[i]}'`;
168-
} else {
169-
searchText += ` OR category = '${category[i]}'`;
170-
}
72+
const add = async (
73+
userid: string | number,
74+
status: string,
75+
category: string | number | null,
76+
) => {
77+
let result;
78+
if (status === 'closed') {
79+
const query = {
80+
$or: [{ userid: userid }, { ticketId: userid }],
81+
...(category && { category }),
82+
};
83+
result = await Supportee.updateMany(query, { $set: { status: 'closed' } });
84+
} else if (status === 'open') {
85+
let ticketId = await getNextTicketId();
86+
result = await Supportee.findOneAndReplace(
87+
{ userid },
88+
{ userid, ticketId, status, category },
89+
{ upsert: true },
90+
);
91+
} else if (status === 'banned') {
92+
result = await Supportee.findOneAndReplace(
93+
{ userid },
94+
{ userid, ticketId: await getNextTicketId(), status: 'banned', category: 'BANNED' },
95+
{ upsert: true },
96+
);
17197
}
98+
return result?.modifiedCount || 0;
99+
};
172100

173-
const searchDB = db
174-
.prepare(
175-
`select * from supportees where status = 'open' ` +
176-
`and (category ${category.length > 0 ? searchText : 'is NULL'})`,
177-
)
178-
.all();
179-
180-
callback(searchDB);
101+
const open = async (callback: Function, category: string[]) => {
102+
const query = {
103+
status: 'open',
104+
...(category.length > 0
105+
? { category: { $in: category } }
106+
: { category: null }),
107+
};
108+
const result = await Supportee.find(query);
109+
callback(result);
181110
};
182111

183-
export {open, add, check, getOpen, checkBan, getId, closeAll, reopen};
112+
export { open, add, check, getTicketById, checkBan, getId, closeAll, reopen };

src/files.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ function fileHandler(type: string, bot: TelegramAddon, ctx: Context) {
8484
return;
8585
}
8686
}
87-
db.getOpen(
87+
db.getTicketById(
8888
msgId,
8989
ctx.session.groupCategory,
9090
async function(ticket: any) {
@@ -257,7 +257,7 @@ function forwardFile(
257257
ctx: Context,
258258
callback: { (userInfo: any): void; (arg0: any): void },
259259
) {
260-
db.getOpen(
260+
db.getTicketById(
261261
ctx.message.from.id,
262262
ctx.session.groupCategory,
263263
function(ticket: any) {

0 commit comments

Comments
 (0)