Skip to content

Commit 5d8a6bb

Browse files
Current work on getting the wiki to be the source of truth.
1 parent f810c6d commit 5d8a6bb

File tree

8 files changed

+835
-13
lines changed

8 files changed

+835
-13
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
*.mw-datamaps
12
*.png
23
*.tiled-session
34
node_modules

extensions/includes/api.mjs

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { InterwikiDataImpl, MetadataImpl } from './metadata.mjs';
12
import { getStringProperty, getWikiUrl } from './util.mjs';
23

34
const USER_AGENT = `tiled-datamaps/1.0 (https://github.com/utdrwiki/maps; admin@undertale.wiki) tiled/${tiled.version}`;
@@ -28,13 +29,18 @@ export function getRestUrl(language = 'en') {
2829
* @param {(value: any|PromiseLike<any>) => void} resolve Promise
2930
* resolution function
3031
* @param {(reason: any?) => void} reject Promise rejection function
32+
* @param {boolean} isArrayBuffer Whether the request expects a binary response
3133
* @returns {() => void} Ready state change handler
3234
*/
33-
const readyStateChange = (xhr, resolve, reject) => () => {
35+
const readyStateChange = (xhr, resolve, reject, isArrayBuffer = false) => () => {
3436
if (xhr.readyState === XMLHttpRequest.DONE) {
3537
if (xhr.status === 200) {
3638
try {
37-
resolve(JSON.parse(xhr.responseText));
39+
if (isArrayBuffer) {
40+
resolve(xhr.response);
41+
} else {
42+
resolve(JSON.parse(xhr.responseText));
43+
}
3844
} catch (error) {
3945
reject(new Error(`Failed to parse response: ${xhr.responseText}`));
4046
}
@@ -160,3 +166,107 @@ export function edit(title, text, summary, accessToken, language = 'en') {
160166
return response.edit;
161167
});
162168
}
169+
170+
/**
171+
* Retrieves maps from the wiki under specific criteria.
172+
* @param {object} options Options for retrieving maps
173+
* @param {string} language Wiki language
174+
* @returns {Promise<DataMap[]>} List of maps on the wiki
175+
*/
176+
function getMaps(options, language = 'en') {
177+
return httpGet(getApiUrl(language), Object.assign({
178+
action: 'query',
179+
prop: 'revisions',
180+
rvprop: 'ids|content',
181+
rvslots: 'main',
182+
format: 'json',
183+
formatversion: '2',
184+
}, options)).then(data => data.query.pages
185+
.filter((/** @type {any} */ page) =>
186+
page.revisions &&
187+
page.revisions.length > 0 &&
188+
page.revisions[0].slots &&
189+
page.revisions[0].slots.main &&
190+
page.revisions[0].slots.main.contentmodel === 'datamap'
191+
)
192+
.map((/** @type {any} */ page) => {
193+
const {slots, revid} = page.revisions[0];
194+
const /** @type {DataMap} */ datamap = JSON.parse(slots.main.content);
195+
datamap.custom = datamap.custom || new MetadataImpl();
196+
datamap.custom.interwiki = datamap.custom.interwiki || {};
197+
datamap.custom.interwiki[language] = new InterwikiDataImpl({
198+
mapName: page.title.split(':').slice(1).join(':'),
199+
});
200+
datamap.custom.interwiki[language].revision = revid;
201+
return datamap;
202+
})
203+
.filter((/** @type {DataMap} */ datamap) => !datamap.$fragment)
204+
);
205+
}
206+
207+
/**
208+
* Retrieves all maps from the wiki.
209+
* @param {string} language Wiki language
210+
* @returns {Promise<DataMap[]>} List of maps on the wiki
211+
*/
212+
export function getAllMaps(language = 'en') {
213+
return getMaps({
214+
generator: 'allpages',
215+
gapnamespace: '2900',
216+
gapfilterredir: 'nonredirects',
217+
gaplimit: 'max',
218+
}, language);
219+
}
220+
221+
/**
222+
* Retrieves a single map from the wiki.
223+
* @param {string} name Map name
224+
* @param {string} language Wiki language
225+
* @returns {Promise<DataMap>} Specified map from the wiki
226+
*/
227+
export function getMap(name, language = 'en') {
228+
return getMaps({
229+
titles: `Map:${name}`
230+
}, language).then(maps => maps[0]);
231+
}
232+
233+
/**
234+
* Returns the URLs of the given map files on the wiki.
235+
* @param {string[]} filenames Map file names
236+
* @param {string} language Wiki language
237+
* @returns {Promise<string[]>} URLs of the given map files on the wiki
238+
*/
239+
export function getFileUrls(filenames, language = 'en') {
240+
return httpGet(getApiUrl(language), {
241+
action: 'query',
242+
titles: filenames.map(name => `File:${name}`).join('|'),
243+
prop: 'imageinfo',
244+
iiprop: 'url',
245+
format: 'json',
246+
formatversion: '2'
247+
}).then(data => filenames.map(filename => data.query.pages
248+
.find((/** @type {any} */ page) => page.title === `File:${
249+
data.query.normalized
250+
?.find((/** @type {any} */ n) => n.from === filename)
251+
?.to ||
252+
filename
253+
}`)
254+
?.imageinfo[0].url)
255+
.filter(Boolean));
256+
}
257+
258+
/**
259+
* Downloads a file from a URL and returns it as an ArrayBuffer.
260+
* @param {string} url URL to download the file from
261+
* @returns {Promise<ArrayBuffer>} Downloaded file data
262+
*/
263+
export function downloadFile(url) {
264+
return new Promise((resolve, reject) => {
265+
const xhr = new XMLHttpRequest();
266+
xhr.open('GET', url, true);
267+
xhr.responseType = 'arraybuffer';
268+
xhr.onreadystatechange = readyStateChange(xhr, resolve, reject, true);
269+
xhr.setRequestHeader('User-Agent', USER_AGENT);
270+
xhr.send();
271+
});
272+
}

0 commit comments

Comments
 (0)