diff --git a/web/app.js b/web/app.js index b006c93..cc3a96f 100644 --- a/web/app.js +++ b/web/app.js @@ -242,6 +242,7 @@ const REFRESH_SETTINGS_KEY = 'trackerRefreshSettings'; const SORT_SETTINGS_KEY = 'trackerSortSettings'; const SORT_SETTINGS_LEGACY_KEY = 'trackerSortMode'; const FACEBOOK_TRACKING_PARAMS = ['__cft__', '__tn__', '__eep__', 'mibextid', 'set', 'comment_id', 'hoisted_section_header_type']; +const FACEBOOK_PROFILE_SEGMENT_BLOCKLIST = new Set(['reel', 'reels', 'watch', 'video.php', 'videos', 'photo.php', 'photos', 'story.php', 'permalink.php', 'share', 'posts']); const VALID_SORT_MODES = new Set(['created', 'deadline', 'smart', 'lastCheck', 'lastChange']); const DEFAULT_SORT_SETTINGS = { mode: 'created', direction: 'desc' }; const BOOKMARKS_BASE_URL = 'https://www.facebook.com/search/top'; @@ -444,6 +445,99 @@ function formatUrlForDisplay(url) { } } +function deriveFacebookProfileUrl(rawValue) { + if (typeof rawValue !== 'string') { + return null; + } + + const trimmed = rawValue.trim(); + if (!trimmed) { + return null; + } + + let parsed; + try { + parsed = new URL(trimmed); + } catch (error) { + try { + parsed = new URL(trimmed, window.location.origin); + } catch (innerError) { + try { + parsed = new URL(trimmed, 'https://www.facebook.com'); + } catch (fallbackError) { + return null; + } + } + } + + const hostname = parsed.hostname.toLowerCase(); + if (!hostname.endsWith('facebook.com')) { + return null; + } + + const origin = `${parsed.protocol}//${parsed.hostname}`; + const normalizedPath = parsed.pathname.replace(/\/+$/, '') || '/'; + const segments = normalizedPath.split('/').filter(Boolean); + const firstSegment = segments[0] || ''; + const lowerFirst = firstSegment.toLowerCase(); + const idParam = parsed.searchParams.get('id'); + + if (lowerFirst === 'groups' && segments[1]) { + return `${origin}/groups/${segments[1]}`; + } + + if (lowerFirst === 'profile.php' && idParam) { + return `${origin}/profile.php?id=${encodeURIComponent(idParam)}`; + } + + if (idParam && (lowerFirst === 'story.php' || lowerFirst === 'permalink.php')) { + return `${origin}/profile.php?id=${encodeURIComponent(idParam)}`; + } + + if (lowerFirst === 'people' && segments[1] && segments[2]) { + return `${origin}/people/${segments[1]}/${segments[2]}`; + } + + if (firstSegment && !FACEBOOK_PROFILE_SEGMENT_BLOCKLIST.has(lowerFirst)) { + return `${origin}/${firstSegment}`; + } + + if (idParam) { + return `${origin}/profile.php?id=${encodeURIComponent(idParam)}`; + } + + return null; +} + +function getProfileLinkForPost(post) { + if (!post || typeof post !== 'object') { + return null; + } + + const candidates = []; + + if (typeof post.url === 'string') { + candidates.push(post.url); + } + + if (Array.isArray(post.alternate_urls)) { + for (const alt of post.alternate_urls) { + if (typeof alt === 'string') { + candidates.push(alt); + } + } + } + + for (const candidate of candidates) { + const profileUrl = deriveFacebookProfileUrl(candidate); + if (profileUrl) { + return profileUrl; + } + } + + return null; +} + function toTimestamp(value, fallback = null) { if (!value) { return fallback; @@ -3454,14 +3548,6 @@ function createPostCard(post, status, meta = {}) { const tabTotalCount = typeof meta.tabTotalCount === 'number' ? meta.tabTotalCount : posts.length; const searchActive = !!meta.searchActive; - const counterBadge = displayIndex !== null - ? ` -
- ` - : ''; - const profileRowsHtml = status.profileStatuses.map((profileStatus) => { const classes = ['profile-line', `profile-line--${profileStatus.status}`]; const isCurrentProfile = parseInt(profileStatus.profile_number, 10) === status.profileNumber; @@ -3555,6 +3641,10 @@ function createPostCard(post, status, meta = {}) { const creatorDisplay = creatorName || 'Unbekannt'; const titleText = (post.title && post.title.trim()) ? post.title.trim() : creatorDisplay; + const profileLink = getProfileLinkForPost(post); + const creatorContent = profileLink + ? `${escapeHtml(creatorDisplay)}` + : escapeHtml(creatorDisplay); const deadlineText = formatDeadline(post.deadline_at); const hasDeadline = Boolean(post.deadline_at); @@ -3598,7 +3688,6 @@ function createPostCard(post, status, meta = {}) { return `