Arca Refresher

Arca Live Extension

// ==UserScript==
// @name            Arca Refresher
// @namespace       LeKAKiD
// @description     Arca Live Extension
// @homepageURL     https://github.com/lekakid/ArcaRefresher
// @supportURL      https://arca.live/b/namurefresher
// @match           https://*.arca.live/*
// @match           https://arca.live/*
// @exclude-match   https://st*.arca.live/*
// @noframes
// @run-at          document-start
// @grant           GM_setValue
// @grant           GM_getValue
// @grant           GM_deleteValue
// @grant           GM_listValues
// @grant           GM_xmlhttpRequest
// @version         2.6.8
// @author          LeKAKiD
// @require         https://unpkg.com/[email protected]/dist/FileSaver.min.js
// @require         https://unpkg.com/[email protected]/dist/jszip.min.js
// @require         https://cdn.jsdelivr.net/combine/npm/@violentmonkey/dom,npm/@violentmonkey/ui
// ==/UserScript==

(function () {
'use strict';

function getContrastYIQ(hexcolor) {
  const r = parseInt(hexcolor.substr(0, 2), 16);
  const g = parseInt(hexcolor.substr(2, 2), 16);
  const b = parseInt(hexcolor.substr(4, 2), 16);
  const yiq = (r * 299 + g * 587 + b * 114) / 1000;
  return yiq >= 128 ? 'black' : 'white';
}
function getRandomColor() {
  return `00000${Math.floor(Math.random() * 0xFFFFFF).toString(16).toUpperCase()}`.slice(-6);
}

var css_248z = "#refresherSetting {\r\n    margin: 0 auto;\r\n    max-width: 1300px;\r\n    border: 1px solid #bbb;\r\n    background-color: #fff;\r\n    padding: 1rem;\r\n}\r\n\r\n#refresherSetting select,\r\n#refresherSetting textarea,\r\n#refresherSetting input[type=\"text\"] {\r\n    display: block;\r\n    width: 100%;\r\n    padding: .5rem .75rem;\r\n    color: #55595c;\r\n    background-color: #fff;\r\n    border: 1px solid #bbb;\r\n}\r\n\r\n#refresherSetting input[disabled] {\r\n    background-color: #eee;\r\n}\r\n\r\n#refresherSetting select {\r\n    overflow: scroll;\r\n}\r\n\r\n#refresherSetting label {\r\n    display: inline;\r\n}\r\n\r\n@media (prefers-color-scheme:dark) {\r\n    #refresherSetting {\r\n        border: 1px solid #43494c;\r\n        background-color: #181a1b;\r\n    }\r\n    \r\n    #refresherSetting select,\r\n    #refresherSetting textarea,\r\n    #refresherSetting input[type=\"text\"] {\r\n        color: #55595c;\r\n        background-color: #fff;\r\n        border: 1px solid #bbb;\r\n    }\r\n    \r\n    #refresherSetting input[disabled] {\r\n        background-color: #999;\r\n    }\r\n}";

const defaultConfig = {
  refreshTime: 5,
  hideRefresher: false,
  useShortcut: false,
  hideNotice: true,
  hideAvatar: false,
  hideMedia: false,
  hideModified: false,
  hideSideMenu: false,
  myImage: '',
  blockRatedown: false,
  blockKeyword: [],
  blockUser: [],
  blockEmoticon: {},
  userMemo: {},
  useAutoRemoverTest: true,
  autoRemoveUser: [],
  autoRemoveKeyword: [],
  category: {},
  imageDownloaderFileName: '%title%'
};
function importConfig(JSONString) {
  const data = JSON.parse(JSONString);

  for (const key of Object.keys(data)) {
    if ({}.hasOwnProperty.call(defaultConfig, key)) {
      GM_setValue(key, data[key]);
    }
  }
}

function exportConfig() {
  const keys = GM_listValues();
  const config = {};

  for (const key of keys) {
    config[key] = GM_getValue(key);
  }

  const result = JSON.stringify(config);
  return result;
}

function reset() {
  const keys = GM_listValues();

  for (const key of keys) {
    GM_deleteValue(key);
  }
}

function setup() {
  // 설정 CSS 등록
  document.head.append(VM.createElement("style", null, css_248z)); // 스크립트 설정 버튼 엘리먼트

  const showSettingBtn = VM.createElement("li", {
    class: "nav-item dropdown",
    id: "showSetting"
  }, VM.createElement("a", {
    "aria-expanded": "false",
    class: "nav-link",
    href: "#"
  }, VM.createElement("span", {
    class: "d-none d-sm-block"
  }, "\uC2A4\uD06C\uB9BD\uD2B8 \uC124\uC815"), VM.createElement("span", {
    class: "d-block d-sm-none"
  }, VM.createElement("span", {
    class: "ion-gear-a"
  })))); // 설정 뷰

  const settingWrapper = VM.createElement("div", {
    class: "hidden clearfix",
    id: "refresherSetting"
  }, VM.createElement("div", {
    class: "row"
  }, VM.createElement("div", {
    class: "col-sm-0 col-md-2"
  }), VM.createElement("div", {
    class: "col-sm-12 col-md-8"
  }, VM.createElement("div", {
    class: "dialog card"
  }, VM.createElement("div", {
    class: "card-block"
  }, VM.createElement("h4", {
    class: "card-title"
  }, "\uC544\uCE74 \uB9AC\uD504\uB808\uC154(Arca Refresher) \uC124\uC815"), VM.createElement("hr", null), VM.createElement("h5", {
    class: "card-title"
  }, "\uC720\uD2F8\uB9AC\uD2F0"), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uC790\uB3D9 \uC0C8\uB85C\uACE0\uCE68"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "refreshTime",
    "data-type": "number"
  }, VM.createElement("option", {
    value: "0"
  }, "\uC0AC\uC6A9 \uC548 \uD568"), VM.createElement("option", {
    value: "3"
  }, "3\uCD08"), VM.createElement("option", {
    value: "5"
  }, "5\uCD08"), VM.createElement("option", {
    value: "10"
  }, "10\uCD08")), VM.createElement("p", null, "\uC77C\uC815 \uC2DC\uAC04\uB9C8\uB2E4 \uAC8C\uC2DC\uBB3C \uBAA9\uB85D\uC744 \uAC31\uC2E0\uD569\uB2C8\uB2E4."))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uC0C8\uB85C\uACE0\uCE68 \uC560\uB2C8\uBA54\uC774\uC158 \uC228\uAE40"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "hideRefresher",
    "data-type": "bool"
  }, VM.createElement("option", {
    value: "false"
  }, "\uC0AC\uC6A9 \uC548 \uD568"), VM.createElement("option", {
    value: "true"
  }, "\uC0AC\uC6A9")), VM.createElement("p", null))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uB2E8\uCD95\uD0A4 \uC0AC\uC6A9"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "useShortcut",
    "data-type": "bool"
  }, VM.createElement("option", {
    value: "false"
  }, "\uC0AC\uC6A9 \uC548 \uD568"), VM.createElement("option", {
    value: "true"
  }, "\uC0AC\uC6A9")), VM.createElement("p", null, VM.createElement("a", {
    href: "https://github.com/lekakid/ArcaRefresher/wiki/Feature#%EB%8B%A8%EC%B6%95%ED%82%A4%EB%A1%9C-%EB%B9%A0%EB%A5%B8-%EC%9D%B4%EB%8F%99",
    target: "_blank",
    rel: "noreferrer"
  }, "\uB2E8\uCD95\uD0A4 \uC548\uB0B4 \uBC14\uB85C\uAC00\uAE30")))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uBE44\uCD94\uCC9C \uC7AC\uD655\uC778 \uCC3D"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "blockRatedown",
    "data-type": "bool"
  }, VM.createElement("option", {
    value: "false"
  }, "\uC0AC\uC6A9 \uC548 \uD568"), VM.createElement("option", {
    value: "true"
  }, "\uC0AC\uC6A9")), VM.createElement("p", null))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uC790\uC9E4 \uAD00\uB9AC"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("button", {
    id: "removeMyImage",
    class: "btn btn-success"
  }, "\uC0AD\uC81C"), VM.createElement("p", null, "\uAC8C\uC2DC\uBB3C \uC870\uD68C \uC2DC \uC774\uBBF8\uC9C0 \uC624\uB978\uCABD \uD074\uB9AD \uBA54\uB274\uC5D0\uC11C \uAD00\uB9AC\uD569\uB2C8\uB2E4."))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uB2E4\uC6B4\uB85C\uB354 \uC774\uB984 \uD3EC\uB9F7"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("input", {
    type: "text",
    id: "imageDownloaderFileName"
  }), VM.createElement("p", null, "\uC774\uBBF8\uC9C0 \uC77C\uAD04 \uB2E4\uC6B4\uB85C\uB4DC \uC0AC\uC6A9 \uC2DC \uC800\uC7A5\uD560 \uD30C\uC77C \uC774\uB984\uC785\uB2C8\uB2E4.", VM.createElement("br", null), "%title% : \uAC8C\uC2DC\uBB3C \uC81C\uBAA9", VM.createElement("br", null), "%category% : \uAC8C\uC2DC\uBB3C \uCE74\uD14C\uACE0\uB9AC", VM.createElement("br", null), "%author% : \uAC8C\uC2DC\uBB3C \uC791\uC131\uC790", VM.createElement("br", null), "%channel% : \uCC44\uB110 \uC774\uB984", VM.createElement("br", null)))), VM.createElement("hr", null), VM.createElement("h5", {
    class: "card-title"
  }, "\uC694\uC18C \uC228\uAE40"), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uC6B0\uCE21 \uC0AC\uC774\uB4DC \uBA54\uB274"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "hideSideMenu",
    "data-type": "bool"
  }, VM.createElement("option", {
    value: "false"
  }, "\uBCF4\uC784"), VM.createElement("option", {
    value: "true"
  }, "\uC228\uAE40")), VM.createElement("p", null, "\uBCA0\uC2A4\uD2B8 \uB77C\uC774\uBE0C, \uD5E4\uB4DC\uB77C\uC778 \uB4F1 \uC6B0\uCE21 \uC0AC\uC774\uB4DC \uBA54\uB274\uB97C \uC228\uAE41\uB2C8\uB2E4."))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uD504\uB85C\uD544 \uC544\uBC14\uD0C0"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "hideAvatar",
    "data-type": "bool"
  }, VM.createElement("option", {
    value: "false"
  }, "\uBCF4\uC784"), VM.createElement("option", {
    value: "true"
  }, "\uC228\uAE40")), VM.createElement("p", null, "\uAC8C\uC2DC\uBB3C \uC870\uD68C \uC2DC \uD504\uB85C\uD544 \uC544\uBC14\uD0C0\uB97C \uC228\uAE41\uB2C8\uB2E4."))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uBCF8\uBB38 \uC774\uBBF8\uC9C0, \uB3D9\uC601\uC0C1"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "hideMedia",
    "data-type": "bool"
  }, VM.createElement("option", {
    value: "false"
  }, "\uBCF4\uC784"), VM.createElement("option", {
    value: "true"
  }, "\uC228\uAE40")), VM.createElement("p", null, "\uAC8C\uC2DC\uBB3C \uC870\uD68C \uC2DC \uBCF8\uBB38\uC5D0 \uB098\uC624\uB294 \uC774\uBBF8\uC9C0\uC640 \uB3D9\uC601\uC0C1\uC744 \uC228\uAE41\uB2C8\uB2E4."))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uB313\uAE00 *\uC218\uC815\uB428"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "hideModified",
    "data-type": "bool"
  }, VM.createElement("option", {
    value: "false"
  }, "\uBCF4\uC784"), VM.createElement("option", {
    value: "true"
  }, "\uC228\uAE40")), VM.createElement("p", null, "\uC218\uC815\uB41C \uB313\uAE00\uC758 \uC218\uC815\uB428 \uD45C\uAE30\uB97C \uC228\uAE41\uB2C8\uB2E4.", VM.createElement("br", null), "\uC8FC\uC758) \uB313\uAE00 \uC0AD\uC81C \uAD8C\uD55C \uBCF4\uC720 \uC2DC \uC0AD\uC81C\uB428 \uD45C\uAE30\uB3C4 \uAC19\uC774 \uC228\uACA8\uC9D1\uB2C8\uB2E4."))), VM.createElement("hr", null), VM.createElement("h5", {
    class: "card-title"
  }, "\uBA54\uBAA8 \uAE30\uB2A5"), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uBA54\uBAA8\uB41C \uC774\uC6A9\uC790"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "userMemo",
    size: "6",
    multiple: "",
    "data-text-format": "%key% - %value%"
  }), VM.createElement("p", null, "\uBA54\uBAA8\uB294 \uAC8C\uC2DC\uBB3C \uC791\uC131\uC790, \uB313\uAE00 \uC791\uC131\uC790 \uC544\uC774\uCF58(IP)\uC744 \uD074\uB9AD\uD574 \uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.", VM.createElement("br", null), "Ctrl, Shift, \uB9C8\uC6B0\uC2A4 \uB4DC\uB798\uADF8\uB97C \uC774\uC6A9\uD574\uC11C \uC5EC\uB7EC\uAC1C\uB97C \uB3D9\uC2DC\uC5D0 \uC120\uD0DD \uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."))), VM.createElement("hr", null), VM.createElement("h5", {
    class: "card-title"
  }, "\uCC44\uB110 \uC124\uC815"), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uCE74\uD14C\uACE0\uB9AC \uC124\uC815"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("table", {
    class: "table align-middle",
    id: "categorySetting"
  }, VM.createElement("colgroup", null, VM.createElement("col", {
    width: "20%"
  }), VM.createElement("col", {
    width: "20%"
  }), VM.createElement("col", {
    width: "60%"
  })), VM.createElement("thead", null, VM.createElement("th", null, "\uCE74\uD14C\uACE0\uB9AC"), VM.createElement("th", null, "\uC0C9\uC0C1"), VM.createElement("th", null, "\uC124\uC815")), VM.createElement("tbody", null)), VM.createElement("p", null, "\uC0C9\uC0C1: \uCE74\uD14C\uACE0\uB9AC\uB97C \uD45C\uC2DC\uD558\uB294 \uC0C9\uC0C1\uC744 \uBCC0\uACBD\uD569\uB2C8\uB2E4. \uB354\uBE14 \uD074\uB9AD \uC2DC \uBB34\uC791\uC704 \uC0C9\uC0C1\uC774 \uC9C0\uC815\uB429\uB2C8\uB2E4.", VM.createElement("br", null), "\uBBF8\uB9AC\uBCF4\uAE30 \uC228\uAE40: \uB9C8\uC6B0\uC2A4 \uC624\uBC84 \uC2DC \uBCF4\uC5EC\uC8FC\uB294 \uBBF8\uB9AC\uBCF4\uAE30\uB97C \uC81C\uAC70\uD569\uB2C8\uB2E4.", VM.createElement("br", null), "\uAC8C\uC2DC\uBB3C \uBBA4\uD2B8: \uD574\uB2F9 \uCE74\uD14C\uACE0\uB9AC\uAC00 \uD3EC\uD568\uB41C \uAC8C\uC2DC\uBB3C\uC744 \uC228\uAE41\uB2C8\uB2E4."))), VM.createElement("hr", null), VM.createElement("h5", {
    class: "card-title"
  }, "\uBBA4\uD2B8 \uAE30\uB2A5"), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uC0AC\uC6A9\uC790 \uBBA4\uD2B8"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("textarea", {
    id: "blockUser",
    rows: "6",
    placeholder: "\uBBA4\uD2B8\uD560 \uC774\uC6A9\uC790\uC758 \uB2C9\uB124\uC784\uC744 \uC785\uB825, \uC904\uBC14\uAFC8\uC73C\uB85C \uAD6C\uBCC4\uD569\uB2C8\uB2E4."
  }), VM.createElement("p", null, "\uC9C0\uC815\uD55C \uC720\uC800\uC758 \uAC8C\uC2DC\uBB3C\uACFC \uB313\uAE00\uC744 \uC228\uAE41\uB2C8\uB2E4."))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uD0A4\uC6CC\uB4DC \uBBA4\uD2B8"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("textarea", {
    id: "blockKeyword",
    rows: "6",
    placeholder: "\uBBA4\uD2B8\uD560 \uD0A4\uC6CC\uB4DC\uB97C \uC785\uB825, \uC904\uBC14\uAFC8\uC73C\uB85C \uAD6C\uBCC4\uD569\uB2C8\uB2E4."
  }), VM.createElement("p", null, "\uC9C0\uC815\uD55C \uD0A4\uC6CC\uB4DC\uAC00 \uD3EC\uD568\uB41C \uC81C\uBAA9\uC744 \uAC00\uC9C4 \uAC8C\uC2DC\uBB3C\uACFC \uB313\uAE00\uC744 \uC228\uAE41\uB2C8\uB2E4."))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uBBA4\uD2B8\uB41C \uC544\uCE74\uCF58"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "blockEmoticon",
    size: "6",
    multiple: "",
    "data-text-format": "%name%"
  }), VM.createElement("p", null, "\uC544\uCE74\uCF58 \uBBA4\uD2B8\uB294 \uB313\uAE00\uC5D0\uC11C \uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.", VM.createElement("br", null), "Ctrl, Shift, \uB9C8\uC6B0\uC2A4 \uB4DC\uB798\uADF8\uB97C \uC774\uC6A9\uD574\uC11C \uC5EC\uB7EC\uAC1C\uB97C \uB3D9\uC2DC\uC5D0 \uC120\uD0DD \uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."))), VM.createElement("hr", null), VM.createElement("h5", {
    class: "card-title"
  }, "\uCC44\uB110 \uAD00\uB9AC\uC790 \uC804\uC6A9"), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uC0AD\uC81C \uD14C\uC2A4\uD2B8 \uBAA8\uB4DC"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("select", {
    id: "useAutoRemoverTest",
    "data-type": "bool"
  }, VM.createElement("option", {
    value: "false"
  }, "\uC0AC\uC6A9 \uC548 \uD568"), VM.createElement("option", {
    value: "true"
  }, "\uC0AC\uC6A9")), VM.createElement("p", null, "\uAC8C\uC2DC\uBB3C\uC744 \uC0AD\uC81C\uD558\uC9C0 \uC54A\uACE0 \uC5B4\uB5A4 \uAC8C\uC2DC\uBB3C\uC774 \uC120\uD0DD\uB418\uB294\uC9C0 \uBD89\uC740 \uC0C9\uC73C\uB85C \uBCF4\uC5EC\uC90D\uB2C8\uB2E4."))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uC720\uC800 \uAC8C\uC2DC\uBB3C \uC0AD\uC81C"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("textarea", {
    id: "autoRemoveUser",
    rows: "6",
    placeholder: "\uB300\uC0C1 \uC774\uC6A9\uC790\uB97C \uC904\uBC14\uAFC8\uC73C\uB85C \uAD6C\uBCC4\uD558\uC5EC \uC785\uB825\uD569\uB2C8\uB2E4."
  }), VM.createElement("p", null, "\uC9C0\uC815\uD55C \uC720\uC800\uC758 \uAC8C\uC2DC\uBB3C\uC744 \uC790\uB3D9\uC73C\uB85C \uC0AD\uC81C\uD569\uB2C8\uB2E4."))), VM.createElement("div", {
    class: "row"
  }, VM.createElement("label", {
    class: "col-md-3"
  }, "\uD0A4\uC6CC\uB4DC \uD3EC\uD568 \uAC8C\uC2DC\uBB3C \uC0AD\uC81C"), VM.createElement("div", {
    class: "col-md-9"
  }, VM.createElement("textarea", {
    id: "autoRemoveKeyword",
    rows: "6",
    placeholder: "\uC0AD\uC81C\uD560 \uD0A4\uC6CC\uB4DC\uB97C \uC785\uB825, \uC904\uBC14\uAFC8\uC73C\uB85C \uAD6C\uBCC4\uD569\uB2C8\uB2E4."
  }), VM.createElement("p", null, "\uC9C0\uC815\uD55C \uD0A4\uC6CC\uB4DC\uAC00 \uD3EC\uD568\uB41C \uC81C\uBAA9\uC744 \uAC00\uC9C4 \uAC8C\uC2DC\uBB3C\uC744 \uC0AD\uC81C\uD569\uB2C8\uB2E4."))), VM.createElement("div", {
    class: "row btns"
  }, VM.createElement("div", {
    class: "col-12"
  }, VM.createElement("a", {
    href: "#",
    id: "exportConfig",
    class: "btn btn-primary"
  }, "\uC124\uC815 \uB0B4\uBCF4\uB0B4\uAE30"), VM.createElement("a", {
    href: "#",
    id: "importConfig",
    class: "btn btn-secondary"
  }, "\uC124\uC815 \uAC00\uC838\uC624\uAE30"), VM.createElement("a", {
    href: "#",
    id: "resetConfig",
    class: "btn btn-danger"
  }, "\uC124\uC815 \uCD08\uAE30\uD654"))), VM.createElement("div", {
    class: "row btns"
  }, VM.createElement("div", {
    class: "col-12"
  }, VM.createElement("a", {
    href: "#",
    id: "saveAndClose",
    class: "btn btn-primary"
  }, "\uC800\uC7A5"), VM.createElement("a", {
    href: "#",
    id: "closeSetting",
    class: "btn btn-success"
  }, "\uB2EB\uAE30"))))))));
  const contentWrapper = document.querySelector('.content-wrapper'); // 설정 버튼 클릭 이벤트

  showSettingBtn.addEventListener('click', () => {
    if (settingWrapper.classList.contains('hidden')) {
      loadConfig();
      contentWrapper.classList.add('disappear');
    } else {
      settingWrapper.classList.add('disappear');
    }
  }); // 애니메이션 처리

  contentWrapper.addEventListener('animationend', () => {
    if (contentWrapper.classList.contains('disappear')) {
      contentWrapper.classList.add('hidden');
      contentWrapper.classList.remove('disappear');
      settingWrapper.classList.add('appear');
      settingWrapper.classList.remove('hidden');
    } else if (contentWrapper.classList.contains('appear')) {
      contentWrapper.classList.remove('appear');
    }
  });
  settingWrapper.addEventListener('animationend', () => {
    if (settingWrapper.classList.contains('disappear')) {
      settingWrapper.classList.add('hidden');
      settingWrapper.classList.remove('disappear');
      contentWrapper.classList.add('appear');
      contentWrapper.classList.remove('hidden');
    } else if (settingWrapper.classList.contains('appear')) {
      settingWrapper.classList.remove('appear');
    }
  }); // 헤더에 버튼 부착

  document.querySelector('ul.navbar-nav').append(showSettingBtn);
  contentWrapper.insertAdjacentElement('afterend', settingWrapper);
  const comboElements = settingWrapper.querySelectorAll('select:not([multiple])');
  const textareaElements = settingWrapper.querySelectorAll('textarea');
  const textElements = settingWrapper.querySelectorAll('input[type="text"]');
  const listElements = settingWrapper.querySelectorAll('select[multiple]');

  for (const element of listElements) {
    const btnElement = VM.createElement("button", {
      href: "#",
      class: "btn btn-success"
    }, "\uC0AD\uC81C");
    btnElement.addEventListener('click', event => {
      event.target.disabled = true;
      const removeElements = element.selectedOptions;

      while (removeElements.length > 0) removeElements[0].remove();

      event.target.disabled = false;
    });
    element.insertAdjacentElement('afterend', btnElement);
  } // 이벤트 핸들러


  settingWrapper.querySelector('#removeMyImage').addEventListener('click', event => {
    event.target.disabled = true;

    if (confirm('등록한 자짤을 삭제하시겠습니까?')) {
      GM_setValue('myImage', '');
      alert('삭제되었습니다.');
    }

    event.target.disabled = false;
  });
  settingWrapper.querySelector('#exportConfig').addEventListener('click', event => {
    event.preventDefault();
    const data = btoa(encodeURIComponent(exportConfig()));
    navigator.clipboard.writeText(data);
    alert('클립보드에 설정이 복사되었습니다.');
  });
  settingWrapper.querySelector('#importConfig').addEventListener('click', event => {
    event.preventDefault();
    let data = prompt('가져올 설정 데이터를 입력해주세요');
    if (data == null) return;

    try {
      if (data == '') throw '[Setting/importConfig] 공백 값을 입력했습니다.';
      data = decodeURIComponent(atob(data));
      const config = JSON.parse(data);

      for (const key in config) {
        if ({}.hasOwnProperty.call(config, key)) {
          GM_setValue(key, config[key]);
        }
      }

      location.reload();
    } catch (error) {
      alert('올바르지 않은 데이터입니다.');
      console.error(error);
    }
  });
  settingWrapper.querySelector('#resetConfig').addEventListener('click', event => {
    event.preventDefault();
    if (!confirm('모든 설정이 초기화 됩니다. 계속하시겠습니까?')) return;
    reset();
    location.reload();
  });
  settingWrapper.querySelector('#saveAndClose').addEventListener('click', event => {
    event.preventDefault();

    for (const element of comboElements) {
      let value;

      switch (element.dataset.type) {
        case 'number':
          value = Number(element.value);
          break;

        case 'bool':
          value = element.value == 'true';
          break;

        default:
          value = null;
          break;
      }

      GM_setValue(element.id, value);
    }

    for (const element of textElements) {
      GM_setValue(element.id, element.value);
    }

    for (const element of textareaElements) {
      let value;

      if (element.value != '') {
        value = element.value.split('\n');
        value = value.filter(item => {
          return item != '';
        });
      } else {
        value = [];
      }

      GM_setValue(element.id, value);
    }

    for (const element of listElements) {
      const data = GM_getValue(element.id, defaultConfig[element.id]);
      const options = element.querySelectorAll('option');
      const keys = Array.from(options, o => o.value);

      for (const key in data) {
        if (keys.indexOf(key) == -1) delete data[key];
      }

      GM_setValue(element.id, data);
    }

    if (settingWrapper.querySelector('#categorySetting tbody').childElementCount == 0) {
      location.reload();
    }
  });
  settingWrapper.querySelector('#closeSetting').addEventListener('click', () => {
    settingWrapper.classList.add('disappear');
  });
}

