From a54659fe4b1b00c841d82d285398ca7250369095 Mon Sep 17 00:00:00 2001 From: pasta04 Date: Sun, 3 May 2020 21:36:07 +0900 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E7=9D=80=E3=81=8C=E4=B8=8A=E3=81=AE?= =?UTF-8?q?=E5=A0=B4=E5=90=88=E3=81=AF=E9=80=86=E9=A0=86=E3=81=AB=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist/index.js | 4 ++++ dist/index.js.map | 2 +- src/main/startServer.ts | 6 +++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 3012037..622ebf4 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1233,6 +1233,10 @@ var taskScheduler = function () { return __awaiter(void 0, void 0, void 0, funct if (!(globalThis.config.commentProcessType === 0)) return [3 /*break*/, 1]; temp = __spreadArrays(globalThis.electron.commentQueueList); globalThis.electron.commentQueueList = []; + // 新着が上の場合は逆順にする + if (!globalThis.config.dispSort) { + temp = temp.reverse(); + } sendDom(temp); return [3 /*break*/, 3]; case 1: diff --git a/dist/index.js.map b/dist/index.js.map index 8018072..6f0e658 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["webpack:///webpack/bootstrap","webpack:///./src/main/ReadIcons.ts","webpack:///./src/main/bouyomi-chan/index.ts","webpack:///./src/main/const.ts","webpack:///./src/main/getRes.ts","webpack:///./src/main/main.ts","webpack:///./src/main/readBBS/Read5ch.ts","webpack:///./src/main/readBBS/readSitaraba.ts","webpack:///./src/main/startServer.ts","webpack:///./src/main/util.ts","webpack:///./src/main/youtube-chat/index.ts","webpack:///./src/main/youtube-chat/live-chat.ts","webpack:///./src/main/youtube-chat/parser.ts"],"sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/main/main.ts\");\n","\"use strict\";\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n/**\r\n * アイコン表示に関するモジュール\r\n * シングルトン\r\n */\r\nvar fs_1 = __importDefault(require(\"fs\"));\r\nvar path_1 = __importDefault(require(\"path\"));\r\nvar electron_log_1 = __importDefault(require(\"electron-log\"));\r\nvar randomIconList;\r\nvar idIconList;\r\n/**\r\n * コンストラクタ\r\n * ・ランダムフォルダからアイコン名を取得してリスト化\r\n * ・IDフォルダからもリスト化、空の対応マップ作製\r\n * ・コテハン対応ファイルを読みこんでmapに格納\r\n */\r\nvar ReadIcons = /** @class */ (function () {\r\n function ReadIcons() {\r\n /**\r\n * アイコンランダム表示機能(デフォルト)\r\n * 起動時に作成したアイコンリストからランダムで1つ取得\r\n */\r\n this.getRandomIcons = function () {\r\n var iconPath = '';\r\n try {\r\n var dirName = './img/random/';\r\n // リストからランダム取得\r\n // const size = randomIconList.size;\r\n var num = Math.floor(randomIconList.length * Math.random());\r\n iconPath = dirName + randomIconList[num];\r\n }\r\n catch (e) {\r\n electron_log_1.default.error(e);\r\n }\r\n return iconPath;\r\n };\r\n //画像ディレクトリ\r\n var randomDir = path_1.default.resolve(__dirname, \"../public/img/random/\");\r\n console.debug('[ReadIcons]loadRandomDir = ' + randomDir);\r\n // ランダムアイコン取得\r\n randomIconList = readDir(randomDir);\r\n //ID用アイコンディレクトリ\r\n var idDir = path_1.default.resolve(__dirname, \"../public/img/id/\");\r\n console.debug('[ReadIcons]loadIDDir = ' + idDir);\r\n // ランダムアイコン取得\r\n idIconList = readDir(idDir);\r\n }\r\n return ReadIcons;\r\n}());\r\nvar readDir = function (imgDir) {\r\n var iconFileList = [];\r\n // 指定したディレクトリのアイコン取得\r\n var files = fs_1.default.readdirSync(imgDir, { withFileTypes: true });\r\n //pngファイルのみ返却リストに格納する\r\n files.forEach(function (file) {\r\n // asar圧縮するとfileが文字列になる。開発環境だとfileオブジェクトになる\r\n var target = typeof file.name !== 'string' ? file : file.name;\r\n var regx = /.*\\.png$/.test(target);\r\n if (regx) {\r\n iconFileList.push(target);\r\n }\r\n });\r\n // console.log('[ReadIcons.readDir]end');\r\n // console.log(JSON.stringify(iconFileList));\r\n return iconFileList;\r\n};\r\n/**\r\n * IDによるアイコン固定機能(オプションでON,OFF可能)\r\n * 初出のIDならばランダムでアイコンを取得し\r\n * IDとファイル名のセットでマップに格納\r\n * @param string // ID\r\n * @return string filename\r\n */\r\n/**\r\n * コテハンリスト機能(オプションでON,OFF可能)\r\n * koteフォルダの下にkotehan.jsonを作って\r\n * 名前とアイコンファイル名の対応をマップにして返すだけ\r\n */\r\nexports.default = ReadIcons;\r\n","\"use strict\";\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar net_1 = __importDefault(require(\"net\"));\r\nvar BouyomiChan = /** @class */ (function () {\r\n function BouyomiChan(options) {\r\n /**\r\n * 棒読みちゃんのホスト\r\n */\r\n this.host = 'localhost';\r\n /**\r\n * 棒読みちゃんのポート番号\r\n */\r\n this.port = 50001;\r\n /**\r\n * 速度(-1:棒読みちゃん画面上の設定)\r\n */\r\n this.speed = 100;\r\n /**\r\n * 音程(-1:棒読みちゃん画面上の設定)\r\n */\r\n this.tone = 100;\r\n /**\r\n * 音量(-1:棒読みちゃん画面上の設定)\r\n */\r\n this.volume = 50;\r\n /**\r\n * 声質( 0:棒読みちゃん画面上の設定、1:女性1、2:女性2、3:男性1、4:男性2、5:中性、6:ロボット、7:機械1、8:機械2、10001~:SAPI5)\r\n */\r\n this.type = 0;\r\n if (!options)\r\n return;\r\n if (options.host)\r\n this.host = options.host;\r\n if (options.port)\r\n this.port = options.port;\r\n if (options.speed)\r\n this.speed = options.speed;\r\n if (options.tone)\r\n this.tone = options.tone;\r\n if (options.volume)\r\n this.volume = options.volume;\r\n if (options.type)\r\n this.type = options.type;\r\n }\r\n /**\r\n * @param message 棒読みちゃんに読み上げてもらう文章\r\n */\r\n BouyomiChan.prototype.speak = function (message) {\r\n /** 棒読みちゃんに送信する設定のバイト長 */\r\n var SETTINGS_BYTES_LENGTH = 15;\r\n var messageByteLength = Buffer.byteLength(message);\r\n var bufferLength = SETTINGS_BYTES_LENGTH + messageByteLength;\r\n var buff = Buffer.alloc(bufferLength);\r\n /** メッセージ読み上げコマンド */\r\n var COMMAND_TO_SPEAK = 1;\r\n var len = buff.writeUInt16LE(COMMAND_TO_SPEAK);\r\n len = buff.writeInt16LE(this.speed, len);\r\n len = buff.writeInt16LE(this.tone, len);\r\n len = buff.writeInt16LE(this.volume, len);\r\n len = buff.writeUInt16LE(this.type, len);\r\n /** 文字コード(0:UTF-8, 1:Unicode, 2:Shift-JIS) */\r\n var ENCODING = 0;\r\n len = buff.writeUInt8(ENCODING, len);\r\n len = buff.writeUInt32LE(messageByteLength, len);\r\n len = buff.write(message, len);\r\n var client = net_1.default.createConnection(this.port, this.host);\r\n client.write(buff);\r\n client.end();\r\n };\r\n return BouyomiChan;\r\n}());\r\nexports.default = BouyomiChan;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.electronEvent = {\r\n /** サーバー起動 */\r\n 'start-server': 'start-server',\r\n /** サーバー停止 */\r\n 'stop-server': 'stop-server',\r\n /** 棒読み再生 */\r\n 'play-tamiyasu': 'play-tamiyasu',\r\n /** レス着信音再生 */\r\n 'play-sound-start': 'play-sound-start',\r\n 'play-sound-end': 'play-sound-end',\r\n 'wait-yomiko-time': 'wait-yomiko-time',\r\n 'speaking-end': 'speaking-end',\r\n /** サーバー起動の返信 */\r\n 'start-server-reply': 'start-server-reply',\r\n};\r\n","\"use strict\";\r\nvar __assign = (this && this.__assign) || function () {\r\n __assign = Object.assign || function(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\r\n t[p] = s[p];\r\n }\r\n return t;\r\n };\r\n return __assign.apply(this, arguments);\r\n};\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar express_1 = __importDefault(require(\"express\"));\r\nvar body_parser_1 = __importDefault(require(\"body-parser\")); // jsonパーサ\r\nvar router = express_1.default.Router();\r\nvar electron_log_1 = __importDefault(require(\"electron-log\"));\r\nvar ReadIcons_1 = __importDefault(require(\"./ReadIcons\")); //アイコンファイル名取得\r\nvar readIcons = new ReadIcons_1.default();\r\nvar startServer_1 = require(\"./startServer\");\r\nvar readSitaraba_1 = __importDefault(require(\"./readBBS/readSitaraba\")); // したらば読み込み用モジュール\r\nvar Read5ch_1 = __importDefault(require(\"./readBBS/Read5ch\")); // 5ch互換板読み込み用モジュール\r\nvar sitaraba = new readSitaraba_1.default();\r\nvar read5ch = new Read5ch_1.default();\r\n// 掲示板読み込みモジュール、一度決定したら使いまわすためにグローバル宣言\r\nvar bbsModule = null;\r\n// リクエストのbodyをパース下りエンコードしたりするためのやつ\r\nrouter.use(body_parser_1.default.urlencoded({ extended: true }));\r\nrouter.use(body_parser_1.default.json());\r\n/**\r\n * ブラウザからの初期処理リクエスト\r\n */\r\nrouter.get('/', function (req, res, next) { return __awaiter(void 0, void 0, void 0, function () {\r\n var threadUrl, resNum, result, doms;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n threadUrl = globalThis.config.url;\r\n resNum = globalThis.config.resNumber ? Number(globalThis.config.resNumber) : NaN;\r\n res.header('Content-Type', 'application/json; charset=UTF-8');\r\n return [4 /*yield*/, getRes(threadUrl, resNum)];\r\n case 1:\r\n result = _a.sent();\r\n // 末尾のレス番号を保存\r\n if (result.length > 0 && result[result.length - 1].number) {\r\n globalThis.electron.threadNumber = Number(result[result.length - 1].number);\r\n }\r\n // 初回なのでキューを初期化\r\n globalThis.electron.commentQueueList = [];\r\n result.shift();\r\n doms = result.map(function (item) { return startServer_1.createDom(item); });\r\n res.send(JSON.stringify(doms));\r\n return [2 /*return*/];\r\n }\r\n });\r\n}); });\r\nexports.getResInterval = function () { return __awaiter(void 0, void 0, void 0, function () {\r\n var result;\r\n var _a;\r\n return __generator(this, function (_b) {\r\n switch (_b.label) {\r\n case 0:\r\n if (!(globalThis.electron.threadNumber > 0)) return [3 /*break*/, 2];\r\n return [4 /*yield*/, getRes(globalThis.config.url, globalThis.electron.threadNumber)];\r\n case 1:\r\n result = _b.sent();\r\n // 指定したレス番は除外対象\r\n result.shift();\r\n if (result.length > 0 && result[result.length - 1].number) {\r\n globalThis.electron.threadNumber = Number(result[result.length - 1].number);\r\n (_a = globalThis.electron.commentQueueList).push.apply(_a, result);\r\n }\r\n notifyThreadResLimit();\r\n _b.label = 2;\r\n case 2: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\n/**\r\n * 掲示板のレスを取得する\r\n * @param threadUrl スレのURL\r\n * @param resNum この番号以降を取得する\r\n */\r\nvar getRes = function (threadUrl, resNum) { return __awaiter(void 0, void 0, void 0, function () {\r\n var response, e_1;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n _a.trys.push([0, 2, , 3]);\r\n // リクエストURLを解析し、使用するモジュールを変更する\r\n bbsModule = analysBBSName(threadUrl);\r\n return [4 /*yield*/, bbsModule.read(threadUrl, resNum)];\r\n case 1:\r\n response = _a.sent();\r\n globalThis.electron.threadConnectionError = 0;\r\n console.log(\"[getRes.js] fetch res end resNum = \" + resNum + \", result = \" + response.length);\r\n return [2 /*return*/, response.map(function (res) {\r\n return __assign(__assign({}, res), { imgUrl: readIcons.getRandomIcons() });\r\n })];\r\n case 2:\r\n e_1 = _a.sent();\r\n electron_log_1.default.error(e_1);\r\n if (globalThis.config.notifyThreadConnectionErrorLimit > 0) {\r\n globalThis.electron.threadConnectionError += 1;\r\n if (globalThis.electron.threadConnectionError >= globalThis.config.notifyThreadConnectionErrorLimit) {\r\n globalThis.electron.threadConnectionError = 0;\r\n return [2 /*return*/, [\r\n {\r\n name: 'unacastより',\r\n imgUrl: './img/unacast.png',\r\n text: '掲示板が規定回数通信エラーになりました。設定を見直すか、掲示板URLを変更してください。',\r\n },\r\n ]];\r\n }\r\n }\r\n return [2 /*return*/, []];\r\n case 3: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\n/*\r\n * URLをみてどこのBBSか判定して使用するモジュールを返却する\r\n */\r\nvar analysBBSName = function (threadUrl) {\r\n // したらばドメイン名\r\n var sitarabaDomain = 'jbbs.shitaraba.net';\r\n // こんな感じで必要に応じて増やしていけばいいんじゃね?\r\n // const dokkanoBBS = 'dokka.bbs.com';\r\n if (threadUrl.indexOf(sitarabaDomain) !== -1) {\r\n // URLにしたらばドメイン名が入ってればしたらば\r\n return sitaraba;\r\n }\r\n // どこにも該当しなかったらとりあえず5chで\r\n // この辺も対応ドメインリストとか作ってちゃんと判定したほうがよさそう\r\n return read5ch;\r\n};\r\nvar notifyThreadResLimit = function () {\r\n if (globalThis.config.notifyThreadResLimit > 0 && globalThis.electron.threadNumber >= globalThis.config.notifyThreadResLimit) {\r\n globalThis.electron.commentQueueList.push({\r\n name: 'unacastより',\r\n imgUrl: './img/unacast.png',\r\n text: \"\\u30EC\\u30B9\\u304C\" + globalThis.config.notifyThreadResLimit + \"\\u3092\\u8D85\\u3048\\u307E\\u3057\\u305F\",\r\n });\r\n }\r\n};\r\nexports.default = router;\r\n","\"use strict\";\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n// Electronのモジュール\r\nvar path_1 = __importDefault(require(\"path\"));\r\nvar electron_1 = __importDefault(require(\"electron\"));\r\nvar electron_log_1 = __importDefault(require(\"electron-log\"));\r\nconsole.trace = function () {\r\n //\r\n};\r\nprocess.on('uncaughtException', function (err) {\r\n electron_log_1.default.error('electron:event:uncaughtException');\r\n electron_log_1.default.error(err);\r\n electron_log_1.default.error(err.stack);\r\n // app.quit();\r\n});\r\n// アプリケーションをコントロールするモジュール\r\nvar app = electron_1.default.app;\r\napp.allowRendererProcessReuse = true;\r\n// サーバー起動モジュール\r\n// eslint-disable-next-line @typescript-eslint/no-var-requires\r\nvar ss = require('./startServer');\r\nconsole.trace(ss);\r\n// ウィンドウを作成するモジュール\r\nvar BrowserWindow = electron_1.default.BrowserWindow;\r\n// メインウィンドウはGCされないようにグローバル宣言\r\nglobalThis.electron = {\r\n mainWindow: undefined,\r\n seList: [],\r\n twitchChat: undefined,\r\n youtubeChat: undefined,\r\n socket: null,\r\n threadConnectionError: 0,\r\n threadNumber: 0,\r\n commentQueueList: [],\r\n};\r\n// 全てのウィンドウが閉じたら終了\r\napp.on('window-all-closed', function () {\r\n if (process.platform != 'darwin') {\r\n app.quit();\r\n }\r\n});\r\n// Electronの初期化完了後に実行\r\napp.on('ready', function () {\r\n // ウィンドウサイズを1280*720(フレームサイズを含まない)に設定する\r\n globalThis.electron.mainWindow = new BrowserWindow({\r\n width: 700,\r\n height: 720,\r\n useContentSize: true,\r\n icon: __dirname + './../../icon.png',\r\n webPreferences: {\r\n nodeIntegration: true,\r\n },\r\n });\r\n globalThis.electron.mainWindow.setTitle('unacast');\r\n globalThis.electron.mainWindow.setMenu(null);\r\n //使用するhtmlファイルを指定する\r\n globalThis.electron.mainWindow.loadURL(path_1.default.resolve(__dirname, '../src/html/index.html'));\r\n // ウィンドウが閉じられたらアプリも終了\r\n globalThis.electron.mainWindow.on('closed', function () {\r\n globalThis.electron.mainWindow = undefined;\r\n });\r\n // 開発者ツールを開く\r\n // globalThis.electron.mainWindow.webContents.openDevTools();\r\n});\r\n// 音声再生できるようにする\r\napp.commandLine.appendSwitch('--autoplay-policy', 'no-user-gesture-required');\r\n","\"use strict\";\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n/**\r\n * 5ch互換BBS読み込み用モジュール\r\n */\r\nvar axios_1 = __importDefault(require(\"axios\"));\r\nvar iconv_lite_1 = __importDefault(require(\"iconv-lite\")); // 文字コード変換用パッケージ\r\nvar electron_log_1 = __importDefault(require(\"electron-log\"));\r\n// ステータスコード304 _NotModified\r\nvar NOT_MODIFIED = '304';\r\nvar RANGE_NOT_SATISFIABLE = '416';\r\n// 最終取得スレッド\r\nvar lastThreadUrl = '';\r\n// 最終レス番号\r\nvar lastResNumber = 0;\r\n//最終更新日時\r\nvar lastModified = null;\r\n// 最終バイト数\r\nvar lastByte = 0;\r\n/**\r\n * コンストラクタ\r\n *\r\n */\r\nvar Read5ch = /** @class */ (function () {\r\n function Read5ch() {\r\n var _this = this;\r\n // constructor() {}\r\n /**\r\n * レス読み込み\r\n * 引数で指定した板からレスを読む\r\n * レス番号を指定していない場合は最新1件取得\r\n * @param threadUrl スレURL\r\n * @param resNum レス番号\r\n */\r\n this.read = function (threadUrl, resNum) { return __awaiter(_this, void 0, void 0, function () {\r\n var rep, requestUrl, range, options, responseJson, response, headers, str, error_1;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n // log.info(`[Read5ch] threadUrl=${threadUrl} resNum=${resNum}`);\r\n // 板や最終日レス番号がかわったら最初からとり直す(lastmodifiと rangeのリセット)\r\n if (threadUrl != lastThreadUrl || Number.isNaN(resNum) || resNum < lastResNumber) {\r\n lastThreadUrl = threadUrl;\r\n lastModified = null;\r\n lastByte = 0;\r\n console.trace('[Read5ch.js]resete!!!!!!!!!!!!!!!!');\r\n }\r\n else {\r\n console.trace('noresete');\r\n }\r\n rep = /\\/test\\/read.cgi(\\/.+)(\\/.+)\\//;\r\n requestUrl = threadUrl.replace(rep, '$1/dat$2.dat');\r\n range = lastByte;\r\n options = {\r\n url: requestUrl,\r\n method: 'GET',\r\n timeout: 3 * 1000,\r\n responseType: 'arraybuffer',\r\n headers: {\r\n 'if-modified-since': lastModified,\r\n range: 'bytes=' + range + '-',\r\n },\r\n };\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, 3, , 4]);\r\n return [4 /*yield*/, axios_1.default(options)];\r\n case 2:\r\n response = _a.sent();\r\n headers = response.headers;\r\n // LastModifiedとRange更新処理\r\n if (headers['last-modified'] != null) {\r\n lastModified = headers['last-modified'];\r\n }\r\n str = iconv_lite_1.default.decode(Buffer.from(response.data), 'Shift_JIS');\r\n // レスポンスオブジェクト作成、content-rangeがある場合とない場合で処理を分ける\r\n if (headers['content-range'] == null || lastByte == 0) {\r\n console.trace('[Read5ch.read]content-range=' + headers['content-range']);\r\n responseJson = purseNewResponse(str, resNum);\r\n }\r\n else {\r\n responseJson = purseDiffResponse(str, resNum);\r\n }\r\n // 取得バイト数表示\r\n if (headers['content-length'] != null && responseJson.length > 0) {\r\n lastByte = lastByte + parseInt(headers['content-length']) - 1;\r\n console.trace('[Read5ch.read]lastByte=' + lastByte);\r\n }\r\n return [3 /*break*/, 4];\r\n case 3:\r\n error_1 = _a.sent();\r\n responseJson = [];\r\n if (error_1.status == NOT_MODIFIED) {\r\n electron_log_1.default.error('[Read5ch.js]5ch系BBSレス取得APIリクエストエラー、NOT_MODIFIED');\r\n }\r\n else if (error_1.status == RANGE_NOT_SATISFIABLE) {\r\n electron_log_1.default.error('[Read5ch.js]5ch系BBSレス取得APIリクエストエラー、RANGE_NOT_SATISFIABLE');\r\n }\r\n else {\r\n electron_log_1.default.error('[Read5ch.js]5ch系BBSレス取得APIリクエストエラー、message=' + error_1.message);\r\n }\r\n throw new Error('connection error');\r\n case 4: return [2 /*return*/, responseJson];\r\n }\r\n });\r\n }); };\r\n }\r\n return Read5ch;\r\n}());\r\n/**\r\n * 取得したレスポンス(複数)のパース\r\n * 戻りとしてパースしたjsonオブジェクトの配列を返す\r\n * @param res 板から返却されたdat\r\n * @param resNum リクエストされたレス番号\r\n */\r\nvar purseNewResponse = function (res, resNum) {\r\n // 結果を格納する配列\r\n var result = [];\r\n // レス番号\r\n var num = 0;\r\n // 新着レスを改行ごとにSplitする\r\n var resArray = res.split(/\\r\\n|\\r|\\n/);\r\n // 新着なしなら戻る。\r\n if (resArray.length === 0) {\r\n return result;\r\n }\r\n // 配列の最後に空の要素が入ることがあるので取り除く\r\n if (resArray[resArray.length - 1].length === 0) {\r\n resArray.pop();\r\n }\r\n // レス指定なしの場合最後の1件取得\r\n if (Number.isNaN(resNum)) {\r\n num = resArray.length - 1;\r\n }\r\n else {\r\n num = resNum - 1;\r\n }\r\n // 1行ごとにパースする\r\n for (; num < resArray.length; num++) {\r\n // パースメソッド呼び出し\r\n if (resArray[num].length > 0) {\r\n result.push(purseResponse(resArray[num], num + 1));\r\n }\r\n }\r\n lastResNumber = num + 1;\r\n // パースしたオブジェクトの配列を返却\r\n return result;\r\n};\r\n/**\r\n * 取得したレスポンス(複数)のパース\r\n * 戻りとしてパースしたjsonオブジェクトの配列を返す\r\n * @param res 板から返却されたdat1行分\r\n * @param resNum リクエストされたレス番号\r\n */\r\nvar purseDiffResponse = function (res, resNum) {\r\n //結果を格納する配列\r\n var result = [];\r\n // レス番号\r\n var num = resNum;\r\n //新着レスを改行ごとにSplitする\r\n var resArray = res.split(/\\r\\n|\\r|\\n/);\r\n // 新着なしなら戻る。\r\n if (resArray.length === 0) {\r\n return result;\r\n }\r\n else {\r\n // 配列の最後に空の要素が入ることがあるので取り除く\r\n if (resArray[resArray.length - 1].length == 0) {\r\n resArray.pop();\r\n }\r\n }\r\n console.trace('[Read5ch.purseDiffResponse]取得レス番号=' + num);\r\n //1行ごとにパースする\r\n resArray.forEach(function (value) {\r\n //パースメソッド呼び出し\r\n if (value.length > 0) {\r\n result.push(purseResponse(value, num));\r\n num++;\r\n }\r\n });\r\n // パースしたオブジェクトの配列を返却\r\n return result;\r\n};\r\n/**\r\n * レスポンスのパース\r\n * Jsonオブジェクトを返却する\r\n * @param String // res レスポンス1レス\r\n * @param Integer // num レス番(0スタート)\r\n */\r\nvar purseResponse = function (res, num) {\r\n //APIの返却値を<>で分割\r\n //レスの要素\r\n //0:名前\r\n //1:メアド\r\n //2:日付とID (2019/11/03(日) 08:55:00 ID:kanikani)みたいに表示\r\n //3:本文\r\n //4:スレタイ (1レス目のみ)\r\n var splitRes = res.split('<>');\r\n // 日付とID分離処理、' ID:'で区切る\r\n var dateId = splitRes[2].split(' ID:');\r\n var date = dateId[0];\r\n var id = dateId.length === 2 ? dateId[1] : '';\r\n var resJson = {\r\n number: num.toString(),\r\n name: splitRes[0],\r\n email: splitRes[1],\r\n date: date,\r\n text: splitRes[3],\r\n // threadTitle: splitRes[4],\r\n id: id,\r\n imgUrl: '',\r\n };\r\n // オブジェクトを返却\r\n return resJson;\r\n};\r\nexports.default = Read5ch;\r\n","\"use strict\";\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n/**\r\n * したらば読み込み用モジュール\r\n */\r\nvar axios_1 = __importDefault(require(\"axios\"));\r\nvar iconv_lite_1 = __importDefault(require(\"iconv-lite\")); // 文字コード変換用パッケージ\r\n/**\r\n * コンストラクタ\r\n */\r\nvar ReadSitaraba = /** @class */ (function () {\r\n function ReadSitaraba() {\r\n // constructor() {}\r\n var _this = this;\r\n /**\r\n * レス読み込み\r\n * @description 引数で指定した板からレスを読む。\r\n * @description レス番号を指定していない場合は最新1件取得\r\n * @param threadUrl スレURL\r\n * @param resNum レス番号\r\n */\r\n this.read = function (threadUrl, resNum) { return __awaiter(_this, void 0, void 0, function () {\r\n var requestUrl, options, response, str, responseJson;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n requestUrl = threadUrl.replace('read.cgi', 'rawmode.cgi');\r\n if (resNum > 0) {\r\n // レス番号がある場合レス番号以降を取得\r\n requestUrl += resNum + '-';\r\n }\r\n else {\r\n // レス番号がない場合最新の1件取得\r\n requestUrl += 'l1';\r\n }\r\n options = {\r\n url: requestUrl,\r\n method: 'GET',\r\n responseType: 'arraybuffer',\r\n timeout: 3 * 1000,\r\n };\r\n return [4 /*yield*/, axios_1.default(options)];\r\n case 1:\r\n response = _a.sent();\r\n str = iconv_lite_1.default.decode(Buffer.from(response.data), 'EUC-JP');\r\n responseJson = purseNewResponse(str);\r\n return [2 /*return*/, responseJson];\r\n }\r\n });\r\n }); };\r\n }\r\n return ReadSitaraba;\r\n}());\r\n/**\r\n * 取得したレスポンス(複数)のパース\r\n * @param res\r\n */\r\nvar purseNewResponse = function (res) {\r\n //結果を格納する配列\r\n var result = [];\r\n // 新着レスを改行ごとにSplitする\r\n var resArray = res.split(/\\r\\n|\\r|\\n/);\r\n // 1行ごとにパースする\r\n resArray.forEach(function (value) {\r\n // パースメソッド呼び出し\r\n if (value.length > 0) {\r\n result.push(purseResponse(value));\r\n }\r\n });\r\n return result;\r\n};\r\n/**\r\n * レスポンスのパース\r\n * Jsonオブジェクトを返却する\r\n * @param String // res レスポンス1レス\r\n */\r\nvar purseResponse = function (res) {\r\n //APIの返却値を<>で分割\r\n //レスの要素\r\n //0:レス番号\r\n //1:名前\r\n //2:メアド\r\n //3:日付\r\n //4:本文\r\n //5:スレタイ\r\n //6:ID\r\n var splitRes = res.split('<>');\r\n var resJson = {\r\n number: splitRes[0],\r\n name: splitRes[1],\r\n email: splitRes[2],\r\n date: splitRes[3],\r\n text: splitRes[4],\r\n // threadTitle: splitRes[5],\r\n id: splitRes[6],\r\n imgUrl: '',\r\n };\r\n // オブジェクトを返却\r\n return resJson;\r\n};\r\nexports.default = ReadSitaraba;\r\n","\"use strict\";\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nvar __spreadArrays = (this && this.__spreadArrays) || function () {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nvar __importStar = (this && this.__importStar) || function (mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result[\"default\"] = mod;\r\n return result;\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar path_1 = __importDefault(require(\"path\"));\r\nvar express_1 = __importDefault(require(\"express\"));\r\nvar electron_log_1 = __importDefault(require(\"electron-log\"));\r\nvar dank_twitch_irc_1 = require(\"dank-twitch-irc\");\r\nvar youtube_chat_1 = require(\"./youtube-chat\");\r\nvar electron_1 = require(\"electron\");\r\nvar express_ws_1 = __importDefault(require(\"express-ws\"));\r\nvar util_1 = require(\"./util\");\r\n// レス取得APIをセット\r\nvar getRes_1 = __importStar(require(\"./getRes\"));\r\nvar bouyomi_chan_1 = __importDefault(require(\"./bouyomi-chan\"));\r\nvar child_process_1 = require(\"child_process\");\r\nvar const_1 = require(\"./const\");\r\nvar app;\r\n// サーバーをグローバル変数にセットできるようにする(サーバー停止処理のため)\r\nvar server;\r\n/** 棒読みちゃんインスタンス */\r\nvar bouyomi;\r\n/** スレッド定期取得のイベント */\r\nvar threadIntervalEvent;\r\n/** キュー処理実行するか */\r\nvar isExecuteQue = false;\r\n/**\r\n * サーバー起動\r\n * config:設定を格納したjson、以下jsonの中身\r\n * url:掲示板URL\r\n * resNumber:読み込み開始レス位置\r\n * port:ポート番号\r\n */\r\nelectron_1.ipcMain.on(const_1.electronEvent['start-server'], function (event, config) { return __awaiter(void 0, void 0, void 0, function () {\r\n var list;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n app = express_ws_1.default(express_1.default()).app;\r\n app.set('view engine', 'ejs');\r\n // viewディレクトリの指定\r\n app.set('views', path_1.default.resolve(__dirname, '../views'));\r\n // 設定情報をグローバル変数へセットする\r\n globalThis.config = config;\r\n console.log('[startServer]設定値 = ');\r\n console.log(globalThis.config);\r\n app.get('/', function (req, res, next) {\r\n res.render('server', config);\r\n req.connection.end();\r\n });\r\n //静的コンテンツはpublicディレクトリの中身を使用するという宣言\r\n app.use(express_1.default.static(path_1.default.resolve(__dirname, '../public')));\r\n // 2ch互換掲示板の取得\r\n app.use('/getRes', getRes_1.default);\r\n if (!globalThis.config.playSe) return [3 /*break*/, 2];\r\n return [4 /*yield*/, util_1.readWavFiles(globalThis.config.sePath)];\r\n case 1:\r\n list = _a.sent();\r\n globalThis.electron.seList = list.map(function (file) { return globalThis.config.sePath + \"/\" + file; });\r\n console.log(\"SE files = \" + globalThis.electron.seList.length);\r\n _a.label = 2;\r\n case 2:\r\n // Twitchに接続\r\n if (globalThis.config.twitchId) {\r\n globalThis.electron.twitchChat = new dank_twitch_irc_1.ChatClient();\r\n globalThis.electron.twitchChat.connect();\r\n globalThis.electron.twitchChat.join(globalThis.config.twitchId);\r\n globalThis.electron.twitchChat.on('PRIVMSG', function (msg) {\r\n var imgUrl = './img/twitch.png';\r\n var name = msg.displayName;\r\n var text = msg.messageText;\r\n globalThis.electron.commentQueueList.push({ imgUrl: imgUrl, name: name, text: text });\r\n });\r\n }\r\n // Youtubeチャット\r\n if (globalThis.config.youtubeId) {\r\n try {\r\n console.log('[Youtube Chat] connect started');\r\n globalThis.electron.youtubeChat = new youtube_chat_1.LiveChat({ channelId: globalThis.config.youtubeId });\r\n // 接続開始イベント\r\n globalThis.electron.youtubeChat.on('start', function (liveId) {\r\n console.log(\"[Youtube Chat] connected liveId = \" + liveId);\r\n });\r\n // 接続終了イベント\r\n globalThis.electron.youtubeChat.on('end', function (reason) {\r\n console.log('[Youtube Chat] disconnect');\r\n });\r\n // チャット受信\r\n globalThis.electron.youtubeChat.on('comment', function (comment) {\r\n var _a, _b;\r\n var imgUrl = (_b = (_a = comment.author.thumbnail) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '';\r\n var name = comment.author.name;\r\n var text = comment.message[0].text;\r\n globalThis.electron.commentQueueList.push({ imgUrl: imgUrl, name: name, text: text });\r\n });\r\n // 何かエラーがあった\r\n globalThis.electron.youtubeChat.on('error', function (err) {\r\n electron_log_1.default.error('[Youtube Chat] error');\r\n electron_log_1.default.error(err);\r\n globalThis.electron.youtubeChat.stop();\r\n });\r\n globalThis.electron.youtubeChat.start();\r\n }\r\n catch (e) {\r\n process.exit(1);\r\n }\r\n }\r\n // 棒読みちゃん接続\r\n if (config.typeYomiko === 'bouyomi') {\r\n if (config.bouyomiPort) {\r\n bouyomi = new bouyomi_chan_1.default({ port: config.bouyomiPort, volume: config.bouyomiVolume });\r\n }\r\n }\r\n // レス取得定期実行\r\n threadIntervalEvent = setInterval(function () { return getRes_1.getResInterval(); }, globalThis.config.interval * 1000);\r\n // キュー処理の開始\r\n isExecuteQue = true;\r\n taskScheduler();\r\n // WebSocketを立てる\r\n app.ws('/ws', function (ws, req) {\r\n globalThis.electron.socket = ws;\r\n ws.on('message', function (message) {\r\n console.trace('Received: ' + message);\r\n if (message === 'ping') {\r\n ws.send('pong');\r\n }\r\n });\r\n ws.on('close', function () {\r\n console.log('I lost a client');\r\n });\r\n });\r\n // 指定したポートで待ち受け開始\r\n server = app.listen(config.port, function () {\r\n console.log('[startServer] start server on port:' + config.port);\r\n });\r\n // 成功メッセージ返却\r\n event.returnValue = 'success';\r\n return [2 /*return*/];\r\n }\r\n });\r\n}); });\r\n/**\r\n * サーバー停止\r\n */\r\nelectron_1.ipcMain.on(const_1.electronEvent['stop-server'], function (event) {\r\n console.log('[startServer]server stop');\r\n server.close();\r\n app = null;\r\n event.returnValue = 'stop';\r\n // キュー処理停止\r\n isExecuteQue = false;\r\n globalThis.electron.commentQueueList = [];\r\n // Twitchチャットの停止\r\n if (globalThis.electron.twitchChat) {\r\n globalThis.electron.twitchChat.close();\r\n globalThis.electron.twitchChat.removeAllListeners();\r\n }\r\n // Youtubeチャットの停止\r\n if (globalThis.electron.youtubeChat) {\r\n globalThis.electron.youtubeChat.stop();\r\n globalThis.electron.youtubeChat.removeAllListeners();\r\n }\r\n // レス取得の停止\r\n if (threadIntervalEvent) {\r\n clearInterval(threadIntervalEvent);\r\n }\r\n});\r\n/**\r\n * キューに溜まったコメントを処理する\r\n */\r\nvar taskScheduler = function () { return __awaiter(void 0, void 0, void 0, function () {\r\n var temp, comment;\r\n var _a, _b;\r\n return __generator(this, function (_c) {\r\n switch (_c.label) {\r\n case 0:\r\n if (!(((_b = (_a = globalThis.electron) === null || _a === void 0 ? void 0 : _a.commentQueueList) === null || _b === void 0 ? void 0 : _b.length) > 0)) return [3 /*break*/, 3];\r\n if (!(globalThis.config.commentProcessType === 0)) return [3 /*break*/, 1];\r\n temp = __spreadArrays(globalThis.electron.commentQueueList);\r\n globalThis.electron.commentQueueList = [];\r\n sendDom(temp);\r\n return [3 /*break*/, 3];\r\n case 1:\r\n comment = globalThis.electron.commentQueueList.shift();\r\n return [4 /*yield*/, sendDom([comment])];\r\n case 2:\r\n _c.sent();\r\n _c.label = 3;\r\n case 3:\r\n if (!isExecuteQue) return [3 /*break*/, 5];\r\n return [4 /*yield*/, util_1.sleep(100)];\r\n case 4:\r\n _c.sent();\r\n taskScheduler();\r\n _c.label = 5;\r\n case 5: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\n/** 読み子によって発話中であるか */\r\nvar isSpeaking = false;\r\n/** 読み子を再生する */\r\nvar playYomiko = function (msg) { return __awaiter(void 0, void 0, void 0, function () {\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n // log.info('[playYomiko] start');\r\n isSpeaking = true;\r\n // 読み子呼び出し\r\n switch (config.typeYomiko) {\r\n case 'tamiyasu': {\r\n child_process_1.exec(config.tamiyasuPath + \" \" + msg);\r\n break;\r\n }\r\n case 'bouyomi': {\r\n if (bouyomi)\r\n bouyomi.speak(msg);\r\n break;\r\n }\r\n }\r\n // 読み子が読んでる時間分相当待つ\r\n globalThis.electron.mainWindow.webContents.send(const_1.electronEvent['wait-yomiko-time'], msg);\r\n _a.label = 1;\r\n case 1:\r\n if (!isSpeaking) return [3 /*break*/, 3];\r\n return [4 /*yield*/, util_1.sleep(50)];\r\n case 2:\r\n _a.sent();\r\n return [3 /*break*/, 1];\r\n case 3: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\nelectron_1.ipcMain.on(const_1.electronEvent['speaking-end'], function (event) { return (isSpeaking = false); });\r\nvar isPlayingSe = false;\r\nvar playSe = function () { return __awaiter(void 0, void 0, void 0, function () {\r\n var wavfilepath;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n wavfilepath = globalThis.electron.seList[Math.floor(Math.random() * globalThis.electron.seList.length)];\r\n isPlayingSe = true;\r\n globalThis.electron.mainWindow.webContents.send(const_1.electronEvent['play-sound-start'], wavfilepath);\r\n _a.label = 1;\r\n case 1:\r\n if (!isPlayingSe) return [3 /*break*/, 3];\r\n return [4 /*yield*/, util_1.sleep(50)];\r\n case 2:\r\n _a.sent();\r\n return [3 /*break*/, 1];\r\n case 3: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\nelectron_1.ipcMain.on(const_1.electronEvent['play-sound-end'], function (event) { return (isPlayingSe = false); });\r\nexports.createDom = function (message) {\r\n var domStr = \"\\n
  • \\n \\n \\n \\n
    \";\r\n //レス番表示\r\n if (globalThis.config.showNumber) {\r\n domStr += \"\\n \" + message.number + \"\\n \";\r\n }\r\n // 名前表示\r\n if (globalThis.config.showName) {\r\n domStr += \"\" + message.name + \"\";\r\n }\r\n // 時刻表示\r\n if (globalThis.config.showTime) {\r\n domStr += \"\" + message.date + \"\";\r\n }\r\n // 名前と本文を改行で分ける\r\n if (globalThis.config.newLine) {\r\n domStr += '
    ';\r\n }\r\n domStr += \"\\n \\n \" + message.text + \"\\n \\n
    \\n
  • \";\r\n return domStr;\r\n};\r\n/**\r\n * コメントのDOMをブラウザに送る\r\n * 必要ならレス着信音も鳴らす\r\n * @param message\r\n */\r\nvar sendDom = function (messageList) { return __awaiter(void 0, void 0, void 0, function () {\r\n var domStr;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n domStr = messageList.map(function (message) { return exports.createDom(message); }).join('\\n');\r\n if (globalThis.electron.socket)\r\n globalThis.electron.socket.send(domStr);\r\n if (!(config.playSe && globalThis.electron.seList.length > 0)) return [3 /*break*/, 2];\r\n return [4 /*yield*/, playSe()];\r\n case 1:\r\n _a.sent();\r\n _a.label = 2;\r\n case 2:\r\n if (!(globalThis.config.typeYomiko !== 'none')) return [3 /*break*/, 4];\r\n return [4 /*yield*/, playYomiko(messageList[messageList.length - 1].text)];\r\n case 3:\r\n _a.sent();\r\n _a.label = 4;\r\n case 4: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\nexports.default = {};\r\n","\"use strict\";\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar fs_1 = __importDefault(require(\"fs\"));\r\nexports.readWavFiles = function (path) {\r\n return new Promise(function (resolve, reject) {\r\n fs_1.default.readdir(path, function (err, files) {\r\n if (err)\r\n reject(err);\r\n var fileList = files.filter(function (file) {\r\n return isExistFile(path + '/' + file) && /.*\\.wav$/.test(file); //絞り込み\r\n });\r\n resolve(fileList);\r\n });\r\n });\r\n};\r\nvar isExistFile = function (file) {\r\n try {\r\n fs_1.default.statSync(file).isFile();\r\n return true;\r\n }\r\n catch (err) {\r\n if (err.code === 'ENOENT')\r\n return false;\r\n }\r\n};\r\nexports.sleep = function (msec) { return new Promise(function (resolve) { return setTimeout(resolve, msec); }); };\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar live_chat_1 = require(\"./live-chat\");\r\nexports.LiveChat = live_chat_1.LiveChat;\r\n","\"use strict\";\r\nvar __extends = (this && this.__extends) || (function () {\r\n var extendStatics = function (d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar events_1 = require(\"events\");\r\nvar axios_1 = __importDefault(require(\"axios\"));\r\nvar parser_1 = require(\"./parser\");\r\n/**\r\n * YouTubeライブチャット取得イベント\r\n */\r\nvar LiveChat = /** @class */ (function (_super) {\r\n __extends(LiveChat, _super);\r\n function LiveChat(options, interval) {\r\n if (interval === void 0) { interval = 1000; }\r\n var _this = _super.call(this) || this;\r\n _this.interval = interval;\r\n _this.prevTime = Date.now();\r\n if ('channelId' in options) {\r\n _this.channelId = options.channelId;\r\n }\r\n else if ('liveId' in options) {\r\n _this.liveId = options.liveId;\r\n }\r\n else {\r\n throw TypeError('Required channelId or liveId.');\r\n }\r\n return _this;\r\n }\r\n LiveChat.prototype.start = function () {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var url, liveRes, e_1;\r\n var _this = this;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!this.channelId) return [3 /*break*/, 4];\r\n url = \"https://www.youtube.com/channel/\" + this.channelId + \"/live\";\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, 3, , 4]);\r\n return [4 /*yield*/, axios_1.default.get(url, { headers: LiveChat.headers })];\r\n case 2:\r\n liveRes = _a.sent();\r\n // if (liveRes.data.match(/LIVE_STREAM_OFFLINE/)) {\r\n // this.emit('error', new Error('Live stream offline'));\r\n // return false;\r\n // }\r\n this.liveId = liveRes.data.match(/videoId\\\\\":\\\\\"(.+?)\\\\/)[1];\r\n return [3 /*break*/, 4];\r\n case 3:\r\n e_1 = _a.sent();\r\n this.emit('error', new Error(\"connection error url = \" + url));\r\n return [2 /*return*/, false];\r\n case 4:\r\n if (!this.liveId) {\r\n this.emit('error', new Error('Live stream not found'));\r\n return [2 /*return*/, false];\r\n }\r\n // console.log(`liveId = ${this.liveId}`);\r\n this.observer = setInterval(function () { return _this.fetchChat(); }, this.interval);\r\n this.emit('start', this.liveId);\r\n return [2 /*return*/, true];\r\n }\r\n });\r\n });\r\n };\r\n LiveChat.prototype.stop = function (reason) {\r\n if (this.observer) {\r\n clearInterval(this.observer);\r\n this.emit('end', reason);\r\n }\r\n };\r\n LiveChat.prototype.fetchChat = function () {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var url, res, items, item, e_2;\r\n var _this = this;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n url = \"https://www.youtube.com/live_chat?v=\" + this.liveId + \"&pbj=1\";\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, 3, , 4]);\r\n return [4 /*yield*/, axios_1.default.get(url, { headers: LiveChat.headers })];\r\n case 2:\r\n res = _a.sent();\r\n items = res.data[1].response.contents.liveChatRenderer.actions\r\n .slice(0, -1)\r\n .filter(function (v) {\r\n var messageRenderer = parser_1.actionToRenderer(v);\r\n if (messageRenderer !== null) {\r\n if (messageRenderer) {\r\n return parser_1.usecToTime(messageRenderer.timestampUsec) > _this.prevTime;\r\n }\r\n }\r\n return false;\r\n })\r\n .map(function (v) { return parser_1.parseData(v); });\r\n items.forEach(function (v) {\r\n if (v) {\r\n _this.emit('comment', v);\r\n }\r\n });\r\n if (items.length > 0) {\r\n item = items[items.length - 1];\r\n if (item)\r\n this.prevTime = item.timestamp;\r\n }\r\n return [3 /*break*/, 4];\r\n case 3:\r\n e_2 = _a.sent();\r\n this.emit('error', new Error(\"Error occured at fetchchat url=\" + url));\r\n return [3 /*break*/, 4];\r\n case 4: return [2 /*return*/];\r\n }\r\n });\r\n });\r\n };\r\n LiveChat.prototype.on = function (event, listener) {\r\n return _super.prototype.on.call(this, event, listener);\r\n };\r\n LiveChat.headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36' };\r\n return LiveChat;\r\n}(events_1.EventEmitter));\r\nexports.LiveChat = LiveChat;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar parseThumbnailToImageItem = function (data, alt) {\r\n var thumbnail = data.pop();\r\n if (thumbnail) {\r\n return {\r\n url: thumbnail.url,\r\n width: thumbnail.width,\r\n height: thumbnail.height,\r\n alt: alt,\r\n };\r\n }\r\n return;\r\n};\r\nvar parseEmojiToImageItem = function (data) {\r\n return parseThumbnailToImageItem(data.emoji.image.thumbnails, data.emoji.shortcuts.shift());\r\n};\r\nvar parseMessages = function (runs) {\r\n return runs.map(function (run) {\r\n if ('text' in run) {\r\n return run;\r\n }\r\n else {\r\n return parseEmojiToImageItem(run);\r\n }\r\n });\r\n};\r\nexports.actionToRenderer = function (action) {\r\n if (!action.addChatItemAction) {\r\n return null;\r\n }\r\n var item = action.addChatItemAction.item;\r\n if (item.liveChatTextMessageRenderer) {\r\n return item.liveChatTextMessageRenderer;\r\n }\r\n else if (item.liveChatPaidMessageRenderer) {\r\n return item.liveChatPaidMessageRenderer;\r\n }\r\n else if (item.liveChatPaidStickerRenderer) {\r\n return item.liveChatPaidStickerRenderer;\r\n }\r\n else {\r\n return item.liveChatMembershipItemRenderer;\r\n }\r\n};\r\nexports.usecToTime = function (usec) {\r\n return Math.floor(Number(usec) / 1000);\r\n};\r\nexports.parseData = function (data) {\r\n var messageRenderer = exports.actionToRenderer(data);\r\n if (messageRenderer === null) {\r\n return null;\r\n }\r\n var message = [];\r\n if ('message' in messageRenderer) {\r\n message = messageRenderer.message.runs;\r\n }\r\n else if ('headerSubtext' in messageRenderer) {\r\n message = messageRenderer.headerSubtext.runs;\r\n }\r\n var ret = {\r\n id: messageRenderer.id,\r\n author: {\r\n name: messageRenderer.authorName.simpleText,\r\n thumbnail: parseThumbnailToImageItem(messageRenderer.authorPhoto.thumbnails, messageRenderer.authorName.simpleText),\r\n channelId: messageRenderer.authorExternalChannelId,\r\n },\r\n message: parseMessages(message),\r\n membership: Boolean('headerSubtext' in messageRenderer),\r\n isOwner: false,\r\n timestamp: exports.usecToTime(messageRenderer.timestampUsec),\r\n };\r\n if (messageRenderer.authorBadges) {\r\n var badge = messageRenderer.authorBadges[0].liveChatAuthorBadgeRenderer;\r\n if (badge.customThumbnail) {\r\n ret.author.badge = {\r\n thumbnail: parseThumbnailToImageItem(badge.customThumbnail.thumbnails, badge.tooltip),\r\n label: badge.tooltip,\r\n };\r\n }\r\n else {\r\n ret.isOwner = true;\r\n }\r\n }\r\n if ('sticker' in messageRenderer) {\r\n ret.superchat = {\r\n amount: messageRenderer.purchaseAmountText.simpleText,\r\n color: messageRenderer.backgroundColor,\r\n sticker: parseThumbnailToImageItem(messageRenderer.sticker.thumbnails, messageRenderer.sticker.accessibility.accessibilityData.label),\r\n };\r\n }\r\n else if ('purchaseAmountText' in messageRenderer) {\r\n ret.superchat = {\r\n amount: messageRenderer.purchaseAmountText.simpleText,\r\n color: messageRenderer.bodyBackgroundColor,\r\n };\r\n }\r\n return ret;\r\n};\r\n"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AClFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AClFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC1EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACxLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC9PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC3IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC5BA;AACA;AACA;AACA;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;A","sourceRoot":""} \ No newline at end of file +{"version":3,"file":"index.js","sources":["webpack:///webpack/bootstrap","webpack:///./src/main/ReadIcons.ts","webpack:///./src/main/bouyomi-chan/index.ts","webpack:///./src/main/const.ts","webpack:///./src/main/getRes.ts","webpack:///./src/main/main.ts","webpack:///./src/main/readBBS/Read5ch.ts","webpack:///./src/main/readBBS/readSitaraba.ts","webpack:///./src/main/startServer.ts","webpack:///./src/main/util.ts","webpack:///./src/main/youtube-chat/index.ts","webpack:///./src/main/youtube-chat/live-chat.ts","webpack:///./src/main/youtube-chat/parser.ts"],"sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/main/main.ts\");\n","\"use strict\";\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n/**\r\n * アイコン表示に関するモジュール\r\n * シングルトン\r\n */\r\nvar fs_1 = __importDefault(require(\"fs\"));\r\nvar path_1 = __importDefault(require(\"path\"));\r\nvar electron_log_1 = __importDefault(require(\"electron-log\"));\r\nvar randomIconList;\r\nvar idIconList;\r\n/**\r\n * コンストラクタ\r\n * ・ランダムフォルダからアイコン名を取得してリスト化\r\n * ・IDフォルダからもリスト化、空の対応マップ作製\r\n * ・コテハン対応ファイルを読みこんでmapに格納\r\n */\r\nvar ReadIcons = /** @class */ (function () {\r\n function ReadIcons() {\r\n /**\r\n * アイコンランダム表示機能(デフォルト)\r\n * 起動時に作成したアイコンリストからランダムで1つ取得\r\n */\r\n this.getRandomIcons = function () {\r\n var iconPath = '';\r\n try {\r\n var dirName = './img/random/';\r\n // リストからランダム取得\r\n // const size = randomIconList.size;\r\n var num = Math.floor(randomIconList.length * Math.random());\r\n iconPath = dirName + randomIconList[num];\r\n }\r\n catch (e) {\r\n electron_log_1.default.error(e);\r\n }\r\n return iconPath;\r\n };\r\n //画像ディレクトリ\r\n var randomDir = path_1.default.resolve(__dirname, \"../public/img/random/\");\r\n console.debug('[ReadIcons]loadRandomDir = ' + randomDir);\r\n // ランダムアイコン取得\r\n randomIconList = readDir(randomDir);\r\n //ID用アイコンディレクトリ\r\n var idDir = path_1.default.resolve(__dirname, \"../public/img/id/\");\r\n console.debug('[ReadIcons]loadIDDir = ' + idDir);\r\n // ランダムアイコン取得\r\n idIconList = readDir(idDir);\r\n }\r\n return ReadIcons;\r\n}());\r\nvar readDir = function (imgDir) {\r\n var iconFileList = [];\r\n // 指定したディレクトリのアイコン取得\r\n var files = fs_1.default.readdirSync(imgDir, { withFileTypes: true });\r\n //pngファイルのみ返却リストに格納する\r\n files.forEach(function (file) {\r\n // asar圧縮するとfileが文字列になる。開発環境だとfileオブジェクトになる\r\n var target = typeof file.name !== 'string' ? file : file.name;\r\n var regx = /.*\\.png$/.test(target);\r\n if (regx) {\r\n iconFileList.push(target);\r\n }\r\n });\r\n // console.log('[ReadIcons.readDir]end');\r\n // console.log(JSON.stringify(iconFileList));\r\n return iconFileList;\r\n};\r\n/**\r\n * IDによるアイコン固定機能(オプションでON,OFF可能)\r\n * 初出のIDならばランダムでアイコンを取得し\r\n * IDとファイル名のセットでマップに格納\r\n * @param string // ID\r\n * @return string filename\r\n */\r\n/**\r\n * コテハンリスト機能(オプションでON,OFF可能)\r\n * koteフォルダの下にkotehan.jsonを作って\r\n * 名前とアイコンファイル名の対応をマップにして返すだけ\r\n */\r\nexports.default = ReadIcons;\r\n","\"use strict\";\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar net_1 = __importDefault(require(\"net\"));\r\nvar BouyomiChan = /** @class */ (function () {\r\n function BouyomiChan(options) {\r\n /**\r\n * 棒読みちゃんのホスト\r\n */\r\n this.host = 'localhost';\r\n /**\r\n * 棒読みちゃんのポート番号\r\n */\r\n this.port = 50001;\r\n /**\r\n * 速度(-1:棒読みちゃん画面上の設定)\r\n */\r\n this.speed = 100;\r\n /**\r\n * 音程(-1:棒読みちゃん画面上の設定)\r\n */\r\n this.tone = 100;\r\n /**\r\n * 音量(-1:棒読みちゃん画面上の設定)\r\n */\r\n this.volume = 50;\r\n /**\r\n * 声質( 0:棒読みちゃん画面上の設定、1:女性1、2:女性2、3:男性1、4:男性2、5:中性、6:ロボット、7:機械1、8:機械2、10001~:SAPI5)\r\n */\r\n this.type = 0;\r\n if (!options)\r\n return;\r\n if (options.host)\r\n this.host = options.host;\r\n if (options.port)\r\n this.port = options.port;\r\n if (options.speed)\r\n this.speed = options.speed;\r\n if (options.tone)\r\n this.tone = options.tone;\r\n if (options.volume)\r\n this.volume = options.volume;\r\n if (options.type)\r\n this.type = options.type;\r\n }\r\n /**\r\n * @param message 棒読みちゃんに読み上げてもらう文章\r\n */\r\n BouyomiChan.prototype.speak = function (message) {\r\n /** 棒読みちゃんに送信する設定のバイト長 */\r\n var SETTINGS_BYTES_LENGTH = 15;\r\n var messageByteLength = Buffer.byteLength(message);\r\n var bufferLength = SETTINGS_BYTES_LENGTH + messageByteLength;\r\n var buff = Buffer.alloc(bufferLength);\r\n /** メッセージ読み上げコマンド */\r\n var COMMAND_TO_SPEAK = 1;\r\n var len = buff.writeUInt16LE(COMMAND_TO_SPEAK);\r\n len = buff.writeInt16LE(this.speed, len);\r\n len = buff.writeInt16LE(this.tone, len);\r\n len = buff.writeInt16LE(this.volume, len);\r\n len = buff.writeUInt16LE(this.type, len);\r\n /** 文字コード(0:UTF-8, 1:Unicode, 2:Shift-JIS) */\r\n var ENCODING = 0;\r\n len = buff.writeUInt8(ENCODING, len);\r\n len = buff.writeUInt32LE(messageByteLength, len);\r\n len = buff.write(message, len);\r\n var client = net_1.default.createConnection(this.port, this.host);\r\n client.write(buff);\r\n client.end();\r\n };\r\n return BouyomiChan;\r\n}());\r\nexports.default = BouyomiChan;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.electronEvent = {\r\n /** サーバー起動 */\r\n 'start-server': 'start-server',\r\n /** サーバー停止 */\r\n 'stop-server': 'stop-server',\r\n /** 棒読み再生 */\r\n 'play-tamiyasu': 'play-tamiyasu',\r\n /** レス着信音再生 */\r\n 'play-sound-start': 'play-sound-start',\r\n 'play-sound-end': 'play-sound-end',\r\n 'wait-yomiko-time': 'wait-yomiko-time',\r\n 'speaking-end': 'speaking-end',\r\n /** サーバー起動の返信 */\r\n 'start-server-reply': 'start-server-reply',\r\n};\r\n","\"use strict\";\r\nvar __assign = (this && this.__assign) || function () {\r\n __assign = Object.assign || function(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\r\n t[p] = s[p];\r\n }\r\n return t;\r\n };\r\n return __assign.apply(this, arguments);\r\n};\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar express_1 = __importDefault(require(\"express\"));\r\nvar body_parser_1 = __importDefault(require(\"body-parser\")); // jsonパーサ\r\nvar router = express_1.default.Router();\r\nvar electron_log_1 = __importDefault(require(\"electron-log\"));\r\nvar ReadIcons_1 = __importDefault(require(\"./ReadIcons\")); //アイコンファイル名取得\r\nvar readIcons = new ReadIcons_1.default();\r\nvar startServer_1 = require(\"./startServer\");\r\nvar readSitaraba_1 = __importDefault(require(\"./readBBS/readSitaraba\")); // したらば読み込み用モジュール\r\nvar Read5ch_1 = __importDefault(require(\"./readBBS/Read5ch\")); // 5ch互換板読み込み用モジュール\r\nvar sitaraba = new readSitaraba_1.default();\r\nvar read5ch = new Read5ch_1.default();\r\n// 掲示板読み込みモジュール、一度決定したら使いまわすためにグローバル宣言\r\nvar bbsModule = null;\r\n// リクエストのbodyをパース下りエンコードしたりするためのやつ\r\nrouter.use(body_parser_1.default.urlencoded({ extended: true }));\r\nrouter.use(body_parser_1.default.json());\r\n/**\r\n * ブラウザからの初期処理リクエスト\r\n */\r\nrouter.get('/', function (req, res, next) { return __awaiter(void 0, void 0, void 0, function () {\r\n var threadUrl, resNum, result, doms;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n threadUrl = globalThis.config.url;\r\n resNum = globalThis.config.resNumber ? Number(globalThis.config.resNumber) : NaN;\r\n res.header('Content-Type', 'application/json; charset=UTF-8');\r\n return [4 /*yield*/, getRes(threadUrl, resNum)];\r\n case 1:\r\n result = _a.sent();\r\n // 末尾のレス番号を保存\r\n if (result.length > 0 && result[result.length - 1].number) {\r\n globalThis.electron.threadNumber = Number(result[result.length - 1].number);\r\n }\r\n // 初回なのでキューを初期化\r\n globalThis.electron.commentQueueList = [];\r\n result.shift();\r\n doms = result.map(function (item) { return startServer_1.createDom(item); });\r\n res.send(JSON.stringify(doms));\r\n return [2 /*return*/];\r\n }\r\n });\r\n}); });\r\nexports.getResInterval = function () { return __awaiter(void 0, void 0, void 0, function () {\r\n var result;\r\n var _a;\r\n return __generator(this, function (_b) {\r\n switch (_b.label) {\r\n case 0:\r\n if (!(globalThis.electron.threadNumber > 0)) return [3 /*break*/, 2];\r\n return [4 /*yield*/, getRes(globalThis.config.url, globalThis.electron.threadNumber)];\r\n case 1:\r\n result = _b.sent();\r\n // 指定したレス番は除外対象\r\n result.shift();\r\n if (result.length > 0 && result[result.length - 1].number) {\r\n globalThis.electron.threadNumber = Number(result[result.length - 1].number);\r\n (_a = globalThis.electron.commentQueueList).push.apply(_a, result);\r\n }\r\n notifyThreadResLimit();\r\n _b.label = 2;\r\n case 2: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\n/**\r\n * 掲示板のレスを取得する\r\n * @param threadUrl スレのURL\r\n * @param resNum この番号以降を取得する\r\n */\r\nvar getRes = function (threadUrl, resNum) { return __awaiter(void 0, void 0, void 0, function () {\r\n var response, e_1;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n _a.trys.push([0, 2, , 3]);\r\n // リクエストURLを解析し、使用するモジュールを変更する\r\n bbsModule = analysBBSName(threadUrl);\r\n return [4 /*yield*/, bbsModule.read(threadUrl, resNum)];\r\n case 1:\r\n response = _a.sent();\r\n globalThis.electron.threadConnectionError = 0;\r\n console.log(\"[getRes.js] fetch res end resNum = \" + resNum + \", result = \" + response.length);\r\n return [2 /*return*/, response.map(function (res) {\r\n return __assign(__assign({}, res), { imgUrl: readIcons.getRandomIcons() });\r\n })];\r\n case 2:\r\n e_1 = _a.sent();\r\n electron_log_1.default.error(e_1);\r\n if (globalThis.config.notifyThreadConnectionErrorLimit > 0) {\r\n globalThis.electron.threadConnectionError += 1;\r\n if (globalThis.electron.threadConnectionError >= globalThis.config.notifyThreadConnectionErrorLimit) {\r\n globalThis.electron.threadConnectionError = 0;\r\n return [2 /*return*/, [\r\n {\r\n name: 'unacastより',\r\n imgUrl: './img/unacast.png',\r\n text: '掲示板が規定回数通信エラーになりました。設定を見直すか、掲示板URLを変更してください。',\r\n },\r\n ]];\r\n }\r\n }\r\n return [2 /*return*/, []];\r\n case 3: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\n/*\r\n * URLをみてどこのBBSか判定して使用するモジュールを返却する\r\n */\r\nvar analysBBSName = function (threadUrl) {\r\n // したらばドメイン名\r\n var sitarabaDomain = 'jbbs.shitaraba.net';\r\n // こんな感じで必要に応じて増やしていけばいいんじゃね?\r\n // const dokkanoBBS = 'dokka.bbs.com';\r\n if (threadUrl.indexOf(sitarabaDomain) !== -1) {\r\n // URLにしたらばドメイン名が入ってればしたらば\r\n return sitaraba;\r\n }\r\n // どこにも該当しなかったらとりあえず5chで\r\n // この辺も対応ドメインリストとか作ってちゃんと判定したほうがよさそう\r\n return read5ch;\r\n};\r\nvar notifyThreadResLimit = function () {\r\n if (globalThis.config.notifyThreadResLimit > 0 && globalThis.electron.threadNumber >= globalThis.config.notifyThreadResLimit) {\r\n globalThis.electron.commentQueueList.push({\r\n name: 'unacastより',\r\n imgUrl: './img/unacast.png',\r\n text: \"\\u30EC\\u30B9\\u304C\" + globalThis.config.notifyThreadResLimit + \"\\u3092\\u8D85\\u3048\\u307E\\u3057\\u305F\",\r\n });\r\n }\r\n};\r\nexports.default = router;\r\n","\"use strict\";\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n// Electronのモジュール\r\nvar path_1 = __importDefault(require(\"path\"));\r\nvar electron_1 = __importDefault(require(\"electron\"));\r\nvar electron_log_1 = __importDefault(require(\"electron-log\"));\r\nconsole.trace = function () {\r\n //\r\n};\r\nprocess.on('uncaughtException', function (err) {\r\n electron_log_1.default.error('electron:event:uncaughtException');\r\n electron_log_1.default.error(err);\r\n electron_log_1.default.error(err.stack);\r\n // app.quit();\r\n});\r\n// アプリケーションをコントロールするモジュール\r\nvar app = electron_1.default.app;\r\napp.allowRendererProcessReuse = true;\r\n// サーバー起動モジュール\r\n// eslint-disable-next-line @typescript-eslint/no-var-requires\r\nvar ss = require('./startServer');\r\nconsole.trace(ss);\r\n// ウィンドウを作成するモジュール\r\nvar BrowserWindow = electron_1.default.BrowserWindow;\r\n// メインウィンドウはGCされないようにグローバル宣言\r\nglobalThis.electron = {\r\n mainWindow: undefined,\r\n seList: [],\r\n twitchChat: undefined,\r\n youtubeChat: undefined,\r\n socket: null,\r\n threadConnectionError: 0,\r\n threadNumber: 0,\r\n commentQueueList: [],\r\n};\r\n// 全てのウィンドウが閉じたら終了\r\napp.on('window-all-closed', function () {\r\n if (process.platform != 'darwin') {\r\n app.quit();\r\n }\r\n});\r\n// Electronの初期化完了後に実行\r\napp.on('ready', function () {\r\n // ウィンドウサイズを1280*720(フレームサイズを含まない)に設定する\r\n globalThis.electron.mainWindow = new BrowserWindow({\r\n width: 700,\r\n height: 720,\r\n useContentSize: true,\r\n icon: __dirname + './../../icon.png',\r\n webPreferences: {\r\n nodeIntegration: true,\r\n },\r\n });\r\n globalThis.electron.mainWindow.setTitle('unacast');\r\n globalThis.electron.mainWindow.setMenu(null);\r\n //使用するhtmlファイルを指定する\r\n globalThis.electron.mainWindow.loadURL(path_1.default.resolve(__dirname, '../src/html/index.html'));\r\n // ウィンドウが閉じられたらアプリも終了\r\n globalThis.electron.mainWindow.on('closed', function () {\r\n globalThis.electron.mainWindow = undefined;\r\n });\r\n // 開発者ツールを開く\r\n // globalThis.electron.mainWindow.webContents.openDevTools();\r\n});\r\n// 音声再生できるようにする\r\napp.commandLine.appendSwitch('--autoplay-policy', 'no-user-gesture-required');\r\n","\"use strict\";\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n/**\r\n * 5ch互換BBS読み込み用モジュール\r\n */\r\nvar axios_1 = __importDefault(require(\"axios\"));\r\nvar iconv_lite_1 = __importDefault(require(\"iconv-lite\")); // 文字コード変換用パッケージ\r\nvar electron_log_1 = __importDefault(require(\"electron-log\"));\r\n// ステータスコード304 _NotModified\r\nvar NOT_MODIFIED = '304';\r\nvar RANGE_NOT_SATISFIABLE = '416';\r\n// 最終取得スレッド\r\nvar lastThreadUrl = '';\r\n// 最終レス番号\r\nvar lastResNumber = 0;\r\n//最終更新日時\r\nvar lastModified = null;\r\n// 最終バイト数\r\nvar lastByte = 0;\r\n/**\r\n * コンストラクタ\r\n *\r\n */\r\nvar Read5ch = /** @class */ (function () {\r\n function Read5ch() {\r\n var _this = this;\r\n // constructor() {}\r\n /**\r\n * レス読み込み\r\n * 引数で指定した板からレスを読む\r\n * レス番号を指定していない場合は最新1件取得\r\n * @param threadUrl スレURL\r\n * @param resNum レス番号\r\n */\r\n this.read = function (threadUrl, resNum) { return __awaiter(_this, void 0, void 0, function () {\r\n var rep, requestUrl, range, options, responseJson, response, headers, str, error_1;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n // log.info(`[Read5ch] threadUrl=${threadUrl} resNum=${resNum}`);\r\n // 板や最終日レス番号がかわったら最初からとり直す(lastmodifiと rangeのリセット)\r\n if (threadUrl != lastThreadUrl || Number.isNaN(resNum) || resNum < lastResNumber) {\r\n lastThreadUrl = threadUrl;\r\n lastModified = null;\r\n lastByte = 0;\r\n console.trace('[Read5ch.js]resete!!!!!!!!!!!!!!!!');\r\n }\r\n else {\r\n console.trace('noresete');\r\n }\r\n rep = /\\/test\\/read.cgi(\\/.+)(\\/.+)\\//;\r\n requestUrl = threadUrl.replace(rep, '$1/dat$2.dat');\r\n range = lastByte;\r\n options = {\r\n url: requestUrl,\r\n method: 'GET',\r\n timeout: 3 * 1000,\r\n responseType: 'arraybuffer',\r\n headers: {\r\n 'if-modified-since': lastModified,\r\n range: 'bytes=' + range + '-',\r\n },\r\n };\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, 3, , 4]);\r\n return [4 /*yield*/, axios_1.default(options)];\r\n case 2:\r\n response = _a.sent();\r\n headers = response.headers;\r\n // LastModifiedとRange更新処理\r\n if (headers['last-modified'] != null) {\r\n lastModified = headers['last-modified'];\r\n }\r\n str = iconv_lite_1.default.decode(Buffer.from(response.data), 'Shift_JIS');\r\n // レスポンスオブジェクト作成、content-rangeがある場合とない場合で処理を分ける\r\n if (headers['content-range'] == null || lastByte == 0) {\r\n console.trace('[Read5ch.read]content-range=' + headers['content-range']);\r\n responseJson = purseNewResponse(str, resNum);\r\n }\r\n else {\r\n responseJson = purseDiffResponse(str, resNum);\r\n }\r\n // 取得バイト数表示\r\n if (headers['content-length'] != null && responseJson.length > 0) {\r\n lastByte = lastByte + parseInt(headers['content-length']) - 1;\r\n console.trace('[Read5ch.read]lastByte=' + lastByte);\r\n }\r\n return [3 /*break*/, 4];\r\n case 3:\r\n error_1 = _a.sent();\r\n responseJson = [];\r\n if (error_1.status == NOT_MODIFIED) {\r\n electron_log_1.default.error('[Read5ch.js]5ch系BBSレス取得APIリクエストエラー、NOT_MODIFIED');\r\n }\r\n else if (error_1.status == RANGE_NOT_SATISFIABLE) {\r\n electron_log_1.default.error('[Read5ch.js]5ch系BBSレス取得APIリクエストエラー、RANGE_NOT_SATISFIABLE');\r\n }\r\n else {\r\n electron_log_1.default.error('[Read5ch.js]5ch系BBSレス取得APIリクエストエラー、message=' + error_1.message);\r\n }\r\n throw new Error('connection error');\r\n case 4: return [2 /*return*/, responseJson];\r\n }\r\n });\r\n }); };\r\n }\r\n return Read5ch;\r\n}());\r\n/**\r\n * 取得したレスポンス(複数)のパース\r\n * 戻りとしてパースしたjsonオブジェクトの配列を返す\r\n * @param res 板から返却されたdat\r\n * @param resNum リクエストされたレス番号\r\n */\r\nvar purseNewResponse = function (res, resNum) {\r\n // 結果を格納する配列\r\n var result = [];\r\n // レス番号\r\n var num = 0;\r\n // 新着レスを改行ごとにSplitする\r\n var resArray = res.split(/\\r\\n|\\r|\\n/);\r\n // 新着なしなら戻る。\r\n if (resArray.length === 0) {\r\n return result;\r\n }\r\n // 配列の最後に空の要素が入ることがあるので取り除く\r\n if (resArray[resArray.length - 1].length === 0) {\r\n resArray.pop();\r\n }\r\n // レス指定なしの場合最後の1件取得\r\n if (Number.isNaN(resNum)) {\r\n num = resArray.length - 1;\r\n }\r\n else {\r\n num = resNum - 1;\r\n }\r\n // 1行ごとにパースする\r\n for (; num < resArray.length; num++) {\r\n // パースメソッド呼び出し\r\n if (resArray[num].length > 0) {\r\n result.push(purseResponse(resArray[num], num + 1));\r\n }\r\n }\r\n lastResNumber = num + 1;\r\n // パースしたオブジェクトの配列を返却\r\n return result;\r\n};\r\n/**\r\n * 取得したレスポンス(複数)のパース\r\n * 戻りとしてパースしたjsonオブジェクトの配列を返す\r\n * @param res 板から返却されたdat1行分\r\n * @param resNum リクエストされたレス番号\r\n */\r\nvar purseDiffResponse = function (res, resNum) {\r\n //結果を格納する配列\r\n var result = [];\r\n // レス番号\r\n var num = resNum;\r\n //新着レスを改行ごとにSplitする\r\n var resArray = res.split(/\\r\\n|\\r|\\n/);\r\n // 新着なしなら戻る。\r\n if (resArray.length === 0) {\r\n return result;\r\n }\r\n else {\r\n // 配列の最後に空の要素が入ることがあるので取り除く\r\n if (resArray[resArray.length - 1].length == 0) {\r\n resArray.pop();\r\n }\r\n }\r\n console.trace('[Read5ch.purseDiffResponse]取得レス番号=' + num);\r\n //1行ごとにパースする\r\n resArray.forEach(function (value) {\r\n //パースメソッド呼び出し\r\n if (value.length > 0) {\r\n result.push(purseResponse(value, num));\r\n num++;\r\n }\r\n });\r\n // パースしたオブジェクトの配列を返却\r\n return result;\r\n};\r\n/**\r\n * レスポンスのパース\r\n * Jsonオブジェクトを返却する\r\n * @param String // res レスポンス1レス\r\n * @param Integer // num レス番(0スタート)\r\n */\r\nvar purseResponse = function (res, num) {\r\n //APIの返却値を<>で分割\r\n //レスの要素\r\n //0:名前\r\n //1:メアド\r\n //2:日付とID (2019/11/03(日) 08:55:00 ID:kanikani)みたいに表示\r\n //3:本文\r\n //4:スレタイ (1レス目のみ)\r\n var splitRes = res.split('<>');\r\n // 日付とID分離処理、' ID:'で区切る\r\n var dateId = splitRes[2].split(' ID:');\r\n var date = dateId[0];\r\n var id = dateId.length === 2 ? dateId[1] : '';\r\n var resJson = {\r\n number: num.toString(),\r\n name: splitRes[0],\r\n email: splitRes[1],\r\n date: date,\r\n text: splitRes[3],\r\n // threadTitle: splitRes[4],\r\n id: id,\r\n imgUrl: '',\r\n };\r\n // オブジェクトを返却\r\n return resJson;\r\n};\r\nexports.default = Read5ch;\r\n","\"use strict\";\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\n/**\r\n * したらば読み込み用モジュール\r\n */\r\nvar axios_1 = __importDefault(require(\"axios\"));\r\nvar iconv_lite_1 = __importDefault(require(\"iconv-lite\")); // 文字コード変換用パッケージ\r\n/**\r\n * コンストラクタ\r\n */\r\nvar ReadSitaraba = /** @class */ (function () {\r\n function ReadSitaraba() {\r\n // constructor() {}\r\n var _this = this;\r\n /**\r\n * レス読み込み\r\n * @description 引数で指定した板からレスを読む。\r\n * @description レス番号を指定していない場合は最新1件取得\r\n * @param threadUrl スレURL\r\n * @param resNum レス番号\r\n */\r\n this.read = function (threadUrl, resNum) { return __awaiter(_this, void 0, void 0, function () {\r\n var requestUrl, options, response, str, responseJson;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n requestUrl = threadUrl.replace('read.cgi', 'rawmode.cgi');\r\n if (resNum > 0) {\r\n // レス番号がある場合レス番号以降を取得\r\n requestUrl += resNum + '-';\r\n }\r\n else {\r\n // レス番号がない場合最新の1件取得\r\n requestUrl += 'l1';\r\n }\r\n options = {\r\n url: requestUrl,\r\n method: 'GET',\r\n responseType: 'arraybuffer',\r\n timeout: 3 * 1000,\r\n };\r\n return [4 /*yield*/, axios_1.default(options)];\r\n case 1:\r\n response = _a.sent();\r\n str = iconv_lite_1.default.decode(Buffer.from(response.data), 'EUC-JP');\r\n responseJson = purseNewResponse(str);\r\n return [2 /*return*/, responseJson];\r\n }\r\n });\r\n }); };\r\n }\r\n return ReadSitaraba;\r\n}());\r\n/**\r\n * 取得したレスポンス(複数)のパース\r\n * @param res\r\n */\r\nvar purseNewResponse = function (res) {\r\n //結果を格納する配列\r\n var result = [];\r\n // 新着レスを改行ごとにSplitする\r\n var resArray = res.split(/\\r\\n|\\r|\\n/);\r\n // 1行ごとにパースする\r\n resArray.forEach(function (value) {\r\n // パースメソッド呼び出し\r\n if (value.length > 0) {\r\n result.push(purseResponse(value));\r\n }\r\n });\r\n return result;\r\n};\r\n/**\r\n * レスポンスのパース\r\n * Jsonオブジェクトを返却する\r\n * @param String // res レスポンス1レス\r\n */\r\nvar purseResponse = function (res) {\r\n //APIの返却値を<>で分割\r\n //レスの要素\r\n //0:レス番号\r\n //1:名前\r\n //2:メアド\r\n //3:日付\r\n //4:本文\r\n //5:スレタイ\r\n //6:ID\r\n var splitRes = res.split('<>');\r\n var resJson = {\r\n number: splitRes[0],\r\n name: splitRes[1],\r\n email: splitRes[2],\r\n date: splitRes[3],\r\n text: splitRes[4],\r\n // threadTitle: splitRes[5],\r\n id: splitRes[6],\r\n imgUrl: '',\r\n };\r\n // オブジェクトを返却\r\n return resJson;\r\n};\r\nexports.default = ReadSitaraba;\r\n","\"use strict\";\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nvar __spreadArrays = (this && this.__spreadArrays) || function () {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nvar __importStar = (this && this.__importStar) || function (mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result[\"default\"] = mod;\r\n return result;\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar path_1 = __importDefault(require(\"path\"));\r\nvar express_1 = __importDefault(require(\"express\"));\r\nvar electron_log_1 = __importDefault(require(\"electron-log\"));\r\nvar dank_twitch_irc_1 = require(\"dank-twitch-irc\");\r\nvar youtube_chat_1 = require(\"./youtube-chat\");\r\nvar electron_1 = require(\"electron\");\r\nvar express_ws_1 = __importDefault(require(\"express-ws\"));\r\nvar util_1 = require(\"./util\");\r\n// レス取得APIをセット\r\nvar getRes_1 = __importStar(require(\"./getRes\"));\r\nvar bouyomi_chan_1 = __importDefault(require(\"./bouyomi-chan\"));\r\nvar child_process_1 = require(\"child_process\");\r\nvar const_1 = require(\"./const\");\r\nvar app;\r\n// サーバーをグローバル変数にセットできるようにする(サーバー停止処理のため)\r\nvar server;\r\n/** 棒読みちゃんインスタンス */\r\nvar bouyomi;\r\n/** スレッド定期取得のイベント */\r\nvar threadIntervalEvent;\r\n/** キュー処理実行するか */\r\nvar isExecuteQue = false;\r\n/**\r\n * サーバー起動\r\n * config:設定を格納したjson、以下jsonの中身\r\n * url:掲示板URL\r\n * resNumber:読み込み開始レス位置\r\n * port:ポート番号\r\n */\r\nelectron_1.ipcMain.on(const_1.electronEvent['start-server'], function (event, config) { return __awaiter(void 0, void 0, void 0, function () {\r\n var list;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n app = express_ws_1.default(express_1.default()).app;\r\n app.set('view engine', 'ejs');\r\n // viewディレクトリの指定\r\n app.set('views', path_1.default.resolve(__dirname, '../views'));\r\n // 設定情報をグローバル変数へセットする\r\n globalThis.config = config;\r\n console.log('[startServer]設定値 = ');\r\n console.log(globalThis.config);\r\n app.get('/', function (req, res, next) {\r\n res.render('server', config);\r\n req.connection.end();\r\n });\r\n //静的コンテンツはpublicディレクトリの中身を使用するという宣言\r\n app.use(express_1.default.static(path_1.default.resolve(__dirname, '../public')));\r\n // 2ch互換掲示板の取得\r\n app.use('/getRes', getRes_1.default);\r\n if (!globalThis.config.playSe) return [3 /*break*/, 2];\r\n return [4 /*yield*/, util_1.readWavFiles(globalThis.config.sePath)];\r\n case 1:\r\n list = _a.sent();\r\n globalThis.electron.seList = list.map(function (file) { return globalThis.config.sePath + \"/\" + file; });\r\n console.log(\"SE files = \" + globalThis.electron.seList.length);\r\n _a.label = 2;\r\n case 2:\r\n // Twitchに接続\r\n if (globalThis.config.twitchId) {\r\n globalThis.electron.twitchChat = new dank_twitch_irc_1.ChatClient();\r\n globalThis.electron.twitchChat.connect();\r\n globalThis.electron.twitchChat.join(globalThis.config.twitchId);\r\n globalThis.electron.twitchChat.on('PRIVMSG', function (msg) {\r\n var imgUrl = './img/twitch.png';\r\n var name = msg.displayName;\r\n var text = msg.messageText;\r\n globalThis.electron.commentQueueList.push({ imgUrl: imgUrl, name: name, text: text });\r\n });\r\n }\r\n // Youtubeチャット\r\n if (globalThis.config.youtubeId) {\r\n try {\r\n console.log('[Youtube Chat] connect started');\r\n globalThis.electron.youtubeChat = new youtube_chat_1.LiveChat({ channelId: globalThis.config.youtubeId });\r\n // 接続開始イベント\r\n globalThis.electron.youtubeChat.on('start', function (liveId) {\r\n console.log(\"[Youtube Chat] connected liveId = \" + liveId);\r\n });\r\n // 接続終了イベント\r\n globalThis.electron.youtubeChat.on('end', function (reason) {\r\n console.log('[Youtube Chat] disconnect');\r\n });\r\n // チャット受信\r\n globalThis.electron.youtubeChat.on('comment', function (comment) {\r\n var _a, _b;\r\n var imgUrl = (_b = (_a = comment.author.thumbnail) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '';\r\n var name = comment.author.name;\r\n var text = comment.message[0].text;\r\n globalThis.electron.commentQueueList.push({ imgUrl: imgUrl, name: name, text: text });\r\n });\r\n // 何かエラーがあった\r\n globalThis.electron.youtubeChat.on('error', function (err) {\r\n electron_log_1.default.error('[Youtube Chat] error');\r\n electron_log_1.default.error(err);\r\n globalThis.electron.youtubeChat.stop();\r\n });\r\n globalThis.electron.youtubeChat.start();\r\n }\r\n catch (e) {\r\n process.exit(1);\r\n }\r\n }\r\n // 棒読みちゃん接続\r\n if (config.typeYomiko === 'bouyomi') {\r\n if (config.bouyomiPort) {\r\n bouyomi = new bouyomi_chan_1.default({ port: config.bouyomiPort, volume: config.bouyomiVolume });\r\n }\r\n }\r\n // レス取得定期実行\r\n threadIntervalEvent = setInterval(function () { return getRes_1.getResInterval(); }, globalThis.config.interval * 1000);\r\n // キュー処理の開始\r\n isExecuteQue = true;\r\n taskScheduler();\r\n // WebSocketを立てる\r\n app.ws('/ws', function (ws, req) {\r\n globalThis.electron.socket = ws;\r\n ws.on('message', function (message) {\r\n console.trace('Received: ' + message);\r\n if (message === 'ping') {\r\n ws.send('pong');\r\n }\r\n });\r\n ws.on('close', function () {\r\n console.log('I lost a client');\r\n });\r\n });\r\n // 指定したポートで待ち受け開始\r\n server = app.listen(config.port, function () {\r\n console.log('[startServer] start server on port:' + config.port);\r\n });\r\n // 成功メッセージ返却\r\n event.returnValue = 'success';\r\n return [2 /*return*/];\r\n }\r\n });\r\n}); });\r\n/**\r\n * サーバー停止\r\n */\r\nelectron_1.ipcMain.on(const_1.electronEvent['stop-server'], function (event) {\r\n console.log('[startServer]server stop');\r\n server.close();\r\n app = null;\r\n event.returnValue = 'stop';\r\n // キュー処理停止\r\n isExecuteQue = false;\r\n globalThis.electron.commentQueueList = [];\r\n // Twitchチャットの停止\r\n if (globalThis.electron.twitchChat) {\r\n globalThis.electron.twitchChat.close();\r\n globalThis.electron.twitchChat.removeAllListeners();\r\n }\r\n // Youtubeチャットの停止\r\n if (globalThis.electron.youtubeChat) {\r\n globalThis.electron.youtubeChat.stop();\r\n globalThis.electron.youtubeChat.removeAllListeners();\r\n }\r\n // レス取得の停止\r\n if (threadIntervalEvent) {\r\n clearInterval(threadIntervalEvent);\r\n }\r\n});\r\n/**\r\n * キューに溜まったコメントを処理する\r\n */\r\nvar taskScheduler = function () { return __awaiter(void 0, void 0, void 0, function () {\r\n var temp, comment;\r\n var _a, _b;\r\n return __generator(this, function (_c) {\r\n switch (_c.label) {\r\n case 0:\r\n if (!(((_b = (_a = globalThis.electron) === null || _a === void 0 ? void 0 : _a.commentQueueList) === null || _b === void 0 ? void 0 : _b.length) > 0)) return [3 /*break*/, 3];\r\n if (!(globalThis.config.commentProcessType === 0)) return [3 /*break*/, 1];\r\n temp = __spreadArrays(globalThis.electron.commentQueueList);\r\n globalThis.electron.commentQueueList = [];\r\n // 新着が上の場合は逆順にする\r\n if (!globalThis.config.dispSort) {\r\n temp = temp.reverse();\r\n }\r\n sendDom(temp);\r\n return [3 /*break*/, 3];\r\n case 1:\r\n comment = globalThis.electron.commentQueueList.shift();\r\n return [4 /*yield*/, sendDom([comment])];\r\n case 2:\r\n _c.sent();\r\n _c.label = 3;\r\n case 3:\r\n if (!isExecuteQue) return [3 /*break*/, 5];\r\n return [4 /*yield*/, util_1.sleep(100)];\r\n case 4:\r\n _c.sent();\r\n taskScheduler();\r\n _c.label = 5;\r\n case 5: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\n/** 読み子によって発話中であるか */\r\nvar isSpeaking = false;\r\n/** 読み子を再生する */\r\nvar playYomiko = function (msg) { return __awaiter(void 0, void 0, void 0, function () {\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n // log.info('[playYomiko] start');\r\n isSpeaking = true;\r\n // 読み子呼び出し\r\n switch (config.typeYomiko) {\r\n case 'tamiyasu': {\r\n child_process_1.exec(config.tamiyasuPath + \" \" + msg);\r\n break;\r\n }\r\n case 'bouyomi': {\r\n if (bouyomi)\r\n bouyomi.speak(msg);\r\n break;\r\n }\r\n }\r\n // 読み子が読んでる時間分相当待つ\r\n globalThis.electron.mainWindow.webContents.send(const_1.electronEvent['wait-yomiko-time'], msg);\r\n _a.label = 1;\r\n case 1:\r\n if (!isSpeaking) return [3 /*break*/, 3];\r\n return [4 /*yield*/, util_1.sleep(50)];\r\n case 2:\r\n _a.sent();\r\n return [3 /*break*/, 1];\r\n case 3: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\nelectron_1.ipcMain.on(const_1.electronEvent['speaking-end'], function (event) { return (isSpeaking = false); });\r\nvar isPlayingSe = false;\r\nvar playSe = function () { return __awaiter(void 0, void 0, void 0, function () {\r\n var wavfilepath;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n wavfilepath = globalThis.electron.seList[Math.floor(Math.random() * globalThis.electron.seList.length)];\r\n isPlayingSe = true;\r\n globalThis.electron.mainWindow.webContents.send(const_1.electronEvent['play-sound-start'], wavfilepath);\r\n _a.label = 1;\r\n case 1:\r\n if (!isPlayingSe) return [3 /*break*/, 3];\r\n return [4 /*yield*/, util_1.sleep(50)];\r\n case 2:\r\n _a.sent();\r\n return [3 /*break*/, 1];\r\n case 3: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\nelectron_1.ipcMain.on(const_1.electronEvent['play-sound-end'], function (event) { return (isPlayingSe = false); });\r\nexports.createDom = function (message) {\r\n var domStr = \"\\n
  • \\n \\n \\n \\n
    \";\r\n //レス番表示\r\n if (globalThis.config.showNumber) {\r\n domStr += \"\\n \" + message.number + \"\\n \";\r\n }\r\n // 名前表示\r\n if (globalThis.config.showName) {\r\n domStr += \"\" + message.name + \"\";\r\n }\r\n // 時刻表示\r\n if (globalThis.config.showTime) {\r\n domStr += \"\" + message.date + \"\";\r\n }\r\n // 名前と本文を改行で分ける\r\n if (globalThis.config.newLine) {\r\n domStr += '
    ';\r\n }\r\n domStr += \"\\n \\n \" + message.text + \"\\n \\n
    \\n
  • \";\r\n return domStr;\r\n};\r\n/**\r\n * コメントのDOMをブラウザに送る\r\n * 必要ならレス着信音も鳴らす\r\n * @param message\r\n */\r\nvar sendDom = function (messageList) { return __awaiter(void 0, void 0, void 0, function () {\r\n var domStr;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n domStr = messageList.map(function (message) { return exports.createDom(message); }).join('\\n');\r\n if (globalThis.electron.socket)\r\n globalThis.electron.socket.send(domStr);\r\n if (!(config.playSe && globalThis.electron.seList.length > 0)) return [3 /*break*/, 2];\r\n return [4 /*yield*/, playSe()];\r\n case 1:\r\n _a.sent();\r\n _a.label = 2;\r\n case 2:\r\n if (!(globalThis.config.typeYomiko !== 'none')) return [3 /*break*/, 4];\r\n return [4 /*yield*/, playYomiko(messageList[messageList.length - 1].text)];\r\n case 3:\r\n _a.sent();\r\n _a.label = 4;\r\n case 4: return [2 /*return*/];\r\n }\r\n });\r\n}); };\r\nexports.default = {};\r\n","\"use strict\";\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar fs_1 = __importDefault(require(\"fs\"));\r\nexports.readWavFiles = function (path) {\r\n return new Promise(function (resolve, reject) {\r\n fs_1.default.readdir(path, function (err, files) {\r\n if (err)\r\n reject(err);\r\n var fileList = files.filter(function (file) {\r\n return isExistFile(path + '/' + file) && /.*\\.wav$/.test(file); //絞り込み\r\n });\r\n resolve(fileList);\r\n });\r\n });\r\n};\r\nvar isExistFile = function (file) {\r\n try {\r\n fs_1.default.statSync(file).isFile();\r\n return true;\r\n }\r\n catch (err) {\r\n if (err.code === 'ENOENT')\r\n return false;\r\n }\r\n};\r\nexports.sleep = function (msec) { return new Promise(function (resolve) { return setTimeout(resolve, msec); }); };\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar live_chat_1 = require(\"./live-chat\");\r\nexports.LiveChat = live_chat_1.LiveChat;\r\n","\"use strict\";\r\nvar __extends = (this && this.__extends) || (function () {\r\n var extendStatics = function (d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar events_1 = require(\"events\");\r\nvar axios_1 = __importDefault(require(\"axios\"));\r\nvar parser_1 = require(\"./parser\");\r\n/**\r\n * YouTubeライブチャット取得イベント\r\n */\r\nvar LiveChat = /** @class */ (function (_super) {\r\n __extends(LiveChat, _super);\r\n function LiveChat(options, interval) {\r\n if (interval === void 0) { interval = 1000; }\r\n var _this = _super.call(this) || this;\r\n _this.interval = interval;\r\n _this.prevTime = Date.now();\r\n if ('channelId' in options) {\r\n _this.channelId = options.channelId;\r\n }\r\n else if ('liveId' in options) {\r\n _this.liveId = options.liveId;\r\n }\r\n else {\r\n throw TypeError('Required channelId or liveId.');\r\n }\r\n return _this;\r\n }\r\n LiveChat.prototype.start = function () {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var url, liveRes, e_1;\r\n var _this = this;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!this.channelId) return [3 /*break*/, 4];\r\n url = \"https://www.youtube.com/channel/\" + this.channelId + \"/live\";\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, 3, , 4]);\r\n return [4 /*yield*/, axios_1.default.get(url, { headers: LiveChat.headers })];\r\n case 2:\r\n liveRes = _a.sent();\r\n // if (liveRes.data.match(/LIVE_STREAM_OFFLINE/)) {\r\n // this.emit('error', new Error('Live stream offline'));\r\n // return false;\r\n // }\r\n this.liveId = liveRes.data.match(/videoId\\\\\":\\\\\"(.+?)\\\\/)[1];\r\n return [3 /*break*/, 4];\r\n case 3:\r\n e_1 = _a.sent();\r\n this.emit('error', new Error(\"connection error url = \" + url));\r\n return [2 /*return*/, false];\r\n case 4:\r\n if (!this.liveId) {\r\n this.emit('error', new Error('Live stream not found'));\r\n return [2 /*return*/, false];\r\n }\r\n // console.log(`liveId = ${this.liveId}`);\r\n this.observer = setInterval(function () { return _this.fetchChat(); }, this.interval);\r\n this.emit('start', this.liveId);\r\n return [2 /*return*/, true];\r\n }\r\n });\r\n });\r\n };\r\n LiveChat.prototype.stop = function (reason) {\r\n if (this.observer) {\r\n clearInterval(this.observer);\r\n this.emit('end', reason);\r\n }\r\n };\r\n LiveChat.prototype.fetchChat = function () {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var url, res, items, item, e_2;\r\n var _this = this;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n url = \"https://www.youtube.com/live_chat?v=\" + this.liveId + \"&pbj=1\";\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, 3, , 4]);\r\n return [4 /*yield*/, axios_1.default.get(url, { headers: LiveChat.headers })];\r\n case 2:\r\n res = _a.sent();\r\n items = res.data[1].response.contents.liveChatRenderer.actions\r\n .slice(0, -1)\r\n .filter(function (v) {\r\n var messageRenderer = parser_1.actionToRenderer(v);\r\n if (messageRenderer !== null) {\r\n if (messageRenderer) {\r\n return parser_1.usecToTime(messageRenderer.timestampUsec) > _this.prevTime;\r\n }\r\n }\r\n return false;\r\n })\r\n .map(function (v) { return parser_1.parseData(v); });\r\n items.forEach(function (v) {\r\n if (v) {\r\n _this.emit('comment', v);\r\n }\r\n });\r\n if (items.length > 0) {\r\n item = items[items.length - 1];\r\n if (item)\r\n this.prevTime = item.timestamp;\r\n }\r\n return [3 /*break*/, 4];\r\n case 3:\r\n e_2 = _a.sent();\r\n this.emit('error', new Error(\"Error occured at fetchchat url=\" + url));\r\n return [3 /*break*/, 4];\r\n case 4: return [2 /*return*/];\r\n }\r\n });\r\n });\r\n };\r\n LiveChat.prototype.on = function (event, listener) {\r\n return _super.prototype.on.call(this, event, listener);\r\n };\r\n LiveChat.headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36' };\r\n return LiveChat;\r\n}(events_1.EventEmitter));\r\nexports.LiveChat = LiveChat;\r\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar parseThumbnailToImageItem = function (data, alt) {\r\n var thumbnail = data.pop();\r\n if (thumbnail) {\r\n return {\r\n url: thumbnail.url,\r\n width: thumbnail.width,\r\n height: thumbnail.height,\r\n alt: alt,\r\n };\r\n }\r\n return;\r\n};\r\nvar parseEmojiToImageItem = function (data) {\r\n return parseThumbnailToImageItem(data.emoji.image.thumbnails, data.emoji.shortcuts.shift());\r\n};\r\nvar parseMessages = function (runs) {\r\n return runs.map(function (run) {\r\n if ('text' in run) {\r\n return run;\r\n }\r\n else {\r\n return parseEmojiToImageItem(run);\r\n }\r\n });\r\n};\r\nexports.actionToRenderer = function (action) {\r\n if (!action.addChatItemAction) {\r\n return null;\r\n }\r\n var item = action.addChatItemAction.item;\r\n if (item.liveChatTextMessageRenderer) {\r\n return item.liveChatTextMessageRenderer;\r\n }\r\n else if (item.liveChatPaidMessageRenderer) {\r\n return item.liveChatPaidMessageRenderer;\r\n }\r\n else if (item.liveChatPaidStickerRenderer) {\r\n return item.liveChatPaidStickerRenderer;\r\n }\r\n else {\r\n return item.liveChatMembershipItemRenderer;\r\n }\r\n};\r\nexports.usecToTime = function (usec) {\r\n return Math.floor(Number(usec) / 1000);\r\n};\r\nexports.parseData = function (data) {\r\n var messageRenderer = exports.actionToRenderer(data);\r\n if (messageRenderer === null) {\r\n return null;\r\n }\r\n var message = [];\r\n if ('message' in messageRenderer) {\r\n message = messageRenderer.message.runs;\r\n }\r\n else if ('headerSubtext' in messageRenderer) {\r\n message = messageRenderer.headerSubtext.runs;\r\n }\r\n var ret = {\r\n id: messageRenderer.id,\r\n author: {\r\n name: messageRenderer.authorName.simpleText,\r\n thumbnail: parseThumbnailToImageItem(messageRenderer.authorPhoto.thumbnails, messageRenderer.authorName.simpleText),\r\n channelId: messageRenderer.authorExternalChannelId,\r\n },\r\n message: parseMessages(message),\r\n membership: Boolean('headerSubtext' in messageRenderer),\r\n isOwner: false,\r\n timestamp: exports.usecToTime(messageRenderer.timestampUsec),\r\n };\r\n if (messageRenderer.authorBadges) {\r\n var badge = messageRenderer.authorBadges[0].liveChatAuthorBadgeRenderer;\r\n if (badge.customThumbnail) {\r\n ret.author.badge = {\r\n thumbnail: parseThumbnailToImageItem(badge.customThumbnail.thumbnails, badge.tooltip),\r\n label: badge.tooltip,\r\n };\r\n }\r\n else {\r\n ret.isOwner = true;\r\n }\r\n }\r\n if ('sticker' in messageRenderer) {\r\n ret.superchat = {\r\n amount: messageRenderer.purchaseAmountText.simpleText,\r\n color: messageRenderer.backgroundColor,\r\n sticker: parseThumbnailToImageItem(messageRenderer.sticker.thumbnails, messageRenderer.sticker.accessibility.accessibilityData.label),\r\n };\r\n }\r\n else if ('purchaseAmountText' in messageRenderer) {\r\n ret.superchat = {\r\n amount: messageRenderer.purchaseAmountText.simpleText,\r\n color: messageRenderer.bodyBackgroundColor,\r\n };\r\n }\r\n return ret;\r\n};\r\n"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AClFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AClFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC1EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACxLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC9PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC3IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACvWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC5BA;AACA;AACA;AACA;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;A","sourceRoot":""} \ No newline at end of file diff --git a/src/main/startServer.ts b/src/main/startServer.ts index e403c83..77f017c 100644 --- a/src/main/startServer.ts +++ b/src/main/startServer.ts @@ -186,8 +186,12 @@ const taskScheduler = async () => { if (globalThis.electron?.commentQueueList?.length > 0) { if (globalThis.config.commentProcessType === 0) { // 一括 - const temp = [...globalThis.electron.commentQueueList]; + let temp = [...globalThis.electron.commentQueueList]; globalThis.electron.commentQueueList = []; + // 新着が上の場合は逆順にする + if (!globalThis.config.dispSort) { + temp = temp.reverse(); + } sendDom(temp); } else { // 1個ずつ