Acfun_UP稿件搜索

来点稿件搜索

// ==UserScript==
// @name         Acfun_UP稿件搜索
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  来点稿件搜索
// @author       幽想
// @match        https://www.acfun.cn/u/*
// @license      GNU GPLv3
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @connect      member.acfun.cn
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/sweetalert2.all.min.js
// ==/UserScript==

var searchPage = 0;

if (!GM_getValue('showSearchCount')) {
    GM_setValue('showSearchCount',20);
}
if (!GM_getValue('searchDefType')) {
    GM_setValue('searchDefType',0);
}
var searchDefType = GM_getValue('searchDefType');
var count = GM_getValue('showSearchCount');

GM_addStyle(`
    #yx_search_main{
        flex-wrap: wrap;
        overflow: visible;
        justify-content: center;
    }
    .yx_search-video,.yx_search-article{
        padding: 0.75rem;
        display: flex;
        border-bottom: 1px solid #ececec;
        transition: all 0.3s ease-in-out;
        max-height: 90px;
        align-items: center;
        background-color: white;
        border-radius: 5px;
    }
    .yx_search-video:hover{
        transform: scale(1.01);
        background-color: lightgrey;
    }
    .yx_search-article{
        width: 47%;
    }
    .yx_search-article:hover{
        transform: scale(1.05);
        background-color: #f3f3f3;
        border: 2px solid #fd4c5d;
    }
    .yx_svideo_main{
        margin-left: 20px;
        display: flex;
        width: 100%;
        flex-wrap: wrap;
    }
    .yx_svideo_main_title{
        font-size: 1.1rem;
        font-weight: bold;
        width: 100%;
    }
    .yx_svideo_main_info{
        font-size: 1rem;
        width: 100%;
        height: 100%;
        margin-top: 1rem;
    }
    .yx_search_keyWord{
        padding-top: 0.5rem;
        height: 30px;
        display: flex;
        justify-content: flex-end;
    }
    .yx_search_keyWord_main{
        border: 1px solid #ccc;
        display: flex;
        width: fit-content;
    }
    .yx_search_keyWord_main > input{
        outline-style: none;
        border: 0;
        padding: 0.3rem;
        border-right: 1px solid #ccc;
        width: 18rem;
    }
    .yx_search_keyWord_main > div{
        display: flex;
        align-items: center;
        cursor: pointer;
        padding: 0px 0.3rem;
        transition: all 0.3s ease-in-out;
        background: white;
    }
    .yx_search_keyWord_main > div:hover{
        background: #fd4c5b;
        color: white;
        transform: scale(1.1);
    }
    #yx_searchBtn_Video{
        border-right: 1px solid #ccc;
    }
    #yx_search_pager{
        margin-top: 0.7rem;
        display: flex;
        justify-content: center;
    }
    .yx_search_aComment{
        float: left;
        width: 130px;
        margin-top: -1px;
        text-align: right;
        font-size: 14px;
        line-height: 14px;
        color: #999;
        cursor: pointer;
    }
    .yx_search_aComment_count{
        font-size: 28px;
        line-height: 28px;
        color: #fd4c5d;
        margin-bottom: 7px;
    }
    #yx_search_settings{
        border-right: 1px solid #ccc;
    }
    #yx_search_settings:hover svg{
        animation: 1s rotate180;
    }
    @keyframes rotate180 {
        from { transform: rotate(0deg); }
        to   { transform: rotate(180deg); }
    }
`)

function toast_info (t,timer = 2000) {
    Swal.fire({
        icon:'info',
        title:t,
        showConfirmButton: false,
        toast: true,
        timer: timer
    });
}
function toast_error (t,timer = 2000) {
    Swal.fire({
        icon:'error',
        title:t,
        showConfirmButton: false,
        toast: true,
        timer: timer
    });
}

function gensHTML_v (acid,coverUrl,title,infos) {
    const content = `
<div class="yx_search-video">
    <div class="yx_svideo_cover">
        <a href="/v/ac${acid}" target="_blank">
            <img src="${coverUrl}" alt="" onerror="onImageError(event, '?imageView2/1/w/160/h/90')">
        </a>
    </div>
    <div class="yx_svideo_main">
        <div class="yx_svideo_main_title">
            <a href="/v/ac${acid}" target="_blank">${title}</a>
        </div>
        <div class="yx_svideo_main_info">
            <p>${infos}</p>
        </div>
    </div>
</div>`
    return content;
}

function gensHTML_a (acid,commentCount,title,infos) {
    const content = `
<div class="yx_search-article">
    <div class="yx_svideo_cover">
        <a href="/a/ac${acid}" target="_blank">
            <div class="yx_search_aComment">
                <div class="yx_search_aComment_count">${commentCount}</div>
                <span>评论</span>
            </div>
        </a>
    </div>
    <div class="yx_svideo_main">
        <div class="yx_svideo_main_title">
            <a href="/a/ac${acid}" target="_blank">${title}</a>
        </div>
        <div class="yx_svideo_main_info">
            <p>${infos}</p>
        </div>
    </div>
</div>`
    return content;
}

function updateNum (n) {
    let div = document.querySelector('#yx_search_TotalNum');
    if (!!div) {
        div.textContent = n;
    }
}

function addPager (np,tp,kw,rt) {
    if (tp==1){
        return;
    }
    let e = document.createElement('div');
    let prev = '';
    let next = '';
    if (np == 0) {
        prev = 'pager__btn__disabled';
    }
    if (np == tp-1) {
        next = 'pager__btn__disabled';
    }
    let content = `<div id="yx_search_pager" class="pager__wrapper">
    <a class="pager__btn pager__btn__prev ${prev}" id="yx_search_pager_prev">上一页</a><span class="pager__ellipsis">${np+1} / ${tp}</span>
    <a class="pager__btn pager__btn__next ${next}" id="yx_search_pager_next">下一页</a><div class="pager__input">跳至<input type="text" id="yx_search_pager_input">页</div></div>`;
    append2Div(content);
    document.querySelector('#yx_search_pager_prev').addEventListener('click',function(){
        if (document.querySelector('#yx_search_pager_prev').classList.contains('pager__btn__disabled')) {
            return;
        }
        search(kw,np-1,rt);
    });
    document.querySelector('#yx_search_pager_next').addEventListener('click',function(){
        if (document.querySelector('#yx_search_pager_next').classList.contains('pager__btn__disabled')) {
            return;
        }
        search(kw,np+1,rt);
    });
    document.querySelector('#yx_search_pager_input').addEventListener('keypress',function(e){
        if (e.keyCode == 13) {
            let page = Number(document.querySelector("#yx_search_pager_input").value) - 1;
            if (page+1 > tp) {
                toast_error('超出页数范围,最大页数为 ' + tp);
                return;
            }
            search(kw,page,rt);
        }
    });
}

function append2Div (v) {
    let tdiv = document.querySelector('#yx_search_main');
    if (!tdiv) {
        //更新,报错
        toast_error('出错,搜索结果面板异常,请刷新页面重试。');
        return;
    }
    let n = document.createElement('div');
    tdiv.appendChild(n);
    n.outerHTML = v;
}

function clearSearchPanel () {
    document.querySelector("#yx_search_main").innerHTML = '';
}

async function getKW (uid,keyword,page = 0,rtype = 2,stype = 3) {//返回JSON
    let res = await gm_xhr('POST','https://member.acfun.cn/list/api/queryContributeList',`pcursor=${page}&count=${count}&resourceType=${rtype}&sortType=${stype}&authorId=${uid}&keyword=${keyword}`);
    if (!!res) {
        res = res.responseText;
    };
    let j = null;
    try {
        j = JSON.parse(res);
    } catch (e) {
    };
    return j;
}