function loadConfig() {
  const settingWrapper = document.querySelector('#refresherSetting'); // 설정 값 불러오기

  const comboElements = settingWrapper.querySelectorAll('select:not([multiple])');

  for (const element of comboElements) {
    element.value = GM_getValue(element.id, defaultConfig[element.id]);
  }

  const textareaElements = settingWrapper.querySelectorAll('textarea');

  for (const element of textareaElements) {
    element.value = GM_getValue(element.id, defaultConfig[element.id]).join('\n');
  }

  const textElements = settingWrapper.querySelectorAll('input[id][type="text"]');

  for (const element of textElements) {
    element.value = GM_getValue(element.id, defaultConfig[element.id]);
  }

  const listElements = settingWrapper.querySelectorAll('select[multiple]');

  for (const element of listElements) {
    if (element.childElementCount) {
      while (element.childElementCount) element.removeChild(element.firstChild);
    }

    const data = GM_getValue(element.id, defaultConfig[element.id]);

    for (const key of Object.keys(data)) {
      const option = VM.createElement("option", null);
      option.value = key;
      const reservedWord = element.dataset.textFormat.match(/%\w*%/g);
      let text = element.dataset.textFormat;

      if (text != '') {
        for (const word of reservedWord) {
          switch (word) {
            case '%key%':
              text = text.replace(word, key);
              break;

            case '%value%':
              text = text.replace(word, data[key]);
              break;

            default:
              text = text.replace(word, data[key][word.replace(/%/g, '')]);
              break;
          }
        }
      } else {
        text = key;
      }

      option.textContent = text;
      element.append(option);
    }
  }
}

