-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🔧 Update the desktop app to use the new augmented API on my website
- Loading branch information
1 parent
ad9aa57
commit 7afe585
Showing
3 changed files
with
31 additions
and
169 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,6 @@ | ||
const API_URL = 'http://live.krlx.org/data.php'; | ||
const SPOTIFY_API_URL = 'https://api.spotify.com/v1/search'; | ||
const SPOTIFY_AUTH_URL = 'https://accounts.spotify.com/api/token'; | ||
const API_URL = 'https://willbeddow.com/api/krlx/v1/live'; | ||
const { shell, remote } = require('electron'); | ||
const Base64 = require('./node_modules/js-base64').Base64; | ||
const fs = require('fs'); | ||
const moment = require('./assets/moment.min.js'); | ||
const spotify_api = require('./spotify_api.json'); | ||
const { init } = require('@sentry/electron'); | ||
let visitor = remote.getCurrentWindow().visitor; | ||
|
||
|
@@ -15,57 +10,22 @@ init({ | |
dsn: 'https://[email protected]/1446827', | ||
enableNative: false, | ||
}); | ||
// The RegEx to resolve student images from the directory | ||
const DIR_REG = new RegExp('(<div class="email"><span class="icon">' + | ||
'\\n{0,1}<\\/span>(\\w+) )|<span class="icon"><\\/span><a href="mailto:(\\w+)@carleton.edu">'); | ||
const HOST_REG = new RegExp('(\\S+) ([^\\s\\d]+ )+(\'(\\d\\d)?|)|(\\S+) (\\S+)'); | ||
const UPDATE_URL = 'https://willbeddow.com/app/krlx-desktop'; | ||
let curr_songs = []; | ||
let spotify_auth = null; | ||
let song_queries = { | ||
"spotify": {}, | ||
"apple": {} | ||
}; | ||
|
||
let auth_missed = 0; | ||
|
||
/** | ||
* Take a host string in the form of Will Beddow '22 and return a widget with a picture of, and information | ||
* about, the host | ||
* @param host_str | ||
* @param host The host object, with name and image url | ||
*/ | ||
function get_host_widget(host_str){ | ||
let parsed_host_str = HOST_REG.exec(host_str); | ||
let first_name = null; | ||
let last_name = null; | ||
let class_year = null; | ||
try{ | ||
first_name = parsed_host_str[1]; | ||
last_name = parsed_host_str[2]; | ||
class_year = "20"+parsed_host_str[3]; | ||
} | ||
catch (error) { | ||
first_name = parsed_host_str[5]; | ||
last_name = parsed_host_str[6]; | ||
} | ||
let username= null; | ||
let data = $.get({ | ||
url: 'https://apps.carleton.edu/campus/directory/?first_name='+first_name+'&last_name='+last_name+'' + | ||
'&search_for=student', | ||
success: function(data){ | ||
let parsed_page = DIR_REG.exec(data); | ||
username = parsed_page[1]; | ||
if (!username){ | ||
username = parsed_page[3]; | ||
} | ||
}, | ||
async: false | ||
}); | ||
let img_url = 'https://apps.carleton.edu/stock/ldapimage.php?id='+username+'&source=campus_directory'; | ||
function get_host_widget(host){ | ||
let img_url = host.image; | ||
// Construct a widget | ||
return "<li class='list-group-item'>" + | ||
"<img class='img-thumbnail rounded-circle' width=50 size=50 src='"+img_url+"' alt='"+host_str+"'>" + | ||
"<b>"+host_str+"</b>"+ | ||
"<img class='img-thumbnail rounded-circle' width=50 size=50 src='"+img_url+"' alt='"+host.name+"'>" + | ||
"<b>"+host.name+"</b>"+ | ||
"</li>" | ||
} | ||
|
||
|
@@ -76,70 +36,11 @@ function get_song_widget(song){ | |
song_item += "<br><b>Album</b>: "+song.album; | ||
} | ||
song_item += "<br><b>Played By</b>: "+song.show_title; | ||
let yt_link = 'https://www.youtube.com/results?search_query='+song.title+"+"+song.artist; | ||
let spotify_link = null; | ||
let yt_link = song.external.youtube.link; | ||
let spotify_link = song.external.spotify.link; | ||
let apple_link = null; | ||
let album_cover = song.external.spotify.album_cover; | ||
// Check if the spotify API is available | ||
if (spotify_auth){ | ||
// Build the query string | ||
let query_string = song.title +" artist:\""+song.artist+"\""; | ||
if (song.album && song.album !== "") { | ||
query_string+= " album:\""+song.album+"\"" | ||
} | ||
if (song_queries.spotify.hasOwnProperty(query_string)){ | ||
console.log("Got cached spotify data"); | ||
let data = song_queries.spotify[query_string]; | ||
if (data.tracks.items.length >= 1){ | ||
try { | ||
spotify_link = data.tracks.items[0].external_urls.spotify; | ||
} | ||
catch (err){ | ||
console.log("Couldn't get external url of:"); | ||
console.log(data); | ||
} | ||
} | ||
} | ||
else { | ||
$.getJSON({ | ||
url: SPOTIFY_API_URL, | ||
headers: { | ||
'Authorization': "Bearer " + spotify_auth | ||
}, | ||
data: { | ||
q: query_string, | ||
limit: 1, | ||
market: "US", | ||
type: "track" | ||
}, | ||
async: false, | ||
success: function (data) { | ||
console.log("Got spotify search data"); | ||
song_queries.spotify[query_string] = data; | ||
try { | ||
if (data.tracks.items.length >= 1){ | ||
spotify_link = data.tracks.items[0].external_urls.spotify; | ||
} | ||
} | ||
catch (err){ | ||
console.log("Couldn't get external url of:"); | ||
} | ||
}, | ||
error: function (jqXHR, textStatus, errorThrown) { | ||
console.log("Spotify search errror " + jqXHR + " " + textStatus + " " + errorThrown); | ||
console.log(jqXHR); | ||
console.log(textStatus); | ||
throw errorThrown; | ||
} | ||
}); | ||
} | ||
} | ||
else{ | ||
console.warn("No spotify auth :("); | ||
auth_missed++; | ||
if (auth_missed >= 2){ | ||
spotify_basic_auth(spotify_api); | ||
} | ||
} | ||
song_item += "<br>Open in: "; | ||
if (apple_link){ | ||
song_item += "<a href='#' onclick='shell.openExternal(\""+apple_link+"\")'><i class='fab fa-apple'></i></a>" | ||
|
@@ -148,6 +49,9 @@ function get_song_widget(song){ | |
song_item += "<a href='#' onclick='shell.openExternal(\""+spotify_link+"\")'><i style='color: #1ED760' class='fab fa-spotify'></i></a>" | ||
} | ||
song_item += "<a href='#' onclick='shell.openExternal(\""+yt_link+"\")'><i style='color: #ff0000' class='fab fa-youtube'></i></a>"; | ||
if (album_cover){ | ||
song_item += '<img src="'+album_cover+'" width="50px" height="50px" style="border-radius: 5px; float: right"</img>' | ||
} | ||
song_item += "</li>"; | ||
return song_item | ||
} | ||
|
@@ -195,6 +99,8 @@ function get_show_widget(show, hosts){ | |
} | ||
|
||
function get_upcoming_widget(show){ | ||
console.log("Getting upcoming widget for "); | ||
console.log(show); | ||
let start_d = new Date(); | ||
let end_d = new Date(); | ||
//[year, month, day, hour, minute, second, millisecond] | ||
|
@@ -222,13 +128,18 @@ function get_upcoming_widget(show){ | |
until = start.toNow(); | ||
} | ||
let widget = "<div class='card mb-3'>"; | ||
let dj_widgets = []; | ||
for (let dj of show.djs){ | ||
dj_widgets.push("<img class='img-thumbnail rounded-circle' width=40 size=40 src='" | ||
+dj.image+"' alt='"+dj.name+"'><span>"+dj.name+"</span>") | ||
} | ||
widget += "<div><div class='card-header'>" + | ||
" <h5 class=\"card-title\">"+show.title+"</h5>\n" + | ||
" <h6 class='card-subtitle'>"+show.day+","+start.format("h:mm A")+"-"+end.format("h:mm A")+"</h6>\n"+ | ||
"</div>"+ | ||
" </div><div class='card-body'>\n" + | ||
" <p class=\"mb-1\">"+show.description+"</p>\n" + | ||
"<p class='mb-1'>"+show.djs.join(',')+"</p>"+ | ||
"<p class='mb-1'>"+dj_widgets.join(',')+"</p>"+ | ||
"</div><div class='card-footer'><p class='mb-1'>Starts "+until+"</p></div>"+ | ||
" </a></div></div>"; | ||
return widget | ||
|
@@ -269,30 +180,30 @@ function set_songs(page){ | |
} | ||
|
||
|
||
function handle_data(data){ | ||
console.log(data); | ||
if (data.status === "on_air"){ | ||
function handle_data(query_data){ | ||
console.log(query_data); | ||
if (query_data.status.online){ | ||
$("#currstatus")[0].innerHTML = "<span class=\"badge badge-pill badge-success\">On Air</span>"; | ||
let dj_widgets = []; | ||
for (dj of data.now.djs){ | ||
for (dj of query_data.data.now.djs){ | ||
let widget = get_host_widget(dj); | ||
dj_widgets.push(widget); | ||
} | ||
let show_widget = get_show_widget(data.now, dj_widgets); | ||
let show_widget = get_show_widget(query_data.data.now, dj_widgets); | ||
$("#currshow")[0].innerHTML = show_widget; | ||
|
||
curr_songs = data.songs; | ||
curr_songs = query_data.data.songs; | ||
set_songs(1); | ||
let next_widget = "<div>"; | ||
for (show of data.next){ | ||
for (show of query_data.data.next){ | ||
show_widget = get_upcoming_widget(show); | ||
next_widget += show_widget; | ||
} | ||
next_widget += '</div>'; | ||
$("#upcoming")[0].innerHTML = next_widget; | ||
} | ||
else{ | ||
$("#currstatus")[0].innerHTML = "<span class='badge badge-pill badge-danger'>"+data.status+"</span>"; | ||
$("#currstatus")[0].innerHTML = "<span class='badge badge-pill badge-danger'>"+query_data.status.blurb+"</span>"; | ||
} | ||
} | ||
|
||
|
@@ -307,22 +218,7 @@ function query_stream(){ | |
handle_data(data) | ||
}, | ||
error: function(jqXHR, textStatus, errorThrown){ | ||
console.log("Query errror "+jqXHR+" "+textStatus+" "+errorThrown+" trying to fix..."); | ||
$.get({ | ||
url: API_URL, | ||
success: function (data){ | ||
console.log("Replacing data..."); | ||
// Match quotes inside the string | ||
let quoteErrorRegex = new RegExp("\"(?:title|album|artist)\":\"(((?!,\"(album|artist|timestamp)\").)+\"((?!,\"(album|artist|timestamp)\").)*)\",\"(?:album|artist|timestamp)\"", 'g'); | ||
let quoteErrors = quoteErrorRegex.exec(data); | ||
if (quoteErrors[1] != null){ | ||
data = data.replace(quoteErrors[1], "Invalid Title") | ||
} | ||
let parsed_data = JSON.parse(data); | ||
console.log("Fixed stream data"); | ||
handle_data(parsed_data); | ||
} | ||
}) | ||
console.log("Query errror "+jqXHR+" "+textStatus+" "+errorThrown); | ||
} | ||
}); | ||
} | ||
|
@@ -367,40 +263,8 @@ function check_updates(){ | |
}) | ||
} | ||
|
||
/** | ||
* Log in with Spotify | ||
*/ | ||
function spotify_basic_auth(auth_data){ | ||
auth_missed = 0; | ||
console.log("Doing spotify auth"); | ||
let client_id = auth_data.client_id; | ||
let client_secret = auth_data.client_secret; | ||
let auth_str = "Basic "+Base64.encode(client_id+":"+client_secret); | ||
$.post({ | ||
url: SPOTIFY_AUTH_URL, | ||
headers: { | ||
'Authorization': auth_str | ||
}, | ||
data: { | ||
grant_type: 'client_credentials' | ||
}, | ||
success: function(data){ | ||
spotify_auth = data.access_token; | ||
console.log("Spotify auth successful. Doing again in "+data.expires_in+" seconds") | ||
// Set the token to auto refresh whenever necessary | ||
setInterval(function(){ | ||
spotify_basic_auth(data); | ||
}, data.expires_in*1000) | ||
}, | ||
error: function(jqXHR, textStatus, errorThrown){ | ||
console.log("Spotify auth errror "+jqXHR+" "+textStatus+" "+errorThrown); | ||
throw errorThrown; | ||
} | ||
}) | ||
} | ||
|
||
$(document).ready(function(){ | ||
spotify_basic_auth(spotify_api); | ||
console.log("Starting interval"); | ||
query_stream(); | ||
// The handler for checking the KRLX API every 30 seconds | ||
|