enwnbot

Converts MediaWiki [[links]] and {{templates}} to links on IRC
git clone http://git.hanabi.in/repos/enwnbot.git
Log | Files | Refs | README | LICENSE

commit 704f0b6984c8bd12b6234212ece779513b186f9c
parent e6d45e19a80f5b99171fedc5057b71958635ae89
Author: Agastya Chandrakant <acagastya@outlook.com>
Date:   Thu,  4 Jun 2020 17:22:05 +0530

Implement time

Diffstat:
M.gitignore | 3+++
Mconfig.js | 2+-
Mirc.js | 64+++++++++++++++++++++++++++++++++-------------------------------
Mpackage.json | 4++--
MpromUrlShortener.js | 3+++
Mutils.js | 35-----------------------------------
Myarn.lock | 10+++++-----
7 files changed, 47 insertions(+), 74 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1 +1,3 @@ node_modules +rss.js +test.js +\ No newline at end of file diff --git a/config.js b/config.js @@ -7,7 +7,7 @@ const config = { maintainers: ['ssmith'], report: '!ADMIN', RQAPI: - 'https://en.wikinews.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Review&format=json', + 'https://en.wikinews.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Review&format=json&cmsort=timestamp&cmprop=timestamp|ids|title', server: 'irc.freenode.net', shortURL: 'https://meta.wikimedia.org/w/api.php?action=shortenurl&format=json&url=', diff --git a/irc.js b/irc.js @@ -1,11 +1,10 @@ const irc = require('irc'); const fetch = require('node-fetch'); -const _ = require('underscore'); +const moment = require('moment'); const { admins, botName, - botPass, channels, maintainers, report, @@ -13,14 +12,7 @@ const { server, } = require('./config'); -const { - fetchData, - fullUrl, - getFullLink, - getFullTemplate, - urlShortener, - urlShortener1, -} = require('./utils'); +const { fetchData, fullUrl, getFullLink, getFullTemplate } = require('./utils'); const { fallback, reset, short } = require('./promUrlShortener'); @@ -58,24 +50,25 @@ async function announceRQ(sender, channel) { `${list.length} articles to review, ${sender}. They are:` ); const titles = list.map(({ title }) => title); + const times = list.map(({ timestamp }) => moment().to(moment(timestamp))); const urls = titles.map(fullUrl); client.say(channel, '(Hold on a sec... Shortening the URLs.)'); - sayShortUrls(urls, channel, titles); + sayShortUrls(urls, channel, titles, times); } } } -async function sayShortUrls(urlList, channel, titles = []) { +async function sayShortUrls(urlList, channel, titles = [], times = []) { const shortUrls = await Promise.all(urlList.map(short)); - if (titles.length == 0) { - shortUrls.forEach(({ url, err }) => { - if (!err) client.say(channel, url); - }); - } else { - shortUrls.forEach(({ url, err }, idx) => { - if (!err) client.say(channel, `${url} -- ${titles[idx]}`); - }); - } + + shortUrls.forEach(({ url, err }, idx) => { + if (!err) { + let msg = `${url} sumbitted for review`; + if (times.length) msg += ` *${times[idx]}*`; + if (titles.length) msg += ` -- ${titles[idx]}`; + client.say(channel, msg); + } else console.log(err); + }); } function groupChat(sender, channel, msg) { @@ -112,16 +105,25 @@ const submittedState = { async function announceSubmitted() { const res = await fetch(RQAPI); const parsed = await res.json(); - const titles = parsed.query.categorymembers.map((el) => el.title); - // rm already announced - const yetToAnnounce = _.without(titles, ...submittedState.announced); - submittedState.announced.push(...yetToAnnounce); - const prepped = yetToAnnounce.map(fullUrl); - if (prepped.length) { - channels.forEach((channel) => client.say(channel, 'Submitted for review:')); - channels.forEach((channel) => - sayShortUrls(prepped, channel, yetToAnnounce) - ); + + const titleTime = parsed.query.categorymembers.map(({ title, timestamp }) => { + return { timestamp, title }; + }); + const allTitles = parsed.query.categorymembers.map(({ title }) => title); + const pending = titleTime.filter( + ({ title }) => !submittedState.announced.includes(title) + ); + // const purgedGlobal = submittedState.announced.filter((el) => + // allTitles.includes(el) + // ); + const titles = pending.map(({ title }) => title); + submittedState.announced = [...allTitles]; + const urls = titles.map(fullUrl); + const times = pending.map(({ timestamp }) => moment().to(moment(timestamp))); + + if (urls.length) { + channels.forEach((channel) => client.say(channel, 'Review Queue:')); + channels.forEach((channel) => sayShortUrls(urls, channel, titles, times)); } } diff --git a/package.json b/package.json @@ -1,10 +1,10 @@ { "dependencies": { "irc": "^0.5.2", + "moment": "^2.26.0", "node-fetch": "^2.6.0", "request": "^2.88.2", - "tinyurl": "^1.1.5", - "underscore": "^1.10.2" + "tinyurl": "^1.1.5" }, "scripts": { "start": "node irc.js" diff --git a/promUrlShortener.js b/promUrlShortener.js @@ -131,10 +131,13 @@ async function short(URI) { }); const { body } = data; const parsed = JSON.parse(body); + if (parsed.error) throw new Error('Rate limit'); res.url = parsed.shortenurl.shorturl; } catch (error) { + globalState.useFallback = true; globalState.error = error; res.error = error; + res.url = await TUrl.shorten(URI); } } else { try { diff --git a/utils.js b/utils.js @@ -41,44 +41,9 @@ function getFullTemplate(template) { return `${URL}Template:${word}`; } -async function urlShortener(URI, bot) { - const req = `${shortURL}${URI}`; - const res = {}; - try { - const data = await bot.rawRequest({ - action: 'shortenurl', - format: 'json', - uri: req, - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - }); - const parsed = JSON.parse(data); - res.url = parsed.shortenurl.shorturl; - } catch (error) { - res.err = true; - console.warn('Error in urlShortener:', error); - } - return res; -} - -async function urlShortener1(URI) { - const res = {}; - try { - res.url = await TUrl.shorten(URI); - } catch (error) { - res.err = true; - console.warn('Error in urlShortener:', error); - } - return res; -} - module.exports = { fetchData, fullUrl, getFullLink, getFullTemplate, - urlShortener, - urlShortener1, }; diff --git a/yarn.lock b/yarn.lock @@ -225,6 +225,11 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.44.0" +moment@^2.26.0: + version "2.26.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a" + integrity sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw== + nan@^2.3.3, nan@^2.3.5: version "2.14.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" @@ -343,11 +348,6 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -underscore@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.10.2.tgz#73d6aa3668f3188e4adb0f1943bd12cfd7efaaaf" - integrity sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg== - uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"