Early Mod Import

This commit is contained in:
Refringe 2024-05-21 21:02:49 -04:00
parent 9f0bfda462
commit 8e11892f57
Signed by: Refringe
GPG Key ID: 7715B85B4A6306ED
8 changed files with 157 additions and 13 deletions

View File

@ -2,11 +2,15 @@
namespace App\Console\Commands;
use App\Models\License;
use App\Models\Mod;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class ImportWoltlabData extends Command
{
@ -30,6 +34,8 @@ class ImportWoltlabData extends Command
public function handle(): void
{
$this->importUsers();
$this->importLicenses();
$this->importMods();
$this->info('Data imported successfully.');
}
@ -47,6 +53,7 @@ class ImportWoltlabData extends Command
$registrationDate->setTimezone('UTC');
$insertData[] = [
'hub_id' => $wolt->userID,
'name' => $wolt->username,
'email' => mb_convert_case($wolt->email, MB_CASE_LOWER, 'UTF-8'),
'password' => $wolt->password,
@ -56,15 +63,143 @@ class ImportWoltlabData extends Command
}
if (!empty($insertData)) {
User::insert($insertData);
User::upsert($insertData, ['hub_id'], ['name', 'email', 'password', 'created_at', 'updated_at']);
$totalInserted += count($insertData);
$this->info('Inserted ' . count($insertData) . ' users. Total inserted so far: ' . $totalInserted);
$this->line('Processed ' . count($insertData) . ' users. Total processed so far: ' . $totalInserted);
}
unset($insertData);
unset($users);
}, 'userID');
$this->info('Total users inserted: ' . $totalInserted);
$this->info('Total users processed: ' . $totalInserted);
$this->newLine();
}
protected function importLicenses(): void
{
$totalInserted = 0;
DB::connection('mysql_woltlab')->table('filebase1_license')->chunkById(100, function (Collection $licenses) use (&$totalInserted) {
$insertData = [];
foreach ($licenses as $license) {
$insertData[] = [
'hub_id' => $license->licenseID,
'name' => $license->licenseName,
'link' => $license->licenseURL,
];
}
if (!empty($insertData)) {
DB::table('licenses')->upsert($insertData, ['hub_id'], ['name', 'link']);
$totalInserted += count($insertData);
$this->line('Processed ' . count($insertData) . ' licenses. Total processed so far: ' . $totalInserted);
}
unset($insertData);
unset($licenses);
}, 'licenseID');
$this->info('Total licenses processed: ' . $totalInserted);
$this->newLine();
}
protected function importMods(): void
{
$command = $this;
$totalInserted = 0;
DB::connection('mysql_woltlab')->table('filebase1_file')->chunkById(5, function (Collection $mods) use (&$command, &$totalInserted) {
foreach ($mods as $mod)
{
$modContent = DB::connection('mysql_woltlab')->table('filebase1_file_content')->where('fileID', $mod->fileID)->first();
$insertData[] = [
'hub_id' => $mod->fileID,
'user_id' => User::whereName($mod->username)->value('id'),
'name' => $modContent->subject,
'slug' => Str::slug($modContent->subject),
'teaser' => $modContent->teaser,
'description' => $modContent->message,
'thumbnail' => $this->fetchModThumbnail($command, $mod->fileID, $mod->iconHash, $mod->iconExtension),
'license_id' => License::whereHubId($mod->licenseID)->value('id'),
'source_code_link' => $this->fetchSourceLinkValue($mod->fileID),
'featured' => $mod->isFeatured,
'contains_ai_content' => $this->fetchContainsAiContentValue($mod->fileID),
'disabled' => $mod->isDisabled,
'created_at' => Carbon::parse($mod->time, 'UTC'),
'updated_at' => Carbon::parse($mod->lastChangeTime, 'UTC'),
];
}
if (!empty($insertData)) {
Mod::upsert($insertData, ['hub_id'], ['user_id', 'name', 'slug', 'teaser', 'description', 'thumbnail', 'license_id', 'source_code_link', 'featured', 'contains_ai_content', 'disabled', 'created_at', 'updated_at']);
$totalInserted += count($insertData);
$command->line('Processed ' . count($insertData) . ' mods. Total processed so far: ' . $totalInserted);
}
unset($insertData);
unset($mods);
}, 'fileID');
$this->info('Total mods processed: ' . $totalInserted);
$this->newLine();
}
protected function fetchSourceLinkValue(string $fileID): string
{
$options = DB::connection('mysql_woltlab')->table('filebase1_file_option_value')->where('fileID', $fileID)->get();
// Iterate over the options and find the 'optionID' of 5 or 1. That record will contain the source code link in
// the 'optionValue' column. The 'optionID' of 5 should take precedence over 1. If neither are found, return an
// empty string.
foreach ($options as $option) {
if ($option->optionID == 5 && !empty($option->optionValue)) {
return $option->optionValue;
}
if ($option->optionID == 1 && !empty($option->optionValue)) {
return $option->optionValue;
}
}
return '';
}
protected function fetchContainsAiContentValue(string $fileID): bool
{
$options = DB::connection('mysql_woltlab')->table('filebase1_file_option_value')->where('fileID', $fileID)->get();
// Iterate over the options and find the 'optionID' of 7. That record will contain the AI flag.
foreach ($options as $option) {
if ($option->optionID == 7) {
return (bool) $option->optionValue;
}
}
return '';
}
protected function fetchModThumbnail($command, string $fileID, string $thumbnailHash, string $thumbnailExtension): string
{
if (empty($fileID) || empty($thumbnailHash) || empty($thumbnailExtension)) {
return '';
}
// Only the first two characters of the icon hash.
$hashShort = substr($thumbnailHash, 0, 2);
$hubUrl = "https://hub.sp-tarkov.com/files/images/file/$hashShort/$fileID.$thumbnailExtension";
$localPath = "mods/$thumbnailHash.$thumbnailExtension";
// Check to make sure the image doesn't already exist.
if (Storage::disk('public')->exists($localPath)) {
return "/storage/$localPath";
}
$command->output->write("Downloading mod thumbnail: $hubUrl... ");
Storage::disk('public')->put($localPath, file_get_contents($hubUrl));
$command->info('Done.');
// Return the path to the saved thumbnail.
return "/storage/$localPath";
}
}

