HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //proc/thread-self/root/tmp/bewertemich_viral_patch.mjs
import { readFileSync, writeFileSync } from 'node:fs';

const updateFile = (file, updater) => {
  const before = readFileSync(file, 'utf8');
  const after = updater(before);
  if (after === before) throw new Error(`No changes applied to ${file}`);
  writeFileSync(file, after, 'utf8');
};

updateFile('web/scripts/generate-seo-pages.mjs', (source) => {
  const start = source.indexOf('const renderViralSharePanel = (page, canonical) => {');
  const end = source.indexOf('\nconst renderRelatedLinks = (page, relatedMap) => {', start);
  if (start < 0 || end < 0) throw new Error('renderViralSharePanel block not found');
  const block = `const renderViralSharePanel = (page, canonical) => {
  if (!page.shareText) return '';
  const shareTitle = page.shareTitle || page.title || 'bewertemich.de';
  const shareText = page.shareText;
  const shareUrl = page.shareUrl ? `${siteBase}${page.shareUrl}` : canonical;
  const pageSlug = page.slug;
  const withShareParams = (target) => {
    const url = new URL(shareUrl);
    url.searchParams.set('utm_source', 'viral_share');
    url.searchParams.set('utm_medium', target);
    url.searchParams.set('utm_campaign', pageSlug);
    return url.toString();
  };
  const shareUrls = {
    whatsapp: withShareParams('whatsapp'),
    telegram: withShareParams('telegram'),
    native: withShareParams('native'),
    copy: withShareParams('copy')
  };
  const encodedWhatsAppText = encodeURIComponent(`${shareText} ${shareUrls.whatsapp}`);
  const encodedTelegramUrl = encodeURIComponent(shareUrls.telegram);
  const encodedTelegramText = encodeURIComponent(shareText);
  return `
      <section class="card viral-share-panel" aria-labelledby="viral-share-${escapeAttr(pageSlug)}">
        <div>
          <span class="eyebrow">Teilen bringt neue Stimmen</span>
          <h2 id="viral-share-${escapeAttr(pageSlug)}">Challenge weitergeben</h2>
          <p>${escapeHtml(shareText)}</p>
        </div>
        <div class="share-actions">
          <a class="btn btn-primary" href="https://wa.me/?text=${encodedWhatsAppText}" target="_blank" rel="noreferrer" data-viral-share-target="whatsapp" data-share-page="${escapeAttr(pageSlug)}">WhatsApp teilen</a>
          <a class="btn btn-secondary dark" href="https://t.me/share/url?url=${encodedTelegramUrl}&text=${encodedTelegramText}" target="_blank" rel="noreferrer" data-viral-share-target="telegram" data-share-page="${escapeAttr(pageSlug)}">Telegram teilen</a>
          <button class="btn btn-secondary dark" type="button" data-viral-share-target="native" data-share-page="${escapeAttr(pageSlug)}">System-Share</button>
          <button class="btn btn-secondary dark" type="button" data-viral-share-target="copy" data-share-page="${escapeAttr(pageSlug)}">Link kopieren</button>
        </div>
        <p class="share-hint" data-copy-feedback="${escapeAttr(pageSlug)}">Teile die Challenge mit jemandem, der schnell 5 Fotos fair mitbewerten kann.</p>
      </section>
      <script>
(function () {
  const shareTitle = ${JSON.stringify(shareTitle)};
  const shareText = ${JSON.stringify(shareText)};
  const shareUrl = ${JSON.stringify(shareUrl)};
  const shareUrls = ${JSON.stringify(shareUrls)};
  const pageSlug = ${JSON.stringify(pageSlug)};
  const pathWithSearch = () => window.location.pathname + window.location.search;
  const post = (target) => {
    if (typeof window.fetch !== 'function') return;
    const targetShareUrl = shareUrls[target] || shareUrl;
    fetch('/api/public/events', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      credentials: 'same-origin',
      keepalive: true,
      body: JSON.stringify({
        event: 'seo_viral_share_click',
        source: 'seo_static',
        surface: pageSlug,
        entryPoint: target,
        path: pathWithSearch(),
        referrer: document.referrer || '',
        meta: { target, shareUrl: targetShareUrl, campaign: pageSlug, utmSource: 'viral_share' }
      })
    }).catch(function () {});
  };
  for (const el of document.querySelectorAll('[data-viral-share-target][data-share-page="' + pageSlug + '"]')) {
    el.addEventListener('click', function () {
      const target = el.getAttribute('data-viral-share-target') || 'unknown';
      const targetShareUrl = shareUrls[target] || shareUrl;
      post(target);
      if (target === 'native' && navigator.share) {
        navigator.share({ title: shareTitle, text: shareText, url: targetShareUrl }).catch(function () {});
      }
      if (target === 'copy') {
        navigator.clipboard && navigator.clipboard.writeText(targetShareUrl).then(function () {
          const feedback = document.querySelector('[data-copy-feedback="' + pageSlug + '"]');
          if (feedback) feedback.textContent = 'Link kopiert. Jetzt direkt an 2-3 Kontakte senden.';
        }).catch(function () {});
      }
    });
  }
})();
      </script>`;
};`;
  let next = source.slice(0, start) + block + source.slice(end);
  next = next.replaceAll('path: window.location.pathname,', 'path: window.location.pathname + window.location.search,');
  return next;
});

