Arca Refresher

Arca Live Extension

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

Advertisement:

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

Advertisement:

// ==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);
  }
})();

}());