jellyfinRichPresence: Complete Plugin Overhaul (#464)
* [Feat] jellyfinRichPresence: Enabled Ability to Use Series Cover
* Enabled the ability for the user to use the series cover (which is more similar to the movie cover) instead of the episode cover when watching an episode.
* Added myself as a contributor to the plugin.
* [QOL] Correct Mistake with Developer Crediting
* [Feat] jellyfinRichPresence: Added Ability to Show Episode Name & Change Season-Episode Display Format
* Added the ability to change the display formatting between 3 different options:
- `S00E00`
- `0x00`
- `Season 0 Episode 0`
* Added the ability to display the episode name after the episode number.
* [Feat] jellyfinRichPresence: Added the Ability to Show Presence when Paused
* Added a settings option that will allow the user to continue showing the presence while the player is paused.
* [Feat] jellyfinRichPresence: Added Privacy Mode
* Added the ability for the user to enable privacy mode, in which the name of their media will not be displayed.
* [Fix] Hide Image when in Privacy Mode
* Made the image hidden when in privacy mode
* Fixed a few es-lint violations
* [Fix] jellyfinRichPresence: Hide When Paused by Default
* Switched the defaults to hide the presence when media is paused
* [Fix] jellyfinRichPresence: Used Different Method for Image Hiding
* Fixed the image not hiding by using a different method
* [Fix] jellyfinRichPresence: Remove Comment that Wasn't Purged, Fix Ancient Autocorrect Mistake
* Update .gitignore for Wakatime files
Add Wakatime related entries to .gitignore
* [Fix] jellyfinRichPresence: Fix Autocorrect Mistake from Commit `a31a3ac`
---------
Co-authored-by: thororen <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
parent
17aa9a1df0
commit
5619852a62
3 changed files with 111 additions and 15 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -29,3 +29,6 @@ ExtensionCache/
|
|||
|
||||
# vencord companion module cache
|
||||
.modules
|
||||
|
||||
# wakatime related stuff
|
||||
.wakatime-project
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ interface MediaData {
|
|||
imageUrl?: string;
|
||||
duration?: number;
|
||||
position?: number;
|
||||
isPaused?: boolean;
|
||||
}
|
||||
|
||||
const settings = definePluginSettings({
|
||||
|
|
@ -84,6 +85,28 @@ const settings = definePluginSettings({
|
|||
description: "Custom Rich Presence name (only used if 'Custom' is selected).\nOptions: {name}, {series}, {season}, {episode}, {artist}, {album}, {year}",
|
||||
type: OptionType.STRING,
|
||||
},
|
||||
coverType: {
|
||||
description: "Choose which cover to display when watching a TV show",
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{ label: "Series Cover", value: "series", default: true },
|
||||
{ label: "Episode Cover", value: "episode" },
|
||||
],
|
||||
},
|
||||
episodeFormat: {
|
||||
description: "Episode number format",
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{ label: "S01E01", value: "long", default: true },
|
||||
{ label: "1x01", value: "short" },
|
||||
{ label: "Season 1 Episode 1", value: "fulltext" },
|
||||
],
|
||||
},
|
||||
showEpisodeName: {
|
||||
description: "Show episode name after season/episode info",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
},
|
||||
showTMDBButton: {
|
||||
description: "Show TheMovieDB button in Rich Presence",
|
||||
type: OptionType.BOOLEAN,
|
||||
|
|
@ -116,6 +139,16 @@ const settings = definePluginSettings({
|
|||
},
|
||||
],
|
||||
},
|
||||
showPausedState: {
|
||||
description: "Show Rich Presence when media is paused",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
},
|
||||
privacyMode: {
|
||||
description: "Privacy Mode (Hide media details like Episode/Song Name)",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const applicationId = "1381368130164625469";
|
||||
|
|
@ -137,7 +170,7 @@ function setActivity(activity: Activity | null) {
|
|||
export default definePlugin({
|
||||
name: "JellyfinRichPresence",
|
||||
description: "Rich presence for Jellyfin media server",
|
||||
authors: [EquicordDevs.vmohammad, Devs.SerStars],
|
||||
authors: [EquicordDevs.vmohammad, Devs.SerStars, EquicordDevs.ZcraftElite],
|
||||
|
||||
settingsAboutComponent: () => (
|
||||
<>
|
||||
|
|
@ -200,10 +233,16 @@ export default definePlugin({
|
|||
const item = userSession.NowPlayingItem;
|
||||
const playState = userSession.PlayState;
|
||||
|
||||
if (playState?.IsPaused) return null;
|
||||
if (playState?.IsPaused && !settings.store.showPausedState) return null;
|
||||
|
||||
const imageUrl = item.ImageTags?.Primary
|
||||
? `${baseUrl}/Items/${item.Id}/Images/Primary`
|
||||
? `${baseUrl}/Items/${
|
||||
item.Type === "Episode" &&
|
||||
item.SeriesId &&
|
||||
settings.store.coverType === "series"
|
||||
? item.SeriesId
|
||||
: item.Id
|
||||
}/Images/Primary`
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
|
|
@ -218,7 +257,8 @@ export default definePlugin({
|
|||
url: `${baseUrl}/web/#!/details?id=${item.Id}`,
|
||||
imageUrl,
|
||||
duration: item.RunTimeTicks ? Math.floor(item.RunTimeTicks / 10000000) : undefined,
|
||||
position: playState?.PositionTicks ? Math.floor(playState.PositionTicks / 10000000) : undefined
|
||||
position: playState?.PositionTicks ? Math.floor(playState.PositionTicks / 10000000) : undefined,
|
||||
isPaused: !!playState?.IsPaused,
|
||||
};
|
||||
} catch (e) {
|
||||
logger.error("Failed to query Jellyfin API", e);
|
||||
|
|
@ -265,22 +305,37 @@ export default definePlugin({
|
|||
switch (nameSetting) {
|
||||
case "full":
|
||||
if (mediaData.type === "Episode" && mediaData.seriesName) {
|
||||
appName = `${mediaData.seriesName} - ${mediaData.name}`;
|
||||
appName = settings.store.privacyMode
|
||||
? `${mediaData.seriesName} - [Episode Hidden]`
|
||||
: `${mediaData.seriesName} - ${mediaData.name}`;
|
||||
} else if (mediaData.type === "Audio") {
|
||||
appName = `${mediaData.artist || "Unknown Artist"} - ${mediaData.name}`;
|
||||
appName = settings.store.privacyMode
|
||||
? "[Track Hidden]"
|
||||
: `${mediaData.artist || "Unknown Artist"} - ${mediaData.name}`;
|
||||
} else {
|
||||
appName = mediaData.name || "Jellyfin";
|
||||
appName = settings.store.privacyMode
|
||||
? "[Movie Hidden]"
|
||||
: mediaData.name || "Jellyfin";
|
||||
}
|
||||
break;
|
||||
case "custom":
|
||||
appName = templateReplace(settings.store.customName || "{name} on Jellyfish");
|
||||
appName = templateReplace(settings.store.customName || "{name} on Jellyfin");
|
||||
if (settings.store.privacyMode) {
|
||||
appName = appName
|
||||
.replace(mediaData.name || "", "[Title Hidden]")
|
||||
.replace(mediaData.seriesName || "", "[Series Hidden]")
|
||||
.replace(mediaData.artist || "", "[Artist Hidden]")
|
||||
.replace(mediaData.album || "", "[Album Hidden]");
|
||||
}
|
||||
break;
|
||||
case "default":
|
||||
default:
|
||||
if (mediaData.type === "Episode" && mediaData.seriesName) {
|
||||
appName = mediaData.seriesName;
|
||||
} else {
|
||||
appName = mediaData.name || "Jellyfin";
|
||||
appName = settings.store.privacyMode
|
||||
? "[Media Hidden]"
|
||||
: mediaData.name || "Jellyfin";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -292,25 +347,59 @@ export default definePlugin({
|
|||
large_text: mediaData.seriesName || mediaData.album || undefined,
|
||||
};
|
||||
|
||||
if (settings.store.privacyMode) {
|
||||
assets.large_image = undefined;
|
||||
}
|
||||
|
||||
const buttons: ActivityButton[] = [];
|
||||
|
||||
const getDetails = () => {
|
||||
if (mediaData.type === "Episode" && mediaData.seriesName) {
|
||||
return mediaData.seriesName;
|
||||
return settings.store.privacyMode ? "Watching a TV Show" : mediaData.seriesName;
|
||||
}
|
||||
return mediaData.name;
|
||||
return settings.store.privacyMode ? "Watching Something" : mediaData.name;
|
||||
};
|
||||
|
||||
const getState = () => {
|
||||
if (mediaData.isPaused) {
|
||||
return "Paused";
|
||||
}
|
||||
if (mediaData.type === "Episode" && mediaData.seriesName) {
|
||||
const season = mediaData.seasonNumber ? `S${mediaData.seasonNumber}` : "";
|
||||
const episode = mediaData.episodeNumber ? `E${mediaData.episodeNumber}` : "";
|
||||
return `${mediaData.name} (${season} - ${episode})`.trim();
|
||||
let episodeFormat = "";
|
||||
const season = mediaData.seasonNumber;
|
||||
const episode = mediaData.episodeNumber;
|
||||
const format = settings.store.episodeFormat || "long";
|
||||
|
||||
if (season != null && episode != null) {
|
||||
switch (format) {
|
||||
case "long":
|
||||
episodeFormat = `S${season.toString().padStart(2, "0")}E${episode.toString().padStart(2, "0")}`;
|
||||
break;
|
||||
case "short":
|
||||
episodeFormat = `${season}x${episode.toString().padStart(2, "0")}`;
|
||||
break;
|
||||
case "fulltext":
|
||||
episodeFormat = `Season ${season} Episode ${episode}`;
|
||||
break;
|
||||
}
|
||||
} else if (season != null) {
|
||||
episodeFormat = format === "fulltext" ? `Season ${season}` : `S${season.toString().padStart(2, "0")}`;
|
||||
} else if (episode != null) {
|
||||
episodeFormat = format === "fulltext" ? `Episode ${episode}` : `E${episode.toString().padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
if (settings.store.showEpisodeName && mediaData.name && !settings.store.privacyMode) {
|
||||
return `${episodeFormat} - ${mediaData.name}`;
|
||||
}
|
||||
return episodeFormat;
|
||||
}
|
||||
if (settings.store.privacyMode) {
|
||||
return mediaData.type === "Audio" ? "Listening to music" : (mediaData.year ? "(????)" : undefined);
|
||||
}
|
||||
return mediaData.artist || (mediaData.year ? `(${mediaData.year})` : undefined);
|
||||
};
|
||||
|
||||
const timestamps = mediaData.position && mediaData.duration ? {
|
||||
const timestamps = (!mediaData.isPaused && mediaData.position != null && mediaData.duration != null) ? {
|
||||
start: Date.now() - (mediaData.position * 1000),
|
||||
end: Date.now() + ((mediaData.duration - mediaData.position) * 1000)
|
||||
} : undefined;
|
||||
|
|
|
|||
|
|
@ -1166,6 +1166,10 @@ export const EquicordDevs = Object.freeze({
|
|||
name: "mmeta",
|
||||
id: 297075664530440192n
|
||||
},
|
||||
ZcraftElite: {
|
||||
name: "ZcraftElite",
|
||||
id: 926788037785047050n
|
||||
},
|
||||
} satisfies Record<string, Dev>);
|
||||
|
||||
// iife so #__PURE__ works correctly
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue