Add autorefresh to Channel to include/exclude in refresh_all loop.

This commit is contained in:
voussoir 2021-09-05 01:26:34 -07:00
parent 0418cae57a
commit 6068d644b9
No known key found for this signature in database
GPG key ID: 5F7554F8C26DACCB
8 changed files with 112 additions and 8 deletions

View file

@ -159,6 +159,20 @@ def post_set_automark(channel_id):
return flasktools.make_json_response({}) return flasktools.make_json_response({})
@flasktools.required_fields(['autorefresh'], forbid_whitespace=True)
@site.route('/channel/<channel_id>/set_autorefresh', methods=['POST'])
def post_set_autorefresh(channel_id):
autorefresh = request.form['autorefresh']
channel = common.ycdldb.get_channel(channel_id)
try:
autorefresh = stringtools.truthystring(autorefresh)
channel.set_autorefresh(autorefresh)
except (ValueError, TypeError):
flask.abort(400)
return flasktools.make_json_response({})
@site.route('/channel/<channel_id>/set_download_directory', methods=['POST']) @site.route('/channel/<channel_id>/set_download_directory', methods=['POST'])
def post_set_download_directory(channel_id): def post_set_download_directory(channel_id):
download_directory = request.form['download_directory'] download_directory = request.form['download_directory']

View file

