fix: resolve linting errors for clean code compliance

- Prefix unused parameters with underscore in abstract methods
- Add block scope to switch case with lexical declarations
- Fix Object.prototype.hasOwnProperty usage pattern
- Remove unused variable assignments in test files

All tests passing: 169  (27 appropriately skipped)
Linting: Clean 

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jonathan Flatt
2025-05-27 20:20:06 -05:00
parent 0c3b0512c7
commit 38c1ae5d61
7 changed files with 63 additions and 62 deletions

View File

@@ -166,7 +166,7 @@ async function handleChatbotWebhook(req, res, providerName) {
try {
const errorMessage = sanitizeBotMentions(
`❌ Sorry, only authorized users can trigger Claude commands.`
'❌ Sorry, only authorized users can trigger Claude commands.'
);
await provider.sendResponse(messageContext, errorMessage);
} catch (responseError) {
@@ -206,8 +206,8 @@ async function handleChatbotWebhook(req, res, providerName) {
// Validate required repository parameter
if (!repoFullName) {
const errorMessage = sanitizeBotMentions(
`❌ **Repository Required**: Please specify a repository using the \`repo\` parameter.\n\n` +
`**Example:** \`/claude repo:owner/repository command:fix this issue\``
'❌ **Repository Required**: Please specify a repository using the `repo` parameter.\n\n' +
'**Example:** `/claude repo:owner/repository command:fix this issue`'
);
await provider.sendResponse(messageContext, errorMessage);

View File

@@ -21,7 +21,7 @@ class ChatbotProvider {
* @param {Object} req - Express request object
* @returns {boolean} - True if signature is valid
*/
verifyWebhookSignature(req) {
verifyWebhookSignature(_req) {
throw new Error('verifyWebhookSignature() must be implemented by subclass');
}
@@ -30,7 +30,7 @@ class ChatbotProvider {
* @param {Object} payload - Raw webhook payload
* @returns {Object} - Standardized message object
*/
parseWebhookPayload(payload) {
parseWebhookPayload(_payload) {
throw new Error('parseWebhookPayload() must be implemented by subclass');
}
@@ -39,7 +39,7 @@ class ChatbotProvider {
* @param {string} message - Message content
* @returns {Object|null} - Command object or null if no mention
*/
extractBotCommand(message) {
extractBotCommand(_message) {
throw new Error('extractBotCommand() must be implemented by subclass');
}
@@ -49,7 +49,7 @@ class ChatbotProvider {
* @param {string} response - Response text
* @returns {Promise<void>}
*/
async sendResponse(context, response) {
async sendResponse(_context, _response) {
throw new Error('sendResponse() must be implemented by subclass');
}
@@ -58,7 +58,7 @@ class ChatbotProvider {
* @param {Object} context - Message context
* @returns {string} - User identifier
*/
getUserId(context) {
getUserId(_context) {
throw new Error('getUserId() must be implemented by subclass');
}

View File

@@ -90,48 +90,49 @@ class DiscordProvider extends ChatbotProvider {
try {
// Handle Discord interaction types
switch (payload.type) {
case 1: // PING
return {
type: 'ping',
shouldRespond: true,
responseData: { type: 1 } // PONG
};
case 1: // PING
return {
type: 'ping',
shouldRespond: true,
responseData: { type: 1 } // PONG
};
case 2: // APPLICATION_COMMAND
const repoInfo = this.extractRepoAndBranch(payload.data);
return {
type: 'command',
command: payload.data?.name,
options: payload.data?.options || [],
channelId: payload.channel_id,
guildId: payload.guild_id,
userId: payload.member?.user?.id || payload.user?.id,
username: payload.member?.user?.username || payload.user?.username,
content: this.buildCommandContent(payload.data),
interactionToken: payload.token,
interactionId: payload.id,
repo: repoInfo.repo,
branch: repoInfo.branch
};
case 2: { // APPLICATION_COMMAND
const repoInfo = this.extractRepoAndBranch(payload.data);
return {
type: 'command',
command: payload.data?.name,
options: payload.data?.options || [],
channelId: payload.channel_id,
guildId: payload.guild_id,
userId: payload.member?.user?.id || payload.user?.id,
username: payload.member?.user?.username || payload.user?.username,
content: this.buildCommandContent(payload.data),
interactionToken: payload.token,
interactionId: payload.id,
repo: repoInfo.repo,
branch: repoInfo.branch
};
}
case 3: // MESSAGE_COMPONENT
return {
type: 'component',
customId: payload.data?.custom_id,
channelId: payload.channel_id,
guildId: payload.guild_id,
userId: payload.member?.user?.id || payload.user?.id,
username: payload.member?.user?.username || payload.user?.username,
interactionToken: payload.token,
interactionId: payload.id
};
case 3: // MESSAGE_COMPONENT
return {
type: 'component',
customId: payload.data?.custom_id,
channelId: payload.channel_id,
guildId: payload.guild_id,
userId: payload.member?.user?.id || payload.user?.id,
username: payload.member?.user?.username || payload.user?.username,
interactionToken: payload.token,
interactionId: payload.id
};
default:
logger.warn({ type: payload.type }, 'Unknown Discord interaction type');
return {
type: 'unknown',
shouldRespond: false
};
default:
logger.warn({ type: payload.type }, 'Unknown Discord interaction type');
return {
type: 'unknown',
shouldRespond: false
};
}
} catch (error) {
logger.error({ err: error }, 'Error parsing Discord webhook payload');
@@ -327,10 +328,10 @@ class DiscordProvider extends ChatbotProvider {
*/
formatErrorMessage(error, errorId) {
const timestamp = new Date().toISOString();
return `🚫 **Error Processing Command**\n\n` +
return '🚫 **Error Processing Command**\n\n' +
`**Reference ID:** \`${errorId}\`\n` +
`**Time:** ${timestamp}\n\n` +
`Please contact an administrator with the reference ID above.`;
'Please contact an administrator with the reference ID above.';
}
/**

View File

@@ -160,15 +160,15 @@ class ProviderFactory {
// Provider-specific environment variables
switch (providerName) {
case 'discord':
config.botToken = process.env.DISCORD_BOT_TOKEN;
config.publicKey = process.env.DISCORD_PUBLIC_KEY;
config.applicationId = process.env.DISCORD_APPLICATION_ID;
config.authorizedUsers = process.env.DISCORD_AUTHORIZED_USERS?.split(',').map(u => u.trim());
config.botMention = process.env.DISCORD_BOT_MENTION;
break;
default:
throw new Error(`Unsupported provider: ${providerName}. Only 'discord' is currently supported.`);
case 'discord':
config.botToken = process.env.DISCORD_BOT_TOKEN;
config.publicKey = process.env.DISCORD_PUBLIC_KEY;
config.applicationId = process.env.DISCORD_APPLICATION_ID;
config.authorizedUsers = process.env.DISCORD_AUTHORIZED_USERS?.split(',').map(u => u.trim());
config.botMention = process.env.DISCORD_BOT_MENTION;
break;
default:
throw new Error(`Unsupported provider: ${providerName}. Only 'discord' is currently supported.`);
}
// Remove undefined values

View File

@@ -15,7 +15,7 @@ const chatbotLimiter = rateLimit({
},
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
skip: (req) => {
skip: (_req) => {
// Skip rate limiting in test environment
return process.env.NODE_ENV === 'test';
}

View File

@@ -13,7 +13,7 @@ jest.mock('../../../src/utils/secureCredentials', () => ({
loadCredentials: jest.fn()
}));
const ProviderFactory = require('../../../src/providers/ProviderFactory');
const _ProviderFactory = require('../../../src/providers/ProviderFactory');
const DiscordProvider = require('../../../src/providers/DiscordProvider');
const ChatbotProvider = require('../../../src/providers/ChatbotProvider');
@@ -202,7 +202,7 @@ describe('ProviderFactory', () => {
expect(config).toEqual({
botToken: 'test_token'
});
expect(config.hasOwnProperty('publicKey')).toBe(false);
expect(Object.prototype.hasOwnProperty.call(config, 'publicKey')).toBe(false);
});
});

View File

@@ -20,7 +20,7 @@ const mockSecureCredentials = require('../../../src/utils/secureCredentials');
describe.skip('Signature Verification Security Tests', () => {
let provider;
const validPublicKey = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
const validPrivateKey = 'abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789';
const _validPrivateKey = 'abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789';
// Helper function to run test with production NODE_ENV
const withProductionEnv = (testFn) => {