Files
ladill-meet/app/Services/Meet/FileSharingService.php
T
isaaccladandCursor 59b59cb70e
Deploy Ladill Meet / deploy (push) Successful in 54s
Bill Meet streaming hourly and storage per GB like Transfer.
Wallet debits at session end, on recording/file storage, and via daily renewals with grace period before asset deletion.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-01 16:33:45 +00:00

121 lines
3.9 KiB
PHP

<?php
namespace App\Services\Meet;
use App\Models\FileDownload;
use App\Models\Participant;
use App\Models\Room;
use App\Models\Session;
use App\Models\SessionFile;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class FileSharingService
{
public function upload(
Room $room,
?Session $session,
UploadedFile $file,
string $uploadedByRef,
string $uploadedByName,
?int $expiresInDays = null,
): SessionFile {
$expiresInDays ??= config('meet.files.default_expiry_days');
$room->loadMissing('organization');
$bytes = (int) $file->getSize();
$billing = app(MeetBillingService::class);
$disk = Storage::disk(config('meet.files.disk', 'local'));
$path = 'meet-files/'.$room->uuid.'/'.Str::uuid().'_'.$file->getClientOriginalName();
$disk->put($path, $file->get());
$sessionFile = SessionFile::create([
'owner_ref' => $room->owner_ref,
'room_id' => $room->id,
'session_id' => $session?->id,
'uploaded_by_ref' => $uploadedByRef,
'uploaded_by_name' => $uploadedByName,
'original_name' => $file->getClientOriginalName(),
'storage_path' => $path,
'mime_type' => $file->getMimeType(),
'file_size' => $bytes,
'expires_at' => $expiresInDays ? now()->addDays($expiresInDays) : null,
]);
try {
$billing->chargeFileStorageInitial($sessionFile);
} catch (\Throwable $e) {
$disk->delete($path);
$sessionFile->delete();
throw $e;
}
return $sessionFile;
}
public function linkFromDrive(Room $room, string $driveFileId, string $name, string $uploadedByRef, string $uploadedByName): SessionFile
{
return SessionFile::create([
'owner_ref' => $room->owner_ref,
'room_id' => $room->id,
'uploaded_by_ref' => $uploadedByRef,
'uploaded_by_name' => $uploadedByName,
'original_name' => $name,
'storage_path' => '',
'drive_file_id' => $driveFileId,
'file_size' => 0,
]);
}
public function download(SessionFile $file, ?Participant $participant = null): string
{
abort_if($file->isExpired(), 410, 'File has expired.');
abort_unless(app(MeetBillingService::class)->storageIsAccessible($file), 402, 'File storage billing is overdue. Top up your Ladill wallet to access this file.');
FileDownload::create([
'session_file_id' => $file->id,
'downloaded_by_ref' => $participant?->user_ref,
'downloaded_by_name' => $participant?->display_name,
'ip_address' => request()?->ip(),
'downloaded_at' => now(),
]);
if ($file->drive_file_id) {
return $this->driveDownloadUrl($file->drive_file_id);
}
return Storage::disk(config('meet.files.disk', 'local'))->path($file->storage_path);
}
public function delete(SessionFile $file): void
{
if ($file->storage_path) {
Storage::disk(config('meet.files.disk', 'local'))->delete($file->storage_path);
}
$file->delete();
}
protected function driveDownloadUrl(string $driveFileId): string
{
$base = rtrim((string) config('meet.files.drive_api_url'), '/');
$key = config('meet.files.drive_api_key');
if ($base && $key) {
try {
$response = Http::withToken($key)->get("{$base}/files/{$driveFileId}/download-url");
if ($response->successful()) {
return $response->json('url', $base.'/files/'.$driveFileId);
}
} catch (\Throwable) {
// fall through
}
}
return $base ? "{$base}/files/{$driveFileId}" : '#';
}
}