2019-10-05 02:09:52 +02:00
|
|
|
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) {
|
2020-04-19 02:14:12 +02:00
|
|
|
if (!tagIds.length) return;
|
2019-10-05 02:09:52 +02:00
|
|
|
|
2020-04-19 02:14:12 +02:00
|
|
|
const ids = tagIds.slice(0, 40);
|
|
|
|
const remaining = tagIds.slice(41);
|
|
|
|
|
2021-02-09 23:37:54 +01:00
|
|
|
fetch(`/fetch/tags?ids[]=${ids.join('&ids[]=')}`)
|
2020-04-19 02:14:12 +02:00
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => data.tags.forEach(tag => persistTag(tag)))
|
|
|
|
.then(() => fetchAndPersistTags(remaining));
|
2019-10-05 02:09:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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) {
|
2021-10-09 21:58:07 +02:00
|
|
|
try { return JSON.parse(data); }
|
|
|
|
catch (_) { return data; }
|
2019-10-05 02:09:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2019-11-13 05:49:37 +01:00
|
|
|
window.booru.csrfToken = $('meta[name="csrf-token"]').content;
|
2019-10-05 02:09:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function BooruOnRails() {
|
|
|
|
this.apiEndpoint = '/api/v2/';
|
2019-11-30 19:14:01 +01:00
|
|
|
this.hiddenTag = '/images/tagblocked.svg';
|
2019-10-05 02:09:52 +02:00
|
|
|
this.tagsVersion = 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
window.booru = new BooruOnRails();
|
|
|
|
|
2020-04-19 02:14:12 +02:00
|
|
|
export { getTag, loadBooruData };
|