updateFile('api/src/jobs/seoGrowthDigest.js', (source) => {
  let next = source;
  next = next.replace(
    'const buildDigestHtml = ({ siteBase, windowLabel, funnelRows, totals, leaderboardRows, contextRows, reciprocityRows, decisionRows, shareTargetRows, pwaShortcutRows, actionFlags }) => {',
    'const buildDigestHtml = ({ siteBase, windowLabel, funnelRows, totals, leaderboardRows, contextRows, reciprocityRows, decisionRows, shareTargetRows, pwaShortcutRows, viralInboundRows, actionFlags }) => {'
  );
  const pwaSectionEnd = `
\t\t\t<div style="margin-top:18px;border:1px solid #e5e7eb;border-radius:16px;padding:16px;background:#fff;">
\t\t\t\t<div style="font-size:14px;color:#4b5563;font-weight:800;">Share-Ziele der Challenges</div>`;
  const viralSection = `
\t\t\t<div style="margin-top:18px;border:1px solid #e5e7eb;border-radius:16px;padding:16px;background:#fff;">
\t\t\t\t<div style="font-size:14px;color:#4b5563;font-weight:800;">Viral-Share-Folgebesuche</div>
\t\t\t\t<p style="margin:6px 0 10px;color:#64748b;font-size:13px;">Misst Besuche, die über Challenge-/Spiel-Shares mit <code>utm_source=viral_share</code> zurückkommen.</p>
\t\t\t\t<table style="width:100%;border-collapse:collapse;margin-top:10px;font-size:13px;">
\t\t\t\t\t<tbody>
\t\t\t\t\t\t${viralInboundRows.map((row) => `
\t\t\t\t\t\t\t<tr>
\t\t\t\t\t\t\t\t<td style="padding:8px;border-top:1px solid #f1f5f9;font-weight:700;">${escapeHtml(row.entry_name)}</td>
\t\t\t\t\t\t\t\t<td style="padding:8px;border-top:1px solid #f1f5f9;text-align:right;">${formatNumber(row.total)} Events</td>
\t\t\t\t\t\t\t\t<td style="padding:8px;border-top:1px solid #f1f5f9;text-align:right;color:#64748b;">${escapeHtml(row.path || row.referrer || '')}</td>
\t\t\t\t\t\t\t</tr>
\t\t\t\t\t\t`).join('') || '<tr><td style="padding:8px;color:#6b7280;">Noch keine Viral-Share-Folgebesuche.</td></tr>'}
\t\t\t\t\t</tbody>
\t\t\t\t</table>
\t\t\t</div>
`;
  if (!next.includes(pwaSectionEnd)) throw new Error('Digest insertion point not found');
  next = next.replace(pwaSectionEnd, viralSection + pwaSectionEnd);
  next = next.replace(
    'const [eventRows, landingRows, leaderboardRows, contextRows, reciprocityRows, decisionRawRows, shareTargetRawRows, pwaShortcutRows] = await Promise.all([',
    'const [eventRows, landingRows, leaderboardRows, contextRows, reciprocityRows, decisionRawRows, shareTargetRawRows, pwaShortcutRows, viralInboundRows] = await Promise.all(['
  );
  const pwaQuery = `\t\tquery(
\t\t\tdb,
\t\t\t\`SELECT COALESCE(NULLIF(entry_point, ''), 'direkt') AS entry_name, path, COUNT(*) AS total
\t\t\t FROM analytics_events
\t\t\t WHERE created_at >= (UTC_TIMESTAMP() - INTERVAL ? DAY)
\t\t\t   AND (path LIKE '%utm_source=pwa_shortcut%' OR referrer LIKE '%pwa_shortcut%')
\t\t\t GROUP BY entry_name, path
\t\t\t ORDER BY total DESC
\t\t\t LIMIT 10\`,
\t\t\t[DAYS]
\t\t)
\t]);`;
  const pwaAndViralQueries = `\t\tquery(
\t\t\tdb,
\t\t\t\`SELECT COALESCE(NULLIF(entry_point, ''), 'direkt') AS entry_name, path, COUNT(*) AS total
\t\t\t FROM analytics_events
\t\t\t WHERE created_at >= (UTC_TIMESTAMP() - INTERVAL ? DAY)
\t\t\t   AND (path LIKE '%utm_source=pwa_shortcut%' OR referrer LIKE '%pwa_shortcut%')
\t\t\t GROUP BY entry_name, path
\t\t\t ORDER BY total DESC
\t\t\t LIMIT 10\`,
\t\t\t[DAYS]
\t\t),
\t\tquery(
\t\t\tdb,
\t\t\t\`SELECT COALESCE(NULLIF(entry_point, ''), 'direkt') AS entry_name, path, referrer, COUNT(*) AS total
\t\t\t FROM analytics_events
\t\t\t WHERE created_at >= (UTC_TIMESTAMP() - INTERVAL ? DAY)
\t\t\t   AND (path LIKE '%utm_source=viral_share%' OR referrer LIKE '%utm_source=viral_share%')
\t\t\t GROUP BY entry_name, path, referrer
\t\t\t ORDER BY total DESC
\t\t\t LIMIT 10\`,
\t\t\t[DAYS]
\t\t)
\t]);`;
  if (!next.includes(pwaQuery)) throw new Error('PWA query block not found');
  next = next.replace(pwaQuery, pwaAndViralQueries);
  next = next.replace(
    '\t\tshareTargetRows,\n\t\tpwaShortcutRows,\n\t\tactionFlags: buildActionFlags(totals, normalizedLeaderboardRows, decisionRows)',
    '\t\tshareTargetRows,\n\t\tpwaShortcutRows,\n\t\tviralInboundRows,\n\t\tactionFlags: buildActionFlags(totals, normalizedLeaderboardRows, decisionRows)'
  );
  return next;
});

updateFile('scripts/growth-smoke-check.mjs', (source) => source
  .replace(
    `{ path: '/profilbild-challenge/', contains: ['Profilbild Challenge', '5 Fotos mitbewerten', '/mitbewerten/', 'seo_viral_share_click', 'data-viral-share-target="whatsapp"'] }`,
    `{ path: '/profilbild-challenge/', contains: ['Profilbild Challenge', '5 Fotos mitbewerten', '/mitbewerten/', 'seo_viral_share_click', 'data-viral-share-target="whatsapp"', 'utm_source=viral_share', 'utm_campaign=profilbild-challenge'] }`
  )
  .replace(
    `{ path: '/foto-bewerten-spiel/', contains: ['Foto bewerten Spiel', '/mitbewerten/', 'seo_viral_share_click', 'data-viral-share-target="telegram"'] }`,
    `{ path: '/foto-bewerten-spiel/', contains: ['Foto bewerten Spiel', '/mitbewerten/', 'seo_viral_share_click', 'data-viral-share-target="telegram"', 'utm_source=viral_share', 'utm_campaign=foto-bewerten-spiel'] }`
  )
);