initial migrations

This commit is contained in:
kappa118 2025-03-01 19:02:21 -05:00
parent c1efb0004d
commit 9c84b65302
10 changed files with 430 additions and 0 deletions

View file

@ -0,0 +1,47 @@
# Generated by Django 5.1.6 on 2025-03-02 00:01
import django.contrib.auth.models
import django.contrib.auth.validators
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('channels', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='User',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('avatar_config', models.JSONField(blank=True, default=dict, null=True)),
('channel_groups', models.ManyToManyField(blank=True, related_name='users', to='channels.channelgroup')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]

View file

@ -0,0 +1,61 @@
# Generated by Django 5.1.6 on 2025-03-02 00:01
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('core', '0001_initial'),
('m3u', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='ChannelGroup',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, unique=True)),
],
),
migrations.CreateModel(
name='Stream',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='Default Stream', max_length=255)),
('url', models.URLField()),
('custom_url', models.URLField(blank=True, max_length=2000, null=True)),
('logo_url', models.URLField(blank=True, max_length=2000, null=True)),
('tvg_id', models.CharField(blank=True, max_length=255, null=True)),
('local_file', models.FileField(blank=True, null=True, upload_to='uploads/')),
('current_viewers', models.PositiveIntegerField(default=0)),
('updated_at', models.DateTimeField(auto_now=True)),
('group_name', models.CharField(blank=True, max_length=255, null=True)),
('m3u_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='streams', to='m3u.m3uaccount')),
('stream_profile', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='streams', to='core.streamprofile')),
],
options={
'verbose_name': 'Stream',
'verbose_name_plural': 'Streams',
'ordering': ['-updated_at'],
},
),
migrations.CreateModel(
name='Channel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('channel_number', models.IntegerField()),
('channel_name', models.CharField(max_length=255)),
('logo_url', models.URLField(blank=True, max_length=2000, null=True)),
('logo_file', models.ImageField(blank=True, null=True, upload_to='logos/')),
('tvg_id', models.CharField(blank=True, max_length=255, null=True)),
('tvg_name', models.CharField(blank=True, max_length=255, null=True)),
('stream_profile', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='channels', to='core.streamprofile')),
('channel_group', models.ForeignKey(blank=True, help_text='Channel group this channel belongs to.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='channels', to='channels.channelgroup')),
('streams', models.ManyToManyField(blank=True, related_name='channels', to='channels.stream')),
],
),
]

View file

@ -0,0 +1,46 @@
# Generated by Django 5.1.6 on 2025-03-02 00:01
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Settings',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('server_name', models.CharField(default='Dispatcharr', max_length=255)),
('time_zone', models.CharField(default='UTC', max_length=50)),
('default_logo_url', models.URLField(blank=True, null=True)),
('max_concurrent_streams', models.PositiveIntegerField(default=10)),
('auto_backup_frequency', models.CharField(choices=[('daily', 'Daily'), ('weekly', 'Weekly'), ('monthly', 'Monthly')], default='weekly', max_length=50)),
('enable_debug_logs', models.BooleanField(default=False)),
('schedules_direct_username', models.CharField(blank=True, max_length=255, null=True)),
('schedules_direct_password', models.CharField(blank=True, max_length=255, null=True)),
('schedules_direct_update_frequency', models.CharField(choices=[('12h', 'Every 12 Hours'), ('daily', 'Daily')], default='daily', max_length=50)),
('schedules_direct_api_key', models.CharField(blank=True, max_length=255, null=True)),
('transcoding_bitrate', models.PositiveIntegerField(default=2000)),
('transcoding_audio_codec', models.CharField(choices=[('aac', 'AAC'), ('mp3', 'MP3')], default='aac', max_length=50)),
('transcoding_resolution', models.CharField(choices=[('720p', '720p'), ('1080p', '1080p')], default='1080p', max_length=50)),
('failover_behavior', models.CharField(choices=[('sequential', 'Sequential'), ('random', 'Random')], default='sequential', max_length=50)),
('stream_health_check_frequency', models.PositiveIntegerField(default=5)),
('email_notifications', models.BooleanField(default=False)),
('webhook_url', models.URLField(blank=True, null=True)),
('cpu_alert_threshold', models.PositiveIntegerField(default=90)),
('memory_alert_threshold', models.PositiveIntegerField(default=90)),
('hdhr_integration', models.BooleanField(default=True)),
('custom_api_endpoints', models.JSONField(blank=True, null=True)),
('backup_path', models.CharField(default='backups/', max_length=255)),
('backup_frequency', models.CharField(choices=[('daily', 'Daily'), ('weekly', 'Weekly'), ('monthly', 'Monthly')], default='weekly', max_length=50)),
('ffmpeg_path', models.CharField(default='/usr/bin/ffmpeg', max_length=255)),
('custom_transcoding_flags', models.TextField(blank=True, null=True)),
('celery_worker_concurrency', models.PositiveIntegerField(default=4)),
],
),
]

