From 0eaa22bd291b03b5a9d135849d261211f56f18f2 Mon Sep 17 00:00:00 2001 From: Siddharth VP Date: Sat, 12 Jun 2021 14:59:28 +0530 Subject: [PATCH] remove xdate, commit some uncommitted tests --- .eslintrc.js | 3 +- botbase.ts | 3 - old/g13-watch/old-sqlite/save-to-db.js | 12 +- redis.test.ts | 11 + reports/draftify-watch.js | 8 +- reports/prod-watch.js | 8 +- webservice/test.ts | 1 + xdate.js | 306 ------------------------- 8 files changed, 28 insertions(+), 324 deletions(-) create mode 100644 redis.test.ts delete mode 100644 xdate.js diff --git a/.eslintrc.js b/.eslintrc.js index c8522d2..6e18255 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,8 @@ module.exports = { "env": { "commonjs": true, "es2021": true, - "node": true + "node": true, + "mocha": true }, "extends": "eslint:recommended", "parserOptions": { diff --git a/botbase.ts b/botbase.ts index 1c70b3f..6a0764a 100644 --- a/botbase.ts +++ b/botbase.ts @@ -38,9 +38,6 @@ export const log = mwn.log; /** Parsed console arguments */ export const argv = require('minimist')(process.argv.slice(2)); -/** Date library, deprecated (now available in mwn) */ -export const xdate = require('./xdate'); - /** bot account and database access credentials */ const auth = require('./.auth'); export class AuthManager { diff --git a/old/g13-watch/old-sqlite/save-to-db.js b/old/g13-watch/old-sqlite/save-to-db.js index 97b2e2a..d0219d0 100644 --- a/old/g13-watch/old-sqlite/save-to-db.js +++ b/old/g13-watch/old-sqlite/save-to-db.js @@ -1,6 +1,6 @@ // start job using: npm run start -const {bot, log, xdate, emailOnError} = require('../botbase'); +const {bot, log, emailOnError} = require('../botbase'); const EventSource = require('eventsource'); const TextExtractor = require('../TextExtractor')(bot); const sqlite3 = require('sqlite3'); @@ -31,9 +31,9 @@ async function main() { } const firstrow = await db.get(`SELECT ts FROM g13 ORDER BY ts DESC`); - - const lastTs = firstrow ? new Date(firstrow.ts * 1000).toISOString() : - (function() { var d = new xdate(); d.setUTCHours(0, 0, 0, 0); return d.toISOString(); })(); + + const lastTs = firstrow ? new Date(firstrow.ts * 1000).toISOString() : + (function() { var d = new bot.date(); d.setUTCHours(0, 0, 0, 0); return d.toISOString(); })(); const stream = new EventSource('https://stream.wikimedia.org/v2/stream/recentchange?since=' + lastTs, { headers: { @@ -61,7 +61,7 @@ async function main() { } let title = match[1]; let ts = data.timestamp; - log(`[+] Page ${title} at ${new xdate(ts * 1000).format('YYYY-MM-DD HH:mm:ss')}`); + log(`[+] Page ${title} at ${new bot.date(ts * 1000).format('YYYY-MM-DD HH:mm:ss')}`); let pagedata = await bot.read(title, {prop: 'revisions|description'}); let text = pagedata.revisions && pagedata.revisions[0] && pagedata.revisions[0].content; let desc = pagedata.description; @@ -89,7 +89,7 @@ async function main() { throw err; } }; - + } main().catch(err => { diff --git a/redis.test.ts b/redis.test.ts new file mode 100644 index 0000000..6446146 --- /dev/null +++ b/redis.test.ts @@ -0,0 +1,11 @@ +import { getRedisInstance, REDIS_HOST } from "./redis"; +import assert = require("assert"); +import { createLocalSSHTunnel } from "./utils"; + +it('redis', async function () { + this.timeout(10000); + await createLocalSSHTunnel(REDIS_HOST); + const redis = await getRedisInstance(); + await redis.set('qwertyhjupo', '123'); + assert.strictEqual(await redis.get('qwertyhjupo'), '123'); +}); \ No newline at end of file diff --git a/reports/draftify-watch.js b/reports/draftify-watch.js index e677e97..d0e87cc 100644 --- a/reports/draftify-watch.js +++ b/reports/draftify-watch.js @@ -1,13 +1,13 @@ -const {bot, mwn, log, xdate, utils, emailOnError, TextExtractor} = require('../botbase'); +const {bot, mwn, log, utils, emailOnError, TextExtractor} = require('../botbase'); const {formatSummary} = require('./commons'); (async () => { await bot.getTokensAndSiteInfo(); - var ts1 = new xdate().subtract(8, 'days'); + var ts1 = new bot.date().subtract(8, 'days'); ts1.setHours(0, 0, 0, 0); - var ts2 = new xdate().subtract(1, 'day'); + var ts2 = new bot.date().subtract(1, 'day'); ts2.setHours(0, 0, 0, 0); // fetch page moves @@ -138,7 +138,7 @@ const {formatSummary} = require('./commons'); var user = utils.arrayChunk(data.user.split(''), 14).map(e => e.join('')).join('
'); table.addRow([ - data.created ? new xdate(data.created).format('YYYY-MM-DD') : '', + data.created ? new bot.date(data.created).format('YYYY-MM-DD') : '', `[[${page}]] (moved from [[${data.source}]])`, `${data.excerpt || ''}`, `[[User:${data.user}|${user}]]`, diff --git a/reports/prod-watch.js b/reports/prod-watch.js index 1d5ae3b..7962794 100644 --- a/reports/prod-watch.js +++ b/reports/prod-watch.js @@ -1,4 +1,4 @@ -const {bot, log, xdate, mwn, emailOnError} = require('../botbase'); +const {bot, log, mwn, emailOnError} = require('../botbase'); const {formatSummary} = require('./commons'); (async function() { @@ -311,9 +311,9 @@ const {formatSummary} = require('./commons'); // Triggers: - await main(new xdate().subtract(7, 'days'), 'last week'); - await main(new xdate().subtract(14, 'days'), 'last fortnight'); - await main(new xdate().subtract(28, 'days'), 'last month'); + await main(new bot.date().subtract(7, 'days'), 'last week'); + await main(new bot.date().subtract(14, 'days'), 'last fortnight'); + await main(new bot.date().subtract(28, 'days'), 'last month'); log(`[i] Finished`); diff --git a/webservice/test.ts b/webservice/test.ts index 081f554..16a8104 100644 --- a/webservice/test.ts +++ b/webservice/test.ts @@ -18,5 +18,6 @@ describe('articlesearch', () => { assertValidId(stringToId('lor"m')); assertValidId(stringToId('lor%$2&()@!m')); assertValidId(stringToId('lo*^r"m-')); + assertValidId(stringToId('H. P. Lovecraft')); }); }); \ No newline at end of file diff --git a/xdate.js b/xdate.js deleted file mode 100644 index 21fd604..0000000 --- a/xdate.js +++ /dev/null @@ -1,306 +0,0 @@ -// Date library, copied off morebits.js (though originally written by me) - -/** - * **************** xdate **************** - */ - -/** - * @constructor - * Create a date object. MediaWiki timestamp format is also acceptable, - * in addition to everything that JS Date() accepts. - */ -var xdate = function() { - var args = Array.prototype.slice.call(arguments); - - if (typeof args[0] === 'string') { - // Attempt to remove a comma and paren-wrapped timezone, to get MediaWiki timestamps to parse - // Firefox (at least in 75) seems to be okay with the comma, though - args[0] = args[0].replace(/(\d\d:\d\d),/, '$1').replace(/\(UTC\)/, 'UTC'); - } - this._d = new (Function.prototype.bind.apply(Date, [Date].concat(args))); - - // parse MediaWiki format: YYYYMMDDHHmmss (used in afd-sorting) - if (isNaN(this._d.getTime()) && typeof args[0] === 'string' && /^\d{14}$/.test(args[0])) { - let match = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/.exec(args[0]); - match[2] = parseInt(match[2]) - 1; // fix month - this._d = new (Function.prototype.bind.apply(Date, [Date].concat(match.slice(1)))); - } - - // Still no? - if (isNaN(this._d.getTime())) { - console.warn('Invalid initialisation of xdate object: ', args); - } -}; - -xdate.localeData = { - months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], - monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], - days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], - relativeTimes: { - thisDay: '[Today at] h:mm A', - prevDay: '[Yesterday at] h:mm A', - nextDay: '[Tomorrow at] h:mm A', - thisWeek: 'dddd [at] h:mm A', - pastWeek: '[Last] dddd [at] h:mm A', - other: 'YYYY-MM-DD' - } -}; - -// Allow native Date.prototype methods to be used on xdate objects -Object.getOwnPropertyNames(Date.prototype).forEach(function(func) { - xdate.prototype[func] = function() { - return this._d[func].apply(this._d, Array.prototype.slice.call(arguments)); - }; -}); - -Object.assign(xdate.prototype, { - - isValid: function() { - return !isNaN(this.getTime()); - }, - - /** @param {(Date|xdate)} date */ - isBefore: function(date) { - return this.getTime() < date.getTime(); - }, - isAfter: function(date) { - return this.getTime() > date.getTime(); - }, - - /** @return {string} */ - getUTCMonthName: function() { - return xdate.localeData.months[this.getUTCMonth()]; - }, - getUTCMonthNameAbbrev: function() { - return xdate.localeData.monthsShort[this.getUTCMonth()]; - }, - getMonthName: function() { - return xdate.localeData.months[this.getMonth()]; - }, - getMonthNameAbbrev: function() { - return xdate.localeData.monthsShort[this.getMonth()]; - }, - getUTCDayName: function() { - return xdate.localeData.days[this.getUTCDay()]; - }, - getUTCDayNameAbbrev: function() { - return xdate.localeData.daysShort[this.getUTCDay()]; - }, - getDayName: function() { - return xdate.localeData.days[this.getDay()]; - }, - getDayNameAbbrev: function() { - return xdate.localeData.daysShort[this.getDay()]; - }, - - /** - * Add a given number of minutes, hours, days, months or years to the date. - * This is done in-place. The modified date object is also returned, allowing chaining. - * @param {number} number - should be an integer - * @param {string} unit - * @throws {Error} if invalid or unsupported unit is given - * @returns {xdate} - */ - add: function(number, unit) { - // mapping time units with getter/setter function names - var unitMap = { - seconds: 'Seconds', - minutes: 'Minutes', - hours: 'Hours', - days: 'Date', - months: 'Month', - years: 'FullYear' - }; - var unitNorm = unitMap[unit] || unitMap[unit + 's']; // so that both singular and plural forms work - if (unitNorm) { - this['set' + unitNorm](this['get' + unitNorm]() + number); - return this; - } - throw new Error('Invalid unit "' + unit + '": Only ' + Object.keys(unitMap).join(', ') + ' are allowed.'); - }, - - /** - * Subtracts a given number of minutes, hours, days, months or years to the date. - * This is done in-place. The modified date object is also returned, allowing chaining. - * @param {number} number - should be an integer - * @param {string} unit - * @throws {Error} if invalid or unsupported unit is given - * @returns {xdate} - */ - subtract: function(number, unit) { - return this.add(-number, unit); - }, - - /** - * Formats the date into a string per the given format string. - * Replacement syntax is a subset of that in moment.js. - * **Different from morebits.js version: takes zone=utc by default** - * @param {string} formatstr - * @param {(string|number)} [zone=utc] - 'system' (for browser-default time zone), - * 'utc' (for UTC), or specify a time zone as number of minutes past UTC. - * @returns {string} - */ - format: function(formatstr, zone) { - if (!this.isValid()) { - return ''; // avoid bogus NaNs in output - } - var udate = this; - // create a new date object that will contain the date to display as system time - if (!zone || zone === 'utc') { - udate = new xdate(this.getTime()).add(this.getTimezoneOffset(), 'minutes'); - } else if (typeof zone === 'number') { - // convert to utc, then add the utc offset given - udate = new xdate(this.getTime()).add(this.getTimezoneOffset() + zone, 'minutes'); - } - - var pad = function(num) { - return num < 10 ? '0' + num : num; - }; - var h24 = udate.getHours(), m = udate.getMinutes(), s = udate.getSeconds(); - var D = udate.getDate(), M = udate.getMonth() + 1, Y = udate.getFullYear(); - var h12 = h24 % 12 || 12, amOrPm = h24 >= 12 ? 'PM' : 'AM'; - var replacementMap = { - 'HH': pad(h24), 'H': h24, 'hh': pad(h12), 'h': h12, 'A': amOrPm, - 'mm': pad(m), 'm': m, - 'ss': pad(s), 's': s, - 'dddd': udate.getDayName(), 'ddd': udate.getDayNameAbbrev(), 'd': udate.getDay(), - 'DD': pad(D), 'D': D, - 'MMMM': udate.getMonthName(), 'MMM': udate.getMonthNameAbbrev(), 'MM': pad(M), 'M': M, - 'YYYY': Y, 'YY': pad(Y % 100), 'Y': Y - }; - - var unbinder = new xunbinder(formatstr); // escape stuff between [...] - unbinder.unbind('\\[', '\\]'); - unbinder.content = unbinder.content.replace( - /* Regex notes: - * d(d{2,3})? matches exactly 1, 3 or 4 occurrences of 'd' ('dd' is treated as a double match of 'd') - * Y{1,2}(Y{2})? matches exactly 1, 2 or 4 occurrences of 'Y' - */ - /H{1,2}|h{1,2}|m{1,2}|s{1,2}|d(d{2,3})?|D{1,2}|M{1,4}|Y{1,2}(Y{2})?|A/g, - function(match) { - return replacementMap[match]; - } - ); - return unbinder.rebind().replace(/\[(.*?)\]/g, '$1'); - }, - - /** - * Gives a readable relative time string such as "Yesterday at 6:43 PM" or "Last Thursday at 11:45 AM". - * Similar to calendar in moment.js, but with time zone support. - * @param {(string|number)} [zone=system] - 'system' (for browser-default time zone), - * 'utc' (for UTC), or specify a time zone as number of minutes past UTC - * @returns {string} - */ - calendar: function(zone) { - // Zero out the hours, minutes, seconds and milliseconds - keeping only the date; - // find the difference. Note that setHours() returns the same thing as getTime(). - var dateDiff = (new Date().setHours(0, 0, 0, 0) - - new Date(this).setHours(0, 0, 0, 0)) / 8.64e7; - switch (true) { - case dateDiff === 0: - return this.format(xdate.localeData.relativeTimes.thisDay, zone); - case dateDiff === 1: - return this.format(xdate.localeData.relativeTimes.prevDay, zone); - case dateDiff > 0 && dateDiff < 7: - return this.format(xdate.localeData.relativeTimes.pastWeek, zone); - case dateDiff === -1: - return this.format(xdate.localeData.relativeTimes.nextDay, zone); - case dateDiff < 0 && dateDiff > -7: - return this.format(xdate.localeData.relativeTimes.thisWeek, zone); - default: - return this.format(xdate.localeData.relativeTimes.other, zone); - } - }, - - /** - * @returns {RegExp} that matches wikitext section titles such as ==December 2019== or - * === Jan 2018 === - */ - monthHeaderRegex: function() { - return new RegExp('^==+\\s*(?:' + this.getUTCMonthName() + '|' + this.getUTCMonthNameAbbrev() + - ')\\s+' + this.getUTCFullYear() + '\\s*==+', 'mg'); - }, - - /** - * Creates a wikitext section header with the month and year. - * @param {number} [level=2] - Header level (default 2) - * @returns {string} - */ - monthHeader: function(level) { - level = level || 2; - var header = Array(level + 1).join('='); // String.prototype.repeat not supported in IE 11 - return header + ' ' + this.getUTCMonthName() + ' ' + this.getUTCFullYear() + ' ' + header; - } - -}); - - -/** - * **************** unbinder **************** - * Used for temporarily hiding a part of a string while processing the rest of it. - * - * eg. var u = new unbinder("Hello world world"); - * u.unbind(''); - * u.content = u.content.replace(/world/g, 'earth'); - * u.rebind(); // gives "Hello earth earth" - * - * Text within the 'unbinded' part (in this case, the HTML comment) remains intact - * unbind() can be called multiple times to unbind multiple parts of the string. - * - * Used by Morebits.wikitext.page.commentOutImage - */ - -/** - * @constructor - * @param {string} string - */ -var xunbinder = function Unbinder(string) { - if (typeof string !== 'string') { - throw new Error('not a string'); - } - this.content = string; - this.counter = 0; - this.history = {}; - this.prefix = '%UNIQ::' + Math.random() + '::'; - this.postfix = '::UNIQ%'; -}; - -xunbinder.prototype = { - /** - * @param {string} prefix - * @param {string} postfix - */ - unbind: function UnbinderUnbind(prefix, postfix) { - var re = new RegExp(prefix + '([\\s\\S]*?)' + postfix, 'g'); - this.content = this.content.replace(re, xunbinder.getCallback(this)); - }, - - /** @returns {string} The output */ - rebind: function UnbinderRebind() { - var content = this.content; - content.self = this; - for (var current in this.history) { - if (Object.prototype.hasOwnProperty.call(this.history, current)) { - content = content.replace(current, this.history[current]); - } - } - return content; - }, - prefix: null, // %UNIQ::0.5955981644938324:: - postfix: null, // ::UNIQ% - content: null, // string - counter: null, // 0++ - history: null // {} -}; - -xunbinder.getCallback = function UnbinderGetCallback(self) { - return function UnbinderCallback(match) { - var current = self.prefix + self.counter + self.postfix; - self.history[current] = match; - ++self.counter; - return current; - }; -}; - -module.exports = xdate; \ No newline at end of file