home · contact · privacy
Replace install.py by a short shell script.
authorChristian Heller <c.heller@plomlompom.de>
Sun, 24 Nov 2024 17:55:31 +0000 (18:55 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Sun, 24 Nov 2024 17:55:31 +0000 (18:55 +0100)
21 files changed:
install.py [deleted file]
install.sh [new file with mode: 0755]
install_to_share/migrations/init_0.sql [new file with mode: 0644]
install_to_share/templates/_base.tmpl [new file with mode: 0644]
install_to_share/templates/_macros.tmpl [new file with mode: 0644]
install_to_share/templates/playlist.tmpl [new file with mode: 0644]
install_to_share/templates/queries.tmpl [new file with mode: 0644]
install_to_share/templates/results.tmpl [new file with mode: 0644]
install_to_share/templates/video.tmpl [new file with mode: 0644]
install_to_share/templates/videos.tmpl [new file with mode: 0644]
install_to_share/templates/yt_video.tmpl [new file with mode: 0644]
migrations/init_0.sql [deleted file]
templates/_base.tmpl [deleted file]
templates/_macros.tmpl [deleted file]
templates/playlist.tmpl [deleted file]
templates/queries.tmpl [deleted file]
templates/results.tmpl [deleted file]
templates/video.tmpl [deleted file]
templates/videos.tmpl [deleted file]
templates/yt_video.tmpl [deleted file]
ytplom/misc.py

diff --git a/install.py b/install.py
deleted file mode 100755 (executable)
index 991ef5f..0000000
+++ /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 (executable)
index 0000000..0661178
--- /dev/null
@@ -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 (file)
index 0000000..5b45769
--- /dev/null
@@ -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 (file)
index 0000000..8839067
--- /dev/null
@@ -0,0 +1,20 @@
+{% import '_macros.tmpl' as macros %}
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+{% block script %}
+{% endblock %}
+</script>
+<style>
+body { background-color: #aaaa00; }
+{% block css %}
+{% endblock %}
+</style>
+</head>
+<body>
+{% block body %}
+{% endblock %}
+</body>
+</html>
diff --git a/install_to_share/templates/_macros.tmpl b/install_to_share/templates/_macros.tmpl
new file mode 100644 (file)
index 0000000..12b28df
--- /dev/null
@@ -0,0 +1,13 @@
+{% macro _link_if(cond, target) %}{% if cond %}<a href="/{{target}}">{% endif %}{{target}}{% if cond %}</a>{% endif %}{% endmacro %}
+
+
+{% macro nav_head(selected="") %}
+<p>
+{{ _link_if("playlist" != selected, "playlist") }}
+{{ _link_if("videos" != selected, "videos") }}
+{{ _link_if("queries" != selected, "queries") }}
+</p>
+<hr />
+{% endmacro %}
diff --git a/install_to_share/templates/playlist.tmpl b/install_to_share/templates/playlist.tmpl
new file mode 100644 (file)
index 0000000..58c2b5b
--- /dev/null
@@ -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") }}
+<table>
+<tr><td id="status" colspan=2>
+{% if running %}{% if pause %}PAUSED{% else %}PLAYING{% endif %}{% else %}STOPPED{% endif %}:<br />
+{{ current_title }}<br />
+<form action="/playlist" method="POST">
+<input type="submit" name="pause" autofocus value="{% if paused %}resume{% else %}pause{% endif %}">
+<input type="submit" name="prev" value="prev">
+<input type="submit" name="next" value="next">
+<input type="submit" name="stop" value="{% if running %}stop{% else %}start{% endif %}">
+<input type="submit" name="reload" value="reload">
+</form>
+</td></tr>
+{% for prev_title, next_title in tuples %}
+<tr><td class="history">
+{{ prev_title }}
+</td><td class="history">
+{{ next_title }}
+</td></tr>
+{% endfor %}
+</table>
+{% endblock %}
+
diff --git a/install_to_share/templates/queries.tmpl b/install_to_share/templates/queries.tmpl
new file mode 100644 (file)
index 0000000..457f80e
--- /dev/null
@@ -0,0 +1,22 @@
+{% extends '_base.tmpl' %}
+
+
+{% block body %}
+{{ macros.nav_head("queries") }}
+<p>quota: {{quota_count}}/100000</p>
+<form action="/queries" method="POST" />
+<input name="query" />
+</form>
+<table>
+<tr>
+<th>retrieved at</th>
+<th>query</th>
+</tr>
+{% for query in queries %}
+<tr>
+<td>{{query.retrieved_at[:19]}}</td>
+<td><a href="/query/{{query.id_}}">{{query.text}}</a></td>
+</tr>
+{% endfor %}
+</table>
+{% endblock %}
diff --git a/install_to_share/templates/results.tmpl b/install_to_share/templates/results.tmpl
new file mode 100644 (file)
index 0000000..131d14e
--- /dev/null
@@ -0,0 +1,23 @@
+{% extends '_base.tmpl' %}
+
+
+{% block body %}
+{{ macros.nav_head() }}
+<p>query: {{query}}</p>
+<table>
+{% for video in videos %}
+<tr>
+<td>
+<a href="/yt_video/{{video.id_}}"><img src="/thumbnails/{{video.id_}}.jpg" /></a>
+</td>
+<td>
+{{video.definition}}<br />
+{{video.duration}}
+</td>
+<td>
+<b><a href="/yt_video/{{video.id_}}">{{video.title}}</a></b> · {{video.description}}
+</td>
+</tr>
+{% endfor %}
+</table>
+{% endblock %}
diff --git a/install_to_share/templates/video.tmpl b/install_to_share/templates/video.tmpl
new file mode 100644 (file)
index 0000000..54d005f
--- /dev/null
@@ -0,0 +1,17 @@
+{% extends '_base.tmpl' %}
+
+
+{% block body %}
+{{ macros.nav_head() }}
+<table>
+<tr><th>path:</th><td>{{file.rel_path}}</td></tr>
+<tr><th>YouTube ID:</th><td><a href="/yt_video/{{file.yt_id}}">{{file.yt_id}}</a></tr>
+<tr><th>present:</th><td>{% if file.present %}<a href="/dl/{{file.yt_id}}">yes</a>{% else %}no{% endif %}</td></tr>
+</table>
+<form action="/video/{{file.yt_id}}" method="POST" />
+{% for flag_name in flag_names %}
+{{ flag_name }}: <input type="checkbox" name="{{flag_name}}" {% if file.flag_set(flag_name) %}checked {% endif %} /><br />
+{% endfor %}
+<input type="submit" />
+</form>
+{% endblock %}
diff --git a/install_to_share/templates/videos.tmpl b/install_to_share/templates/videos.tmpl
new file mode 100644 (file)
index 0000000..5cbf47f
--- /dev/null
@@ -0,0 +1,12 @@
+{% extends '_base.tmpl' %}
+
+
+{% block body %}
+{{ macros.nav_head("videos") }}
+<p>downloaded videos:</p>
+<ul>
+{% for video_id, path in videos %}
+<li><a href="/video/{{video_id}}">{{ path }}</a>
+{% endfor %}
+</ul>
+{% endblock %}
diff --git a/install_to_share/templates/yt_video.tmpl b/install_to_share/templates/yt_video.tmpl
new file mode 100644 (file)
index 0000000..1ecb258
--- /dev/null
@@ -0,0 +1,23 @@
+{% extends '_base.tmpl' %}
+
+
+{% block body %}
+{{ macros.nav_head() }}
+<table>
+<tr><th>title:</th><td>{{video_data.title}}</td></tr>
+<tr><th>thumbnail:</th><td><img src="/thumbnails/{{video_data.id_}}.jpg" /></td></tr>
+<tr><th>description:</th><td>{{video_data.description}}</td></tr>
+<tr><th>duration:</th><td>{{video_data.duration}}</td></tr>
+<tr><th>definition:</th><td>{{video_data.definition}}</td></tr>
+<tr><th>YouTube ID:</th><td>{{video_data.id_}} (<a href="{{youtube_prefix}}{{video_data.id_}}">watch</a>)</td></tr>
+<tr><th>download:</th><td>{% if is_temp %}working on it{% else %}<a href="/dl/{{video_data.id_}}">{{ file_path if file_path else "please do" }}</a>{% endif %}</td></tr>
+<tr>
+<th>linked queries:</th>
+<td>
+<ul>
+{% for query in queries %}<li><a href="/query/{{query.id_}}">{{query.text}}</a>{% endfor %}
+</ul>
+</td>
+</tr>
+</table>
+{% endblock %}
diff --git a/migrations/init_0.sql b/migrations/init_0.sql
deleted file mode 100644 (file)
index 5b45769..0000000
+++ /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 (file)
index 8839067..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{% import '_macros.tmpl' as macros %}
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="UTF-8">
-<script>
-{% block script %}
-{% endblock %}
-</script>
-<style>
-body { background-color: #aaaa00; }
-{% block css %}
-{% endblock %}
-</style>
-</head>
-<body>
-{% block body %}
-{% endblock %}
-</body>
-</html>
diff --git a/templates/_macros.tmpl b/templates/_macros.tmpl
deleted file mode 100644 (file)
index 12b28df..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{% macro _link_if(cond, target) %}{% if cond %}<a href="/{{target}}">{% endif %}{{target}}{% if cond %}</a>{% endif %}{% endmacro %}
-
-
-{% macro nav_head(selected="") %}
-<p>
-{{ _link_if("playlist" != selected, "playlist") }}
-{{ _link_if("videos" != selected, "videos") }}
-{{ _link_if("queries" != selected, "queries") }}
-</p>
-<hr />
-{% endmacro %}
diff --git a/templates/playlist.tmpl b/templates/playlist.tmpl
deleted file mode 100644 (file)
index 58c2b5b..0000000
+++ /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") }}
-<table>
-<tr><td id="status" colspan=2>
-{% if running %}{% if pause %}PAUSED{% else %}PLAYING{% endif %}{% else %}STOPPED{% endif %}:<br />
-{{ current_title }}<br />
-<form action="/playlist" method="POST">
-<input type="submit" name="pause" autofocus value="{% if paused %}resume{% else %}pause{% endif %}">
-<input type="submit" name="prev" value="prev">
-<input type="submit" name="next" value="next">
-<input type="submit" name="stop" value="{% if running %}stop{% else %}start{% endif %}">
-<input type="submit" name="reload" value="reload">
-</form>
-</td></tr>
-{% for prev_title, next_title in tuples %}
-<tr><td class="history">
-{{ prev_title }}
-</td><td class="history">
-{{ next_title }}
-</td></tr>
-{% endfor %}
-</table>
-{% endblock %}
-
diff --git a/templates/queries.tmpl b/templates/queries.tmpl
deleted file mode 100644 (file)
index 457f80e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{% extends '_base.tmpl' %}
-
-
-{% block body %}
-{{ macros.nav_head("queries") }}
-<p>quota: {{quota_count}}/100000</p>
-<form action="/queries" method="POST" />
-<input name="query" />
-</form>
-<table>
-<tr>
-<th>retrieved at</th>
-<th>query</th>
-</tr>
-{% for query in queries %}
-<tr>
-<td>{{query.retrieved_at[:19]}}</td>
-<td><a href="/query/{{query.id_}}">{{query.text}}</a></td>
-</tr>
-{% endfor %}
-</table>
-{% endblock %}
diff --git a/templates/results.tmpl b/templates/results.tmpl
deleted file mode 100644 (file)
index 131d14e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{% extends '_base.tmpl' %}
-
-
-{% block body %}
-{{ macros.nav_head() }}
-<p>query: {{query}}</p>
-<table>
-{% for video in videos %}
-<tr>
-<td>
-<a href="/yt_video/{{video.id_}}"><img src="/thumbnails/{{video.id_}}.jpg" /></a>
-</td>
-<td>
-{{video.definition}}<br />
-{{video.duration}}
-</td>
-<td>
-<b><a href="/yt_video/{{video.id_}}">{{video.title}}</a></b> · {{video.description}}
-</td>
-</tr>
-{% endfor %}
-</table>
-{% endblock %}
diff --git a/templates/video.tmpl b/templates/video.tmpl
deleted file mode 100644 (file)
index 54d005f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{% extends '_base.tmpl' %}
-
-
-{% block body %}
-{{ macros.nav_head() }}
-<table>
-<tr><th>path:</th><td>{{file.rel_path}}</td></tr>
-<tr><th>YouTube ID:</th><td><a href="/yt_video/{{file.yt_id}}">{{file.yt_id}}</a></tr>
-<tr><th>present:</th><td>{% if file.present %}<a href="/dl/{{file.yt_id}}">yes</a>{% else %}no{% endif %}</td></tr>
-</table>
-<form action="/video/{{file.yt_id}}" method="POST" />
-{% for flag_name in flag_names %}
-{{ flag_name }}: <input type="checkbox" name="{{flag_name}}" {% if file.flag_set(flag_name) %}checked {% endif %} /><br />
-{% endfor %}
-<input type="submit" />
-</form>
-{% endblock %}
diff --git a/templates/videos.tmpl b/templates/videos.tmpl
deleted file mode 100644 (file)
index 5cbf47f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{% extends '_base.tmpl' %}
-
-
-{% block body %}
-{{ macros.nav_head("videos") }}
-<p>downloaded videos:</p>
-<ul>
-{% for video_id, path in videos %}
-<li><a href="/video/{{video_id}}">{{ path }}</a>
-{% endfor %}
-</ul>
-{% endblock %}
diff --git a/templates/yt_video.tmpl b/templates/yt_video.tmpl
deleted file mode 100644 (file)
index 1ecb258..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{% extends '_base.tmpl' %}
-
-
-{% block body %}
-{{ macros.nav_head() }}
-<table>
-<tr><th>title:</th><td>{{video_data.title}}</td></tr>
-<tr><th>thumbnail:</th><td><img src="/thumbnails/{{video_data.id_}}.jpg" /></td></tr>
-<tr><th>description:</th><td>{{video_data.description}}</td></tr>
-<tr><th>duration:</th><td>{{video_data.duration}}</td></tr>
-<tr><th>definition:</th><td>{{video_data.definition}}</td></tr>
-<tr><th>YouTube ID:</th><td>{{video_data.id_}} (<a href="{{youtube_prefix}}{{video_data.id_}}">watch</a>)</td></tr>
-<tr><th>download:</th><td>{% if is_temp %}working on it{% else %}<a href="/dl/{{video_data.id_}}">{{ file_path if file_path else "please do" }}</a>{% endif %}</td></tr>
-<tr>
-<th>linked queries:</th>
-<td>
-<ul>
-{% for query in queries %}<li><a href="/query/{{query.id_}}">{{query.text}}</a>{% endfor %}
-</ul>
-</td>
-</tr>
-</table>
-{% endblock %}
index 9e46c8292030c9704f10803ce99aabfe4c705d37..647ad3901c98a5b924d47c3ea124924ad711e83b 100644 (file)
@@ -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())