diff --git a/assets/components/actors/actor.vue b/assets/components/actors/actor.vue index 231de1c0..3f983288 100644 --- a/assets/components/actors/actor.vue +++ b/assets/components/actors/actor.vue @@ -44,7 +44,7 @@ class="avatar-link" > @@ -153,7 +153,7 @@ {{ actor.bust || '??' }}{{ actor.cup || '?' }}-{{ actor.waist || '??' }}-{{ actor.hip || '??' }} @@ -271,6 +271,10 @@ async function fetchActor() { }); } +function sfw() { + return this.$store.state.ui.sfw; +} + async function route() { await this.fetchActor(); } @@ -303,6 +307,9 @@ export default { expanded: false, }; }, + computed: { + sfw, + }, watch: { $route: route, }, @@ -495,6 +502,7 @@ export default { .enhanced.icon { fill: $primary; padding: 0 .5rem; + transform: scaleX(-1); } .ethnicity { diff --git a/assets/components/actors/actors.vue b/assets/components/actors/actors.vue index 260eedb3..6e58a500 100644 --- a/assets/components/actors/actors.vue +++ b/assets/components/actors/actors.vue @@ -1,60 +1,60 @@ @@ -226,7 +226,7 @@ export default { } } -@media(max-width: $breakpoint) { +@media(max-width: $breakpoint0) { .tiles { grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); } diff --git a/assets/components/actors/photos.vue b/assets/components/actors/photos.vue index af54d184..c10226c0 100644 --- a/assets/components/actors/photos.vue +++ b/assets/components/actors/photos.vue @@ -11,7 +11,7 @@ class="avatar-link photo-link" > @@ -26,7 +26,7 @@ class="photo-link" > @@ -35,6 +35,10 @@ diff --git a/assets/components/header/header.vue b/assets/components/header/header.vue index 95d4e867..931767a0 100644 --- a/assets/components/header/header.vue +++ b/assets/components/header/header.vue @@ -1,128 +1,128 @@ diff --git a/assets/components/header/search.vue b/assets/components/header/search.vue index 8d14a1bd..cc01941c 100644 --- a/assets/components/header/search.vue +++ b/assets/components/header/search.vue @@ -1,57 +1,64 @@ diff --git a/assets/components/releases/releases.vue b/assets/components/releases/releases.vue index ba33be91..979dffb3 100644 --- a/assets/components/releases/releases.vue +++ b/assets/components/releases/releases.vue @@ -1,72 +1,72 @@ diff --git a/assets/components/search/search.vue b/assets/components/search/search.vue index 10f70ce9..4aae2bbb 100644 --- a/assets/components/search/search.vue +++ b/assets/components/search/search.vue @@ -1,47 +1,89 @@ @@ -54,4 +96,12 @@ export default { color: $shadow; font-weight: bold; } + +.tiles { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); + grid-gap: 0 .5rem; + flex-grow: 1; + margin: 0 0 1rem 0; +} diff --git a/assets/components/tile/actor.vue b/assets/components/tile/actor.vue index 4f568900..714da5df 100644 --- a/assets/components/tile/actor.vue +++ b/assets/components/tile/actor.vue @@ -8,29 +8,37 @@ class="link" > - {{ actor.name }} + + - {{ actor.name }} - + + - - {{ actor.name }} +
@@ -45,7 +53,9 @@ - + + + {{ actor.ageThen }} - - import Gender from '../actors/gender.vue'; +function sfw() { + return this.$store.state.ui.sfw; +} + export default { components: { Gender, @@ -95,6 +107,13 @@ export default { type: Object, default: null, }, + alias: { + type: Object, + default: null, + }, + }, + computed: { + sfw, }, }; @@ -137,18 +156,29 @@ export default { display: flex; align-items: center; justify-content: center; - padding: .5rem; font-weight: bold; + + .name { + padding: .5rem; + } + + .alias { + fill: var(--highlight); + } } .favicon { + font-size: 0; + padding: .5rem .25rem; + + &:last-child { + padding: .5rem; + } +} + +.favicon-icon { width: 1rem; height: 1rem; - margin: 0 .5rem 0 0; - - & + .name { - padding: 0 1rem 0 0; - } } .name { @@ -156,13 +186,13 @@ export default { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - text-align: center; } .avatar-container { display: flex; flex-grow: 1; position: relative; + overflow: hidden; } .avatar { @@ -191,6 +221,7 @@ export default { height: 1.75rem; display: flex; align-items: center; + justify-content: space-between; box-sizing: border-box; padding: .5rem; position: absolute; @@ -199,14 +230,13 @@ export default { font-weight: bold; } -.age, -.country, -.gender { - flex: 1; +.gender-age { + display: flex; + align-items: center; } .gender { - text-align: center; + margin: .25rem .25rem 0 0; } .country { @@ -216,7 +246,7 @@ export default { } .flag { - height: 1rem; + height: .75rem; margin: 0 0 0 .5rem; } diff --git a/assets/components/tile/release.vue b/assets/components/tile/release.vue index b61f8824..281ff4a3 100644 --- a/assets/components/tile/release.vue +++ b/assets/components/tile/release.vue @@ -1,175 +1,175 @@ diff --git a/assets/components/tile/tag.vue b/assets/components/tile/tag.vue index 885d4daf..82ce165b 100644 --- a/assets/components/tile/tag.vue +++ b/assets/components/tile/tag.vue @@ -1,68 +1,68 @@ diff --git a/assets/img/icons/boobjob.svg b/assets/img/icons/boobjob.svg new file mode 100644 index 00000000..e4db8562 --- /dev/null +++ b/assets/img/icons/boobjob.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/img/icons/forward.svg b/assets/img/icons/forward.svg new file mode 100644 index 00000000..69d294d5 --- /dev/null +++ b/assets/img/icons/forward.svg @@ -0,0 +1,5 @@ + + +forward + + diff --git a/assets/img/icons/redo2.svg b/assets/img/icons/redo2.svg new file mode 100644 index 00000000..becaa9b8 --- /dev/null +++ b/assets/img/icons/redo2.svg @@ -0,0 +1,5 @@ + + +redo2 + + diff --git a/assets/img/icons/reply-all.svg b/assets/img/icons/reply-all.svg new file mode 100644 index 00000000..f5e3581e --- /dev/null +++ b/assets/img/icons/reply-all.svg @@ -0,0 +1,6 @@ + + +reply-all + + + diff --git a/assets/img/icons/reply.svg b/assets/img/icons/reply.svg new file mode 100644 index 00000000..94db7312 --- /dev/null +++ b/assets/img/icons/reply.svg @@ -0,0 +1,5 @@ + + +reply + + diff --git a/assets/img/icons/undo2.svg b/assets/img/icons/undo2.svg new file mode 100644 index 00000000..a1135fe8 --- /dev/null +++ b/assets/img/icons/undo2.svg @@ -0,0 +1,5 @@ + + +undo2 + + diff --git a/assets/img/icons/users2.svg b/assets/img/icons/users2.svg new file mode 100644 index 00000000..80900d73 --- /dev/null +++ b/assets/img/icons/users2.svg @@ -0,0 +1,31 @@ + + +users2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/img/icons/users3.svg b/assets/img/icons/users3.svg new file mode 100644 index 00000000..ec2d3cec --- /dev/null +++ b/assets/img/icons/users3.svg @@ -0,0 +1,6 @@ + + +users3 + + + diff --git a/assets/js/actors/actions.js b/assets/js/actors/actions.js index 47a61e6e..2350052c 100644 --- a/assets/js/actors/actions.js +++ b/assets/js/actors/actions.js @@ -4,53 +4,9 @@ import { releaseActorsFragment, releaseTagsFragment, } from '../fragments'; -import { curateRelease } from '../curate'; +import { curateActor, curateRelease } from '../curate'; import getDateRange from '../get-date-range'; -function curateActor(actor) { - if (!actor) { - return null; - } - - const curatedActor = { - ...actor, - height: actor.heightMetric && { - metric: actor.heightMetric, - imperial: actor.heightImperial, - }, - weight: actor.weightMetric && { - metric: actor.weightMetric, - imperial: actor.weightImperial, - }, - origin: actor.birthCountry && { - city: actor.birthCity, - state: actor.birthState, - country: actor.birthCountry, - }, - residence: actor.residenceCountry && { - city: actor.residenceCity, - state: actor.residenceState, - country: actor.residenceCountry, - }, - scrapedAt: new Date(actor.createdAt), - updatedAt: new Date(actor.updatedAt), - }; - - if (actor.profiles && actor.profiles.length > 0) { - const photos = actor.profiles - .map(profile => profile.avatar) - .filter(avatar => avatar && (!curatedActor.avatar || avatar.hash !== curatedActor.avatar.hash)); - - curatedActor.photos = Object.values(photos.reduce((acc, photo) => ({ ...acc, [photo.hash]: photo }), {})); - } - - if (actor.releases) { - curatedActor.releases = actor.releases.map(release => curateRelease(release.release)); - } - - return curatedActor; -} - function initActorActions(store, _router) { async function fetchActorBySlug({ _commit }, { actorSlug, limit = 100, range = 'latest' }) { const { before, after, orderBy } = getDateRange(range); @@ -110,6 +66,12 @@ function initActorActions(store, _router) { hash comment copyright + sfw: sfwMedia { + id + thumbnail + path + comment + } } profiles: actorsProfiles { description @@ -121,6 +83,12 @@ function initActorActions(store, _router) { hash comment copyright + sfw: sfwMedia { + id + thumbnail + path + comment + } } } birthCity @@ -202,7 +170,7 @@ function initActorActions(store, _router) { exclude: store.state.ui.filter, }); - return curateActor(actor); + return curateActor(actor, null, curateRelease); } async function fetchActors({ _commit }, { @@ -223,13 +191,16 @@ function initActorActions(store, _router) { first:$limit, orderBy: NAME_ASC, filter: { + aliasFor: { + isNull: true + } name: { startsWith: $letter - }, + } gender: { ${genderFilter} - }, - }, + } + } ) { id name @@ -249,17 +220,13 @@ function initActorActions(store, _router) { lazy comment copyright + sfw: sfwMedia { + id + thumbnail + path + comment + } } - actorsProfiles { - actorsAvatarByProfileId { - media { - id - path - thumbnail - copyright - } - } - } birthCountry: countryByBirthCountryAlpha2 { alpha2 name diff --git a/assets/js/curate.js b/assets/js/curate.js index 22c2dc48..ebb7666b 100644 --- a/assets/js/curate.js +++ b/assets/js/curate.js @@ -1,17 +1,50 @@ import dayjs from 'dayjs'; -function curateActor(actor, release) { +function curateActor(actor, release, curateActorRelease) { + if (!actor) { + return null; + } + const curatedActor = { ...actor, - origin: actor.originCountry && { - country: actor.originCountry, + height: actor.heightMetric && { + metric: actor.heightMetric, + imperial: actor.heightImperial, }, + weight: actor.weightMetric && { + metric: actor.weightMetric, + imperial: actor.weightImperial, + }, + origin: actor.birthCountry && { + city: actor.birthCity, + state: actor.birthState, + country: actor.birthCountry, + }, + residence: actor.residenceCountry && { + city: actor.residenceCity, + state: actor.residenceState, + country: actor.residenceCountry, + }, + scrapedAt: new Date(actor.createdAt), + updatedAt: new Date(actor.updatedAt), }; + if (actor.profiles && actor.profiles.length > 0) { + const photos = actor.profiles + .map(profile => profile.avatar) + .filter(avatar => avatar && (!curatedActor.avatar || avatar.hash !== curatedActor.avatar.hash)); + + curatedActor.photos = Object.values(photos.reduce((acc, photo) => ({ ...acc, [photo.hash]: photo }), {})); + } + if (release && release.date && curatedActor.birthdate) { curatedActor.ageThen = dayjs(release.date).diff(actor.birthdate, 'year'); } + if (actor.releases) { + curatedActor.releases = actor.releases.map(actorRelease => curateActorRelease(actorRelease.release)); + } + return curatedActor; } diff --git a/assets/js/releases/actions.js b/assets/js/releases/actions.js index 11054a96..9ea26acd 100644 --- a/assets/js/releases/actions.js +++ b/assets/js/releases/actions.js @@ -28,75 +28,6 @@ function initReleasesActions(store, _router) { return releases.map(release => curateRelease(release)); } - async function searchReleases({ _commit }, { query, limit = 20 }) { - const res = await graphql(` - query SearchReleases( - $query: String! - $limit: Int = 20 - ) { - releases: searchReleases( - query: $query - first: $limit - ) { - id - title - slug - date - url - type - isNew - site { - id - slug - name - url - network { - id - slug - name - url - } - } - actors: releasesActors { - actor { - id - slug - name - } - } - tags: releasesTags(orderBy: TAG_BY_TAG_ID__PRIORITY_DESC) { - tag { - id - name - slug - } - } - poster: releasesPosterByReleaseId { - media { - id - thumbnail - lazy - } - } - covers: releasesCovers { - media { - id - thumbnail - lazy - } - } - } - } - `, { - query, - limit, - }); - - if (!res) return []; - - return res.releases.map(release => curateRelease(release)); - } - async function fetchReleaseById({ _commit }, releaseId) { // const release = await get(`/releases/${releaseId}`); @@ -114,7 +45,6 @@ function initReleasesActions(store, _router) { return { fetchReleases, fetchReleaseById, - searchReleases, }; } diff --git a/assets/js/ui/actions.js b/assets/js/ui/actions.js index a53d2b3a..5364b7eb 100644 --- a/assets/js/ui/actions.js +++ b/assets/js/ui/actions.js @@ -1,3 +1,6 @@ +import { graphql } from '../api'; +import { curateRelease, curateActor } from '../curate'; + function initUiActions(_store, _router) { function setFilter({ commit }, filter) { commit('setFilter', filter); @@ -23,7 +26,133 @@ function initUiActions(_store, _router) { localStorage.setItem('sfw', sfw); } + async function search({ _commit }, { query, limit = 20 }) { + const res = await graphql(` + query SearchReleases( + $query: String! + $limit: Int = 20 + ) { + releases: searchReleases( + query: $query + first: $limit + ) { + id + title + slug + date + url + type + isNew + site { + id + slug + name + url + network { + id + slug + name + url + } + } + actors: releasesActors { + actor { + id + slug + name + } + } + tags: releasesTags(orderBy: TAG_BY_TAG_ID__PRIORITY_DESC) { + tag { + id + name + slug + } + } + poster: releasesPosterByReleaseId { + media { + id + thumbnail + lazy + } + } + covers: releasesCovers { + media { + id + thumbnail + lazy + } + } + } + actors: searchActors( + search: $query, + first: $limit + ) { + id + name + slug + age + dateOfBirth + gender + aliasFor: actorByAliasFor { + id + name + slug + age + dateOfBirth + gender + network { + id + name + slug + } + avatar: avatarMedia { + id + path + thumbnail + lazy + comment + copyright + } + birthCountry: countryByBirthCountryAlpha2 { + alpha2 + name + alias + } + } + network { + id + name + slug + } + avatar: avatarMedia { + id + path + thumbnail + lazy + comment + copyright + } + birthCountry: countryByBirthCountryAlpha2 { + alpha2 + name + alias + } + } + } + `, { + query, + limit, + }); + + return { + releases: res.releases.map(release => curateRelease(release)), + actors: res.actors.map(actor => curateActor(actor)), + }; + } + return { + search, setFilter, setRange, setBatch, diff --git a/migrations/20190325001339_releases.js b/migrations/20190325001339_releases.js index 91b8ede5..13ce67e8 100644 --- a/migrations/20190325001339_releases.js +++ b/migrations/20190325001339_releases.js @@ -270,8 +270,6 @@ exports.up = knex => Promise.resolve() .references('id') .inTable('networks'); - table.unique(['slug', 'network_id']); - table.integer('alias_for', 12) .references('id') .inTable('actors'); @@ -794,6 +792,9 @@ exports.up = knex => Promise.resolve() ALTER TABLE releases_search ADD COLUMN document tsvector; + CREATE UNIQUE INDEX unique_actor_slugs_network ON actors (slug, network_id); + CREATE UNIQUE INDEX unique_actor_slugs ON actors (slug, (network_id IS NULL)); + CREATE TEXT SEARCH DICTIONARY traxxx_dict ( TEMPLATE = pg_catalog.simple, stopwords = traxxx @@ -825,6 +826,12 @@ exports.up = knex => Promise.resolve() url ILIKE ('%' || search || '%') $$ LANGUAGE SQL STABLE; + CREATE FUNCTION search_actors(search text, min_length numeric DEFAULT 2) RETURNS SETOF actors AS $$ + SELECT * FROM actors + WHERE length(search) >= min_length + AND name ILIKE ('%' || search || '%') + $$ LANGUAGE SQL STABLE; + CREATE FUNCTION releases_is_new(release releases) RETURNS boolean AS $$ SELECT NOT EXISTS(SELECT true FROM batches WHERE batches.id = release.created_batch_id + 1 LIMIT 1); $$ LANGUAGE sql STABLE; @@ -894,8 +901,8 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style DROP TABLE IF EXISTS countries CASCADE; DROP TABLE IF EXISTS networks CASCADE; - DROP FUNCTION IF EXISTS releases_by_tag_slugs; DROP FUNCTION IF EXISTS search_sites; + DROP FUNCTION IF EXISTS search_actors; DROP FUNCTION IF EXISTS get_random_sfw_media_id; DROP TEXT SEARCH CONFIGURATION IF EXISTS traxxx; diff --git a/public/img/logos/penthouse/misc/penthouse_dark.png b/public/img/logos/penthouse/misc/penthouse_dark.png new file mode 100644 index 00000000..a2b225ff Binary files /dev/null and b/public/img/logos/penthouse/misc/penthouse_dark.png differ diff --git a/public/img/logos/penthouse/penthouse.png b/public/img/logos/penthouse/penthouse.png new file mode 100644 index 00000000..b4427e0a Binary files /dev/null and b/public/img/logos/penthouse/penthouse.png differ diff --git a/seeds/04_media.js b/seeds/04_media.js index e38931e4..c5eb17cc 100644 --- a/seeds/04_media.js +++ b/seeds/04_media.js @@ -357,7 +357,6 @@ const sfw = Object.entries({ ['NI_fJ15rIfI', 'Szabo Viktor'], ['LymVMRIUwPQ', 'Happy Films'], ['mrNVnLEphdo', 'Greg Nunes'], - ['FKvoEKSV2LY', 'zhou yu'], ['CKLF34baCTQ', 'Willian Justen de Vasconcellos'], ['7uGCN9qshsY', 'Siora Photography'], ['xBTnaTgleQE', 'Glen Carrie'], diff --git a/src/actors.js b/src/actors.js index ca0953e3..d885f7a0 100644 --- a/src/actors.js +++ b/src/actors.js @@ -127,6 +127,10 @@ function curateProfileEntry(profile) { } async function curateProfile(profile) { + if (!profile) { + return null; + } + try { const curatedProfile = { id: profile.id, @@ -161,7 +165,7 @@ async function curateProfile(profile) { curatedProfile.dateOfDeath = Number.isNaN(Number(profile.dateOfDeath)) ? null : profile.dateOfDeath; - curatedProfile.cup = profile.cup || profile.bust?.match(/[a-zA-Z]+/)?.[0] || null; + curatedProfile.cup = profile.cup || (typeof profile.bust === 'string' && profile.bust?.match(/[a-zA-Z]+/)?.[0]) || null; curatedProfile.bust = Number(profile.bust) || profile.bust?.match(/\d+/)?.[0] || null; curatedProfile.waist = Number(profile.waist) || profile.waist?.match(/\d+/)?.[0] || null; curatedProfile.hip = Number(profile.hip) || profile.hip?.match(/\d+/)?.[0] || null; @@ -257,6 +261,7 @@ async function interpolateProfiles(actors) { profile.date_of_birth = getMostFrequentDate(valuesByProperty.date_of_birth); profile.date_of_death = getMostFrequentDate(valuesByProperty.date_of_death); + // TODO: fix city, state and country not matching profile.birth_city = getMostFrequent(valuesByProperty.birth_city); profile.birth_state = getMostFrequent(valuesByProperty.birth_state); profile.birth_country_alpha2 = getMostFrequent(valuesByProperty.birth_country_alpha2); @@ -300,51 +305,6 @@ async function interpolateProfiles(actors) { .catch(transaction.rollback); } -async function scrapeProfiles(actor, sources, networksBySlug, sitesBySlug) { - const profiles = Promise.map(sources, async (source) => { - try { - return await [].concat(source).reduce(async (outcome, scraperSlug) => outcome.catch(async () => { - const scraper = scrapers[scraperSlug]; - const siteOrNetwork = networksBySlug[scraperSlug] || sitesBySlug[scraperSlug]; - - if (!scraper?.fetchProfile) { - logger.warn(`No profile profile scraper available for ${scraperSlug}`); - throw new Error(`No profile profile scraper available for ${scraperSlug}`); - } - - if (!siteOrNetwork) { - logger.warn(`No site or network found for ${scraperSlug}`); - throw new Error(`No site or network found for ${scraperSlug}`); - } - - logger.verbose(`Searching profile for '${actor.name}' on '${scraperSlug}'`); - - const profile = await scraper.fetchProfile(actor.name, scraperSlug, siteOrNetwork, include); - - if (!profile || typeof profile === 'number') { // scraper returns HTTP code on request failure - logger.verbose(`Profile for '${actor.name}' not available on ${scraperSlug}, scraper returned ${profile}`); - throw Object.assign(new Error(`Profile for '${actor.name}' not available on ${scraperSlug}`), { code: 'PROFILE_NOT_AVAILABLE' }); - } - - return { - ...actor, - ...profile, - scraper: scraperSlug, - site: siteOrNetwork, - }; - }), Promise.reject(new Error())); - } catch (error) { - if (error.code !== 'PROFILE_NOT_AVAILABLE') { - logger.error(`Failed to fetch profile for '${actor.name}': ${error.message}`); - } - } - - return null; - }); - - return profiles.filter(Boolean); -} - async function upsertProfiles(profiles) { const curatedProfileEntries = profiles.map(profile => curateProfileEntry(profile)); @@ -403,6 +363,51 @@ async function upsertProfiles(profiles) { } } +async function scrapeProfiles(actor, sources, networksBySlug, sitesBySlug) { + const profiles = Promise.map(sources, async (source) => { + try { + return await [].concat(source).reduce(async (outcome, scraperSlug) => outcome.catch(async () => { + const scraper = scrapers[scraperSlug]; + const siteOrNetwork = networksBySlug[scraperSlug] || sitesBySlug[scraperSlug]; + + if (!scraper?.fetchProfile) { + logger.warn(`No profile profile scraper available for ${scraperSlug}`); + throw new Error(`No profile profile scraper available for ${scraperSlug}`); + } + + if (!siteOrNetwork) { + logger.warn(`No site or network found for ${scraperSlug}`); + throw new Error(`No site or network found for ${scraperSlug}`); + } + + logger.verbose(`Searching profile for '${actor.name}' on '${scraperSlug}'`); + + const profile = await scraper.fetchProfile(actor.name, scraperSlug, siteOrNetwork, include); + + if (!profile || typeof profile === 'number') { // scraper returns HTTP code on request failure + logger.verbose(`Profile for '${actor.name}' not available on ${scraperSlug}, scraper returned ${profile}`); + throw Object.assign(new Error(`Profile for '${actor.name}' not available on ${scraperSlug}`), { code: 'PROFILE_NOT_AVAILABLE' }); + } + + return { + ...actor, + ...profile, + scraper: scraperSlug, + site: siteOrNetwork, + }; + }), Promise.reject(new Error())); + } catch (error) { + if (error.code !== 'PROFILE_NOT_AVAILABLE') { + logger.error(`Failed to fetch profile for '${actor.name}': ${error.message}`); + } + } + + return null; + }); + + return profiles.filter(Boolean); +} + async function scrapeActors(actorNames) { const baseActors = toBaseActors(actorNames); @@ -438,7 +443,8 @@ async function scrapeActors(actorNames) { { concurrency: 10 }, ); - const profiles = await Promise.all(profilesPerActor.flat().map(profile => curateProfile(profile))); + const curatedProfiles = await Promise.all(profilesPerActor.flat().map(profile => curateProfile(profile))); + const profiles = curatedProfiles.filter(Boolean); if (argv.inspect) { console.log(profiles); @@ -495,31 +501,25 @@ async function associateActors(releases, batchId) { return null; } - const baseActorsBySlugAndNetworkId = baseActors.reduce((acc, baseActor) => ({ + const baseActorsBySlug = baseActors.reduce((acc, baseActor) => ({ ...acc, - [baseActor.slug]: { - ...acc[baseActor.slug], - [baseActor.network.id]: baseActor, - }, + [baseActor.slug]: baseActor, }), {}); - const uniqueBaseActors = Object.values(baseActorsBySlugAndNetworkId).map(baseActorsByNetworkId => Object.values(baseActorsByNetworkId)).flat(); + const uniqueBaseActors = Object.values(baseActorsBySlug); const actors = await getOrCreateActors(uniqueBaseActors, batchId); - const actorIdsBySlugAndNetworkId = actors.reduce((acc, actor) => ({ + const actorIdsBySlug = actors.reduce((acc, actor) => ({ ...acc, - [actor.network_id]: { - ...acc[actor.network_id], - [actor.slug]: actor.alias_for || actor.id, - }, + [actor.slug]: actor.alias_for || actor.id, }), {}); const releaseActorAssociations = Object.entries(baseActorsByReleaseId) .map(([releaseId, releaseActors]) => releaseActors .map(releaseActor => ({ release_id: releaseId, - actor_id: actorIdsBySlugAndNetworkId[releaseActor.network.id]?.[releaseActor.slug] || actorIdsBySlugAndNetworkId.null[releaseActor.slug], + actor_id: actorIdsBySlug[releaseActor.slug], }))) .flat(); diff --git a/src/scrapers/bang.js b/src/scrapers/bang.js index 7dc51fce..df8246da 100644 --- a/src/scrapers/bang.js +++ b/src/scrapers/bang.js @@ -252,9 +252,13 @@ async function fetchProfile(actorName) { }, { encodeJSON: true }); if (res.ok) { - const actor = res.body.hits.hits.find(hit => hit._source.name === actorName); + const actor = res.body.hits.hits.find(hit => hit._source.name.toLowerCase() === actorName.toLowerCase()); - return scrapeProfile(actor._source); + if (actor) { + return scrapeProfile(actor._source); + } + + return null; } return res.status;