diff --git a/AnalyticsforSpotify/urls.py b/AnalyticsforSpotify/urls.py index da213ef..fbc1453 100644 --- a/AnalyticsforSpotify/urls.py +++ b/AnalyticsforSpotify/urls.py @@ -19,4 +19,7 @@ urlpatterns = [ path('analytics/', include('webBackend.urls')), + path('', include('webBackend.urls')), + path('spotify/', include('webBackend.urls')), + ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/README.md b/README.md index 7b102d2..708706d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Analytics for Spotify -### Not Currently Setup For Deployment +### WIP Self Hosted Last.FM Alternative to keeping track of your Spotify History @@ -24,3 +24,120 @@ Notes: ![Alt text](img/SpotifyAnalyticsSample.png?raw=true "Sample Output") + + +## Installation Instructions +## This contains only installation instructions. Thier are currently no Update Instructions!!! +### Instructions are for installing a VM / No Other Websites Hosted. +### This Project is a work in progress.
The database structure could change in future versions. +#### Installation Instructions are also a work in progress and were tested on Ubuntu Server 20.04.2. +I currently run this virtualized on a Virtual Machine running Debian 10. +#### Please Thoroughly Read The Instructions +### Note: +This must run on a machine that is always on or
+it must be on and running when you want to keep track of play history. + +Ideal Setup is a Local Server or a Local Machine
+ +Do not run on an external machine or allow external network access.
+It is Not Setup for Secure External Operation. + +Default Installation are as follows.
+ +### Get Spotify API Credentials: +Create a Non-Commercial Spotify App: https://developer.spotify.com/dashboard + +For API Redirect URL Box
+Same Machine: http://localhost:PORT
+Local Server http://IPV4ADDRESS:PORT
+(Replace with the Local IPv4 Address of your server)
+Port 80 is recommended. However if you already using port 80 for another service, you will need to use a different port. + +Keep Track of your Client ID, Secret Key, and Redirect Url
+ + +### Code: +SSH into Local Server or run on local machine.
+Default Installation is ~/. + +``` +cd ~/ +git clone https://github.com/ArthurVardevanyan/Analytics-for-Spotify.git +``` + + +### Database Setup : +If you have a mariaDB or mySQL database setup with proper credentials, ou may skip this section. +``` +sudo apt-get install mariadb-server +``` +Log Into MySql (sudo password, if asked) +``` +sudo mysql +``` +Within mysql Create User, Grant Privileges, and create database.
+Note: Alter statement may error out on older versions of MySql, you can ignore the error and continue. +``` +CREATE USER 'spotify'@'localhost' IDENTIFIED BY 'spotify'; +GRANT ALL PRIVILEGES ON *.* TO 'spotify'@'localhost'; +alter user 'spotify'@'localhost' identified with mysql_native_password by 'spotify'; +flush privileges; +create database spotify; +exit; +``` + +The default database credentials are: +``` +host = localhost +database = spotify +user = spotify +password = spotify +``` +### Project Setup : +Run the setup.py to setup the project. +``` +sudo apt-get install python3-pip libmariadb-dev +``` +``` +cd Analytics-for-Spotify +pip3 install -r requirements.txt && sudo pip3 install -r requirements.txt +python3 setup.py +``` + + + +### WSGI Apache WebServer Setup: +If you have an existing webserver you will need to modify the below to run on a different port / virtual host.
+Otherwise just delete everything in the file below and replace with this.
+You must change "PATH_TO_PROGRAM" with your path. +``` +sudo apt-get install apache2 libapache2-mod-wsgi-py3 +sudo nano /etc/apache2/sites-available/000-default.conf +``` + +``` + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + Alias /spotify /PATH_TO_PROGRAM/Analytics-for-Spotify/webFrontend + + Require all granted + + + + + Require all granted + + + + WSGIDaemonProcess AnalyticsforSpotify python-path=//PATH_TO_PROGRAM/Analytics-for-Spotify/ + WSGIScriptAlias / /PATH_TO_PROGRAM/Analytics-for-Spotify/AnalyticsforSpotify/wsgi.py process-group=AnalyticsforSpotify application-group=%{GLOBAL} + WSGIProcessGroup AnalyticsforSpotify + +``` + +``` +sudo systemctl restart apache2 +``` +After Navigating to the IP, Click "Start Service" diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..a08ba83 --- /dev/null +++ b/setup.py @@ -0,0 +1,106 @@ +import os +import base64 +import binascii +import urllib.parse +import mysql.connector +import json +import zipfile + + +def unzip(): + with zipfile.ZipFile("webFrontend/node_modules.zip", 'r') as zip_ref: + zip_ref.extractall("webFrontend/") + + +def executeScriptsFromFile(c, filename): + # https://stackoverflow.com/a/19473206 + # Open and read the file as a single buffer + fd = open(filename, 'r') + sqlFile = fd.read() + fd.close() + + # all SQL commands (split on ';') + sqlCommands = sqlFile.split(';') + + # Execute every command from the input file + for command in sqlCommands: + # This will skip and report errors + # For example, if the tables do not yet exist, this will skip over + # the DROP TABLE commands + try: + c.execute(command) + except: + continue + + +def main(): + print("*Disclaimer*, DO NOT USE WITH PUBLIC ACCESS") + unzip() + CLIENT = input("Enter Spotify Client Key:") + SECRET = input("Enter Spotify Secret Key:") + R_URL = input("Enter Spotify Redirect URL Key:") + B64CS = str(base64.b64encode( + ":".join([CLIENT, SECRET]).encode("utf-8")), "utf-8") + SCOPES = "&scope=user-read-currently-playing+user-read-recently-played" + URL = "https://accounts.spotify.com/authorize?client_id=" + CLIENT + \ + "&response_type=code&redirect_uri=" + \ + urllib.parse.quote_plus(R_URL) + SCOPES + API = { + "client": CLIENT, + "secret": SECRET, + "B64CS": B64CS, + "url": URL, + "redirect_url": R_URL, + } + DJANGO_PRIVATE = str(binascii.hexlify(os.urandom(24)), "utf-8") + ENV = [ + "D_DEBUG = True", + "D_SECRET = '" + str(DJANGO_PRIVATE) + "'", + "HOSTS = ['*']", + ] + with open("AnalyticsforSpotify/env.py", 'w+') as f: + f.writelines('\n'.join(ENV)) + + print("MySql / MariaDB Integration") + IP = input("Enter Database IP or (localhost):") + DB = input("Enter Database Name:") + USER = input("Enter Username:") + PASS = input("Enter Password:") + MYSQL = [ + "[client]", + "host = " + IP, + "database = " + DB, + "user = "+USER, + "password = "+PASS, + "default-character-set = utf8", + ] + with open("AnalyticsforSpotify/my.cnf", 'w+') as f: + f.writelines('\n'.join(MYSQL)) + + db = mysql.connector.connect( + host=IP, + user=USER, + passwd=PASS, + database=DB, + auth_plugin='mysql_native_password' + ) + cursor = db.cursor() + executeScriptsFromFile(cursor, "spotify.sql") + delete = "DELETE FROM `spotifyAPI` WHERE 1" + cursor.execute(delete) + add = ("INSERT IGNORE INTO spotifyAPI" + "(api)" + "VALUES (%s)") + data = ( + json.dumps(API), + ) + cursor.execute(add, data) + db.commit() + db.close + + print("Finalizing Django Setup") + os.system("python3 manage.py migrate") + + +if __name__ == "__main__": + main() diff --git a/songMonitoringBackend/log.py b/songMonitoringBackend/log.py deleted file mode 100644 index 7714012..0000000 --- a/songMonitoringBackend/log.py +++ /dev/null @@ -1,43 +0,0 @@ - -# log.py -__version__ = "v20200208" -import os -import logging -from datetime import datetime - - -def logInit(fileName, logFolder="logs/"): - global logger - logger = log(fileName, logFolder) - - -def log(fileName, logFolder): - try: - # Creates the Directory for Output - if not os.path.exists(logFolder): - os.makedirs(logFolder) - except OSError: - print("Creation of the log directory failed") - now = datetime.now() - current_time = now.strftime("%Y%m%d%H%M%S") - # Create and configure logger - logging.basicConfig(filename=logFolder+fileName + "_"+current_time+".log", - format='%(asctime)s %(message)s', - filemode='w') - # Creating an object - logger = logging.getLogger() - # Setting the threshold of logger to DEBUG - logger.setLevel(logging.DEBUG) - return logger - - -def Print(obj0, obj1="", obj2=""): - print(obj0, obj1, obj2) - logger.debug("".join([str(obj0), str(obj1), str(obj2)])) - - -def Input(obj): - logger.debug(str(obj)) - IN = input(obj) - logger.debug(str(IN)) - return IN diff --git a/songMonitoringBackend/spotify.py b/songMonitoringBackend/spotify.py index 99aeec7..4ba6414 100644 --- a/songMonitoringBackend/spotify.py +++ b/songMonitoringBackend/spotify.py @@ -1,3 +1,6 @@ +import songMonitoringBackend.playlistSongs as playlistSongs +import songMonitoringBackend.database as database +from webBackend.credentials import refresh_token as authorize import requests import time import _thread @@ -8,15 +11,6 @@ from _datetime import timedelta import sys sys.path.append("..") -from webBackend.credentials import refresh_token as authorize -import songMonitoringBackend.database as database -import songMonitoringBackend.log as log -import songMonitoringBackend.playlistSongs as playlistSongs - -os.chdir(os.path.abspath(os.path.dirname(__file__))) -log.logInit("spotify") -print = log.Print -input = log.Input def update_status(user, status, value): diff --git a/webBackend/urls.py b/webBackend/urls.py index 46efda9..7607f83 100644 --- a/webBackend/urls.py +++ b/webBackend/urls.py @@ -3,6 +3,8 @@ from . import views urlpatterns = [ + path('', views.redirect), + path('spotify/', views.redirect), path('listeningHistory/', views.listeningHistory, name='listeningHistory'), path('listeningHistoryAll/', views.listeningHistoryAll, name='listeningHistoryAll'), path('listeningHistoryShort/', views.listeningHistoryShort, name='listeningHistoryShort'), diff --git a/webBackend/views.py b/webBackend/views.py index 50695fb..eeec426 100644 --- a/webBackend/views.py +++ b/webBackend/views.py @@ -36,6 +36,9 @@ def logout(request): url = '' return HttpResponse(url, content_type="text/html") +def redirect(request): + url = '' + return HttpResponse(url, content_type="text/html") def dictfetchall(cursor): # https://stackoverflow.com/a/58969129