]> littlesong.place Git - littlesongplace.git/commitdiff
Add ntfy instructions, uuid
authorChris Fulljames <christianfulljames@gmail.com>
Sun, 6 Jul 2025 22:15:34 +0000 (18:15 -0400)
committerChris Fulljames <christianfulljames@gmail.com>
Sun, 6 Jul 2025 22:16:49 +0000 (18:16 -0400)
14 files changed:
src/littlesongplace/__init__.py
src/littlesongplace/auth.py
src/littlesongplace/db.py
src/littlesongplace/sql/schema.sql
src/littlesongplace/sql/schema_revert.sql
src/littlesongplace/sql/schema_update.sql
src/littlesongplace/static/ntfy_done.webp [new file with mode: 0644]
src/littlesongplace/static/ntfy_server.webp [new file with mode: 0644]
src/littlesongplace/static/ntfy_sub.webp [new file with mode: 0644]
src/littlesongplace/templates/activity.html
src/littlesongplace/templates/index.html
src/littlesongplace/templates/news.html
src/littlesongplace/templates/notifications.html [new file with mode: 0644]
src/littlesongplace/users.py

index 5754392307871a35d5af0d0c446563cd3e243ec8..b2648fa3769f7b9a6ae9398b4d99e1f4cbac5c9a 100644 (file)
@@ -91,6 +91,10 @@ def site_news():
 def about():
     return render_template("about.html")
 
+@app.get("/notifications")
+def notifications():
+    return render_template("notifications.html")
+
 def get_gif_data():
     # Convert all .gifs to base64 strings and embed them as dataset entries
     # in <div>s.  This is used by nav.js:customImage() - it replaces specific
index 174a5f273155ccda2f6339efec31c55bb7e282cc..b32a05bb9c9a925fb24706074eff01ba180f2580 100644 (file)
@@ -4,7 +4,7 @@ from datetime import datetime, timezone
 import bcrypt
 from flask import Blueprint, render_template, redirect, flash, g, request, current_app, session
 
-from . import comments, db
+from . import comments, db, users
 from .logutils import flash_and_log
 
 bp = Blueprint("auth", __name__)
@@ -108,10 +108,14 @@ def requires_login(f):
         if not "userid" in session:
             return redirect("/login")
 
-        g.userid = session["userid"]
-        g.username = session["username"]
-
         return f(*args, **kwargs)
 
     return _wrapper
 
+@bp.before_app_request
+def load_user():
+    if "userid" in session:
+        g.userid = session["userid"]
+        g.username = session["username"]
+        g.user = users.by_id(session["userid"])
+
index ec1ebad111f272904489cee6cbd7e021efaed155..0fd94c9698f240ba7866f2b6c8099f4da154570c 100644 (file)
@@ -6,7 +6,7 @@ from flask import abort, g, current_app
 
 from . import datadir
 
-DB_VERSION = 5
+DB_VERSION = 6
 
 def get():
     db = getattr(g, '_database', None)