async function search (keyword,page = 0,rtype = 2, append = false) {
    if (!append) {
        clearSearchPanel();
    }
    toast_info('正在获取数据…',1000);
    let uid;
    try {
       uid = document.URL.match(/acfun.cn\/u\/(.*)/)[1];
    } catch {
        toast_error('uid获取出错');
        console.log('uid获取出错');
        return;
    }
    let j = await getKW (uid,keyword,page,rtype);
    if (j == null) {
        toast_error('API返回信息出错');
        console.log('返回信息出错');
        return;
    }
    //console.log(j)
    if (j.totalNum == 0) {
        toast_info('未找到相关稿件');
        console.log('未找到相关稿件');
        return;
    };
    updateNum(j.totalNum);
    let arr = j.feed;
    let content;
    arr.forEach(function(v){
        if (rtype == 2) {
            let resizeCoverUrl = v.coverUrl.replace('?imageslim',`?imageView2/1/w/160/h/90|imageMogr2/auto-orient/format/webp/quality/80!/ignore-error/1`);
            //console.log(resizeCoverUrl);
            content = gensHTML_v(v.dougaId,resizeCoverUrl,v.title,`播放:${v.viewCountShow} 评论:${v.commentCount} 弹幕:${v.danmakuCount} 时间:${v.createTime}`);
        }
        if (rtype == 3) {
            let otime = v.contributeTime;
            let ntime = getTime_Unix(otime);
            content = gensHTML_a(v.contentId,v.commentCount,v.contentTitle,`浏览:${v.viewCountShow} 时间:${ntime}`);
        }
        if (!!content) {
            append2Div(content);
        }
    });
    if (rtype == 2) {
        document.querySelector('#yx_search_main').style.display = '';
    }
    if (rtype == 3) {
        document.querySelector('#yx_search_main').style.display = 'flex';
    }
    addPager(page,Math.ceil(j.totalNum/count),keyword,rtype);
    document.querySelector("#yx_search_li").click();
}

function getTime_Unix (unix) {
    unix = Number(unix);
    let le = unix.toString().length;
    if (le == 10) {//10为unix则乘1000
        unix = unix * 1000;
    }
    let time = new Date(unix);
    return time.getFullYear() + '/' + (time.getMonth()+1) + '/' + time.getDate();
}

function changeSearchDefType (v) {
    GM_setValue('searchDefType',v);
    searchDefType = v;
}

function showSettings () {
    Swal.fire({
        title: '稿件搜索栏设置',
        html:
          `<div style="border-bottom: 1px solid lightblue;padding-bottom: 1rem;display: flex;flex-wrap: wrap;justify-content: center;">
          <p style="text-align: left;width: 100%;font-weight: bold;color: black;">回车键默认搜索</p>
          <div style="margin-right: 3rem;"><input type="radio" name="defSerchType" id="yx_search_settings_defVideo"><span>视频</span></div>
          <div><input type="radio" name="defSerchType" id="yx_search_settings_defArticle"><span>文章</span></div>
      </div>
      <div style="border-bottom: 1px solid lightblue;padding: 1rem 0;display: flex;flex-wrap: wrap;justify-content: center;">
          <p style="text-align: left;width: 100%;font-weight: bold;color: black;">检索结果每页显示数量</p>
            <div>
              <input class="swal2-input" style="width: 7rem;text-align: center;" type="text" maxlength="2" id="yx_search_settings_showCountForSPage">
              <p>(1-99)</p>
            </div>
      </div>
      <p style="width: 100%;margin-top: 1rem;color: black;">设置将实时保存</p>
      `,
        allowEscapeKey: false,
        allowEnterKey: false,
        allowOutsideClick: false,
        didOpen: function () {
            //导入默认配置
            if (GM_getValue('searchDefType') == 1) {
                document.querySelector("#yx_search_settings_defArticle").checked = true
            } else {
                document.querySelector("#yx_search_settings_defVideo").checked = true
            };
            document.querySelector("#yx_search_settings_showCountForSPage").value = count;
            //实现按钮效果
            document.querySelector("#yx_search_settings_defVideo").addEventListener('click',function(){
                changeSearchDefType(0);
            });
            document.querySelector("#yx_search_settings_defArticle").addEventListener('click',function(){
                changeSearchDefType(1);
            });
            document.querySelector("#yx_search_settings_showCountForSPage").addEventListener('keyup',function(){
                let text = document.querySelector("#yx_search_settings_showCountForSPage").value;
                text = text.replace(/[^\d]/g,'');
                let num = Number(text);
                num = Math.floor(num);
                if (!num || text.includes('.')) {
                    alert('输入了非法字符\n(只能输入数字,不可输入小数点)');
                    document.querySelector("#yx_search_settings_showCountForSPage").value = '';
                    return;
                };
                if (num < 1) {
                    alert('数量区间在1-99');
                    document.querySelector("#yx_search_settings_showCountForSPage").value = '1';
                };
                count = num;
                GM_setValue('showSearchCount',num);
            });
        },

    })
      
}

