Zum Hauptinhalt springen

Core Models

Die Core-Domäne umfasst das zentrale SocialProfile-Model und seine direkten Dependents: Metriken, Bilder, Links und Scores.

SocialProfile

Zentrales Model für alle beobachteten Social-Media-Profile (YouTube und Instagram).

Tabelle: social_profiles

FeldTypNullableBeschreibung
idbigintPKPrimary Key
platformstringneinyoutube oder instagram
handlestringneinOriginal-Handle
handle_normalizedstringneinNormalisierter Handle (lowercase, ohne Sonderzeichen)
external_idstringjaPlattform-spezifische ID (Channel-ID, Instagram-User-ID)
canonical_urlstringjaKanonische Profil-URL
datajsonjaRohdaten der Plattform-API
titlestringjaAnzeigename / Channel-Titel
descriptiontextjaProfil-/Channel-Beschreibung
thumbnail_urlstringjaProfilbild-URL
custom_urlstringjaCustom URL (YouTube @handle)
published_atdatetimejaErstellungsdatum auf der Plattform
countrystring(2)jaLändercode (von Plattform)
languagestringjaSprache (von Plattform)
detected_countrystring(2)jaAI-erkanntes Land
detected_languagestringjaAI-erkannte Sprache
detected_atdatetimejaZeitpunkt der AI-Erkennung
ai_categorystringjaAI-erkannte Kategorie
ai_category_confidencefloatjaConfidence der Kategorie-Erkennung
ai_keywordsjsonjaAI-erkannte Keywords (Array)
ai_keywords_confidencefloatjaConfidence der Keyword-Erkennung
ai_descriptiontextjaAI-generierte Beschreibung (englisch)
ai_description_confidencefloatjaConfidence der Beschreibung
ai_description_detextjaAI-Beschreibung deutsch
ai_description_de_confidencefloatjaConfidence deutsch
ai_description_estextjaAI-Beschreibung spanisch
ai_description_es_confidencefloatjaConfidence spanisch
ai_description_ittextjaAI-Beschreibung italienisch
ai_description_it_confidencefloatjaConfidence italienisch
ai_description_frtextjaAI-Beschreibung franzoesisch
ai_description_fr_confidencefloatjaConfidence franzoesisch
ai_description_pttextjaAI-Beschreibung portugiesisch
ai_description_pt_confidencefloatjaConfidence portugiesisch
ai_description_quality_scoreintegerjaQualitaetsscore der AI-Beschreibung (1-10)
ai_translated_atdatetimejaZeitpunkt der letzten AI-Uebersetzung
ai_social_linksjsonjaAI-erkannte Social-Links
ai_manual_categorystringjaManuell gesetzte Kategorie (Override)
ai_manual_descriptiontextjaManuell gesetzte Beschreibung (Override)
ai_manual_keywordsjsonjaManuell gesetzte Keywords (Override)
ai_manual_edited_atdatetimejaLetzte manuelle AI-Feld-Aenderung
ai_manual_edited_bybigint (FK)jaAdmin der die Aenderung vornahm
is_privatebooleanjaPrivates Profil (Instagram)
profile_typestringjaProfil-Typ (Instagram: personal/business/creator)
is_verifiedbooleanjaVerifiziertes Profil
last_scraped_atdatetimejaLetzter erfolgreicher Scrape
last_daily_scrape_ondatejaDatum des letzten täglichen Scrapes
last_daily_queue_ondatejaDatum der letzten Queue-Einreihung
last_daily_queue_atdatetimejaZeitpunkt der letzten Queue-Einreihung
last_scrape_failed_atdatetimejaLetzter fehlgeschlagener Scrape
last_scrape_errortextjaLetzte Fehlermeldung
tracking_enabledbooleanneinMaster-Schalter: Tracking aktiv
tracking_disabled_atdatetimejaZeitpunkt der Deaktivierung
tracking_disabled_by_systembooleanjaVom System deaktiviert (nicht manuell)
tracking_disabled_reasonstringjaGrund der Deaktivierung
api_statusstringjaAPI-Status (ok, not_found, suspended, etc.)
api_status_reasonstringjaDetail zum API-Status
scrape_fail_streakintegerjaAnzahl aufeinanderfolgender Scrape-Fehler
next_retry_atdatetimejaNächster geplanter Retry-Zeitpunkt
retry_countintegerjaAnzahl bereits durchgeführter Retries
deactivated_atdatetimejaDeaktiviert durch Fail-Streak
archived_atdatetimejaPermanent archiviert
archive_reasonstringjaGrund der Archivierung
manual_penaltyintegerjaManueller Score-Abzug (0–100%)
blocked_atdatetimejaAdmin-Sperre
blocked_bybigint (FK)jaUser-ID des sperrenden Admins
block_reasonstringjaSperrgrund
sanitized_atdatetimejaAuto-Deaktivierung durch Sanitizer
sanitize_reasonstringjaGrund der Sanitizer-Deaktivierung
sanitize_checked_atdatetimejaAdmin-Override-Marker (Schutz vor Re-Sanitize)
related_channels_statusstringjaStatus der Related-Channels-Suche
related_channels_searched_atdatetimejaLetzter Related-Channels-Lauf
related_channels_errortextjaFehler bei Related-Channels
related_profiles_statusstringjaStatus der Related-Profiles-Berechnung
related_profiles_calculated_atdatetimejaLetzter Related-Profiles-Lauf
related_profiles_errortextjaFehler bei Related-Profiles
parsed_linksjsonjaGeparste Links aus Beschreibung
parsed_links_atdatetimejaZeitpunkt des letzten Link-Parsings
ai_detection_failed_atdatetimejaLetzter AI-Detection-Fehler
first_metric_datedatejaErstes Metrik-Datum (fuer Newcomer-Qualitaetsfilter)
pro_enabledbooleanjaPRO-Status fuer priorisiertes Scraping
followers_countbigintjaGecachte Follower-Anzahl (schnelles Filtern)
slugstringjaURL-Slug fuer Public Explorer
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
metrics()hasManySocialProfileDailyMetricsocial_profile_idAlle Tagesmetriken
latestMetric()hasOneSocialProfileDailyMetricsocial_profile_idNeueste Metrik (latestOfMany('date'))
images()hasManySocialProfileImagesocial_profile_idProfilbilder
youtubeVideos()hasManyYouTubeVideosocial_profile_idYouTube-Videos
youtubeVideoSync()hasOneYouTubeVideoSyncsocial_profile_idVideo-Sync-Status
watcherSources()hasManyWatcherSourcesocial_profile_idWatcher-Verknüpfungen
contactLinks()hasManySocialProfileLinksocial_profile_idAlle Kontakt-Links
approvedContactLinks()hasManySocialProfileLinksocial_profile_idNur genehmigte Links (whereNotNull('approved_at'))
relatedChannels()hasManyYouTubeRelatedChannelsocial_profile_idVerwandte YouTube-Channels
pendingYouTubeImports()hasManyPendingYouTubeChannelImportsource_social_profile_idPending Channel-Imports
relatedProfiles()hasManyInstagramRelatedProfilesocial_profile_idVerwandte Instagram-Profile
instagramKeywords()hasManyInstagramProfileKeywordsocial_profile_idInstagram Keywords
exploreMetrics()hasOneExploreProfileMetricsocial_profile_idExplore-Metriken
scores()hasManySocialProfileScoresocial_profile_idScore-Verlauf
latestScore()hasOneSocialProfileScoresocial_profile_idAktueller Score (latestOfMany('date'))
crossPlatformRelated()hasManyCrossPlatformRelatedProfilesource_profile_idCross-Platform-Verknüpfungen
aiManualOverrideLogs()hasManyAiManualOverrideLogsocial_profile_idAudit-Log fuer manuelle AI-Feld-Aenderungen
aiManualEditedBy()belongsToUserai_manual_edited_byAdmin der AI-Felder manuell bearbeitet hat
blockedByUser()belongsToUserblocked_bySperrender Admin