@ -43,6 +43,14 @@ function set_automark(channel_id, state, callback)
return common.post(url, data, callback); return common.post(url, data, callback);
} }
api.channels.set_autorefresh =
function set_autorefresh(channel_id, autorefresh, callback)
{
const url = `/channel/${channel_id}/set_autorefresh`;
const data = {"autorefresh": autorefresh};
return common.post(url, data, callback);
}
api.channels.set_download_directory = api.channels.set_download_directory =
function set_download_directory(channel_id, download_directory, callback) function set_download_directory(channel_id, download_directory, callback)
{ {

View file

@ -259,6 +259,11 @@ https://stackoverflow.com/a/35153397
</div> <!-- tab-videos --> </div> <!-- tab-videos -->
<div class="tab" data-tab-title="Settings"> <div class="tab" data-tab-title="Settings">
<div>
<label><input type="checkbox" id="set_autorefresh_checkbox" {{"checked" if channel.autorefresh else ""}} onchange="return set_autorefresh_form(event);"/> Automatically refresh this channel regularly.</label>
<span id="set_autorefresh_spinner" class="hidden">Working...</span>
</div>
<div> <div>
New videos are: New videos are:
<select onchange="return set_automark_form(event);"> <select onchange="return set_automark_form(event);">
@ -615,6 +620,21 @@ function set_automark_callback(response)
set_automark_spinner.hide(); set_automark_spinner.hide();
} }
function set_autorefresh_form(event)
{
set_autorefresh_spinner.show();
api.channels.set_autorefresh(CHANNEL_ID, event.target.checked, set_autorefresh_callback);
}
function set_autorefresh_callback(response)
{
if (response.meta.status != 200)
{
alert(JSON.stringify(response));
}
set_autorefresh_spinner.hide();
}
function set_download_directory_form(event) function set_download_directory_form(event)
{ {
const download_directory = set_download_directory_input.value.trim(); const download_directory = set_download_directory_input.value.trim();
@ -653,6 +673,9 @@ if (CHANNEL_ID)
var set_automark_spinner = document.getElementById("set_automark_spinner"); var set_automark_spinner = document.getElementById("set_automark_spinner");
set_automark_spinner = new spinner.Spinner(set_automark_spinner); set_automark_spinner = new spinner.Spinner(set_automark_spinner);
var set_autorefresh_spinner = document.getElementById("set_autorefresh_spinner");
set_autorefresh_spinner = new spinner.Spinner(set_autorefresh_spinner);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View file

@ -63,7 +63,10 @@
{% endif %} {% endif %}
<a href="/channel/{{channel.id}}">{{channel.name}}</a> <a href="/channel/{{channel.id}}/pending">(p)</a> <a href="/channel/{{channel.id}}">{{channel.name}}</a> <a href="/channel/{{channel.id}}/pending">(p)</a>
{% if channel.automark not in [none, "pending"] %} {% if channel.automark not in [none, "pending"] %}
<span>automark: {{channel.automark}}</span> <span>(automark: {{channel.automark}})</span>
{% endif %}
{% if not channel.autorefresh %}
<span>(autorefresh: no)</span>
{% endif %} {% endif %}
</div> </div>
{% endfor %} {% endfor %}

View file

@ -284,6 +284,37 @@ def upgrade_8_to_9(ycdldb):
m.go() m.go()
def upgrade_9_to_10(ycdldb):
'''
In this version, the `autorefresh` column was added to the channels table.
'''
m = Migrator(ycdldb)
m.tables['channels']['create'] = '''
CREATE TABLE IF NOT EXISTS channels(
id TEXT,
name TEXT,
uploads_playlist TEXT,
download_directory TEXT COLLATE NOCASE,
queuefile_extension TEXT COLLATE NOCASE,
automark TEXT,
autorefresh INT
);
'''
m.tables['channels']['transfer'] = '''
INSERT INTO channels SELECT
id,
name,
uploads_playlist,
download_directory,
queuefile_extension,
automark,
1
FROM channels_old;
'''
m.go()
def upgrade_all(data_directory): def upgrade_all(data_directory):
''' '''
Given the directory containing a ycdl database, apply all of the Given the directory containing a ycdl database, apply all of the

View file

@ -1,6 +1,6 @@
from voussoirkit import sqlhelpers from voussoirkit import sqlhelpers
DATABASE_VERSION = 9 DATABASE_VERSION = 10
DB_VERSION_PRAGMA = f''' DB_VERSION_PRAGMA = f'''
PRAGMA user_version = {DATABASE_VERSION}; PRAGMA user_version = {DATABASE_VERSION};
''' '''
@ -21,7 +21,8 @@ CREATE TABLE IF NOT EXISTS channels(
uploads_playlist TEXT, uploads_playlist TEXT,
download_directory TEXT COLLATE NOCASE, download_directory TEXT COLLATE NOCASE,
queuefile_extension TEXT COLLATE NOCASE, queuefile_extension TEXT COLLATE NOCASE,
automark TEXT automark TEXT,
autorefresh INT
); );
CREATE TABLE IF NOT EXISTS videos( CREATE TABLE IF NOT EXISTS videos(
id TEXT, id TEXT,

View file

@ -2,6 +2,7 @@ import datetime
import typing import typing
from voussoirkit import pathclass from voussoirkit import pathclass
from voussoirkit import stringtools
from . import constants from . import constants
from . import exceptions from . import exceptions
@ -42,6 +43,7 @@ class Channel(Base):
) )
self.queuefile_extension = self.normalize_queuefile_extension(db_row['queuefile_extension']) self.queuefile_extension = self.normalize_queuefile_extension(db_row['queuefile_extension'])
self.automark = db_row['automark'] or 'pending' self.automark = db_row['automark'] or 'pending'
self.autorefresh = stringtools.truthystring(db_row['autorefresh'])
def __repr__(self): def __repr__(self):
return f'Channel:{self.id}' return f'Channel:{self.id}'
@ -204,6 +206,25 @@ class Channel(Base):
if commit: if commit:
self.ycdldb.commit() self.ycdldb.commit()
def set_autorefresh(self, autorefresh, commit=True):
if isinstance(autorefresh, int):
if autorefresh not in {0, 1}:
raise ValueError(f'autorefresh should be a boolean, not {autorefresh}.')
autorefresh = bool(autorefresh)
if not isinstance(autorefresh, bool):
raise TypeError(f'autorefresh should be a boolean, not {autorefresh}.')
pairs = {
'id': self.id,
'autorefresh': autorefresh,
}
self.ycdldb.sql_update(table='channels', pairs=pairs, where_key='id')
self.autorefresh = autorefresh
if commit:
self.ycdldb.commit()
def set_download_directory(self, download_directory, commit=True): def set_download_directory(self, download_directory, commit=True):
download_directory = self.normalize_download_directory(download_directory) download_directory = self.normalize_download_directory(download_directory)

View file

@ -146,7 +146,8 @@ class YCDLDBChannelMixin:
'uploads_playlist': self.youtube.get_user_uploads_playlist_id(channel_id), 'uploads_playlist': self.youtube.get_user_uploads_playlist_id(channel_id),
'download_directory': download_directory.absolute_path if download_directory else None, 'download_directory': download_directory.absolute_path if download_directory else None,
'queuefile_extension': queuefile_extension, 'queuefile_extension': queuefile_extension,
'automark': "pending", 'automark': 'pending',
'autorefresh': True,
} }
self.sql_insert(table='channels', data=data) self.sql_insert(table='channels', data=data)
@ -169,7 +170,7 @@ class YCDLDBChannelMixin:
def get_channels_by_sql(self, query, bindings=None): def get_channels_by_sql(self, query, bindings=None):
return self.get_things_by_sql('channel', query, bindings) return self.get_things_by_sql('channel', query, bindings)
def _rss_assisted_refresh(self, skip_failures=False, commit=True): def _rss_assisted_refresh(self, channels, skip_failures=False, commit=True):
''' '''
Youtube provides RSS feeds for every channel. These feeds do not Youtube provides RSS feeds for every channel. These feeds do not
require the API token and seem to have generous ratelimits, or require the API token and seem to have generous ratelimits, or
@ -216,7 +217,7 @@ class YCDLDBChannelMixin:
) )
traditional(channel) traditional(channel)
new_ids = (id for channel in self.get_channels() for id in assisted(channel)) new_ids = (id for channel in channels for id in assisted(channel))
for video in self.youtube.get_videos(new_ids): for video in self.youtube.get_videos(new_ids):
self.ingest_video(video, commit=False) self.ingest_video(video, commit=False)
@ -235,11 +236,13 @@ class YCDLDBChannelMixin:
): ):
self.log.info('Refreshing all channels.') self.log.info('Refreshing all channels.')
channels = self.get_channels_by_sql('SELECT * FROM channels WHERE autorefresh == 1')
if rss_assisted and not force: if rss_assisted and not force:
return self._rss_assisted_refresh(skip_failures=skip_failures, commit=commit) return self._rss_assisted_refresh(channels, skip_failures=skip_failures, commit=commit)
excs = [] excs = []
for channel in self.get_channels(): for channel in channels:
try: try:
channel.refresh(force=force, commit=commit) channel.refresh(force=force, commit=commit)
except Exception as exc: except Exception as exc: