// ==UserScript==
// @name AcFun Area 63 Mobile
// @namespace http://tampermonkey.net/
// @version 0.23
// @description 在手机版文章区添加简单的评论区、夜间模式等BUG
// @author Approved233
// @icon https://cdn.aixifan.com/ico/favicon.ico
// @match *://m.acfun.cn/v/?ac=*
// @match *://m.acfun.cn/list/*
// @require https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js
// @require https://cdn.jsdelivr.net/npm/xss@1.0.3/dist/xss.min.js
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @run-at document-start
// ==/UserScript==
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function hook() {
if(!unsafeWindow.Zepto)
unsafeWindow.Zepto = {};
try{
unsafeWindow.$.ajax = function(options) {
alert('hooked $.ajax for', options.url);
if(options.url)
options.url = options.url.replace('http:', 'https:');
return $.ajax(options);
};
return true;
}catch(e){
}
return false;
}
let canHook = false;
let intervalId;
intervalId = setInterval(()=>{
if(hook()){
alert('hooked');
canHook = true;
clearInterval(intervalId);
}
}, 1);
(async ()=>{
while (!canHook) {
await sleep(1);
}
GM_xmlhttpRequest({
method: 'GET',
headers: {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
},
url: `http://down.hualuoo.com:66/%E7%A7%81%E4%BA%BA%E4%BA%91/fangsi/acfun/dark.css?_=${GM_info.script.version}`,
onload: function (res) {
GM_addStyle(res.responseText);
}
});
if(unsafeWindow.location.pathname === '/list/'){
let system = unsafeWindow.system, a = system.handle, n = system.func, $ = unsafeWindow.$, $$ = unsafeWindow.$$;
n.getList = function(e) {
var t, s, l, i;
switch (l = {
sort: 4,
pageNo: 1,
pageSize: 20
},
$.extend(l, e),
!1) {
case !($.inArray(a.channelId, function() {
var e, n, s, l;
for (s = a.channelList,
l = [],
e = 0,
n = s.length; e < n; e++)
t = s[e],
l.push(t.id);
return l
}()) > -1):
l.parentChannelId = a.channelId;
break;
default:
l.channelIds = isNaN(a.channelId) ? 1 : a.channelId
}
return (a.sort || config.channel.sort) && (l.sort = a.sort || config.channel.sort),
$$("#loading ").html('<i class="icon waiting"></i><span>正在加载数据...</span>').addClass("active"),
$.inArray(a.channelId, a.alist) !== -1 && 71 !== a.channelId ? (a.type = "article",
$$("#stage").addClass("article"),
i = s = '<div class="item logunit" data-show="false" data-id="[ac]" data-num="[num]" data-ac="[ac]"><a href="[url]" target="_blank" class="inner"><div class="hint"><span class="[ccomms]">[comms]</span><span class="b">评论</span></div><h3 class="title">[title]</h3><p class="article-info"><span class="name">[name]</span> / <span class="time">[time]</span> / <span class="pts">[views]</span>人围观</p><p class="desc">[desc]</p></a></div>') : (a.type = "video",
$$("#stage").removeClass("article"),
s = '<div class="unit logunit" data-show="false" data-id="[id]" data-ac="[ac]" data-num="[num]"><a href="[url]" target="_blank" class="inner"><div class="l"><div id="[coverid]" class="cover"></div></div><div class="r"><div class="title"><h3>[title]</h3></div><div class="info"><p class="author">UP主:<span class="name">[name]</span></p><p class="pts">' + ("article" === a.type ? "点击" : "播放") + ':<span class="count">[views]</span></p></div></div></a></div>',
i = '<div class="unit logunit" data-show="false" data-id="[id]" data-ac="[ac]" data-num="[num]"><a href="[url]" target="_blank" class="inner"><div class="l"><div style="background-image:url(\'[image]\')" class="cover"></div></div><div class="r"><div class="title"><h3>[title]</h3></div><div class="info"><p class="author">UP主:<span class="name">[name]</span></p><p class="pts">' + ("article" === a.type ? "点击" : "播放") + ':<span class="count">[views]</span></p></div></div></a></div>'),
n.getListData(l).done(function(e) {
var t, c, o, r, d, h, m, u, g, p, f, v, I, w, b, N, y, C, _;
if (200 === e.code) {
if ($$("#stage").hasClass("loading") && $$("#stage").removeClass("loading"),
l.recommendSize && e.data.recommendPage && (w = e.data.recommendPage.list,
$.isArray(w) && w.length)) {
for (b = "",
u = h = 0,
g = w.length; h < g; u = ++h)
t = w[u],
t.comments > 9999 && (t.comments = 9999),
r = t.contentId.replace("ac", ""),
_ = "/v/ac" + r,
$.inArray(t.channelId, a.alist) !== -1 && (_ = "/a/ac" + r),
C = "/v/?ac=" + r,
$.os.wp && $.browser.ie && (C = _),
b += i.replace(/\[comms\]/g, "article" === a.type ? t.comments : "").replace("[url]", C).replace("[id]", r).replace("[ac]", r).replace("[num]", u).replace("[image]", $.parseSafe(t.cover)).replace("[title]", $.parseSafe(t.title)).replace("[name]", $.parseSafe(t.user.username)).replace("[views]", $.parsePts(t.views)).replace("[time]", $.parseTime(t.releaseDate)).replace("[ccomms]", t.comments > 999 ? "c" : "a").replace("[desc]", $.parseSafe(null != (N = t.description) ? N.slice(0, 25) : void 0));
$$("#recom .mainer").html(b)
}
if (o = e.data,
f = o.list,
$.isArray(f) && f.length) {
for (a.totalPageCount || (a.totalPageCount = parseInt(o.totalCount / o.pageSize) + 1),
d = "",
u = m = 0,
p = f.length; m < p; u = ++m)
c = f[u],
r = c.contentId.replace("ac", ""),
C = "/v/?ac=" + r,
_ = "/v/ac" + r,
$.inArray(c.channelId, a.alist) !== -1 && (_ = "/a/ac" + c.contentId),
$.os.wp && $.browser.ie && (C = _),
"video" === a.type && (a.contentCount++,
I = {
id: "cover-" + a.contentCount,
img: $.parseSafe(c.cover)
},
a.contentList.push(I)),
c.comments > 9999 && (c.comments = 9999),
d += s.replace(/\[comms\]/g, "article" === a.type ? c.comments : "").replace("[url]", C).replace("[id]", r).replace("[ac]", r).replace("[num]", u).replace("[title]", $.parseSafe(c.title)).replace("[name]", $.parseSafe(c.user.username)).replace("[views]", $.parsePts(c.views)).replace("[time]", $.parseTime(c.releaseDate)).replace("[ccomms]", c.comments > 999 ? "c" : "a").replace("[coverid]", "cover-" + a.contentCount).replace("[desc]", $.parseSafe(null != (y = c.description) ? y.slice(0, 50) : void 0));
return $$("#content .mainer").append('<div class="part">' + d + "</div>"),
$$("#stage").hasClass("loading") && $$("#stage").removeClass("loading"),
a.totalPage > 4 && !$.browser.ie && (
v = window.pageYOffset - a.partHeight),
a.firstList ? ($("#btn-more-list").length || $$("#content").append('<div id="btn-more-list"><button>加载更多...</button></div>'),
a.scrollStarted || n.handleScroll(),
a.flagMoreList = !1,
a.firstList = !1,
a.partHeight = $$("#content .mainer").find(".part").height() + 12) : a.flagMoreList = !0,
a.pageNo++,
a.totalPage++,
$$("#loading").removeClass("active"),
n.loadImage()
}
return a.firstList && $("#btn-more-list").length && $("#btn-more-list").hide(),
$$("#loading").text("没有更多结果了。")
}
}).fail(function() {
return $$("#loading").html('加载失败(つд⊂)<a class="retry" onclick="location.reload()">重试</a>'),
a.flagMoreList = !0
})
}
return;
}
let urlParams = new URLSearchParams(unsafeWindow.location.search);
let acId = urlParams.get('ac');
unsafeWindow.acInvoke.jumpToApp = () => {
console.log('hooked jumpToApp');
};
$('.gradient').click();
$('.comment-img').remove();
$('.comment-title').parent().append('<div id="area-comment"><div id="area-comment-inner"><div class="comment-list"></div></div></div>');
$('<link>').appendTo('head').attr({
type: 'text/css',
rel: 'stylesheet',
href: '//cdn.aixifan.com/acfun-pc/2.5.98/css/comm-floor.min.css'
});
$('.to-app-region').each(function() {
$(this).insertAfter($(this).parent().find('.content'));
});
let regex = /globalConfig\s+=\s+([^}]+})/g;
let currentPage, isLoading;
GM_xmlhttpRequest({
method: 'GET',
headers: {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
},
url: `https://www.acfun.cn/a/ac${acId}`,
onload: function (res) {
let html = res.responseText.replace(/\n/g, ' ');
$('head').append(`<script>window.globalConfig = ${regex.exec(html)[1].replace(/ /g, '')}</script>`);
fetchComment(1);
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) {
fetchComment(currentPage + 1);
}
});
}
});
function fetchComment(page){
if(isLoading)
return;
currentPage = page;
isLoading = true;
GM_xmlhttpRequest({
method: 'GET',
headers: {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
},
url: `https://www.acfun.cn/rest/pc-direct/comment/listByFloor?sourceId=${acId}&sourceType=1&page=${currentPage}`,
responseType: 'json',
onload: function (res) {
isLoading = false;
let comments = parseFloorList(res.response.commentIds, res.response.commentsMap);
buildCommentArea(comments)
}
});
}
function parseFloorList(commentIds, commentsMap){
let alreadyParse = [],
finalFloors = [];
let maxStacks = 2000;
for(let cid of commentIds){
let comment = commentsMap[`c${cid}`];
alreadyParse.push(comment.cid);
let r = [{
comment: comment,
isRepeated: false,
isMainComment: true,
isParallel: false
}];
let quoteId = comment.quoteId;
for(let stack = 0; stack < maxStacks; stack++){
let quoteComment = commentsMap[`c${quoteId}`]
if(!quoteComment)
break;
r.push({
comment: quoteComment,
isRepeated: alreadyParse.indexOf(quoteId) >= 0,
isMainComment: false,
isParallel: stack > 10
});
quoteId = quoteComment.quoteId;
}
finalFloors.push(r);
}
return finalFloors;
}
function buildCommentArea(comments){
let list = $('.comment-list');
comments.forEach(comment => {
for(let i in comment){
let subComment = comment[i];
if(i == 0)
list.append(buildComment(subComment.comment));
// else {
// if(subComment.isRepeated){
// var d = new s(o).getQuotedComment();
// o.isParallel ? i.getNode().before(d.getNode()) : i.getNode().prepend(d.getNode()),
// i = d
// }
// }
}
})
}
function buildComment(comment){
return $('<div/>').addClass('main-comment-item').append($('<li/>').addClass('avatar').append(buildAvatar(comment))).append($('<li/>').addClass('content').append(buildBasicComment(comment)));
}
function buildBasicComment(comment){
return $('<div/>').addClass('comment-item').attr({
'data-cid': comment.cid
}).append(buildNameBar(comment)).append(buildContent(comment));
//, buildContent(comment), buildFooter(comment)
}
function buildNameBar(comment){
let name = filterXSS(comment.userName),
verifiedHtml = "";
if(comment.verified != 0){
let verifiedTitle = "";
switch(comment.verified){
case 1:
verifiedTitle = '猴子';
break;
case 2:
verifiedTitle = '猴山官方认证';
break;
case 3:
verifiedTitle = '猴山认证'
break;
}
verifiedHtml = `<li><span class="verified-ico verified-${comment.verified}" title="${verifiedTitle}"></span></li>`
}
let numberFloorHtml = `<li><span class="comment-floor">#${comment.floor}</span></li>`;
let nameColor = "";
switch(comment.nameRed){
case 1:
case 10:
nameColor = 'nameRed';
break;
case 9:
nameColor = 'nameOrange';
break;
case 8:
nameColor = 'namePurple';
break;
}
let nameHtml = `<li><a class="name ${nameColor}" data-uid="${comment.userId}">${name}</a></li>`;
return $(`<div class="comment-name-bar"><ul>${numberFloorHtml}${nameHtml}${verifiedHtml}</ul></div>`);
}
function buildContent(comment){
let parseContent = (content = comment.content)=>{
let c = content;
c = c.search(/(?:\[[^\]]*?\[)|(?:\][^\[]*?\])/) ? c : c.replace(/\[.*?\]/g, "").replace(/\[|\]/g, "");
c = c.replace(/&/g, "&").replace(/ /g, " ").replace(/'/g, "'").replace(/("|")/g, '"').replace(/>/g, ">").replace(/</g, "<").replace(/<br\s?\/?>/g, "").replace(/((\s| )*\r?\n){3,}/g, "\r\n\r\n").replace(/^((\s| )*\r?\n)+/g, "").replace(/((\s| )*\r?\n)+$/g, "");
c = c.replace(/\[p\]/g, "<p>").replace(/\[\/p\]/g, "</p>");
c = c.replace(/\[ac\=(\S+?)\](\S+?)\[\/ac\]/g, '<a class="ac title" data-aid="$1" href="/v/ac$1" target="_blank"><i class="icon icon-play-circle"></i>$2</a>').replace(/\[aa\=(\S+?)\](\S+?)\[\/aa\]/g, '<a class="aa " href="/a/aa$1" target="_blank" title="该链接通向AcFun合辑"><i class="icon icon-list"></i>$2</a>').replace(/\[sm\=(\S+?)\](\S+?)\[\/sm\]/g, '<a class="sm" href="http://www.nicovideo.jp/watch/sm$1" target="_blank" title="该链接通向ニコニコ动画"><i class="icon icon-film"></i>$2</a>').replace(/\[email\](\S+?)\[\/email\]/g, '<a class="email " href="mailto:$1" target="_blank" title="点击以发送邮件"><i class="icon icon-envelope"></i>$1</a>').replace(/\[wiki\=(\S+?)\](\S+?)\[\/wiki\]/g, '<a class="wiki " href="http://wiki.acfun.cn/index.php/$1" target="_blank" title="该链接通向AC百科"><i class="icon icon-tag"></i>$2</a>');
c = c.replace(/\[emot\=(\S+?)\,(\S+?)\/\]/g, '<img class="emotion" src="' + globalConfig.oldPath + '/umeditor/dialogs/emotion/images/$1/$2.gif">')
c = c.replace(/\[acimg.*?\](.*?)\[\/acimg\]/g, '<img src="$1" class="comment-thumbnail"/>');
c = c.replace(/\[img\](\S+?)\[\/img\]/g, '<a class="btn-img" href="$1" target="_blank" title="点击以浏览图像"><img src="$1" class="comment-thumbnail"/></a>').replace(/\[img\=(\S+?)\](\S+?)\[\/img\]/g, function(t, e, i) {
var n, o;
return n = i.replace(/javascript(:|\s+:)/gi, ""),
o = n.match(/.*(acfun.tv|acfun.cn|tudou.acfun.com)/) ? "" : n,
'<a class="btn-img" href="' + o + '" target="_blank" title="点击以浏览图像"><img src="' + o + '" class="comment-thumbnail"/></a>'
}),
c = c.replace(/\[at\]([\s\S]+?)\[\/at\]/g, '<a class="name" target="_blank" href="/member/findUser.aspx?userName=$1">@$1</a>').replace(/\[\/?back.*?\]/g, "").replace(/\[username\]([\s\S]+?)\[\/username\]/g, '<a class="name" target="_blank" href="/member/findUser.aspx?userName=$1">$1</a>').replace(/\[.*?\]/g, "").replace(/([\s\W\_])[o|O][n|N]\w+?\s*?\=/g, "$1data-event="),
$.trim(content),
c = c.replace(/&/g, "&").replace(/[/g, "[").replace(/]/g, "]")
return c;
}
return $(`<div class="comment-content">${parseContent()}</div>`)
}
function buildAvatar(comment){
let defaultAvatar = `${unsafeWindow.globalConfig.oldPath}/style/image/avatar.jpg`,
avatar = defaultAvatar;
if(comment.headUrl && comment.headUrl.length > 0)
avatar = comment.headUrl[0].url;
let node = $('<a/>').addClass('avatar');
let avatarNode = $('<img/>').attr({
class: 'avatar',
src: avatar,
'data-name': comment.userName
});
avatarNode.one("error", function() {
$(this).attr("src", defaultAvatar);
});
node.append(avatarNode);
if(comment.avatarFrame)
node.append($('<img/>').addClass('avatar-bg').attr({
src: comment.avatarImage
}))
return node;
}
})();