这是Adorable Newcomer[更多]讨论页贡献上传历史封禁及历史被删贡献移动日志巡查日志用户权限的分身账号。 其操作者在本页主动宣示其用途,遵循基本方针和分身账号方针操控此账号。 致维护人员:当要对此账号采取任何操作前,请先联系此用户。 |
更新{{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)
})
)
})()
|