Skip to content

Commit 6d86dd0

Browse files
authored
Merge branch 'ticketz-oss:main' into main
2 parents c9d1d6b + 4776c62 commit 6d86dd0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1662
-1320
lines changed

backend/package-lock.json

Lines changed: 604 additions & 662 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"@types/lodash": "^4.17.1",
3030
"async-mutex": "^0.4.1",
3131
"axios": "^1.7.2",
32-
"baileys": "^6.7.18",
32+
"baileys": "6.7.18",
3333
"bcryptjs": "^2.4.3",
3434
"bull": "^4.12.2",
3535
"cookie-parser": "^1.4.6",

backend/src/app.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@ import cookieParser from "cookie-parser";
77
import * as Sentry from "@sentry/node";
88

99
import "./database";
10+
import path from "path";
1011
import uploadConfig from "./config/upload";
1112
import AppError from "./errors/AppError";
1213
import routes from "./routes";
1314
import { logger } from "./utils/logger";
1415
import { messageQueue, sendScheduledMessages } from "./queues";
1516

17+
class SystemError extends Error {
18+
code?: string;
19+
}
20+
1621
Sentry.init({ dsn: process.env.SENTRY_DSN });
1722

1823
const app = express();
@@ -25,13 +30,34 @@ app.set("queues", {
2530
app.use(
2631
cors({
2732
credentials: true,
28-
origin: process.env.FRONTEND_URL
33+
origin: process.env.FRONTEND_URL,
34+
exposedHeaders: ["Content-Range", "X-Content-Range"]
2935
})
3036
);
3137
app.use(cookieParser());
3238
app.use(express.json());
3339
app.use(Sentry.Handlers.requestHandler());
34-
app.use("/public", express.static(uploadConfig.directory));
40+
app.get("/public/*", (req, res) => {
41+
const filePath = path.join(uploadConfig.directory, req.params[0]);
42+
43+
if (filePath.endsWith(".aac")) {
44+
res.setHeader("Content-Type", "audio/aac");
45+
}
46+
47+
res.download(filePath, (err: SystemError) => {
48+
if (err) {
49+
if (err.code === "ENOENT") {
50+
res.status(404).end();
51+
} else {
52+
logger.debug(
53+
{ err },
54+
`Error downloading file ${req.params[0]}: ${err.message}`
55+
);
56+
res.status(500).end();
57+
}
58+
}
59+
});
60+
});
3561

3662
app.use((req, _res, next) => {
3763
const { method, url, query, body, headers } = req;

backend/src/controllers/MessageController.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import Ticket from "../models/Ticket";
2424
import ForwardMessageService from "../services/MessageServices/ForwardMessageService";
2525
import { getWbot } from "../libs/wbot";
2626
import { verifyMessage } from "../services/WbotServices/wbotMessageListener";
27+
import { getJidOf } from "../services/WbotServices/getJidOf";
2728

2829
type IndexQuery = {
2930
pageNumber: string;
@@ -121,15 +122,12 @@ export const react = async (req: Request, res: Response): Promise<Response> => {
121122

122123
const msg = JSON.parse(message.dataJson);
123124

124-
const sentMessage = await wbot.sendMessage(
125-
ticket.contact.number + (ticket.isGroup ? "@g.us" : "@s.whatsapp.net"),
126-
{
127-
react: {
128-
text: emoji,
129-
key: msg.key
130-
}
125+
const sentMessage = await wbot.sendMessage(getJidOf(ticket), {
126+
react: {
127+
text: emoji,
128+
key: msg.key
131129
}
132-
);
130+
});
133131

134132
if (!sentMessage) {
135133
throw new AppError("ERR_WHATSAPP_MESSAGE_NOT_SENT", 500);

backend/src/controllers/SessionController.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,6 @@ export const remove = async (
7777
req: Request,
7878
res: Response
7979
): Promise<Response> => {
80-
const { id } = req.user;
81-
const user = await User.findByPk(id);
82-
await user.update({ online: false });
83-
8480
res.clearCookie("jrt");
8581

8682
return res.send();

backend/src/database/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Contact from "../models/Contact";
55
import ContactTag from "../models/ContactTag";
66
import Ticket from "../models/Ticket";
77
import Whatsapp from "../models/Whatsapp";
8+
import WhatsappLidMap from "../models/WhatsappLidMap";
89
import ContactCustomField from "../models/ContactCustomField";
910
import Message from "../models/Message";
1011
import OldMessage from "../models/OldMessage";
@@ -54,6 +55,7 @@ const models = [
5455
Message,
5556
OldMessage,
5657
Whatsapp,
58+
WhatsappLidMap,
5759
ContactCustomField,
5860
Setting,
5961
Queue,
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { QueryInterface, DataTypes } from "sequelize";
2+
3+
export default {
4+
up: async (queryInterface: QueryInterface) => {
5+
await queryInterface.createTable("WhatsappLidMaps", {
6+
id: {
7+
type: DataTypes.INTEGER,
8+
autoIncrement: true,
9+
primaryKey: true,
10+
allowNull: false
11+
},
12+
lid: {
13+
type: DataTypes.STRING,
14+
allowNull: false
15+
},
16+
companyId: {
17+
type: DataTypes.INTEGER,
18+
allowNull: false
19+
},
20+
contactId: {
21+
type: DataTypes.INTEGER,
22+
allowNull: false,
23+
references: {
24+
model: "Contacts",
25+
key: "id"
26+
},
27+
onDelete: "CASCADE",
28+
onUpdate: "CASCADE"
29+
},
30+
createdAt: {
31+
type: DataTypes.DATE,
32+
allowNull: false
33+
},
34+
updatedAt: {
35+
type: DataTypes.DATE,
36+
allowNull: false
37+
}
38+
});
39+
40+
await queryInterface.addIndex("WhatsappLidMaps", ["lid"]);
41+
await queryInterface.addIndex("WhatsappLidMaps", ["companyId"]);
42+
await queryInterface.addConstraint("WhatsappLidMaps", {
43+
fields: ["lid", "companyId"],
44+
type: "unique",
45+
name: "unique_lid_companyId"
46+
});
47+
},
48+
49+
down: async (queryInterface: QueryInterface) => {
50+
return queryInterface.dropTable("WhatsappLidMaps");
51+
}
52+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { QueryInterface } from "sequelize";
2+
3+
export default {
4+
up: async (queryInterface: QueryInterface) => {
5+
await queryInterface.removeColumn("Users", "online");
6+
},
7+
8+
down: async (queryInterface: QueryInterface) => {
9+
await queryInterface.addColumn("Users", "online", {
10+
type: "BOOLEAN",
11+
allowNull: true
12+
});
13+
}
14+
};

backend/src/helpers/SetTicketMessagesAsRead.ts

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { WASocket, proto } from "baileys";
2-
import { cacheLayer } from "../libs/cache";
32
import { getIO } from "../libs/socket";
43
import Message from "../models/Message";
54
import Ticket from "../models/Ticket";
@@ -8,7 +7,6 @@ import GetTicketWbot from "./GetTicketWbot";
87

98
const SetTicketMessagesAsRead = async (ticket: Ticket): Promise<void> => {
109
await ticket.update({ unreadMessages: 0 }, { silent: true });
11-
await cacheLayer.set(`contacts:${ticket.contactId}:unreads`, "0");
1210
let companyId: number;
1311

1412
try {
@@ -40,32 +38,39 @@ const SetTicketMessagesAsRead = async (ticket: Ticket): Promise<void> => {
4038
`Marking ${messageKeys.length} messages of ticket ${ticket.id} as read`
4139
);
4240

43-
// Process message keys in batches of 250
44-
const batchSize = 250;
45-
for (let i = 0; i < messageKeys.length; i += batchSize) {
46-
const batch = messageKeys.slice(i, i + batchSize);
47-
(wbot as WASocket).readMessages(batch).catch(err => {
48-
logger.error(
49-
{ error: err as Error },
50-
`Could not mark messages as read. Err: ${err?.message}`
51-
);
52-
});
53-
}
54-
55-
const lastMessage: proto.IWebMessageInfo = JSON.parse(messages[0].dataJson);
56-
if (lastMessage?.key?.remoteJid && !lastMessage.key.fromMe) {
57-
// Asynchronous chatModify call
58-
(wbot as WASocket)
59-
.chatModify(
60-
{ markRead: true, lastMessages: [lastMessage] },
61-
lastMessage.key.remoteJid
62-
)
63-
.catch(err => {
41+
if (wbot) {
42+
// Process message keys in batches of 250
43+
const batchSize = 250;
44+
for (let i = 0; i < messageKeys.length; i += batchSize) {
45+
const batch = messageKeys.slice(i, i + batchSize);
46+
try {
47+
// eslint-disable-next-line no-await-in-loop
48+
await (wbot as WASocket).readMessages(batch);
49+
} catch (err) {
6450
logger.error(
6551
{ error: err as Error },
66-
`Could not modify chat. Err: ${err?.message}`
52+
`Could not mark messages as read. Err: ${err?.message}`
6753
);
68-
});
54+
}
55+
}
56+
57+
const lastMessage: proto.IWebMessageInfo = JSON.parse(
58+
messages[0].dataJson
59+
);
60+
if (lastMessage?.key?.remoteJid && !lastMessage.key.fromMe) {
61+
// Asynchronous chatModify call
62+
(wbot as WASocket)
63+
.chatModify(
64+
{ markRead: true, lastMessages: [lastMessage] },
65+
lastMessage.key.remoteJid
66+
)
67+
.catch(err => {
68+
logger.error(
69+
{ error: err as Error },
70+
`Could not modify chat. Err: ${err?.message}`
71+
);
72+
});
73+
}
6974
}
7075

7176
await Message.update(

backend/src/libs/socket.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import { instrument } from "@socket.io/admin-ui";
4444
import { Server } from "http";
4545
import { verify } from "jsonwebtoken";
4646
import AppError from "../errors/AppError";
47-
import { logger } from "../utils/logger";
47+
import { logger, socketSendBuffer } from "../utils/logger";
4848
import User from "../models/User";
4949
import Queue from "../models/Queue";
5050
import Ticket from "../models/Ticket";
@@ -118,7 +118,6 @@ export const initIO = (httpServer: Server): SocketIO => {
118118
if (userId && userId !== "undefined" && userId !== "null") {
119119
user = await User.findByPk(userId, { include: [Queue] });
120120
if (user) {
121-
user.online = true;
122121
await user.save();
123122
} else {
124123
logger.info(`onConnect: User ${userId} not found`);
@@ -172,6 +171,7 @@ export const initIO = (httpServer: Server): SocketIO => {
172171
"started transmission of backend logs"
173172
]
174173
});
174+
socketSendBuffer();
175175
} else {
176176
logger.info(`User ${user.id} tried to join superlog channel.`);
177177
}

0 commit comments

Comments
 (0)