-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRetroarch Download Pico8.js
141 lines (121 loc) · 3.85 KB
/
Retroarch Download Pico8.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: light-brown; icon-glyph: memory;
// share-sheet-inputs: file-url;
/// <reference path="./types/retroarch.d.ts" />
// @ts-ignore
// eslint-disable-next-line
try { require; } catch(e) { require = importModule; }
const {
getInput,
string,
encodeURIComponent,
downloadText,
downloadFile,
pathJoin,
isFile,
log,
output
} = require('./lib/lib.js');
/**
* @typedef {Object} Thread represents a Pico-8 BBS Thread
* @param {string} url the link to the thread
* @param {string} name the name of the thread
*/
const urlLister = 'https://www.lexaloffle.com/bbs/lister.php';
const urlCarts = 'https://www.lexaloffle.com/bbs/cposts';
/** @type {ObjectMap<string>} */
const urlListerQuery = {
use_hurl: '1',
cat: '7',
sub: '2',
mode: '',
page: '1',
orderby: 'featured'
};
const help = '' +
`Downloads all "Featured" Pico-8 games into a given directory. If a game already
exists, it will not be re-downloaded.
`;
/**
* Given a query string key-value map, generates a query string.
* @param {ObjectMap<string>} map the map of parameter keys to values
* @return {string} the resulting query string
*/
const getQueryString = map =>
Object.entries(map)
.map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
.join('&');
/**
* Converts a user-edited name into a proper file name.
* @param {string} name the name to convert
* @return {string} the file name
*/
const getFileName = name => name
.replaceAll('[', '(')
.replaceAll(']', ')')
.replaceAll(/\s*&\s*/g, ' + ')
.replaceAll(/\s*:+\s*/g, ' - ')
.replaceAll(/\s*\/+\s*/g, '--')
.replaceAll(/[^\w\s\-'",.#()]/g, '_');
const gameMatcher = /`([^`]+)`[,'" \n]+\/bbs\/thumbs\/(.+?)\.png/g;
/**
* Parse CLI arguments and run `downloadPlaylist` once for every playlist found
* in the configuration file.
*/
const main = async () => {
const input = await getInput({
name: 'Retroarch Download Pico8',
help,
inScriptable: true,
args: [{
name: 'folder',
shortName: 'f',
type: 'pathFolder',
bookmarkName: 'retroarch-download-pico8-destination',
help: 'The directory to populate with Pico-8 cartridges.'
}]
});
if (!input) { return; }
const folder = string(input.folder);
let page = 1;
let countFound = 1;
let countDownload = 0;
let countFail = 0;
let countCache = 0;
while(countFound > 0) {
countFound = 0;
urlListerQuery.page = page.toString();
const query = getQueryString(urlListerQuery);
const text = await downloadText(`${urlLister}?${query}`);
for(const game of text.matchAll(gameMatcher) ?? [ ]) {
const urlName = game[2].replace(/^pico(8_)?/, '');
const urlPrefix = urlName.substring(0, 2);
const url = `${urlCarts}/${urlPrefix}/${urlName}.p8.png`;
const name = game[1]
.replaceAll('&', '&')
.replaceAll('"', '"');
const nameFile = getFileName(name) + '.p8.png';
const pathFile = pathJoin(folder, nameFile);
if (await isFile(pathFile)) {
log(`[ C] - ${nameFile}`);
countCache += 1;
} else {
//console.log(url);
const code = await downloadFile(url, pathFile);
log(`${code === 200 ? '[ D ]' : '[X ]'} - ${nameFile}`);
countFail += code === 200 ? 0 : 1;
countDownload += code === 200 ? 1 : 0;
}
countFound += 1;
}
page += 1;
}
output(
'Retroarch Download Pico8',
`Downloaded: ${countDownload}, ` +
`Failed: ${countFail}, ` +
`Cached: ${countCache}`
);
};
main();