| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 | #!/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 <username>.${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();}))();
 |