index 51057b6baff7d7007233030866dfca20c4ce6220..6b3401352e24c33bbc3c86f2823b192eee43cfea 100644 (file)
@@ -1,3 +1,17 @@
+DROP TABLE IF EXISTS jam_events;
+CREATE TABLE jam_events(
+    eventid INTEGER PRIMARY KEY,
+    jamid INTEGER NOT NULL,
+    threadid INTEGER NOT NULL,
+    created TEXT NOT NULL,
+    title TEXT NOT NULL, -- Hidden until startdate
+    startdate TEXT,
+    enddate TEXT,
+    description TEXT, -- Hidden until startdate
+    FOREIGN KEY(jamid) REFERENCES jams(jamid),
+    FOREIGN KEY(threadid) REFERENCES comment_threads(threadid)
+);
+
 DROP TABLE IF EXISTS users;
 CREATE TABLE users (
     userid INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -21,9 +35,12 @@ CREATE TABLE songs (
     title TEXT NOT NULL,
     description TEXT,
     threadid INTEGER,
-    FOREIGN KEY(userid) REFERENCES users(userid)
+    eventid INTEGER,
+    FOREIGN KEY(userid) REFERENCES users(userid),
+    FOREIGN KEY(eventid) REFERENCES jam_events(eventid)
 );
 CREATE INDEX idx_songs_by_user ON songs(userid);
+CREATE INDEX idx_songs_by_eventid ON songs(eventid);
 
 DROP TABLE IF EXISTS song_collaborators;
 CREATE TABLE song_collaborators (
@@ -159,5 +176,15 @@ BEGIN
     DELETE FROM notifications WHERE objectid = OLD.commentid AND objecttype = 0;
 END;
 
-PRAGMA user_version = 4;
+DROP TABLE IF EXISTS jams;
+CREATE TABLE jams (
+    jamid INTEGER PRIMARY KEY,
+    ownerid INTEGER NOT NULL,
+    created TEXT NOT NULL,
+    title TEXT NOT NULL,
+    description TEXT,
+    FOREIGN KEY(ownerid) REFERENCES users(userid)
+);
+
+PRAGMA user_version = 5;
 
index a6cd88388abb6d846254cc2b24979922302cff4d..b4b96afb45447eca31b817c901fe366f6fed2432 100644 (file)
@@ -1,7 +1,3 @@
-DROP INDEX idx_songs_by_eventid;
-ALTER TABLE songs DROP COLUMN eventid;
-DROP TABLE IF EXISTS jams;
-DROP TABLE IF EXISTS jam_events;
-
-PRAGMA user_version = 4;
+ALTER TABLE users DROP COLUMN ntfyuuid;
+PRAGMA user_version = 5;
 
index ffb9b60a0b69310759846dfde36c7b2e28a96927..2e1021a9e809c7bd8485f45a3645d6ddb3d997aa 100644 (file)
@@ -1,29 +1,3 @@
---DROP TABLE IF EXISTS jams;
-CREATE TABLE jams (
-    jamid INTEGER PRIMARY KEY,
-    ownerid INTEGER NOT NULL,
-    created TEXT NOT NULL,
-    title TEXT NOT NULL,
-    description TEXT,
-    FOREIGN KEY(ownerid) REFERENCES users(userid)
-);
-
---DROP TABLE IF EXISTS jam_events;
-CREATE TABLE jam_events(
-    eventid INTEGER PRIMARY KEY,
-    jamid INTEGER NOT NULL,
-    threadid INTEGER NOT NULL,
-    created TEXT NOT NULL,
-    title TEXT NOT NULL, -- Hidden until startdate
-    startdate TEXT,
-    enddate TEXT,
-    description TEXT, -- Hidden until startdate
-    FOREIGN KEY(jamid) REFERENCES jams(jamid),
-    FOREIGN KEY(threadid) REFERENCES comment_threads(threadid)
-);
-
-ALTER TABLE songs ADD COLUMN eventid INTEGER REFERENCES jam_events(eventid);
-CREATE INDEX idx_songs_by_eventid ON songs(eventid);
-
-PRAGMA user_version = 5;
+ALTER TABLE users ADD COLUMN ntfyuuid TEXT;
+PRAGMA user_version = 6;
 
diff --git a/src/littlesongplace/static/ntfy_done.webp b/src/littlesongplace/static/ntfy_done.webp
new file mode 100644 (file)
index 0000000..da3444e
Binary files /dev/null and b/src/littlesongplace/static/ntfy_done.webp differ
diff --git a/src/littlesongplace/static/ntfy_server.webp b/src/littlesongplace/static/ntfy_server.webp
new file mode 100644 (file)
index 0000000..faf5f0f
Binary files /dev/null and b/src/littlesongplace/static/ntfy_server.webp differ
diff --git a/src/littlesongplace/static/ntfy_sub.webp b/src/littlesongplace/static/ntfy_sub.webp
new file mode 100644 (file)
index 0000000..ff47abe
Binary files /dev/null and b/src/littlesongplace/static/ntfy_sub.webp differ
index 19f8f250f9591005a4f040d588489ff3a1688d09..9a33dc0e5551c148a4f74edc1e967182f8d772c4 100644 (file)
@@ -4,6 +4,8 @@
 
 {% block body %}
 
+<p><a href="/notifications">[push notifications available]</a></p>
+
 {% if comments %}
 <h1>activity</h1>
 
index 587ff5ddc31790e74bec81aefafe2a0bfe8c6a95..edc7f79ba77e3af5950b0b811c869bb06e7d7d2a 100644 (file)
@@ -33,6 +33,7 @@
 </div>
 
 <h2>hot new tunes</h2>
+<p><a href="/notifications">[push notifications available]</a></p>
 {% include "song-list.html" %}
 
 {% endblock %}
index 36bd09011f012609bfd2dcd8c3221a5fbe70fffb..d552f817235ff40541478992bcfb3a038aa3eb56 100644 (file)
@@ -6,6 +6,8 @@
 
 <h1>site news</h1>
 
+<p><a href="/notifications">[push notifications available]</a></p>
+
 <h2>2025-07-01 - Download Button</h2>
 <p>
 You can now download your own songs as mp3 files from the dedicated button on
diff --git a/src/littlesongplace/templates/notifications.html b/src/littlesongplace/templates/notifications.html
new file mode 100644 (file)
index 0000000..82dccab
--- /dev/null
@@ -0,0 +1,32 @@
+{% extends "base.html" %}
+
+{% block title %}Push Notifications{% endblock %}
+
+{% block body %}
+
+<h1>Push Notifications</h1>
+
+<p>
+littlesong.place can send you push notifications on your phone via
+<a href="https://ntfy.sh/">ntfy</a>.
+It takes a few minutes to set up (I know, it's a little clunky), but you only have to do it once.
+Here's how it works:
+</p>
+<ol>
+    <li>Install the <a href="https://ntfy.sh/">ntfy app</a> on your device.</li>
+    <li>Open the app and grant it permission to send you push notifications when asked.</li>
+    <li>In the ntfy app, open the <b>Settings</b> tab, and set <b>Default server</b> to <a href="https://ntfy.littlesong.place">https://ntfy.littlesong.place</a>.<br><img src="/static/ntfy_server.webp" width="256"></li>
+    <li>Subscribe to each topic you'd like to be notified about using the '+' button in the app (see available topics below).<br><img src="/static/ntfy_sub.webp" width="256"></li>
+    <li>When you're done, it should look something like this:<br><img src="/static/ntfy_done.webp" width="256"><br></li>
+</ol>
+Available topics include:
+<ul>
+    <li><b>songs</b> - get notified (at most once per day) when new songs are uploaded</li>
+    <li><b>news</b> - get notified about <a href="/site-news">site news</a></li>
+    <li><b>jams</b> - get notified when <a href="/site-news">jams</a> start or end</li>
+    {% if g.user %}
+    <li><b>{{ g.user.ntfy_uuid }}</b> (unique to you) - get notified about <a href="/activity">activity</a> (comments)</li>
+    {% endif %}
+</ul>
+
+{% endblock %}
index 857196d48e29af698aae92b814a5007492d0b57b..8d8de2d25ad61db30aa1b9e4dae4802d3ac81ffd 100644 (file)
@@ -1,3 +1,4 @@
+import uuid
 from dataclasses import dataclass
 
 from . import colors, datadir, db
@@ -9,6 +10,7 @@ class User:
     fgcolor: str
     bgcolor: str
     accolor: str
+    _ntfy_uuid: str
 
     @property
     def colors(self):
@@ -18,12 +20,23 @@ class User:
             "accolor": self.accolor,
         }
 
+    @property
+    def ntfy_uuid(self):
+        if not self._ntfy_uuid:
+            self._ntfy_uuid = str(uuid.uuid4())
+            db.query(
+                    "UPDATE users SET ntfyuuid = ? WHERE userid = ?",
+                    [self._ntfy_uuid, self.userid])
+            db.commit()
+        return self._ntfy_uuid
+
     @classmethod
     def from_row(cls, row):
         user_colors = get_user_colors(row)
         return User(
                 userid=row["userid"],
                 username=row["username"],
+                _ntfy_uuid=row["ntfyuuid"],
                 **user_colors)
 
 def by_id(userid):