traxxx/src/tags.js

109 lines
3.4 KiB
JavaScript
Raw Normal View History

'use strict';
const logger = require('./logger')(__filename);
const knex = require('./knex');
const whereOr = require('./utils/where-or');
async function curateTag(tag) {
const [aliases, media] = await Promise.all([
knex('tags').where({ alias_for: tag.id }),
knex('media')
.where('domain', 'tags')
.andWhere('target_id', tag.id)
.orderBy('index'),
]);
return {
id: tag.id,
name: tag.name,
slug: tag.slug,
description: tag.description,
poster: media.find(photo => photo.role === 'poster'),
photos: media.filter(photo => photo.role === 'photo'),
group: {
id: tag.group_id,
name: tag.group_name,
description: tag.group_description,
slug: tag.group_slug,
},
aliases: aliases.map(({ name }) => name),
};
}
function curateTags(tags) {
return Promise.all(tags.map(async tag => curateTag(tag)));
}
async function matchTags(rawTags) {
const tags = rawTags
.concat(rawTags.map(tag => tag.toLowerCase()))
.concat(rawTags.map(tag => tag.toUpperCase()));
const tagEntries = await knex('tags')
.pluck('aliases.id')
.whereIn('tags.name', tags)
.leftJoin('tags as aliases', function join() {
this
.on('tags.alias_for', 'aliases.id')
.orOn('tags.id', 'aliases.id');
})
.where(function where() {
this
.whereNull('tags.alias_for')
.orWhereNull('aliases.alias_for');
})
.groupBy('aliases.id');
return tagEntries;
}
async function associateTags(release, releaseId) {
2020-01-13 22:45:09 +00:00
const siteTags = release.site.tags.filter(tag => tag.inherit === true).map(tag => tag.id);
const rawReleaseTags = release.tags || [];
const releaseTags = rawReleaseTags.some(tag => typeof tag === 'string')
? await matchTags(release.tags) // scraper returned raw tags
: rawReleaseTags; // tags already matched by (outdated) scraper
const tags = Array.from(new Set(releaseTags.concat(siteTags)));
2020-01-13 22:45:09 +00:00
if (tags.length === 0) {
2020-01-12 04:30:46 +00:00
logger.info(`No tags available for (${release.site.name}, ${releaseId}) "${release.title}"`);
return;
}
const associationEntries = await knex('releases_tags')
.where('release_id', releaseId)
.whereIn('tag_id', tags);
const existingAssociations = new Set(associationEntries.map(association => association.tag_id));
const newAssociations = tags.filter(tagId => !existingAssociations.has(tagId));
await knex('releases_tags').insert(newAssociations.map(tagId => ({
tag_id: tagId,
release_id: releaseId,
})));
}
async function fetchTags(queryObject, groupsQueryObject, limit = 100) {
const tags = await knex('tags')
.where(builder => whereOr(queryObject, 'tags', builder))
.orWhere(builder => whereOr(groupsQueryObject, 'tags_groups', builder))
.andWhere({ 'tags.alias_for': null })
.select(
'tags.*',
'tags_groups.id as group_id', 'tags_groups.name as group_name', 'tags_groups.slug as group_slug', 'tags_groups.description as groups_description',
)
.leftJoin('tags_groups', 'tags.group_id', 'tags_groups.id')
.orderBy('name')
.limit(limit);
return curateTags(tags);
}
module.exports = {
associateTags,
fetchTags,
matchTags,
};