Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Update] Improve MAL Import #155

Merged
merged 5 commits into from
Jun 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions app/Enums/MALImportBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace App\Enums;

use BenSampo\Enum\Enum;

/**
* @method static MALImportBehavior Overwrite()
* @method static MALImportBehavior Merge()
*/
final class MALImportBehavior extends Enum
{
const Overwrite = 0;
const Merge = 1;
}
9 changes: 5 additions & 4 deletions app/Events/MALImportFinished.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Events;

use App\Enums\MALImportBehavior;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
Expand All @@ -27,18 +28,18 @@ class MALImportFinished
/**
* The behavior of the import.
*
* @var string
* @var MALImportBehavior
*/
public string $behavior;
public MALImportBehavior $behavior;

/**
* Create a new event instance.
*
* @param User $user
* @param array $results
* @param string $behavior
* @param MALImportBehavior $behavior
*/
public function __construct(User $user, array $results, string $behavior)
public function __construct(User $user, array $results, MALImportBehavior $behavior)
{
$this->user = $user;
$this->results = $results;
Expand Down
6 changes: 5 additions & 1 deletion app/Http/Controllers/LibraryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Http\Controllers;

use App\Enums\MALImportBehavior;
use App\Models\Anime;
use App\Enums\UserLibraryStatus;
use App\Helpers\JSONResult;
Expand Down Expand Up @@ -153,8 +154,11 @@ function malImport(MALImportRequest $request): JsonResponse
// Read XML file
$xmlContent = File::get($data['file']->getRealPath());

// Get import behavior
$behavior = MALImportBehavior::fromValue((int) $data['behavior']);

// Dispatch job
dispatch(new ProcessMALImport($user, $xmlContent, $data['behavior']));
dispatch(new ProcessMALImport($user, $xmlContent, $behavior));

// Update last MAL import date for user
$user->last_mal_import_at = now();
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Requests/MALImportRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Http\Requests;

use App\Enums\MALImportBehavior;
use Illuminate\Foundation\Http\FormRequest;

class MALImportRequest extends FormRequest
Expand All @@ -25,7 +26,7 @@ public function rules(): array
{
return [
'file' => ['required', 'file', 'mimes:xml', 'max:' . config('mal-import.max_xml_file_size')],
'behavior' => ['required', 'string', 'in:overwrite']
'behavior' => ['required', 'integer', 'in:' . implode(',', MALImportBehavior::getValues())]
];
}
}
69 changes: 53 additions & 16 deletions app/Jobs/ProcessMALImport.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

namespace App\Jobs;

use App\Enums\MALImportBehavior;
use App\Models\Anime;
use App\Enums\UserLibraryStatus;
use App\Models\AnimeRating;
use App\Models\UserLibrary;
use App\Notifications\MALImportFinished;
use App\Models\User;
use Illuminate\Bus\Queueable;
Expand Down Expand Up @@ -40,9 +43,9 @@ class ProcessMALImport implements ShouldQueue
/**
* The behavior of the import action.
*
* @var string
* @var MALImportBehavior
*/
protected string $behavior;
protected MALImportBehavior $behavior;

