Initial commit
This commit is contained in:
commit
e86ab53de5
35 changed files with 2638 additions and 0 deletions
3
app/models/__init__.py
Normal file
3
app/models/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
"""
|
||||
Models package for Podcastrr.
|
||||
"""
|
26
app/models/database.py
Normal file
26
app/models/database.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
"""
|
||||
Database configuration for Podcastrr.
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
import sqlalchemy.orm as sa_orm
|
||||
|
||||
# Add compatibility for older SQLAlchemy versions
|
||||
if not hasattr(sa_orm, 'DeclarativeBase'):
|
||||
# Create a class that mimics DeclarativeBase for SQLAlchemy 1.4
|
||||
class DeclarativeBase:
|
||||
pass
|
||||
# Monkey-patch sqlalchemy.orm
|
||||
sa_orm.DeclarativeBase = DeclarativeBase
|
||||
|
||||
if not hasattr(sa_orm, 'DeclarativeBaseNoMeta'):
|
||||
# Create a class that mimics DeclarativeBaseNoMeta for SQLAlchemy 1.4
|
||||
class DeclarativeBaseNoMeta:
|
||||
pass
|
||||
# Monkey-patch sqlalchemy.orm
|
||||
sa_orm.DeclarativeBaseNoMeta = DeclarativeBaseNoMeta
|
||||
|
||||
# Now import Flask-SQLAlchemy
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
# Create SQLAlchemy instance
|
||||
db = SQLAlchemy()
|
89
app/models/podcast.py
Normal file
89
app/models/podcast.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
"""
|
||||
Podcast and Episode models for Podcastrr.
|
||||
"""
|
||||
from datetime import datetime
|
||||
from app.models.database import db
|
||||
|
||||
class Podcast(db.Model):
|
||||
"""
|
||||
Model representing a podcast.
|
||||
"""
|
||||
__tablename__ = 'podcasts'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
title = db.Column(db.String(255), nullable=False)
|
||||
author = db.Column(db.String(255))
|
||||
description = db.Column(db.Text)
|
||||
image_url = db.Column(db.String(512))
|
||||
feed_url = db.Column(db.String(512), nullable=False, unique=True)
|
||||
external_id = db.Column(db.String(255), unique=True)
|
||||
last_updated = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
last_checked = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
auto_download = db.Column(db.Boolean, default=False)
|
||||
|
||||
# Relationships
|
||||
episodes = db.relationship('Episode', backref='podcast', lazy='dynamic', cascade='all, delete-orphan')
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Podcast {self.title}>'
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Convert podcast to dictionary for API responses.
|
||||
"""
|
||||
return {
|
||||
'id': self.id,
|
||||
'title': self.title,
|
||||
'author': self.author,
|
||||
'description': self.description,
|
||||
'image_url': self.image_url,
|
||||
'feed_url': self.feed_url,
|
||||
'external_id': self.external_id,
|
||||
'last_updated': self.last_updated.isoformat() if self.last_updated else None,
|
||||
'last_checked': self.last_checked.isoformat() if self.last_checked else None,
|
||||
'auto_download': self.auto_download,
|
||||
'episode_count': self.episodes.count()
|
||||
}
|
||||
|
||||
class Episode(db.Model):
|
||||
"""
|
||||
Model representing a podcast episode.
|
||||
"""
|
||||
__tablename__ = 'episodes'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
podcast_id = db.Column(db.Integer, db.ForeignKey('podcasts.id'), nullable=False)
|
||||
title = db.Column(db.String(255), nullable=False)
|
||||
description = db.Column(db.Text)
|
||||
audio_url = db.Column(db.String(512), nullable=False)
|
||||
image_url = db.Column(db.String(512))
|
||||
published_date = db.Column(db.DateTime)
|
||||
duration = db.Column(db.Integer) # Duration in seconds
|
||||
file_size = db.Column(db.Integer) # Size in bytes
|
||||
episode_number = db.Column(db.String(50))
|
||||
guid = db.Column(db.String(512), unique=True)
|
||||
downloaded = db.Column(db.Boolean, default=False)
|
||||
file_path = db.Column(db.String(512))
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Episode {self.title}>'
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Convert episode to dictionary for API responses.
|
||||
"""
|
||||
return {
|
||||
'id': self.id,
|
||||
'podcast_id': self.podcast_id,
|
||||
'title': self.title,
|
||||
'description': self.description,
|
||||
'audio_url': self.audio_url,
|
||||
'image_url': self.image_url,
|
||||
'published_date': self.published_date.isoformat() if self.published_date else None,
|
||||
'duration': self.duration,
|
||||
'file_size': self.file_size,
|
||||
'episode_number': self.episode_number,
|
||||
'guid': self.guid,
|
||||
'downloaded': self.downloaded,
|
||||
'file_path': self.file_path
|
||||
}
|
33
app/models/settings.py
Normal file
33
app/models/settings.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
Settings model for Podcastrr.
|
||||
"""
|
||||
from app.models.database import db
|
||||
|
||||
class Settings(db.Model):
|
||||
"""
|
||||
Model representing application settings.
|
||||
"""
|
||||
__tablename__ = 'settings'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
download_path = db.Column(db.String(512), nullable=False)
|
||||
naming_format = db.Column(db.String(255), nullable=False, default="{podcast_title}/{episode_title}")
|
||||
auto_download = db.Column(db.Boolean, default=False)
|
||||
max_downloads = db.Column(db.Integer, default=5)
|
||||
delete_after_days = db.Column(db.Integer, default=30)
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Settings id={self.id}>'
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Convert settings to dictionary for API responses.
|
||||
"""
|
||||
return {
|
||||
'id': self.id,
|
||||
'download_path': self.download_path,
|
||||
'naming_format': self.naming_format,
|
||||
'auto_download': self.auto_download,
|
||||
'max_downloads': self.max_downloads,
|
||||
'delete_after_days': self.delete_after_days
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue