mirror of
https://github.com/KevinMidboe/zoff.git
synced 2025-10-29 01:40:24 +00:00
675 lines
19 KiB
JavaScript
675 lines
19 KiB
JavaScript
var path = require("path");
|
|
var time_regex = /P((([0-9]*\.?[0-9]*)Y)?(([0-9]*\.?[0-9]*)M)?(([0-9]*\.?[0-9]*)W)?(([0-9]*\.?[0-9]*)D)?)?(T(([0-9]*\.?[0-9]*)H)?(([0-9]*\.?[0-9]*)M)?(([0-9]*\.?[0-9]*)S)?)?/;
|
|
try {
|
|
var keys = require(path.join(__dirname, "../config/api_key.js"));
|
|
var key = keys.youtube;
|
|
var soundcloudKey = keys.soundcloud;
|
|
} catch (e) {
|
|
console.log(
|
|
"(!) Missing file - /config/api_key.js Have a look at /config/api_key.example.js. The server won't run without this existing."
|
|
);
|
|
process.exit(1);
|
|
}
|
|
var request = require("request");
|
|
var db = require(pathThumbnails + "/handlers/db.js");
|
|
var countryCodes = ["US", "NO", "SE", "DK", "CA", "EU", "UK"];
|
|
|
|
function check_if_error_or_blocked(id, channel, errored, callback) {
|
|
if (!errored) {
|
|
callback(false);
|
|
return;
|
|
}
|
|
db.collection(channel).find({ id: id, now_playing: true }, function(
|
|
err,
|
|
song
|
|
) {
|
|
if (song.length == 0) {
|
|
callback(false);
|
|
return;
|
|
}
|
|
var song_info = song[0];
|
|
if (song_info.source != "soundcloud") {
|
|
request(
|
|
{
|
|
type: "GET",
|
|
url:
|
|
"https://www.googleapis.com/youtube/v3/videos?part=id,status,contentDetails&key=" +
|
|
key +
|
|
"&id=" +
|
|
song_info.id
|
|
},
|
|
function(error, response, body) {
|
|
try {
|
|
var resp = JSON.parse(body);
|
|
if (resp.pageInfo.totalResults == 0) {
|
|
callback(true);
|
|
return;
|
|
} else if (!resp.items[0].status.embeddable) {
|
|
callback(true);
|
|
return;
|
|
} else if (
|
|
resp.items[0].contentDetails.hasOwnProperty("licensedContent") &&
|
|
resp.items[0].contentDetails.licensedContent
|
|
) {
|
|
callback(true);
|
|
return;
|
|
} else if (
|
|
resp.items[0].contentDetails.hasOwnProperty(
|
|
"regionRestriction"
|
|
) &&
|
|
resp.items[0].contentDetails.regionRestriction.hasOwnProperty(
|
|
"blocked"
|
|
) &&
|
|
resp.items[0].contentDetails.regionRestriction.blocked.length > 0
|
|
) {
|
|
var any = resp.items[0].contentDetails.blocked.some(function(
|
|
element
|
|
) {
|
|
return countryCodes.indexOf(element) > -1;
|
|
});
|
|
if (any) {
|
|
callback(true);
|
|
return;
|
|
}
|
|
}
|
|
callback(false);
|
|
return;
|
|
} catch (e) {
|
|
callback(true);
|
|
return;
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
request(
|
|
{
|
|
type: "GET",
|
|
url:
|
|
"http://api.soundcloud.com/tracks/" +
|
|
song_info.id +
|
|
"?client_id=" +
|
|
soundcloudKey
|
|
},
|
|
function(error, response, body) {
|
|
try {
|
|
var resp = JSON.parse(body);
|
|
if (resp.sharing != "public" || resp.embeddable_by != "all") {
|
|
callback(true);
|
|
return;
|
|
}
|
|
callback(false);
|
|
return;
|
|
} catch (e) {
|
|
callback(true);
|
|
return;
|
|
}
|
|
}
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
function filterFunction(el) {
|
|
return el != null && el != "" && el != undefined && el.trim() != "";
|
|
}
|
|
|
|
function get_genres_soundcloud(song, channel) {
|
|
request(
|
|
"http://api.soundcloud.com/tracks/" +
|
|
song.id +
|
|
"?client_id=" +
|
|
soundcloudKey,
|
|
function(err, response, body) {
|
|
if (err) {
|
|
console.log("error start", err, song, "error end");
|
|
return;
|
|
}
|
|
try {
|
|
var object = JSON.parse(body);
|
|
if (
|
|
!object.hasOwnProperty("genre") ||
|
|
!object.hasOwnProperty("tag_list")
|
|
)
|
|
return;
|
|
var genre = object.genre + ",";
|
|
genre = genre
|
|
.toLowerCase()
|
|
.split(",")
|
|
.concat(object.tag_list.toLowerCase().split('"'));
|
|
genre = genre.filter(filterFunction);
|
|
|
|
db.collection(channel).update(
|
|
{ id: song.id },
|
|
{
|
|
$set: {
|
|
tags: genre
|
|
}
|
|
},
|
|
function(e, d) {}
|
|
);
|
|
} catch (e) {
|
|
console.log("errored 2", e);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
function get_genres_list(list, channel) {
|
|
var youtube_array = "";
|
|
var i = 0;
|
|
try {
|
|
for (var i = 0; i < list.length; i++) {
|
|
if (!list[i].hasOwnProperty("id")) continue;
|
|
if (list[i].source == undefined || list[i].source == "youtube") {
|
|
youtube_array += list[i].id + ",";
|
|
} else if (
|
|
list[i].source != undefined &&
|
|
list[i].source == "soundcloud"
|
|
) {
|
|
get_genres_soundcloud(list[i], channel);
|
|
}
|
|
}
|
|
if (youtube_array.length > 0) {
|
|
if (youtube_array > 49) {
|
|
var subList = [];
|
|
for (var i = 0; i < youtube_array.length; i++) {
|
|
subList.push(youtube_array[i]);
|
|
if (subList.length > 49) {
|
|
get_genres_youtube(subList.join(","), channel);
|
|
subList = [];
|
|
}
|
|
}
|
|
get_genres_youtube(subList.join(","), channel);
|
|
subList = [];
|
|
} else {
|
|
get_genres_youtube(youtube_array, channel);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.log("errored", e);
|
|
return;
|
|
}
|
|
}
|
|
|
|
function start_soundcloud_get(arr, channel, callback) {
|
|
get_genres_soundcloud_recursive(arr, channel, 0, callback);
|
|
}
|
|
|
|
function get_genres_soundcloud_recursive(arr, channel, i, callback) {
|
|
if (i >= arr.length) {
|
|
if (typeof callback == "function") callback();
|
|
return;
|
|
}
|
|
var song = arr[i];
|
|
request(
|
|
"http://api.soundcloud.com/tracks/" +
|
|
song.id +
|
|
"?client_id=" +
|
|
soundcloudKey,
|
|
function(err, response, body) {
|
|
if (err) {
|
|
console.log("error start", err, song, "error end");
|
|
get_genres_soundcloud_recursive(arr, channel, i + 1, callback);
|
|
return;
|
|
}
|
|
try {
|
|
var object = JSON.parse(body);
|
|
if (
|
|
!object.hasOwnProperty("genre") ||
|
|
!object.hasOwnProperty("tag_list")
|
|
) {
|
|
get_genres_soundcloud_recursive(arr, channel, i + 1, callback);
|
|
return;
|
|
}
|
|
var genre = object.genre + ",";
|
|
genre = genre
|
|
.toLowerCase()
|
|
.split(",")
|
|
.concat(object.tag_list.toLowerCase().split('"'));
|
|
genre = genre.filter(filterFunction);
|
|
|
|
db.collection(channel).update(
|
|
{ id: song.id },
|
|
{
|
|
$set: {
|
|
tags: genre
|
|
}
|
|
},
|
|
function(e, d) {
|
|
get_genres_soundcloud_recursive(arr, channel, i + 1, callback);
|
|
}
|
|
);
|
|
} catch (e) {
|
|
console.log("errored 2", e);
|
|
get_genres_soundcloud_recursive(arr, channel, i + 1, callback);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
function get_genres_list_recursive(list, channel, callback) {
|
|
var youtube_array = [];
|
|
var soundcloud_array = [];
|
|
for (var i = 0; i < list.length; i++) {
|
|
if (!list[i].hasOwnProperty("id")) continue;
|
|
if (list[i].source == undefined || list[i].source == "youtube") {
|
|
youtube_array.push(list[i]);
|
|
} else if (list[i].source != undefined && list[i].source == "soundcloud") {
|
|
soundcloud_array.push(list[i]);
|
|
}
|
|
}
|
|
start_youtube_get(youtube_array, channel, function() {
|
|
start_soundcloud_get(soundcloud_array, channel, function() {
|
|
if (typeof callback == "function") callback();
|
|
});
|
|
});
|
|
}
|
|
|
|
function start_youtube_get(arr, channel, callback) {
|
|
get_genres_youtube_recursive(arr, channel, 0, callback);
|
|
}
|
|
|
|
function get_genres_youtube_recursive(arr, channel, i, callback) {
|
|
if (i >= arr.length) {
|
|
if (typeof callback == "function") callback();
|
|
return;
|
|
}
|
|
var ids = [];
|
|
for (var y = i; y < arr.length; y++) {
|
|
if (ids.length >= 48) {
|
|
break;
|
|
}
|
|
ids.push(arr[y].id);
|
|
}
|
|
request(
|
|
{
|
|
type: "GET",
|
|
url:
|
|
"https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id,topicDetails&key=" +
|
|
key +
|
|
"&id=" +
|
|
ids.join(",")
|
|
},
|
|
function(error, response, body) {
|
|
if (error) {
|
|
get_genres_youtube_recursive(arr, channel, i + ids.length, callback);
|
|
return;
|
|
}
|
|
var resp = JSON.parse(body);
|
|
if (!resp.hasOwnProperty("items")) {
|
|
get_genres_youtube_recursive(arr, channel, i + ids.length, callback);
|
|
return;
|
|
}
|
|
if (resp.items.length > 0) {
|
|
for (var z = 0; z < resp.items.length; z++) {
|
|
if (!resp.items[z].hasOwnProperty("topicDetails")) continue;
|
|
var genre = resp.items[z].topicDetails.topicCategories;
|
|
genre = genre.join(",");
|
|
genre = genre.replace(
|
|
new RegExp("https://en.wikipedia.org/wiki/", "g"),
|
|
""
|
|
);
|
|
genre = genre
|
|
.replace(/_/g, " ")
|
|
.toLowerCase()
|
|
.split(",");
|
|
genre = genre.filter(filterFunction);
|
|
//console.log(resp.items[i].id + " - ", genre);
|
|
db.collection(channel).update(
|
|
{ id: resp.items[z].id },
|
|
{
|
|
$set: {
|
|
tags: genre
|
|
}
|
|
},
|
|
function(e, d) {}
|
|
);
|
|
}
|
|
get_genres_youtube_recursive(arr, channel, i + ids.length, callback);
|
|
} else {
|
|
get_genres_youtube_recursive(arr, channel, i + ids.length, callback);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
function get_genres_youtube(ids, channel) {
|
|
request(
|
|
{
|
|
type: "GET",
|
|
url:
|
|
"https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id,topicDetails&key=" +
|
|
key +
|
|
"&id=" +
|
|
ids
|
|
},
|
|
function(error, response, body) {
|
|
if (error) {
|
|
return;
|
|
}
|
|
var resp = JSON.parse(body);
|
|
if (!resp.hasOwnProperty("items")) {
|
|
return;
|
|
}
|
|
if (resp.items.length > 0) {
|
|
for (var i = 0; i < resp.items.length; i++) {
|
|
if (!resp.items[i].hasOwnProperty("topicDetails")) continue;
|
|
var genre = resp.items[i].topicDetails.topicCategories;
|
|
genre = genre.join(",");
|
|
genre = genre.replace(
|
|
new RegExp("https://en.wikipedia.org/wiki/", "g"),
|
|
""
|
|
);
|
|
genre = genre
|
|
.replace(/_/g, " ")
|
|
.toLowerCase()
|
|
.split(",");
|
|
genre = genre.filter(filterFunction);
|
|
//console.log(resp.items[i].id + " - ", genre);
|
|
db.collection(channel).update(
|
|
{ id: resp.items[i].id },
|
|
{
|
|
$set: {
|
|
tags: genre
|
|
}
|
|
},
|
|
function(e, d) {}
|
|
);
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
function get_correct_info(song_generated, channel, broadcast, callback) {
|
|
//channel = channel.replace(/ /g,'');
|
|
request(
|
|
{
|
|
type: "GET",
|
|
url:
|
|
"https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id,topicDetails&key=" +
|
|
key +
|
|
"&id=" +
|
|
song_generated.id
|
|
},
|
|
function(error, response, body) {
|
|
try {
|
|
var resp = JSON.parse(body);
|
|
if (resp.items.length == 1) {
|
|
var duration = parseInt(
|
|
durationToSeconds(resp.items[0].contentDetails.duration)
|
|
);
|
|
var title = resp.items[0].snippet.localized.title;
|
|
var genre = resp.items[0].topicDetails.topicCategories;
|
|
genre = genre.join(",");
|
|
genre = genre.replace(
|
|
new RegExp("https://en.wikipedia.org/wiki/", "g"),
|
|
""
|
|
);
|
|
genre = genre
|
|
.replace(/_/g, " ")
|
|
.toLowerCase()
|
|
.split(",");
|
|
genre = genre.filter(filterFunction);
|
|
//console.log(genre + " - ", song_generated.id);
|
|
if (
|
|
title != song_generated.title ||
|
|
duration < parseInt(song_generated.duration)
|
|
) {
|
|
if (title != song_generated.title) {
|
|
song_generated.title = title;
|
|
}
|
|
if (duration < parseInt(song_generated.duration)) {
|
|
song_generated.duration = duration;
|
|
song_generated.start = 0;
|
|
song_generated.end = duration;
|
|
}
|
|
db.collection(channel).update(
|
|
{ id: song_generated.id },
|
|
{
|
|
$set: {
|
|
duration: song_generated.duration,
|
|
start: song_generated.start,
|
|
end: song_generated.end,
|
|
title: song_generated.title,
|
|
tags: genre
|
|
}
|
|
},
|
|
function(err, docs) {
|
|
if (broadcast && docs.nModified == 1) {
|
|
song_generated.new_id = song_generated.id;
|
|
//if(song_generated.type == "video")
|
|
if (typeof callback == "function") {
|
|
callback(song_generated, true);
|
|
} else {
|
|
io.to(channel).emit("channel", {
|
|
type: "changed_values",
|
|
value: song_generated
|
|
});
|
|
}
|
|
} else {
|
|
if (typeof callback == "function") {
|
|
callback(song_generated, true);
|
|
}
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
db.collection(channel).update(
|
|
{ id: song_generated.id },
|
|
{
|
|
$set: {
|
|
tags: genre
|
|
}
|
|
},
|
|
function(e, d) {
|
|
if (typeof callback == "function") {
|
|
callback(song_generated, true);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
} else {
|
|
findSimilar(song_generated, channel, broadcast, callback);
|
|
}
|
|
} catch (e) {
|
|
if (typeof callback == "function") {
|
|
callback({}, false);
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
function check_error_video(msg, channel) {
|
|
if (
|
|
!msg.hasOwnProperty("id") ||
|
|
!msg.hasOwnProperty("title") ||
|
|
typeof msg.id != "string" ||
|
|
typeof msg.title != "string"
|
|
) {
|
|
var result = {
|
|
id: {
|
|
expected: "string",
|
|
got: msg.hasOwnProperty("id") ? typeof msg.id : undefined
|
|
},
|
|
title: {
|
|
expected: "string",
|
|
got: msg.hasOwnProperty("title") ? typeof msg.title : undefined
|
|
}
|
|
};
|
|
return;
|
|
}
|
|
if (msg.source == "soundcloud") return;
|
|
//channel = channel.replace(/ /g,'');
|
|
request(
|
|
{
|
|
type: "GET",
|
|
url:
|
|
"https://www.googleapis.com/youtube/v3/videos?part=id&key=" +
|
|
key +
|
|
"&id=" +
|
|
msg.id
|
|
},
|
|
function(error, response, body) {
|
|
try {
|
|
var resp = JSON.parse(body);
|
|
if (resp.pageInfo.totalResults == 0) {
|
|
findSimilar(msg, channel, true, undefined);
|
|
}
|
|
} catch (e) {
|
|
console.log(msg.id, key, e, body);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
function findSimilar(msg, channel, broadcast, callback) {
|
|
//channel = channel.replace(/ /g,'');
|
|
var yt_url =
|
|
"https://www.googleapis.com/youtube/v3/search?key=" +
|
|
key +
|
|
"&videoEmbeddable=true&part=id&type=video&order=viewCount&safeSearch=none&maxResults=5&q=" +
|
|
encodeURIComponent(msg.title);
|
|
request(
|
|
{
|
|
method: "GET",
|
|
url: yt_url
|
|
},
|
|
function(error, response, body) {
|
|
var resp = JSON.parse(body);
|
|
if (resp.items.length > 0) {
|
|
var vid_url =
|
|
"https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id&key=" +
|
|
key +
|
|
"&id=";
|
|
for (var i = 0; i < resp.items.length; i++) {
|
|
vid_url += resp.items[i].id.videoId + ",";
|
|
}
|
|
request(
|
|
{
|
|
type: "GET",
|
|
url: vid_url
|
|
},
|
|
function(error, response, body) {
|
|
var resp = JSON.parse(body);
|
|
var found = false;
|
|
var element = {};
|
|
for (var i = 0; i < resp.items.length; i++) {
|
|
if (
|
|
similarity(resp.items[i].snippet.localized.title, msg.title) >
|
|
0.75
|
|
) {
|
|
found = true;
|
|
element = {
|
|
title: resp.items[i].snippet.localized.title,
|
|
duration: parseInt(
|
|
durationToSeconds(resp.items[i].contentDetails.duration)
|
|
),
|
|
id: resp.items[i].id,
|
|
start: 0,
|
|
end: parseInt(
|
|
durationToSeconds(resp.items[i].contentDetails.duration)
|
|
)
|
|
};
|
|
break;
|
|
}
|
|
}
|
|
if (found) {
|
|
db.collection(channel).update(
|
|
{ id: msg.id },
|
|
{
|
|
$set: element
|
|
},
|
|
function(err, docs) {
|
|
if (
|
|
docs &&
|
|
docs.hasOwnProperty("nModified") &&
|
|
docs.nModified == 1 &&
|
|
broadcast
|
|
) {
|
|
element.new_id = element.id;
|
|
element.id = msg.id;
|
|
if (!callback) {
|
|
io.to(channel).emit("channel", {
|
|
type: "changed_values",
|
|
value: element
|
|
});
|
|
}
|
|
}
|
|
if (typeof callback == "function") {
|
|
msg.title = element.title;
|
|
msg.id = element.id;
|
|
msg.duration = element.duration;
|
|
msg.start = element.start;
|
|
msg.end = element.end;
|
|
callback(msg, true);
|
|
}
|
|
}
|
|
);
|
|
} else if (typeof callback == "function") {
|
|
callback({}, false);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
function similarity(s1, s2) {
|
|
var longer = s1;
|
|
var shorter = s2;
|
|
if (s1.length < s2.length) {
|
|
longer = s2;
|
|
shorter = s1;
|
|
}
|
|
var longerLength = longer.length;
|
|
if (longerLength == 0) {
|
|
return 1.0;
|
|
}
|
|
return (
|
|
(longerLength - editDistance(longer, shorter)) / parseFloat(longerLength)
|
|
);
|
|
}
|
|
|
|
function editDistance(s1, s2) {
|
|
s1 = s1.toLowerCase();
|
|
s2 = s2.toLowerCase();
|
|
|
|
var costs = new Array();
|
|
for (var i = 0; i <= s1.length; i++) {
|
|
var lastValue = i;
|
|
for (var j = 0; j <= s2.length; j++) {
|
|
if (i == 0) costs[j] = j;
|
|
else {
|
|
if (j > 0) {
|
|
var newValue = costs[j - 1];
|
|
if (s1.charAt(i - 1) != s2.charAt(j - 1))
|
|
newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1;
|
|
costs[j - 1] = lastValue;
|
|
lastValue = newValue;
|
|
}
|
|
}
|
|
}
|
|
if (i > 0) costs[s2.length] = lastValue;
|
|
}
|
|
return costs[s2.length];
|
|
}
|
|
|
|
function durationToSeconds(duration) {
|
|
var matches = duration.match(time_regex);
|
|
hours = parseInt(matches[12]) || 0;
|
|
minutes = parseInt(matches[14]) || 0;
|
|
seconds = parseInt(matches[16]) || 0;
|
|
return hours * 60 * 60 + minutes * 60 + seconds;
|
|
}
|
|
|
|
module.exports.check_if_error_or_blocked = check_if_error_or_blocked;
|
|
module.exports.get_genres_list_recursive = get_genres_list_recursive;
|
|
module.exports.get_genres_soundcloud = get_genres_soundcloud;
|
|
module.exports.get_genres_youtube = get_genres_youtube;
|
|
module.exports.get_genres_list = get_genres_list;
|
|
module.exports.check_error_video = check_error_video;
|
|
module.exports.get_correct_info = get_correct_info;
|