/**
* The results of the import action.
Expand All @@ -59,9 +62,9 @@ class ProcessMALImport implements ShouldQueue
*
* @param User $user
* @param string $xmlContent
* @param string $behavior
* @param MALImportBehavior $behavior
*/
public function __construct(User $user, string $xmlContent, string $behavior)
public function __construct(User $user, string $xmlContent, MALImportBehavior $behavior)
{
$this->user = $user;
$this->xmlContent = $xmlContent;
Expand All @@ -74,8 +77,9 @@ public function __construct(User $user, string $xmlContent, string $behavior)
public function handle()
{
// Wipe current library if behavior is set to overwrite
if ($this->behavior === 'overwrite') {
if ($this->behavior->value === MALImportBehavior::Overwrite) {
$this->user->library()->detach();
$this->user->animeRating()->delete();
}

// Create XML object
Expand All @@ -87,7 +91,7 @@ public function handle()

// Loop through the anime in the export file
foreach($json['anime'] as $anime) {
$this->handleXMLFileAnime($anime['series_animedb_id'], $anime['my_status']);
$this->handleXMLFileAnime($anime['series_animedb_id'], $anime['my_status'], $anime['my_score']);
}

// Notify the user that the MAL import was finished
Expand All @@ -99,16 +103,18 @@ public function handle()
*
* @param int $malID
* @param string $malStatus
* @param int $malRating
*/
protected function handleXMLFileAnime(int $malID, string $malStatus)
protected function handleXMLFileAnime(int $malID, string $malStatus, int $malRating)
{
// Try to find the Anime in our DB
$animeMatch = Anime::where('mal_id', $malID)->first();
$anime = Anime::firstWhere('mal_id', $malID);

// If a match was found
if ($animeMatch) {
// Convert the MAL status to one of our own
if (!empty($anime)) {
// Convert the MAL data to our own
$status = $this->convertMALStatus($malStatus);
$rating = $this->convertMALRating($malRating);

// Status not found
if ($status === null) {
Expand All @@ -117,11 +123,25 @@ protected function handleXMLFileAnime(int $malID, string $malStatus)
}

// Add the anime to their library
$this->user->library()->attach($animeMatch, ['status' => $status]);

$this->registerSuccess($animeMatch->id, $malID, $status);
UserLibrary::updateOrCreate([
'user_id' => $this->user->id,
'anime_id' => $anime->id,
], [
'status' => $status
]);

// Updated their anime score
AnimeRating::updateOrCreate([
'user_id' => $this->user->id,
'anime_id' => $anime->id,
], [
'rating' => $rating,
]);

$this->registerSuccess($anime->id, $malID, $status, $rating);
} else {
$this->registerFailure($malID, 'MAL ID could not be found.');
}
else $this->registerFailure($malID, 'MAL ID could not be found.');
}

/**
Expand All @@ -142,19 +162,36 @@ protected function convertMALStatus(string $malStatus): ?int
};
}

/**
* Converts and returns Kurozora specific rating.
*
* @param int $malRating
* @return int
*/
protected function convertMALRating(int $malRating): int
{
if ($malRating == 0) {
return $malRating;
}

return round($malRating) * 0.5;
}

/**
* Registers a success in the import process.
*
* @param int $animeID
* @param int $malID
* @param string $status
* @param int $rating
*/
protected function registerSuccess(int $animeID, int $malID, string $status)
protected function registerSuccess(int $animeID, int $malID, string $status, int $rating)
{
$this->results['successful'][] = [
'anime_id' => $animeID,
'mal_id' => $malID,
'status' => $status
'status' => $status,
'rating' => $rating,
];
}

Expand Down
10 changes: 10 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@ class User extends Authenticatable implements HasMedia, MustVerifyEmail, Reacter
*/
protected string $profileImageCollectionName = 'profile';

/**
* Returns the anime ratings the user has.
*
* @return HasMany
*/
public function animeRating(): HasMany
{
return $this->hasMany(AnimeRating::class);
}

/**
* Returns the associated feed messages for the user.
*
Expand Down
11 changes: 6 additions & 5 deletions app/Notifications/MALImportFinished.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Notifications;

use App\Enums\MALImportBehavior;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
Expand All @@ -23,17 +24,17 @@ class MALImportFinished extends Notification implements ShouldQueue
/**
* The behavior used when importing.
*
* @var string $behavior
* @var MALImportBehavior $behavior
*/
private string $behavior;
private MALImportBehavior $behavior;

/**
* Create a new notification instance.
*
* @param array $results
* @param string $behavior
* @param MALImportBehavior $behavior
*/
public function __construct(array $results, string $behavior)
public function __construct(array $results, MALImportBehavior $behavior)
{
$this->results = $results;
$this->behavior = $behavior;
Expand Down Expand Up @@ -61,7 +62,7 @@ public function toDatabase(mixed $notifiable): array
return [
'successful_count' => count($this->results['successful']),
'failure_count' => count($this->results['failure']),
'behavior' => $this->behavior
'behavior' => $this->behavior->description
];
}

Expand Down
2 changes: 1 addition & 1 deletion config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
| or any other location as required by the application or its packages.
*/

'version' => '1.2.0-alpha.89',
'version' => '1.2.0-alpha.91',

/*
|--------------------------------------------------------------------------
Expand Down
8 changes: 4 additions & 4 deletions config/mal-import.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
| This option controls the cooldown in days for users between importing
| a MAL export file.
|
| Default: 7
| Default: 3
|
*/

'cooldown_in_days' => 7,
'cooldown_in_days' => 3,

/*
|--------------------------------------------------------------------------
Expand All @@ -24,10 +24,10 @@
| This option controls the maximum allowed file size for a MAL export file
| in kilobytes.
|
| Default: 5000
| Default: 10000
|
*/

'max_xml_file_size' => 5000
'max_xml_file_size' => 10000

];
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ public function up()
});

Schema::table(AnimeRating::TABLE_NAME, function(Blueprint $table) {
// Set unique key constraints
$table->unique(['anime_id', 'user_id']);

// Set foreign key constraints
$table->foreign('anime_id')->references('id')->on(Anime::TABLE_NAME)->onDelete('cascade');
$table->foreign('user_id')->references('id')->on(User::TABLE_NAME)->onDelete('cascade');
Expand Down
9 changes: 5 additions & 4 deletions public/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -3491,12 +3491,13 @@
"description": "The lock status used to lock or unlock a thread.\n- 0 = unlock\n- 1 = lock"
},
"MALImportBehavior": {
"type": "string",
"type": "integer",
"enum": [
"overwrite"
0,
1
],
"default": "overwrite",
"description": "The set of available MAL import behavior types."
"default": 1,
"description": "The set of available MAL import behavior types.\n- 0 = overwrite\n- 1 = merge"
},
"NotificationReadStatus": {
"type": "integer",
Expand Down
Loading