first commit

This commit is contained in:
Lars Behrends
2025-10-17 13:29:28 +02:00
commit 929ee43001
85 changed files with 10361 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateSourcesTable extends Migration
{
public function up()
{
// Get the capsule instance from Database class
$capsule = Database::getCapsule();
$capsule->schema()->create('sources', function (Blueprint $table) {
$table->id();
$table->string('name'); // steam, jellyfin, stash, xbvr
$table->string('display_name');
$table->string('api_url')->nullable();
$table->string('api_key')->nullable();
$table->json('config')->nullable(); // Additional configuration
$table->boolean('is_active')->default(true);
$table->timestamp('last_sync_at')->nullable();
$table->timestamps();
});
}
public function down()
{
// Get the capsule instance from Database class
$capsule = Database::getCapsule();
$capsule->schema()->dropIfExists('sources');
}
}

View File

@@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateActorsTable extends Migration
{
public function up()
{
// Get the capsule instance from Database class
Database::getCapsule()->schema()->create('actors', function ($table) {
$table->id();
$table->string('name');
$table->string('thumbnail_path')->nullable();
$table->json('metadata')->nullable(); // XBVR/Stash specific data
$table->timestamp('created_at')->nullable();
$table->timestamp('updated_at')->nullable();
//$table->index(['unique_actor_name']);
});
}
public static function down(PDO $pdo): void
{
$sql = "DROP TABLE IF EXISTS actors;";
$pdo->exec($sql);
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateMediaTypesTable extends Migration
{
public function up()
{
// Get the capsule instance from Database class
$capsule = Database::getCapsule();
$capsule->schema()->create('media_types', function (Blueprint $table) {
$table->id();
$table->string('name'); // games, movies, tv_shows, music
$table->string('display_name');
$table->string('icon')->nullable(); // Icon class for UI
$table->boolean('is_active')->default(true);
$table->timestamps();
});
}
public function down()
{
// Get the capsule instance from Database class
$capsule = Database::getCapsule();
$capsule->schema()->dropIfExists('media_types');
}
}

View File

@@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateGamesTable extends Migration
{
public function up()
{
Database::getCapsule()->schema()->create('games', function ($table) {
$table->id();
$table->string('title');
$table->text('description')->nullable();
$table->string('genre')->nullable();
$table->string('developer')->nullable();
$table->string('publisher')->nullable();
$table->date('release_date')->nullable();
$table->string('platform')->nullable(); // PC, PlayStation, Xbox, etc.
$table->string('steam_app_id')->nullable(); // For Steam integration
$table->string('image_url')->nullable();
$table->string('banner_url')->nullable();
$table->decimal('rating', 3, 1)->nullable(); // 0.0 to 10.0
$table->integer('playtime_minutes')->default(0); // Total playtime in minutes
$table->integer('completion_percentage')->default(0); // 0-100
$table->boolean('is_installed')->default(false);
$table->boolean('is_favorite')->default(false);
$table->json('metadata')->nullable(); // Additional game-specific data
$table->foreignId('source_id')->constrained('sources');
$table->timestamp('last_played_at')->nullable();
$table->timestamps();
});
}
public function down()
{
Database::getCapsule()->schema()->dropIfExists('games');
}
}

View File

@@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateMoviesTable extends Migration
{
public function up()
{
Database::getCapsule()->schema()->create('movies', function ($table) {
$table->id();
$table->string('title');
$table->text('overview')->nullable();
$table->string('director')->nullable();
$table->string('writer')->nullable();
$table->string('genre')->nullable();
$table->string('cast')->nullable(); // Comma-separated actors
$table->date('release_date')->nullable();
$table->integer('runtime_minutes')->nullable(); // Runtime in minutes
$table->decimal('rating', 3, 1)->nullable(); // IMDb rating 0.0 to 10.0
$table->string('imdb_id')->nullable();
$table->string('tmdb_id')->nullable(); // The Movie Database ID
$table->string('poster_url')->nullable();
$table->string('backdrop_url')->nullable();
$table->boolean('watched')->default(false);
$table->integer('watch_count')->default(0);
$table->boolean('is_favorite')->default(false);
$table->json('metadata')->nullable(); // Additional movie-specific data
$table->foreignId('source_id')->constrained('sources');
$table->timestamp('last_watched_at')->nullable();
$table->timestamps();
});
}
public function down()
{
Database::getCapsule()->schema()->dropIfExists('movies');
}
}

View File

@@ -0,0 +1,41 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateTvShowsTable extends Migration
{
public function up()
{
Database::getCapsule()->schema()->create('tv_shows', function ($table) {
$table->id();
$table->string('title');
$table->text('overview')->nullable();
$table->string('creator')->nullable();
$table->string('genre')->nullable();
$table->string('cast')->nullable(); // Comma-separated actors
$table->date('first_air_date')->nullable();
$table->date('last_air_date')->nullable();
$table->integer('number_of_seasons')->default(0);
$table->integer('number_of_episodes')->default(0);
$table->decimal('rating', 3, 1)->nullable(); // IMDb rating 0.0 to 10.0
$table->string('imdb_id')->nullable();
$table->string('tmdb_id')->nullable(); // The Movie Database ID
$table->string('tvdb_id')->nullable(); // TVDB ID
$table->string('poster_url')->nullable();
$table->string('backdrop_url')->nullable();
$table->boolean('is_favorite')->default(false);
$table->json('metadata')->nullable(); // Additional show-specific data
$table->foreignId('source_id')->constrained('sources');
$table->timestamps();
});
}
public function down()
{
Database::getCapsule()->schema()->dropIfExists('tv_shows');
}
}

View File

@@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateTvEpisodesTable extends Migration
{
public function up()
{
Database::getCapsule()->schema()->create('tv_episodes', function ($table) {
$table->id();
$table->string('title');
$table->text('overview')->nullable();
$table->integer('season_number');
$table->integer('episode_number');
$table->date('air_date')->nullable();
$table->integer('runtime_minutes')->nullable();
$table->decimal('rating', 3, 1)->nullable();
$table->string('director')->nullable();
$table->string('writer')->nullable();
$table->string('still_url')->nullable(); // Episode still image
$table->boolean('watched')->default(false);
$table->integer('watch_count')->default(0);
$table->json('metadata')->nullable(); // Additional episode-specific data
$table->foreignId('tv_show_id')->constrained('tv_shows')->onDelete('cascade');
$table->foreignId('source_id')->constrained('sources');
$table->timestamp('last_watched_at')->nullable();
$table->timestamps();
});
}
public function down()
{
Database::getCapsule()->schema()->dropIfExists('tv_episodes');
}
}

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateMusicArtistsTable extends Migration
{
public function up()
{
Database::getCapsule()->schema()->create('music_artists', function ($table) {
$table->id();
$table->string('name');
$table->text('biography')->nullable();
$table->date('formed_date')->nullable();
$table->string('genre')->nullable();
$table->string('country')->nullable();
$table->string('image_url')->nullable();
$table->string('banner_url')->nullable();
$table->string('spotify_id')->nullable();
$table->string('musicbrainz_id')->nullable();
$table->boolean('is_favorite')->default(false);
$table->json('metadata')->nullable(); // Additional artist-specific data
$table->foreignId('source_id')->constrained('sources');
$table->timestamps();
});
}
public function down()
{
Database::getCapsule()->schema()->dropIfExists('music_artists');
}
}

View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateMusicAlbumsTable extends Migration
{
public function up()
{
Database::getCapsule()->schema()->create('music_albums', function ($table) {
$table->id();
$table->string('title');
$table->string('artist_name'); // Denormalized for performance
$table->date('release_date')->nullable();
$table->string('genre')->nullable();
$table->integer('track_count')->default(0);
$table->integer('total_duration_seconds')->default(0);
$table->string('cover_url')->nullable();
$table->string('spotify_id')->nullable();
$table->string('musicbrainz_id')->nullable();
$table->boolean('is_favorite')->default(false);
$table->json('metadata')->nullable(); // Additional album-specific data
$table->foreignId('artist_id')->constrained('music_artists')->onDelete('cascade');
$table->foreignId('source_id')->constrained('sources');
$table->timestamps();
});
}
public function down()
{
Database::getCapsule()->schema()->dropIfExists('music_albums');
}
}

View File

@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateMusicTracksTable extends Migration
{
public function up()
{
Database::getCapsule()->schema()->create('music_tracks', function ($table) {
$table->id();
$table->string('title');
$table->string('artist_name'); // Denormalized for performance
$table->string('album_name')->nullable(); // Denormalized for performance
$table->integer('track_number')->nullable();
$table->integer('duration_seconds')->nullable();
$table->string('genre')->nullable();
$table->date('release_date')->nullable();
$table->integer('play_count')->default(0);
$table->boolean('is_favorite')->default(false);
$table->json('metadata')->nullable(); // Additional track-specific data
$table->foreignId('artist_id')->constrained('music_artists')->onDelete('cascade');
$table->foreignId('album_id')->nullable()->constrained('music_albums')->onDelete('set null');
$table->foreignId('source_id')->constrained('sources');
$table->timestamp('last_played_at')->nullable();
$table->timestamps();
});
}
public function down()
{
Database::getCapsule()->schema()->dropIfExists('music_tracks');
}
}

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateSyncLogsTable extends Migration
{
public function up()
{
Database::getCapsule()->schema()->create('sync_logs', function ($table) {
$table->id();
$table->foreignId('source_id')->constrained('sources');
$table->string('sync_type'); // full, incremental
$table->string('status'); // started, completed, failed
$table->integer('total_items')->default(0);
$table->integer('processed_items')->default(0);
$table->integer('new_items')->default(0);
$table->integer('updated_items')->default(0);
$table->integer('deleted_items')->default(0);
$table->json('errors')->nullable(); // Array of error messages
$table->text('message')->nullable(); // Additional details
$table->timestamp('started_at')->nullable();
$table->timestamp('completed_at')->nullable();
$table->timestamps();
});
}
public function down()
{
Database::getCapsule()->schema()->dropIfExists('sync_logs');
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateUsersTable extends Migration
{
public function up()
{
Database::getCapsule()->schema()->create('users', function ($table) {
$table->id();
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('password');
$table->string('role')->default('user'); // user, admin
$table->boolean('is_active')->default(true);
$table->timestamp('last_login_at')->nullable();
$table->string('login_ip')->nullable();
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Database::getCapsule()->schema()->dropIfExists('users');
}
}

View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class AddGameGroupingFields extends Migration
{
public function up()
{
Database::getCapsule()->schema()->table('games', function ($table) {
// Add game_key for grouping games across platforms
$table->string('game_key')->nullable()->after('title')->index();
// Add platform_game_id for platform-specific identifiers
$table->string('platform_game_id')->nullable()->after('platform');
// Add platform_achievements for platform-specific achievement data
$table->json('platform_achievements')->nullable()->after('metadata');
// Add platform_stats for platform-specific statistics
$table->json('platform_stats')->nullable()->after('platform_achievements');
});
}
public function down()
{
Database::getCapsule()->schema()->table('games', function ($table) {
$table->dropColumn(['game_key', 'platform_game_id', 'platform_achievements', 'platform_stats']);
});
}
}

View File

@@ -0,0 +1,46 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use App\Database\Database;
class CreateAdultVideosTable extends Migration
{
public function up()
{
// Get the capsule instance from Database class
Database::getCapsule()->schema()->create('adult_videos', function ($table) {
$table->id();
$table->string('title');
$table->text('overview')->nullable();
$table->string('poster_url')->nullable();
$table->string('backdrop_url')->nullable();
$table->decimal('rating', 3, 1)->nullable();
$table->integer('runtime_minutes')->nullable();
$table->date('release_date')->nullable();
$table->string('director')->nullable();
$table->string('writer')->nullable();
$table->text('cast')->nullable();
$table->string('genre')->nullable();
$table->json('metadata')->nullable(); // XBVR/Stash specific data
$table->boolean('watched')->default(false);
$table->integer('watch_count')->default(0);
$table->boolean('is_favorite')->default(false);
$table->unsignedBigInteger('source_id');
$table->string('external_id')->nullable(); // XBVR/Stash ID
$table->timestamps();
$table->foreign('source_id')->references('id')->on('sources')->onDelete('cascade');
$table->index(['source_id', 'external_id']);
$table->index('title');
});
}
public function down()
{
// Get the capsule instance from Database class
$capsule = Database::getCapsule();
$capsule->schema()->dropIfExists('adult_videos');
}
}