Scopes:

ScopeSQL-ÄquivalentVerwendung
notBlocked()WHERE blocked_at IS NULLNicht gesperrte Profile
notSanitized()WHERE sanitized_at IS NULLNicht sanitized Profile
notExcluded()WHERE blocked_at IS NULL AND sanitized_at IS NULL AND archived_at IS NULLFür öffentliche Anzeige

Casts:

'last_scraped_at' => 'datetime',
'last_daily_scrape_on' => 'date',
'last_daily_queue_on' => 'date',
'last_daily_queue_at' => 'datetime',
'last_scrape_failed_at' => 'datetime',
'tracking_enabled' => 'boolean',
'tracking_disabled_at' => 'datetime',
'tracking_disabled_by_system' => 'boolean',
'scrape_fail_streak' => 'integer',
'next_retry_at' => 'datetime',
'retry_count' => 'integer',
'deactivated_at' => 'datetime',
'archived_at' => 'datetime',
'manual_penalty' => 'integer',
'blocked_at' => 'datetime',
'sanitized_at' => 'datetime',
'sanitize_checked_at' => 'datetime',
'published_at' => 'datetime',
'detected_at' => 'datetime',
'data' => 'array',
'ai_keywords' => 'array',
'ai_social_links' => 'array',
'ai_manual_keywords' => 'array',
'ai_description_quality_score' => 'integer',
'ai_translated_at' => 'datetime',
'parsed_links' => 'array',
'parsed_links_at' => 'datetime',
'first_metric_date' => 'date',
'pro_enabled' => 'boolean',
'is_private' => 'boolean',
'is_verified' => 'boolean',
'related_channels_searched_at' => 'datetime',
'related_profiles_calculated_at' => 'datetime',
'cross_platform_related_calculated_at' => 'datetime',