function setupCategory(channel) {
  const settingWrapper = document.querySelector('#refresherSetting');
  const showSettingBtn = document.getElementById('showSetting');
  const categoryTable = settingWrapper.querySelector('#categorySetting tbody'); // 설정 버튼 클릭 이벤트

  showSettingBtn.addEventListener('click', () => {
    if (settingWrapper.classList.contains('hidden')) {
      loadCategoryConfig(channel);
    }
  }); // 카테고리 목록 등록

  const boardCategoryElements = document.querySelectorAll('.board-category a');

  for (const element of boardCategoryElements) {
    const name = element.textContent == '전체' ? '일반' : element.textContent;
    const tableCategoryElement = VM.createElement("tr", {
      id: name
    }, VM.createElement("td", null, name), name == '일반' && VM.createElement("td", null, VM.createElement("input", {
      type: "text",
      name: "color",
      placeholder: "000000",
      disabled: ""
    })), name != '일반' && VM.createElement("td", null, VM.createElement("input", {
      type: "text",
      name: "color",
      placeholder: "000000",
      maxlength: "6"
    })), VM.createElement("td", null, VM.createElement("label", null, VM.createElement("input", {
      type: "checkbox",
      name: "blockPreview"
    }), VM.createElement("span", null, " \uBBF8\uB9AC\uBCF4\uAE30 \uC228\uAE40 ")), VM.createElement("label", null, VM.createElement("input", {
      type: "checkbox",
      name: "blockArticle"
    }), VM.createElement("span", null, " \uAC8C\uC2DC\uBB3C \uBBA4\uD2B8 "))));
    categoryTable.append(tableCategoryElement);
  } // 이벤트 핸들러


  categoryTable.addEventListener('keypress', event => {
    const regex = /[0-9a-fA-F]/;
    if (!regex.test(event.key)) event.preventDefault();
  });
  categoryTable.addEventListener('dblclick', event => {
    if (event.target.name != 'color') return;
    if (event.target.disabled) return;
    const color = getRandomColor();
    event.target.value = color;
    event.target.style.backgroundColor = `#${color}`;
    event.target.style.color = getContrastYIQ(color);
  });
  categoryTable.addEventListener('input', event => {
    if (event.target.value.length == 6 || event.target.value.length == 3) {
      const color = event.target.value;
      const textColor = getContrastYIQ(color);
      event.target.style.backgroundColor = `#${color}`;
      event.target.style.color = textColor;
    } else {
      event.target.style.backgroundColor = '';
      event.target.style.color = '';
    }
  });
  settingWrapper.querySelector('#saveAndClose').addEventListener('click', event => {
    event.preventDefault();
    const categoryConfig = GM_getValue('category', defaultConfig.category);
    const rows = settingWrapper.querySelectorAll('#categorySetting tr');

    if (categoryConfig[channel] == undefined) {
      categoryConfig[channel] = {};
    }

    for (const row of rows) {
      if (categoryConfig[channel][row.id] == undefined) {
        categoryConfig[channel][row.id] = {};
      }

      categoryConfig[channel][row.id].color = row.querySelector('[name="color"]').value.toUpperCase();
      categoryConfig[channel][row.id].blockPreview = row.querySelector('[name="blockPreview"]').checked;
      categoryConfig[channel][row.id].blockArticle = row.querySelector('[name="blockArticle"]').checked;
    }

    GM_setValue('category', categoryConfig);
    location.reload();
  });
}

function loadCategoryConfig(channel) {
  // 카테고리 설정 불러오기
  const categoryConfig = GM_getValue('category', defaultConfig.category);

  if (categoryConfig[channel] == undefined) {
    categoryConfig[channel] = {};
  }

  for (const key of Object.keys(categoryConfig[channel])) {
    const row = document.getElementById(key);

    if (row) {
      const colorInput = row.querySelector('[name="color"]');
      colorInput.value = categoryConfig[channel][key].color;

      if (categoryConfig[channel][key].color == '') {
        colorInput.style.backgroundColor = '';
        colorInput.style.color = '';
      } else {
        colorInput.style.backgroundColor = `#${categoryConfig[channel][key].color}`;
        colorInput.style.color = getContrastYIQ(categoryConfig[channel][key].color);
      }

      row.querySelector('[name="blockPreview"]').checked = categoryConfig[channel][key].blockPreview;
      row.querySelector('[name="blockArticle"]').checked = categoryConfig[channel][key].blockArticle;
    }
  }
}

function apply() {
  const hideAvatar = GM_getValue('hideAvatar', defaultConfig.hideAvatar);
  const hideMedia = GM_getValue('hideMedia', defaultConfig.hideMedia);
  const hideModified = GM_getValue('hideModified', defaultConfig.hideModified);
  const hideSideMenu = GM_getValue('hideSideMenu', defaultConfig.hideSideMenu);
  const contentWrapper = document.querySelector('.content-wrapper');
  if (hideAvatar) contentWrapper.classList.add('hide-avatar');
  if (hideMedia) contentWrapper.classList.add('hide-media');
  if (hideModified) contentWrapper.classList.add('hide-modified');
  if (hideSideMenu) contentWrapper.classList.add('hide-sidemenu');
}

function filter(articles, channel) {
  const categoryConfig = GM_getValue('category', defaultConfig.category);
  articles.forEach(article => {
    const badge = article.querySelector('.badge');
    if (badge == null) return;
    let category = badge.textContent;
    category = category == '' ? '일반' : category;
    const preview = article.querySelector('.vrow-preview');

    if (categoryConfig[channel] && categoryConfig[channel][category]) {
      const filtered = categoryConfig[channel][category].blockPreview || false;
      if (filtered && preview != null) preview.remove();
    }
  });
}

var css_248z$1 = "#imageList {\r\n    margin: 1rem 0;\r\n}\r\n\r\n#imageList img {\r\n    width: 50px;\r\n}\r\n\r\n#imageList .video-placeholder {\r\n    display: flex;\r\n    height: 50px;\r\n    align-items: center;\r\n    justify-content: center;\r\n}\r\n\r\n#imageList tbody a {\r\n    word-break: break-all;\r\n    color: #000;\r\n}\r\n\r\n#imageList tfoot td {\r\n    padding: 0;\r\n}\r\n\r\n#imageList button {\r\n    width: 100%;\r\n    margin: 0;\r\n}\r\n\r\n@media (prefers-color-scheme:dark) {\r\n    #imageList tbody a {\r\n        color: #e2e2e2;\r\n    }\r\n}";

function apply$1() {
  const data = parse();
  if (data.length == 0) return;
  document.head.append(VM.createElement("style", null, css_248z$1));
  const table = VM.createElement("div", {
    class: "article-image hidden"
  }, VM.createElement("table", {
    class: "table align-middle",
    id: "imageList"
  }, VM.createElement("colgroup", null, VM.createElement("col", {
    width: "5%"
  }), VM.createElement("col", {
    width: "10%"
  }), VM.createElement("col", {
    width: "85%"
  })), VM.createElement("thead", null, VM.createElement("th", null, VM.createElement("input", {
    type: "checkbox",
    name: "selectAll"
  })), VM.createElement("th", null, "\uC378\uB124\uC77C"), VM.createElement("th", null, "\uD30C\uC77C\uBA85")), VM.createElement("tbody", null), VM.createElement("tfoot", null, VM.createElement("td", {
    colspan: "3"
  }, VM.createElement("button", {
    class: "btn btn-success"
  }, "\uC77C\uAD04 \uB2E4\uC6B4\uB85C\uB4DC")))));
  const enableBtn = VM.createElement("a", {
    href: "#",
    class: "btn btn-success"
  }, VM.createElement("span", {
    class: "ion-ios-download-outline"
  }), " \uC774\uBBF8\uC9C0 \uB2E4\uC6B4\uB85C\uB4DC \uBAA9\uB85D \uBCF4\uC774\uAE30");
  enableBtn.addEventListener('click', event => {
    event.preventDefault();

    if (table.classList.contains('hidden')) {
      table.classList.remove('hidden');
    } else {
      table.classList.add('hidden');
    }
  });
  document.querySelector('.article-body').insertAdjacentElement('afterend', enableBtn).insertAdjacentElement('afterend', table);
  const list = table.querySelector('tbody');

  for (const d of data) {
    const itemElement = VM.createElement("tr", null, VM.createElement("td", null, VM.createElement("input", {
      type: "checkbox",
      name: "select"
    })), VM.createElement("td", null, d.type == 'image' && VM.createElement("img", {
      src: d.thumb
    }), d.type != 'image' && VM.createElement("div", {
      class: "video-placeholder"
    }, VM.createElement("span", {
      class: "ion-ios-videocam"
    }, " \uB3D9\uC601\uC0C1"))), VM.createElement("td", null, VM.createElement("a", {
      href: "#",
      "data-url": d.url
    }, d.image)));
    list.append(itemElement);
  }

  table.addEventListener('click', async event => {
    if (event.target.tagName == 'A') {
      event.preventDefault();
      const url = event.target.dataset.url;

      if (url != '') {
        event.target.dataset.url = '';
        const filename = event.target.textContent;
        const file = await download(url, event.target, '다운로드 중...[percent]%', filename);
        window.saveAs(file, filename);
        event.target.dataset.url = url;
      }
    } else if (event.target.name == 'selectAll') {
      const inputElements = table.querySelectorAll('input[type="checkbox"]');

      for (const i of inputElements) {
        i.checked = event.target.checked;
      }
    }
  });
  const downloadBtn = table.querySelector('tfoot button');
  downloadBtn.addEventListener('click', async event => {
    event.preventDefault();
    downloadBtn.disabled = true;
    const checkboxElements = list.querySelectorAll('input[type="checkbox"]');
    const urlElements = list.querySelectorAll('a');
    const originalText = downloadBtn.textContent;
    const downloadList = [];
    const nameList = [];

    for (let i = 0; i < urlElements.length; i += 1) {
      if (checkboxElements[i].checked) {
        downloadList.push(urlElements[i].dataset.url);
        nameList.push(urlElements[i].textContent);
      }
    }

    if (downloadList.length == 0) {
      alert('선택된 파일이 없습니다.');
      downloadBtn.disabled = false;
      return;
    }

    const zip = new JSZip();
    const total = downloadList.length;

    for (let i = 0; i < total; i += 1) {
      const file = await download(downloadList[i], downloadBtn, `다운로드 중...[percent]% (${i}/${total})`);
      zip.file(`${`${i}`.padStart(3, '0')}_${nameList[i]}`, file);
    }

    downloadBtn.textContent = originalText;
    const title = document.querySelector('.article-head .title');
    const category = document.querySelector('.article-head .badge');
    const author = document.querySelector('.article-head .user-info');
    const channel = document.querySelector('.board-title a:not([class])');
    let filename = GM_getValue('imageDownloaderFileName', defaultConfig.imageDownloaderFileName);
    const reservedWord = filename.match(/%\w*%/g);

    for (const word of reservedWord) {
      try {
        switch (word) {
          case '%title%':
            filename = filename.replace(word, title.textContent.trim());
            break;

          case '%category%':
            filename = filename.replace(word, category.textContent.trim());
            break;

          case '%author%':
            filename = filename.replace(word, author.innerText.trim());
            break;

          case '%channel%':
            filename = filename.replace(word, channel.textContent.trim());
            break;

          default:
            break;
        }
      } catch (error) {
        console.warn(error);
        filename = filename.replace(word, '');
      }
    }

    const zipblob = await zip.generateAsync({
      type: 'blob'
    });
    window.saveAs(zipblob, `${filename}.zip`);
    downloadBtn.disabled = false;
  });
}

function parse() {
  const images = document.querySelectorAll('.article-body img, .article-body video');
  const result = [];
  images.forEach(element => {
    let src = element.src;

    if (element.getAttribute('data-orig') != null) {
      src += `.${element.getAttribute('data-orig')}`;
    }

    const item = {};
    item.thumb = `${src}?type=list`;
    item.url = `${src}?type=orig`;
    item.image = src.replace(/.*\.arca\.live\/.*\//, '').replace(/\..*\./, '.');
    item.type = ['gif', 'png', 'jpg', 'jpeg', 'wepb'].indexOf(item.image.split('.')[1]) > -1 ? 'image' : 'video';
    result.push(item);
  });
  return result;
}

function download(url, element, progressString, loadString) {
  return new Promise((resolve, reject) => {
    GM_xmlhttpRequest({
      method: 'GET',
      url,
      responseType: 'blob',
      onprogress: event => {
        let text = null;

        if (progressString) {
          text = progressString.replace('[percent]', Math.round(event.loaded / event.total * 100));
        } else {
          text = `${Math.round(event.loaded / event.total * 100)}%`;
        }

        if (element) element.textContent = text;
      },
      onload: response => {
        if (loadString) element.textContent = loadString;
        resolve(response.response);
      },
      onerror: reject
    });
  });
}

var styles = {"wrapper":"ArticleContextMenu-module_wrapper__HgPxK","menu":"ArticleContextMenu-module_menu__156PJ","devider":"ArticleContextMenu-module_devider__28LCE","item":"ArticleContextMenu-module_item__18yvS"};
var stylesheet=".ArticleContextMenu-module_wrapper__HgPxK {\r\n    position: fixed;\r\n    display:flex;\r\n    justify-content: center;\r\n    align-items: center;\r\n    top: 0;\r\n    left: 0;\r\n    background-color: rgba(0, 0, 0, 0);\r\n    width: 100%;\r\n    height: 100%;\r\n    pointer-events: none;\r\n}\r\n\r\n.ArticleContextMenu-module_menu__156PJ {\r\n    position: absolute;\r\n    width: 300px;\r\n    padding: .5rem;\r\n    border: 1px solid #bbb;\r\n    background-color: #fff;\r\n    z-index: 20;\r\n    pointer-events: auto;\r\n}\r\n\r\n.ArticleContextMenu-module_menu__156PJ .ArticleContextMenu-module_devider__28LCE {\r\n    height: 1px;\r\n    margin: .5rem 0;\r\n    overflow: hidden;\r\n    background-color: #e5e5e5;\r\n}\r\n\r\n.ArticleContextMenu-module_menu__156PJ .ArticleContextMenu-module_item__18yvS {\r\n    display: block;\r\n    width: 100%;\r\n    padding: 3px 20px;\r\n    clear: both;\r\n    font-weight: 400;\r\n    color: #373a3c;\r\n    white-space: nowrap;\r\n    border: 0;\r\n}\r\n\r\n.ArticleContextMenu-module_menu__156PJ .ArticleContextMenu-module_item__18yvS:hover,\r\n.ArticleContextMenu-module_menu__156PJ .ArticleContextMenu-module_item__18yvS:focus {\r\n    color: #2b2d2f;\r\n    background-color: #f5f5f5;\r\n    text-decoration: none;\r\n}";

function apply$2() {
  const articleBody = document.querySelector('article .article-body');
  if (articleBody == null) return;
  document.head.append(VM.createElement("style", null, stylesheet));
  const wrapper = VM.createElement("div", {
    class: `${styles.wrapper} hidden`
  }, VM.createElement("div", {
    class: styles.menu,
    id: "context-menu",
    "data-url": "",
    "data-html": "",
    "data-orig": ""
  }, VM.createElement("a", {
    href: "#",
    class: styles.item,
    id: "copy-clipboard"
  }, "\uC774\uBBF8\uC9C0\uB97C \uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uBCF5\uC0AC"), VM.createElement("a", {
    href: "#",
    class: styles.item,
    id: "save"
  }, "SAVE_SOMETHING"), VM.createElement("a", {
    href: "#",
    class: styles.item,
    id: "copy-url"
  }, "\uC6D0\uBCF8 \uC8FC\uC18C \uBCF5\uC0AC"), VM.createElement("a", {
    href: "#",
    class: styles.item,
    id: "apply-myimage"
  }, "\uC790\uC9E4\uB85C \uB4F1\uB85D"), VM.createElement("div", {
    id: "search-wrapper"
  }, VM.createElement("div", {
    class: styles.devider
  }), VM.createElement("a", {
    href: "",
    class: styles.item,
    id: "search-google",
    target: "_blank",
    rel: "noreferrer"
  }, "Google \uAC80\uC0C9"), VM.createElement("a", {
    href: "",
    class: styles.item,
    id: "search-yandex",
    target: "_blank",
    rel: "noreferrer",
    title: "\uB7EC\uC2DC\uC544 \uAC80\uC0C9\uC5D4\uC9C4\uC785\uB2C8\uB2E4."
  }, "Yandex \uAC80\uC0C9"), VM.createElement("a", {
    href: "#",
    class: styles.item,
    id: "search-saucenao",
    target: "_blank",
    title: "\uB9DD\uAC00, \uD53D\uC2DC\uBE0C \uC0AC\uC774\uD2B8 \uAC80\uC0C9\uC744 \uC9C0\uC6D0\uD569\uB2C8\uB2E4."
  }, "SauceNao \uAC80\uC0C9"), VM.createElement("a", {
    href: "#",
    class: styles.item,
    id: "search-twigaten",
    target: "_blank",
    title: "\uD2B8\uC704\uD130 \uC774\uBBF8\uC9C0 \uAC80\uC0C9\uC744 \uC9C0\uC6D0\uD569\uB2C8\uB2E4."
  }, "TwiGaTen \uAC80\uC0C9"), VM.createElement("a", {
    href: "#",
    class: styles.item,
    id: "search-ascii2d",
    target: "_blank",
    title: "\uD2B8\uC704\uD130, \uD53D\uC2DC\uBE0C \uC0AC\uC774\uD2B8 \uAC80\uC0C9\uC744 \uC9C0\uC6D0\uD569\uB2C8\uB2E4."
  }, "Ascii2D \uAC80\uC0C9"))));
  wrapper.addEventListener('contextmenu', event => {
    event.preventDefault();
  });
  wrapper.addEventListener('click', onClickContextMenu);
  document.querySelector('.root-container').append(wrapper);
  const context = wrapper.querySelector('#context-menu');

  function closeContext() {
    if (!wrapper.classList.contains('hidden')) wrapper.classList.add('hidden');
  }

  function onAnimationEnd() {
    if (wrapper.classList.contains('appear')) {
      wrapper.classList.remove('appear');
    }
  }

  wrapper.addEventListener('animationend', onAnimationEnd);
  document.addEventListener('click', closeContext);
  document.addEventListener('contextmenu', closeContext);
  document.addEventListener('scroll', closeContext);
  articleBody.addEventListener('contextmenu', event => {
    if (event.target.tagName != 'IMG' && event.target.tagName != 'VIDEO') return;

    if (!wrapper.classList.contains(styles.mobile)) {
      context.setAttribute('style', `left: ${event.clientX + 2}px; top: ${event.clientY + 2}px`);
    }

    if (!wrapper.classList.contains('hidden')) {
      wrapper.classList.add('hidden');
      return;
    }

    event.preventDefault();
    event.stopPropagation();
    wrapper.classList.remove('hidden');
    let url = event.target.src;
    let type;

    if (event.target.getAttribute('data-orig')) {
      url = `${url}.${event.target.getAttribute('data-orig')}?type=orig`;
      type = event.target.getAttribute('data-orig');
    } else {
      url = `${url}?type=orig`;
      type = event.target.src.replace(/.*\.arca\.live\/.*\/.*\./, '');
    }

    context.setAttribute('data-url', url);
    context.setAttribute('data-html', event.target.outerHTML);
    context.querySelector('#search-google').href = `https://www.google.com/searchbyimage?safe=off&image_url=${url}`;
    context.querySelector('#search-yandex').href = `https://yandex.com/images/search?rpt=imageview&url=${url}`;

    if (['gif', 'png', 'jpg', 'jpeg', 'wepb'].indexOf(type) > -1) {
      context.querySelector('#copy-clipboard').removeAttribute('style');
      context.querySelector('#save').innerText = '원본 이미지 저장';
      context.querySelector('#search-wrapper').removeAttribute('style');
    } else {
      context.querySelector('#copy-clipboard').setAttribute('style', 'display:none');
      context.querySelector('#save').innerText = '원본 비디오 저장';
      context.querySelector('#search-wrapper').setAttribute('style', 'display:none');
    }
  });
}

async function onClickContextMenu(event) {
  const context = document.querySelector('#context-menu');
  const originalText = event.target.textContent;

  if (event.target.id == 'copy-clipboard') {
    event.preventDefault();
    event.stopPropagation();
    const url = context.getAttribute('data-url');
    GM_xmlhttpRequest({
      method: 'GET',
      url,
      responseType: 'arraybuffer',
      onprogress: e => {
        event.target.textContent = `${Math.round(e.loaded / e.total * 100)}%`;
      },
      onload: response => {
        const buffer = response.response;
        const blob = new Blob([buffer], {
          type: 'image/png'
        });
        const item = new ClipboardItem({
          [blob.type]: blob
        });
        navigator.clipboard.write([item]);
        context.parentNode.classList.add('hidden');
        event.target.textContent = originalText;
      }
    });
    return;
  }

  if (event.target.id == 'save') {
    event.preventDefault();
    event.stopPropagation();
    const url = context.getAttribute('data-url');
    const imgBlob = await download(url, event.target, '[percent]%', event.target.textContent);
    window.saveAs(imgBlob, `image.${imgBlob.type.split('/')[1]}`);
    context.parentNode.classList.add('hidden');
  }

  if (event.target.id == 'copy-url') {
    event.preventDefault();
    const url = context.getAttribute('data-url');
    navigator.clipboard.writeText(url);
  }

  if (event.target.id == 'apply-myimage') {
    event.preventDefault();
    const html = context.getAttribute('data-html');
    GM_setValue('myImage', html);
    alert('선택한 짤이 등록되었습니다.\n새 게시물 작성 시 최상단에 자동으로 첨부됩니다.');
  }

  if (event.target.id.indexOf('search') > -1) {
    if (event.target.id == 'search-google') return;
    if (event.target.id == 'search-yandex') return;
    event.preventDefault();
    event.stopPropagation();
    const img = context.getAttribute('data-url');
    const db = event.target.id.split('-')[1];

    try {
      const imgBlob = await download(img, event.target);
      event.target.textContent = '업로드 중...';
      let url = '';
      const formdata = new FormData();
      formdata.append('file', imgBlob, `image.${imgBlob.type.split('/')[1]}`);

      if (db == 'saucenao') {
        formdata.append('frame', 1);
        formdata.append('database', 999);
        url = 'https://saucenao.com/search.php';
      } else if (db == 'ascii2d') {
        const tokenDocument = await new Promise((resolve, reject) => {
          GM_xmlhttpRequest({
            method: 'GET',
            url: 'https://ascii2d.net',
            responseType: 'document',
            data: formdata,
            onload: resolve,
            onerror: () => {
              reject(new Error('Access Rejected'));
            }
          });
        });
        const token = tokenDocument.response.querySelector('input[name="authenticity_token"]').value;
        formdata.append('utf8', '✓');
        formdata.append('authenticity_token', token);
        url = 'https://ascii2d.net/search/file';
      } else if (db == 'twigaten') {
        url = 'https://twigaten.204504byse.info/search/media';
      }

      const result = await new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
          method: 'POST',
          url,
          responseType: 'document',
          data: formdata,
          onload: resolve,
          onerror: () => {
            reject(new Error('Access Rejected'));
          }
        });
      });

      if (db == 'saucenao') {
        const replaceURL = result.response.querySelector('#yourimage a').href.split('image=')[1];
        window.open(`https://saucenao.com/search.php?db=999&url=https://saucenao.com/userdata/tmp/${replaceURL}`);
      } else if (db == 'ascii2d') {
        window.open(result.finalUrl);
      } else if (db == 'twigaten') {
        window.open(result.finalUrl);
      }
    } catch (error) {
      alert('업로드 중 발생했습니다.\n개발자 도구(F12)의 콘솔(Console) 탭을 캡처해서 문의바랍니다.');
      console.error(error);
    } finally {
      context.parentNode.classList.add('hidden');
      event.target.textContent = originalText;
    }
  }
}

