Added stuff
- Attempted to fix the status for when screensharing - Added the application icon
This commit is contained in:
parent
9330106c24
commit
3a164c5599
38 changed files with 260 additions and 222 deletions
|
@ -11,6 +11,7 @@ class Program
|
|||
private const string ConfigFilePath = "config.json";
|
||||
private static DiscordRpcClient _discordClient;
|
||||
private static Config _config;
|
||||
private static bool isScreenSharing = false; // Track screen sharing status
|
||||
|
||||
// Hard-code the Discord Client ID here
|
||||
private const string DiscordClientId = "1312264302601834578"; // Replace with your actual Discord client ID
|
||||
|
@ -29,6 +30,62 @@ class Program
|
|||
_discordClient.Initialize();
|
||||
|
||||
// Poll Jellyfin API for currently playing media
|
||||
var updateTask = UpdateRichPresence(); // Start the rich presence update task
|
||||
|
||||
// Command loop for toggling screen sharing
|
||||
while (true)
|
||||
{
|
||||
var command = Console.ReadLine()?.ToLower();
|
||||
if (command == "toggle")
|
||||
{
|
||||
ToggleScreenSharing();
|
||||
}
|
||||
else if (command == "exit")
|
||||
{
|
||||
break; // Exit the loop and end the program
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid command. Type 'toggle' to toggle screen sharing or 'exit' to quit.");
|
||||
}
|
||||
}
|
||||
|
||||
await updateTask; // Wait for the rich presence update task to finish
|
||||
}
|
||||
|
||||
private static void ToggleScreenSharing()
|
||||
{
|
||||
isScreenSharing = !isScreenSharing; // Toggle the screen sharing state
|
||||
Console.WriteLine(isScreenSharing ? "Screen sharing enabled." : "Screen sharing disabled.");
|
||||
UpdateDiscordPresence(); // Manually update Discord presence when toggling screen sharing
|
||||
}
|
||||
|
||||
private static void UpdateDiscordPresence()
|
||||
{
|
||||
// Log the current status of screen sharing
|
||||
Console.WriteLine($"Updating Discord Presence. Screen Sharing: {isScreenSharing}");
|
||||
|
||||
// Ensure we immediately update the Discord presence when toggling screen sharing
|
||||
_discordClient.SetPresence(new RichPresence
|
||||
{
|
||||
Details = isScreenSharing ? "Sharing screen" : "Watching media",
|
||||
State = isScreenSharing ? "Screen sharing is active" : "Not sharing screen",
|
||||
Timestamps = new Timestamps
|
||||
{
|
||||
Start = DateTime.UtcNow
|
||||
},
|
||||
Assets = new Assets
|
||||
{
|
||||
LargeImageKey = isScreenSharing ? "screen_sharing" : "media_playing",
|
||||
LargeImageText = isScreenSharing ? "Screen sharing on Discord" : "Watching media on Jellyfin"
|
||||
}
|
||||
});
|
||||
|
||||
Console.WriteLine("Presence updated successfully.");
|
||||
}
|
||||
|
||||
private static async Task UpdateRichPresence()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
|
@ -36,48 +93,53 @@ class Program
|
|||
var playingInfo = await GetCurrentlyPlaying().ConfigureAwait(false);
|
||||
if (playingInfo != null)
|
||||
{
|
||||
// Get the raw JToken from nowPlaying (instead of passing PlayingInfo)
|
||||
JToken nowPlaying = playingInfo.NowPlayingItem;
|
||||
|
||||
// Check if album art exists and pre-fetch it
|
||||
string largeImageKey = playingInfo.IsMusic
|
||||
? await GetAlbumCover(nowPlaying).ConfigureAwait(false) // Pass the JToken nowPlaying here
|
||||
? await GetAlbumCover(nowPlaying).ConfigureAwait(false)
|
||||
: await GetJellyfinLogo().ConfigureAwait(false);
|
||||
string largeImageText = playingInfo.IsMusic
|
||||
? nowPlaying["Album"]?.ToString() ?? "Unknown Album" // Extract album name or fallback to "Unknown Album"
|
||||
? nowPlaying["Album"]?.ToString() ?? "Unknown Album"
|
||||
: "Jellyfin Media Player";
|
||||
// Update Discord Rich Presence for music or video
|
||||
|
||||
string details = playingInfo.IsMusic
|
||||
? $"{playingInfo.Title}" // Show song name
|
||||
: $"Watching: {playingInfo.Title}"; // Show video title
|
||||
|
||||
string state = isScreenSharing ? "Sharing screen" : playingInfo.IsMusic
|
||||
? $"{playingInfo.Artist}" // Show artist name
|
||||
: $"Season {playingInfo.Season}, Episode {playingInfo.Episode}";
|
||||
|
||||
Console.WriteLine($"Updating presence with details: {details}, state: {state}");
|
||||
|
||||
_discordClient.SetPresence(new RichPresence
|
||||
{
|
||||
Details = playingInfo.IsMusic
|
||||
? $"{playingInfo.Title}" // Show song name
|
||||
: $"Watching: {playingInfo.Title}", // Show video title
|
||||
State = playingInfo.IsMusic
|
||||
? $"{playingInfo.Artist}" // Show artist only (no album name)
|
||||
: $"Season {playingInfo.Season}, Episode {playingInfo.Episode}",
|
||||
Details = details,
|
||||
State = state, // Dynamic state based on screen sharing or media
|
||||
Timestamps = new Timestamps
|
||||
{
|
||||
Start = DateTime.UtcNow - playingInfo.Progress, // Start time based on current progress
|
||||
End = DateTime.UtcNow + (playingInfo.Duration - playingInfo.Progress) // End time based on total duration
|
||||
Start = DateTime.UtcNow - playingInfo.Progress,
|
||||
End = DateTime.UtcNow + (playingInfo.Duration - playingInfo.Progress)
|
||||
},
|
||||
Assets = new Assets
|
||||
{
|
||||
LargeImageKey = largeImageKey, // Dynamically set image based on media type
|
||||
LargeImageText = largeImageText // Use album name or fallback text
|
||||
LargeImageKey = largeImageKey,
|
||||
LargeImageText = largeImageText
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_discordClient.ClearPresence();
|
||||
Console.WriteLine("No media playing, clearing presence.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error: {ex.Message}");
|
||||
Console.WriteLine($"Error fetching Jellyfin data: {ex.Message}");
|
||||
}
|
||||
|
||||
// Wait for a few seconds before polling again
|
||||
// Wait before polling again
|
||||
await Task.Delay(5000).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -93,16 +155,13 @@ class Program
|
|||
var jsonResponse = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
var json = JObject.Parse(jsonResponse);
|
||||
|
||||
// Attempt to get the logo URL
|
||||
var logoUrl = json["LogoUrl"]?.ToString();
|
||||
|
||||
// Fallback to a default logo if no logo URL is found
|
||||
return logoUrl ?? "jellyfin_logo";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error fetching Jellyfin logo: {ex.Message}");
|
||||
return "jellyfin_logo"; // Default fallback in case of error
|
||||
return "jellyfin_logo"; // Default fallback
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,39 +169,21 @@ class Program
|
|||
{
|
||||
if (File.Exists(ConfigFilePath))
|
||||
{
|
||||
// Load configuration from file
|
||||
var configJson = File.ReadAllText(ConfigFilePath);
|
||||
_config = JsonSerializer.Deserialize<Config>(configJson);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prompt user for configuration on first startup (without Discord Client ID)
|
||||
_config = new Config();
|
||||
Console.Write("Enter Jellyfin Server URL: ");
|
||||
_config.JellyfinBaseUrl = Console.ReadLine();
|
||||
Console.Write("Enter Jellyfin API Key: ");
|
||||
_config.JellyfinApiKey = Console.ReadLine();
|
||||
Console.Write("Enter Jellyfin User ID: ");
|
||||
_config.JellyfinUserId = Console.ReadLine();
|
||||
|
||||
do
|
||||
{
|
||||
Console.Write("Enter Jellyfin Server URL (e.g., http://your-jellyfin-server:8096): ");
|
||||
_config.JellyfinBaseUrl = Console.ReadLine();
|
||||
} while (string.IsNullOrWhiteSpace(_config.JellyfinBaseUrl));
|
||||
|
||||
do
|
||||
{
|
||||
Console.Write("Enter Jellyfin API Key: ");
|
||||
_config.JellyfinApiKey = Console.ReadLine();
|
||||
} while (string.IsNullOrWhiteSpace(_config.JellyfinApiKey));
|
||||
|
||||
Console.WriteLine("Go to the following URL and find your Jellyfin User ID:");
|
||||
Console.WriteLine(" http://<your-jellyfin-server>:PORTNUMBER/Users?api_key=<your-api-key>");
|
||||
do
|
||||
{
|
||||
Console.Write("Enter Jellyfin User ID: ");
|
||||
_config.JellyfinUserId = Console.ReadLine();
|
||||
} while (string.IsNullOrWhiteSpace(_config.JellyfinUserId));
|
||||
|
||||
// Save configuration to file (without Discord Client ID)
|
||||
var configJson = JsonSerializer.Serialize(_config, new JsonSerializerOptions { WriteIndented = true });
|
||||
File.WriteAllText(ConfigFilePath, configJson);
|
||||
|
||||
Console.WriteLine("Configuration saved to config.json.");
|
||||
}
|
||||
}
|
||||
|
@ -160,35 +201,29 @@ class Program
|
|||
|
||||
foreach (var session in sessions)
|
||||
{
|
||||
if (session["UserId"]?.ToString() == _config.JellyfinUserId &&
|
||||
session["NowPlayingItem"] != null)
|
||||
if (session["UserId"]?.ToString() == _config.JellyfinUserId && session["NowPlayingItem"] != null)
|
||||
{
|
||||
var nowPlaying = session["NowPlayingItem"]; // This is the raw JToken we need
|
||||
|
||||
// Extract media type
|
||||
var nowPlaying = session["NowPlayingItem"];
|
||||
var mediaType = nowPlaying["Type"]?.ToString();
|
||||
bool isMusic = mediaType?.ToLower() == "audio";
|
||||
|
||||
string albumCover = ""; // Default value for album cover
|
||||
string artist = "Unknown Artist"; // Default value for artist
|
||||
string albumCover = "";
|
||||
string artist = "Unknown Artist";
|
||||
|
||||
// If it's music, extract the album art and artist name
|
||||
if (isMusic)
|
||||
{
|
||||
albumCover = await GetAlbumCover(nowPlaying).ConfigureAwait(false); // Pass JToken (not PlayingInfo)
|
||||
albumCover = await GetAlbumCover(nowPlaying).ConfigureAwait(false);
|
||||
var artists = nowPlaying["Artists"]?.ToObject<JArray>();
|
||||
if (artists != null && artists.Count > 0)
|
||||
{
|
||||
artist = artists[0].ToString(); // Get the first artist from the array
|
||||
artist = artists[0].ToString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's video, set artist to Unknown Artist
|
||||
artist = "Unknown Artist";
|
||||
}
|
||||
|
||||
// Return the extracted data wrapped in the PlayingInfo object
|
||||
return new PlayingInfo
|
||||
{
|
||||
Title = nowPlaying["Name"]?.ToString(),
|
||||
|
@ -199,7 +234,7 @@ class Program
|
|||
Progress = TimeSpan.FromTicks((long)session["PlayState"]["PositionTicks"]),
|
||||
Duration = TimeSpan.FromTicks((long)nowPlaying["RunTimeTicks"]),
|
||||
IsMusic = isMusic,
|
||||
NowPlayingItem = nowPlaying // Add the raw NowPlayingItem JToken here
|
||||
NowPlayingItem = nowPlaying
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -214,44 +249,23 @@ class Program
|
|||
|
||||
private static async Task<string> GetAlbumCover(JToken nowPlaying)
|
||||
{
|
||||
// Try to get the album cover from the "MediaStreams" (audio specific)
|
||||
var mediaStreams = nowPlaying["MediaStreams"]?.ToObject<JArray>();
|
||||
if (mediaStreams != null)
|
||||
{
|
||||
// Look for the stream that indicates an image (usually "mjpeg" codec)
|
||||
foreach (var stream in mediaStreams)
|
||||
{
|
||||
if (stream["Codec"]?.ToString() == "mjpeg" && stream["Type"]?.ToString() == "EmbeddedImage")
|
||||
var imageTag = stream["ImageTag"]?.ToString();
|
||||
if (!string.IsNullOrEmpty(imageTag))
|
||||
{
|
||||
// Check for the image tag and try to form the image URL
|
||||
string imageTag = nowPlaying["ParentLogoImageTag"]?.ToString();
|
||||
if (!string.IsNullOrWhiteSpace(imageTag))
|
||||
{
|
||||
string itemId = nowPlaying["Id"]?.ToString();
|
||||
if (!string.IsNullOrWhiteSpace(itemId))
|
||||
{
|
||||
// Construct the URL for the album cover
|
||||
return $"{_config.JellyfinBaseUrl}/emby/Items/{itemId}/Images/Primary?tag={imageTag}&api_key={_config.JellyfinApiKey}";
|
||||
}
|
||||
}
|
||||
return imageTag; // Return the album cover image tag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Check if there is an explicit album cover URL in the item
|
||||
string albumArtUrl = nowPlaying["ImageTags"]?["Primary"]?.ToString();
|
||||
if (!string.IsNullOrWhiteSpace(albumArtUrl))
|
||||
{
|
||||
return $"{_config.JellyfinBaseUrl}/emby/Items/{nowPlaying["Id"]}/Images/Primary?tag={albumArtUrl}&api_key={_config.JellyfinApiKey}";
|
||||
}
|
||||
|
||||
// Fallback to a default cover if no album art is found
|
||||
return "default_cover";
|
||||
return "album_cover";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Config
|
||||
class Config
|
||||
{
|
||||
public string JellyfinBaseUrl { get; set; }
|
||||
public string JellyfinApiKey { get; set; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue