Files
2026-08-07 16:01:41 +02:00

305 lines
13 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Console\Commands;
use App\Facades\Elasticsearch;
use App\Facades\Search;
use App\Models\UsenetGroup;
use App\Services\Search\Support\ElasticsearchResponseHelper;
use Elastic\Elasticsearch\Client as ElasticsearchClient;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
class NntmuxResetDb extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'nntmux:resetdb';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This command will reset your database to blank state (will retain settings)';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* @throws \Exception
*/
public function handle(): void
{
// Allow database reset only if app environment is local
if (app()->environment() !== 'local') {
$this->error('This command can only be run in local environment');
return;
}
if ($this->confirm('This command removes all releases, nzb files, samples, previews , nfos, truncates all article tables and resets all groups. Are you sure you want reset the DB?')) {
$timestart = now();
DB::statement('SET FOREIGN_KEY_CHECKS = 0;');
UsenetGroup::query()->update([
'first_record' => 0,
'first_record_postdate' => null,
'last_record' => 0,
'last_record_postdate' => null,
'last_updated' => null,
]);
$this->info('Reseting all groups completed.');
$arr = [
'binaries',
'collections',
'parts',
'missed_parts',
'videos',
'tv_episodes',
'tv_info',
'release_nfos',
'release_comments',
'users_releases',
'user_movies',
'user_series',
'movieinfo',
'musicinfo',
'release_files',
'audio_data',
'release_subtitles',
'video_data',
'media_infos',
'releases',
'anidb_titles',
'anidb_info',
'releases_groups',
];
foreach ($arr as &$value) {
DB::statement("TRUNCATE TABLE $value");
$this->info('Truncating '.$value.' completed.');
}
unset($value);
if (config('search.default') === 'elasticsearch') {
/** @var ElasticsearchClient $client */
$client = app('elasticsearch');
if (ElasticsearchResponseHelper::boolResponse($client, fn (ElasticsearchClient $elasticClient) => $elasticClient->indices()->exists(['index' => 'releases']))) {
Elasticsearch::indices()->delete(['index' => 'releases']);
}
$releases_index = [
'index' => 'releases',
'body' => [
'settings' => [
'number_of_shards' => 2,
'number_of_replicas' => 0,
],
'mappings' => [
'properties' => [
'id' => [
'type' => 'long',
'index' => false,
],
'name' => ['type' => 'text'],
'searchname' => [
'type' => 'text',
'fields' => [
'sort' => [
'type' => 'keyword',
],
],
],
'plainsearchname' => [
'type' => 'text',
'fields' => [
'sort' => [
'type' => 'keyword',
],
],
],
'fromname' => ['type' => 'text'],
'filename' => ['type' => 'text'],
'add_date' => ['type' => 'date', 'format' => 'yyyy-MM-dd HH:mm:ss'],
'post_date' => ['type' => 'date', 'format' => 'yyyy-MM-dd HH:mm:ss'],
'media_movie_name' => ['type' => 'text'],
'media_file_name' => ['type' => 'text'],
'media_unique_id' => ['type' => 'keyword'],
'media_container_format' => ['type' => 'text'],
'media_video_format' => ['type' => 'text'],
'media_video_codec' => ['type' => 'text'],
'media_video_width' => ['type' => 'integer'],
'media_video_height' => ['type' => 'integer'],
'media_audio_format' => ['type' => 'text'],
'media_audio_channels' => ['type' => 'text'],
'media_audio_language' => ['type' => 'text'],
'media_subtitle_language' => ['type' => 'text'],
'has_media_info' => ['type' => 'integer'],
],
],
],
];
Elasticsearch::indices()->create($releases_index);
if (ElasticsearchResponseHelper::boolResponse($client, fn (ElasticsearchClient $elasticClient) => $elasticClient->indices()->exists(['index' => 'predb']))) {
Elasticsearch::indices()->delete(['index' => 'predb']);
}
$predb_index = [
'index' => 'predb',
'body' => [
'settings' => [
'number_of_shards' => 2,
'number_of_replicas' => 0,
],
'mappings' => [
'properties' => [
'id' => [
'type' => 'long',
'index' => false,
],
'title' => [
'type' => 'text',
'fields' => [
'sort' => [
'type' => 'keyword',
],
],
],
'filename' => ['type' => 'text'],
'source' => ['type' => 'text'],
],
],
],
];
Elasticsearch::indices()->create($predb_index);
// Delete and recreate movies index
if (ElasticsearchResponseHelper::boolResponse($client, fn (ElasticsearchClient $elasticClient) => $elasticClient->indices()->exists(['index' => 'movies']))) {
Elasticsearch::indices()->delete(['index' => 'movies']);
}
$movies_index = [
'index' => 'movies',
'body' => [
'settings' => [
'number_of_shards' => 2,
'number_of_replicas' => 0,
],
'mappings' => [
'properties' => [
'id' => [
'type' => 'long',
'index' => false,
],
'imdbid' => ['type' => 'keyword'],
'tmdbid' => ['type' => 'integer'],
'traktid' => ['type' => 'integer'],
'title' => [
'type' => 'text',
'fields' => [
'sort' => [
'type' => 'keyword',
],
],
],
'year' => ['type' => 'text'],
'genre' => ['type' => 'text'],
'actors' => ['type' => 'text'],
'director' => ['type' => 'text'],
'rating' => ['type' => 'text'],
'plot' => ['type' => 'text'],
],
],
],
];
Elasticsearch::indices()->create($movies_index);
// Delete and recreate tvshows index
if (ElasticsearchResponseHelper::boolResponse($client, fn (ElasticsearchClient $elasticClient) => $elasticClient->indices()->exists(['index' => 'tvshows']))) {
Elasticsearch::indices()->delete(['index' => 'tvshows']);
}
$tvshows_index = [
'index' => 'tvshows',
'body' => [
'settings' => [
'number_of_shards' => 2,
'number_of_replicas' => 0,
],
'mappings' => [
'properties' => [
'id' => [
'type' => 'long',
'index' => false,
],
'title' => [
'type' => 'text',
'fields' => [
'sort' => [
'type' => 'keyword',
],
],
],
'tvdb' => ['type' => 'integer'],
'trakt' => ['type' => 'integer'],
'tvmaze' => ['type' => 'integer'],
'tvrage' => ['type' => 'integer'],
'imdb' => ['type' => 'keyword'],
'tmdb' => ['type' => 'integer'],
'started' => ['type' => 'text'],
'type' => ['type' => 'integer'],
],
],
],
];
Elasticsearch::indices()->create($tvshows_index);
$this->info('All done! ElasticSearch indexes are deleted and recreated.');
} else {
Search::truncateIndex([
'releases_rt', 'predb_rt', 'movies_rt', 'tvshows_rt',
'music_rt', 'books_rt', 'games_rt', 'console_rt', 'steam_rt', 'anime_rt',
]);
}
$this->info('Deleting nzbfiles subfolders.');
$files = File::allFiles(config('nntmux_settings.path_to_nzbs'));
File::delete($files);
$this->info('Deleting all images, previews and samples that still remain.');
$files = File::allFiles(storage_path('covers/'));
foreach ($files as $file) {
$path = $file->getPathname();
if (basename($path) !== '.gitignore' && basename($path) !== 'no-cover.jpg' && basename($path) !== 'no-backdrop.jpg') {
File::delete($path);
}
}
$this->call('cache:clear');
$this->info('Deleted all releases, images, previews and samples. This script finished '.now()->diffForHumans($timestart).' start');
DB::statement('SET FOREIGN_KEY_CHECKS = 1;');
} else {
$this->info('Script execution stopped');
}
}
}