function getTimeStr(datetime) {
  const date = new Date(datetime);
  let hh = date.getHours();
  let mm = date.getMinutes();

  if (hh.toString().length == 1) {
    hh = `0${hh}`;
  }

  if (mm.toString().length == 1) {
    mm = `0${mm}`;
  }

  return `${hh}:${mm}`;
}
function getDateStr(datetime) {
  const date = new Date(datetime);
  const year = date.getFullYear();
  let month = date.getMonth() + 1;
  let day = date.getDate();
  let hh = date.getHours();
  let mm = date.getMinutes();
  let ss = date.getSeconds();

  if (month.toString().length == 1) {
    month = `0${month}`;
  }

  if (day.toString().length == 1) {
    day = `0${day}`;
  }

  if (hh.toString().length == 1) {
    hh = `0${hh}`;
  }

  if (mm.toString().length == 1) {
    mm = `0${mm}`;
  }

  if (ss.toString().length == 1) {
    ss = `0${ss}`;
  }

  return `${year}-${month}-${day} ${hh}:${mm}:${ss}`;
}
function in24(datetime) {
  const target = new Date(datetime);
  const criteria = new Date();
  criteria.setHours(criteria.getHours() - 24);
  if (target > criteria) return true;
  return false;
}

function blockArticle(board, articles, channel) {
  if (document.readyState != 'complete') {
    window.addEventListener('load', () => {
      blockArticle(board, articles, channel);
    }, {
      once: true
    });
    return;
  }

  const count = {
    keyword: 0,
    user: 0,
    category: 0,
    notice: 0,
    all: 0
  };
  let userlist = GM_getValue('blockUser', defaultConfig.blockUser);
  let keywordlist = GM_getValue('blockKeyword', defaultConfig.blockKeyword);
  const categoryConfig = GM_getValue('category', defaultConfig.category);

  if ((unsafeWindow.LiveConfig || undefined) && unsafeWindow.LiveConfig.mute != undefined) {
    userlist.push(...unsafeWindow.LiveConfig.mute.users);
    keywordlist.push(...unsafeWindow.LiveConfig.mute.keywords);
    userlist = Array.from(new Set(userlist));
    keywordlist = Array.from(new Set(keywordlist));
  }

  articles.forEach(item => {
    const title = item.querySelector('.col-title');
    const author = item.querySelector('.col-author');
    const categoryElement = item.querySelector('.badge');
    let category;

    if (categoryElement == null || categoryElement.textContent == '') {
      category = '일반';
    } else {
      category = categoryElement.textContent;
    }

    const authorAllow = userlist.length == 0 ? false : new RegExp(userlist.join('|')).test(author.innerText);
    const titleAllow = keywordlist.length == 0 ? false : new RegExp(keywordlist.join('|')).test(title.innerText);
    let categoryAllow = false;

    if (categoryConfig[channel] && categoryConfig[channel][category]) {
      categoryAllow = categoryConfig[channel][category].blockArticle;
    }

    if (titleAllow) {
      item.classList.add('filtered');
      item.classList.add('filtered-keyword');
      count.keyword += 1;
    }

    if (authorAllow) {
      item.classList.add('filtered');
      item.classList.add('filtered-user');
      count.user += 1;
    }

    if (categoryAllow) {
      item.classList.add('filtered');
      item.classList.add('filtered-category');
      count.category += 1;
    }

    if (item.classList.contains('notice-board') && item.nextElementSibling.classList.contains('notice-board')) {
      item.classList.add('filtered');
      item.classList.add('filtered-notice');
      count.notice += 1;
    }

    if (item.classList.contains('filtered')) count.all += 1;
  });
  let toggleHeader = board.querySelector('.frontend-header');
  if (toggleHeader) toggleHeader.remove();
  toggleHeader = VM.createElement("div", {
    class: "frontend-header"
  }, VM.createElement("span", {
    class: "filter-title"
  }, "\uD544\uD130\uB41C \uAC8C\uC2DC\uBB3C"), VM.createElement("span", {
    class: "filter-count-container"
  }));
  const container = toggleHeader.querySelector('.filter-count-container');

  if (count.all > 0) {
    board.prepend(toggleHeader);

    for (const key of Object.keys(count)) {
      if (count[key] > 0) {
        let className = `show-filtered-${key}`;
        if (key == 'all') className = 'show-filtered';
        let text;

        switch (key) {
          case 'all':
            text = '전체';
            break;

          case 'keyword':
            text = '키워드';
            break;

          case 'user':
            text = '사용자';
            break;

          case 'category':
            text = '카테고리';
            break;

          case 'notice':
            text = '공지';
            break;
        }

        const btn = VM.createElement("span", {
          class: `filter-count filter-count-${key}`
        }, text, " (", count[key], ")");
        container.append(btn);
        btn.addEventListener('click', () => {
          if (board.classList.contains(className)) {
            board.classList.remove(className);
          } else {
            board.classList.add(className);
          }
        });

        if (key == 'notice') {
          // eslint-disable-next-line no-loop-func
          btn.addEventListener('click', () => {
            if (board.classList.contains(className)) {
              GM_setValue('hideNotice', false);
            } else {
              GM_setValue('hideNotice', true);
            }
          });
        }
      }
    }
  }

  const noticeConfig = GM_getValue('hideNotice', defaultConfig.hideNotice);
  if (!noticeConfig) board.classList.add('show-filtered-notice');
}
function blockComment(comments) {
  if (document.readyState != 'complete') {
    window.addEventListener('load', () => {
      blockComment(comments);
    }, {
      once: true
    });
    return;
  }

  const count = {
    keyword: 0,
    user: 0,
    all: 0
  };
  comments.forEach(item => {
    const author = item.querySelector('.user-info');
    const message = item.querySelector('.message');
    let userlist = GM_getValue('blockUser', defaultConfig.blockUser);
    let keywordlist = GM_getValue('blockKeyword', defaultConfig.blockKeyword);

    if ((unsafeWindow.LiveConfig || undefined) && unsafeWindow.LiveConfig.mute != undefined) {
      userlist.push(...unsafeWindow.LiveConfig.mute.users);
      keywordlist.push(...unsafeWindow.LiveConfig.mute.keywords);
      userlist = Array.from(new Set(userlist));
      keywordlist = Array.from(new Set(keywordlist));
    }

    const authorAllow = userlist.length == 0 ? false : new RegExp(userlist.join('|')).test(author.innerText);
    const textAllow = keywordlist.length == 0 ? false : new RegExp(keywordlist.join('|')).test(message.innerText);

    if (textAllow) {
      item.classList.add('filtered');
      item.classList.add('filtered-keyword');
      count.keyword += 1;
    }

    if (authorAllow) {
      item.classList.add('filtered');
      item.classList.add('filtered-user');
      count.user += 1;
    }

    if (item.classList.contains('deleted')) {
      item.classList.add('filtered');
      item.classList.add('filtered-deleted');
    }

    if (item.classList.contains('filtered')) count.all += 1;
  });
  let toggleHeader = document.querySelector('#comment .frontend-header');
  if (toggleHeader) toggleHeader.remove();
  toggleHeader = VM.createElement("div", {
    class: "frontend-header"
  }, VM.createElement("span", {
    class: "filter-title"
  }, "\uD544\uD130\uB41C \uAC8C\uC2DC\uBB3C"), VM.createElement("span", {
    class: "filter-count-container"
  }));
  const container = toggleHeader.querySelector('.filter-count-container');

  if (count.all > 0) {
    document.querySelector('#comment .title').insertAdjacentElement('afterend', toggleHeader);

    for (const key of Object.keys(count)) {
      if (count[key] > 0) {
        let className = `show-filtered-${key}`;
        if (key == 'all') className = 'show-filtered';
        let text;

        switch (key) {
          case 'all':
            text = '전체';
            break;

          case 'keyword':
            text = '키워드';
            break;

          case 'user':
            text = '사용자';
            break;

          case 'deleted':
            text = '삭제됨';
            break;
        }

        const btn = VM.createElement("span", {
          class: `filter-count filter-count-${key}`
        }, text, " (", count[key], ")");
        container.append(btn);
        btn.addEventListener('click', () => {
          const list = document.querySelector('#comment .list-area');

          if (list.classList.contains(className)) {
            list.classList.remove(className);
            toggleHeader.classList.remove(className);
          } else {
            list.classList.add(className);
            toggleHeader.classList.add(className);
          }
        });
      }
    }
  }

  for (const key of Object.keys(count)) {
    const btn = container.querySelector(`.filter-count-${key}`);
    if (btn) container.append(btn);
  }
}
function blockEmoticon(comments) {
  const blockEmoticons = GM_getValue('blockEmoticon', defaultConfig.blockEmoticon);
  let list = [];

  for (const key in blockEmoticons) {
    if ({}.hasOwnProperty.call(blockEmoticons, key)) {
      list = list.concat(blockEmoticons[key].bundle);
    }
  }

  comments.forEach(item => {
    const emoticon = item.querySelector('.emoticon');

    if (emoticon) {
      const id = emoticon.dataset.id;

      if (list.indexOf(id) > -1) {
        emoticon.closest('.message').innerText = '[아카콘 뮤트됨]';
      }
    }
  });
}
function blockRatedown() {
  if (!GM_getValue('blockRatedown', defaultConfig.blockRatedown)) return;
  const ratedown = document.querySelector('#rateDown');
  if (ratedown == null) return;
  ratedown.addEventListener('click', e => {
    if (!confirm('비추천을 눌렀습니다.\n계속하시겠습니까?')) {
      e.preventDefault();
    }
  });
}

var styles$1 = {"green":"IPScouter-module_green__K9yWK","red":"IPScouter-module_red__3yMjL","blue":"IPScouter-module_blue__YSAPo"};
var stylesheet$1=".vcol.col-author {\r\n    width: 7.5rem !important;\r\n}\r\n\r\n.IPScouter-module_green__K9yWK {\r\n    color: rgb(37, 141, 37)\r\n}\r\n\r\n.IPScouter-module_red__3yMjL {\r\n    color: rgb(236, 69, 69)\r\n}\r\n\r\n.IPScouter-module_blue__YSAPo {\r\n    color: rgb(56, 174, 252)\r\n}";

const db = {
  KT: ['1.96', '1.97', '1.98', '1.99', '1.100', '1.101', '1.102', '1.103', '1.104', '1.105', '1.106', '1.107', '1.108', '1.109', '1.110', '1.111', '39.4', '39.5', '39.6', '39.7', '49.16', '49.17', '49.18', '49.19', '49.20', '49.21', '49.22', '49.23', '49.24', '49.25', '49.26', '49.27', '49.28', '49.29', '49.30', '49.31', '49.56', '49.57', '49.58', '49.59', '49.60', '49.61', '49.62', '49.63', '110.68', '110.69', '110.70', '110.71', '116.200', '116.201', '118.234', '118.235', '119.194', '163.213', '163.222', '163.229', '163.255', '175.216', '175.217', '175.218', '175.219', '175.220', '175.221', '175.222', '175.223'],
  SK: ['27.160', '27.161', '27.162', '27.163', '27.164', '27.165', '27.166', '27.167', '27.168', '27.169', '27.170', '27.171', '27.172', '27.173', '27.174', '27.175', '27.176', '27.177', '27.178', '27.179', '27.180', '27.181', '27.182', '27.183', '42.16', '42.17', '42.18', '42.19', '42.20', '42.21', '42.22', '42.23', '42.24', '42.25', '42.26', '42.27', '42.28', '42.29', '42.30', '42.31', '42.32', '42.33', '42.34', '42.35', '42.36', '42.37', '42.38', '42.39', '42.40', '42.41', '42.42', '42.43', '42.44', '42.45', '42.46', '42.47', '58.102', '58.103', '111.218', '111.219', '113.216', '113.217', '114.52', '114.53', '123.228', '123.229', '124.0', '124.1', '124.2', '124.3', '124.136', '124.137', '124.138', '124.139', '180.132', '180.133', '180.134', '180.135', '219.252', '219.253', '220.103', '223.32', '223.33', '223.34', '223.35', '223.36', '223.37', '223.38', '223.39', '223.40', '223.41', '223.42', '223.43', '223.44', '223.45', '223.46', '223.47', '223.48', '223.49', '223.50', '223.51', '223.52', '223.53', '223.54', '223.55', '223.56', '223.57', '223.58', '223.59', '223.60', '223.61', '223.62', '223.63'],
  LG: ['106.96', '109.97', '109.98', '109.99', '106.100', '106.101', '106.102', '106.103', '117.110', '117.111', '211.36', '223.168', '223.169', '223.170', '223.171', '223.172', '223.173', '223.174', '223.175'],
  proxy: ['5.79', '5.254', '31.3', '37.58', '37.221', '46.28', '46.183', '50.7', '62.210', '66.249', '89.238', '89.238', '91.221', '94.242', '95.141', '103.10', '103.254', '107.167', '109.200', '176.123', '178.162', '178.255', '179.43', '185.9', '185.82', '185.104', '192.71', '192.99', '193.182', '207.244', '209.58'],
  tor: ['1.161', '103.28', '103.16', '103.125', '103.194', '103.208', '103.214', '103.234', '103.236', '103.75', '104.40', '104.194', '104.196', '104.200', '104.218', '104.244', '107.155', '109.69', '109.70', '109.169', '109.194', '109.201', '109.248', '114.32', '111.90', '114.158', '115.73', '118.163', '119.237', '122.147', '123.30', '124.109', '125.212', '126.75', '128.14', '128.199', '128.31', '130.149', '137.74', '138.197', '139.162', '139.28', '139.99', '142.44', '142.58', '142.93', '143.202', '144.217', '145.239', '149.202', '151.53', '151.73', '151.77', '153.229', '154.127', '156.54', '157.157', '157.161', '157.230', '158.174', '158.69', '159.89', '160.119', '160.202', '162.213', '162.244', '162.247', '163.172', '164.132', '164.77', '166.70', '167.114', '167.86', '167.99', '169.197', '171.22', '171.244', '171.25', '172.96', '172.98', '173.14', '173.199', '173.212', '173.244', '173.255', '176.10', '176.126', '176.152', '176.214', '176.31', '176.53', '177.205', '178.128', '178.165', '178.17', '178.175', '178.20', '178.239', '178.254', '178.32', '178.9', '179.43', '179.48', '18.18', '18.85', '180.149', '180.150', '184.75', '185.10', '185.100', '185.103', '185.104', '185.107', '185.112', '185.113', '185.117', '185.121', '185.125', '185.127', '185.129', '185.14', '185.147', '185.158', '185.162', '185.165', '185.169', '185.175', '185.177', '185.193', '185.195', '185.203', '185.220', '185.222', '185.227', '185.233', '185.234', '185.242', '185.244', '185.248', '185.255', '185.4', '185.56', '185.61', '185.65', '185.66', '185.72', '185.86', '185.9', '186.214', '187.178', '188.166', '188.214', '188.65', '189.84', '190.10', '190.164', '190.210', '190.216', '191.114', '191.243', '191.32', '192.160', '192.195', '192.227', '192.34', '192.42', '192.68', '193.110', '193.150', '193.169', '193.201', '193.36', '193.56', '193.9', '193.90', '194.71', '194.99', '195.123', '195.176', '195.206', '195.228', '195.254', '196.41', '197.231', '198.167', '198.211', '198.46', '198.50', '198.96', '198.98', '199.127', '199.195', '199.249', '199.87', '200.52', '200.86', '200.98', '201.80', '203.78', '204.11', '204.17', '204.194', '204.8', '204.85', '205.168', '205.185', '206.248', '206.55', '207.244', '208.12', '209.126', '209.141', '209.95', '210.140', '210.160', '212.16', '212.21', '212.47', '212.75', '212.81', '213.108', '213.136', '213.160', '213.202', '213.252', '213.61', '213.95', '216.218', '216.239', '217.115', '217.12', '217.170', '220.135', '223.26', '23.129', '23.239', '24.20', '24.3', '27.122', '31.131', '31.185', '31.220', '31.31', '35.0', '37.128', '37.139', '37.187', '37.220', '37.228', '37.28', '37.48', '40.124', '41.215', '41.77', '45.114', '45.125', '45.32', '45.33', '45.35', '45.56', '45.76', '45.79', '46.101', '46.165', '46.166', '46.173', '46.182', '46.194', '46.23', '46.246', '46.29', '46.38', '46.98', '5.135', '5.150', '5.189', '5.196', '5.199', '5.2', '5.252', '5.3', '5.34', '5.39', '5.79', '50.247', '51.15', '51.254', '51.255', '51.38', '51.68', '51.75', '51.77', '52.167', '54.36', '54.37', '54.39', '58.153', '58.96', '59.127', '62.102', '62.210', '62.212', '62.219', '62.98', '64.113', '64.27', '65.181', '65.19', '66.110', '66.146', '66.155', '66.175', '66.42', '66.70', '67.163', '67.215', '69.162', '69.164', '70.168', '71.19', '72.14', '72.210', '72.221', '72.83', '73.15', '74.82', '77.141', '77.247', '77.55', '77.73', '77.81', '78.109', '78.142', '78.46', '79.117', '79.134', '79.141', '79.172', '80.127', '80.241', '80.67', '80.68', '80.79', '81.17', '82.118', '82.151', '82.221', '82.223', '82.228', '82.94', '84.19', '84.200', '84.209', '85.214', '85.235', '85.248', '86.123', '86.124', '86.127', '86.148', '87.101', '87.118', '87.120', '87.123', '87.247', '88.130', '88.76', '89.234', '89.236', '89.247', '89.31', '91.132', '91.146', '91.203', '91.207', '91.213', '91.219', '91.231', '92.116', '92.222', '92.63', '93.174', '93.55', '94.100', '94.102', '94.140', '94.168', '94.230', '94.242', '94.32', '95.128', '95.130', '95.142', '95.143', '95.168', '95.179', '95.211', '95.216', '96.66', '96.70', '97.74', '98.174'],
  hola: ['103.18', '104.131', '106.185', '106.186', '106.187', '107.161', '107.170', '107.181', '107.190', '107.191', '107.22', '108.61', '109.74', '14.136', '149.154', '149.62', '151.236', '158.255', '162.217', '162.218', '162.221', '162.243', '167.88', '168.235', '176.58', '176.9', '177.67', '178.209', '178.79', '192.110', '192.121', '192.184', '192.211', '192.241', '192.30', '192.40', '192.73', '192.81', '192.99', '198.147', '198.58', '199.241', '208.68', '209.222', '213.229', '217.78', '23.227', '23.249', '23.29', '31.193', '37.235', '41.223', '46.17', '46.19', '46.4', '5.9', '50.116', '54.225', '54.243', '66.85', '77.237', '81.4', '85.234', '88.150', '91.186', '92.48', '94.76', '95.215', '96.126']
};
function applyArticles(articles) {
  articles.forEach(article => {
    const ipElement = article.querySelector('small');
    if (ipElement) appendInfo(ipElement);
  });
}
function applyAuthor() {
  const ipElement = document.querySelector('.article-head .user-info small');
  if (ipElement) appendInfo(ipElement);
}
function applyComments(comments) {
  comments.forEach(comment => {
    const ipElement = comment.querySelector('small');
    if (ipElement) appendInfo(ipElement);
  });
}

function appendInfo(ipElement) {
  const ip = ipElement.textContent.replace(/\(|\)/g, '');
  const [result, color] = checkIP(ip);
  ipElement.parentNode.append(VM.createElement("span", {
    class: color
  }, ` - ${result}`));
}

function checkIP(ip) {
  let result = '고정';
  let color = styles$1.green;

  if (db.KT.indexOf(ip) > -1) {
    result = 'KT';
    color = styles$1.blue;
  } else if (db.SK.indexOf(ip) > -1) {
    result = 'SK';
    color = styles$1.blue;
  } else if (db.LG.indexOf(ip) > -1) {
    result = 'LG';
    color = styles$1.blue;
  } else if (db.proxy.indexOf(ip) > -1) {
    result = '젠메이트';
    color = styles$1.red;
  } else if (db.tor.indexOf(ip) > -1) {
    result = '토르';
    color = styles$1.red;
  } else if (db.hola.indexOf(ip) > -1) {
    result = '홀라';
    color = styles$1.red;
  }

  return [result, color];
}

function apply$3(target) {
  const users = document.querySelectorAll('.content-wrapper .user-info');
  const memos = GM_getValue('userMemo', defaultConfig.userMemo);
  users.forEach(user => {
    let id = user.dataset.id;

    if (id == undefined) {
      id = user.innerText.trim();
      const subid = user.querySelector('a[title], span[title]');

      if (subid && subid.title.indexOf('#') > -1) {
        id = subid.title.substring(subid.title.indexOf('#'));
      }

      user.dataset.id = id;
    }

    if (target && id != target) return;
    let slot = user.querySelector('.memo');

    if (memos[id]) {
      if (slot == null) {
        slot = VM.createElement("span", {
          class: "memo"
        });
        user.append(slot);
      }

      slot.textContent = ` - ${memos[id]}`;
      user.title = memos[id];
    } else if (slot) {
      slot.remove();
      user.title = '';
    }
  });
}
function applyHandler() {
  const memos = GM_getValue('userMemo', defaultConfig.userMemo);
  const wrapper = document.querySelector('article .article-wrapper');
  if (wrapper == null) return;
  wrapper.addEventListener('click', event => {
    if (event.target.tagName != 'SPAN' && event.target.tagName != 'SMALL') return;
    const user = event.target.closest('.user-info');
    if (user == null) return;
    const id = user.getAttribute('data-id');
    let memo = memos[id];
    memo = prompt('이용자 메모를 설정합니다.\n', memo || '');
    if (memo == null) return;
    let slot = user.querySelector('.memo');

    if (slot == null) {
      slot = VM.createElement("span", {
        class: "memo"
      });
      user.append(slot);
    }

    if (memo) {
      slot.textContent = ` - ${memo}`;
      memos[id] = memo;
    } else {
      slot.remove();
      delete memos[id];
    }

    GM_setValue('userMemo', memos);
    apply$3(id);
  });
}

function applyRefreshBtn(commentArea) {
  if (commentArea.querySelector('.alert')) {
    // 댓글 작성 권한 없음
    return;
  }

  const btn = VM.createElement("button", {
    class: "btn btn-success",
    style: "margin-left: 1rem"
  }, VM.createElement("span", {
    class: "icon ion-android-refresh"
  }), VM.createElement("span", null, " \uC0C8\uB85C\uACE0\uCE68"));
  const clonebtn = btn.cloneNode(true);
  commentArea.querySelector('.title a').insertAdjacentElement('beforebegin', btn);
  commentArea.querySelector('.subtitle').append(clonebtn);

  async function onClick(event) {
    event.preventDefault();
    btn.disabled = true;
    clonebtn.disabled = true;
    const response = await getRefreshData();
    const newComments = response.querySelector('.article-comment .list-area');

    try {
      commentArea.querySelector('.list-area').remove();
    } // eslint-disable-next-line no-empty
    catch (_unused) {}

    if (newComments) {
      newComments.querySelectorAll('time').forEach(time => {
        time.textContent = getDateStr(time.dateTime);
      });
      commentArea.querySelector('.title').insertAdjacentElement('afterend', newComments);
      const items = newComments.querySelectorAll('.comment-item');
      apply$3();
      applyComments(items);
      blockComment(items);
      blockEmoticon(items);
      applyEmoticonBlockBtn(commentArea);
    }

    btn.disabled = false;
    clonebtn.disabled = false;
  }

  btn.addEventListener('click', onClick);
  clonebtn.addEventListener('click', onClick);
}

function getRefreshData() {
  return new Promise(resolve => {
    const req = new XMLHttpRequest();
    req.open('GET', window.location.href);
    req.responseType = 'document';
    req.addEventListener('load', () => {
      resolve(req.response);
    });
    req.send();
  });
}

function applyEmoticonBlockBtn(commentArea) {
  const emoticons = commentArea.querySelectorAll('.emoticon');
  emoticons.forEach(item => {
    const btn = VM.createElement("span", null, '\n | ', VM.createElement("a", {
      href: "#",
      class: "block-emoticon",
      "data-id": item.dataset.id
    }, VM.createElement("span", {
      class: "ion-ios-close"
    }), ' 아카콘 뮤트'));
    const timeElement = item.closest('.content').querySelector('.right > time');
    timeElement.insertAdjacentElement('afterend', btn);
  });
  commentArea.addEventListener('click', async event => {
    if (event.target.tagName != 'A') return;
    if (!event.target.classList.contains('block-emoticon')) return;
    event.preventDefault();
    event.target.textContent = '뮤트 처리 중...';
    event.target.classList.remove('block-emoticon');
    const id = event.target.getAttribute('data-id');
    const [name, bundleID] = await getEmoticonInfo(id);
    const bundle = await getEmoticonBundle(bundleID);
    const blockEmoticon = GM_getValue('blockEmoticon', defaultConfig.blockEmoticon);
    blockEmoticon[bundleID] = {
      name,
      bundle
    };
    GM_setValue('blockEmoticon', blockEmoticon);
    location.reload();
  });
}

function getEmoticonInfo(id) {
  return new Promise(resolve => {
    const req = new XMLHttpRequest();
    req.open('GET', `/api/emoticon/shop/${id}`);
    req.responseType = 'document';
    req.addEventListener('load', () => {
      const name = req.response.querySelector('.article-head .title').innerText;
      const bundleID = req.response.URL.split('/e/')[1];
      resolve([name, bundleID]);
    });
    req.send();
  });
}

function getEmoticonBundle(bundleID) {
  return new Promise(resolve => {
    const req = new XMLHttpRequest();
    req.open('GET', `/api/emoticon/${bundleID}`);
    req.responseType = 'json';
    req.addEventListener('load', () => {
      const bundle = Object.keys(req.response);
      resolve(bundle);
    });
    req.send();
  });
}

function applyFullAreaRereply(commentArea) {
  commentArea.addEventListener('click', event => {
    const checkWriteForm = event.target.closest('form');
    if (checkWriteForm) return;
    const element = event.target.closest('a, .emoticon, .btn-more, .message');
    if (element == null) return;
    if (!element.classList.contains('message')) return;
    event.preventDefault();
    element.parentNode.querySelector('.reply-link').click();
  });
}

var styles$2 = {"loader":"Refresher-module_loader__2EBKq","target":"Refresher-module_target__hOVDj","light":"Refresher-module_light__2hVGO","loaderspin":"Refresher-module_loaderspin__3kEgT"};
var stylesheet$2="@keyframes Refresher-module_light__2hVGO{\r\n    0% {\r\n        background-color: rgb(246, 247, 239);\r\n    }\r\n    100% {\r\n        background-color: rgba(255, 255, 255, 0);\r\n    }\r\n\r\n}\r\n\r\n@keyframes Refresher-module_loaderspin__3kEgT {\r\n    0% { transform: rotate(0deg);\r\n        box-shadow: 0 0 15px #3d414d;\r\n    }\r\n    5% {\r\n        box-shadow: 0 0 -10px #3d414d;\r\n    }\r\n    15%{\r\n        box-shadow: 0 0 0px #3d414d;\r\n    }\r\n    100% { transform: rotate(360deg);\r\n        box-shadow: 0 0 0px #3d414d;\r\n    }\r\n}\r\n\r\n.Refresher-module_loader__2EBKq {\r\n    border: 6px solid #d3d3d3;\r\n    border-top: 6px solid #3d414d;\r\n    border-radius: 50%;\r\n    position: fixed;\r\n    bottom: 30px;\r\n    left: 10px;\r\n    width: 40px;\r\n    height: 40px;\r\n    z-index: 20;\r\n}\r\n\r\n.Refresher-module_target__hOVDj {\r\n    background-color: #e6aaaa;\r\n}\r\n\r\n.badge {\r\n    transition: none;\r\n}";

function removeArticle(articles) {
  const form = document.querySelector('.batch-delete-form');
  if (form == null) return false;
  const userlist = GM_getValue('autoRemoveUser', defaultConfig.autoRemoveUser);
  const keywordlist = GM_getValue('autoRemoveKeyword', defaultConfig.autoRemoveKeyword);
  const testMode = GM_getValue('useAutoRemoverTest', defaultConfig.useAutoRemoverTest);
  const articleid = [];
  articles.forEach(item => {
    const title = item.querySelector('.col-title');
    const author = item.querySelector('.col-author');
    const checkbox = item.querySelector('.batch-check');
    const authorAllow = userlist.length == 0 ? false : new RegExp(userlist.join('|')).test(author.innerText);
    const titleAllow = keywordlist.length == 0 ? false : new RegExp(keywordlist.join('|')).test(title.innerText);

    if (titleAllow || authorAllow) {
      if (testMode) {
        item.classList.add(styles$2.target);
      } else {
        articleid.push(checkbox.getAttribute('data-id'));
      }
    }
  });

  if (articleid.length > 0 && !testMode) {
    form.querySelector('input[name="articleIds"]').value = articleid.join(',');
    form.submit();
    return true;
  }

  return false;
}

