https://song-displayer.herokuapp.com/
- Flask is a microframework used as a backend for web apps. It is used here for exactly that; a web server backend.
- python-dotenv is a library used for accessing a
.env
file which contains sensitive information. The sensitive information in contains can vary, but usually it is used for containing API keys and secrets. This is convenient as it allows you to easily keep Git from pushing sensitive data by ignoring the.env
file. - requests is used for handling requests sent to APIs easily in Python.
- Heroku is a cloud service platform used for easily deploying webapps with as little overhead as possible. Heroku allows you to install dependencies on the host for your webapp as well as create a domain name for free.
- flask-login is a framework which is used to aid user management.
- SQLAlchemy is a tool to help bridge the gap between Python and SQL-style query languages.
- PostgresQL is an object-relational database which can easily be integrated with Heroku.
- Spotify API is used here for the following:
- Finding songs by artists
- Accessing previews of said songs
- Getting album art
- Genius API is used strictly for finding lyrics for the above songs. The lyrics are accessed directly from Genius' website.
- Create a folder which will contain the webapp
- Open a terminal and change directory into the newly created folder:
cd <directory-name>
- Fork the repository into this folder:
git clone https://github.com/csc4350-f21/project1-rydwhelchel.git
- Create a Spotify account at https://developer.spotify.com/dashboard/login
- Accept the terms
- Create an app; the name and description do not matter.
- Select the app
- Locate the Client ID and Client Secret (click "Show client secret"). You will need these later. (.env and Heroku secret section)
- Create a Genius account by going to https://genius.com/developers and clicking "Create an API Client"
- Create a new API client
- Fill out the App Name field
- Leave Icon URL field blank
- Put https://example.com for the App Website URL (or whatever you want)
- Leave the Redirect URI field blank
- Click
Generate Access Token
and save the token for later. (.env and Heroku secret section)
This is for running a app locally. This is useful if you just want to preview the webapp or if you want to test changes you make to the app. If you only interested
-
Install the requirements. If you don't have pip (and are on a linux based operating system) use:
sudo apt-get update
followed bysudo apt install pip
pip3 install requests
pip3 install python-dotenv
pip3 install Flask
sudo apt install postgresql
sudo -u postgres psql
pip install Flask-SQLAlchemy==2.1
-
Create a file called
.env
in the root directory ofproject1-rydwhelchel
(or whatever you renamed the folder to). -
Add the following lines to the
.env
file:export SPOT_SECRET='<your spotify secret here>'
export SPOT_ID='<your spotify id here>'
export GEN_ACCESS='<your genius access key here>'
-
Ensure that there is a
.gitignore
file in the root directory (wherever app.py is located). -
Ensure that in the
.gitignore
file, there is a line that says.env
. Add it if there isn't. -
In app.py, change
app.run(...)
line to justapp.run(debug=True)
. This allows you to launch the app locally. If you don't need to be able to make changes on the fly while the app is up, you can simply change it toapp.run()
. -
You're good to go! Just run app.py and click "Open Browser" on the prompt that appears (if you are using VSCode). If you aren't using VSCode, open your browser and enter
http://127.0.0.1
in the address bar. -
If you are running this on a VM, you likely will have to forward a port to access it on your local machine. I recommend using VSCode to automate this process.
This is if you want to deploy this app using Heroku on your own.
-
To start, ensure that in
app.py
, theapp.run(...)
line contains the argumentshost='0.0.0.0'
andport=int(os.getenv('PORT', 8080))
. IE:app.run( host='0.0.0.0', port=int(os.getenv('PORT', 8080)), )
-
Install Heroku using
sudo snap install --classic heroku
. While this is downloading complete steps 3- -
Make a Heroku account at https://dashboard.heroku.com/
-
Create a
requirements.txt
. Note that there may already be arequirements.txt
file. In which case, you only need to ensure that all appropriate packages are listed in it. -
Ensure that the following lines are included in
requirements.txt
Flask
python-dotenv
requests
psycopg2
flask_login
flask_SQLAlchemy
-
Add any additional packages that you have decided to add to the webapp. If you haven't added any additional third party packages ignore this step.
-
Create a
Procfile
. AProcfile
is the trigger file used by Heroku to decide how to run your app. In this case, the file is simply calledProcfile
(with no file extensions). In this file, include the lineweb: python app.py
This file may need to be modified if you have made modifications to the application.Note: this file may already be included.
-
Add and commit all changes made to files with Git
git add -A
git commit -m "<your message here>"
-
Assuming your Heroku install has finished use the following to login to Heroku via your terminal/bash
heroku login -i
-
Create a Heroku app:
heroku create
. This will create the Heroku URL as well as the associated git URL which you can push your application to. You can push to this the same way you push toorigin
by using the nameheroku
instead.Note: You may run into issues if your `main` branch is instead named `master`. Highly recommend renaming your `master` branch to `main` before continuning.
-
Next we need to create a Heroku database for this app:
heroku addons:create heroku-postgresql:hobby-dev -a <app-name>
where<app-name>
is the name of the Heroku app you just created. -
Next, get the Heroku DB URL by running
heroku config
and copy the value for DATABASE_URL. -
Enter this value in your
.env
file with the lineexport DATABASE_URL='<url>'
-
Change the value in the
DATABASE_URL
frompostgres:...
topostgresql:...
. -
Now push your project to heroku:
git push heroku main
-
Next we need to give Heroku our API IDs, secrets and tokens. If you created the .env file earlier, you can refer to that. Otherwise refer to steps 4-11 in this section.
-
Log in to https://dashboard.heroku.com/apps/
-
Select the app you created earlier in the terminal/bash.
-
Input the following, fields are seperated by colons:
-
In order to correct the Heroku database url, cd to the correct directory and run the following commands in terminal:
heroku addons:attach heroku-postgresql -a <app_name> --as HEROKU_DATABASE
heroku addons:detach DATABASE -a <app_name>
heroku config:add DATABASE_URL=<database_url>
Where <app_name>
is the name of your Heroku app and <database_url>
is the database url with postgresql
prepended instead of postgres
.
- Note that the order does not matter, however the variable names must be exactly as shown above.
- Everything should be handled! Try typing
heroku open
into terminal/bash to open your newly deployed webapp!
-
Lyric links are not 100% accurate
This is a problem that was expected, as our access of the Genius API currently only searches the site and takes the top result. Sometimes that top result isn't exactly what we want.
-
Runtime is longer than desired
This is covered above in the technical issues section. As of right now, over half of runtime is spent accessing Genius API to get a lyrics link for each song. A solution is in the making, stay tuned!
-
Error thrown when accessing some artists
When attempting to show the songs of an artist who does not have 10 songs or is a podcaster, an error will be thrown Not a perfect solution, but simply rerandomizes the artist if this issue is run into.
-
Display issues on mobile devices and smaller displays
When accessing site on mobile devices, the preview player covers the lyrics link. On smaller displays, the album images can take up too much real estate
- Adding a "guessing game" bit:
- The idea is that you display the song preview and either list several artists for the user to pick from or, if you're confident in your ability to match user input to the artist, let the user type in what they think the artist's name is. Difficulty would be deciding the list of artists to randomly pick from.
- I would consider it a problem that there is no password for your account. A lack of password security feels almost as if it is no longer your account at all. You could also list this as a future feature.
- I think my code is currently leaning towards spaghetti. On working on this milestone, I realized that many of the things I have done in this project could be further modularized and be much easier to modify and much cleaner to read. Where this is most obvious is in my routed methods (the methods within app.py). I call
get_gen_access
andget_spot_access
too often, I could just as easily call those methods within methods such asget_artist_id
to avoid repeating myself too often in the main routing methods. I think this problem was originally created because I thought it would be less repetition to call them in the routed methods, but I quickly realized during this milestone that you can have a ton of routed methods depending on requests sent.
- The first issue that jumps out to me is the issue of handling information per user. This is my first foray into handling user data within a database and it took me some time to wrap my head around the flow of it. I originally was trying to create a seperate table for each user so that each users' data would be private. I eventually realized that this wasn't quite how it worked. Storing all of the favorite artists in one table and then querying for a specific users favorite artists was much, much easier and more effective than whatever it was I trying to do. I solved this by researching how others handle user specific data, and I wish I had researched it earlier. After researching this in particular, the answer practically jumped out at me.
- I originally had issues with initializing the database due to circular imports. I went through some comments in a forum and saw that in would be beneficial to break up the logic for initializing the app and the database into 3 files rather than just 2. Utilizing this method fixed my problem immediately.