security hardening
This commit is contained in:
@@ -23,20 +23,25 @@ const { getNextTicketNumber, checkTicketLimits, getOrCreateTicketCategory, creat
|
||||
const { getEmailRouting } = require('./services/guildSettings');
|
||||
const { logError, logGmail, logAutomation } = require('./services/debugLog');
|
||||
const { increment } = require('./services/patternStore');
|
||||
const { enqueueSend } = require('./services/channelQueue');
|
||||
|
||||
const Ticket = mongoose.model('Ticket');
|
||||
const Transcript = mongoose.model('Transcript');
|
||||
|
||||
let isPolling = false;
|
||||
let authErrorNotified = false;
|
||||
let pollSuspended = false;
|
||||
let pollCount = 0, totalProcessed = 0, totalSkipped = 0, totalErrors = 0;
|
||||
|
||||
function setPollSuspended(val) { pollSuspended = !!val; }
|
||||
function isPollSuspended() { return pollSuspended; }
|
||||
|
||||
/**
|
||||
* Poll Gmail for unread primary-inbox messages and route them to Discord.
|
||||
* @param {import('discord.js').Client} client
|
||||
*/
|
||||
async function poll(client) {
|
||||
if (isPolling) return;
|
||||
if (isPolling || pollSuspended) return;
|
||||
isPolling = true;
|
||||
try {
|
||||
pollCount++;
|
||||
@@ -155,7 +160,8 @@ async function poll(client) {
|
||||
|
||||
if (ticketChan) {
|
||||
const truncatedFollowup = followupBody.slice(0, 1800);
|
||||
await ticketChan.send(
|
||||
await enqueueSend(
|
||||
ticketChan,
|
||||
`<@&${CONFIG.ROLE_ID_TO_PING}>\n**New Follow-up from ${sEmail}:**\n${truncatedFollowup}`
|
||||
);
|
||||
} else {
|
||||
@@ -247,7 +253,7 @@ async function poll(client) {
|
||||
);
|
||||
|
||||
enforceEmbedLimit([ticketInfoEmbed]);
|
||||
const welcomeMsg = await ticketChan.send({
|
||||
const welcomeMsg = await enqueueSend(ticketChan, {
|
||||
content: `<@&${CONFIG.ROLE_ID_TO_PING}>`,
|
||||
embeds: [ticketInfoEmbed],
|
||||
components: [buttons]
|
||||
@@ -275,7 +281,8 @@ async function poll(client) {
|
||||
.catch(() => null);
|
||||
|
||||
if (transcriptChan) {
|
||||
await ticketChan.send(
|
||||
await enqueueSend(
|
||||
ticketChan,
|
||||
`This email thread has ${transcriptRows.length} previous transcript(s):`
|
||||
);
|
||||
|
||||
@@ -286,11 +293,11 @@ async function poll(client) {
|
||||
|
||||
if (!transcriptMsg) continue;
|
||||
|
||||
await ticketChan.send(`Transcript: ${transcriptMsg.url}`);
|
||||
await enqueueSend(ticketChan, `Transcript: ${transcriptMsg.url}`);
|
||||
|
||||
const originalAttachment = transcriptMsg.attachments.first();
|
||||
if (originalAttachment) {
|
||||
await ticketChan.send({
|
||||
await enqueueSend(ticketChan, {
|
||||
content: 'Transcript file:',
|
||||
files: [originalAttachment.url]
|
||||
});
|
||||
@@ -304,7 +311,7 @@ async function poll(client) {
|
||||
}
|
||||
|
||||
const truncated = firstBody.slice(0, 1900);
|
||||
await ticketChan.send(`**Message:**\n${truncated}`);
|
||||
await enqueueSend(ticketChan, `**Message:**\n${truncated}`);
|
||||
|
||||
// Welcome message skipped for email tickets – the email body speaks for itself.
|
||||
// Panel-created (Discord) tickets still send the welcome message in handlers/buttons.js.
|
||||
@@ -359,10 +366,14 @@ async function poll(client) {
|
||||
e.code === 401;
|
||||
|
||||
if (isAuthError) {
|
||||
logError('Gmail OAuth', { message: 'Gmail OAuth token invalid or expired. Re-authentication required.', stack: e.stack || e.message || String(e) }, null, client);
|
||||
pollSuspended = true;
|
||||
const suspendMsg = 'Gmail OAuth token invalid or expired. Polling SUSPENDED — will not retry automatically. Re-authenticate to resume.';
|
||||
console.error('[gmail-poll]', suspendMsg);
|
||||
logError('Gmail OAuth', { message: suspendMsg, stack: e.stack || e.message || String(e) }, null, client);
|
||||
try { require('./broccolini-discord').clearGmailPollInterval?.(); } catch (_) {}
|
||||
if (CONFIG.ADMIN_ID && !authErrorNotified) {
|
||||
authErrorNotified = true;
|
||||
client.users.fetch(CONFIG.ADMIN_ID).then(u => u.send('Gmail OAuth token invalid or expired. Re-authentication required.')).catch(() => {});
|
||||
client.users.fetch(CONFIG.ADMIN_ID).then(u => u.send(suspendMsg)).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,4 +386,4 @@ async function poll(client) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { poll };
|
||||
module.exports = { poll, setPollSuspended, isPollSuspended };
|
||||
|
||||
Reference in New Issue
Block a user