diff --git a/.gitignore b/.gitignore
index ae49879..550336a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,5 @@ devenv.local.yaml
# pre-commit
.pre-commit-config.yaml
+
+ssl
diff --git a/access_token.txt b/access_token.txt
deleted file mode 100644
index f4f68c1..0000000
--- a/access_token.txt
+++ /dev/null
@@ -1 +0,0 @@
-BQBNPC2WwzpQqZTz_CO2pjKj16j0hMKLGBv0xEQbUD1Ezf7e4fUT1oj2YKH7cyfRv5WiJ5TtQiNhBDfSONPgfnwfNV1IXkVWiNveGWCOkgmlGyV2wJV6TbXZEGjLFCMwpZZTR2GdP8vswc_veA2MH-T5A-Uooz3DYADjtwZz3_WuHN2W-6XwVCRHfRd4EPwG2FwtHvsC2GmZIILMYU7g0YFbDWnXIgGafA2_wEl7S-3Yuon2lNMfmmoc0LHBfupwyxdn9oD-Og
\ No newline at end of file
diff --git a/current b/current
deleted file mode 100644
index b2c9af4..0000000
--- a/current
+++ /dev/null
@@ -1,450 +0,0 @@
-{
- "nodes": {
- "devenv": {
- "locked": {
- "dir": "src/modules",
- "lastModified": 1764927628,
- "owner": "cachix",
- "repo": "devenv",
- "rev": "247d7027f91368054fb0eefbd755a73d42b66fee",
- "type": "github"
- },
- "original": {
- "dir": "src/modules",
- "owner": "cachix",
- "repo": "devenv",
- "type": "github"
- }
- },
- "flake-compat": {
- "flake": false,
- "locked": {
- "lastModified": 1764712249,
- "owner": "edolstra",
- "repo": "flake-compat",
- "rev": "3b279e4317ccfa4865356387935310531357d919",
- "type": "github"
- },
- "original": {
- "owner": "edolstra",
- "repo": "flake-compat",
- "type": "github"
- }
- },
- "git-hooks": {
- "inputs": {
- "flake-compat": "flake-compat",
- "gitignore": "gitignore",
- "nixpkgs": [
- "nixpkgs"
- ]
- },
- "locked": {
- "lastModified": 1765016596,
- "owner": "cachix",
- "repo": "git-hooks.nix",
- "rev": "548fc44fca28a5e81c5d6b846e555e6b9c2a5a3c",
- "type": "github"
- },
- "original": {
- "owner": "cachix",
- "repo": "git-hooks.nix",
- "type": "github"
- }
- },
- "gitignore": {
- "inputs": {
- "nixpkgs": [
- "git-hooks",
- "nixpkgs"
- ]
- },
- "locked": {
- "lastModified": 1762808025,
- "owner": "hercules-ci",
- "repo": "gitignore.nix",
- "rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
- "type": "github"
- },
- "original": {
- "owner": "hercules-ci",
- "repo": "gitignore.nix",
- "type": "github"
- }
- },
- "nixpkgs": {
- "locked": {
- "lastModified": 1764580874,
- "owner": "cachix",
- "repo": "devenv-nixpkgs",
- "rev": "dcf61356c3ab25f1362b4a4428a6d871e84f1d1d",
- "type": "github"
- },
- "original": {
- "owner": "cachix",
- "ref": "rolling",
- "repo": "devenv-nixpkgs",
- "type": "github"
- }
- },
- "root": {
- "inputs": {
- "devenv": "devenv",
- "git-hooks": "git-hooks",
- "nixpkgs": "nixpkgs",
- "pre-commit-hooks": [
- "git-hooks"
- ]
- }
- }
- },
- "root": "root",
- "version": 7
-}
-{ pkgs, lib, config, inputs, ... }: {
- env.GREET = "SpotDL devenv";
- packages = [pkgs.spotdl pkgs.python313Packages.spotipy pkgs.python313Packages.flask pkgs.openssl];
-
- scripts.hello.exec = ''echo hello from $GREET ! '';
-
- scripts.craftcerts.exec = ''
- mkdir -p ssl # Use -p to avoid error if the directory exists
- cd ssl
- if [ ! -f ../openssl.cnf ]; then
- echo "Please create 'openssl.cnf' in the parent directory."
- exit 1
- fi
- openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.cert -days 365 -nodes -config ../openssl.cnf >/dev/null
- '';
-
- scripts.download.exec = ''
- while true; do
- url=$(python ./geturl.py) # Capture the output of geturl.py
- if [ $? -eq 0 ]; then
- spotdl "$url"
- break
- fi
- echo "Error downloading, retrying..."
- sleep 2
- done
- '';
-
- enterShell = ''
- hello
- craftcerts
- download
- '';
-}
-# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
-inputs:
- nixpkgs:
- url: github:cachix/devenv-nixpkgs/rolling
-
-# If you're using non-OSS software, you can set allowUnfree to true.
-# allowUnfree: true
-
-# If you're willing to use a package that's vulnerable
-# permittedInsecurePackages:
-# - "openssl-1.1.1w"
-
-# If you have more than one devenv you can merge them
-#imports:
-# - ./backend
-from flask import Flask, request, redirect
-import spotipy
-from spotipy.oauth2 import SpotifyOAuth
-import subprocess
-import os
-import time
-from datetime import datetime
-
-app = Flask(__name__)
-
-client_id = "c0020cc0e05245efb2ddb61b7045e4f2"
-client_secret = "2e2e7c98f849403fbacc219c1f01c17d"
-redirect_uri = "https://localhost:8888/callback"
-
-sp_oauth = SpotifyOAuth(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, scope="playlist-modify-private user-library-read")
-
-@app.route('/')
-def index():
- return "Welcome! Login to Spotify"
-
-@app.route('/login')
-def login():
- return redirect(sp_oauth.get_authorize_url())
-
-@app.route('/callback')
-def callback():
- code = request.args.get('code')
- token_info = sp_oauth.get_access_token(code)
- access_token = token_info['access_token']
- sp = spotipy.Spotify(auth=access_token)
-
- print("Fetching liked songs...")
- liked_songs = []
- results = sp.current_user_saved_tracks()
-
- while results:
- for item in results['items']:
- liked_songs.append(item['track']['id'])
- if results['next']:
- results = sp.next(results)
- time.sleep(1)
- else:
- break
-
- playlist_name = datetime.now().strftime("Liked Songs Collection - %Y-%m-%d %H-%M-%S")
- user_id = sp.me()['id']
- new_playlist = sp.user_playlist_create(user_id, playlist_name, public=False)
-
- print(f"Created playlist: {playlist_name}")
-
- for i in range(0, len(liked_songs), 100):
- batch = liked_songs[i:i + 100]
- sp.playlist_add_items(new_playlist['id'], batch)
- print(f"Added {len(batch)} songs...")
- time.sleep(1)
-
- playlist_url = new_playlist['external_urls']['spotify']
- print(f"Playlist URL: {playlist_url}")
-
- # Write playlist URL for the download script
- with open("last_playlist_url.txt", "w") as f:
- f.write(playlist_url)
-
- return f"{playlist_url}"
-
-if __name__ == "__main__":
- print("Starting Flask server...")
- os.execvp('flask', [
- 'flask',
- 'run',
- '--host=0.0.0.0',
- '--port=8888',
- '--cert=ssl/server.cert',
- '--key=ssl/server.key'
- ])
-from flask import Flask, request, redirect
-import spotipy
-from spotipy.oauth2 import SpotifyOAuth
-import threading
-import os
-import sys
-import time # Import time module
-from datetime import datetime
-
-app = Flask(__name__)
-
-client_id = "c0020cc0e05245efb2ddb61b7045e4f2"
-client_secret = "2e2e7c98f849403fbacc219c1f01c17d"
-redirect_uri = "https://localhost:8888/callback"
-
-sp_oauth = SpotifyOAuth(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, scope="playlist-modify-private user-library-read")
-
-@app.route('/')
-def index():
- return "Welcome! Login to Spotify"
-
-@app.route('/login')
-def login():
- return redirect(sp_oauth.get_authorize_url())
-
-@app.route('/callback')
-def callback():
- code = request.args.get('code')
- token_info = sp_oauth.get_access_token(code)
- access_token = token_info['access_token']
-
- with open("access_token.txt", "w") as f:
- f.write(access_token)
-
- print("Authorization complete. You can close this window.", file=sys.stderr)
- return "Authorization complete. You can close this window."
-
-def create_playlist():
- if not os.path.exists("access_token.txt"):
- print("No access token found.", file=sys.stderr)
- return
-
- with open("access_token.txt", "r") as f:
- access_token = f.read().strip()
-
- sp = spotipy.Spotify(auth=access_token)
-
- print("Fetching liked songs...", file=sys.stderr)
- liked_songs = []
- results = sp.current_user_saved_tracks()
-
- while results:
- for item in results['items']:
- liked_songs.append(item['track']['id'])
- if results['next']:
- results = sp.next(results)
- else:
- break
-
- playlist_name = datetime.now().strftime("Liked Songs Collection - %Y-%m-%d %H-%M-%S")
- user_id = sp.me()['id']
- new_playlist = sp.user_playlist_create(user_id, playlist_name, public=False)
-
- print(f"Created playlist: {playlist_name}", file=sys.stderr)
-
- for i in range(0, len(liked_songs), 100):
- batch = liked_songs[i:i + 100]
- sp.playlist_add_items(new_playlist['id'], batch)
- print(f"Added {len(batch)} songs...", file=sys.stderr)
-
- playlist_url = new_playlist['external_urls']['spotify']
- print(f"Playlist URL: {playlist_url}", file=sys.stderr)
-
- return playlist_url
-
-def run_flask():
- app.run(ssl_context=('ssl/server.cert', 'ssl/server.key'), host="0.0.0.0", port=8888)
-
-def main():
- # Start the Flask app in a background thread
- flask_thread = threading.Thread(target=run_flask, daemon=True)
- flask_thread.start()
-
- # Inform the user to authorize access via the URL shown in the terminal
- print("Please authorize access via the following URL:", sp_oauth.get_authorize_url())
-
- # Wait until the access token is available
- while not os.path.exists("access_token.txt"):
- time.sleep(1) # Sleep for a while, then check again
-
- # Now that we have the token, proceed with creating the playlist
- playlist_url = create_playlist()
- print(f"Playlist URL returned: {playlist_url}")
-
-if __name__ == "__main__":
- main()
-[req]
-default_bits = 2048
-distinguished_name = req_distinguished_name
-prompt = no
-[req_distinguished_name]
-C = US
-ST = California
-L = San Francisco
-O = Example Company
-OU = IT Department
-CN = localhost
-emailAddress = email@example.com
-To implement HTTPS using Let's Encrypt and ngrok while modifying your Flask application, follow these structured steps:
-
-## Step 1: Install and Set Up ngrok
-
-1. **Download ngrok**:
- - Go to the [ngrok website](https://ngrok.com/download) and download the appropriate version for your OS.
- - Install ngrok by following the instructions on the site.
-
-2. **Authenticate ngrok**:
- - Sign up for a free account at ngrok.com.
- - After signing up, you’ll receive an authtoken. Run the following command to set it up:
- ```bash
- ngrok config add-authtoken
- ```
-
-## Step 2: Modify Flask to Accept HTTPS
-
-Update your Flask application to use ngrok to tunnel HTTPS traffic:
-
-1. **Change `run_flask()` to bind to HTTP**:
- This is so ngrok can handle the SSL termination. Update the endpoint by removing the `ssl_context`:
- ```python
- def run_flask():
- app.run(host="0.0.0.0", port=8888)
- ```
-
-2. **Expose the Flask app via ngrok**:
- You can run ngrok to expose your Flask app by executing:
- ```bash
- ngrok http 8888
- ```
- This will give you a public HTTPS URL that tunnels to your local Flask app.
-
-## Step 3: Modify the Development Environment (devenv.nix)
-
-You’ll need to add the ngrok installation to your `devenv.nix` configuration, if it's not already installed.
-
-1. **Edit `devenv.nix`**:
-
-```nix
-{ pkgs ? import {} }:
-
-pkgs.mkShell {
- buildInputs = [
- pkgs.ngrok
- ];
-
- shellHook = ''
- # Set up ngrok to run automatically
- ngrok http 8888 &
- '';
-}
-```
-
-This snippet sets up ngrok to run in the background whenever you start your development environment.
-
-## Step 4: Implement the PKI Chain in `geturl.py`
-
-To implement an HTTPS PKI chain, consider using the Let's Encrypt certificate. For local development, you can't use Let's Encrypt directly without a publicly reachable domain, but you can still prepare your code as if you're using secure connections.
-
-1. **Modify `geturl.py`**:
-
-Assuming your application logic has not changed, implement a function to fetch the ngrok URL:
-
-```python
-import os
-import requests
-import threading
-import time
-
-def get_ngrok_url():
- response = requests.get("http://localhost:4040/api/tunnels")
- tunnels = response.json()["tunnels"]
- for tunnel in tunnels:
- if tunnel["name"] == "http":
- return tunnel["public_url"]
- return None
-
-def create_playlist():
- # Your existing code to create a playlist
- ...
-
-def run_flask():
- app.run(host="0.0.0.0", port=8888)
-
-def main():
- # Start Flask in a background thread
- flask_thread = threading.Thread(target=run_flask, daemon=True)
- flask_thread.start()
-
- # Wait for ngrok to be ready
- time.sleep(5) # Allow some time for ngrok to initialize
-
- ngrok_url = get_ngrok_url()
- print(f"Ngrok URL: {ngrok_url}")
-
- print("Please authorize access via the following URL:", sp_oauth.get_authorize_url())
-
- while not os.path.exists("access_token.txt"):
- time.sleep(1)
-
- playlist_url = create_playlist()
- print(f"Playlist URL returned: {playlist_url}")
-
-if __name__ == "__main__":
- main()
-```
-
-In this code:
-- `get_ngrok_url()` fetches the ngrok tunnel URL dynamically.
-- You can then safely use this URL to inform other services of your HTTPS endpoint.
-
-## Summary
-
-This setup will let you run a local Flask application using HTTPS through an ngrok tunnel. You process the playlist creation and output the URL correctly while working in a secure environment. If you later transition to production, you can directly implement Let's Encrypt for your domain, maintaining the same architecture with minimal changes.
diff --git a/geturl.old b/geturl.old
deleted file mode 100644
index 56e5bd3..0000000
--- a/geturl.old
+++ /dev/null
@@ -1,75 +0,0 @@
-from flask import Flask, request, redirect
-import spotipy
-from spotipy.oauth2 import SpotifyOAuth
-import subprocess
-import os
-import time
-from datetime import datetime
-
-app = Flask(__name__)
-
-client_id = "c0020cc0e05245efb2ddb61b7045e4f2"
-client_secret = "2e2e7c98f849403fbacc219c1f01c17d"
-redirect_uri = "https://localhost:8888/callback"
-
-sp_oauth = SpotifyOAuth(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, scope="playlist-modify-private user-library-read")
-
-@app.route('/')
-def index():
- return "Welcome! Login to Spotify"
-
-@app.route('/login')
-def login():
- return redirect(sp_oauth.get_authorize_url())
-
-@app.route('/callback')
-def callback():
- code = request.args.get('code')
- token_info = sp_oauth.get_access_token(code)
- access_token = token_info['access_token']
- sp = spotipy.Spotify(auth=access_token)
-
- print("Fetching liked songs...")
- liked_songs = []
- results = sp.current_user_saved_tracks()
-
- while results:
- for item in results['items']:
- liked_songs.append(item['track']['id'])
- if results['next']:
- results = sp.next(results)
- time.sleep(1)
- else:
- break
-
- playlist_name = datetime.now().strftime("Liked Songs Collection - %Y-%m-%d %H-%M-%S")
- user_id = sp.me()['id']
- new_playlist = sp.user_playlist_create(user_id, playlist_name, public=False)
-
- print(f"Created playlist: {playlist_name}")
-
- for i in range(0, len(liked_songs), 100):
- batch = liked_songs[i:i + 100]
- sp.playlist_add_items(new_playlist['id'], batch)
- print(f"Added {len(batch)} songs...")
- time.sleep(1)
-
- playlist_url = new_playlist['external_urls']['spotify']
- print(f"Playlist URL: {playlist_url}")
-
- # Write playlist URL for the download script
- with open("last_playlist_url.txt", "w") as f:
- f.write(playlist_url)
-
- return f"{playlist_url}"
-
-if __name__ == "__main__":
- print("Starting Flask server...")
- os.execvp('flask', [
- 'flask',
- 'run',
- '--host=0.0.0.0',
- '--port=8888',
- '--cert=ssl/server.cert',
- '--key=ssl/server.key'
- ])
diff --git a/whatsnext.md b/whatsnext.md
deleted file mode 100644
index 8294bbf..0000000
--- a/whatsnext.md
+++ /dev/null
@@ -1,115 +0,0 @@
-To implement HTTPS using Let's Encrypt and ngrok while modifying your Flask application, follow these structured steps:
-
-## Step 1: Install and Set Up ngrok
-
-1. **Download ngrok**:
- - Go to the [ngrok website](https://ngrok.com/download) and download the appropriate version for your OS.
- - Install ngrok by following the instructions on the site.
-
-2. **Authenticate ngrok**:
- - Sign up for a free account at ngrok.com.
- - After signing up, you’ll receive an authtoken. Run the following command to set it up:
- ```bash
- ngrok config add-authtoken
- ```
-
-## Step 2: Modify Flask to Accept HTTPS
-
-Update your Flask application to use ngrok to tunnel HTTPS traffic:
-
-1. **Change `run_flask()` to bind to HTTP**:
- This is so ngrok can handle the SSL termination. Update the endpoint by removing the `ssl_context`:
- ```python
- def run_flask():
- app.run(host="0.0.0.0", port=8888)
- ```
-
-2. **Expose the Flask app via ngrok**:
- You can run ngrok to expose your Flask app by executing:
- ```bash
- ngrok http 8888
- ```
- This will give you a public HTTPS URL that tunnels to your local Flask app.
-
-## Step 3: Modify the Development Environment (devenv.nix)
-
-You’ll need to add the ngrok installation to your `devenv.nix` configuration, if it's not already installed.
-
-1. **Edit `devenv.nix`**:
-
-```nix
-{ pkgs ? import {} }:
-
-pkgs.mkShell {
- buildInputs = [
- pkgs.ngrok
- ];
-
- shellHook = ''
- # Set up ngrok to run automatically
- ngrok http 8888 &
- '';
-}
-```
-
-This snippet sets up ngrok to run in the background whenever you start your development environment.
-
-## Step 4: Implement the PKI Chain in `geturl.py`
-
-To implement an HTTPS PKI chain, consider using the Let's Encrypt certificate. For local development, you can't use Let's Encrypt directly without a publicly reachable domain, but you can still prepare your code as if you're using secure connections.
-
-1. **Modify `geturl.py`**:
-
-Assuming your application logic has not changed, implement a function to fetch the ngrok URL:
-
-```python
-import os
-import requests
-import threading
-import time
-
-def get_ngrok_url():
- response = requests.get("http://localhost:4040/api/tunnels")
- tunnels = response.json()["tunnels"]
- for tunnel in tunnels:
- if tunnel["name"] == "http":
- return tunnel["public_url"]
- return None
-
-def create_playlist():
- # Your existing code to create a playlist
- ...
-
-def run_flask():
- app.run(host="0.0.0.0", port=8888)
-
-def main():
- # Start Flask in a background thread
- flask_thread = threading.Thread(target=run_flask, daemon=True)
- flask_thread.start()
-
- # Wait for ngrok to be ready
- time.sleep(5) # Allow some time for ngrok to initialize
-
- ngrok_url = get_ngrok_url()
- print(f"Ngrok URL: {ngrok_url}")
-
- print("Please authorize access via the following URL:", sp_oauth.get_authorize_url())
-
- while not os.path.exists("access_token.txt"):
- time.sleep(1)
-
- playlist_url = create_playlist()
- print(f"Playlist URL returned: {playlist_url}")
-
-if __name__ == "__main__":
- main()
-```
-
-In this code:
-- `get_ngrok_url()` fetches the ngrok tunnel URL dynamically.
-- You can then safely use this URL to inform other services of your HTTPS endpoint.
-
-## Summary
-
-This setup will let you run a local Flask application using HTTPS through an ngrok tunnel. You process the playlist creation and output the URL correctly while working in a secure environment. If you later transition to production, you can directly implement Let's Encrypt for your domain, maintaining the same architecture with minimal changes.