Accessors: api_status_effective, effective_country, effective_language, effective_category, effective_description, effective_keywords

Die effective_* Accessors implementieren das Dual-Field-System: ai_manual_* hat Vorrang vor ai_*. Alle Consumer (Explore, Discover, PublicExplorer, Tags, etc.) nutzen ausschliesslich effective_*.

Konstanten: TRANSLATION_LANGUAGES = ['de', 'es', 'it', 'fr', 'pt'], PLACEHOLDER_IMAGE

Methoden: platformEnum(), isLanguageDetected(), isBlocked(), isSanitized(), isArchived(), isPendingRetry(), isDeactivated(), isNewcomer(), isProProfile(), isLowPriorityProfile(), hasManualAiOverride(), getAiDescriptionForLocale($locale), getAiDescriptionConfidenceForLocale($locale), availableTranslations(), hasRealImage(), getImageBlurhash(), getDisplayImageUrl($size), formattedFollowers()

Location: app/Models/SocialProfile.php


SocialProfileDailyMetric

Tägliche Metriken-Snapshots eines Profils. Pro Profil und Tag maximal ein Eintrag.

Tabelle: social_profile_daily_metrics

FeldTypNullableBeschreibung
idbigintPKPrimary Key
social_profile_idbigint (FK)neinZugehöriges Profil
datedateneinDatum des Snapshots
followers_countbigintjaFollower/Subscriber-Anzahl
view_countbigintjaGesamtaufrufe (YouTube)
video_countintegerjaAnzahl Videos (YouTube)
comment_countbigintjaKommentare (YouTube)
following_countintegerjaFollowing-Anzahl (Instagram)
post_countintegerjaAnzahl Posts (Instagram)
rawjsonjaRohdaten des Scrapes
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
profile()belongsToSocialProfilesocial_profile_idZugehöriges Profil

Casts: date → date, raw → array

Location: app/Models/SocialProfileDailyMetric.php


SocialProfileImage

Gespeicherte Profilbilder mit Deduplizierung über Content-Hash. Unterstützt optimierte Varianten (Thumbnail + Medium) im WebP/AVIF-Format sowie LQIP (Low Quality Image Placeholder) für progressive Bilddarstellung.

Tabelle: social_profile_images

FeldTypNullableBeschreibung
idbigintPKPrimary Key
social_profile_idbigint (FK)neinZugehöriges Profil
pathstringneinLokaler Speicherpfad (Original)
path_mediumstringjaMedium-Variante (256×256 WebP/AVIF)
path_thumbnailstringjaThumbnail-Variante (128×128 WebP/AVIF)
original_widthunsigned intjaOriginalbreite in px
original_heightunsigned intjaOriginalhöhe in px
file_sizeunsigned intjaDateigröße des Originals in Bytes
blurhashstring(200)jaLQIP Base64 Data URI (4×4 WebP)
hashstringneinContent-Hash (SHA-256) für Deduplizierung
source_urlstringjaOriginal-URL des Bildes
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
profile()belongsToSocialProfilesocial_profile_idZugehöriges Profil

Public Methods:

MethodParameterReturnBeschreibung
getUrlForSize()string $size = 'medium'?stringURL für Variante (thumb/medium/original), Fallback auf Original
hasVariants()boolPrüft ob Medium + Thumbnail Varianten vorhanden

Location: app/Models/SocialProfileImage.php


Kontakt-Links eines Profils (URLs, E-Mails, Social-Media-Links). Unterstützt 19 Plattformen mit URL-Templates. Links durchlaufen einen Approval-Workflow.

Tabelle: social_profile_links

FeldTypNullableBeschreibung
idbigintPKPrimary Key
social_profile_idbigint (FK)neinZugehöriges Profil
typestringneinTyp: url, email, social
platformstringjaPlattform (twitter, tiktok, etc.)
valuestringneinLink-Wert (URL/E-Mail/Handle)
display_urlstringjaAnzeige-URL
sourcestringjaHerkunft des Links
approved_atdatetimejaGenehmigungszeitpunkt
approved_bybigint (FK)jaGenehmigender Admin
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
socialProfile()belongsToSocialProfilesocial_profile_idZugehöriges Profil
approver()belongsToUserapproved_byGenehmigender Admin

Scopes:

ScopeBeschreibung
approved()Nur genehmigte Links
unapproved()Nur ungenehmigte Links
ofType($type)Nach Typ filtern (url, email, social)
ofPlatform($platform)Nach Plattform filtern

Casts: approved_at → datetime

Konstanten: PLATFORM_URL_TEMPLATES -- URL-Templates für 19 Plattformen (Twitter, TikTok, Facebook, LinkedIn, etc.)

Methoden: isApproved(), generateDisplayUrl() (static), detectPlatformFromUrl() (static), availablePlatforms() (static)

Location: app/Models/SocialProfileLink.php


SocialProfileScore

Berechneter Score (0–100) für ein Profil. Gewichtung: 40% Growth + 30% Momentum + 20% Consistency + 10% Engagement. Tier-normalisiert nach Follower-Größe.

Tabelle: social_profile_scores

FeldTypNullableBeschreibung
idbigintPKPrimary Key
social_profile_idbigint (FK)neinZugehöriges Profil
datedateneinBerechnungsdatum
scoreintegerneinScore (0–100)
data_source_datedatejaDatum der Datengrundlage
statusstringneinpending, preliminary, stable, no_data
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
profile()belongsToSocialProfilesocial_profile_idZugehöriges Profil

Casts: date → date, data_source_date → date, score → integer

Status-Logik:

StatusBedingungBeschreibung
pending< 7 DatenpunkteNoch nicht genug Daten
preliminary7–9 DatenpunkteVorläufiger Score
stable>= 10 DatenpunkteStabiler Score
no_dataKeine MetrikenKeine Daten vorhanden

Methoden: isPreliminary(), isPending(), isStable()

Location: app/Models/SocialProfileScore.php