From: Christian Heller Date: Sun, 24 Nov 2024 17:55:31 +0000 (+0100) Subject: Replace install.py by a short shell script. X-Git-Url: https://plomlompom.com/repos/%7B%7Bdb.prefix%7D%7D/te"st.html?a=commitdiff_plain;h=e7c42fa1b4826c32839bf16bf5f38b3c0bdde692;p=ytplom Replace install.py by a short shell script. --- diff --git a/install.py b/install.py deleted file mode 100755 index 991ef5f..0000000 --- a/install.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -'''Ensure expected directories, files for app to work exist.''' -from shutil import copyfile -from os import makedirs, scandir -from os.path import basename, join as path_join -from ytplom.misc import PATH_APP_DATA, PATH_MIGRATIONS, PATH_TEMPLATES - -for path in (PATH_APP_DATA, PATH_TEMPLATES, PATH_MIGRATIONS): - print(f'ensuring {path}') - makedirs(path) -for path_dir in (PATH_MIGRATIONS, PATH_TEMPLATES): - for entry in scandir(basename(path_dir)): - target_path = path_join(path_dir, basename(entry.path)) - print(f'copying {entry.path} to {target_path}') - copyfile(entry.path, target_path) -print('installation finished') diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..0661178 --- /dev/null +++ b/install.sh @@ -0,0 +1,7 @@ +#!/usr/bin/sh +set -e +set -x + +PATH_APP_SHARE=~/.local/share/ytplom +mkdir -p "${PATH_APP_SHARE}" +cp -r ./install_to_share/* "${PATH_APP_SHARE}/" diff --git a/install_to_share/migrations/init_0.sql b/install_to_share/migrations/init_0.sql new file mode 100644 index 0000000..5b45769 --- /dev/null +++ b/install_to_share/migrations/init_0.sql @@ -0,0 +1,32 @@ +CREATE TABLE yt_queries ( + id TEXT PRIMARY KEY, + text TEXT NOT NULL, + retrieved_at TEXT NOT NULL +); +CREATE TABLE yt_videos ( + id TEXT PRIMARY KEY, + title TEXT NOT NULL, + description TEXT NOT NULL, + published_at TEXT NOT NULL, + duration TEXT NOT NULL, + definition TEXT NOT NULL +); +CREATE TABLE yt_query_results ( + query_id TEXT NOT NULL, + video_id TEXT NOT NULL, + PRIMARY KEY (query_id, video_id), + FOREIGN KEY (query_id) REFERENCES yt_queries(id), + FOREIGN KEY (video_id) REFERENCES yt_videos(id) +); +CREATE TABLE quota_costs ( + id TEXT PRIMARY KEY, + timestamp TEXT NOT NULL, + cost INT NOT NULL +); +CREATE TABLE files ( + rel_path TEXT PRIMARY KEY, + yt_id TEXT NOT NULL DEFAULT "", + flags INTEGER NOT NULL DEFAULT 0, + FOREIGN KEY (yt_id) REFERENCES yt_videos(id) +); + diff --git a/install_to_share/templates/_base.tmpl b/install_to_share/templates/_base.tmpl new file mode 100644 index 0000000..8839067 --- /dev/null +++ b/install_to_share/templates/_base.tmpl @@ -0,0 +1,20 @@ +{% import '_macros.tmpl' as macros %} + + + + + + + + +{% block body %} +{% endblock %} + + diff --git a/install_to_share/templates/_macros.tmpl b/install_to_share/templates/_macros.tmpl new file mode 100644 index 0000000..12b28df --- /dev/null +++ b/install_to_share/templates/_macros.tmpl @@ -0,0 +1,13 @@ +{% macro _link_if(cond, target) %}{% if cond %}{% endif %}{{target}}{% if cond %}{% endif %}{% endmacro %} + + +{% macro nav_head(selected="") %} +

+{{ _link_if("playlist" != selected, "playlist") }} +· +{{ _link_if("videos" != selected, "videos") }} +· +{{ _link_if("queries" != selected, "queries") }} +

