git-utils #3

Merged
jrmyr merged 2 commits from git-utils into main 2025-05-01 23:03:11 +00:00
6 changed files with 139 additions and 7 deletions
Showing only changes of commit 1f99e26b50 - Show all commits

77
_opt/gitUtils.js Normal file
View File

@ -0,0 +1,77 @@
import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js';
import { exec } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);
/**
* Git-related slash commands: /gitstatus and /gitpull
*/
export const commands = [
// Show current branch and commit status
{
data: new SlashCommandBuilder()
.setName('gitstatus')
.setDescription('Show current git branch and remote status'),
async execute(interaction, client) {
try {
// Get current branch and commit
const { stdout: branchOut } = await execAsync('git rev-parse --abbrev-ref HEAD');
const branch = branchOut.trim();
const { stdout: localOut } = await execAsync('git rev-parse HEAD');
const local = localOut.trim().slice(0, 7);
// Fetch updates and get remote commit
await execAsync('git fetch --quiet');
const { stdout: remoteOut } = await execAsync(`git rev-parse origin/${branch}`);
const remote = remoteOut.trim().slice(0, 7);
// Determine ahead/behind counts
const { stdout: behindOut } = await execAsync(`git rev-list --count HEAD..origin/${branch}`);
const behind = parseInt(behindOut.trim(), 10);
const { stdout: aheadOut } = await execAsync(`git rev-list --count origin/${branch}..HEAD`);
const ahead = parseInt(aheadOut.trim(), 10);
const status = (ahead === 0 && behind === 0)
? 'Up-to-date' : `${ahead} ahead, ${behind} behind`;
// Reply with status
await interaction.reply({
content: `Branch: \`${branch}\`\nLocal: \`${local}\`\nRemote: \`${remote}\`\nStatus: ${status}`,
ephemeral: true
});
} catch (err) {
client.logger.error(`Error in gitstatus: ${err.message}`);
await interaction.reply({ content: `Failed to get git status: ${err.message}`, ephemeral: true });
}
}
},
// Pull latest changes and restart bot (owner only)
{
data: new SlashCommandBuilder()
.setName('gitpull')
.setDescription('Pull latest changes and restart bot (Owner only)')
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
async execute(interaction, client) {
const ownerId = client.config.owner;
if (interaction.user.id !== ownerId) {
return interaction.reply({ content: 'Only the bot owner can perform this action.', ephemeral: true });
}
await interaction.deferReply({ ephemeral: true });
try {
// Pull with fast-forward only
const { stdout, stderr } = await execAsync('git pull --ff-only');
const output = stdout.trim() || stderr.trim();
await interaction.editReply({
content: `Git pull output:\n\`\`\`\n${output}\n\`\`\`\nRestarting...`
});
setTimeout(() => process.exit(0), 1000);
} catch (err) {
client.logger.error(`Error in gitpull: ${err.message}`);
await interaction.editReply({ content: `Git pull failed: ${err.message}`, ephemeral: true });
}
}
}
];
/**
* No special init logic for git utilities
*/
export async function init(client, config) {
client.logger.info('Git utilities module loaded');
}

View File

@ -0,0 +1,28 @@
// _opt/messageQueue-example.js
import { onMessageQueueEvent } from './pbUtils.js';
/**
* Example module that listens for 'test' messages in the message_queue collection.
*/
export const init = async (client, config) => {
client.logger.info('Initializing Message Queue Example module');
onMessageQueueEvent(client, async (action, record) => {
// Only process newly created records
if (action !== 'create') return;
// Only process messages meant for this client
if (record.destination !== client.config.id) return;
// Only handle test dataType
if (record.dataType !== 'test') return;
// At this point we have a test message for us
client.logger.info('test received');
// Delete the processed message from the queue
try {
await client.pb.deleteMessageQueue(record.id);
client.logger.debug(`Deleted message_queue record ${record.id}`);
} catch (err) {
client.logger.error(`Failed to delete message_queue record ${record.id}: ${err.message}`);
}
});
};

View File

@ -19,12 +19,15 @@ export const loadModules = async (clientConfig, client) => {
// Load each module
for (const moduleName of modules) {
try {
const modulePath = path.join(modulesDir, `${moduleName}.js`);
// Check if module exists
// Try _opt first, then fallback to core _src modules
let modulePath = path.join(modulesDir, `${moduleName}.js`);
if (!fs.existsSync(modulePath)) {
client.logger.warn(`Module not found: ${modulePath}`);
// Fallback to core source directory
modulePath = path.join(rootDir, '_src', `${moduleName}.js`);
if (!fs.existsSync(modulePath)) {
client.logger.warn(`Module not found in _opt or _src: ${moduleName}.js`);
continue;
}
}
// Import module (using dynamic import for ES modules)

View File

@ -70,6 +70,7 @@ export default {
'pbUtils',
'responses',
'responsesQuery',
'gitUtils'
]
},

22
package-lock.json generated
View File

@ -13,6 +13,7 @@
"discord-api-types": "^0.37.120",
"discord.js": "^14.18.0",
"dotenv": "^16.5.0",
"eventsource": "^3.0.6",
"node-cron": "^3.0.3",
"openai": "^4.95.1",
"pocketbase": "^0.25.2",
@ -519,6 +520,27 @@
"node": ">=6"
}
},
"node_modules/eventsource": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.6.tgz",
"integrity": "sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==",
"license": "MIT",
"dependencies": {
"eventsource-parser": "^3.0.1"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/eventsource-parser": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz",
"integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==",
"license": "MIT",
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",

View File

@ -19,6 +19,7 @@
"discord-api-types": "^0.37.120",
"discord.js": "^14.18.0",
"dotenv": "^16.5.0",
"eventsource": "^3.0.6",
"node-cron": "^3.0.3",
"openai": "^4.95.1",
"pocketbase": "^0.25.2",