Skip to content

Instantly share code, notes, and snippets.

@FlandreDaisuki
Last active July 26, 2016 07:54
Show Gist options
  • Save FlandreDaisuki/ac26b3178804b067b5f71417373e87e1 to your computer and use it in GitHub Desktop.
Save FlandreDaisuki/ac26b3178804b067b5f71417373e87e1 to your computer and use it in GitHub Desktop.
let dymy more powerful
// ==UserScript==
// @name CustomDYMY
// @description Custom your favorite teams for new anime
// @namespace FlandreDaisuki
// @include https://share.dmhy.org/*
// @author FlandreDaisuki
// @version 2016.07.16
// @grant none
// ==/UserScript==
/* jshint esnext: true */
console.log('點擊[新番追番]可以按時間列出所有已追動畫');
console.log('點擊[增加新番],顧名思義');
console.log('左鍵點擊<已追動畫>,可只列出該動畫');
console.log('右鍵點擊<已追動畫>,可刪除該動畫');
console.log('點擊[清除全部追番],清除全部追番');
const qs = document.querySelector.bind(document);
const qsa = document.querySelectorAll.bind(document);
const jx = 'javascript:;';
const tbody = qs('#topic_list tbody');
const wmap = new WeakMap();
let lsf = lsget();
function el(selector) {
const m = selector.match(/[#\.]?[^#\.]+/g);
const id = new Set(m.filter(x => x[0] === '#'));
const cl = new Set(m.filter(x => x[0] === '.'));
const t = new Set(m.filter(x => !id.has(x)).filter(x => !cl.has(x)));
let e = document.createElement((t.size) ? ([...t][0]) : ('div'));
if (id.size) {
e.id = [...id][0].slice(1);
}
if (cl.size) {
e.className = [...cl].map(x => x.slice(1)).join(' ');
}
return e;
}
function lsset() {
localStorage.setItem('lsf', JSON.stringify(lsf));
}
function lsget() {
const f = localStorage.getItem('lsf');
return f ? JSON.parse(f) : [];
}
function rmqsa(s) {
Array.from(qsa(s)).forEach(x => x.remove());
}
function setupHTML(setupHTMLEvents) {
/** li part
ul.nav>
li#czli>
(
a#czdes+
ul#flnav>
(
li.flli>
a.fldes
)*n+
(
li#addli>
a#adddes
)+
li#clearli>
a#cleardes
)
*/
const ulnav = qs('ul.nav');
const czli = el('li#czli');
ulnav.appendChild(czli);
const czdes = el('a#czdes');
czdes.innerHTML = '新番追番';
czdes.href = jx;
const flnav = el('ul#flnav');
czli.appendChild(czdes);
czli.appendChild(flnav);
const addli = el('li#addli');
flnav.appendChild(addli);
const adddes = el('a#adddes');
adddes.innerHTML = '增加新番';
adddes.href = jx;
addli.appendChild(adddes);
reset_flnav(addli);
const clearli = el('li#clearli');
ulnav.appendChild(clearli);
const cleardes = el('a#cleardes');
cleardes.innerHTML = '清除全部追番';
cleardes.href = jx;
clearli.appendChild(cleardes);
/** ui part
div#czui>
(
select#czanime+
select#czteam+
a#czadd
)
*/
const czui = el('#czui.hide');
qs('body').appendChild(czui);
const czanime = el('select#czanime');
const czteam = el('select#czteam');
const czenc = el('select#czenc');
const czadd = el('a#czadd');
czui.appendChild(czanime);
czui.appendChild(czteam);
czui.appendChild(czenc);
czui.appendChild(czadd);
czadd.href = jx;
czadd.innerHTML = '新增';
const czanime_all = el('option');
czanime_all.value = 'keyword=';
czanime_all.innerHTML = '全部';
czanime.appendChild(czanime_all);
czteam.innerHTML = `
<option value="team_id=0">全部</option>
<option value="team_id=58">澄空學園</option>
<option value="team_id=88">动音漫影</option>
<option value="team_id=185">極影字幕社</option>
<option value="team_id=241">幻櫻字幕组</option>
<option value="team_id=303">動漫國字幕组</option>
<option value="team_id=348">HKACG香港動漫</option>
<option value="team_id=407">DHR動研字幕組</option>
`;
czenc.innerHTML = `
<option value="">繁簡</option>
<option value="繁|big5">繁體</option>
<option value="簡|GB">簡體</option>
`;
const jmd_base_trs = Array.from(qsa('table.jmd_base tr'));
jmd_base_trs.forEach(tr => {
const optgroup = el('optgroup');
optgroup.label = tr.firstChild.innerText;
const tds = Array.from(tr.lastChild.children);
tds.forEach(td => {
const opt = el('option');
opt.value = td.href.match(/keyword=.*/).pop();
opt.innerText = td.innerText;
optgroup.appendChild(opt);
});
czanime.appendChild(optgroup);
});
setupHTMLEvents();
}
function setupEvents() {
addli.addEventListener('click', function() {
czui.classList.remove('hide');
});
czui.addEventListener('click', function(event) {
if (event.target === this) {
czui.classList.add('hide');
}
});
czdes.addEventListener('click', function() {
rmqsa('#topic_list tbody tr');
Promise.all(Array.from(qsa('.fldes')).map(a => wmap.get(a)))
.then(a => {
const trs = a.reduce((a, b) => a.concat(b), []);
trssort(trs);
trs.forEach(tr => {
tbody.appendChild(tr);
});
});
});
czadd.addEventListener('click', function() {
const as = czanime.selectedOptions[0];
const ss = czteam.selectedOptions[0];
const ens = czenc.selectedOptions[0];
lsf.push({
name: as.innerHTML,
team: ss.innerHTML,
enc: ens.innerHTML,
target: `https://share.dmhy.org/topics/list?${as.value} ${ens.value}&${ss.value}`,
});
lsset();
rmqsa('.flli');
reset_flnav(addli);
czui.classList.add('hide');
});
cleardes.addEventListener('click', function() {
if (confirm("確定清除全部追番?")) {
localStorage.clear();
location.href = location.href;
}
});
}
function setupCSS() {
const style = document.createElement('style');
document.head.appendChild(style);
style.innerHTML = `
#czli,
#flnav li {
width: initial !important;
min-width: 240px;
}
#czli:hover #flnav{
display: block;
}
#flnav {
display: none;
position: absolute;
width: initial !important;
}
#flnav .flli {
display: block;
float: none;
}
#flnav a {
width: 100%;
}
#czui> *{
margin: 20px;
}
#czui {
height: 100vh;
width: 100vw;
background-color: rgba(60, 60, 60, 0.5);
position: fixed;
top: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
}
#czui select {
font-size: 16px;
height: 32px;
}
#czui optgroup {
font-size: 14px;
}
#czui option {
font-size: 16px;
}
#czui.hide {
display: none;
}
#czadd {
padding: 5px 10px;
border-radius: 3px;
background-color: #9CC;
}
#adddes {
font-size: 1rem;
color: #9E334F;
font-weight: bold;
letter-spacing: 5px;
}
#clearli {
margin-left: 150px;
}
#cleardes {
color: #F00;
font-weight: bold;
}
#topic_list tbody tr:nth-child(odd){
background-color: #CDF;
}
`;
}
function reset_flnav(addli) {
lsf.forEach(function(rec) {
const li = el('li.flli');
const a = el('a.fldes');
wmap.set(a, fetchTargets(rec.target));
li.appendChild(a);
a.href = `${jx}`;
a.innerHTML = `[${rec.team}] ${rec.name} (${rec.enc})`;
a.onmouseup = showordel;
a.oncontextmenu = () => false;
addli.parentNode.insertBefore(li, addli);
});
}
function fetchTargets(url) {
return fetch(url)
.then(res => res.text())
.then(html => (new DOMParser()).parseFromString(html, 'text/html'))
.then(doc => {
const kws = Array.from(doc.querySelectorAll('span.keyword'));
kws.forEach(kw => {
kw.outerHTML = kw.innerHTML;
});
return Array.from(doc.querySelectorAll('#topic_list tbody tr'));
})
.catch(err => {
console.log(err);
});
}
function showordel(event) {
const node = event.target;
const btn = ['left', 'mid', 'right'][event.button];
if(btn === 'left'){
if (wmap.has(node)) {
const p = wmap.get(node);
p.then(trs => {
rmqsa('#topic_list tbody tr');
trssort(trs);
trs.forEach(tr => tbody.appendChild(tr) );
});
}
} else if(btn === 'right'){
if (confirm(`確定清除 ${node.innerHTML} ?`)) {
const li = node.parentNode;
const target_i = [].indexOf.call(li.parentNode.children, li);
lsf.splice(target_i, 1);
lsset();
location.href = location.href;
}
} else {
return false;
}
}
function trssort(trs) {
trs.sort((a, b) => {
const aa = new Date(a.firstElementChild.firstElementChild.innerText);
const bb = new Date(b.firstElementChild.firstElementChild.innerText);
return bb - aa;
});
}
function removeAd() {
[
'#zds_ad',
'#mbjx_ad',
'#shareman_ad',
'iframe',
].forEach(x => {
qs(x).remove();
});
}
setupHTML(setupEvents);
setupCSS();
removeAd();
@FlandreDaisuki
Copy link
Author

Installation 安裝

  1. 安裝 Chrome 的 Tampermonkey 或 Firefox 的 GreaseMonkey
  2. Raw 下載

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment