Skip to content

Instantly share code, notes, and snippets.

@viettelidc-oss
Last active March 11, 2020 04:58
Show Gist options
  • Save viettelidc-oss/f0013e72dd7f14f8b25b14444b8a2fec to your computer and use it in GitHub Desktop.
Save viettelidc-oss/f0013e72dd7f14f8b25b14444b8a2fec to your computer and use it in GitHub Desktop.
Fork from voz next sticker
// ==UserScript==
// @name Next Sticker
// @namespace http://tampermonkey.net/
// @version 1.3.0
// @updateURL https://gist.githubusercontent.com/phonglk/915ecd87e1d14dfd25cecf6215571a9a/raw/next-sticker.user.js
// @description Add Sticker to your post
// @author greans@voz
// @match *.gamevn.com/*
// @match https://*.voz.vn/*
// @connect imgur.com
// @homepage https://next.voz.vn/threads/userscript-sticker-cho-next.854/
// @supportURL https://next.voz.vn/threads/userscript-sticker-cho-next.854/
// @source https://gist.github.com/phonglk/915ecd87e1d14dfd25cecf6215571a9a
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_xmlhttpRequest
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/cash.min.js
// ==/UserScript==
/**
* LICENSE: GNU General Public License v3.0
*/
const request = (url, options) =>
new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
...options,
url,
onload: function(response) {
if (response.readyState === 4 && response.status === 200) {
resolve(JSON.parse(response.responseText));
} else {
reject(new Error(`Cannot load url ${url}`));
}
}
});
});
function addGlobalStyle(css) {
var head, style;
head = document.getElementsByTagName("head")[0];
if (!head) {
return;
}
style = document.createElement("style");
style.type = "text/css";
style.innerHTML = css;
head.appendChild(style);
}
addGlobalStyle(`
#ns {
margin-top: 10px;
}
#ns a.button {
display: inline-block;
text-decoration: none;
border: 1px solid rgba(0,0,0,0.5);
padding: 2px;
cursor: pointer;
min-width: auto;
border-radius: 0;
}
#ns .btn-add {
padding-left: 5px;
padding-right: 5px;
}
#ns .btn-sticker {
margin-right: 3px;
}
#ns .sticker-wrapper {
background: white;
height: 200px;
overflow-y: auto;
overflow-x: hidden;
position: relative;
transition: all 0.3s;
}
#ns .sticker-img {
border: 1px solid transparent;
transition: all 0.3s;
cursor: pointer;
display: inline-block;
}
#ns .sticker-img:hover {
border: 1px solid rgba(0,0,0,0.5);
}
`);
const candy = "11f712f3240e20c";
const CONTAINER_ID = "ns";
const BEFORE_SELECTOR = ".js-previewContainer";
const STICKER_SET_LIST_KEY = "sticker_set_list";
const SELECTED_SS_KEY = "selected_sticker_set";
const GET_SET_KEY = url => `sticker_set_${url}`;
let stickerSetList = GM_getValue(STICKER_SET_LIST_KEY, []);
let selectedSS = GM_getValue(SELECTED_SS_KEY, null);
let $root;
function insertDom() {
if ($(BEFORE_SELECTOR).length === 0) return;
let ele = $(`#${CONTAINER_ID}`);
if (ele.length > 0) return ($root = ele);
ele = $(`
<div id="${CONTAINER_ID}">
<div class='sticker-panel'>
<a class='btn-delete button'>Delete</a>
<div class='sticker-wrapper'></div>
</div>
<a class='btn-add button button--primary'>ADD STICKER</a>
<span class='ss-list'></span>
</div>
`);
ele.insertBefore(".js-previewContainer");
ele.find(".btn-add").on("click", addStickerSet);
ele.find(".btn-delete").on("click", deleteStickerSet);
$root = ele;
}
function addStickerSet() {
let url = prompt("imgur album url or id", "http://imgur.com/a/");
if (!url.startsWith("http")) url = "http://imgur.com/a/" + url;
const albumId = url.match(/a\/([^ ]*)/)[1];
const name = prompt("Sticker name", albumId);
stickerSetList.push({ name, url });
GM_setValue(STICKER_SET_LIST_KEY, stickerSetList);
renderStickerSetList();
}
const deleteStickerSet = () => {
stickerSetList = stickerSetList.filter(({ url }) => url !== selectedSS);
GM_setValue(STICKER_SET_LIST_KEY, stickerSetList);
GM_deleteValue(GET_SET_KEY(selectedSS))
renderStickerSetList();
selectSticker(stickerSetList.length > 0 ? stickerSetList[0].url : null);
};
const renderStickerSetList = () => {
const $list = $root.find(".ss-list");
$list.empty();
stickerSetList.forEach(({ url, name }) => {
const btn = $(
`<a class='button btn-sticker ${
url === selectedSS ? "button--primary" : "button--link"
}'>${name}</a>`
);
$list.append(btn);
btn.on("click", () => selectSticker(url));
});
};
const selectSticker = url => {
selectedSS = url;
GM_setValue(SELECTED_SS_KEY, url);
renderStickerPanel();
renderStickerSetList();
};
const renderStickerPanel = async () => {
const $panel = $root.find(".sticker-panel");
if (!selectedSS) {
$panel.css("display", "none");
return;
}
$panel.css("display", "block");
const $wrapper = $panel.find(".sticker-wrapper");
$wrapper.empty();
const stickerList = GM_getValue(GET_SET_KEY(selectedSS), []);
if (stickerList.length === 0) {
$wrapper.text("Loading stickers ...");
try {
await loadSticker(selectedSS);
setTimeout(renderStickerPanel, 300);
} catch (e) {
$wrapper.text(`Cannot load sticker set from ${selectedSS}`);
}
return;
}
stickerList.forEach(url => {
const item = $(`<div class="sticker-img"><img src="${url}" /></div>`);
$wrapper.append(item);
item.find("img").on("click", () => insertStickerImg(url));
});
};
const loadSticker = async url => {
const id = url.match(/a\/([^ ]*)/)[1];
const resp = await request(`https://api.imgur.com/3/album/${id}/images`, {
headers: {
Authorization: `Client-ID ${candy}`,
Accept: "application/json"
}
});
GM_setValue(
GET_SET_KEY(url),
resp.data.map(({ link }) => link)
);
};
function insertStickerImg(url) {
const sel = window.getSelection();
const img = $(`<img src="${url}" />`)[0];
const target = $("div.fr-view[contenteditable=true] > *");
const node =
sel.anchorNode.nodeType === 3
? sel.anchorNode.parentElement
: sel.anchorNode;
if (
sel.getRangeAt &&
sel.rangeCount &&
node.matches("div[contenteditable=true] *")
) {
const range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode(img);
sel.modify("move", "right", "character");
} else if (target.length > 0) {
target.last()[0].appendChild(img);
}
}
function detectImgurAlbum() {
const IMGURL_PREFIX = '://imgur.com/a/'
const eles = $(`iframe[src*="${IMGURL_PREFIX}"]`).add(`a[href*="${IMGURL_PREFIX}"]`)
const toProcess = []
eles.each((_, node) => {
try {
const url = node.src || node.href
if (node.parentElement.classList.contains('imgur-embed-pub')) {
node = node.parentElement.parentElement
}
const textNode = node.previousSibling
const text = textNode.textContent;
if (text.length > 20) return;
const addBtn = $(`<a class="button button--link">Add Sticker ${text}</a>`)
$(textNode).replaceWith(addBtn)
addBtn.on('click', () => addStickerFromPage(url.trim(), text.trim()));
} catch (e) {
throw e
}
})
}
function addStickerFromPage(url, name) {
stickerSetList.push({ name, url });
GM_setValue(STICKER_SET_LIST_KEY, stickerSetList);
renderStickerSetList();
alert(`Added ${name} from ${url}`)
}
insertDom();
renderStickerSetList();
renderStickerPanel();
detectImgurAlbum();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment