Compare commits

...

13 Commits

Author SHA1 Message Date
1374f90397 1.3.3 2026-02-07 17:19:22 +01:00
33733720c5 Added avatar credit exclusion to profile interpolation. 2026-02-07 17:19:20 +01:00
ec4b15ce33 1.3.2 2026-01-09 02:09:21 +01:00
3f6f3ed038 Removed slugify. 2026-01-09 02:09:19 +01:00
ee23dc0358 1.3.1 2026-01-09 01:51:47 +01:00
b2305966ed Using CommonJS for slugify. 2026-01-09 01:51:45 +01:00
0c9917fc27 1.3.0 2026-01-09 01:49:37 +01:00
fda6f5cb93 Added slugify. 2026-01-09 01:49:28 +01:00
c45852d693 Added twitter.com to socials hostname index. 2025-12-28 05:59:14 +01:00
4b90a5feec 1.2.10 2025-12-28 05:37:27 +01:00
b9ee4e1c90 Added socials config. 2025-12-28 05:37:21 +01:00
dc00c3d58a 1.2.9 2024-11-03 03:28:10 +01:00
721f5b91d8 Fixed entity ID inherited from profile. 2024-11-03 03:28:08 +01:00
3 changed files with 44 additions and 7 deletions

View File

@@ -80,6 +80,7 @@ function mergeMainProfile(profile, mainProfile) {
export async function interpolateProfiles(actorIdsOrNames, context, options = {}) { export async function interpolateProfiles(actorIdsOrNames, context, options = {}) {
const profiles = await fetchProfiles(actorIdsOrNames, context); const profiles = await fetchProfiles(actorIdsOrNames, context);
const columns = await context.knex.table('actors').columnInfo().then((table) => Object.keys(table)); const columns = await context.knex.table('actors').columnInfo().then((table) => Object.keys(table));
const preservedKeys = ['id', 'name', 'slug', 'entity_id', 'entry_id'];
const profilesByActorId = profiles.reduce((acc, profile) => ({ const profilesByActorId = profiles.reduce((acc, profile) => ({
...acc, ...acc,
@@ -163,20 +164,20 @@ export async function interpolateProfiles(actorIdsOrNames, context, options = {}
profile.avatar_media_id = actorProfiles profile.avatar_media_id = actorProfiles
.map((actorProfile) => actorProfile.avatar) .map((actorProfile) => actorProfile.avatar)
.filter((avatar) => avatar && (avatar.entropy === null || avatar.entropy > 5.5)) .filter((avatar) => avatar && (avatar.entropy === null || avatar.entropy > 5.5) && !options.avoidAvatarCredits?.includes(avatar.credit) && !options.excludeAvatarCredits?.includes(avatar.credit))
.sort((avatarA, avatarB) => avatarB.height - avatarA.height)[0]?.id || null; .sort((avatarA, avatarB) => avatarB.height - avatarA.height)[0]?.id || null;
if (!profile.avatar_media_id) { if (!profile.avatar_media_id) {
// try to settle for low quality avatar // try to settle for low quality avatar
profile.avatar_media_id = actorProfiles profile.avatar_media_id = actorProfiles
.map((actorProfile) => actorProfile.avatar) .map((actorProfile) => actorProfile.avatar)
.filter((avatar) => avatar) .filter((avatar) => !!avatar && !options?.excludeAvatarCredits?.includes(avatar.credit))
.sort((avatarA, avatarB) => avatarB.height - avatarA.height)[0]?.id || null; .sort((avatarA, avatarB) => avatarB.height - avatarA.height)[0]?.id || null;
} }
columns.forEach((key) => { columns.forEach((key) => {
// generic handling for remaining properties // generic handling for remaining properties
if (Object.hasOwn(valuesByProperty, key) && !Object.hasOwn(profile, key)) { if (Object.hasOwn(valuesByProperty, key) && !Object.hasOwn(profile, key) && !preservedKeys.includes(key)) {
profile[key] = getMostFrequent(valuesByProperty[key], context); profile[key] = getMostFrequent(valuesByProperty[key], context);
} }
}); });
@@ -187,7 +188,6 @@ export async function interpolateProfiles(actorIdsOrNames, context, options = {}
const transaction = await context.knex.transaction(); const transaction = await context.knex.transaction();
// clear existing interpolated data // clear existing interpolated data
const preservedKeys = ['id', 'name', 'slug', 'entity_id', 'entry_id'];
const emptyProfile = Object.fromEntries(columns.filter((key) => !preservedKeys.includes(key)).map((key) => [key, null])); const emptyProfile = Object.fromEntries(columns.filter((key) => !preservedKeys.includes(key)).map((key) => [key, null]));
await context.knex('actors') await context.knex('actors')
@@ -222,3 +222,40 @@ export async function interpolateProfiles(actorIdsOrNames, context, options = {}
await context.knex.schema.refreshMaterializedView('actors_meta'); await context.knex.schema.refreshMaterializedView('actors_meta');
} }
} }
export const socials = {
urls: {
cashapp: 'https://cash.app/${handle}', // eslint-disable-line no-template-curly-in-string
fansly: 'https://fansly.com/{handle}',
instagram: 'https://www.instagram.com/{handle}',
linktree: 'https://linktr.ee/{handle}',
loyalfans: 'https://www.loyalfans.com/{handle}',
manyvids: 'https://{handle}.manyvids.com',
onlyfans: 'https://onlyfans.com/{handle}',
pornhub: 'https://www.pornhub.com/model/{handle}',
reddit: 'https://www.reddit.com/u/{handle}',
twitter: 'https://x.com/{handle}',
},
prefix: {
default: '@',
cashapp: '$',
reddit: 'u/',
},
};
export const platformsByHostname = {
...Object.fromEntries(Object.entries(socials.urls).map(([platform, url]) => {
const { hostname, pathname } = new URL(url);
return [hostname, {
platform,
pathname: decodeURIComponent(pathname),
url,
}];
})),
'twitter.com': {
platform: 'twitter',
pathname: '/{handle}',
url: 'https://twitter.com/{handle}',
},
};

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "traxxx-utils", "name": "traxxx-utils",
"version": "1.2.8", "version": "1.3.3",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "traxxx-utils", "name": "traxxx-utils",
"version": "1.2.8", "version": "1.3.3",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.25.7", "@babel/cli": "^7.25.7",

View File

@@ -1,6 +1,6 @@
{ {
"name": "traxxx-common", "name": "traxxx-common",
"version": "1.2.8", "version": "1.3.3",
"description": "Common utilities for traxxx core and web.", "description": "Common utilities for traxxx core and web.",
"main": "src/app.js", "main": "src/app.js",
"scripts": { "scripts": {