2019-06-14 21:24:48 -04:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
// Twitch Data
|
|
|
|
// Get data, from Twitch.
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
import Module from 'utilities/module';
|
|
|
|
import {get, debounce, generateUUID} from 'utilities/object';
|
|
|
|
|
|
|
|
const LANGUAGE_MATCHER = /^auto___lang_(\w+)$/;
|
|
|
|
|
2019-06-19 13:55:04 -04:00
|
|
|
const ALGOLIA_LANGUAGES = {
|
|
|
|
bg: 'bg-bg',
|
|
|
|
cs: 'cs-cz',
|
|
|
|
da: 'da-dk',
|
|
|
|
de: 'de-de',
|
|
|
|
el: 'el-gr',
|
|
|
|
en: 'en-us',
|
|
|
|
es: 'es-es',
|
|
|
|
'es-mx': 'es-mx',
|
|
|
|
fi: 'fi-fi',
|
|
|
|
fr: 'fr-fr',
|
|
|
|
hu: 'hu-hu',
|
|
|
|
it: 'it-it',
|
|
|
|
ja: 'ja-jp',
|
|
|
|
ko: 'ko-kr',
|
|
|
|
nl: 'nl-nl',
|
|
|
|
no: 'no-no',
|
|
|
|
pl: 'pl-pl',
|
|
|
|
'pt-br': 'pt-br',
|
|
|
|
pt: 'pt-pt',
|
|
|
|
ro: 'ro-ro',
|
|
|
|
ru: 'ru-ru',
|
|
|
|
sk: 'sk-sk',
|
|
|
|
sv: 'sv-se',
|
|
|
|
th: 'th-th',
|
|
|
|
tr: 'tr-tr',
|
|
|
|
vi: 'vi-vn',
|
|
|
|
'zh-cn': 'zh-cn',
|
|
|
|
'zh-tw': 'zh-tw'
|
|
|
|
};
|
|
|
|
|
|
|
|
function getAlgoliaLanguage(locale) {
|
|
|
|
if ( ! locale )
|
|
|
|
return ALGOLIA_LANGUAGES.en;
|
|
|
|
|
|
|
|
locale = locale.toLowerCase();
|
|
|
|
if ( ALGOLIA_LANGUAGES[locale] )
|
|
|
|
return ALGOLIA_LANGUAGES[locale];
|
|
|
|
|
|
|
|
locale = locale.split('-')[0];
|
|
|
|
return ALGOLIA_LANGUAGES[locale] || ALGOLIA_LANGUAGES.en;
|
|
|
|
}
|
|
|
|
|
2019-06-14 21:24:48 -04:00
|
|
|
export default class TwitchData extends Module {
|
|
|
|
constructor(...args) {
|
|
|
|
super(...args);
|
|
|
|
|
2019-08-09 14:24:26 -04:00
|
|
|
this.site = this.parent;
|
|
|
|
|
2019-06-14 21:24:48 -04:00
|
|
|
this.inject('site.apollo');
|
|
|
|
this.inject('site.web_munch');
|
|
|
|
|
2019-06-15 03:58:06 -04:00
|
|
|
this._waiting_stream_ids = new Map;
|
|
|
|
this._waiting_stream_logins = new Map;
|
|
|
|
|
2019-06-14 21:24:48 -04:00
|
|
|
this.tag_cache = new Map;
|
|
|
|
this._waiting_tags = new Map;
|
|
|
|
|
2019-06-15 03:58:06 -04:00
|
|
|
this._loadTags = debounce(this._loadTags, 50);
|
|
|
|
this._loadStreams = debounce(this._loadStreams, 50);
|
2019-06-14 21:24:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
queryApollo(query, variables, options) {
|
|
|
|
let thing;
|
|
|
|
if ( ! variables && ! options && query.query )
|
|
|
|
thing = query;
|
|
|
|
else {
|
|
|
|
thing = {
|
|
|
|
query,
|
|
|
|
variables
|
|
|
|
};
|
|
|
|
|
|
|
|
if ( options )
|
|
|
|
thing = Object.assign(thing, options);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.apollo.client.query(thing);
|
|
|
|
}
|
|
|
|
|
|
|
|
get languageCode() {
|
|
|
|
const session = this.site.getSession();
|
|
|
|
return session && session.languageCode || 'en'
|
|
|
|
}
|
|
|
|
|
|
|
|
get locale() {
|
|
|
|
const session = this.site.getSession();
|
|
|
|
return session && session.locale || 'en-US'
|
|
|
|
}
|
|
|
|
|
|
|
|
get searchClient() {
|
|
|
|
if ( this._search )
|
|
|
|
return this._search;
|
|
|
|
|
|
|
|
const apollo = this.apollo.client,
|
2019-06-15 03:58:06 -04:00
|
|
|
core = this.site.getCore(),
|
2019-06-14 21:24:48 -04:00
|
|
|
|
|
|
|
search_module = this.web_munch.getModule('algolia-search'),
|
|
|
|
SearchClient = search_module && search_module.a;
|
|
|
|
|
|
|
|
if ( ! SearchClient || ! apollo || ! core )
|
|
|
|
return null;
|
|
|
|
|
|
|
|
this._search = new SearchClient({
|
|
|
|
appId: core.config.algoliaApplicationID,
|
|
|
|
apiKey: core.config.algoliaAPIKey,
|
|
|
|
apolloClient: apollo,
|
|
|
|
logger: core.logger,
|
|
|
|
config: core.config,
|
|
|
|
stats: core.stats
|
|
|
|
});
|
|
|
|
|
|
|
|
return this._search;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
// Categories
|
|
|
|
// ========================================================================
|
|
|
|
|
|
|
|
async getMatchingCategories(query) {
|
|
|
|
const data = await this.queryApollo(
|
|
|
|
require('./data/search-category.gql'),
|
|
|
|
{ query }
|
|
|
|
);
|
|
|
|
|
|
|
|
return {
|
|
|
|
cursor: get('data.searchFor.games.cursor', data),
|
|
|
|
items: get('data.searchFor.games.items', data) || [],
|
|
|
|
finished: ! get('data.searchFor.games.pageInfo.hasNextPage', data)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-10-22 18:32:56 -04:00
|
|
|
async getCategory(id, name) {
|
|
|
|
const data = await this.queryApollo(
|
|
|
|
require('./data/category-fetch.gql'),
|
|
|
|
{ id, name }
|
|
|
|
);
|
|
|
|
|
|
|
|
return get('data.game', data);
|
|
|
|
}
|
|
|
|
|
2019-06-14 21:24:48 -04:00
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
// Users
|
|
|
|
// ========================================================================
|
|
|
|
|
|
|
|
async getMatchingUsers(query) {
|
|
|
|
const data = await this.queryApollo(
|
|
|
|
require('./data/search-user.gql'),
|
|
|
|
{ query }
|
|
|
|
);
|
|
|
|
|
|
|
|
return {
|
|
|
|
cursor: get('data.searchFor.users.cursor', data),
|
|
|
|
items: get('data.searchFor.users.items', data) || [],
|
|
|
|
finished: ! get('data.searchFor.users.pageInfo.hasNextPage', data)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
async getUser(id, login) {
|
|
|
|
const data = await this.queryApollo(
|
|
|
|
require('./data/user-fetch.gql'),
|
|
|
|
{ id, login }
|
|
|
|
);
|
|
|
|
|
|
|
|
return get('data.user', data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-18 20:56:33 -04:00
|
|
|
// ========================================================================
|
|
|
|
// Broadcast ID
|
|
|
|
// ========================================================================
|
|
|
|
|
|
|
|
async getBroadcastID(id, login) {
|
|
|
|
const data = await this.queryApollo({
|
|
|
|
query: require('./data/broadcast-id.gql'),
|
|
|
|
variables: {
|
|
|
|
id,
|
|
|
|
login
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return get('data.user.stream.archiveVideo.id', data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-15 03:58:06 -04:00
|
|
|
// ========================================================================
|
|
|
|
// Stream Up-Type (Uptime and Type, for Directory Purposes)
|
|
|
|
// ========================================================================
|
|
|
|
|
|
|
|
getStreamMeta(id, login) {
|
2019-06-19 20:57:14 -04:00
|
|
|
return new Promise((s, f) => {
|
2019-06-15 03:58:06 -04:00
|
|
|
if ( id ) {
|
|
|
|
if ( this._waiting_stream_ids.has(id) )
|
|
|
|
this._waiting_stream_ids.get(id).push([s, f]);
|
|
|
|
else
|
|
|
|
this._waiting_stream_ids.set(id, [[s, f]]);
|
|
|
|
} else if ( login ) {
|
|
|
|
if ( this._waiting_stream_logins.has(login) )
|
|
|
|
this._waiting_stream_logins.get(login).push([s, f]);
|
|
|
|
else
|
|
|
|
this._waiting_stream_logins.set(login, [[s, f]]);
|
|
|
|
} else
|
|
|
|
f('id and login cannot both be null');
|
|
|
|
|
|
|
|
if ( ! this._loading_streams )
|
|
|
|
this._loadStreams();
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async _loadStreams() {
|
|
|
|
if ( this._loading_streams )
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._loading_streams = true;
|
|
|
|
|
|
|
|
// Get the first 50... things.
|
|
|
|
const ids = [...this._waiting_stream_ids.keys()].slice(0, 50),
|
|
|
|
remaining = 50 - ids.length,
|
|
|
|
logins = remaining > 0 ? [...this._waiting_stream_logins.keys()].slice(0, remaining) : [];
|
|
|
|
|
|
|
|
let nodes;
|
|
|
|
|
|
|
|
try {
|
|
|
|
const data = await this.queryApollo({
|
|
|
|
query: require('./data/stream-fetch.gql'),
|
|
|
|
variables: {
|
|
|
|
ids: ids.length ? ids : null,
|
|
|
|
logins: logins.length ? logins : null
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
nodes = get('data.users', data);
|
|
|
|
|
|
|
|
} catch(err) {
|
|
|
|
for(const id of ids) {
|
|
|
|
const promises = this._waiting_stream_ids.get(id);
|
|
|
|
this._waiting_stream_ids.delete(id);
|
|
|
|
|
|
|
|
for(const pair of promises)
|
|
|
|
pair[1](err);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(const login of logins) {
|
|
|
|
const promises = this._waiting_stream_logins.get(login);
|
|
|
|
this._waiting_stream_logins.delete(login);
|
|
|
|
|
|
|
|
for(const pair of promises)
|
|
|
|
pair[1](err);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const id_set = new Set(ids),
|
|
|
|
login_set = new Set(logins);
|
|
|
|
|
|
|
|
if ( Array.isArray(nodes) )
|
|
|
|
for(const node of nodes) {
|
|
|
|
if ( ! node || ! node.id )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
id_set.delete(node.id);
|
|
|
|
login_set.delete(node.login);
|
|
|
|
|
|
|
|
let promises = this._waiting_stream_ids.get(node.id);
|
|
|
|
if ( promises ) {
|
|
|
|
this._waiting_stream_ids.delete(node.id);
|
|
|
|
for(const pair of promises)
|
|
|
|
pair[0](node.stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
promises = this._waiting_stream_logins.get(node.login);
|
|
|
|
if ( promises ) {
|
|
|
|
this._waiting_stream_logins.delete(node.login);
|
|
|
|
for(const pair of promises)
|
|
|
|
pair[0](node.stream);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(const id of id_set) {
|
|
|
|
const promises = this._waiting_stream_ids.get(id);
|
|
|
|
if ( promises ) {
|
|
|
|
this._waiting_stream_ids.delete(id);
|
|
|
|
for(const pair of promises)
|
|
|
|
pair[0](null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(const login of login_set) {
|
|
|
|
const promises = this._waiting_stream_logins.get(login);
|
|
|
|
if ( promises ) {
|
|
|
|
this._waiting_stream_logins.delete(login);
|
|
|
|
for(const pair of promises)
|
|
|
|
pair[0](null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this._loading_streams = false;
|
|
|
|
|
|
|
|
if ( this._waiting_stream_ids.size || this._waiting_stream_logins.size )
|
|
|
|
this._loadStreams();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-14 21:24:48 -04:00
|
|
|
// ========================================================================
|
|
|
|
// Tags
|
|
|
|
// ========================================================================
|
|
|
|
|
2019-06-15 03:58:06 -04:00
|
|
|
memorizeTag(node, dispatch = true) {
|
|
|
|
// We want properly formed tags.
|
|
|
|
if ( ! node || ! node.id || ! node.tagName || ! node.localizedName )
|
|
|
|
return;
|
|
|
|
|
|
|
|
let old = null;
|
|
|
|
if ( this.tag_cache.has(node.id) )
|
|
|
|
old = this.tag_cache.get(old);
|
|
|
|
|
|
|
|
const match = node.isLanguageTag && LANGUAGE_MATCHER.exec(node.tagName),
|
|
|
|
lang = match && match[1] || null;
|
|
|
|
|
|
|
|
const new_tag = {
|
|
|
|
id: node.id,
|
|
|
|
value: node.id,
|
|
|
|
is_language: node.isLanguageTag,
|
|
|
|
language: lang,
|
|
|
|
name: node.tagName,
|
|
|
|
label: node.localizedName
|
|
|
|
};
|
|
|
|
|
|
|
|
if ( node.localizedDescription )
|
|
|
|
new_tag.description = node.localizedDescription;
|
|
|
|
|
|
|
|
const tag = old ? Object.assign(old, new_tag) : new_tag;
|
|
|
|
this.tag_cache.set(tag.id, tag);
|
|
|
|
|
|
|
|
if ( dispatch && tag.description && this._waiting_tags.has(tag.id) ) {
|
|
|
|
const promises = this._waiting_tags.get(tag.id);
|
|
|
|
this._waiting_tags.delete(tag.id);
|
|
|
|
for(const pair of promises)
|
|
|
|
pair[0](tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
return tag;
|
|
|
|
}
|
|
|
|
|
2019-06-14 21:24:48 -04:00
|
|
|
async _loadTags() {
|
|
|
|
if ( this._loading_tags )
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._loading_tags = true;
|
2019-06-15 03:58:06 -04:00
|
|
|
|
|
|
|
// Get the first 50 tags.
|
|
|
|
const ids = [...this._waiting_tags.keys()].slice(0, 50);
|
|
|
|
|
|
|
|
let nodes
|
2019-06-14 21:24:48 -04:00
|
|
|
|
|
|
|
try {
|
|
|
|
const data = await this.queryApollo(
|
|
|
|
require('./data/tags-fetch.gql'),
|
|
|
|
{
|
2019-06-15 03:58:06 -04:00
|
|
|
ids
|
2019-06-14 21:24:48 -04:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2019-06-15 03:58:06 -04:00
|
|
|
nodes = get('data.contentTags', data);
|
2019-06-14 21:24:48 -04:00
|
|
|
|
|
|
|
} catch(err) {
|
2019-06-15 03:58:06 -04:00
|
|
|
for(const id of ids) {
|
|
|
|
const promises = this._waiting_tags.get(id);
|
|
|
|
this._waiting_tags.delete(id);
|
|
|
|
|
2019-06-14 21:24:48 -04:00
|
|
|
for(const pair of promises)
|
|
|
|
pair[1](err);
|
2019-06-15 03:58:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const id_set = new Set(ids);
|
|
|
|
|
|
|
|
if ( Array.isArray(nodes) )
|
|
|
|
for(const node of nodes) {
|
|
|
|
const tag = this.memorizeTag(node, false),
|
|
|
|
promises = this._waiting_tags.get(tag.id);
|
|
|
|
|
|
|
|
this._waiting_tags.delete(tag.id);
|
|
|
|
id_set.delete(tag.id);
|
|
|
|
|
|
|
|
if ( promises )
|
|
|
|
for(const pair of promises)
|
|
|
|
pair[0](tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(const id of id_set) {
|
|
|
|
const promises = this._waiting_tags.get(id);
|
|
|
|
this._waiting_tags.delete(id);
|
|
|
|
|
|
|
|
for(const pair of promises)
|
|
|
|
pair[0](null);
|
2019-06-14 21:24:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
this._loading_tags = false;
|
|
|
|
|
|
|
|
if ( this._waiting_tags.size )
|
|
|
|
this._loadTags();
|
|
|
|
}
|
|
|
|
|
|
|
|
getTag(id, want_description = false) {
|
2019-06-15 03:58:06 -04:00
|
|
|
// Make sure we weren't accidentally handed a tag object.
|
|
|
|
if ( id && id.id )
|
|
|
|
id = id.id;
|
|
|
|
|
2019-06-14 21:24:48 -04:00
|
|
|
if ( this.tag_cache.has(id) ) {
|
|
|
|
const out = this.tag_cache.get(id);
|
|
|
|
if ( out && (out.description || ! want_description) )
|
|
|
|
return Promise.resolve(out);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise((s, f) => {
|
|
|
|
if ( this._waiting_tags.has(id) )
|
|
|
|
this._waiting_tags.get(id).push([s, f]);
|
|
|
|
else {
|
|
|
|
this._waiting_tags.set(id, [[s, f]]);
|
|
|
|
if ( ! this._loading_tags )
|
|
|
|
this._loadTags();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
getTagImmediate(id, callback, want_description = false) {
|
2019-06-15 03:58:06 -04:00
|
|
|
// Make sure we weren't accidentally handed a tag object.
|
|
|
|
if ( id && id.id )
|
|
|
|
id = id.id;
|
|
|
|
|
2019-06-14 21:24:48 -04:00
|
|
|
let out = null;
|
|
|
|
if ( this.tag_cache.has(id) )
|
|
|
|
out = this.tag_cache.get(id);
|
|
|
|
|
2019-06-17 15:32:38 -04:00
|
|
|
if ( (want_description && (! out || ! out.description)) || (! out && callback) ) {
|
|
|
|
const promise = this.getTag(id, want_description);
|
|
|
|
if ( callback )
|
|
|
|
promise.then(tag => callback(id, tag)).catch(err => callback(id, null, err));
|
|
|
|
}
|
2019-06-14 21:24:48 -04:00
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
async getTopTags(limit = 50) {
|
|
|
|
const data = await this.queryApollo(
|
|
|
|
require('./data/tags-top.gql'),
|
|
|
|
{limit}
|
|
|
|
);
|
|
|
|
|
|
|
|
const nodes = get('data.topTags', data);
|
|
|
|
if ( ! Array.isArray(nodes) )
|
|
|
|
return [];
|
|
|
|
|
|
|
|
const out = [], seen = new Set;
|
|
|
|
for(const node of nodes) {
|
|
|
|
if ( ! node || seen.has(node.id) )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
seen.add(node.id);
|
2019-06-15 03:58:06 -04:00
|
|
|
out.push(this.memorizeTag(node));
|
2019-06-14 21:24:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
getLanguagesFromTags(tags, callback) {
|
|
|
|
const out = [],
|
|
|
|
fn = callback ? debounce(() => {
|
|
|
|
this.getLanguagesFromTags(tags, callback);
|
|
|
|
}, 16) : null
|
|
|
|
|
|
|
|
if ( Array.isArray(tags) )
|
|
|
|
for(const tag_id of tags) {
|
|
|
|
const tag = this.getTagImmediate(tag_id, fn);
|
|
|
|
if ( tag && tag.is_language ) {
|
|
|
|
const match = LANGUAGE_MATCHER.exec(tag.name);
|
|
|
|
if ( match )
|
|
|
|
out.push(match[1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2019-06-15 03:58:06 -04:00
|
|
|
async getMatchingTags(query, locale, category = null) {
|
2019-06-14 21:24:48 -04:00
|
|
|
if ( ! locale )
|
|
|
|
locale = this.locale;
|
|
|
|
|
2019-06-19 13:55:04 -04:00
|
|
|
locale = getAlgoliaLanguage(locale);
|
2019-06-15 03:58:06 -04:00
|
|
|
|
|
|
|
let nodes;
|
|
|
|
|
|
|
|
if ( category ) {
|
|
|
|
const data = await this.searchClient.queryForType(
|
|
|
|
'stream_tag', query, generateUUID(), {
|
|
|
|
hitsPerPage: 100,
|
|
|
|
faceFilters: [
|
|
|
|
`category_id:${category}`
|
|
|
|
],
|
|
|
|
restrictSearchableAttributes: [
|
|
|
|
`localizations.${locale}`,
|
|
|
|
'tag_name'
|
|
|
|
]
|
|
|
|
}
|
|
|
|
);
|
2019-06-14 21:24:48 -04:00
|
|
|
|
2019-06-15 03:58:06 -04:00
|
|
|
nodes = get('streamTags.hits', data);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
const data = await this.searchClient.queryForType(
|
|
|
|
'tag', query, generateUUID(), {
|
|
|
|
hitsPerPage: 100,
|
|
|
|
facetFilters: [
|
|
|
|
['tag_scope:SCOPE_ALL', 'tag_scope:SCOPE_CATEGORY']
|
|
|
|
],
|
|
|
|
restrictSearchableAttributes: [
|
|
|
|
`localizations.${locale}`,
|
|
|
|
'tag_name'
|
|
|
|
]
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
nodes = get('tags.hits', data);
|
|
|
|
}
|
2019-06-14 21:24:48 -04:00
|
|
|
|
|
|
|
if ( ! Array.isArray(nodes) )
|
|
|
|
return [];
|
|
|
|
|
|
|
|
const out = [], seen = new Set;
|
|
|
|
for(const node of nodes) {
|
2019-06-15 03:58:06 -04:00
|
|
|
const tag_id = node.tag_id || node.objectID;
|
|
|
|
if ( ! node || seen.has(tag_id) )
|
2019-06-14 21:24:48 -04:00
|
|
|
continue;
|
|
|
|
|
2019-06-15 03:58:06 -04:00
|
|
|
seen.add(tag_id);
|
|
|
|
if ( ! this.tag_cache.has(tag_id) ) {
|
|
|
|
const match = node.tag_name && LANGUAGE_MATCHER.exec(node.tag_name),
|
|
|
|
lang = match && match[1] || null;
|
|
|
|
|
2019-06-14 21:24:48 -04:00
|
|
|
const tag = {
|
2019-06-15 03:58:06 -04:00
|
|
|
id: tag_id,
|
|
|
|
value: tag_id,
|
|
|
|
is_language: lang != null,
|
|
|
|
language: lang,
|
2019-06-14 21:24:48 -04:00
|
|
|
label: node.localizations && (node.localizations[locale] || node.localizations['en-us']) || node.tag_name
|
|
|
|
};
|
|
|
|
|
2019-06-15 03:58:06 -04:00
|
|
|
if ( node.description_localizations ) {
|
|
|
|
const desc = node.description_localizations[locale] || node.description_localizations['en-us'];
|
|
|
|
if ( desc )
|
|
|
|
tag.description = desc;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.tag_cache.set(tag.id, tag);
|
2019-06-14 21:24:48 -04:00
|
|
|
out.push(tag);
|
|
|
|
|
|
|
|
} else {
|
2019-06-15 03:58:06 -04:00
|
|
|
const tag = this.tag_cache.get(tag_id);
|
|
|
|
if ( ! tag.description && node.description_localizations ) {
|
|
|
|
const desc = node.description_localizations[locale] || node.description_localizations['en-us'];
|
|
|
|
if ( desc ) {
|
|
|
|
tag.description = desc;
|
|
|
|
this.tag_cache.set(tag.id, tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out.push(tag);
|
2019-06-14 21:24:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
}
|