function init () {
    let tagsDiv = document.querySelector("ul.tags");
    let n = document.createElement('li');
    tagsDiv.insertBefore(n,tagsDiv.lastElementChild)
    n.outerHTML = `<li data-index="yx_search" data-count="0" id="yx_search_li">搜索结果<span id="yx_search_TotalNum">0</span></li>`;
    let contentDiv = document.querySelector("div.ac-space-contribute-list");
    let n1 = document.createElement('div');
    n1.setAttribute('data-index','yx_search');
    n1.setAttribute('id','yx_search_main');
    n1.setAttribute('class','tag-content');
    contentDiv.appendChild(n1);
    let contributeDiv;
    document.querySelectorAll("#ac-space > div.wp > div.tab-content").forEach(function(v){
        if (v.getAttribute('tab-index') == 'contribute') {
            contributeDiv = v;
        }
    })
    let n2 = document.createElement('div');
    contributeDiv.insertBefore(n2,contributeDiv.firstChild);
    n2.outerHTML = `<div class="yx_search_keyWord"><div class="yx_search_keyWord_main"><div id="yx_search_settings"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492zM5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0z"></path><path d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115l.094-.319z"></path></svg></div><input id="yx_search_keyWordInput" autocomplete="off"><div id="yx_searchBtn_Video">搜索视频</div><div id="yx_searchBtn_Article">搜索文章</div></div></div>`;
    document.querySelector("#yx_search_keyWordInput").addEventListener('keypress',function(e){
        if (e.keyCode == 13) {
            if (searchDefType == 0) {//检索视频
                search(document.querySelector("#yx_search_keyWordInput").value);
            } else {//检索文章
                search(document.querySelector("#yx_search_keyWordInput").value,0,3);
            }
        }
    })
    document.querySelector("#yx_searchBtn_Video").addEventListener('click',function(){
        search(document.querySelector("#yx_search_keyWordInput").value);
    });
    document.querySelector("#yx_searchBtn_Article").addEventListener('click',function(){
        search(document.querySelector("#yx_search_keyWordInput").value,0,3);
    });
    document.querySelector("#yx_search_settings").addEventListener('click',function(){
        showSettings();
    })
}

function xhrAsync(method,url,data,headers) {//发出请求
    if (!data) {
        data = null;
    };
    if (!headers) {
        headers = {
            "Content-Type": "application/x-www-form-urlencoded"
        }
    };
    return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            method: method,
            url: url,
            data: data,
            headers: headers,
            onload: resolve
        });
    });
}

function delayAsync(time) {//超时返回
    return new Promise(resolve => {
        setTimeout(resolve, time);
    });
}

async function gm_xhr(method,url,data,headers) {
    console.log("发起请求…");
    return xhrAsync(method,url,data,headers).then(response => {//返回xhr请求结果
        if (response.responseText == "未响应" || response.responseText.includes("ERRO")) {
            return null;
        } else {//正常获得返回数据
            console.log('获得数据…');
            return response;
        }
    });
}

window.onload = function() {
    init();
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址