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
|
import { $ } from './utils/dom';
import parseSearch from './match_query';
import store from './utils/store';
/* Store a tag locally, marking the retrieval time */
function persistTag(tagData) {
tagData.fetchedAt = new Date().getTime() / 1000;
store.set(`bor_tags_${tagData.id}`, tagData);
}
function isStale(tag) {
const now = new Date().getTime() / 1000;
return tag.fetchedAt === null || tag.fetchedAt < (now - 604800);
}
function clearTags() {
Object.keys(localStorage).forEach(key => {
if (key.substring(0, 9) === 'bor_tags_') {
store.remove(key);
}
});
}
/* Returns a single tag, or a dummy tag object if we don't know about it yet */
function getTag(tagId) {
const stored = store.get(`bor_tags_${tagId}`);
if (stored) {
return stored;
}
return {
id: tagId,
name: '(unknown tag)',
images: 0,
spoiler_image_uri: null,
};
}
/* Fetches lots of tags in batches and stores them locally */
function fetchAndPersistTags(tagIds) {
const chunk = 40;
for (let i = 0; i < tagIds.length; i += chunk) {
const ids = tagIds.slice(i, i + chunk);
fetch(`${window.booru.apiEndpoint}tags/fetch_many.json?ids[]=${ids.join('&ids[]=')}`)
.then(response => response.json())
.then(data => data.tags.forEach(tag => persistTag(tag)));
}
}
/* Figure out which tags in the list we don't know about */
function fetchNewOrStaleTags(tagIds) {
const fetchIds = [];
tagIds.forEach(t => {
const stored = store.get(`bor_tags_${t}`);
if (!stored || isStale(stored)) {
fetchIds.push(t);
}
});
fetchAndPersistTags(fetchIds);
}
function verifyTagsVersion(latest) {
if (store.get('bor_tags_version') !== latest) {
clearTags();
store.set('bor_tags_version', latest);
}
}
function initializeFilters() {
const tags = window.booru.spoileredTagList
.concat(window.booru.hiddenTagList)
.filter((a, b, c) => c.indexOf(a) === b);
verifyTagsVersion(window.booru.tagsVersion);
fetchNewOrStaleTags(tags);
}
function unmarshal(data) {
try { return JSON.parse(data); }
catch (_) { return data; }
}
function loadBooruData() {
const booruData = document.querySelector('.js-datastore').dataset;
// Assign all elements to booru because lazy
for (const prop in booruData) {
window.booru[prop] = unmarshal(booruData[prop]);
}
window.booru.hiddenFilter = parseSearch(window.booru.hiddenFilter);
window.booru.spoileredFilter = parseSearch(window.booru.spoileredFilter);
// Fetch tag metadata and set up filtering
initializeFilters();
// CSRF
window.booru.csrfToken = $('meta[name="csrf-token"]').content;
window.booru.csrfParam = $('meta[name="csrf-param"]').content;
}
function BooruOnRails() {
this.apiEndpoint = '/api/v2/';
this.tagsVersion = 5;
}
window.booru = new BooruOnRails();
export { getTag, loadBooruData };
|