Skip to content
Permalink
Browse files

🔧 Update the desktop app to use the new augmented API on my website

  • Loading branch information...
ironman5366 committed Oct 7, 2019
1 parent ad9aa57 commit 7afe58511b1a7e5fd55dffe41173cc01806d7ce2
Showing with 31 additions and 169 deletions.
  1. +1 −1 index.html
  2. +1 −3 package.json
  3. +29 −165 page.js
@@ -54,7 +54,7 @@ <h4 class="card-title">Status: <span id="currstatus"><span class="badge badge-pi
</div>
<div class="card-footer">
<div class="row">
Made with ❤️ by Will Beddow '22 & Kristin Albright '22
Made with ❤️ by Will Beddow '22
<br>
&copy <script>document.write(new Date().getFullYear())</script>
</div>
@@ -1,6 +1,6 @@
{
"name": "krlxdesktop",
"version": "1.0.4",
"version": "1.1.0",
"description": "A desktop player for KRLX",
"main": "index.js",
"scripts": {
@@ -33,8 +33,6 @@
"category": "Music"
},
"files": [
"spotify_api.json",
"assets/spotify_api.json",
"assets/*",
"**/**"
]
194 page.js
@@ -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://79f7d930af9c4696a5229b962be84102@sentry.io/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+)&nbsp;)|<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

0 comments on commit 7afe585

Please sign in to comment.
You can’t perform that action at this time.