diff --git a/app/Http/Controllers/AnimeController.php b/app/Http/Controllers/AnimeController.php
index e2d4a1d1dc..bf4883d748 100644
--- a/app/Http/Controllers/AnimeController.php
+++ b/app/Http/Controllers/AnimeController.php
@@ -711,7 +711,7 @@ public function exportAnimeList(Request $request, AnimeListExportService $export
// Validation
$request->validate([
- 'export_type' => 'required|in:myanimelist,arigatou',
+ 'export_type' => 'required|in:myanimelist,arigatou,myanimelistcss',
]);
$userId = Auth::id();
@@ -727,6 +727,9 @@ public function exportAnimeList(Request $request, AnimeListExportService $export
} elseif ($exportType === 'arigatou') {
$fileName = "{$fileNameBase}.json";
Storage::put('exports/'.$fileName, $result['output']);
+ } elseif ($exportType === 'myanimelistcss') {
+ $fileName = "{$fileNameBase}.css";
+ Storage::put('exports/'.$fileName, $result['output']);
} else {
return redirect()->back()->with('message', 'Export failed due to unknown file type.');
}
diff --git a/app/Services/AnimeListExportService.php b/app/Services/AnimeListExportService.php
index c35ca83694..ef12001500 100644
--- a/app/Services/AnimeListExportService.php
+++ b/app/Services/AnimeListExportService.php
@@ -15,6 +15,8 @@ public function export($fileType, $userId, $logger = null)
return $this->exportToMyAnimeList($userId, $logger);
} elseif ($fileType === 'arigatou') {
return $this->exportToArigatou($userId, $logger);
+ } elseif ($fileType === 'myanimelistcss') {
+ return $this->exportToMyAnimeListCss($userId, $logger);
} else {
// Unknown file type
return "";
@@ -115,4 +117,50 @@ private function exportToArigatou($userId, $logger = null)
$duration = microtime(true) - $startTime;
return ["total" => $total, "duration" => $duration, "output" => $formattedJson];
}
+
+ private function exportToMyAnimeListCss($userId, $logger = null)
+ {
+ $startTime = microtime(true);
+ $animeList = AnimeUser::with('anime')
+ ->where('user_id', $userId)
+ ->whereHas('watch_status', function ($query) {
+ $query->where('status', 'COMPLETED');
+ })
+ ->where('sort_order', '>=', 1)
+ ->orderBy('sort_order', 'ASC')
+ ->get();
+ $total = count($animeList);
+ $cssOutput = "";
+ //These seem to be the min and max orders MAL allows, starting from -1000 and going up to 3000.
+ $minOrder = -1000;
+ $maxOrder = 3000;
+ $currentOrder = $minOrder;
+ foreach ($animeList as $animeUser) {
+ $source = collect(explode(', ', $animeUser->anime->sources))->first(function ($source) {
+ return str_contains($source, 'myanimelist.net/anime/');
+ });
+ if ($source) {
+ preg_match('/myanimelist\.net\/anime\/(\d+)/', $source, $matches);
+ $animeId = $matches[1] ?? null;
+ if ($animeId) {
+ //If we wanted to use just the provided sort order, from 1 to 3000, we could just use sort_order.
+ //$order = $animeUser->sort_order;
+ //Technically, by default the order is limited from 1 to 3000, maybe we want more anime total, so let's scale it from min to max for a total of 4000 anime.
+ $order = $currentOrder;
+ $cssOutput .= ".list-container .list-block .completed table.list-table > tbody.list-item:has(a[href*=\"anime/{$animeId}/\"]) {\n";
+ $cssOutput .= " visibility: unset;\n";
+ $cssOutput .= " height: unset;\n";
+ $cssOutput .= " order: {$order};\n";
+ $cssOutput .= "}\n";
+ $currentOrder++;
+ }
+ }
+ if ($currentOrder > $maxOrder) {
+ exit("You have exceeded the maximum total anime for MAL custom sorting, congratulations! This isn't very easily achievable.");
+ }
+ }
+
+ $duration = microtime(true) - $startTime;
+ return ["total" => $total, "duration" => $duration, "output" => $cssOutput];
+ }
}
diff --git a/resources/views/exportanimelist.blade.php b/resources/views/exportanimelist.blade.php
index 6f14083c36..820ab539d6 100644
--- a/resources/views/exportanimelist.blade.php
+++ b/resources/views/exportanimelist.blade.php
@@ -22,6 +22,7 @@