View file

@ -0,0 +1,47 @@
# Generated by Django 5.1.6 on 2025-03-02 00:01
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='EPGData',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('tvg_id', models.CharField(blank=True, max_length=255, null=True)),
('channel_name', models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name='EPGSource',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
('source_type', models.CharField(choices=[('xmltv', 'XMLTV URL'), ('schedules_direct', 'Schedules Direct API')], max_length=20)),
('url', models.URLField(blank=True, null=True)),
('api_key', models.CharField(blank=True, max_length=255, null=True)),
('is_active', models.BooleanField(default=True)),
],
),
migrations.CreateModel(
name='ProgramData',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('start_time', models.DateTimeField()),
('end_time', models.DateTimeField()),
('title', models.CharField(max_length=255)),
('sub_title', models.CharField(blank=True, max_length=255, null=True)),
('description', models.TextField(blank=True, null=True)),
('tvg_id', models.CharField(blank=True, max_length=255, null=True)),
('epg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='programs', to='epg.epgdata')),
],
),
]

View file

@ -0,0 +1,23 @@
# Generated by Django 5.1.6 on 2025-03-02 00:01
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='HDHRDevice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('friendly_name', models.CharField(default='Dispatcharr HDHomeRun', max_length=100)),
('device_id', models.CharField(max_length=32, unique=True)),
('tuner_count', models.PositiveIntegerField(default=3)),
],
),
]

View file

@ -0,0 +1,65 @@
# Generated by Django 5.1.6 on 2025-03-02 00:01
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('core', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='ServerGroup',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Unique name for this server group.', max_length=100, unique=True)),
],
),
migrations.CreateModel(
name='M3UAccount',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Unique name for this M3U account', max_length=255, unique=True)),
('server_url', models.URLField(blank=True, help_text='The base URL of the M3U server (optional if a file is uploaded)', null=True)),
('uploaded_file', models.FileField(blank=True, null=True, upload_to='m3u_uploads/')),
('max_streams', models.PositiveIntegerField(default=0, help_text='Maximum number of concurrent streams (0 for unlimited)')),
('is_active', models.BooleanField(default=True, help_text='Set to false to deactivate this M3U account')),
('created_at', models.DateTimeField(auto_now_add=True, help_text='Time when this account was created')),
('updated_at', models.DateTimeField(auto_now=True, help_text='Time when this account was last updated')),
('user_agent', models.ForeignKey(blank=True, help_text='The User-Agent associated with this M3U account.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='m3u_accounts', to='core.useragent')),
('server_group', models.ForeignKey(blank=True, help_text='The server group this M3U account belongs to', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='m3u_accounts', to='m3u.servergroup')),
],
),
migrations.CreateModel(
name='M3UFilter',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('filter_type', models.CharField(choices=[('group', 'Group Title'), ('name', 'Stream Name')], default='group', help_text='Filter based on either group title or stream name.', max_length=50)),
('regex_pattern', models.CharField(help_text='A regex pattern to match streams or groups.', max_length=200)),
('exclude', models.BooleanField(default=True, help_text='If True, matching items are excluded; if False, only matches are included.')),
('m3u_account', models.ForeignKey(help_text='The M3U account this filter is applied to.', on_delete=django.db.models.deletion.CASCADE, related_name='filters', to='m3u.m3uaccount')),
],
),
migrations.CreateModel(
name='M3UAccountProfile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Name for the M3U account profile', max_length=255)),
('is_default', models.BooleanField(default=False, help_text='Set to false to deactivate this profile')),
('max_streams', models.PositiveIntegerField(default=0, help_text='Maximum number of concurrent streams (0 for unlimited)')),
('is_active', models.BooleanField(default=True, help_text='Set to false to deactivate this profile')),
('search_pattern', models.CharField(max_length=255)),
('replace_pattern', models.CharField(max_length=255)),
('current_viewers', models.PositiveIntegerField(default=0)),
('m3u_account', models.ForeignKey(help_text='The M3U account this profile belongs to.', on_delete=django.db.models.deletion.CASCADE, related_name='profiles', to='m3u.m3uaccount')),
],
options={
'constraints': [models.UniqueConstraint(fields=('m3u_account', 'name'), name='unique_account_profile_name')],
},
),
]

View file

@ -0,0 +1,46 @@
# Generated by Django 5.1.6 on 2025-03-02 00:01
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='CoreSettings',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('key', models.CharField(max_length=255, unique=True)),
('name', models.CharField(max_length=255)),
('value', models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name='StreamProfile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('profile_name', models.CharField(help_text='Name of the stream profile', max_length=255)),
('command', models.CharField(help_text="Command to execute (e.g., 'yt.sh', 'streamlink', or 'vlc')", max_length=255)),
('parameters', models.TextField(help_text='Command-line parameters. Use {userAgent} and {streamUrl} as placeholders.')),
('is_active', models.BooleanField(default=True, help_text='Whether this profile is active')),
('user_agent', models.CharField(blank=True, help_text='Optional user agent to use. If not set, you can fall back to a default.', max_length=512, null=True)),
],
),
migrations.CreateModel(
name='UserAgent',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('user_agent_name', models.CharField(help_text='The User-Agent name.', max_length=512, unique=True)),
('user_agent', models.CharField(help_text='The complete User-Agent string sent by the client.', max_length=512, unique=True)),
('description', models.CharField(blank=True, help_text='An optional description of the client or device type.', max_length=255)),
('is_active', models.BooleanField(default=True, help_text='Whether this user agent is currently allowed/recognized.')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
),
]

View file

@ -0,0 +1,36 @@
# Generated by Django 5.1.6 on 2025-03-01 14:01
from django.db import migrations
def preload_user_agent(apps, schema_editor):
UserAgent = apps.get_model("core", "UserAgent")
UserAgent.objects.create(
user_agent_name="TiviMate",
user_agent="TiviMate/5.16 (Android 12)",
description="",
is_active=True,
)
UserAgent.objects.create(
user_agent_name="VLC",
user_agent="VLC/3.0.21 LibVLC/3.0.21",
description="",
is_active=True,
)
UserAgent.objects.create(
user_agent_name="Chrome",
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.3",
description="",
is_active=True,
)
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
]
operations = [
migrations.RunPython(preload_user_agent),
]

View file

@ -0,0 +1,31 @@
# Generated by Django 5.1.6 on 2025-03-01 14:01
from django.db import migrations
def preload_stream_profiles(apps, schema_editor):
StreamProfile = apps.get_model("core", "StreamProfile")
StreamProfile.objects.create(
profile_name="ffmpeg",
command="ffmpeg",
parameters="-i {streamUrl} -c:v copy -c:a copy -f mpegts pipe:1",
is_active=True,
user_agent="1",
)
StreamProfile.objects.create(
profile_name="streamlink",
command="streamlink",
parameters="{streamUrl} best --stdout",
is_active=True,
user_agent="1",
)
class Migration(migrations.Migration):
dependencies = [
('core', '0002_preload_user_agents'),
]
operations = [
migrations.RunPython(preload_stream_profiles),
]

View file

@ -0,0 +1,28 @@
# Generated by Django 5.1.6 on 2025-03-01 14:01
from django.db import migrations
from django.utils.text import slugify
def preload_core_settings(apps, schema_editor):
CoreSettings = apps.get_model("core", "CoreSettings")
CoreSettings.objects.create(
key=slugify("Default Stream Profile"),
name="Default Stream Profile",
value=1,
)
CoreSettings.objects.create(
key=slugify("Default User-Agent"),
name="Default User-Agent",
value=1,
)
class Migration(migrations.Migration):
dependencies = [
('core', '0003_preload_stream_profiles'),
]
operations = [
migrations.RunPython(preload_core_settings),
]