import { BaseCommand } from '@adonisjs/core/ace' import { CommandOptions } from '@adonisjs/core/types/ace' import { Worker } from 'bullmq' import queueConfig from '#config/queue' import NntpService from '#services/NntpService' import { YencFile } from '#services/YencFile' import File from '#models/file' import { createExtractorFromData } from 'node-unrar-js' export default class CollectionWorker extends BaseCommand { public static commandName = 'worker:collection' public static description = 'Starts a worker to process file collections (e.g., RAR archives).' public static options: CommandOptions = { startApp: true, } public async run() { this.logger.info('Starting collection worker...') const pool = NntpService const worker = new Worker('collection-queue', async (job) => { const { fileId } = job.data this.logger.debug(`Processing file ID ${fileId} for collection.`) const file = await File.find(fileId) if (!file) { this.logger.error(`File with ID ${fileId} not found in the database.`) return } const RAR_REGEX = /\.part0*1\.rar$/ if (RAR_REGEX.test(file.filename)) { this.logger.info(`File "${file.filename}" is the first part of a RAR set.`) const firstPart = file.messageIds['1'] if (!firstPart || !firstPart.id) { this.logger.error(`Could not find message ID for the first part of file "${file.filename}".`) return } let conn try { conn = await pool.acquire() const bodyBuffer = (await conn.body(`<${firstPart.id}>`)).data const yencFile = new YencFile() yencFile.processPart(bodyBuffer) const decodedBuffer = yencFile.getBuffer() const extractor = await createExtractorFromData({ data: new Uint8Array(decodedBuffer).buffer }) const fileList = extractor.getFileList() // In a real implementation, we would save this file list. this.logger.info(`Files in "${file.filename}": ${JSON.stringify(fileList)}`) } catch (error: any) { if (error.code === 430) { this.logger.error(`Article not found for first part of RAR set (Message ID: ${firstPart.id})`) } else { this.logger.error(`Error processing RAR file: ${error.message}`) } } finally { if (conn) { pool.release(conn) } } } else { this.logger.debug(`File "${file.filename}" is not the first part of a RAR set.`) } }, { connection: queueConfig.connection }) worker.on('failed', (job, err) => { this.logger.error(`Collection job ${job?.id} failed: ${err.message}`) }) this.logger.info('Collection worker started and listening for jobs.') await new Promise(() => {}) } }