wrolpi/modules/videos/channel/lib.py
Roland 9b899f6fc0
A new start
Signed-off-by: Roland <roland@learningselfreliance.com>
2021-11-01 16:43:09 -06:00

168 lines
5.3 KiB
Python

from typing import List, Dict
from sqlalchemy.orm.exc import NoResultFound
from wrolpi.common import sanitize_link, run_after, get_relative_to_media_directory, make_media_directory
from wrolpi.db import get_db_session, get_db_curs
from wrolpi.errors import UnknownChannel, UnknownDirectory, APIError, ValidationError
from ..common import check_for_channel_conflicts
from ..lib import save_channels_config
from ..models import Channel
DEFAULT_DOWNLOAD_FREQUENCY = 60 * 60 * 24 * 7 # weekly
DEFAULT_DOWNLOAD_TIMEOUT = 60.0 * 10.0 # Ten minutes
async def get_minimal_channels() -> List[dict]:
"""
Get the minimum amount of information necessary about all channels.
"""
with get_db_curs() as curs:
# Get all channels, even if they don't have videos.
stmt = '''
SELECT
c.id, name, link, directory, url, download_frequency, info_date, next_download
FROM
channel AS c
ORDER BY LOWER(name)
'''
curs.execute(stmt)
channels = list(map(dict, curs.fetchall()))
video_counts = await get_channels_video_count()
for channel in channels:
channel_id = channel['id']
channel['video_count'] = video_counts[channel_id]
return channels
async def get_channels_video_count() -> Dict[int, int]:
"""
Add video counts to all channels
"""
with get_db_curs() as curs:
stmt = 'SELECT id FROM channel'
curs.execute(stmt)
# Get all channel IDs, start them with a count of 0.
video_counts = {int(i['id']): 0 for i in curs.fetchall()}
stmt = '''
SELECT
c.id, COUNT(v.id) AS video_count
FROM
channel AS c
LEFT JOIN video AS v ON v.channel_id = c.id
WHERE
v.video_path IS NOT NULL
GROUP BY 1
'''
curs.execute(stmt)
# Replace all the counts of those channels with videos.
video_counts.update({int(i['id']): int(i['video_count']) for i in curs.fetchall()})
return video_counts
@run_after(save_channels_config)
def delete_channel(link):
with get_db_session(commit=True) as session:
try:
channel = session.query(Channel).filter_by(link=link).one()
except NoResultFound:
raise UnknownChannel()
channel.delete_with_videos()
@run_after(save_channels_config)
def update_channel(data, link):
with get_db_session(commit=True) as session:
try:
channel = session.query(Channel).filter_by(link=link).one()
except NoResultFound:
raise UnknownChannel()
# Only update directory if it was empty
if data.get('directory') and not channel.directory:
try:
data['directory'] = get_relative_to_media_directory(data['directory'])
except UnknownDirectory:
if data['mkdir']:
make_media_directory(data['directory'])
data['directory'] = get_relative_to_media_directory(data['directory'])
else:
raise
if 'directory' in data:
data['directory'] = str(data['directory'])
if 'download_frequency' in data:
try:
data['download_frequency'] = int(data['download_frequency'])
except ValueError:
raise APIError('Invalid download frequency')
if data.get('match_regex') in ('None', 'null'):
data['match_regex'] = None
# Verify that the URL/Name/Link aren't taken
check_for_channel_conflicts(
session,
id_=channel.id,
url=data.get('url'),
name=data.get('name'),
link=data.get('link'),
directory=data.get('directory'),
)
# Apply the changes now that we've OK'd them
channel.update(data)
return channel
def get_channel(link) -> dict:
"""
Get a Channel by it's `link`. Raise UnknownChannel if it does not exist.
"""
with get_db_session() as session:
try:
channel = session.query(Channel).filter_by(link=link).one()
except NoResultFound:
raise UnknownChannel()
return channel.dict()
@run_after(save_channels_config)
def create_channel(data: dict) -> dict:
"""
Create a new Channel. Check for conflicts with existing Channels.
"""
with get_db_session(commit=True) as session:
try:
# Verify that the URL/Name/Link aren't taken
check_for_channel_conflicts(
session,
url=data.get('url'),
name=data['name'],
link=sanitize_link(data['name']),
directory=str(data['directory']),
)
except APIError as e:
raise ValidationError() from e
channel = Channel(
name=data['name'],
url=data.get('url'),
match_regex=data.get('match_regex'),
link=sanitize_link(data['name']),
directory=str(data['directory']),
download_frequency=data.get('download_frequency', DEFAULT_DOWNLOAD_FREQUENCY),
)
session.add(channel)
session.commit()
session.flush()
session.refresh(channel)
return channel.dict()