Format code using Prettier

This commit is contained in:
Manuel 2022-08-07 16:14:24 +02:00
parent 8ba7ceb7f4
commit 00a66a668f
13 changed files with 3100 additions and 301 deletions

View File

@ -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
View 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"
}

View File

@ -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) {
// 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 += "▒";
@ -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)) {
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") {
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;

View File

@ -11,5 +11,5 @@ function getDiscordClient () {
module.exports = {
getDiscordClient,
init
init,
};

View File

@ -9,5 +9,5 @@ function getAudioDispatcher () {
module.exports = {
setAudioDispatcher,
getAudioDispatcher
getAudioDispatcher,
};

View File

@ -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"]);
@ -27,27 +27,38 @@ try {
prefix.apply(log, {
format(level, name, timestamp) {
return `${chalk.gray(`[${timestamp}]`)} ${colors[level.toUpperCase()](level)} ${chalk.green(`${name}:`)}`;
}
return `${chalk.gray(`[${timestamp}]`)} ${colors[level.toUpperCase()](
level
)} ${chalk.green(`${name}:`)}`;
},
});
prefix.apply(log.getLogger("critical"), {
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);
}

View File

@ -5,11 +5,37 @@ 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() {
@ -38,16 +64,35 @@ 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) {
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,
};

View File

@ -1,4 +1,3 @@
const { ApiClient, Events } = require("jellyfin-apiclient");
const CONFIG = require("../config.json");
const os = require("os");
@ -6,7 +5,13 @@ 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());
jellyfinClient = new ApiClient(
CONFIG["server-address"],
CONFIG["jellyfin-app-name"],
"0.0.1",
os.hostname(),
os.hostname()
);
}
function getJellyfinClient() {
@ -20,5 +25,5 @@ function getJellyfinEvents () {
module.exports = {
getJellyfinClient,
getJellyfinEvents,
init
init,
};

View File

@ -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");
@ -20,7 +15,9 @@ var isSummendByPlay = false;
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);
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({
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;
@ -94,7 +104,10 @@ function summonMessage (message) {
}
async function playThis(message) {
const indexOfItemID = message.content.indexOf(CONFIG["discord-prefix"] + "play") + (CONFIG["discord-prefix"] + "play").length + 1;
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;
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
@ -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,
};

View File

@ -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.
@ -27,11 +24,34 @@ 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;
@ -39,26 +59,38 @@ function startPlaying (voiceconnection = discordclientmanager.getDiscordClient()
_seek = seekTo * 1000;
updatePlayMessage();
async function playasync() {
const url = streamURLbuilder(itemIDPlaylist[playlistIndex], voiceconnection.channel.bitrate);
setAudioDispatcher(voiceconnection.play(url, {
seek: seekTo
}));
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
);
}
}
});
@ -82,18 +124,42 @@ function startPlaying (voiceconnection = discordclientmanager.getDiscordClient()
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);
}
@ -104,10 +170,31 @@ async function spawnPlayMessage (message) {
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);
}
}
}
@ -117,8 +204,16 @@ async function updatePlayMessage () {
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");
}
@ -134,32 +229,60 @@ function addTracks (itemID) {
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() {
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
);
}
}
@ -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();
@ -189,19 +317,23 @@ function stop (disconnectVoiceConnection, itemId = getItemId()) {
function pause() {
log.debug("pause");
isPaused = true;
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
jellyfinClientManager
.getJellyfinClient()
.reportPlaybackProgress(getProgressPayload());
getAudioDispatcher().pause(true);
}
function resume() {
log.debug("resume");
isPaused = false;
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
jellyfinClientManager
.getJellyfinClient()
.reportPlaybackProgress(getProgressPayload());
getAudioDispatcher().resume();
}
function playPause() {
if (!(getAudioDispatcher())) {
if (!getAudioDispatcher()) {
throw Error("There is nothing Playing right now!");
}
if (getAudioDispatcher().paused) {
@ -213,7 +345,10 @@ function playPause () {
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() {
@ -239,11 +374,13 @@ function getPlaySessionId () {
}
function getNowPLayingQueue() {
return [{
return [
{
Id: getItemId(),
// as I curently dont support Playlists
PlaylistItemId: getPlaylistItemId()
}];
PlaylistItemId: getPlaylistItemId(),
},
];
}
function getCanSeek() {
@ -298,7 +435,7 @@ function getProgressPayload () {
PositionTicks: getPostitionTicks(),
RepeatMode: getRepeatMode(),
VolumeLevel: getVolumeLevel(),
EventName: "pauseplayupdate"
EventName: "pauseplayupdate",
};
return payload;
}
@ -309,7 +446,7 @@ function getStopPayload () {
itemId: getItemId(),
sessionID: getPlaySessionId(),
playSessionId: getPlaySessionId(),
positionTicks: getPostitionTicks()
positionTicks: getPostitionTicks(),
};
return payload;
}
@ -326,5 +463,5 @@ module.exports = {
previousTrack,
addTracks,
getPostitionTicks,
spawnPlayMessage
spawnPlayMessage,
};

View File

@ -1,6 +1,10 @@
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) {
@ -9,7 +13,8 @@ function ticksToSeconds (ticks) {
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);
@ -46,5 +51,5 @@ module.exports = {
ticksToSeconds,
hmsToSeconds,
getDiscordEmbedError,
secondsToHms
secondsToHms,
};

View File

@ -4,17 +4,23 @@ const { ticksToSeconds } = require("./util");
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,
};

2499
yarn.lock Normal file

File diff suppressed because it is too large Load Diff