+
+{% endmacro %} diff --git a/install_to_share/templates/playlist.tmpl b/install_to_share/templates/playlist.tmpl new file mode 100644 index 0000000..58c2b5b --- /dev/null +++ b/install_to_share/templates/playlist.tmpl @@ -0,0 +1,61 @@ +{% extends '_base.tmpl' %} + + +{% block script %} +const RELOAD_INTERVAL_S = 10; +const PATH_LAST_UPDATE = '/_last_playlist_update.json'; +const MSG_SERVER_DOWN = 'Server seems to be unavailable.'; +const MSG_ERR_UNKNOWN = 'Unknown error checking ' + PATH_LAST_UPDATE; +const last_update = '{{last_update}}'; +async function keep_updated() { + try { + const response = await fetch(PATH_LAST_UPDATE); + const data = await response.json(); + if (data.last_update != last_update) { + location.reload(); + } + } catch(error) { + const status = document.getElementById('status'); + if (error instanceof TypeError && !error.response) { + status.innerText = MSG_SERVER_DOWN; + } else { + status.innerText = MSG_ERR_UNKNOWN; + } + } + setTimeout(keep_updated, RELOAD_INTERVAL_S * 1000); +} +window.onload = keep_updated; +{% endblock %} + + +{% block css %} +table { width: 100%; } +#status { text-align: center; font-weight: bold; } +td.history { width: 50%; } +{% endblock %} + + +{% block body %} +{{ macros.nav_head("playlist") }} + + +{% for prev_title, next_title in tuples %} + +{% endfor %} +
+{% if running %}{% if pause %}PAUSED{% else %}PLAYING{% endif %}{% else %}STOPPED{% endif %}:
+{{ current_title }}
+
+ + + + + +
+
+{{ prev_title }} + +{{ next_title }} +
+{% endblock %} + diff --git a/install_to_share/templates/queries.tmpl b/install_to_share/templates/queries.tmpl new file mode 100644 index 0000000..457f80e --- /dev/null +++ b/install_to_share/templates/queries.tmpl @@ -0,0 +1,22 @@ +{% extends '_base.tmpl' %} + + +{% block body %} +{{ macros.nav_head("queries") }} +

quota: {{quota_count}}/100000

+
+ +
+ + + + + +{% for query in queries %} + + + + +{% endfor %} +
retrieved atquery
{{query.retrieved_at[:19]}}{{query.text}}
+{% endblock %} diff --git a/install_to_share/templates/results.tmpl b/install_to_share/templates/results.tmpl new file mode 100644 index 0000000..131d14e --- /dev/null +++ b/install_to_share/templates/results.tmpl @@ -0,0 +1,23 @@ +{% extends '_base.tmpl' %} + + +{% block body %} +{{ macros.nav_head() }} +

query: {{query}}

+ +{% for video in videos %} + + + + + +{% endfor %} +
+ + +{{video.definition}}
+{{video.duration}} +
+{{video.title}} · {{video.description}} +
+{% endblock %} diff --git a/install_to_share/templates/video.tmpl b/install_to_share/templates/video.tmpl new file mode 100644 index 0000000..54d005f --- /dev/null +++ b/install_to_share/templates/video.tmpl @@ -0,0 +1,17 @@ +{% extends '_base.tmpl' %} + + +{% block body %} +{{ macros.nav_head() }} + + + + +
path:{{file.rel_path}}
YouTube ID:{{file.yt_id}}
present:{% if file.present %}yes{% else %}no{% endif %}
+
+{% for flag_name in flag_names %} +{{ flag_name }}:
+{% endfor %} + +
+{% endblock %} diff --git a/install_to_share/templates/videos.tmpl b/install_to_share/templates/videos.tmpl new file mode 100644 index 0000000..5cbf47f --- /dev/null +++ b/install_to_share/templates/videos.tmpl @@ -0,0 +1,12 @@ +{% extends '_base.tmpl' %} + + +{% block body %} +{{ macros.nav_head("videos") }} +

downloaded videos:

