diff --git a/core.js b/core.js index 7d9ded3..09efa43 100644 --- a/core.js +++ b/core.js @@ -370,7 +370,9 @@ let core = { }) }, - update(keys, done) { + update(keys, opt, done) { + if (opt.db) return api.getDB() + let aa = [] if (!keys) keys = _.keys(ads.data) diff --git a/index.js b/index.js index 774f1dd..727f4a8 100755 --- a/index.js +++ b/index.js @@ -60,9 +60,13 @@ cli .command('update') .description('update all installed addons') .option('--anyway', 'update latest addon release for _classic_ mode anyway') + .option( + '--db', + 'for update addon database, no addon will be updated if this option is specified' + ) .action(cmd => { cfg.anyway(cmd.anyway) - core.update(cli.args.length > 1 ? cli.args.slice(0, -1) : null) + core.update(cli.args.length > 1 ? cli.args.slice(0, -1) : null, cmd) }) cli diff --git a/source/curse.js b/source/curse.js index b3c4990..afba051 100644 --- a/source/curse.js +++ b/source/curse.js @@ -1,22 +1,3 @@ -const x = require('x-ray')({ - filters: { - trim(v) { - return typeof v === 'string' ? v.trim() : v - }, - num(v) { - let unit = v.split(' ')[0] - if (unit) { - unit = unit[unit.length - 1].toLowerCase() - unit = unit === 'm' ? 1000000 : unit === 'k' ? 1000 : 1 - } else unit = 1 - return parseInt(v.split(',').join('')) * unit - }, - tail(v) { - let d = v.split('/') - return d[d.length - 1] - } - } -}) const g = require('got') const _ = require('underscore') const cfg = require('../lib/config') @@ -24,70 +5,98 @@ const log = console.log let api = { $url: 'https://www.curseforge.com/wow/addons/', - $srl: 'https://addons-ecs.forgesvc.net/api/v2/addon/search', + $srl: 'https://addons-ecs.forgesvc.net/api/v2/addon', $lcl: /(addons|projects)\/(.*)$/, $scl: 'curseforge.com', info(ad, done) { - let mo = cfg.getMode() - let url = api.$url + ad.key + '/files/all' - - if (!ad.anyway) - url += `?filter-game-version=1738749986:${ - mo === '_retail_' ? '517' : '67408' - }` - - x(url, { - name: 'header h2 | trim', - owner: '.text-sm span | trim', - create: ['div span abbr@data-epoch | num'], - - download: ['.w-full span | num'], - version: x('tbody tr', [ - { - name: 'a | trim', - size: ['td | trim'], - game: 'td div div | trim', - link: '.button--hollow@href' - } - ]) - })((err, d) => { - // log('/???', ad.key, err, d) - if (!d) { - done() - return - } + let flavor = cfg.getMode() === '_classic_' ? 'wow_classic' : 'wow_retail' + let top = require('./') - let tmp = d.create - d.create = tmp[1] - d.update = tmp[2] + top.getDB('curse', db => { + // log('curse info') + if (!db) return done() - d.version.forEach(x => { - x.link += '/file' - x.size = x.size[2] - }) - d.download = d.download[2] + // log('got db', db) + + let x = _.find(db, d => ad.key === d.key) + + // log('got x', x) + + if (!x) return done() + + let id = x.id + + let qs = `${api.$srl}/${id}` + + // log('getting', qs) + g.get(qs) + .then(res => { + res = JSON.parse(res.body) + // log('got', res) + + let data = { + name: res.name, + owner: res.authors ? res.authors[0].name : 'unknown', + create: new Date(res.dateCreated).valueOf() / 1000, + update: new Date(res.dateReleased).valueOf() / 1000, + download: res.downloadCount, + version: res.latestFiles.map(x => { + return { + name: x.displayName, + size: x.fileLength, + link: x.downloadUrl, + flavor: x.gameVersionFlavor, + date: new Date(x.fileDate) + } + }) + } + + if (!ad.anyway) + data.version = _.filter(data.version, x => x.flavor === flavor) + + data.version.sort((a, b) => b.date - a.date) - // log(d) - done(err || !d.update || d.version.length === 0 ? null : d) + // log('final data', data) + done(!data.version.length ? null : data) + }) + .catch(err => { + done() + }) }) }, - search(ad, done) { - let mo = cfg.getMode() - - let qs = `${api.$srl}?gameId=1&index=0&pageSize=15&searchFilter=${ad.key}` + summary(done) { + g.get('https://github.com/antiwinter/scrap/raw/master/wowa/db-curse.json') + .then(res => { + done(JSON.parse(res.body)) + }) + .catch(err => { + done() + }) + }, - if (mo === '_classic_' && !ad.anyway) - qs += `&gameVersion=${cfg.getGameVersion()}` + search(ad, done) { + let flavor = cfg.getMode() === '_classic_' ? 'wow_classic' : 'wow_retail' + let qs = `${api.$srl}/search?gameId=1&index=0&pageSize=30&searchFilter=${ad.key}` // log('searching', qs) g.get(qs) .then(res => { // log(res.body) + let data = JSON.parse(res.body) + + if (!ad.anyway) + data = _.filter(data, d => + _.find( + d.gameVersionLatestFiles, + _d => _d.gameVersionFlavor === flavor + ) + ) + done( - JSON.parse(res.body).map(x => { + data.map(x => { return { name: x.name, key: x.websiteUrl.split('/').pop(), diff --git a/source/index.js b/source/index.js index 37a383e..bd91ebd 100644 --- a/source/index.js +++ b/source/index.js @@ -128,29 +128,46 @@ let src = { }, summary(done) { - src.$api.mmoui.summary(done) + let db = [] + src.$api.curse.summary(d => { + db = db.concat(d) + src.$api.mmoui.summary(d => { + db = db.concat(d) + done(db) + }) + }) }, - getDB(done) { + getDB(filter, done) { let p = cfg.getPath('db') + if (!done) { + done = filter + filter = null + } + + let _done = db => { + done(filter ? _.filter(db, d => d.source === filter) : db) + } + if ( !fs.existsSync(p) || - new Date() - fs.statSync(p).mtime > 24 * 3600 * 1000 + new Date() - fs.statSync(p).mtime > 24 * 3600 * 1000 || + !done // force update ) { mk(path.dirname(p), err => { process.stdout.write(cl.i('\nUpdating database...')) src.summary(s => { fs.writeFileSync(p, JSON.stringify(s), 'utf-8') log(cl.i('done')) - done(s) + if (done) _done(s) }) }) return } - done(fs.existsSync(p) ? JSON.parse(fs.readFileSync(p, 'utf-8')) : null) + _done(fs.existsSync(p) ? JSON.parse(fs.readFileSync(p, 'utf-8')) : null) return } } diff --git a/source/mmoui.js b/source/mmoui.js index 4ffe30a..7dee16e 100644 --- a/source/mmoui.js +++ b/source/mmoui.js @@ -67,7 +67,7 @@ let api = { let mo = cfg.getMode() let top = require('./index') - top.getDB(db => { + top.getDB('mmoui', db => { if (!db) return done() if (!ad.anyway) db = _.filter(db, d => mo === d.mode) diff --git a/test.js b/test.js index ed6cbd6..3db24a9 100644 --- a/test.js +++ b/test.js @@ -68,7 +68,7 @@ function commonTests(aa) { }) ava.serial.cb(nme('update-none'), t => { - core.update(null, res => { + core.update(null, {}, res => { let p = cfg.getPath('addon') t.assert(res.count === 0) t.assert(res.update === 1) @@ -89,7 +89,7 @@ function commonTests(aa) { ava.serial.cb(nme('update-1'), t => { ads.data['classicon'].update = 0 - core.update(null, res => { + core.update(null, {}, res => { let p = cfg.getPath('addon') t.assert(res.count === 1) t.assert(res.update === 1) @@ -215,7 +215,7 @@ function commonTests(aa) { t.assert(res.match(/Deadly Boss Mods/)) t.assert(res.match(/MysticalOS/)) t.assert(res.match(/curse/)) - t.assert(res.search(cfg.getGameVersion()) > 0) + // t.assert(res.search(cfg.getGameVersion()) > 0) t.end() }) })