#!/usr/bin/env node "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const fs = require("fs"); const path = require("path"); const commandLineUsage = require("command-line-usage"); const exampleConfig = require("../config.example.json"); const command_1 = require("./command"); const json = require("./json"); const loggers_1 = require("./loggers"); const koishi_1 = require("./koishi"); const twitter_1 = require("./twitter"); const logger = (0, loggers_1.getLogger)(); const sections = [ { header: 'GoCQHTTP Instagram Stories Bot', content: 'The QQ Bot that forwards Instagram stories.', }, { header: 'Synopsis', content: [ '$ cq-igstory-bot {underline config.json}', '$ cq-igstory-bot {bold --help}', ], }, { header: 'Documentation', content: [ 'Project home: {underline https://github.com/CL-Jeremy/mirai-twitter-bot}', 'Example config: {underline https://git.io/JJ0jN}', ], }, ]; const usage = commandLineUsage(sections); const args = process.argv.slice(2); if (args.length === 0 || args[0] === 'help' || args[0] === '-h' || args[0] === '--help') { console.log(usage); process.exit(0); } const configPath = args[0]; let config; try { config = JSON.parse(fs.readFileSync(path.resolve(configPath), 'utf8')); } catch (e) { console.log('Failed to parse config file: ', configPath); console.log(usage); process.exit(1); } const requiredFields = [ 'ig_username', 'ig_password', 'cq_bot_qq', ...(config.mode || exampleConfig.mode) === 0 ? ['playwright_ws_spec_endpoint'] : [], ]; const warningFields = [ 'cq_ws_host', 'cq_ws_port', 'cq_access_token', ]; const optionalFields = [ 'lockfile', 'cachefile', 'inactive_hours', 'work_interval', 'webshot_delay', 'loglevel', 'mode', 'resume_on_start', 'ig_socks_proxy', ].concat(warningFields); if (requiredFields.some((value) => config[value] === undefined)) { console.log(`${requiredFields.join(', ')} are required`); process.exit(1); } optionalFields.forEach(key => { if (config[key] === undefined || typeof (config[key]) !== typeof (exampleConfig[key])) { if (warningFields.includes(key)) logger.warn(`${key} is undefined, use ${exampleConfig[key] || 'empty string'} as default`); config[key] = exampleConfig[key]; } }); ['ig_session_lockfile', ...(config.mode || exampleConfig.mode) === 0 ? ['webshot_cookies_lockfile'] : []].forEach(key => { if (!config[key]) { logger.warn(`${key} is undefined, use .${key.replace('_lockfile', '.lock')} as default`); config[key] = `${config.ig_username}.${key.replace('_lockfile', '.lock')}`; } }); const k = 'ig_2fa_code_receiver_port'; if (!config[k] || config[k] < 2048 || config[k] > 65536) { logger.warn(`invalid value of config.${k}, use ${exampleConfig[k]} as default`); config[k] = exampleConfig[k]; } (0, loggers_1.setLogLevels)(config.loglevel); (() => __awaiter(void 0, void 0, void 0, function* () { const deserialized = { lockfile: { workon: 0, feed: [], threads: {}, }, cachefile: {}, }; const fileEntries = Object.keys(deserialized).map(file => [file, path.resolve(config[file])]); for (const [file, filePath] of fileEntries) { if (fs.existsSync(filePath)) try { deserialized[file] = yield json.readFile(filePath); fs.access(filePath, fs.constants.W_OK, err => { if (err) { logger.fatal(`cannot write ${file} ${filePath}, permission denied`); process.exit(1); } }); continue; } catch (err) { logger.error(`Failed to parse ${file} ${config[file]}: `, err); } try { yield json.writeFile(filePath, deserialized[file]); } catch (err) { logger.fatal(`cannot write ${file} ${filePath}, permission denied`); process.exit(1); } } const { lockfile: lock, cachefile: cache } = deserialized; if (!config.resume_on_start) { Object.keys(lock.threads).forEach(key => { lock.threads[key].offset = '-1'; }); } const qq = new koishi_1.default({ access_token: config.cq_access_token, host: config.cq_ws_host, port: config.cq_ws_port, bot_id: config.cq_bot_qq, list: (c, a, cb) => (0, command_1.list)(c, a, cb, lock), sub: (c, a, cb) => (0, command_1.sub)(c, a, cb, lock, config.lockfile), unsub: (c, a, cb) => (0, command_1.unsub)(c, a, cb, lock, config.lockfile), unsubAll: (c, a, cb) => (0, command_1.unsubAll)(c, a, cb, lock, config.lockfile), }); const worker = new twitter_1.default({ sessionLockfile: config.ig_session_lockfile, credentials: [config.ig_username, config.ig_password], codeServicePort: config.ig_2fa_code_receiver_port, proxyUrl: config.ig_socks_proxy, lock, lockfile: config.lockfile, cache, cachefile: config.cachefile, inactiveHours: config.inactive_hours, workInterval: config.work_interval, bot: qq, webshotDelay: config.webshot_delay, webshotCookiesLockfile: config.webshot_cookies_lockfile, mode: config.mode, wsUrl: config.playwright_ws_spec_endpoint, }); worker.session.init().then(worker.launch); qq.connect(); }))();