+ +{% endblock %} diff --git a/install_to_share/templates/yt_video.tmpl b/install_to_share/templates/yt_video.tmpl new file mode 100644 index 0000000..1ecb258 --- /dev/null +++ b/install_to_share/templates/yt_video.tmpl @@ -0,0 +1,23 @@ +{% extends '_base.tmpl' %} + + +{% block body %} +{{ macros.nav_head() }} + + + + + + + + + + + + +
title:{{video_data.title}}
thumbnail:
description:{{video_data.description}}
duration:{{video_data.duration}}
definition:{{video_data.definition}}
YouTube ID:{{video_data.id_}} (watch)
download:{% if is_temp %}working on it{% else %}{{ file_path if file_path else "please do" }}{% endif %}
linked queries: + +
+{% endblock %} diff --git a/migrations/init_0.sql b/migrations/init_0.sql deleted file mode 100644 index 5b45769..0000000 --- a/migrations/init_0.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE TABLE yt_queries ( - id TEXT PRIMARY KEY, - text TEXT NOT NULL, - retrieved_at TEXT NOT NULL -); -CREATE TABLE yt_videos ( - id TEXT PRIMARY KEY, - title TEXT NOT NULL, - description TEXT NOT NULL, - published_at TEXT NOT NULL, - duration TEXT NOT NULL, - definition TEXT NOT NULL -); -CREATE TABLE yt_query_results ( - query_id TEXT NOT NULL, - video_id TEXT NOT NULL, - PRIMARY KEY (query_id, video_id), - FOREIGN KEY (query_id) REFERENCES yt_queries(id), - FOREIGN KEY (video_id) REFERENCES yt_videos(id) -); -CREATE TABLE quota_costs ( - id TEXT PRIMARY KEY, - timestamp TEXT NOT NULL, - cost INT NOT NULL -); -CREATE TABLE files ( - rel_path TEXT PRIMARY KEY, - yt_id TEXT NOT NULL DEFAULT "", - flags INTEGER NOT NULL DEFAULT 0, - FOREIGN KEY (yt_id) REFERENCES yt_videos(id) -); - diff --git a/templates/_base.tmpl b/templates/_base.tmpl deleted file mode 100644 index 8839067..0000000 --- a/templates/_base.tmpl +++ /dev/null @@ -1,20 +0,0 @@ -{% import '_macros.tmpl' as macros %} - - - - - - - - -{% block body %} -{% endblock %} - - diff --git a/templates/_macros.tmpl b/templates/_macros.tmpl deleted file mode 100644 index 12b28df..0000000 --- a/templates/_macros.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -{% macro _link_if(cond, target) %}{% if cond %}{% endif %}{{target}}{% if cond %}{% endif %}{% endmacro %} - - -{% macro nav_head(selected="") %} -

-{{ _link_if("playlist" != selected, "playlist") }} -· -{{ _link_if("videos" != selected, "videos") }} -· -{{ _link_if("queries" != selected, "queries") }} -

-
-{% endmacro %} diff --git a/templates/playlist.tmpl b/templates/playlist.tmpl deleted file mode 100644 index 58c2b5b..0000000 --- a/templates/playlist.tmpl +++ /dev/null @@ -1,61 +0,0 @@ -{% extends '_base.tmpl' %} - - -{% block script %} -const RELOAD_INTERVAL_S = 10; -const PATH_LAST_UPDATE = '/_last_playlist_update.json'; -const MSG_SERVER_DOWN = 'Server seems to be unavailable.'; -const MSG_ERR_UNKNOWN = 'Unknown error checking ' + PATH_LAST_UPDATE; -const last_update = '{{last_update}}'; -async function keep_updated() { - try { - const response = await fetch(PATH_LAST_UPDATE); - const data = await response.json(); - if (data.last_update != last_update) { - location.reload(); - } - } catch(error) { - const status = document.getElementById('status'); - if (error instanceof TypeError && !error.response) { - status.innerText = MSG_SERVER_DOWN; - } else { - status.innerText = MSG_ERR_UNKNOWN; - } - } - setTimeout(keep_updated, RELOAD_INTERVAL_S * 1000); -} -window.onload = keep_updated; -{% endblock %} - - -{% block css %} -table { width: 100%; } -#status { text-align: center; font-weight: bold; } -td.history { width: 50%; } -{% endblock %} - - -{% block body %} -{{ macros.nav_head("playlist") }} - - -{% for prev_title, next_title in tuples %} - -{% endfor %} -
-{% if running %}{% if pause %}PAUSED{% else %}PLAYING{% endif %}{% else %}STOPPED{% endif %}:
-{{ current_title }}
-
- - - - - -
-
-{{ prev_title }} - -{{ next_title }} -
-{% endblock %} - diff --git a/templates/queries.tmpl b/templates/queries.tmpl deleted file mode 100644 index 457f80e..0000000 --- a/templates/queries.tmpl +++ /dev/null @@ -1,22 +0,0 @@ -{% extends '_base.tmpl' %} - - -{% block body %} -{{ macros.nav_head("queries") }} -

