diff --git a/.gitignore b/.gitignore index 130a69d..8e26ca8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +*Venv* +*venv* + # User uploaded files directory uploads/ # sensitive auth data diff --git a/app.py b/app.py index f205b1e..1621a2a 100644 --- a/app.py +++ b/app.py @@ -1,17 +1,15 @@ # App launch-point # ---- Dependency imports ---- # -from enum import unique import logging import math import os import time -from configparser import ConfigParser, RawConfigParser from datetime import datetime, timedelta from os.path import exists from werkzeug.utils import secure_filename -from flask import (Flask, Response, redirect, render_template, request, +from flask import (Flask, redirect, render_template, request, send_file, session, url_for) from flask_assets import Bundle, Environment @@ -21,6 +19,9 @@ import glob import shutil +from dotenv import load_dotenv +load_dotenv() + # ---------------------------- # ALLOWED_EXTENSIONS = {'png', 'jpeg', 'jpg', 'gpx'} @@ -71,13 +72,6 @@ assets.config['PYSCSS_ASSETS_ROOT'] = assets.directory assets.register('scss_all', scss) -# -------- Read and load config data -------- # -configParser = RawConfigParser() -configFilePath = r'./app.cfg' -configParser.read(configFilePath) - -config = ConfigParser() -config.read_file(open(r'./app.cfg')) # -------------------------------------------- # import networks.strava # Must be imported after config has been read @@ -86,8 +80,8 @@ userCachedData = {} apis = { - 'strava': networks.strava.StravaApi(config, flaskApp), - #'twitter': networks.twitter.twitterApi(config, flaskApp) + 'strava': networks.strava.StravaApi(flaskApp), + #'twitter': networks.twitter.twitterApi(flaskApp) } shareAuthURLs = {} @@ -159,7 +153,6 @@ def render_parameters(): for file in request.files.getlist('gpxFile'): if file and functions.allowed_file(file.filename, ALLOWED_EXTENSIONS): filename = secure_filename(functions.randomAlphanumericString(16) + "_" + file.filename) - #print(file) file.save(os.path.join(flaskApp.config['UPLOAD_FOLDER'] + "/" + uniqueId, filename)) if not uniqueId in userCachedData: @@ -340,8 +333,4 @@ def render_privacyPage(): if sessionDataValidationResult == True: return render_template('privacyPage.html', userData = session['userData']) else: - return render_template('privacyPage.html') - -# Store any config items not related to API logins under app.config -for key in config["DEFAULT"]: - flaskApp.config[key] = config["DEFAULT"][key] \ No newline at end of file + return render_template('privacyPage.html') \ No newline at end of file diff --git a/networks/strava.py b/networks/strava.py index 47e254a..0fdb5ed 100644 --- a/networks/strava.py +++ b/networks/strava.py @@ -3,25 +3,24 @@ import math import os import time -from flask import Flask, redirect, render_template, request, url_for, Response +from flask import redirect, request, url_for import functions -import generateVis import polyline import app as main import datetime # ---------------------------- # class StravaApi: - def __init__(self, cfg, app): + def __init__(self, app): # Configure strava-specific connection details self.configCode = 'strava' - self.configDetails = cfg[self.configCode] - self.tokenUrl = self.configDetails['TOKEN_URL'].strip('\'') - self.clientId = self.configDetails['CLIENT_ID'].strip('\'') - self.clientSecret = self.configDetails['CLIENT_SECRET'].strip('\'') - self.authUrl = self.configDetails['AUTH_URL'].strip('\'') + self.tokenUrl = 'https://www.strava.com/oauth/token'.strip('\'') + self.clientId = os.getenv('STRAVA_CLIENT_ID').strip('\'') + self.clientSecret = os.getenv('STRAVA_CLIENT_SECRET').strip('\'') + self.authUrl = "www.strava.com/oauth/authorize?client_id={client_id}&response_type=code&redirect_uri={app_address}/strava-login&approval_prompt=auto&scope=read,activity:read".format(client_id=os.getenv('STRAVA_CLIENT_ID'), app_address=os.getenv('APP_ADDRESS') or 'http://127.0.0.1:5000').strip('\'') self.verifyToken = str(binascii.hexlify(os.urandom(24)))[2:-1] self.loginWith = True + # Handle Strava authentication. When users successfully log in to Strava, they are sent to {site-url}/strava-login @app.route('/' + self.configCode + '-login') def stravaAuth(): @@ -41,6 +40,8 @@ def stravaAuth(): # Store user activities main.userCachedData[uniqueId] = self.getActivitiesInRange() + print(main.userCachedData[uniqueId]) + if len(main.userCachedData[uniqueId]) > 0: # Render parameters page return redirect(url_for('render_parameters')) diff --git a/readme.md b/readme.md index 983de72..9e92700 100644 --- a/readme.md +++ b/readme.md @@ -1,60 +1,15 @@ # GPX Visualizer - -# Windows Environment Setup -Terminal commands in this section can be executed in Windows Powershell or Microsoft Visual Studio Code. -- Install [Python](https://www.python.org/downloads/). -- Install virtualenv: `pip3 install --user virtualenv` -- Create virtual environment: `python -m virtualenv CapstoneVenv` - - If this command opens the Microsoft Store, follow the instructions [here](https://stackoverflow.com/a/58773979) to make a command exception for Python and repeat the command. - - If this command returns an error result stating that the python command could not be found, follow the instructions [here](https://www.geeksforgeeks.org/how-to-add-python-to-windows-path/). -- Activate virtual environment: `CapstoneVenv/Scripts/activate.bat` -- Clone repo: `git clone https://github.com/joemuzina/capstone` -- Install Flask & its dependencies - - `pip3 install flask` - - `pip3 install Flask-Assets` - - `pip3 install pyscss` - - `pip3 install configparser` - - `pip3 install requests` - - `pip3 install gpxpy` - - `pip3 install pandas` - - `pip3 install tweepy` -- Complete app.cfg - - Log in to the shared Strava account. The app API tokens/etc. are in the [API dashboard](https://www.strava.com/settings/api). - - In `AUTH_URL`: replace `{ID}` with the Client ID from the dashboard - - Replace `CLIENT_ID` with the Client ID from the dashboard - - Replace `CLIENT_SECRET` with the Client Secret from the dashboard - - Replace `SECRET_KEY` with a random string, whatever you like. - - Fill in Twitter credentials using information securely sent via Bitwarden. -- Open Capstone project folder: `cd Capstone` -- Run web server using the flask executable. In my case the command is `python -m flask run` < should start the webserver. - -# Linux Environment Setup -- Clone repo: `git clone https://github.com/joemuzina/capstone` -- Install Nginx: `sudo apt-get install nginx` -- Set up Nginx to proxy the Flask server: [instructions](https://stackoverflow.com/questions/11443917/why-does-gunicorn-use-port-8000-8001-instead-of-80) -- Set Nginx upload limit to 50m: [instructions](https://learn.coderslang.com/0018-how-to-fix-error-413-request-entity-too-large-in-nginx/) -- Install Python dependencies - - Python3 venv: `apt install python3.8-venv` - - VirtualEnv: `sudo apt-get install python3-virtualenv` - - Python3: `sudo apt-get install python3` -- Create venv - - `python3 -m venv venv/` - - `.venv/bin/activate` -- Install Flask & its dependencies - - `pip3 install flask` - - `pip3 install Flask-Assets` - - `pip3 install pyscss` - - `pip3 install configparser` - - `pip3 install requests` - - `pip3 install gpxpy` - - `pip3 install pandas` - - `pip3 install tweepy` - - `pip3 install gunicorn` -- Complete app.cfg - - Log in to the shared Strava account. The app API tokens/etc. are in the [API dashboard](https://www.strava.com/settings/api). - - In `AUTH_URL`: replace `{ID}` with the Client ID from the dashboard - - Replace `CLIENT_ID` with the Client ID from the dashboard - - Replace `CLIENT_SECRET` with the Client Secret from the dashboard - - Replace `SECRET_KEY` with a random string, whatever you like. - - Fill in Twitter credentials using information securely sent via Bitwarden. -- Run web server: `bash start.sh` + +## Features +* **Activity import**: Authenticate with Strava or load activities from GPX files +* **Activity filtering**: Filter activities by date, activity type, and other attributes +* **Generate custom images**: Turn your activities into images with custom color, background, and style! +------------------ +## Building +- Install python dependencies: `pip install -r requirements.txt` +- Set environment variables (.env): + - `APP_ADDRESS`: Base address of the application where it is being served. If unset, the app will use `http://127.0.0.1:5000`. + - Strava auth data (see [Developer Dashboard](https://www.strava.com/settings/api)) + - `STRAVA_CLIENT_ID`: Strava OAUTH Client ID + - `STRAVA_CLIENT_SECRET`: Strava OAUTH Client Secret +- Run Flask locally: `python3 -m flask run` \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a447db9 Binary files /dev/null and b/requirements.txt differ diff --git a/start.sh b/start.sh deleted file mode 100644 index b9bf679..0000000 --- a/start.sh +++ /dev/null @@ -1,2 +0,0 @@ -bash startNGINX.sh -bash startVM.sh diff --git a/startNGINX.sh b/startNGINX.sh deleted file mode 100644 index 4225baf..0000000 --- a/startNGINX.sh +++ /dev/null @@ -1,5 +0,0 @@ -sudo systemctl disable nginx; -sudo systemctl stop nginx; -sudo systemctl enable nginx; -sudo systemctl start nginx; -sudo systemctl status nginx; diff --git a/startVM.sh b/startVM.sh deleted file mode 100644 index 2124196..0000000 --- a/startVM.sh +++ /dev/null @@ -1,5 +0,0 @@ -sudo systemctl disable gpx_vis; -sudo systemctl stop gpx_vis; -sudo systemctl enable gpx_vis; -sudo systemctl start gpx_vis; -sudo systemctl status gpx_vis;