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.