function applyArticles$1(articles, channel) {
  const categoryConfig = GM_getValue('category', defaultConfig.category);
  articles.forEach(article => {
    const category = article.querySelector('.badge');
    if (category == null) return;
    let color = '';

    if (categoryConfig[channel] && categoryConfig[channel][category.textContent]) {
      color = categoryConfig[channel][category.textContent].color;
    }

    const textColor = getContrastYIQ(color);

    if (color != '') {
      category.style.backgroundColor = `#${color}`;
      category.style.color = textColor;
    }
  });
}

function initLoader() {
  document.head.append(VM.createElement("style", null, stylesheet$2));
  const loader = VM.createElement("div", {
    id: "article_loader",
    class: styles$2.loader
  });
  document.body.append(loader);
  return loader;
}

function playLoader(loader, time) {
  if (loader) {
    loader.removeAttribute('style');
    setTimeout(() => {
      loader.setAttribute('style', `animation: ${styles$2.loaderspin} ${time}s ease-in-out`);
    }, 50);
  }
}

function getNewArticles() {
  return new Promise(resolve => {
    const req = new XMLHttpRequest();
    req.open('GET', window.location.href);
    req.responseType = 'document';
    req.addEventListener('load', () => {
      const articles = req.response.querySelectorAll('a.vrow');
      resolve(articles);
    });
    req.send();
  });
}

function swapNewArticle(newArticles) {
  const board = document.querySelector('.board-article-list .list-table, .included-article-list .list-table');
  const oldArticles = board.querySelectorAll('a.vrow');
  const oldnums = [];

  for (const o of oldArticles) {
    oldnums.push(o.pathname.split('/')[3]);
    o.remove();
  }

  for (const n of newArticles) {
    if (oldnums.indexOf(n.pathname.split('/')[3]) == -1) {
      n.setAttribute('style', `animation: ${styles$2.light} 0.5s`);
    }

    const lazywrapper = n.querySelector('noscript');
    if (lazywrapper) lazywrapper.outerHTML = lazywrapper.innerHTML;
    const time = n.querySelector('time');

    if (time && in24(time.dateTime)) {
      time.innerText = getTimeStr(time.dateTime);
    }
  }

  board.append(...newArticles);
}

function run(board, channel) {
  const refreshTime = GM_getValue('refreshTime', defaultConfig.refreshTime);
  if (refreshTime == 0) return;
  let loader = null;

  if (!GM_getValue('hideRefresher', defaultConfig.hideRefresher)) {
    loader = initLoader();
  }

  playLoader(loader, refreshTime);
  let loadLoop = null;

  async function routine() {
    playLoader(loader, refreshTime);
    const articles = await getNewArticles();
    swapNewArticle(articles);
    apply$3();
    applyArticles$1(articles, channel);
    filter(articles, channel);
    applyArticles(articles);
    blockArticle(board, articles, channel);

    if (removeArticle(articles)) {
      clearInterval(loadLoop);
      loadLoop = null;
    }
  }

  loadLoop = setInterval(routine, refreshTime * 1000);
  document.addEventListener('visibilitychange', () => {
    if (document.hidden) {
      clearInterval(loadLoop);
      loadLoop = null;
    } else {
      if (loadLoop == null) {
        playLoader(loader, refreshTime);
        loadLoop = setInterval(routine, refreshTime * 1000);
      }
    }
  });
  board.addEventListener('click', event => {
    if (event.target.tagName != 'INPUT') return;

    if (event.target.classList.contains('batch-check-all')) {
      if (event.target.checked) {
        clearInterval(loadLoop);
        loadLoop = null;
      } else {
        playLoader(loader, refreshTime);
        loadLoop = setInterval(routine, refreshTime * 1000);
      }
    } else {
      const btns = document.querySelectorAll('.batch-check');

      for (const btn of btns) {
        if (btn.checked) {
          clearInterval(loadLoop);
          loadLoop = null;
          return;
        }
      }

      playLoader(loader, refreshTime);
      loadLoop = setInterval(routine, refreshTime * 1000);
    }
  });
}

function applyMyImage(editor) {
  if (editor.core.isEmpty()) {
    const img = GM_getValue('myImage', defaultConfig.myImage);
    editor.html.set(img);
    editor.html.insert('<p></p>');
    editor.selection.setAtEnd(editor.$el.get(0));
  }
}
function applyClipboardUpload(editor) {
  editor.events.on('paste.before', event => {
    const files = event.clipboardData.files;
    if (files.length == 0) return true;
    editor.image.upload(files);
    return false;
  }, true);
}

function apply$4(view) {
  if (!GM_getValue('useShortcut', defaultConfig.useShortcut)) return;

  if (view == 'article') {
    document.addEventListener('keydown', onArticle);
  } else if (view == 'board') {
    document.addEventListener('keydown', onBoard);
  }
}

function onArticle(event) {
  // A 목록 바로가기
  // R 댓글 목록보기
  // W 댓글 입력 포커스
  if (event.target.nodeName == 'INPUT' || event.target.nodeName == 'TEXTAREA') return;

  switch (event.code) {
    case 'KeyA':
      event.preventDefault();
      location.pathname = location.pathname.replace(/\/[0-9]+/, '');
      break;

    case 'KeyR':
      {
        event.preventDefault();
        const commentForm = document.querySelector('.article-comment');
        window.scrollTo({
          top: commentForm.offsetTop - 50,
          behavior: 'smooth'
        });
        break;
      }

    case 'KeyW':
      {
        event.preventDefault();
        const inputForm = document.querySelector('.article-comment .subtitle');
        const input = document.querySelector('.article-comment .input textarea');
        const top = window.pageYOffset + inputForm.getBoundingClientRect().top;
        window.scrollTo({
          top: top - 50,
          behavior: 'smooth'
        });
        input.focus({
          preventScroll: true
        });
        break;
      }
  }
}

function onBoard(event) {
  // W 게시물 쓰기
  // E 헤드라인
  // D 이전 페이지
  // F 다음 페이지
  if (event.target.nodeName == 'INPUT' || event.target.nodeName == 'TEXTAREA') return;

  switch (event.code) {
    case 'KeyW':
      {
        event.preventDefault();
        const path = location.pathname.split('/');
        let writePath = '';

        if (path[path.length - 1] == '') {
          path[path.length - 1] = 'write';
        } else {
          path.push('write');
        }

        writePath = path.join('/');
        location.pathname = writePath;
        break;
      }

    case 'KeyE':
      {
        event.preventDefault();

        if (location.search.indexOf('mode=best') > -1) {
          location.search = '';
        } else {
          location.search = '?mode=best';
        }

        break;
      }

    case 'KeyD':
      {
        event.preventDefault();
        const active = document.querySelector('.pagination .active');

        if (active.previousElementSibling) {
          active.previousElementSibling.firstChild.click();
        }

        break;
      }

    case 'KeyF':
      {
        event.preventDefault();
        const active = document.querySelector('.pagination .active');

        if (active.nextElementSibling) {
          active.nextElementSibling.firstChild.click();
        }

        break;
      }
  }
}

async function waitForElement(selector) {
  let targetElement = document.querySelector(selector);
  if (targetElement) return Promise.resolve(targetElement);
  return new Promise(resolve => {
    const observer = new MutationObserver(() => {
      targetElement = document.querySelector(selector);

      if (targetElement) {
        observer.disconnect();
        resolve(targetElement);
      }
    });
    observer.observe(document, {
      childList: true,
      subtree: true
    });
  });
}

var css_248z$2 = ".body .root-container {\r\n    padding-top: 42px;\r\n}\r\n.body .navbar-wrapper {\r\n    top: 0px;\r\n    position: fixed !important;\r\n    width: 100%;\r\n    z-index: 20;\r\n}";

var css_248z$3 = ".hidden {\r\n    display: none !important;\r\n}\r\n\r\n.appear {\r\n    animation: fadein 0.25s;\r\n    animation-fill-mode: forwards;\r\n}\r\n\r\n.disappear {\r\n    animation: fadeout 0.25s;\r\n    animation-fill-mode: forwards;\r\n}\r\n\r\n@keyframes fadein {\r\n    from {\r\n        opacity: 0;\r\n    }\r\n    to {\r\n        opacity: 1;\r\n    }\r\n}\r\n\r\n@keyframes fadeout {\r\n    from {\r\n        opacity: 1;\r\n    }\r\n    to {\r\n        opacity: 0;\r\n    }\r\n}";

var css_248z$4 = ".content-wrapper.hide-avatar .avatar {\r\n    display: none !important;\r\n}\r\n.content-wrapper.hide-avatar .input-wrapper > .input {\r\n    width: calc(100% - 4.5rem - .5rem) !important;\r\n}\r\n\r\n.list-table.hide-notice a.notice {\r\n    display: none !important;\r\n}\r\n\r\n.content-wrapper.hide-media .article-body img, \r\n.content-wrapper.hide-media .article-body video {\r\n    display: none;\r\n}\r\n\r\n.content-wrapper.hide-modified b.modified {\r\n    display: none !important;\r\n}\r\n\r\n.content-wrapper.hide-sidemenu .right-sidebar {\r\n    display: none;\r\n}\r\n\r\n@media screen and (min-width: 991px) {\r\n    .content-wrapper.hide-sidemenu .board-article {\r\n        padding: 1rem;\r\n        margin: 0;\r\n    }\r\n}";

var css_248z$5 = ".body .board-article .article-list .list-table.show-filtered-category .vrow.filtered-category {\r\n    display: flex;\r\n}";

(async function () {
  document.head.append(VM.createElement("style", null, css_248z$2));
  document.head.append(VM.createElement("style", null, css_248z$3));
  document.head.append(VM.createElement("style", null, css_248z$4));
  document.head.append(VM.createElement("style", null, css_248z$5));
  document.head.append(VM.createElement("style", null, stylesheet$1));
  const path = location.pathname.split('/');
  const channel = path[2] || '';
  await waitForElement('.content-wrapper');
  const oldData = GM_getValue('Setting');

  if (oldData != undefined) {
    importConfig(oldData);
    GM_deleteValue('Setting');
  }

  setup();
  apply();
  await waitForElement('footer');
  let targetElement = document.querySelector('article > .article-view, article > div.board-article-list .list-table, article > .article-write');
  if (targetElement == null) return;
  apply$3();
  let type = '';
  if (targetElement.classList.contains('article-view')) type = 'article';
  if (targetElement.classList.contains('list-table')) type = 'board';
  if (targetElement.classList.contains('article-write')) type = 'write';

  if (type == 'article') {
    try {
      applyHandler();
      applyAuthor();
      apply$2();
      blockRatedown();
      apply$1();
    } catch (error) {
      console.warn('게시물 처리 중 오류 발생');
      console.error(error);
    }

    try {
      const commentArea = targetElement.querySelector('#comment');

      if (commentArea) {
        const comments = commentArea.querySelectorAll('.comment-item');
        applyComments(comments);
        blockComment(comments);
        blockEmoticon(comments);
        applyRefreshBtn(commentArea);
        applyEmoticonBlockBtn(commentArea);
        applyFullAreaRereply(commentArea);
      }
    } catch (error) {
      console.warn('댓글 처리 중 오류 발생');
      console.error(error);
    }

    apply$4('article');
    targetElement = targetElement.querySelector('.included-article-list .list-table');
    if (targetElement) type = 'board-included';
  }

  if (type.indexOf('board') > -1) {
    setupCategory(channel);
    const articles = targetElement.querySelectorAll('a.vrow');
    applyArticles$1(articles, channel);
    filter(articles, channel);
    applyArticles(articles);
    blockArticle(targetElement, articles, channel);

    if (type != 'board-included') {
      run(targetElement, channel);
      apply$4('board');
    }
  }

  if (type == 'write') {
    await waitForElement('.fr-box');
    const editor = unsafeWindow.FroalaEditor('#content');
    applyClipboardUpload(editor);
    applyMyImage(editor);
  }
})();

}());