Implement creator studio and upload updates

This commit is contained in:
2026-04-04 10:12:02 +02:00
parent 1da7d3bf88
commit 0b216b7ecd
15107 changed files with 31206 additions and 626514 deletions

View File

@@ -0,0 +1,199 @@
<?php
namespace App\Models;
use App\Enums\ModerationEscalationStatus;
use App\Enums\ModerationContentType;
use App\Enums\ModerationSeverity;
use App\Enums\ModerationStatus;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* @property ModerationContentType $content_type
* @property int $content_id
* @property int|null $artwork_id
* @property int|null $user_id
* @property ModerationStatus $status
* @property ModerationSeverity $severity
* @property int $score
* @property string $content_hash
* @property string $scanner_version
* @property array|null $reasons_json
* @property array|null $matched_links_json
* @property array|null $matched_domains_json
* @property array|null $matched_keywords_json
* @property string|null $content_snapshot
* @property int|null $reviewed_by
* @property \Illuminate\Support\Carbon|null $reviewed_at
* @property string|null $action_taken
* @property string|null $admin_notes
* @property string|null $content_hash_normalized
* @property string|null $group_key
* @property array|null $rule_hits_json
* @property array|null $domain_ids_json
* @property int|null $user_risk_score
* @property bool $is_auto_hidden
* @property string|null $auto_action_taken
* @property \Illuminate\Support\Carbon|null $auto_hidden_at
* @property int|null $resolved_by
* @property \Illuminate\Support\Carbon|null $resolved_at
* @property int|null $restored_by
* @property \Illuminate\Support\Carbon|null $restored_at
* @property string|null $content_target_type
* @property int|null $content_target_id
* @property string|null $campaign_key
* @property int|null $cluster_score
* @property string|null $cluster_reason
* @property int|null $priority_score
* @property string|null $ai_provider
* @property string|null $ai_label
* @property int|null $ai_confidence
* @property string|null $ai_explanation
* @property bool $is_false_positive
* @property int $false_positive_count
* @property string|null $policy_name
* @property string|null $review_bucket
* @property ModerationEscalationStatus $escalation_status
* @property array|null $score_breakdown_json
*/
class ContentModerationFinding extends Model
{
protected $table = 'content_moderation_findings';
protected $fillable = [
'content_type',
'content_id',
'artwork_id',
'user_id',
'status',
'severity',
'score',
'content_hash',
'scanner_version',
'reasons_json',
'matched_links_json',
'matched_domains_json',
'matched_keywords_json',
'content_snapshot',
'reviewed_by',
'reviewed_at',
'action_taken',
'admin_notes',
'content_hash_normalized',
'group_key',
'rule_hits_json',
'domain_ids_json',
'user_risk_score',
'is_auto_hidden',
'auto_action_taken',
'auto_hidden_at',
'resolved_by',
'resolved_at',
'restored_by',
'restored_at',
'content_target_type',
'content_target_id',
'campaign_key',
'cluster_score',
'cluster_reason',
'priority_score',
'ai_provider',
'ai_label',
'ai_confidence',
'ai_explanation',
'is_false_positive',
'false_positive_count',
'policy_name',
'review_bucket',
'escalation_status',
'score_breakdown_json',
];
protected $casts = [
'content_type' => ModerationContentType::class,
'status' => ModerationStatus::class,
'severity' => ModerationSeverity::class,
'score' => 'integer',
'reasons_json' => 'array',
'matched_links_json' => 'array',
'matched_domains_json' => 'array',
'matched_keywords_json' => 'array',
'rule_hits_json' => 'array',
'domain_ids_json' => 'array',
'user_risk_score' => 'integer',
'is_auto_hidden' => 'boolean',
'reviewed_at' => 'datetime',
'auto_hidden_at' => 'datetime',
'resolved_at' => 'datetime',
'restored_at' => 'datetime',
'content_target_id' => 'integer',
'cluster_score' => 'integer',
'priority_score' => 'integer',
'ai_confidence' => 'integer',
'is_false_positive' => 'boolean',
'false_positive_count' => 'integer',
'escalation_status' => ModerationEscalationStatus::class,
'score_breakdown_json' => 'array',
];
public function artwork(): BelongsTo
{
return $this->belongsTo(Artwork::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function reviewer(): BelongsTo
{
return $this->belongsTo(User::class, 'reviewed_by');
}
public function resolver(): BelongsTo
{
return $this->belongsTo(User::class, 'resolved_by');
}
public function restorer(): BelongsTo
{
return $this->belongsTo(User::class, 'restored_by');
}
public function actionLogs(): HasMany
{
return $this->hasMany(ContentModerationActionLog::class, 'finding_id')->orderByDesc('created_at');
}
public function aiSuggestions(): HasMany
{
return $this->hasMany(ContentModerationAiSuggestion::class, 'finding_id')->orderByDesc('created_at');
}
public function feedback(): HasMany
{
return $this->hasMany(ContentModerationFeedback::class, 'finding_id')->orderByDesc('created_at');
}
public function isPending(): bool
{
return $this->status === ModerationStatus::Pending;
}
public function isReviewed(): bool
{
return in_array($this->status, [
ModerationStatus::ReviewedSafe,
ModerationStatus::ConfirmedSpam,
ModerationStatus::Resolved,
], true);
}
public function hasMatchedDomains(): bool
{
return ! empty($this->matched_domains_json);
}
}