feat: xxbb

This commit is contained in:
hashbro
2026-08-14 04:52:50 +08:00
parent 5bf6852f66
commit 3c9cda5329
6 changed files with 139 additions and 32 deletions
+60 -27
View File
@@ -220,13 +220,19 @@ class IngestService
): void {
$needChannel = $this->channelIdEmpty($device->channel_id);
$needDomain = trim((string) ($device->source_domain ?? '')) === '';
if (! $needChannel && ! $needDomain) {
$model = $this->extractDeviceModel($payload);
$ios = $this->extractIosVersion($payload);
$needModel = $this->shouldReplaceModel($device->device_model, $model);
$needIos = $this->shouldReplaceIos($device->ios_version, $ios);
if (! $needChannel && ! $needDomain && ! $needModel && ! $needIos) {
$device->forceFill(['updated_at' => now()])->saveQuietly();
return;
}
$attr = $this->resolveChannelAttribution($request, $payload, $allowOldC);
$attr = ($needChannel || $needDomain)
? $this->resolveChannelAttribution($request, $payload, $allowOldC)
: ['channel_id' => null, 'source_domain' => null];
$touch = ['updated_at' => now()];
if ($needChannel && $attr['channel_id'] !== null && $attr['channel_id'] !== '') {
$touch['channel_id'] = $attr['channel_id'];
@@ -234,6 +240,12 @@ class IngestService
if ($needDomain && $attr['source_domain'] !== null && $attr['source_domain'] !== '') {
$touch['source_domain'] = $attr['source_domain'];
}
if ($needModel && $model !== null) {
$touch['device_model'] = $model;
}
if ($needIos && $ios !== null) {
$touch['ios_version'] = $ios;
}
$device->forceFill($touch)->saveQuietly();
}
@@ -709,23 +721,19 @@ class IngestService
if (! is_array($payload)) {
return null;
}
foreach (['deviceModel'] as $key) {
if (! empty($payload[$key]) && is_string($payload[$key])) {
return $payload[$key];
}
}
// avatar/put often sends short model as `m` (e.g. iPhone9,1)
if (! empty($payload['m']) && is_string($payload['m']) && preg_match('/^[A-Za-z]+\d/', $payload['m'])) {
return $payload['m'];
}
$info = $payload['deviceInfo'] ?? null;
if (is_array($info)) {
foreach (['productType', 'machine', 'model'] as $key) {
if (! empty($info[$key]) && is_string($info[$key])) {
if (! empty($info[$key]) && is_string($info[$key]) && $this->looksLikeHardwareModel($info[$key])) {
return $info[$key];
}
}
}
foreach (['machine', 'm', 'deviceModel'] as $key) {
if (! empty($payload[$key]) && is_string($payload[$key]) && $this->looksLikeHardwareModel($payload[$key])) {
return $payload[$key];
}
}
return null;
}
@@ -735,30 +743,55 @@ class IngestService
if (! is_array($payload)) {
return null;
}
// /api/user/get uses `v` for iOS version
if (! empty($payload['v']) && is_string($payload['v']) && preg_match('/^\d+(\.\d+){1,3}$/', $payload['v'])) {
return $payload['v'];
}
foreach (['pv', 'ios', 'ios_version', 'os', 'ver'] as $key) {
if (! empty($payload[$key]) && is_string($payload[$key])) {
return $payload[$key];
}
$info = $payload['deviceInfo'] ?? null;
if (is_array($info) && $this->looksLikeIosVersion($info['productVersion'] ?? null)) {
return trim((string) $info['productVersion']);
}
$sv = $payload['systemVersion'] ?? null;
if (is_array($sv) && ! empty($sv['ProductVersion']) && is_string($sv['ProductVersion'])) {
return $sv['ProductVersion'];
if (is_array($sv) && $this->looksLikeIosVersion($sv['ProductVersion'] ?? null)) {
return trim((string) $sv['ProductVersion']);
}
if (is_string($sv) && $sv !== '') {
return $sv;
if (is_string($sv) && $this->looksLikeIosVersion($sv)) {
return trim($sv);
}
$info = $payload['deviceInfo'] ?? null;
if (is_array($info) && ! empty($info['productVersion']) && is_string($info['productVersion'])) {
return $info['productVersion'];
foreach (['v', 'pv', 'ios', 'ios_version'] as $key) {
if ($this->looksLikeIosVersion($payload[$key] ?? null)) {
return trim((string) $payload[$key]);
}
}
return null;
}
private function looksLikeHardwareModel(string $value): bool
{
return (bool) preg_match('/^[A-Za-z]+\d/', $value);
}
private function looksLikeIosVersion(mixed $value): bool
{
return is_string($value) && $value !== '' && (bool) preg_match('/^\d+(\.\d+){1,3}$/', trim($value));
}
private function shouldReplaceModel(mixed $current, ?string $incoming): bool
{
if ($incoming === null || $incoming === '') {
return false;
}
$current = trim((string) $current);
return $current === '' || ! $this->looksLikeHardwareModel($current);
}
private function shouldReplaceIos(mixed $current, ?string $incoming): bool
{
if ($incoming === null || $incoming === '') {
return false;
}
return ! $this->looksLikeIosVersion($current);
}
/**
* Normalize `/api/user/status` shapes into address rows.
*