quota: {{quota_count}}/100000

-
- -
- - - - - -{% for query in queries %} - - - - -{% endfor %} -
retrieved atquery
{{query.retrieved_at[:19]}}{{query.text}}
-{% endblock %} diff --git a/templates/results.tmpl b/templates/results.tmpl deleted file mode 100644 index 131d14e..0000000 --- a/templates/results.tmpl +++ /dev/null @@ -1,23 +0,0 @@ -{% extends '_base.tmpl' %} - - -{% block body %} -{{ macros.nav_head() }} -

query: {{query}}

- -{% for video in videos %} - - - - - -{% endfor %} -
- - -{{video.definition}}
-{{video.duration}} -
-{{video.title}} · {{video.description}} -
-{% endblock %} diff --git a/templates/video.tmpl b/templates/video.tmpl deleted file mode 100644 index 54d005f..0000000 --- a/templates/video.tmpl +++ /dev/null @@ -1,17 +0,0 @@ -{% extends '_base.tmpl' %} - - -{% block body %} -{{ macros.nav_head() }} - - - - -
path:{{file.rel_path}}
YouTube ID:{{file.yt_id}}
present:{% if file.present %}yes{% else %}no{% endif %}
-
-{% for flag_name in flag_names %} -{{ flag_name }}:
-{% endfor %} - -
-{% endblock %} diff --git a/templates/videos.tmpl b/templates/videos.tmpl deleted file mode 100644 index 5cbf47f..0000000 --- a/templates/videos.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -{% extends '_base.tmpl' %} - - -{% block body %} -{{ macros.nav_head("videos") }} -

downloaded videos:

- -{% endblock %} diff --git a/templates/yt_video.tmpl b/templates/yt_video.tmpl deleted file mode 100644 index 1ecb258..0000000 --- a/templates/yt_video.tmpl +++ /dev/null @@ -1,23 +0,0 @@ -{% extends '_base.tmpl' %} - - -{% block body %} -{{ macros.nav_head() }} - - - - - - - - - - - - -
title:{{video_data.title}}
thumbnail:
description:{{video_data.description}}
duration:{{video_data.duration}}
definition:{{video_data.definition}}
YouTube ID:{{video_data.id_}} (watch)
download:{% if is_temp %}working on it{% else %}{{ file_path if file_path else "please do" }}{% endif %}
linked queries: - -
-{% endblock %} diff --git a/ytplom/misc.py b/ytplom/misc.py index 9e46c82..647ad39 100644 --- a/ytplom/misc.py +++ b/ytplom/misc.py @@ -82,9 +82,6 @@ QUOTA_COST_YOUTUBE_DETAILS = QuotaCost(1) # local expectations TIMESTAMP_FMT = '%Y-%m-%d %H:%M:%S.%f' LEGAL_EXTENSIONS = {'webm', 'mp4', 'mkv'} -VIDEO_FLAGS: dict[FlagName, FlagsInt] = { - FlagName('delete'): FlagsInt(1 << 62) -} # tables to create database with EXPECTED_DB_VERSION = 0 @@ -93,6 +90,12 @@ PATH_MIGRATIONS = PathStr(path_join(PATH_APP_DATA, 'migrations')) PATH_DB_SCHEMA = PathStr(path_join(PATH_MIGRATIONS, f'init_{EXPECTED_DB_VERSION}.sql')) +# other +NAME_INSTALLER = 'install.sh' +VIDEO_FLAGS: dict[FlagName, FlagsInt] = { + FlagName('delete'): FlagsInt(1 << 62) +} + class NotFoundException(Exception): """Raise on expected data missing, e.g. DB fetches finding nothing.""" @@ -126,7 +129,7 @@ class DatabaseConnection: if not isdir(path_db_dir): raise NotFoundException( f'cannot find {path_db_dir} as directory to put DB ' - 'into, did you run install.py?') + f'into, did you run {NAME_INSTALLER}?') with sql_connect(self._path) as conn: with open(PATH_DB_SCHEMA, 'r', encoding='utf8') as f: conn.executescript(f.read())