mirror of
https://github.com/informaticker/discord-jellyfin-bot.git
synced 2024-11-23 18:21:55 +01:00
Format code using Prettier
This commit is contained in:
parent
8ba7ceb7f4
commit
00a66a668f
10
config.json
10
config.json
@ -1,10 +0,0 @@
|
||||
{
|
||||
"token":"",
|
||||
"server-address":"",
|
||||
"jellyfin-username":"",
|
||||
"jellyfin-password":"",
|
||||
"discord-prefix":"?",
|
||||
"jellyfin-app-name":"Jellyfin Discord Music Bot",
|
||||
"interactive-seek-bar-update-intervall":2000,
|
||||
"log-level":"info"
|
||||
}
|
10
config.json.example
Normal file
10
config.json.example
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"token": "",
|
||||
"server-address": "",
|
||||
"jellyfin-username": "",
|
||||
"jellyfin-password": "",
|
||||
"discord-prefix": "?",
|
||||
"jellyfin-app-name": "Jellyfin Discord Music Bot",
|
||||
"interactive-seek-bar-update-intervall": 10000,
|
||||
"log-level": "info"
|
||||
}
|
@ -1,16 +1,13 @@
|
||||
const discordclientmanager = require("./discordclientmanager");
|
||||
const CONFIG = require("../config.json");
|
||||
const {
|
||||
secondsToHms,
|
||||
ticksToSeconds
|
||||
} = require("./util");
|
||||
const { secondsToHms, ticksToSeconds } = require("./util");
|
||||
|
||||
function getProgressString (percent) {
|
||||
function getProgressString(percent) {
|
||||
// the min with of the discord window allows for this many chars
|
||||
const NUMBER_OF_CHARS = 12;
|
||||
let string = "";
|
||||
for (let iX = 0; iX < NUMBER_OF_CHARS; iX++) {
|
||||
if (percent > (iX) / NUMBER_OF_CHARS) {
|
||||
if (percent > iX / NUMBER_OF_CHARS) {
|
||||
string += "█";
|
||||
} else {
|
||||
string += "▒";
|
||||
@ -24,7 +21,7 @@ function getProgressString (percent) {
|
||||
* @returns {String}
|
||||
*/
|
||||
// TODO do this with something like wcwidth
|
||||
function getMaxWidthString (string) {
|
||||
function getMaxWidthString(string) {
|
||||
const NUMBER_OF_CHARS = 12;
|
||||
if (string.length > NUMBER_OF_CHARS) {
|
||||
return string.slice(0, NUMBER_OF_CHARS - 3) + "...";
|
||||
@ -49,35 +46,53 @@ class InterActivePlayMessage {
|
||||
* @param {Function} onNext
|
||||
* @param {Function} onRepeat
|
||||
*/
|
||||
constructor (message, title, artist, imageURL, itemURL, ticksLength, onPrevious, onPausePlay, onStop, onNext, onRepeat, playlistLenth) {
|
||||
constructor(
|
||||
message,
|
||||
title,
|
||||
artist,
|
||||
imageURL,
|
||||
itemURL,
|
||||
ticksLength,
|
||||
onPrevious,
|
||||
onPausePlay,
|
||||
onStop,
|
||||
onNext,
|
||||
onRepeat,
|
||||
playlistLenth
|
||||
) {
|
||||
this.ticksLength = ticksLength;
|
||||
var exampleEmbed = {
|
||||
color: 0x0099ff,
|
||||
title: "Now Playing",
|
||||
url: itemURL,
|
||||
description: `${getMaxWidthString(title)}\nby\n ${getMaxWidthString(artist)}`,
|
||||
description: `\`\`${getMaxWidthString(title)}\`\` by \`\`${getMaxWidthString(
|
||||
artist
|
||||
)}\`\``,
|
||||
thumbnail: {
|
||||
url: imageURL
|
||||
url: imageURL,
|
||||
},
|
||||
fields: [],
|
||||
timestamp: new Date()
|
||||
timestamp: new Date(),
|
||||
};
|
||||
if (typeof CONFIG["interactive-seek-bar-update-intervall"] === "number") {
|
||||
exampleEmbed.fields.push({
|
||||
name: getProgressString(0 / this.ticksLength),
|
||||
value: `${secondsToHms(0)} / ${secondsToHms(ticksToSeconds(this.ticksLength))}`,
|
||||
inline: false
|
||||
value: `${secondsToHms(0)} / ${secondsToHms(
|
||||
ticksToSeconds(this.ticksLength)
|
||||
)}`,
|
||||
inline: false,
|
||||
});
|
||||
}
|
||||
if (playlistLenth) {
|
||||
exampleEmbed.fields.push({
|
||||
name: `1 of ${playlistLenth}`,
|
||||
value: "Playlist",
|
||||
inline: false
|
||||
inline: false,
|
||||
});
|
||||
}
|
||||
message.channel.send({
|
||||
embed: exampleEmbed
|
||||
message.channel
|
||||
.send({
|
||||
embed: exampleEmbed,
|
||||
})
|
||||
.then((val) => {
|
||||
this.musicplayermessage = val;
|
||||
@ -86,10 +101,11 @@ class InterActivePlayMessage {
|
||||
val.react("⏹️");
|
||||
val.react("⏭️");
|
||||
val.react("🔁");
|
||||
}).catch(console.error);
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
function reactionchange (reaction, user, musicplayermessage) {
|
||||
if (reaction.message.id === musicplayermessage.id && !(user.bot)) {
|
||||
function reactionchange(reaction, user, musicplayermessage) {
|
||||
if (reaction.message.id === musicplayermessage.id && !user.bot) {
|
||||
try {
|
||||
switch (reaction._emoji.name) {
|
||||
case "⏮️":
|
||||
@ -110,26 +126,34 @@ class InterActivePlayMessage {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
}
|
||||
|
||||
discordclientmanager.getDiscordClient().on("messageReactionAdd", (reaction, user) => {
|
||||
discordclientmanager
|
||||
.getDiscordClient()
|
||||
.on("messageReactionAdd", (reaction, user) => {
|
||||
reactionchange(reaction, user, this.musicplayermessage);
|
||||
});
|
||||
discordclientmanager.getDiscordClient().on("messageReactionRemove", (reaction, user) => {
|
||||
discordclientmanager
|
||||
.getDiscordClient()
|
||||
.on("messageReactionRemove", (reaction, user) => {
|
||||
reactionchange(reaction, user, this.musicplayermessage);
|
||||
});
|
||||
}
|
||||
|
||||
updateProgress (ticks) {
|
||||
if (typeof this.musicplayermessage !== "undefined" && typeof this.musicplayermessage.embeds[0] !== "undefined" && typeof this.musicplayermessage.embeds[0].fields[0] !== "undefined") {
|
||||
updateProgress(ticks) {
|
||||
if (
|
||||
typeof this.musicplayermessage !== "undefined" &&
|
||||
typeof this.musicplayermessage.embeds[0] !== "undefined" &&
|
||||
typeof this.musicplayermessage.embeds[0].fields[0] !== "undefined"
|
||||
) {
|
||||
this.musicplayermessage.embeds[0].fields[0] = {
|
||||
name: getProgressString(ticks / this.ticksLength),
|
||||
value: `${secondsToHms(ticksToSeconds(ticks))} / ${secondsToHms(ticksToSeconds(this.ticksLength))}`,
|
||||
inline: false
|
||||
value: `${secondsToHms(ticksToSeconds(ticks))} / ${secondsToHms(
|
||||
ticksToSeconds(this.ticksLength)
|
||||
)}`,
|
||||
inline: false,
|
||||
};
|
||||
|
||||
this.musicplayermessage.timestamp = new Date();
|
||||
@ -137,19 +161,34 @@ class InterActivePlayMessage {
|
||||
}
|
||||
}
|
||||
|
||||
updateCurrentSongMessage (title, artist, imageURL, itemURL, ticksLength, playlistIndex, playlistLenth) {
|
||||
updateCurrentSongMessage(
|
||||
title,
|
||||
artist,
|
||||
imageURL,
|
||||
itemURL,
|
||||
ticksLength,
|
||||
playlistIndex,
|
||||
playlistLenth
|
||||
) {
|
||||
this.musicplayermessage.embeds[0].url = itemURL;
|
||||
this.musicplayermessage.embeds[0].description = `${getMaxWidthString(title)}\nby\n${getMaxWidthString(artist)}`;
|
||||
this.musicplayermessage.embeds[0].description = `\`\`${getMaxWidthString(
|
||||
title
|
||||
)}\`\` by \`\`${getMaxWidthString(artist)}\`\``;
|
||||
this.musicplayermessage.embeds[0].thumbnail = { url: imageURL };
|
||||
const indexOfPlaylistMessage = this.musicplayermessage.embeds[0].fields.findIndex((element) => { return element.value === "Playlist"; });
|
||||
const indexOfPlaylistMessage =
|
||||
this.musicplayermessage.embeds[0].fields.findIndex((element) => {
|
||||
return element.value === "Playlist";
|
||||
});
|
||||
if (indexOfPlaylistMessage === -1) {
|
||||
this.musicplayermessage.embeds[0].fields.push({
|
||||
name: `${playlistIndex} of ${playlistLenth}`,
|
||||
value: "Playlist",
|
||||
inline: false
|
||||
inline: false,
|
||||
});
|
||||
} else {
|
||||
this.musicplayermessage.embeds[0].fields[indexOfPlaylistMessage].name = `${playlistIndex} of ${playlistLenth}`;
|
||||
this.musicplayermessage.embeds[0].fields[
|
||||
indexOfPlaylistMessage
|
||||
].name = `${playlistIndex} of ${playlistLenth}`;
|
||||
}
|
||||
this.ticksLength = ticksLength;
|
||||
|
||||
@ -157,7 +196,7 @@ class InterActivePlayMessage {
|
||||
this.musicplayermessage.edit(this.musicplayermessage.embeds[0]);
|
||||
}
|
||||
|
||||
destroy () {
|
||||
destroy() {
|
||||
this.musicplayermessage.delete();
|
||||
delete this;
|
||||
}
|
||||
|
@ -2,14 +2,14 @@ const Discord = require("discord.js");
|
||||
|
||||
var discordClient;
|
||||
|
||||
function init () {
|
||||
function init() {
|
||||
discordClient = new Discord.Client();
|
||||
}
|
||||
function getDiscordClient () {
|
||||
function getDiscordClient() {
|
||||
return discordClient;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getDiscordClient,
|
||||
init
|
||||
init,
|
||||
};
|
||||
|
@ -1,13 +1,13 @@
|
||||
var audioDispatcher;
|
||||
|
||||
function setAudioDispatcher (par) {
|
||||
function setAudioDispatcher(par) {
|
||||
audioDispatcher = par;
|
||||
}
|
||||
function getAudioDispatcher () {
|
||||
function getAudioDispatcher() {
|
||||
return audioDispatcher;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setAudioDispatcher,
|
||||
getAudioDispatcher
|
||||
getAudioDispatcher,
|
||||
};
|
||||
|
37
src/index.js
37
src/index.js
@ -1,3 +1,5 @@
|
||||
const log = require("loglevel");
|
||||
|
||||
try {
|
||||
const CONFIG = require("../config.json");
|
||||
|
||||
@ -6,10 +8,8 @@ try {
|
||||
const discordclientmanager = require("./discordclientmanager");
|
||||
discordclientmanager.init();
|
||||
const discordClient = discordclientmanager.getDiscordClient();
|
||||
const {
|
||||
handleChannelMessage
|
||||
} = require("./messagehandler");
|
||||
const log = require("loglevel");
|
||||
const { handleChannelMessage } = require("./messagehandler");
|
||||
|
||||
const prefix = require("loglevel-plugin-prefix");
|
||||
const chalk = require("chalk");
|
||||
const colors = {
|
||||
@ -17,7 +17,7 @@ try {
|
||||
DEBUG: chalk.cyan,
|
||||
INFO: chalk.blue,
|
||||
WARN: chalk.yellow,
|
||||
ERROR: chalk.red
|
||||
ERROR: chalk.red,
|
||||
};
|
||||
|
||||
log.setLevel(CONFIG["log-level"]);
|
||||
@ -26,28 +26,39 @@ try {
|
||||
log.enableAll();
|
||||
|
||||
prefix.apply(log, {
|
||||
format (level, name, timestamp) {
|
||||
return `${chalk.gray(`[${timestamp}]`)} ${colors[level.toUpperCase()](level)} ${chalk.green(`${name}:`)}`;
|
||||
}
|
||||
format(level, name, timestamp) {
|
||||
return `${chalk.gray(`[${timestamp}]`)} ${colors[level.toUpperCase()](
|
||||
level
|
||||
)} ${chalk.green(`${name}:`)}`;
|
||||
},
|
||||
});
|
||||
|
||||
prefix.apply(log.getLogger("critical"), {
|
||||
format (level, name, timestamp) {
|
||||
format(level, name, timestamp) {
|
||||
return chalk.red.bold(`[${timestamp}] ${level} ${name}:`);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
jellyfinClientManager.init();
|
||||
// TODO Error Checking as the apiclients is inefficent
|
||||
jellyfinClientManager.getJellyfinClient().authenticateUserByName(CONFIG["jellyfin-username"], CONFIG["jellyfin-password"]).then((response) => {
|
||||
jellyfinClientManager.getJellyfinClient().setAuthenticationInfo(response.AccessToken, response.SessionInfo.UserId);
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.authenticateUserByName(
|
||||
CONFIG["jellyfin-username"],
|
||||
CONFIG["jellyfin-password"]
|
||||
)
|
||||
.then((response) => {
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.setAuthenticationInfo(response.AccessToken, response.SessionInfo.UserId);
|
||||
});
|
||||
|
||||
discordClient.on("message", message => {
|
||||
discordClient.on("message", (message) => {
|
||||
handleChannelMessage(message);
|
||||
});
|
||||
|
||||
discordClient.login(CONFIG.token);
|
||||
} catch (error) {
|
||||
log.error(error);
|
||||
console.error(error);
|
||||
}
|
||||
|
@ -5,14 +5,40 @@ var iapm;
|
||||
|
||||
var updateInterval;
|
||||
|
||||
function init (message, title, artist, imageURL, itemURL, getProgress, onPrevious, onPausePlay, onStop, onNext, onRepeat, playlistLenth) {
|
||||
function init(
|
||||
message,
|
||||
title,
|
||||
artist,
|
||||
imageURL,
|
||||
itemURL,
|
||||
getProgress,
|
||||
onPrevious,
|
||||
onPausePlay,
|
||||
onStop,
|
||||
onNext,
|
||||
onRepeat,
|
||||
playlistLenth
|
||||
) {
|
||||
if (typeof iapm !== "undefined") {
|
||||
destroy();
|
||||
}
|
||||
iapm = new InterActivePlayMessage(message, title, artist, imageURL, itemURL, getProgress, onPrevious, onPausePlay, onStop, onNext, onRepeat, playlistLenth);
|
||||
iapm = new InterActivePlayMessage(
|
||||
message,
|
||||
title,
|
||||
artist,
|
||||
imageURL,
|
||||
itemURL,
|
||||
getProgress,
|
||||
onPrevious,
|
||||
onPausePlay,
|
||||
onStop,
|
||||
onNext,
|
||||
onRepeat,
|
||||
playlistLenth
|
||||
);
|
||||
}
|
||||
|
||||
function destroy () {
|
||||
function destroy() {
|
||||
if (typeof iapm !== "undefined") {
|
||||
iapm.destroy();
|
||||
iapm = undefined;
|
||||
@ -26,7 +52,7 @@ function destroy () {
|
||||
}
|
||||
}
|
||||
|
||||
function hasMessage () {
|
||||
function hasMessage() {
|
||||
if (typeof iapm === "undefined") {
|
||||
return false;
|
||||
} else {
|
||||
@ -37,17 +63,36 @@ function hasMessage () {
|
||||
*
|
||||
* @param {Function} callback function to retrieve current ticks
|
||||
*/
|
||||
function startUpate (callback) {
|
||||
if (typeof CONFIG["interactive-seek-bar-update-intervall"] === "number" && CONFIG["interactive-seek-bar-update-intervall"] > 0) {
|
||||
function startUpate(callback) {
|
||||
if (
|
||||
typeof CONFIG["interactive-seek-bar-update-intervall"] === "number" &&
|
||||
CONFIG["interactive-seek-bar-update-intervall"] > 0
|
||||
) {
|
||||
updateInterval = setInterval(() => {
|
||||
iapm.updateProgress(callback());
|
||||
}, CONFIG["interactive-seek-bar-update-intervall"]);
|
||||
}
|
||||
}
|
||||
|
||||
function updateCurrentSongMessage (title, artist, imageURL, itemURL, ticksLength, playlistIndex, playlistLenth) {
|
||||
function updateCurrentSongMessage(
|
||||
title,
|
||||
artist,
|
||||
imageURL,
|
||||
itemURL,
|
||||
ticksLength,
|
||||
playlistIndex,
|
||||
playlistLenth
|
||||
) {
|
||||
if (typeof iapm !== "undefined") {
|
||||
iapm.updateCurrentSongMessage(title, artist, imageURL, itemURL, ticksLength, playlistIndex, playlistLenth);
|
||||
iapm.updateCurrentSongMessage(
|
||||
title,
|
||||
artist,
|
||||
imageURL,
|
||||
itemURL,
|
||||
ticksLength,
|
||||
playlistIndex,
|
||||
playlistLenth
|
||||
);
|
||||
} else {
|
||||
throw Error("No Interactive Message Found");
|
||||
}
|
||||
@ -58,5 +103,5 @@ module.exports = {
|
||||
destroy,
|
||||
hasMessage,
|
||||
startUpate,
|
||||
updateCurrentSongMessage
|
||||
updateCurrentSongMessage,
|
||||
};
|
||||
|
@ -1,24 +1,29 @@
|
||||
|
||||
const { ApiClient, Events } = require("jellyfin-apiclient");
|
||||
const CONFIG = require("../config.json");
|
||||
const os = require("os");
|
||||
|
||||
var jellyfinClient;
|
||||
|
||||
function init () {
|
||||
jellyfinClient = new ApiClient(CONFIG["server-address"], CONFIG["jellyfin-app-name"], "0.0.1", os.hostname(), os.hostname());
|
||||
function init() {
|
||||
jellyfinClient = new ApiClient(
|
||||
CONFIG["server-address"],
|
||||
CONFIG["jellyfin-app-name"],
|
||||
"0.0.1",
|
||||
os.hostname(),
|
||||
os.hostname()
|
||||
);
|
||||
}
|
||||
|
||||
function getJellyfinClient () {
|
||||
function getJellyfinClient() {
|
||||
return jellyfinClient;
|
||||
}
|
||||
|
||||
function getJellyfinEvents () {
|
||||
function getJellyfinEvents() {
|
||||
return Events;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getJellyfinClient,
|
||||
getJellyfinEvents,
|
||||
init
|
||||
init,
|
||||
};
|
||||
|
@ -1,12 +1,7 @@
|
||||
const CONFIG = require("../config.json");
|
||||
const Discord = require("discord.js");
|
||||
const {
|
||||
checkJellyfinItemIDRegex
|
||||
} = require("./util");
|
||||
const {
|
||||
hmsToSeconds,
|
||||
getDiscordEmbedError
|
||||
} = require("./util");
|
||||
const { checkJellyfinItemIDRegex } = require("./util");
|
||||
const { hmsToSeconds, getDiscordEmbedError } = require("./util");
|
||||
|
||||
const discordclientmanager = require("./discordclientmanager");
|
||||
const jellyfinClientManager = require("./jellyfinclientmanager");
|
||||
@ -17,10 +12,12 @@ const discordClient = discordclientmanager.getDiscordClient();
|
||||
var isSummendByPlay = false;
|
||||
|
||||
// random Color of the Jellyfin Logo Gradient
|
||||
function getRandomDiscordColor () {
|
||||
function getRandomDiscordColor() {
|
||||
const random = Math.random();
|
||||
function randomNumber (b, a) {
|
||||
return Math.floor(random * Math.pow(Math.pow((b - a), 2), 1 / 2)) + (b > a ? a : b);
|
||||
function randomNumber(b, a) {
|
||||
return (
|
||||
Math.floor(random * Math.pow(Math.pow(b - a, 2), 1 / 2)) + (b > a ? a : b)
|
||||
);
|
||||
}
|
||||
|
||||
const GRANDIENT_START = "#AA5CC3";
|
||||
@ -40,14 +37,21 @@ function getRandomDiscordColor () {
|
||||
gE = parseInt(gE, 16);
|
||||
bE = parseInt(bE, 16);
|
||||
|
||||
return ("#" + ("00" + (randomNumber(rS, rE)).toString(16)).substr(-2) + ("00" + (randomNumber(gS, gE)).toString(16)).substr(-2) + ("00" + (randomNumber(bS, bE)).toString(16)).substr(-2));
|
||||
return (
|
||||
"#" +
|
||||
("00" + randomNumber(rS, rE).toString(16)).substr(-2) +
|
||||
("00" + randomNumber(gS, gE).toString(16)).substr(-2) +
|
||||
("00" + randomNumber(bS, bE).toString(16)).substr(-2)
|
||||
);
|
||||
}
|
||||
|
||||
// Song Search, return the song itemID
|
||||
async function searchForItemID (searchString) {
|
||||
const response = await jellyfinClientManager.getJellyfinClient().getSearchHints({
|
||||
async function searchForItemID(searchString) {
|
||||
const response = await jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.getSearchHints({
|
||||
searchTerm: searchString,
|
||||
includeItemTypes: "Audio,MusicAlbum,Playlist"
|
||||
includeItemTypes: "Audio,MusicAlbum,Playlist",
|
||||
});
|
||||
|
||||
if (response.TotalRecordCount < 1) {
|
||||
@ -58,9 +62,15 @@ async function searchForItemID (searchString) {
|
||||
return [response.SearchHints[0].ItemId];
|
||||
case "Playlist":
|
||||
case "MusicAlbum": {
|
||||
const resp = await jellyfinClientManager.getJellyfinClient().getItems(jellyfinClientManager.getJellyfinClient().getCurrentUserId(), { sortBy: "SortName", sortOrder: "Ascending", parentId: response.SearchHints[0].ItemId });
|
||||
const resp = await jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.getItems(jellyfinClientManager.getJellyfinClient().getCurrentUserId(), {
|
||||
sortBy: "SortName",
|
||||
sortOrder: "Ascending",
|
||||
parentId: response.SearchHints[0].ItemId,
|
||||
});
|
||||
const itemArray = [];
|
||||
resp.Items.forEach(element => {
|
||||
resp.Items.forEach((element) => {
|
||||
itemArray.push(element.Id);
|
||||
});
|
||||
return itemArray;
|
||||
@ -69,11 +79,11 @@ async function searchForItemID (searchString) {
|
||||
}
|
||||
}
|
||||
|
||||
function summon (voiceChannel) {
|
||||
function summon(voiceChannel) {
|
||||
voiceChannel.join();
|
||||
}
|
||||
|
||||
function summonMessage (message) {
|
||||
function summonMessage(message) {
|
||||
if (!message.member.voice.channel) {
|
||||
message.reply("please join a voice channel to summon me!");
|
||||
} else if (message.channel.type === "dm") {
|
||||
@ -93,8 +103,11 @@ function summonMessage (message) {
|
||||
}
|
||||
}
|
||||
|
||||
async function playThis (message) {
|
||||
const indexOfItemID = message.content.indexOf(CONFIG["discord-prefix"] + "play") + (CONFIG["discord-prefix"] + "play").length + 1;
|
||||
async function playThis(message) {
|
||||
const indexOfItemID =
|
||||
message.content.indexOf(CONFIG["discord-prefix"] + "play") +
|
||||
(CONFIG["discord-prefix"] + "play").length +
|
||||
1;
|
||||
const argument = message.content.slice(indexOfItemID);
|
||||
let items;
|
||||
// check if play command was used with itemID
|
||||
@ -107,17 +120,30 @@ async function playThis (message) {
|
||||
} catch (e) {
|
||||
const noSong = getDiscordEmbedError(e);
|
||||
message.channel.send(noSong);
|
||||
playbackmanager.stop(isSummendByPlay ? discordClient.user.client.voice.connections.first() : undefined);
|
||||
playbackmanager.stop(
|
||||
isSummendByPlay
|
||||
? discordClient.user.client.voice.connections.first()
|
||||
: undefined,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
playbackmanager.startPlaying(discordClient.user.client.voice.connections.first(), items, 0, 0, isSummendByPlay);
|
||||
playbackmanager.startPlaying(
|
||||
discordClient.user.client.voice.connections.first(),
|
||||
items,
|
||||
0,
|
||||
0,
|
||||
isSummendByPlay,
|
||||
);
|
||||
playbackmanager.spawnPlayMessage(message);
|
||||
}
|
||||
|
||||
async function addThis (message) {
|
||||
const indexOfItemID = message.content.indexOf(CONFIG["discord-prefix"] + "add") + (CONFIG["discord-prefix"] + "add").length + 1;
|
||||
async function addThis(message) {
|
||||
const indexOfItemID =
|
||||
message.content.indexOf(CONFIG["discord-prefix"] + "add") +
|
||||
(CONFIG["discord-prefix"] + "add").length +
|
||||
1;
|
||||
const argument = message.content.slice(indexOfItemID);
|
||||
let items;
|
||||
// check if play command was used with itemID
|
||||
@ -137,7 +163,7 @@ async function addThis (message) {
|
||||
playbackmanager.addTracks(items);
|
||||
}
|
||||
|
||||
function handleChannelMessage (message) {
|
||||
function handleChannelMessage(message) {
|
||||
getRandomDiscordColor();
|
||||
|
||||
if (message.content.startsWith(CONFIG["discord-prefix"] + "summon")) {
|
||||
@ -146,7 +172,9 @@ function handleChannelMessage (message) {
|
||||
websocketHanler.openSocket();
|
||||
|
||||
summonMessage(message);
|
||||
} else if (message.content.startsWith(CONFIG["discord-prefix"] + "disconnect")) {
|
||||
} else if (
|
||||
message.content.startsWith(CONFIG["discord-prefix"] + "disconnect")
|
||||
) {
|
||||
playbackmanager.stop();
|
||||
jellyfinClientManager.getJellyfinClient().closeWebSocket();
|
||||
discordClient.user.client.voice.connections.forEach((element) => {
|
||||
@ -160,7 +188,10 @@ function handleChannelMessage (message) {
|
||||
.setTimestamp()
|
||||
.setDescription("<:wave:757938481585586226> " + desc);
|
||||
message.channel.send(vcJoin);
|
||||
} else if ((message.content.startsWith(CONFIG["discord-prefix"] + "pause")) || (message.content.startsWith(CONFIG["discord-prefix"] + "resume"))) {
|
||||
} else if (
|
||||
message.content.startsWith(CONFIG["discord-prefix"] + "pause") ||
|
||||
message.content.startsWith(CONFIG["discord-prefix"] + "resume")
|
||||
) {
|
||||
try {
|
||||
playbackmanager.playPause();
|
||||
const noPlay = new Discord.MessageEmbed()
|
||||
@ -188,7 +219,10 @@ function handleChannelMessage (message) {
|
||||
playbackmanager.stop();
|
||||
}
|
||||
} else if (message.content.startsWith(CONFIG["discord-prefix"] + "seek")) {
|
||||
const indexOfArgument = message.content.indexOf(CONFIG["discord-prefix"] + "seek") + (CONFIG["discord-prefix"] + "seek").length + 1;
|
||||
const indexOfArgument =
|
||||
message.content.indexOf(CONFIG["discord-prefix"] + "seek") +
|
||||
(CONFIG["discord-prefix"] + "seek").length +
|
||||
1;
|
||||
const argument = message.content.slice(indexOfArgument);
|
||||
try {
|
||||
playbackmanager.seek(hmsToSeconds(argument) * 10000000);
|
||||
@ -216,43 +250,59 @@ function handleChannelMessage (message) {
|
||||
/* eslint-disable quotes */
|
||||
const reply = new Discord.MessageEmbed()
|
||||
.setColor(getRandomDiscordColor())
|
||||
.setTitle("<:musical_note:757938541123862638> " + "Jellyfin Discord Music Bot" + " <:musical_note:757938541123862638> ")
|
||||
.addFields({
|
||||
.setTitle(
|
||||
"<:musical_note:757938541123862638> " +
|
||||
"Jellyfin Discord Music Bot" +
|
||||
" <:musical_note:757938541123862638> ",
|
||||
)
|
||||
.addFields(
|
||||
{
|
||||
name: `${CONFIG["discord-prefix"]}summon`,
|
||||
value: "Join the channel the author of the message"
|
||||
}, {
|
||||
value: "Join the channel the author of the message",
|
||||
},
|
||||
{
|
||||
name: `${CONFIG["discord-prefix"]}disconnect`,
|
||||
value: "Disconnect from all current Voice Channels"
|
||||
}, {
|
||||
value: "Disconnect from all current Voice Channels",
|
||||
},
|
||||
{
|
||||
name: `${CONFIG["discord-prefix"]}play`,
|
||||
value: "Play the following item"
|
||||
}, {
|
||||
value: "Play the following item",
|
||||
},
|
||||
{
|
||||
name: `${CONFIG["discord-prefix"]}add`,
|
||||
value: "Add the following item to the current playlist"
|
||||
}, {
|
||||
value: "Add the following item to the current playlist",
|
||||
},
|
||||
{
|
||||
name: `${CONFIG["discord-prefix"]}pause/resume`,
|
||||
value: "Pause/Resume audio"
|
||||
}, {
|
||||
value: "Pause/Resume audio",
|
||||
},
|
||||
{
|
||||
name: `${CONFIG["discord-prefix"]}seek`,
|
||||
value: "Where to Seek to in seconds or MM:SS"
|
||||
}, {
|
||||
value: "Where to Seek to in seconds or MM:SS",
|
||||
},
|
||||
{
|
||||
name: `${CONFIG["discord-prefix"]}skip`,
|
||||
value: "Skip this Song"
|
||||
}, {
|
||||
value: "Skip this Song",
|
||||
},
|
||||
{
|
||||
name: `${CONFIG["discord-prefix"]}spawn`,
|
||||
value: "Spawns an Interactive Play Controller"
|
||||
}, {
|
||||
value: "Spawns an Interactive Play Controller",
|
||||
},
|
||||
{
|
||||
name: `${CONFIG["discord-prefix"]}help`,
|
||||
value: "Display this help message"
|
||||
}, {
|
||||
value: "Display this help message",
|
||||
},
|
||||
{
|
||||
name: `GitHub`,
|
||||
value: "Find the code for this bot at: https://github.com/KGT1/jellyfin-discord-music-bot"
|
||||
});
|
||||
value:
|
||||
"Find the code for this bot at: https://github.com/KGT1/jellyfin-discord-music-bot",
|
||||
},
|
||||
);
|
||||
message.channel.send(reply);
|
||||
/* eslint-enable quotes */
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
handleChannelMessage
|
||||
handleChannelMessage,
|
||||
};
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
const interactivemsghandler = require("./interactivemsghandler");
|
||||
const CONFIG = require("../config.json");
|
||||
const discordclientmanager = require("./discordclientmanager");
|
||||
@ -6,11 +5,9 @@ const log = require("loglevel");
|
||||
|
||||
const {
|
||||
getAudioDispatcher,
|
||||
setAudioDispatcher
|
||||
setAudioDispatcher,
|
||||
} = require("./dispachermanager");
|
||||
const {
|
||||
ticksToSeconds
|
||||
} = require("./util");
|
||||
const { ticksToSeconds } = require("./util");
|
||||
|
||||
// this whole thing should be a class but its probably too late now.
|
||||
|
||||
@ -23,42 +20,77 @@ var _seek;
|
||||
|
||||
const jellyfinClientManager = require("./jellyfinclientmanager");
|
||||
|
||||
function streamURLbuilder (itemID, bitrate) {
|
||||
function streamURLbuilder(itemID, bitrate) {
|
||||
// so the server transcodes. Seems appropriate as it has the source file.(doesnt yet work i dont know why)
|
||||
const supportedCodecs = "opus";
|
||||
const supportedContainers = "ogg,opus";
|
||||
return `${jellyfinClientManager.getJellyfinClient().serverAddress()}/Audio/${itemID}/universal?UserId=${jellyfinClientManager.getJellyfinClient().getCurrentUserId()}&DeviceId=${jellyfinClientManager.getJellyfinClient().deviceId()}&MaxStreamingBitrate=${bitrate}&Container=${supportedContainers}&AudioCodec=${supportedCodecs}&api_key=${jellyfinClientManager.getJellyfinClient().accessToken()}&TranscodingContainer=ts&TranscodingProtocol=hls`;
|
||||
return `${jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.serverAddress()}/Audio/${itemID}/universal?UserId=${jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.getCurrentUserId()}&DeviceId=${jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.deviceId()}&MaxStreamingBitrate=${bitrate}&Container=${supportedContainers}&AudioCodec=${supportedCodecs}&api_key=${jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.accessToken()}&TranscodingContainer=ts&TranscodingProtocol=hls`;
|
||||
}
|
||||
|
||||
function startPlaying (voiceconnection = discordclientmanager.getDiscordClient().user.client.voice.connections.first(), itemIDPlaylist = currentPlayingPlaylist, playlistIndex = currentPlayingPlaylistIndex, seekTo, disconnectOnFinish = _disconnectOnFinish) {
|
||||
log.debug("start playing ", playlistIndex, ". of list: ", itemIDPlaylist, " in a voiceconnection?: ", typeof voiceconnection !== "undefined");
|
||||
function startPlaying(
|
||||
voiceconnection = discordclientmanager
|
||||
.getDiscordClient()
|
||||
.user.client.voice.connections.first(),
|
||||
itemIDPlaylist = currentPlayingPlaylist,
|
||||
playlistIndex = currentPlayingPlaylistIndex,
|
||||
seekTo,
|
||||
disconnectOnFinish = _disconnectOnFinish
|
||||
) {
|
||||
log.debug(
|
||||
"start playing ",
|
||||
playlistIndex,
|
||||
". of list: ",
|
||||
itemIDPlaylist,
|
||||
" in a voiceconnection?: ",
|
||||
typeof voiceconnection !== "undefined"
|
||||
);
|
||||
isPaused = false;
|
||||
currentPlayingPlaylist = itemIDPlaylist;
|
||||
currentPlayingPlaylistIndex = playlistIndex;
|
||||
_disconnectOnFinish = disconnectOnFinish;
|
||||
_seek = seekTo * 1000;
|
||||
updatePlayMessage();
|
||||
async function playasync () {
|
||||
const url = streamURLbuilder(itemIDPlaylist[playlistIndex], voiceconnection.channel.bitrate);
|
||||
setAudioDispatcher(voiceconnection.play(url, {
|
||||
seek: seekTo
|
||||
}));
|
||||
async function playasync() {
|
||||
const url = streamURLbuilder(
|
||||
itemIDPlaylist[playlistIndex],
|
||||
voiceconnection.channel.bitrate
|
||||
);
|
||||
setAudioDispatcher(
|
||||
voiceconnection.play(url, {
|
||||
seek: seekTo,
|
||||
})
|
||||
);
|
||||
if (seekTo) {
|
||||
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.reportPlaybackProgress(getProgressPayload());
|
||||
} else {
|
||||
jellyfinClientManager.getJellyfinClient().reportPlaybackStart({
|
||||
userID: `${jellyfinClientManager.getJellyfinClient().getCurrentUserId()}`,
|
||||
itemID: `${itemIDPlaylist[playlistIndex]}`,
|
||||
canSeek: true,
|
||||
playSessionId: getPlaySessionId(),
|
||||
playMethod: getPlayMethod()
|
||||
playMethod: getPlayMethod(),
|
||||
});
|
||||
}
|
||||
|
||||
getAudioDispatcher().on("finish", () => {
|
||||
if (isRepeat) {
|
||||
log.debug("repeat and sending following payload as reportPlaybackStopped to the server: ", getStopPayload());
|
||||
jellyfinClientManager.getJellyfinClient().reportPlaybackStopped(getStopPayload());
|
||||
log.debug(
|
||||
"repeat and sending following payload as reportPlaybackStopped to the server: ",
|
||||
getStopPayload()
|
||||
);
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.reportPlaybackStopped(getStopPayload());
|
||||
startPlaying(voiceconnection, undefined, currentPlayingPlaylistIndex, 0);
|
||||
} else {
|
||||
if (currentPlayingPlaylist.length < playlistIndex) {
|
||||
@ -68,9 +100,19 @@ function startPlaying (voiceconnection = discordclientmanager.getDiscordClient()
|
||||
stop(undefined, currentPlayingPlaylist[playlistIndex - 1]);
|
||||
}
|
||||
} else {
|
||||
log.debug("repeat and sending following payload as reportPlaybackStopped to the server: ", getStopPayload());
|
||||
jellyfinClientManager.getJellyfinClient().reportPlaybackStopped(getStopPayload());
|
||||
startPlaying(voiceconnection, undefined, currentPlayingPlaylistIndex + 1, 0);
|
||||
log.debug(
|
||||
"repeat and sending following payload as reportPlaybackStopped to the server: ",
|
||||
getStopPayload()
|
||||
);
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.reportPlaybackStopped(getStopPayload());
|
||||
startPlaying(
|
||||
voiceconnection,
|
||||
undefined,
|
||||
currentPlayingPlaylistIndex + 1,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -80,20 +122,44 @@ function startPlaying (voiceconnection = discordclientmanager.getDiscordClient()
|
||||
});
|
||||
}
|
||||
|
||||
async function spawnPlayMessage (message) {
|
||||
async function spawnPlayMessage(message) {
|
||||
log.debug("spawned Play Message?: ", typeof message !== "undefined");
|
||||
const itemIdDetails = await jellyfinClientManager.getJellyfinClient().getItem(jellyfinClientManager.getJellyfinClient().getCurrentUserId(), getItemId());
|
||||
const imageURL = await jellyfinClientManager.getJellyfinClient().getImageUrl(itemIdDetails.AlbumId || getItemId(), { type: "Primary" });
|
||||
const itemIdDetails = await jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.getItem(
|
||||
jellyfinClientManager.getJellyfinClient().getCurrentUserId(),
|
||||
getItemId()
|
||||
);
|
||||
const imageURL = await jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.getImageUrl(itemIdDetails.AlbumId || getItemId(), { type: "Primary" });
|
||||
try {
|
||||
interactivemsghandler.init(message, itemIdDetails.Name, itemIdDetails.Artists[0] || "VA", imageURL,
|
||||
`${jellyfinClientManager.getJellyfinClient().serverAddress()}/web/index.html#!/details?id=${itemIdDetails.AlbumId}`,
|
||||
interactivemsghandler.init(
|
||||
message,
|
||||
itemIdDetails.Name,
|
||||
itemIdDetails.Artists[0] || "VA",
|
||||
imageURL,
|
||||
`${jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.serverAddress()}/web/index.html#!/details?id=${itemIdDetails.AlbumId}`,
|
||||
itemIdDetails.RunTimeTicks,
|
||||
((ticksToSeconds(getPostitionTicks()) > 10) ? previousTrack : seek),
|
||||
ticksToSeconds(getPostitionTicks()) > 10 ? previousTrack : seek,
|
||||
playPause,
|
||||
() => { stop(_disconnectOnFinish ? discordclientmanager.getDiscordClient().user.client.voice.connections.first() : undefined); },
|
||||
() => {
|
||||
stop(
|
||||
_disconnectOnFinish
|
||||
? discordclientmanager
|
||||
.getDiscordClient()
|
||||
.user.client.voice.connections.first()
|
||||
: undefined
|
||||
);
|
||||
},
|
||||
nextTrack,
|
||||
() => { setIsRepeat(!isRepeat); },
|
||||
currentPlayingPlaylist.length);
|
||||
() => {
|
||||
setIsRepeat(!isRepeat);
|
||||
},
|
||||
currentPlayingPlaylist.length
|
||||
);
|
||||
if (typeof CONFIG["interactive-seek-bar-update-intervall"] === "number") {
|
||||
interactivemsghandler.startUpate(getPostitionTicks);
|
||||
}
|
||||
@ -102,23 +168,52 @@ async function spawnPlayMessage (message) {
|
||||
}
|
||||
}
|
||||
|
||||
async function updatePlayMessage () {
|
||||
async function updatePlayMessage() {
|
||||
if (getItemId() !== undefined) {
|
||||
const itemIdDetails = await jellyfinClientManager.getJellyfinClient().getItem(jellyfinClientManager.getJellyfinClient().getCurrentUserId(), getItemId());
|
||||
const imageURL = await jellyfinClientManager.getJellyfinClient().getImageUrl(itemIdDetails.AlbumId || getItemId(), { type: "Primary" });
|
||||
interactivemsghandler.updateCurrentSongMessage(itemIdDetails.Name, itemIdDetails.Artists[0] || "VA", imageURL,
|
||||
`${jellyfinClientManager.getJellyfinClient().serverAddress()}/web/index.html#!/details?id=${itemIdDetails.AlbumId}`, itemIdDetails.RunTimeTicks, currentPlayingPlaylistIndex + 1, currentPlayingPlaylist.length);
|
||||
const itemIdDetails = await jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.getItem(
|
||||
jellyfinClientManager.getJellyfinClient().getCurrentUserId(),
|
||||
getItemId()
|
||||
);
|
||||
const imageURL = await jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.getImageUrl(itemIdDetails.AlbumId || getItemId(), { type: "Primary" });
|
||||
|
||||
try {
|
||||
interactivemsghandler.updateCurrentSongMessage(
|
||||
itemIdDetails.Name,
|
||||
itemIdDetails.Artists[0] || "VA",
|
||||
imageURL,
|
||||
`${jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.serverAddress()}/web/index.html#!/details?id=${itemIdDetails.AlbumId}`,
|
||||
itemIdDetails.RunTimeTicks,
|
||||
currentPlayingPlaylistIndex + 1,
|
||||
currentPlayingPlaylist.length
|
||||
);
|
||||
} catch (exception) {
|
||||
console.error(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} toSeek - where to seek in ticks
|
||||
*/
|
||||
function seek (toSeek = 0) {
|
||||
function seek(toSeek = 0) {
|
||||
log.debug("seek to: ", toSeek);
|
||||
if (getAudioDispatcher()) {
|
||||
startPlaying(undefined, undefined, undefined, ticksToSeconds(toSeek), _disconnectOnFinish);
|
||||
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
|
||||
startPlaying(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
ticksToSeconds(toSeek),
|
||||
_disconnectOnFinish
|
||||
);
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.reportPlaybackProgress(getProgressPayload());
|
||||
} else {
|
||||
throw Error("No Song Playing");
|
||||
}
|
||||
@ -127,46 +222,74 @@ function seek (toSeek = 0) {
|
||||
*
|
||||
* @param {Array} itemID - array of itemIDs to be added
|
||||
*/
|
||||
function addTracks (itemID) {
|
||||
function addTracks(itemID) {
|
||||
log.debug("added track: ", itemID);
|
||||
currentPlayingPlaylist = currentPlayingPlaylist.concat(itemID);
|
||||
}
|
||||
|
||||
function nextTrack () {
|
||||
function nextTrack() {
|
||||
log.debug("nextTrack");
|
||||
if (!(currentPlayingPlaylist)) {
|
||||
if (!currentPlayingPlaylist) {
|
||||
throw Error("There is currently nothing playing");
|
||||
} else if (currentPlayingPlaylistIndex + 1 >= currentPlayingPlaylist.length) {
|
||||
throw Error("This is the Last song");
|
||||
}
|
||||
|
||||
log.debug("sending following payload as reportPlaybackStopped to the server: ", getStopPayload());
|
||||
jellyfinClientManager.getJellyfinClient().reportPlaybackStopped(getStopPayload());
|
||||
log.debug(
|
||||
"sending following payload as reportPlaybackStopped to the server: ",
|
||||
getStopPayload()
|
||||
);
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.reportPlaybackStopped(getStopPayload());
|
||||
|
||||
startPlaying(undefined, undefined, currentPlayingPlaylistIndex + 1, 0, _disconnectOnFinish);
|
||||
startPlaying(
|
||||
undefined,
|
||||
undefined,
|
||||
currentPlayingPlaylistIndex + 1,
|
||||
0,
|
||||
_disconnectOnFinish
|
||||
);
|
||||
}
|
||||
|
||||
function previousTrack () {
|
||||
function previousTrack() {
|
||||
log.debug("previousTrack");
|
||||
if (ticksToSeconds(getPostitionTicks()) < 10) {
|
||||
if (!(currentPlayingPlaylist)) {
|
||||
if (!currentPlayingPlaylist) {
|
||||
throw Error("There is currently nothing playing");
|
||||
} else if (currentPlayingPlaylistIndex - 1 < 0) {
|
||||
startPlaying(undefined, undefined, currentPlayingPlaylistIndex, 0, _disconnectOnFinish);
|
||||
startPlaying(
|
||||
undefined,
|
||||
undefined,
|
||||
currentPlayingPlaylistIndex,
|
||||
0,
|
||||
_disconnectOnFinish
|
||||
);
|
||||
throw Error("This is the First song");
|
||||
}
|
||||
|
||||
log.debug("sending following payload as reportPlaybackStopped to the server: ", getStopPayload());
|
||||
jellyfinClientManager.getJellyfinClient().reportPlaybackStopped(getStopPayload());
|
||||
log.debug(
|
||||
"sending following payload as reportPlaybackStopped to the server: ",
|
||||
getStopPayload()
|
||||
);
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.reportPlaybackStopped(getStopPayload());
|
||||
|
||||
startPlaying(undefined, undefined, currentPlayingPlaylistIndex - 1, 0, _disconnectOnFinish);
|
||||
startPlaying(
|
||||
undefined,
|
||||
undefined,
|
||||
currentPlayingPlaylistIndex - 1,
|
||||
0,
|
||||
_disconnectOnFinish
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object=} disconnectVoiceConnection - Optional The voice Connection do disconnect from
|
||||
*/
|
||||
function stop (disconnectVoiceConnection, itemId = getItemId()) {
|
||||
function stop(disconnectVoiceConnection, itemId = getItemId()) {
|
||||
isPaused = true;
|
||||
if (interactivemsghandler.hasMessage()) {
|
||||
interactivemsghandler.destroy();
|
||||
@ -174,8 +297,13 @@ function stop (disconnectVoiceConnection, itemId = getItemId()) {
|
||||
if (disconnectVoiceConnection) {
|
||||
disconnectVoiceConnection.disconnect();
|
||||
}
|
||||
log.debug("stop playback and send following payload as reportPlaybackStopped to the server: ", getStopPayload());
|
||||
jellyfinClientManager.getJellyfinClient().reportPlaybackStopped(getStopPayload());
|
||||
log.debug(
|
||||
"stop playback and send following payload as reportPlaybackStopped to the server: ",
|
||||
getStopPayload()
|
||||
);
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.reportPlaybackStopped(getStopPayload());
|
||||
if (getAudioDispatcher()) {
|
||||
try {
|
||||
getAudioDispatcher().destroy();
|
||||
@ -186,22 +314,26 @@ function stop (disconnectVoiceConnection, itemId = getItemId()) {
|
||||
setAudioDispatcher(undefined);
|
||||
}
|
||||
|
||||
function pause () {
|
||||
function pause() {
|
||||
log.debug("pause");
|
||||
isPaused = true;
|
||||
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.reportPlaybackProgress(getProgressPayload());
|
||||
getAudioDispatcher().pause(true);
|
||||
}
|
||||
|
||||
function resume () {
|
||||
function resume() {
|
||||
log.debug("resume");
|
||||
isPaused = false;
|
||||
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
|
||||
jellyfinClientManager
|
||||
.getJellyfinClient()
|
||||
.reportPlaybackProgress(getProgressPayload());
|
||||
getAudioDispatcher().resume();
|
||||
}
|
||||
|
||||
function playPause () {
|
||||
if (!(getAudioDispatcher())) {
|
||||
function playPause() {
|
||||
if (!getAudioDispatcher()) {
|
||||
throw Error("There is nothing Playing right now!");
|
||||
}
|
||||
if (getAudioDispatcher().paused) {
|
||||
@ -211,17 +343,20 @@ function playPause () {
|
||||
}
|
||||
}
|
||||
|
||||
function getPostitionTicks () {
|
||||
function getPostitionTicks() {
|
||||
// this is very sketchy but i dont know how else to do it
|
||||
return (_seek + getAudioDispatcher().streamTime - getAudioDispatcher().pausedTime) * 10000;
|
||||
return (
|
||||
(_seek + getAudioDispatcher().streamTime - getAudioDispatcher().pausedTime) *
|
||||
10000
|
||||
);
|
||||
}
|
||||
|
||||
function getPlayMethod () {
|
||||
function getPlayMethod() {
|
||||
// TODO figure out how to figure this out
|
||||
return "DirectPlay";
|
||||
}
|
||||
|
||||
function getRepeatMode () {
|
||||
function getRepeatMode() {
|
||||
if (isRepeat) {
|
||||
return "RepeatOne";
|
||||
} else {
|
||||
@ -229,43 +364,45 @@ function getRepeatMode () {
|
||||
}
|
||||
}
|
||||
|
||||
function getPlaylistItemId () {
|
||||
function getPlaylistItemId() {
|
||||
return getItemId();
|
||||
}
|
||||
|
||||
function getPlaySessionId () {
|
||||
function getPlaySessionId() {
|
||||
// i think its just a number which you dont need to retrieve but need to report
|
||||
return "ae2436edc6b91b11d72aeaa67f84e0ea";
|
||||
}
|
||||
|
||||
function getNowPLayingQueue () {
|
||||
return [{
|
||||
function getNowPLayingQueue() {
|
||||
return [
|
||||
{
|
||||
Id: getItemId(),
|
||||
// as I curently dont support Playlists
|
||||
PlaylistItemId: getPlaylistItemId()
|
||||
}];
|
||||
PlaylistItemId: getPlaylistItemId(),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function getCanSeek () {
|
||||
function getCanSeek() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function getIsMuted () {
|
||||
function getIsMuted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getVolumeLevel () {
|
||||
function getVolumeLevel() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
function getItemId () {
|
||||
function getItemId() {
|
||||
if (typeof currentPlayingPlaylist !== "undefined") {
|
||||
return currentPlayingPlaylist[currentPlayingPlaylistIndex];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getIsPaused () {
|
||||
function getIsPaused() {
|
||||
// AudioDispacker Paused is to slow
|
||||
|
||||
if (isPaused === undefined) {
|
||||
@ -275,7 +412,7 @@ function getIsPaused () {
|
||||
return isPaused;
|
||||
}
|
||||
|
||||
function setIsRepeat (arg) {
|
||||
function setIsRepeat(arg) {
|
||||
if (arg === undefined) {
|
||||
if (!(isRepeat === undefined)) {
|
||||
isRepeat = !isRepeat;
|
||||
@ -284,7 +421,7 @@ function setIsRepeat (arg) {
|
||||
isRepeat = arg;
|
||||
}
|
||||
|
||||
function getProgressPayload () {
|
||||
function getProgressPayload() {
|
||||
const payload = {
|
||||
CanSeek: getCanSeek(),
|
||||
IsMuted: getIsMuted(),
|
||||
@ -298,18 +435,18 @@ function getProgressPayload () {
|
||||
PositionTicks: getPostitionTicks(),
|
||||
RepeatMode: getRepeatMode(),
|
||||
VolumeLevel: getVolumeLevel(),
|
||||
EventName: "pauseplayupdate"
|
||||
EventName: "pauseplayupdate",
|
||||
};
|
||||
return payload;
|
||||
}
|
||||
|
||||
function getStopPayload () {
|
||||
function getStopPayload() {
|
||||
const payload = {
|
||||
userId: jellyfinClientManager.getJellyfinClient().getCurrentUserId(),
|
||||
itemId: getItemId(),
|
||||
sessionID: getPlaySessionId(),
|
||||
playSessionId: getPlaySessionId(),
|
||||
positionTicks: getPostitionTicks()
|
||||
positionTicks: getPostitionTicks(),
|
||||
};
|
||||
return payload;
|
||||
}
|
||||
@ -326,5 +463,5 @@ module.exports = {
|
||||
previousTrack,
|
||||
addTracks,
|
||||
getPostitionTicks,
|
||||
spawnPlayMessage
|
||||
spawnPlayMessage,
|
||||
};
|
||||
|
21
src/util.js
21
src/util.js
@ -1,15 +1,20 @@
|
||||
function checkJellyfinItemIDRegex (strgintomatch) {
|
||||
function checkJellyfinItemIDRegex(strgintomatch) {
|
||||
const regexresult = strgintomatch.match(/([0-9]|[a-f]){32}/);
|
||||
if (regexresult) { return [regexresult[0]]; } else { return undefined; }
|
||||
if (regexresult) {
|
||||
return [regexresult[0]];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function ticksToSeconds (ticks) {
|
||||
function ticksToSeconds(ticks) {
|
||||
return ticks / 10000000;
|
||||
}
|
||||
|
||||
function hmsToSeconds (str) {
|
||||
function hmsToSeconds(str) {
|
||||
var p = str.split(":");
|
||||
var s = 0; var m = 1;
|
||||
var s = 0;
|
||||
var m = 1;
|
||||
|
||||
while (p.length > 0) {
|
||||
s += m * parseInt(p.pop(), 10);
|
||||
@ -19,7 +24,7 @@ function hmsToSeconds (str) {
|
||||
return s;
|
||||
}
|
||||
|
||||
function secondsToHms (totalSeconds) {
|
||||
function secondsToHms(totalSeconds) {
|
||||
const hours = Math.floor(totalSeconds / 3600);
|
||||
totalSeconds %= 3600;
|
||||
const minutes = Math.floor(totalSeconds / 60);
|
||||
@ -32,7 +37,7 @@ function secondsToHms (totalSeconds) {
|
||||
}
|
||||
}
|
||||
|
||||
function getDiscordEmbedError (e) {
|
||||
function getDiscordEmbedError(e) {
|
||||
const Discord = require("discord.js");
|
||||
return new Discord.MessageEmbed()
|
||||
.setColor(0xff0000)
|
||||
@ -46,5 +51,5 @@ module.exports = {
|
||||
ticksToSeconds,
|
||||
hmsToSeconds,
|
||||
getDiscordEmbedError,
|
||||
secondsToHms
|
||||
secondsToHms,
|
||||
};
|
||||
|
@ -2,19 +2,25 @@ const jellyfinClientManager = require("./jellyfinclientmanager");
|
||||
const playbackmanager = require("./playbackmanager");
|
||||
const { ticksToSeconds } = require("./util");
|
||||
|
||||
function openSocket () {
|
||||
function openSocket() {
|
||||
jellyfinClientManager.getJellyfinClient().openWebSocket();
|
||||
jellyfinClientManager.getJellyfinClient().reportCapabilities(
|
||||
{
|
||||
jellyfinClientManager.getJellyfinClient().reportCapabilities({
|
||||
PlayableMediaTypes: "Audio",
|
||||
SupportsMediaControl: true,
|
||||
SupportedCommands: "SetRepeatMode,Play,Playstate"
|
||||
}
|
||||
);
|
||||
jellyfinClientManager.getJellyfinEvents().on(jellyfinClientManager.getJellyfinClient(), "message", (type, data) => {
|
||||
SupportedCommands: "SetRepeatMode,Play,Playstate",
|
||||
});
|
||||
jellyfinClientManager
|
||||
.getJellyfinEvents()
|
||||
.on(jellyfinClientManager.getJellyfinClient(), "message", (type, data) => {
|
||||
if (data.MessageType === "Play") {
|
||||
if (data.Data.PlayCommand === "PlayNow") {
|
||||
playbackmanager.startPlaying(undefined, data.Data.ItemIds, data.Data.StartIndex || 0, 0, false);
|
||||
playbackmanager.startPlaying(
|
||||
undefined,
|
||||
data.Data.ItemIds,
|
||||
data.Data.StartIndex || 0,
|
||||
0,
|
||||
false
|
||||
);
|
||||
}
|
||||
} else if (data.MessageType === "Playstate") {
|
||||
if (data.Data.Command === "PlayPause") {
|
||||
@ -23,7 +29,9 @@ function openSocket () {
|
||||
playbackmanager.stop();
|
||||
} else if (data.Data.Command === "Seek") {
|
||||
// because the server sends seek an privious track at same time so i have to do timing
|
||||
setTimeout(async () => { playbackmanager.seek(data.Data.SeekPositionTicks); }, 20);
|
||||
setTimeout(async () => {
|
||||
playbackmanager.seek(data.Data.SeekPositionTicks);
|
||||
}, 20);
|
||||
} else if (data.Data.Command === "NextTrack") {
|
||||
try {
|
||||
playbackmanager.nextTrack();
|
||||
@ -44,5 +52,5 @@ function openSocket () {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
openSocket
|
||||
openSocket,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user