2023年政策修订增补工作正在进行中,欢迎参与!
  • Moegirl.ICU:萌娘百科流亡社群 581077156(QQ),欢迎对萌娘百科运营感到失望的编辑者加入
  • Moegirl.ICU:账号认领正在试运行,有意者请参照账号认领流程

User:AdorN

萌娘百科,万物皆可萌的百科全书!转载请标注来源页面的网页链接,并声明引自萌娘百科。内容不可商用。
跳转到导航 跳转到搜索
更新{{YoutubeCount}}再生代码(TypeScript)
import { MediaWikiJS } from '@lavgup/mediawiki.js' //已魔改(doEdit()中加入tags: 'Bot')
import axios from 'axios'
import HttpsProxyAgent from 'https-proxy-agent' //解决axios库无法正常使用代理的bug

const bot = new MediaWikiJS({
    url: 'https://zh.moegirl.org.cn/api.php',
    botUsername: /* USERNAME */,
    botPassword: /* PASSWORD */,
})

async function getYoutubeViewCount(id: string): Promise<Number> {
    return (await axios.get("https://youtube.googleapis.com/youtube/v3/videos", {
        httpsAgent: HttpsProxyAgent({ host: "127.0.0.1", port: 9910/* BASED UPON PROXY TOOL */ }),
        params: {
            part: "statistics",
            id,
            fields: "items(id,statistics)",
            key: "AIzaSyCrYqZhekQ6xBq5HkaGntDyD3y7XbOg9rU",
        }
    })).data.items[0].statistics.viewCount
}

async function getSourceCode(title: string) {
    let response = await axios.get('https://zh.moegirl.org.cn/index.php', {
        params: { title, action: "raw" }
    })
    return response.data as string
}

(async () => {
    await bot.login()
    let pages = await bot.search("hastemplate:YoutubeCount insource:YoutubeCount", true) as string[] //按需调整
    Promise.all(
        pages.map(title => {
            getSourceCode(title).then(async (text: string) => {
                text = text.replace(/<!--.*更新.*-->/, '')
                let templates = text.match(/\{\{YoutubeCount[^\}]+\}\}/ig) || []
                for (let original of templates) {
                    let modified = original
                    let id = (<RegExpMatchArray>original.match(/(?:id *=)([^|]+)/))[1].trim()
                    let viewCount = await getYoutubeViewCount(id)
                    text = text.replace(original, modified.replace(/fallback *= *\d+/, 'fallback=' + viewCount.toString())
                        + `<!--更新时间:${(new Date()).toISOString().slice(0, 10).split('-').join('')}-->`)
                }
                //console.log(text)
                return bot.edit({ //bot库已魔改(doEdit()中加入tags: 'Bot')
                    title,
                    content: text,
                    summary: "更新再生",
                    minor: true,
                })
            }).then(console.log, console.error)
        })
    )
})()
{{Temple Song/list}}排序代码(TypeScript)
function matchRecursiveBracket(str: string, startIndex: number = 0) {
    let stack: number[] = [], exp = /\{\{|\}\}/mg, res: RegExpExecArray | null, endIndex = 0
    exp.lastIndex = startIndex
    for (let i = 0; (res = exp.exec(str)) !== null; i++) {
        if (i === 0) startIndex = exp.lastIndex - 2
        endIndex = Math.max(endIndex, exp.lastIndex)
        if (res[0] == '{{') stack.push(1)
        else {
            if (stack.length <= 1) break;
            stack.pop()
        }
    }
    return str.slice(startIndex, endIndex)
}

class TempleSong {
    readonly text: string;
    readonly id: string;
    constructor(text: string) {
        this.text = text
        this.id = (<RegExpMatchArray>this.text.match(/(?:(?:nnd|nc)_id *=) *(\w+)/))[1].trim()
    }
    viewCount = -1;
}

(async () => {
    await bot.login()
    let pages = [
        "VOCALOID神话曲",
        "VOCALOID传说直前曲",
        "VOCALOID传说直前直前曲"
    ]
    Promise.all(
        pages.map(async title => {
            getSourceCode(title).then(async (text: string) => {
                let original = text,
                    liststr = matchRecursiveBracket(text, text.indexOf('{{Temple Song/list')).slice(0, -2).replace(/\{\{Temple Song\/list\s*\|\s*/, '').trim(),
                    temples = liststr.split(/(?<=\})\s*\|\s*(?=\{)/).map(x => new TempleSong(x)),
                    templesMap = new Map(temples.map(x => [x.id, x])),
                    response = (await axios.get("https://api.search.nicovideo.jp/api/v2/snapshot/video/contents/search", {
                        httpsAgent: HttpsProxyAgent({ host: "127.0.0.1", port: 9910 }),
                        params: {
                            q: "",
                            fields: "contentId,viewCounter",
                            "filters[contentId]": temples.map(x => x.id),
                            _context: "apiguide",
                            _sort: "-startTime",
                            _limit: 100
                        }
                    })).data.data
                for (let x of response) (templesMap.get(x.contentId) as TempleSong).viewCount = x.viewCounter
                temples.sort((a, b) => b.viewCount - a.viewCount)
                text = original.replace(liststr, `${temples.map(x => x.text).join('\n|\n')}`)
                return bot.edit({ //一抹钙
                    title,
                    content: text,
                    summary: "排序",
                    minor: true
                })
            }).then(console.log, console.error)
        })
    )
})()