diff --git a/app/Http/Controllers/FileServerController.php b/app/Http/Controllers/FileServerController.php index 5a03c77..2054018 100644 --- a/app/Http/Controllers/FileServerController.php +++ b/app/Http/Controllers/FileServerController.php @@ -77,9 +77,11 @@ class FileServerController extends Controller { abort(404); } - if( !EntryHelpers::fileAlreadyDownloaded($file) ) { - EntryHelpers::markFileAsDownloaded($file); - $file->increaseDownloadCount(); + if($request->input('count_download', true)) { + if (!EntryHelpers::fileAlreadyDownloaded($file)) { + EntryHelpers::markFileAsDownloaded($file); + $file->increaseDownloadCount(); + } } return redirect( $this->fs->getDownloadFileUrl( $file) ); diff --git a/app/Http/Controllers/ToolsController.php b/app/Http/Controllers/ToolsController.php index 9e54d91..36fa137 100644 --- a/app/Http/Controllers/ToolsController.php +++ b/app/Http/Controllers/ToolsController.php @@ -12,13 +12,12 @@ class ToolsController extends Controller public function patcher() { - return view('tools.patcher'); } public function directPatch( Request $request, int $entryId, EntryFile $file ) { - if( $file->entry_id != $entryId ) { + if( $file->entry_id != $entryId || $file->state === 'private' ) { abort(404); } @@ -38,22 +37,28 @@ class ToolsController extends Controller public function play( Request $request, int $entryId, EntryFile $file ) { - if( $file->entry_id != $entryId ) { + if( $file->entry_id != $entryId || $file->state === 'private' ) { abort(404); } $service = app(FileServersService::class); - $patches = [ - 'file' => $service->getDownloadFileUrl( $file ), - 'name' => $file->entry->title, - 'outputName' => $file->filename - ]; $emuConfig = [ 'core' => $file->playOnlineSetting?->core, 'threads' => $file->playOnlineSetting?->threads, ]; + if( $file->entry->type === 'homebrew' ){ + $filePath = $service->getDownloadFileUrl( $file ); + + return view('tools.play-homebrew', compact('filePath', 'emuConfig')); + } + $patches = [ + 'file' => $service->getDownloadFileUrl( $file ), + 'name' => $file->entry->title, + 'outputName' => $file->filename + ]; + return view('tools.play', compact('patches', 'emuConfig')); } } diff --git a/app/Models/EntryFile.php b/app/Models/EntryFile.php index a213637..69df869 100644 --- a/app/Models/EntryFile.php +++ b/app/Models/EntryFile.php @@ -62,6 +62,23 @@ class EntryFile extends Model return $this->hasOne(PlayOnlineSetting::class,'file_id'); } + public function prettyFileSize(): string + { + $bytes = $this->filesize; + + if ($bytes >= 1073741824) { + $bytes = number_format($bytes / 1073741824, 2) . ' GB'; + } elseif ($bytes >= 1048576) { + $bytes = number_format($bytes / 1048576, 2) . ' MB'; + } elseif ($bytes >= 1024) { + $bytes = number_format($bytes / 1024, 2) . ' KB'; + } else { + $bytes = ($bytes == 0) ? '0 bytes' : $bytes . ' bytes'; + } + + return $bytes; + } + public function increaseDownloadCount(): void { $this->download_count++; diff --git a/app/Services/FileServersService.php b/app/Services/FileServersService.php index 742db53..d798e5f 100644 --- a/app/Services/FileServersService.php +++ b/app/Services/FileServersService.php @@ -8,6 +8,8 @@ use Illuminate\Http\Client\ConnectionException; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Str; class FileServersService { @@ -69,15 +71,38 @@ class FileServersService { * @param EntryFile $file * @return string */ - public function getDownloadFileUrl( EntryFile $file ): string + public function getDownloadFileUrl( EntryFile $file, bool $countDownload = true ): string { $serverKey = $this->getEntryFileServerKey( $file ); $url = $this->servers[$serverKey]['download'] ?? "#"; if( $url === "#" ) return $url; - return $url . "&" . http_build_query( [ 'filename' => $file->filename, 'filepath' => $file->filepath ] ); + $args = [ 'filename' => $file->filename, 'filepath' => $file->filepath ]; + if( !$countDownload ) + $args['count_download'] = false; + return $url . "&" . http_build_query( $args ); + + } + + + public function getArchiveExplorerUrl( EntryFile $file ): ?string + { + if( !Str::endsWith( $file->filename, ['zip', 'rar', '7z'] ) ) + return null; + + $serverKey = $this->getEntryFileServerKey( $file ); + $url = $this->servers[$serverKey]['file_explorer'] ?? "#"; + + if( $url === "#" ) + return null; + + $args = [ 'filename' => $file->filename, 'filepath' => $file->filepath, + 'zeus' => $this->generateZeusToken(\Auth::user()->user_id ?? 0, $this->servers[$serverKey]['base_url'], 'Fileexplorer') + ]; + + return $url . "&" . http_build_query( $args ); } /** @@ -137,11 +162,13 @@ class FileServersService { foreach( $this->servers as $serverKey => $server ){ - $response = Http::withHeaders([]) + $token = $this->generateZeusToken( $userId, $server['base_url'], "Deletefile" ); + + $response = Http::asForm()->withHeaders([]) ->post( $server['delete_file'], [ 'filepath' => $filePath, 'filename' => $fileName, - 'zeus' => $this->generateZeusToken( $userId, $server['base_url'], "Deletefile" ), + 'zeus' => $token, ]); if (!$response->successful()) { diff --git a/app/Services/SubmissionsService.php b/app/Services/SubmissionsService.php index 15130cf..e89c394 100644 --- a/app/Services/SubmissionsService.php +++ b/app/Services/SubmissionsService.php @@ -63,8 +63,10 @@ class SubmissionsService { if( $files === [] ) return []; + $service = app(FileServersService::class); + return array_map( - function( string $uuid ) { + function( string $uuid ) use ($service) { $file = EntryFile::where('file_uuid', $uuid)->first(); if( $file ) @@ -78,6 +80,9 @@ class SubmissionsService { 'error' => null, 'uuid' => $uuid, 'state' => $file->state, + 'file_explorer' => $service->getArchiveExplorerUrl($file), + 'file_explorer_files' => null, + 'download_url' => $service->getDownloadFileUrl($file, false), 'can_be_online_patched' => EntryHelpers::enableOnlinePatcherBasedOnExtension($file['filename']), 'meta_online_patcher' => $file->online_patcher, 'meta_secondary_online_patcher' => $file->secondary_online_patcher, @@ -98,6 +103,9 @@ class SubmissionsService { 'error' => null, 'uuid' => $uuid, 'state' => $file['state'], + 'file_explorer' => null, + 'file_explorer_files' => null, + 'download_url' => null, 'can_be_online_patched' => EntryHelpers::enableOnlinePatcherBasedOnExtension($file['filename']), 'meta_online_patcher' => false, 'meta_secondary_online_patcher' => false, @@ -707,10 +715,10 @@ class SubmissionsService { $needDeletion = array_diff( $existingUuids, $requestUuids ); if( !empty( $needDeletion ) ){ $userId = \Auth::user()->user_id; - EntryFile::where('entry_id', $entryId)->whereIn('file_uuid', $needDeletion)->get()->each( function ( $f ) use ( $userId ) { + EntryFile::where('entry_id', $entryId)->whereIn('file_uuid', $needDeletion)->whereNot('state', 'archived')->get()->each( function ( $f ) use ( $userId ) { DeleteFile::dispatch( $f->filepath, $f->filename, $userId); }); - EntryFile::where('entry_id', $entryId)->whereIn('file_uuid', $needDeletion)->delete(); + EntryFile::where('entry_id', $entryId)->whereIn('file_uuid', $needDeletion)->whereNot('state', 'archived')->delete(); } $needAddition = array_diff( $requestUuids, $existingUuids ); diff --git a/resources/js/PlayOnline.js b/resources/js/PlayOnline.js new file mode 100644 index 0000000..4950b03 --- /dev/null +++ b/resources/js/PlayOnline.js @@ -0,0 +1,43 @@ +window.PlayOnline = function( filePath = "", emulatorJsConfig = {} ){ + + return { + + fileUrl: filePath, + emuConfig: emulatorJsConfig, + + init(){ + this.launchEmulatorJs(); + }, + + cleanEmulatorJsVars() { + ['EJS_player','EJS_core','EJS_gameUrl','EJS_pathtodata', + 'EJS_startOnLoaded','EJS_threads'] + .forEach(k => delete window[k]); + }, + + prepareEmulatorJs(){ + window.EJS_player = '#game'; + window.EJS_core = this.emuConfig.core; + window.EJS_gameUrl = this.filePath; + window.EJS_pathtodata = "https://cdn.emulatorjs.org/stable/data/"; + window.EJS_startOnLoaded = true; + window.EJS_threads = this.emuConfig.threads ?? false; + }, + + launchEmulatorJs(){ + + this.cleanEmulatorJsVars(); + this.prepareEmulatorJs(); + + const script = document.createElement('script'); + script.id = 'ejs-loader'; + script.src = 'https://cdn.emulatorjs.org/stable/data/loader.js'; + document.body.appendChild(script); + + this.launchGame = true; + + } + + } + +} diff --git a/resources/js/SubmissionsClass/FSFileData.js b/resources/js/SubmissionsClass/FSFileData.js index 6c4fc13..623e885 100644 --- a/resources/js/SubmissionsClass/FSFileData.js +++ b/resources/js/SubmissionsClass/FSFileData.js @@ -1,6 +1,6 @@ /** @typedef { import('types/UploadchunkResponse.js').UploadchunkResponse} UploadchunkResponse */ -export const CHUNK_SIZE = 8192; +export const CHUNK_SIZE = 8192 * 1024; const PATCH_EXTENSIONS = new Set([ 'ips', 'bps', 'ups', 'aps', 'ppf', 'xdelta', "zip" @@ -72,6 +72,15 @@ export function FSFileData(name, totalChunks, rawFile ) { */ state: 'public', + file_explorer: null, + + file_explorer_files: null, + + /** + * For files already uploaded, download URL. + */ + download_url: null, + can_be_online_patched: PATCH_EXTENSIONS.has(extension), /** diff --git a/resources/js/SubmissionsClass/FSUploader.js b/resources/js/SubmissionsClass/FSUploader.js index 96af2ed..8c7a597 100644 --- a/resources/js/SubmissionsClass/FSUploader.js +++ b/resources/js/SubmissionsClass/FSUploader.js @@ -105,6 +105,29 @@ export function FSUploader(){ }, + handleDownloadFile( index ){ + let download_url = this.files[index].download_url; + window.location.href = download_url; + }, + + async handleFileExplorer( index ){ + + if( this.files[index].file_explorer_files !== null ) + return; + + let file_explorer_url = this.files[index].file_explorer; + + let response = await fetch(file_explorer_url, { method: 'GET', headers: { 'Content-Type': 'application/json' } }); + let json = await response.json(); + + if( !json.files ){ + this.files[index].file_explorer_files = [ "An error occurred during request" ]; + return; + } + + this.files[index].file_explorer_files = json.files; + }, + /** * Retry file uploading. * @@ -126,6 +149,8 @@ export function FSUploader(){ * @param {number} index FSFileData index in this.files. */ handleRemoveFile( index ){ + if( this.files[index].state === 'archived') + return; this.files.splice(index, 1); }, diff --git a/resources/views/livewire/entry-files-modal.blade.php b/resources/views/livewire/entry-files-modal.blade.php index dfb2817..14b3e2c 100644 --- a/resources/views/livewire/entry-files-modal.blade.php +++ b/resources/views/livewire/entry-files-modal.blade.php @@ -17,10 +17,13 @@