diff --git a/modules/oeis/config.json b/modules/oeis/config.json new file mode 100644 index 0000000..5a951d2 --- /dev/null +++ b/modules/oeis/config.json @@ -0,0 +1,3 @@ +{ + "outputPrefix": "\u00033oeis\u000f" +} diff --git a/modules/oeis/oeis.js b/modules/oeis/oeis.js new file mode 100644 index 0000000..8debcc7 --- /dev/null +++ b/modules/oeis/oeis.js @@ -0,0 +1,144 @@ +/** + * Module Name: oeis + * Description: Interacts with the Online Encyclopedia of Integer Sequences + * API to provide integer sequence lookups and related information + */ + +var rp = require('request-promise-native'); + +var OEIS = function(dbot) { + this.apiRoot = 'https://oeis.org/search'; + this.webRoot = 'https://oeis.org/'; + + this.internalAPI = { + 'parseResult': result => { + return { + a: result.number, + a6: 'A' + result.number.toString().padStart(6, '0'), + name: result.name.slice(0, result.name.indexOf('.') + 1), + sample: result.data.split(',').slice(0, 8), + more: result.data.length > 8, + url: this.webRoot + 'A' + result.number.toString().padStart(6, '0') + }; + }, + + 'outputError': (event, e) => { + switch(e) { + case 'no-results': event.reply(dbot.t('sequence_not_found')); return; + } + + console.log(e); + event.reply(dbot.t('oeis_error')); + } + }; + + this.api = { + 'lookupSequenceByKeywords': async keywords => { + var body = await rp({ + url: this.apiRoot, + qs: { + fmt: 'json', + q: '"' + keywords + '"' + }, + json: true + }); + + if(!body.results) throw 'no-results'; + return this.internalAPI.parseResult(body.results[0]); + }, + + 'lookupSequenceByExample': async (terms, inOrder) => { + var joinChar = inOrder ? ',' : ' '; + var body = await rp({ + url: this.apiRoot, + qs: { + fmt: 'json', + q: terms.join(joinChar) + }, + json: true + }); + + if(!body.results) throw 'no-results'; + return this.internalAPI.parseResult(body.results[0]); + }, + + 'lookupSequenceByA': async a => { + var body = await rp({ + url: this.apiRoot, + qs: { + fmt: 'json', + q: 'A' + a.toString().padStart(6, '0') + }, + json: true + }); + + if(!body.results) throw 'no-results'; + return this.internalAPI.parseResult(body.results[0]); + }, + + 'getRandomSequenceA': async set => { + // This feature uses OEIS's 'webcam' which serves up random entries + // each time the page is refreshed. It appears to be the only way to get + // valid random entries from the database. The alternative is to just generate + // random A-numbers from the set of all A-numbers, but that seems dirty to me. + var body = await rp({ + url: this.webRoot + '/webcam', + qs: { + fromjavascript: 1, + q: 'keyword:' + set + } + }); + + // Find where the A-number is located + var i = body.indexOf('