Skip to content

Instantly share code, notes, and snippets.

@saschanaz
Last active July 8, 2020 06:36
Show Gist options
  • Save saschanaz/5a48028ed12e33625e9ce62e95d75328 to your computer and use it in GitHub Desktop.
Save saschanaz/5a48028ed12e33625e9ce62e95d75328 to your computer and use it in GitHub Desktop.
로드 오브 히어로즈 유저스크립트
// ==UserScript==
// @name 로드 오브 히어로즈 포럼 유저 뮤트
// @namespace http://saschanaz.github.io/
// @version 0.3
// @description 맘에 안 드는 유저를 포럼에서 뮤트합니다
// @author Kagami Sascha Rosylight
// @match https://community-ko.lordofheroes.com/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @run-at document-start
// @downloadURL https://gist.github.com/saschanaz/5a48028ed12e33625e9ce62e95d75328/raw/mute.user.js
// @require https://raw.githubusercontent.com/GoogleChrome/dialog-polyfill/master/dist/dialog-polyfill.js
// ==/UserScript==
/* global dialogPolyfill */
document.addEventListener("DOMContentLoaded", () => {
'use strict';
const users = JSON.parse(GM_getValue("users") || "[]");
GM_registerMenuCommand("유저 뮤트 설정", () => {
const savedUsers = JSON.parse(GM_getValue("users")).join(",");
const dialog = document.createElement("dialog");
dialog.innerHTML = `
<p>
유저 목록: <input>
</p>
<p style="word-break: keep-all">
띄어쓰기 없이 쉼표로 구분합니다. 아래 예시는 어느 평행세계의 바네사가 썼다고 합니다.
</p>
<p>
예: 프라우,조슈아
</p>
<p>
저장하시면 새로고침됩니다!
</p>
<div style="text-align: center">
<button>저장 및 새로고침</button><button>닫기</button>
</div>
`;
dialog.style.width = "400px";
dialog.style.height = "400px";
dialogPolyfill.registerDialog(dialog);
const [saveButton, closeButton] = dialog.querySelectorAll("button");
const input = dialog.querySelector("input");
input.value = savedUsers;
saveButton.addEventListener("click", () => {
GM_setValue("users", JSON.stringify(input.value.split(",")));
location.reload();
});
closeButton.addEventListener("click", () => {
dialog.close();
dialog.remove();
});
document.body.append(dialog);
dialog.showModal();
});
hideParent("li", "li .item-user__text");
const commentList = document.querySelector(".comment_list");
if (commentList) {
const observer = new MutationObserver(mutations => {
hideParent(".comment_entity", "a.__xe_user");
});
observer.observe(commentList, { childList: true });
}
function hideParent(parentSelector, childSelector) {
const nodes =
[...document.querySelectorAll(childSelector)]
.filter(n => users.includes(n.textContent.trim()));
for (const node of nodes) {
const parent = node.closest(parentSelector);
parent.style.visibility = "hidden";
}
}
});
// ==UserScript==
// @name 로드 오브 히어로즈 포럼 게시판 기능 강화
// @namespace http://saschanaz.github.io/
// @version 0.5
// @description 내가 쓴 글 버튼 및 게시판 검색 버튼을 추가해 줍니다
// @author Kagami Sascha Rosylight
// @match https://community-ko.lordofheroes.com/*
// @grant none
// @run-at document-start
// @downloadURL https://gist.github.com/saschanaz/5a48028ed12e33625e9ce62e95d75328/raw/mypost.user.js
// ==/UserScript==
document.addEventListener("DOMContentLoaded", () => {
'use strict';
const writeButton = document.querySelector(".section-board--pc .section-board__write-button");
if (!writeButton) {
return;
}
const writeButtonParent = writeButton.closest(".float-right");
const root = writeButtonParent.parentElement;
// The order is important; otherwise it will look weird
addMypostButton();
addSearchButton();
function addMypostButton() {
const nicknameElement = document.querySelector(".header-login-user__nick-text");
if (!nicknameElement) {
return;
}
const writeButtonParent = writeButton.closest(".float-right");
const mypostsButton = writeButtonParent.cloneNode(true);
const mypostsAnchor = mypostsButton.querySelector("a");
mypostsAnchor.textContent = "내가 쓴 글";
const url = new URL(location.href);
url.searchParams.set("writer", nicknameElement.textContent);
mypostsAnchor.href = url;
root.append(mypostsButton);
}
function addSearchButton() {
const container = parseHTML('<div class="float-right">');
const input = parseHTML('<input type="text" placeholder="게시판 검색" style="height: 34px; border: none; border-bottom: 1px rgb(190, 185, 175) solid; padding-right: 30px;">');
input.value = new URLSearchParams(location.search).get("title_content");
input.addEventListener("keydown", ev => {
if (ev.key === "Enter") {
navigate();
}
});
const button = parseHTML('<button style="border: none; margin-left: -25px; background-color: transparent;"><i class="xi-search"></i></button>');
button.addEventListener("click", navigate);
container.append(input, button);
root.append(container);
function navigate(ev) {
if (!input.value) {
return;
}
const url = new URL(location.href);
url.searchParams.set("title_content", input.value);
location.href = url;
}
}
function parseHTML(html) {
return document.createRange().createContextualFragment(html).children[0];
}
});
// ==UserScript==
// @name 로드 오브 히어로즈 포럼 스티커 보충
// @namespace https://saschanaz.github.io/
// @version 0.2
// @description 자이라와 요한 스티커를 추가합니다.
// @author Kagami Sascha Rosylight
// @match https://community-ko.lordofheroes.com/*
// @grant none
// @run-at document-start
// @downloadURL https://gist.github.com/saschanaz/5a48028ed12e33625e9ce62e95d75328/raw/stickers-additional.user.js
// ==/UserScript==
document.addEventListener("DOMContentLoaded", async () => {
'use strict';
const commentForm = document.querySelector(".__xe_comment_form");
if (!commentForm) {
return;
}
untilMutate(commentForm).then(searchAndAddStickers);
// Do not wait for comment form as it fills separately
await untilMutate(document.querySelector(".__xe_comment_list"));
const replyForms = document.querySelectorAll(".__xe_comment_reply_form");
// Parallel on purpose
replyForms.forEach(async replyForm => {
while (true) {
await untilMutate(replyForm);
searchAndAddStickers(replyForm);
}
});
function untilMutate(parent) {
return new Promise(resolve => {
const observer = new MutationObserver(mutations => {
observer.disconnect();
resolve(parent);
});
observer.observe(parent, { childList: true });
});
}
function searchAndAddStickers(parent) {
const stickerList = parent.querySelector(".comment-sticker__list");
if (!stickerList) {
return;
}
stickerList.append(createStickerItem(11), createStickerItem(12));
}
function createStickerItem(index) {
const paddedIndexStr = padZero(index);
return document.createRange().createContextualFragment(
`<li><img class="__trigger-sticker-image"
src="https://community-ko.lordofheroes.com/plugins/xehub__custom/assets/img/sticker/common_chat_icon${paddedIndexStr}.png"
alt="스티커 ${paddedIndexStr}"></li>`
);
}
function padZero(n) {
const str = n.toString();
return "0".repeat(2 - str.length) + str;
}
});
// ==UserScript==
// @name XpressEngine 3 시간대 보정
// @namespace http://tampermonkey.net/
// @version 0.1
// @description 외국에서 접속했을 때 글 작성시간이 잘못 표시되는 문제를 수정합니다.
// @author Kagami Sascha Rosylight
// @match https://community-ko.lordofheroes.com/*
// @grant none
// @run-at document-start
// @downloadURL https://gist.github.com/saschanaz/5a48028ed12e33625e9ce62e95d75328/raw/timezone.user.js
// ==/UserScript==
// 참고글
// https://www.xpressengine.com/index.php/forum/%EA%B8%80-%EB%B0%8F-%EB%8C%93%EA%B8%80-%EC%8B%9C%EA%B0%84%EC%9D%B4-%EC%99%B8%EA%B5%AD%EC%97%90%EC%84%9C-%EC%A0%91%EC%86%8D%ED%96%88%EC%9D%84-%EB%95%8C%EB%8A%94-%EC%9E%98%EB%AA%BB-%ED%91%9C%EC%8B%9C%EB%90%A9%EB%8B%88%EB%8B%A4
document.addEventListener("DOMContentLoaded", () => {
'use strict';
addTimeZoneToChildren(document);
const observer = new MutationObserver(mutations => {
for (const mutation of mutations) {
for (const addedNode of mutation.addedNodes) {
if (addedNode.nodeType === addedNode.ELEMENT_NODE) {
addTimeZoneToChildren(addedNode);
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
function addTimeZoneToChildren(parent) {
parent.querySelectorAll("[data-xe-timeago]").forEach(addTimeZone);
}
function addTimeZone(el) {
if (el.dataset.xeTimeago.includes("+")) {
return;
}
el.dataset.xeTimeago += "+0900";
const { xeTimeago } = el.dataset;
if (xeTimeago !== el.innerText) {
el.textContent = globalThis.XE.moment(el.dataset.xeTimeago).fromNow();
}
}
});
// ==UserScript==
// @name 로드 오브 히어로즈 트위터 버튼 수정
// @namespace https://saschanaz.github.io/
// @version 0.2
// @description 트위터 공유 버튼이 제목도 표시하게끔 수정합니다.
// @author Kagami Sascha Rosylight
// @match https://community-ko.lordofheroes.com/*
// @grant none
// @run-at document-start
// @downloadURL https://gist.github.com/saschanaz/5a48028ed12e33625e9ce62e95d75328/raw/twitter.user.js
// ==/UserScript==
document.addEventListener("DOMContentLoaded", async () => {
'use strict';
const shareButton = document.querySelector(".xe-share");
if (!shareButton) {
return;
}
let twitterButton;
while (!twitterButton) {
const { parentElement: parent } = shareButton;
await untilMutate(parent);
twitterButton = parent.querySelector(".share-item[data-type=twitter]");
}
const url = new URL(twitterButton.dataset.url);
url.searchParams.set("text", document.title);
twitterButton.dataset.url = url.toString();
function untilMutate(parent) {
return new Promise(resolve => {
const observer = new MutationObserver(mutations => {
observer.disconnect();
resolve(parent);
});
observer.observe(parent, { childList: true, subtree: true });
});
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment