維基百科這類的網站都是由一個有2.6K星星的開源專案 MediaWiki 所建置而成,我對API文件的第一印象就是:很亂。
可能是功能太多的緣故,單單就參數的部分滑鼠就要滾九圈才看得完。
維基百科的API文件雖然有中文頁面,但實際上只翻譯了前面一點點。網路上的跟維基API有關的中文資料相較於金流、天氣等服務,更是少得可憐。也因為如此,我只好花30分鐘乖乖讀官方文件了。
除了最原始的API外,他還有 REST API ,但囿於原本的 DC chatbot 框架,我選擇了較為熟悉的原始API。
這次會用到的API是這個:
`https://zh.wikipedia.org/w/api.php?action=query&format=json&list=search&utf8=1&srsearch=${keyword}`
替換子域名 zh -> en 就會切換至英文頁面。
如果說今天我把${keyword}
改成柴犬的話,就會request這個JSON頁面。
我們要的就是他respond的snippet,然而,仔細一看,會發現他給我們的資料是html格式,因此,我們還要寫個函式去除Html標籤。
function stripHTML(input) {
var output = '';
if(typeof(input)=='string'){
var output = input.replace(/(<([^>]+)>)/ig,"");
}
return output;
}
進到主程式的部分:
新增了兩個別名"enwiki"、"zhwiki"來處理不同語言的搜尋結果,而無添加的"wiki"則是中文搜尋的結果。
之後建立一個 embed message 來回覆搜尋結果,並在程式正式開始先做簡單的邊緣測試。
在這裡使用了 request 套件,因為會發送請求,所以放了兩個try-catch做例外處理。我發現 request 的 URL 不能放中文的字串,所以還要 encode 成 URL。
接下來就依照返回的JSON數據,填入 embed message 裡。
比較重要的坑是貌似javascript的變數是類似c的傳址,所以,請求外面即使是全域變數也不能存裡面數據。(這我不確定,只是一種感覺而已)。
cmds/wiki.js
const request = require('request')
module.exports={
name: 'wiki',
description: 'getting wikipedia search result',
aliases: ['enwiki', 'zhwiki',],
cooldown: 0,
async execute(msg, args, cmd, client, Discord){
const Embed = new Discord.MessageEmbed()
.setColor('#5B00AE')
.setTimestamp()
.setFooter('Wikipedia');
if(!args){
msg.channel.send('請輸入欲搜尋的關鍵字');
return;
}
if(cmd === 'wiki' || cmd === 'zhwiki') var url = `https://zh.wikipedia.org/`;
else if(cmd === 'enwiki') var url = `https://en.wikipedia.org/`;
try{
request({
url: encodeURI(url+`w/api.php?action=query&format=json&list=search&utf8=1&srsearch=${args}`),
json: true
}, (err, res, req) => {
try{
Embed.addFields({
name: req.query.search[0].title,
value: stripHTML(req.query.search[0].snippet)
})
.setTitle('查看更多搜尋結果')
.setURL(url+`w/index.php?search=${args}&ns0=1`);
msg.channel.send(Embed);
}catch(e){
console.log(`Error:${e}`);
Embed.setTitle('查看線上搜尋結果')
.setURL(url+`w/index.php?search=${args}&ns0=1`)
.setDescription('搜尋失敗');
}
});
}catch(e){
console.log(`Error${e}`);
msg.channel.send('伺服器連線失敗,請稍後再試,謝謝');
}
}
}
最後看一下成果:
後記
這個小翠兒chatbot是我本地測試用的,跟微笑柴柴的prefix(@)不同,是#。
因為微笑柴柴因為已經部署了,所以還沒更新這個新功能,會等以後有其他更新時一併處理。
附錄