From 515553aebcaef56dd0077e0f6b2f9a8a843c3e19 Mon Sep 17 00:00:00 2001 From: Chris Fulljames Date: Mon, 19 Jan 2026 16:00:09 -0500 Subject: [PATCH] Add missing duration field to update queue, other importer fixes --- src/littlesongplace/dreams_importer.py | 8 +-- src/littlesongplace/songs.py | 24 +++++++- src/littlesongplace/sql/schema_revert.sql | 3 + src/littlesongplace/sql/schema_update.sql | 3 +- .../templates/dreams-importer.html | 61 +++++++++++-------- src/littlesongplace/templates/edit-song.html | 2 +- test/test_dreams_importer.py | 5 +- test/test_online.py | 23 ++++++- test/test_songs.py | 2 + test/utils.py | 4 +- 10 files changed, 96 insertions(+), 39 deletions(-) diff --git a/src/littlesongplace/dreams_importer.py b/src/littlesongplace/dreams_importer.py index 4f7d88a..82fd38b 100644 --- a/src/littlesongplace/dreams_importer.py +++ b/src/littlesongplace/dreams_importer.py @@ -75,16 +75,16 @@ def delete_from_queue(queueid): db.query("DELETE FROM import_queue WHERE queueid = ?", [queueid]) current_app.logger.info(f"dreams_importer: Removed {queueid} from queue") -def add_to_queue(songid, indreams_url): +def add_to_queue(songid, indreams_url, duration): print(songid, indreams_url) timestamp = datetime.now(timezone.utc).isoformat() result = db.query( """ - INSERT INTO import_queue (created, indreamsurl, songid, status) - VALUES (?, ?, ?, 0) + INSERT INTO import_queue (created, indreamsurl, songid, status, duration) + VALUES (?, ?, ?, 0, ?) RETURNING queueid """, - [timestamp, indreams_url, songid], + [timestamp, indreams_url, songid, duration], expect_one=True) queueid = result["queueid"] diff --git a/src/littlesongplace/songs.py b/src/littlesongplace/songs.py index 562c616..a0ec845 100644 --- a/src/littlesongplace/songs.py +++ b/src/littlesongplace/songs.py @@ -294,6 +294,22 @@ def validate_song_form(): return error +def duration_in_seconds(song_duration): + DEFAULT_DURATION = 180 + + if not ":" in song_duration: + return DEFAULT_DURATION + + minutes, seconds = song_duration.split(":") + + try: + minutes = int(minutes) + seconds = int(seconds) + except ValueError: + return DEFAULT_DURATION + + return (minutes * 60) + seconds + def update_song(): songid = request.args["songid"] try: @@ -306,6 +322,7 @@ def update_song(): title = request.form["title"] description = request.form["description"] upload_type = request.form["upload-type"] + song_duration = request.form["song-duration"] tags = [t.strip() for t in request.form["tags"].split(",") if t] collaborators = [c.strip() for c in request.form["collabs"].split(",") if c] @@ -362,7 +379,8 @@ def update_song(): if upload_type == "dreams" and url: if song_data["queueid"] is not None: dreams_importer.delete_from_queue(song_data["queueid"]) - dreams_importer.add_to_queue(songid, url) + duration = duration_in_seconds(song_duration) + dreams_importer.add_to_queue(songid, url, duration) db.commit() flash_and_log(f"Successfully updated '{title}'", "success") @@ -375,6 +393,7 @@ def create_song(): title = request.form["title"] description = request.form["description"] upload_type = request.form["upload-type"] + song_duration = request.form["song-duration"] tags = [t.strip() for t in request.form["tags"].split(",") if t] collaborators = [c.strip() for c in request.form["collabs"].split(",") if c] try: @@ -423,7 +442,8 @@ def create_song(): [songid, collab]) if upload_type == "dreams": - dreams_importer.add_to_queue(songid, url) + duration = duration_in_seconds(song_duration) + dreams_importer.add_to_queue(songid, url, duration) db.commit() diff --git a/src/littlesongplace/sql/schema_revert.sql b/src/littlesongplace/sql/schema_revert.sql index fcb8d53..19e44da 100644 --- a/src/littlesongplace/sql/schema_revert.sql +++ b/src/littlesongplace/sql/schema_revert.sql @@ -1,3 +1,6 @@ +DROP VIEW IF EXISTS songs_view; +ALTER TABLE songs DROP COLUMN queueid; +DROP TABLE IF EXISTS import_queue; PRAGMA user_version = 7; diff --git a/src/littlesongplace/sql/schema_update.sql b/src/littlesongplace/sql/schema_update.sql index bbb2b41..a19e484 100644 --- a/src/littlesongplace/sql/schema_update.sql +++ b/src/littlesongplace/sql/schema_update.sql @@ -6,7 +6,8 @@ CREATE TABLE import_queue ( created TEXT NOT NULL, indreamsurl TEXT NOT NULL, songid INTEGER NOT NULL REFERENCES songs(songid) ON DELETE CASCADE, - status INTEGER NOT NULL + status INTEGER NOT NULL, + duration INTEGER NOT NULL ); DROP VIEW IF EXISTS songs_view; diff --git a/src/littlesongplace/templates/dreams-importer.html b/src/littlesongplace/templates/dreams-importer.html index f23f9b3..c6274ff 100644 --- a/src/littlesongplace/templates/dreams-importer.html +++ b/src/littlesongplace/templates/dreams-importer.html @@ -4,29 +4,52 @@

dreams importer

-

how it works

+

overview

-The Dreams importer is a script that runs on my PC. It automates interactions -with littlesong.place, indreams.me, and Dreams running on my PS5. +The Dreams importer allows you to import your songs into LSP directly from +Dreams! It just requires a link to the element on +indreams.me and the length of the song (which +are both entered on the usual song upload page).

-This means that my PC and PS5 need to be turned on and connected for the -importer to work. Generally, I will try to make sure it runs at least once a -week (usually on weekends) when there are songs in the import queue. I will -also make sure to run it the day of the little song jam to upload any jam -entries. +The imports usually won't be instant. I have to start the process manually, so +it's most efficient for me to run it on large batches of songs. It may take up +to a week for the importer to run after you submit a song. I'll usually run it +on weekends, and especially on jam days right before the jam.

If more than one weekend has passed and it still hasn't run, please send me an email at littlesongplace@gmail.com.

+ +

tips for imports

+For best results: + + +

how it works

+

+The Dreams importer is a script that runs on my PC. It automates interactions +with littlesong.place, indreams.me, and Dreams running on my PS5. +

The script performs the following sequence for each song in the queue:

    -
  1. Connect to LSP and get the song's InDreams URL
  2. -
  3. Load the InDreams URL and click the "Play Later" button
  4. -
  5. Remix the element in Dreams
  6. +
  7. Connect to LSP and get the song's indreams.me URL
  8. +
  9. Load the indreams.me URL and click the "Play Later" button
  10. +
  11. In Dreams (via remote play), remix the first element in the Play Later queue
  12. Play the song without recording to make sure all samples are loaded
  13. Play the song again, recording the audio
  14. Upload the song to LSP
  15. @@ -46,20 +69,4 @@ HDMI capture cards or the built-in screen recordings.)

    -

    tips for imports

    -For best results: - - {% endblock %} diff --git a/src/littlesongplace/templates/edit-song.html b/src/littlesongplace/templates/edit-song.html index 2495139..ea01b9f 100644 --- a/src/littlesongplace/templates/edit-song.html +++ b/src/littlesongplace/templates/edit-song.html @@ -118,7 +118,7 @@ function selectUploadMethod() { // Show dreams import URL box document.getElementById("song-url-container").hidden = false; document.getElementById("song-url").required = {% if song %}false{% else %}true{% endif %}; - document.getElementById("song-url-label").innerText = "InDreams Element URL (element must be public!)" + document.getElementById("song-url-label").innerText = "indreams.me Element URL (element must be public!)" document.getElementById("song-file-container").hidden = true; document.getElementById("song-file").required = false; diff --git a/test/test_dreams_importer.py b/test/test_dreams_importer.py index 3b81f3f..5f46c54 100644 --- a/test/test_dreams_importer.py +++ b/test/test_dreams_importer.py @@ -7,7 +7,8 @@ def test_import_failure(client, user): upload_song( client, b"Queued for import from Dreams", upload_type="dreams", - song_url=TEST_URL) + song_url=TEST_URL, + song_duration="3:19") response = client.get(f"/users/user") assert b"[Hidden]" in response.data assert b"[Queue Pos: 1]" in response.data @@ -17,6 +18,7 @@ def test_import_failure(client, user): assert response.json["next"]["userid"] == 1 assert response.json["next"]["songid"] == 1 assert response.json["next"]["queueid"] == 1 + assert response.json["next"]["duration"] == 199 # Now in progress response = client.get(f"/users/user") @@ -56,6 +58,7 @@ def test_reset_queue_after_error(client, user): # In queue response = client.get("/dreams-importer/next-in-queue") assert response.json["next"]["indreamsurl"] == TEST_URL + assert response.json["next"]["duration"] == 180 # Default # No next item - but signals failure response = client.get("/dreams-importer/next-in-queue") diff --git a/test/test_online.py b/test/test_online.py index 2683238..dde7051 100644 --- a/test/test_online.py +++ b/test/test_online.py @@ -22,6 +22,9 @@ def test_upload_and_delete_song(session): "description": "song description", "tags": "tag1, tag2", "collabs": "p1, p2", + "song-url": "", + "song-duration": "", + "upload-type": "file", }, ) response.raise_for_status() @@ -46,7 +49,15 @@ def test_comments_and_activity(session): response = session.post( url("/upload-song"), files={"song-file": open(TEST_DATA/"sample-3s.mp3", "rb")}, - data={"title": "song title", "description": "", "tags": "", "collabs": ""}, + data={ + "title": "song title", + "description": "", + "tags": "", + "collabs": "", + "song-url": "", + "song-duration": "", + "upload-type": "file", + }, ) response.raise_for_status() songs = _get_song_list_from_page(response.text) @@ -91,7 +102,15 @@ def test_upload_song_from_youtube(session): response = session.post( url("/upload-song"), - data={"title": "yt-song", "description": "", "tags": "", "collabs": "", "song-url": "https://youtu.be/5e5Z6gZWiEs"}, + data={ + "title": "yt-song", + "description": "", + "tags": "", + "collabs": "", + "song-url": "https://youtu.be/5e5Z6gZWiEs", + "song-duration": "", + "upload-type": "yt", + }, ) response.raise_for_status() songs = _get_song_list_from_page(response.text) diff --git a/test/test_songs.py b/test/test_songs.py index 2687dab..44d4272 100644 --- a/test/test_songs.py +++ b/test/test_songs.py @@ -219,6 +219,8 @@ def test_update_song_other_users_song(client): "tags": "tag", "collabs": "collab", "upload-type": "file", + "song-url": "", + "song-duration": "", } response = client.post(f"/upload-song?songid=1", data=data) diff --git a/test/utils.py b/test/utils.py index 57fb641..effa87a 100644 --- a/test/utils.py +++ b/test/utils.py @@ -47,7 +47,8 @@ def create_user_song_and_playlist(client, playlist_type="private"): def upload_song( client, msg, error=False, songid=None, eventid=None, - user="user", userid=1, filename=TEST_DATA/"sample-3s.mp3", upload_type="file", song_url=None, **kwargs): + user="user", userid=1, filename=TEST_DATA/"sample-3s.mp3", + upload_type="file", song_url=None, song_duration=None, **kwargs): song_file = None if filename: @@ -61,6 +62,7 @@ def upload_song( "collabs": "collab", "upload-type": upload_type, "song-url": song_url, + "song-duration": song_duration, } for k, v in kwargs.items(): data[k] = v -- 2.39.5