View File

@ -9,20 +9,20 @@ use Illuminate\View\Component;
class ModListSection extends Component
{
public Collection $modsSuggested;
public Collection $modsFeatured;
public Collection $modsLatest;
public Collection $modsUpdated;
public function __construct()
{
$this->modsSuggested = $this->fetchSuggestedMods();
$this->modsFeatured = $this->fetchFeaturedMods();
$this->modsLatest = $this->fetchLatestMods();
$this->modsUpdated = $this->fetchUpdatedMods();
}
private function fetchSuggestedMods(): Collection
private function fetchFeaturedMods(): Collection
{
return Mod::with('versionLatestSptVersion.sptVersion')->whereSuggested(true)->take(6)->get();
return Mod::with('versionLatestSptVersion.sptVersion')->whereFeatured(true)->take(6)->get();
}
private function fetchLatestMods(): Collection
@ -39,8 +39,8 @@ class ModListSection extends Component
{
return [
[
'title' => 'Suggested Mods',
'mods' => $this->modsSuggested,
'title' => 'Featured Mods',
'mods' => $this->modsFeatured,
'versionScope' => 'versionLatestSptVersion'
],
[

View File

@ -20,10 +20,11 @@ class ModFactory extends Factory
'user_id' => User::factory(),
'name' => $name,
'slug' => Str::slug($name),
'description' => $this->faker->paragraph,
'teaser' => $this->faker->sentence,
'description' => $this->faker->sentences(6, true),
'license_id' => License::factory(),
'source_code_link' => $this->faker->url(),
'suggested' => $this->faker->boolean,
'featured' => $this->faker->boolean,
'contains_ai_content' => $this->faker->boolean,
'created_at' => now(),
'updated_at' => now(),

View File

@ -13,6 +13,7 @@ return new class extends Migration
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('hub_id')->nullable()->unique();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();

View File

@ -10,6 +10,7 @@ return new class extends Migration
{
Schema::create('licenses', function (Blueprint $table) {
$table->id();
$table->string('hub_id')->nullable()->unique();
$table->string('name');
$table->string('link');
$table->softDeletes();

View File

@ -12,14 +12,18 @@ return new class extends Migration
{
Schema::create('mods', function (Blueprint $table) {
$table->id();
$table->string('hub_id')->nullable()->unique();
$table->foreignIdFor(User::class)->constrained('users');
$table->string('name');
$table->string('slug');
$table->string('teaser');
$table->longText('description');
$table->foreignIdFor(License::class)->constrained('licenses');
$table->string('thumbnail')->default('');
$table->foreignIdFor(License::class)->nullable()->default(null)->constrained('licenses');
$table->string('source_code_link');
$table->boolean('suggested')->default(false);
$table->boolean('featured')->default(false);
$table->boolean('contains_ai_content')->default(false);
$table->boolean('disabled')->default(false);
$table->softDeletes();
$table->timestamps();
});

View File

@ -10,6 +10,7 @@ return new class extends Migration
{
Schema::create('spt_versions', function (Blueprint $table) {
$table->id();
$table->string('hub_id')->nullable()->unique();
$table->string('version');
$table->string('color_class');
$table->softDeletes();

View File

@ -12,6 +12,7 @@ return new class extends Migration
{
Schema::create('mod_versions', function (Blueprint $table) {
$table->id();
$table->string('hub_id')->nullable()->unique();
$table->foreignIdFor(Mod::class)->constrained('mods');
$table->string('version');
$table->longText('description');