From 354c0935b9cccbea2a302f5c7e21730dae3e8be8 Mon Sep 17 00:00:00 2001 From: Scritches Date: Sat, 24 Mar 2018 16:20:33 -0400 Subject: [PATCH 1/7] Move spotify api key into config; Restore spotify functionality to lastfm module ~listening command --- modules/lastfm/lastfm.js | 10 +++++----- modules/spotify/README.md | 4 ++++ modules/spotify/config.json | 4 +++- modules/spotify/spotify.js | 19 ++++++++----------- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/modules/lastfm/lastfm.js b/modules/lastfm/lastfm.js index 9dbdfc1..ec79ec8 100644 --- a/modules/lastfm/lastfm.js +++ b/modules/lastfm/lastfm.js @@ -288,13 +288,13 @@ var lastfm = function(dbot) { } } - /* dbot.api.spotify.spotifySearch(term, function(body, t) { + dbot.api.spotify.spotifySearch(term, function(body, url, uri) { if(body) { - output += ' - ' + t; + output += ' - ' + url + ' - ' + uri; } - - });*/ - event.reply(output); + + event.reply(output); + }); }); } else { if(err == 'no_user') { diff --git a/modules/spotify/README.md b/modules/spotify/README.md index ec0839f..5e2d0b4 100644 --- a/modules/spotify/README.md +++ b/modules/spotify/README.md @@ -6,6 +6,10 @@ Various Spotify functionality. This module posts information on Spotify links, as well as providing Spotify search functionality. +### config.json +Edit the "api_key_clientid" setting with your Spotify API client ID. Edit the +"api_key_clientsecret" setting with your Spotify API client secret. + ## Commands ### ~spotify [query] diff --git a/modules/spotify/config.json b/modules/spotify/config.json index 0b1135b..4eb225e 100644 --- a/modules/spotify/config.json +++ b/modules/spotify/config.json @@ -1,5 +1,7 @@ { "dependencies": [ "link" ], "ignorable": true, - "outputPrefix": "\u00039spotify\u000f" + "outputPrefix": "\u00039spotify\u000f", + "api_key_clientid": "blah", + "api_key_clientsecret": "blah" } diff --git a/modules/spotify/spotify.js b/modules/spotify/spotify.js index 72e6743..39ff8a8 100644 --- a/modules/spotify/spotify.js +++ b/modules/spotify/spotify.js @@ -21,16 +21,15 @@ var spotify = function(dbot) { this.spotifyText = '\u00039spotify\u000f'; this.spotifyAuthUrl = 'https://accounts.spotify.com/api/token'; - // ClientID and ClientSecret come from the spotify developer center; you will need to supply your own. - this.spotifyClientID = 'e2491c50879a4d7f900dcefcc74b7c90'; - this.spotifyClientSecret = 'b29da299612e4e659099ab3367ffa3f4'; - this.spotifyAuth = new Buffer(this.spotifyClientID + ":" + this.spotifyClientSecret).toString("base64"); - + this.auth = false; + this.authenticate = function(callback) { + this.auth = this.auth || new Buffer(this.config.api_key_clientid + ":" + this.config.api_key_clientsecret).toString("base64"); + request({ url: this.spotifyAuthUrl, method: "POST", - headers: { Authorization: "Basic " + this.spotifyAuth }, + headers: { Authorization: "Basic " + this.auth }, form: { grant_type: "client_credentials" } }, function(error, response, body) { if (!error && response.statusCode == 200) { @@ -83,11 +82,9 @@ var spotify = function(dbot) { }, function(error, response, body) { if(!error && response.statusCode == 200) { if(_.has(body, 'tracks') && body.tracks.items[0] && _.has(body.tracks.items[0], 'href')) { - var t = body.tracks.items[0].href; - ///*t = t.replace(/:/g, '/'); - t = t.replace(/api.spotify.com\/v1\/tracks/, - 'open.spotify.com/track'); - callback(body, t); + var url = body.tracks.items[0].href; + url = url.replace(/api.spotify.com\/v1\/tracks/, 'open.spotify.com/track'); + callback(body, url, body.tracks.items[0].uri); } else { callback(false); } From bd148915ed0bb814971e8031cef5b5312502500c Mon Sep 17 00:00:00 2001 From: Scritches Date: Sat, 24 Mar 2018 17:21:26 -0400 Subject: [PATCH 2/7] test --- run.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/run.js b/run.js index dc8e5cf..8a0247a 100644 --- a/run.js +++ b/run.js @@ -1,4 +1,4 @@ -var fs = require('fs'), + var fs = require('fs'), _ = require('underscore')._, jsbot = require('./jsbot/jsbot'), DatabaseDriver = require('./database').DatabaseDriver, @@ -6,7 +6,7 @@ var fs = require('fs'), require('./snippets'); var DBot = function() { - + /*** Load the DB ***/ if(fs.existsSync('db.json')) { try { @@ -44,11 +44,11 @@ var DBot = function() { this.instance.addConnection(name, server.server, server.port, this.config.admin, function(event) { var server = this.config.servers[event.server]; - + _.each(server.channels, function(channel) { this.instance.join(event, channel); }, this); - }.bind(this), server.nickserv, server.password); + }.bind(this), server.nickserv, server.password); }, this); // Load the modules and connect to the server @@ -63,7 +63,7 @@ DBot.prototype.reloadConfig = function() { console.log('Error: config.json file does not exist. Stopping'); process.exit(); } - + try { var configFile = fs.readFileSync('config.json', 'utf-8'); this.config = JSON.parse(configFile); @@ -96,11 +96,11 @@ DBot.prototype.say = function(server, channel, message) { // Format given stored string in config language DBot.prototype.t = function(string, formatData) { var formattedString = 'String not found. Something has gone screwy. Maybe.'; - + if(_.has(this.strings, string)) { var lang = this.config.language; if(!_.has(this.strings[string], lang)) { - lang = "en"; + lang = "en"; } if(_.has(this.strings[string], lang)) { @@ -113,7 +113,7 @@ DBot.prototype.t = function(string, formatData) { } } } - + return formattedString; }; @@ -146,7 +146,7 @@ DBot.prototype.reloadModules = function() { this.usage = {}; this.reloadConfig(); this.ddb.createDB(name, this.config.dbType, {}, function(db) {}); - + try { this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8')); } catch(err) { @@ -155,7 +155,7 @@ DBot.prototype.reloadModules = function() { var moduleNames = this.config.moduleNames; - // Enforce having command. it can still be reloaded, but dbot _will not_ + // Enforce having command. it can still be reloaded, but dbot _will not_ // function without it, so not having it should be impossible if(!_.include(moduleNames, 'command')) { moduleNames.push("command"); @@ -244,15 +244,15 @@ DBot.prototype.reloadModules = function() { if(propertyKey) delete require.cache[propertyKey]; propertyObj = require(moduleDir + property).fetch(this); } catch(err) { - console.log('Module error (' + module.name + ') in ' + + console.log('Module error (' + module.name + ') in ' + property + ': ' + err); - } + } } if(!_.has(module, property)) module[property] = {}; _.extend(module[property], propertyObj); _.each(module[property], function(item, itemName) { - item.module = name; + item.module = name; if(_.has(module.config, property) && _.has(module.config[property], itemName)) { _.extend(item, module.config[property][itemName]); } @@ -283,7 +283,7 @@ DBot.prototype.reloadModules = function() { try { propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); } catch(err) { - console.log('Data error (' + module.name + ') in ' + + console.log('Data error (' + module.name + ') in ' + property + ': ' + err); }; _.extend(this[property], propertyData); From 72a45527422055c11c8f4526e7f96954c677b18f Mon Sep 17 00:00:00 2001 From: Scritches Date: Sat, 24 Mar 2018 17:22:22 -0400 Subject: [PATCH 3/7] Revert "test" This reverts commit bd148915ed0bb814971e8031cef5b5312502500c. --- run.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/run.js b/run.js index 8a0247a..dc8e5cf 100644 --- a/run.js +++ b/run.js @@ -1,4 +1,4 @@ - var fs = require('fs'), +var fs = require('fs'), _ = require('underscore')._, jsbot = require('./jsbot/jsbot'), DatabaseDriver = require('./database').DatabaseDriver, @@ -6,7 +6,7 @@ require('./snippets'); var DBot = function() { - + /*** Load the DB ***/ if(fs.existsSync('db.json')) { try { @@ -44,11 +44,11 @@ var DBot = function() { this.instance.addConnection(name, server.server, server.port, this.config.admin, function(event) { var server = this.config.servers[event.server]; - + _.each(server.channels, function(channel) { this.instance.join(event, channel); }, this); - }.bind(this), server.nickserv, server.password); + }.bind(this), server.nickserv, server.password); }, this); // Load the modules and connect to the server @@ -63,7 +63,7 @@ DBot.prototype.reloadConfig = function() { console.log('Error: config.json file does not exist. Stopping'); process.exit(); } - + try { var configFile = fs.readFileSync('config.json', 'utf-8'); this.config = JSON.parse(configFile); @@ -96,11 +96,11 @@ DBot.prototype.say = function(server, channel, message) { // Format given stored string in config language DBot.prototype.t = function(string, formatData) { var formattedString = 'String not found. Something has gone screwy. Maybe.'; - + if(_.has(this.strings, string)) { var lang = this.config.language; if(!_.has(this.strings[string], lang)) { - lang = "en"; + lang = "en"; } if(_.has(this.strings[string], lang)) { @@ -113,7 +113,7 @@ DBot.prototype.t = function(string, formatData) { } } } - + return formattedString; }; @@ -146,7 +146,7 @@ DBot.prototype.reloadModules = function() { this.usage = {}; this.reloadConfig(); this.ddb.createDB(name, this.config.dbType, {}, function(db) {}); - + try { this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8')); } catch(err) { @@ -155,7 +155,7 @@ DBot.prototype.reloadModules = function() { var moduleNames = this.config.moduleNames; - // Enforce having command. it can still be reloaded, but dbot _will not_ + // Enforce having command. it can still be reloaded, but dbot _will not_ // function without it, so not having it should be impossible if(!_.include(moduleNames, 'command')) { moduleNames.push("command"); @@ -244,15 +244,15 @@ DBot.prototype.reloadModules = function() { if(propertyKey) delete require.cache[propertyKey]; propertyObj = require(moduleDir + property).fetch(this); } catch(err) { - console.log('Module error (' + module.name + ') in ' + + console.log('Module error (' + module.name + ') in ' + property + ': ' + err); - } + } } if(!_.has(module, property)) module[property] = {}; _.extend(module[property], propertyObj); _.each(module[property], function(item, itemName) { - item.module = name; + item.module = name; if(_.has(module.config, property) && _.has(module.config[property], itemName)) { _.extend(item, module.config[property][itemName]); } @@ -283,7 +283,7 @@ DBot.prototype.reloadModules = function() { try { propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); } catch(err) { - console.log('Data error (' + module.name + ') in ' + + console.log('Data error (' + module.name + ') in ' + property + ': ' + err); }; _.extend(this[property], propertyData); From 25d572e8cbc6a06236b788ea4c7db6cf533da297 Mon Sep 17 00:00:00 2001 From: Scritches Date: Sat, 24 Mar 2018 19:24:57 -0400 Subject: [PATCH 4/7] lastfm ~listening: make youtube and spotify api calls in parallel --- modules/lastfm/lastfm.js | 47 ++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/modules/lastfm/lastfm.js b/modules/lastfm/lastfm.js index ec79ec8..db9ab7b 100644 --- a/modules/lastfm/lastfm.js +++ b/modules/lastfm/lastfm.js @@ -280,22 +280,41 @@ var lastfm = function(dbot) { 'artist': track.artist['#text'] }); } - dbot.api.youtube.search(term, function(body) { - if(_.isObject(body) && _.has(body, 'items') && body.items.length > 0) { - var link = body.items[0].id.videoId - if(link) { - output += ' - http://youtu.be/' + link; - } + + async.parallel({ + youtube: function(cb) { + dbot.api.youtube.search(term, function(body) { + if(_.isObject(body) && _.has(body, 'items') && body.items.length > 0) { + var link = body.items[0].id.videoId + if(link) { + cb(null,"http://youtu.be/" + link); + } else { + cb(null, undefined); + } + } + }); + }, + spotify: function(cb) { + dbot.api.spotify.spotifySearch(term, function(body, url, uri) { + if(body) { + cb(null, { url:url, uri:uri }); + } else { + cb(null, undefined); + } + }); } - - dbot.api.spotify.spotifySearch(term, function(body, url, uri) { - if(body) { - output += ' - ' + url + ' - ' + uri; - } - - event.reply(output); - }); + }, function(err, results) { + if (results.youtube || results.spotify) output += " - " + + if (results.youtube) output += results.youtube; + if (results.spotify) { + if (results.youtube) output += " | "; + output += results.spotify.url + " - " + results.spotify.uri; + } + + event.reply(output); }); + } else { if(err == 'no_user') { event.reply('Unknown LastFM user.'); From 167525b5b9bc0957cef73570fd6d5ecfe623cbd3 Mon Sep 17 00:00:00 2001 From: Scritches Date: Sat, 24 Mar 2018 20:57:57 -0400 Subject: [PATCH 5/7] Added ~ytpl command to search youtube for playlists --- modules/youtube/strings.json | 5 ++++ modules/youtube/youtube.js | 49 +++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/modules/youtube/strings.json b/modules/youtube/strings.json index 51a3b55..251d7f7 100644 --- a/modules/youtube/strings.json +++ b/modules/youtube/strings.json @@ -4,6 +4,11 @@ "it": "[{title} di {author} — \u000312▶\u000f{plays} ({minutes}:{seconds}) (\u00039▲{likes}\u000f|\u000312{dislikes}▼\u000f)]", "de": "[{title} von {author} — \u000312▶\u000f{plays} ({minutes}:{seconds}) (\u00039▲{likes}\u000f|\u000312{dislikes}▼\u000f)]" }, + + "yt_playlist": { + "en": "[{title} by {author} - \u000312▶\u000f{videos} videos\u000f)]" + }, + "yt_noresults": { "en": "No results found.", "it": "Nessun risultato.", diff --git a/modules/youtube/youtube.js b/modules/youtube/youtube.js index 0bd73d9..154d1e1 100644 --- a/modules/youtube/youtube.js +++ b/modules/youtube/youtube.js @@ -10,14 +10,16 @@ var youtube = function(dbot) { this.LinkRegex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/; this.api = { - 'search': function(term, callback) { + 'search': function(term, callback, type) { + type = type || "video" var qs = _.clone(this.params); request.get(this.ApiRoot + 'search', { 'qs': { 'key': this.config.api_key, 'q': term, 'maxResults': 1, - 'part': "snippet" + 'part': "snippet", + 'type': type }, 'json': true }, function(error, response, body) { @@ -58,10 +60,25 @@ var youtube = function(dbot) { } return res; - }.bind(this) + }.bind(this), + + 'formatPlaylistLink': function(v) { + var res = dbot.t('yt_playlist', { + 'title': v.snippet.title, + 'author': v.snippet.channelTitle, + 'videos': v.contentDetails.itemCount + }); + + if (v.id) { + res += " - https://www.youtube.com/playlist?list=" + v.id; + } + + return res; + } }; this.commands = { + // search for a youtube video '~yt': function(event) { this.api.search(event.input[1], function(body) { if(_.isObject(body) && _.has(body, 'items') && body.items.length > 0) { @@ -81,10 +98,34 @@ var youtube = function(dbot) { } else { event.reply(dbot.t('yt_noresults')); } - }.bind(this)); + }.bind(this), "video"); + }, + + // search for a youtube playlist + '~ytpl': function(event) { + this.api.search(event.input[1], function(body) { + if(_.isObject(body) && _.has(body, 'items') && body.items.length > 0) { + request.get(this.ApiRoot + 'playlists' , { + 'qs': { + 'key': this.config.api_key, + 'id': body.items[0].id.playlistId, + 'maxResults': 1, + 'part': "snippet,contentDetails" + }, + 'json': true + }, function(error, response, body) { + if(_.isObject(body) && _.has(body, 'items') && body.items.length > 0) { + event.reply(this.internalAPI.formatPlaylistLink(body.items[0])); + } + }.bind(this)); + } else { + event.reply(dbot.t('yt_noresults')); + } + }.bind(this), "playlist"); } }; this.commands['~yt'].regex = [/^yt (.+)$/, 2]; + this.commands['~ytpl'].regex = [/^ytpl (.+)$/, 2]; this.onLoad = function() { dbot.api.link.addHandler(this.name, this.LinkRegex, From 0118f962b6797454570ad77ca9c90933f26f42b3 Mon Sep 17 00:00:00 2001 From: Scritches Date: Sat, 24 Mar 2018 21:11:46 -0400 Subject: [PATCH 6/7] Include spotify desktop URI in ~syt results --- modules/spotify/spotify.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/spotify/spotify.js b/modules/spotify/spotify.js index 39ff8a8..419c31b 100644 --- a/modules/spotify/spotify.js +++ b/modules/spotify/spotify.js @@ -129,7 +129,8 @@ var spotify = function(dbot) { function(a) { return a.name }).join(', '), 'album': body.tracks.items[0].album.name, 'track': body.tracks.items[0].name, - 'url': t + 'url': t, + 'uri': body.tracks.items[0].uri })); } else { event.reply(dbot.t('not-found')); From ff7be1f31d5f978f54daa8fda85aacee3e6d3e14 Mon Sep 17 00:00:00 2001 From: Scritches Date: Sat, 24 Mar 2018 22:10:57 -0400 Subject: [PATCH 7/7] https instead of http for ~listening youtube link --- modules/lastfm/lastfm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lastfm/lastfm.js b/modules/lastfm/lastfm.js index db9ab7b..1ad9813 100644 --- a/modules/lastfm/lastfm.js +++ b/modules/lastfm/lastfm.js @@ -287,7 +287,7 @@ var lastfm = function(dbot) { if(_.isObject(body) && _.has(body, 'items') && body.items.length > 0) { var link = body.items[0].id.videoId if(link) { - cb(null,"http://youtu.be/" + link); + cb(null,"https://youtu.be/" + link); } else { cb(null, undefined); }