Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6e51680
Updated Example; Solved #64
Lachee May 13, 2019
2c7e3bb
Added Signing
Lachee May 14, 2019
e689251
Fixed Signing
Lachee May 14, 2019
3705420
README.md spell fault
letsdank May 23, 2019
596ffd6
Merge pull request #69 from letsdank/patch-1
Lachee May 23, 2019
6e14c4e
Update README.md
Lachee May 29, 2019
5a4f60f
typo
ijre Jun 2, 2019
a7cef0e
Merge pull request #70 from ijre/patch-1
Lachee Jun 2, 2019
df0e8f2
Prevented SetPresence Spam & Cloned Presence
Lachee Jul 1, 2019
523a9f0
Added Flags and PremiumType to users
Lachee Jul 1, 2019
feed0ac
Create FUNDING.yml
Lachee Jul 8, 2019
00d8ea3
Update FUNDING.yml
Lachee Jul 8, 2019
6d9a070
Fixed nullref
yousucklol Aug 5, 2019
7f13bda
Merge branch 'master' of https://github.com/Lachee/discord-rpc-csharp
yousucklol Aug 5, 2019
86009e8
Fixed formatting on example
yousucklol Aug 8, 2019
13f1860
Updated some inline documentation
yousucklol Aug 8, 2019
d3e9696
Patch to fix issue #72
yousucklol Aug 12, 2019
432857a
updated build scripts
yousucklol Aug 16, 2019
5df121d
Automating Documentation
yousucklol Aug 16, 2019
c042523
Automating Documentation
yousucklol Aug 16, 2019
297a431
Linked Documentation
Lachee Aug 16, 2019
e2eb21d
Early Checkout
yousucklol Aug 16, 2019
97e3fc5
Merge branch 'master' of https://github.com/Lachee/discord-rpc-csharp
yousucklol Aug 16, 2019
8a00d0f
Fixed documentation generation
yousucklol Aug 16, 2019
902b537
Added Base URL
yousucklol Aug 16, 2019
e8d8ba2
more doc fixes
yousucklol Aug 16, 2019
dd5a7ff
Added Ko-Fi
yousucklol Aug 16, 2019
ca54720
Remove Ko-Fi
Lachee Aug 16, 2019
144a721
More specific git
yousucklol Aug 16, 2019
202ad79
Renamed internal functions to better describe what they are doing
yousucklol Oct 2, 2019
6c46a76
Escaped characters in doc build script
yousucklol Oct 2, 2019
2f7c0d2
Modified documentation build script to add all changes
yousucklol Oct 2, 2019
db6bbf6
Fixed the Remove-Item
yousucklol Oct 2, 2019
b886337
Attempted to add force
yousucklol Oct 2, 2019
72ba51f
Remove output option in docs build script
Still34 Oct 2, 2019
7e1482b
Fix markdown stylings
Still34 Oct 2, 2019
0332213
Add topicUid on landing pages
Still34 Oct 2, 2019
0d85aff
Fix docfx.json
Still34 Oct 2, 2019
efd58e7
Merge pull request #75 from Still34/patches/docs-settings
Lachee Oct 2, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# These are supported funding model platforms
ko_fi:
lachee
389 changes: 196 additions & 193 deletions DiscordRPC.Example/Program.cs

Large diffs are not rendered by default.

29 changes: 18 additions & 11 deletions DiscordRPC/DiscordRpcClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ public ILogger Logger
/// Indicates if the client will automatically invoke the events without <see cref="Invoke"/> having to be called.
/// </summary>
public bool AutoEvents { get; private set; }

/// <summary>
/// Skips sending presences that are identical to the current one.
/// </summary>
public bool SkipIdenticalPresence { get; set; }
#endregion

/// <summary>
Expand Down Expand Up @@ -117,7 +122,6 @@ public bool ShutdownOnly
}
}
private bool _shutdownOnly = true;

private object _sync = new object();

#region Events
Expand Down Expand Up @@ -226,6 +230,7 @@ public DiscordRpcClient(string applicationID, int pipe = -1, ILogger logger = nu
ProcessID = System.Diagnostics.Process.GetCurrentProcess().Id;
HasRegisteredUriScheme = false;
AutoEvents = autoEvents;
SkipIdenticalPresence = true;

//Prepare the logger
_logger = logger ?? new NullLogger();
Expand Down Expand Up @@ -452,11 +457,12 @@ public void SetPresence(RichPresence presence)
if (!IsInitialized)
Logger.Warning("The client is not yet initialized, storing the presence as a state instead.");

//SEnd the event
//Send the event
if (!presence)
{
//Clear the presence
connection.EnqueueCommand(new PresenceCommand() { PID = this.ProcessID, Presence = null });
{
//Clear the presence
if (!SkipIdenticalPresence || CurrentPresence != null)
connection.EnqueueCommand(new PresenceCommand() { PID = this.ProcessID, Presence = null });
}
else
{
Expand All @@ -471,12 +477,13 @@ public void SetPresence(RichPresence presence)
if (presence.HasSecrets() && !presence.HasParty())
Logger.Warning("The presence has set the secrets but no buttons will show as there is no party available.");

//Send the presence
connection.EnqueueCommand(new PresenceCommand() { PID = this.ProcessID, Presence = presence.Clone() });
//Send the presence, but only if we are not skipping
if (!SkipIdenticalPresence || !presence.Matches(CurrentPresence))
connection.EnqueueCommand(new PresenceCommand() { PID = this.ProcessID, Presence = presence.Clone() });
}

//Update our local store
lock (_sync) { CurrentPresence = presence; }
lock (_sync) { CurrentPresence = presence != null ? presence.Clone() : null; }
}

#region Updates
Expand Down Expand Up @@ -829,9 +836,9 @@ private void SubscribeToTypes(EventType type, bool isUnsubscribe)
if ((type & EventType.Join) == EventType.Join)
connection.EnqueueCommand(new SubscribeCommand() { Event = RPC.Payload.ServerEvent.ActivityJoin, IsUnsubscribe = isUnsubscribe });

if ((type & EventType.JoinRequest) == EventType.JoinRequest)
connection.EnqueueCommand(new SubscribeCommand() { Event = RPC.Payload.ServerEvent.ActivityJoinRequest, IsUnsubscribe = isUnsubscribe });
}
if ((type & EventType.JoinRequest) == EventType.JoinRequest)
connection.EnqueueCommand(new SubscribeCommand() { Event = RPC.Payload.ServerEvent.ActivityJoinRequest, IsUnsubscribe = isUnsubscribe });
}

#endregion

Expand Down
3 changes: 1 addition & 2 deletions DiscordRPC/EventType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public enum EventType
/// <summary>
/// Called when another Discord Client has requested permission to join this game.
/// </summary>
JoinRequest = 0x4,

JoinRequest = 0x4
}
}
2 changes: 1 addition & 1 deletion DiscordRPC/Helper/StringTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public static bool WithinLength(this string str, int bytes, Encoding encoding)


/// <summary>
/// Converts the string into CamelCase (Pascal Case).
/// Converts the string into UpperCamelCase (Pascal Case).
/// </summary>
/// <param name="str">The string to convert</param>
/// <returns></returns>
Expand Down
92 changes: 60 additions & 32 deletions DiscordRPC/IO/ManagedNamedPipeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,17 @@ public ManagedNamedPipeClient()
/// <returns></returns>
public bool Connect(int pipe)
{
Logger.Trace("ManagedNamedPipeClient.Connection(" + pipe + ")");

if (_isDisposed)
throw new ObjectDisposedException("NamedPipe");

if (pipe > 9)
throw new ArgumentOutOfRangeException("pipe", "Argument cannot be greater than 9");

//Iterate until we connect to a pipe
if (pipe < 0)
{
//Iterate until we connect to a pipe
for (int i = 0; i < 10; i++)
{
if (AttemptConnection(i) || AttemptConnection(i, true))
Expand All @@ -94,26 +96,34 @@ public bool Connect(int pipe)
}
}
}

//Attempt to connect to a specific pipe
if (AttemptConnection(pipe) || AttemptConnection(pipe, true))
else
{
BeginReadStream();
return true;
//Attempt to connect to a specific pipe
if (AttemptConnection(pipe) || AttemptConnection(pipe, true))
{
BeginReadStream();
return true;
}
}

//We failed to connect
return false;
}

private bool AttemptConnection(int pipe, bool doSandbox = false)
/// <summary>
/// Attempts a new connection
/// </summary>
/// <param name="pipe">The pipe number to connect too.</param>
/// <param name="isSandbox">Should the connection to a sandbox be attempted?</param>
/// <returns></returns>
private bool AttemptConnection(int pipe, bool isSandbox = false)
{
if (_isDisposed)
throw new ObjectDisposedException("_stream");

//If we are sandbox but we dont support sandbox, then skip
string sandbox = doSandbox ? GetPipeSandbox() : "";
if (doSandbox && sandbox == null)
string sandbox = isSandbox ? GetPipeSandbox() : "";
if (isSandbox && sandbox == null)
{
Logger.Trace("Skipping sandbox connection.");
return false;
Expand Down Expand Up @@ -266,6 +276,20 @@ private void EndReadStream(IAsyncResult callback)
}
}
}
else
{
//If we read 0 bytes, its probably a broken pipe. However, I have only confirmed this is the case for MacOSX.
// I have added this check here just so the Windows builds are not effected and continue to work as expected.
if (IsUnix())
{
Logger.Error("Empty frame was read on " + Environment.OSVersion.ToString() + ", aborting.");
Close();
}
else
{
Logger.Warning("Empty frame was read. Please send report to Lachee.");
}
}

//We are still connected, so continue to read
if (!_isClosed && IsConnected)
Expand Down Expand Up @@ -424,35 +448,22 @@ public void Dispose()
}

/// <summary>
/// Gets the name of the pipe, resolving the complete path.
/// Returns a platform specific path that Discord is hosting the IPC on.
/// </summary>
/// <param name="pipe"></param>
/// <param name="sandbox"></param>
/// <param name="pipe">The pipe number.</param>
/// <param name="sandbox">The sandbox the pipe is in. Leave blank for no sandbox.</param>
/// <returns></returns>
private string GetPipeName(int pipe, string sandbox = "")
public static string GetPipeName(int pipe, string sandbox = "")
{
switch (Environment.OSVersion.Platform)
{
default:
case PlatformID.Win32NT:
case PlatformID.Win32S:
case PlatformID.Win32Windows:
case PlatformID.WinCE:
Logger.Trace("PIPE WIN");
return sandbox + string.Format(PIPE_NAME, pipe);

case PlatformID.Unix:
case PlatformID.MacOSX:
Logger.Trace("PIPE UNIX / MACOSX");
return Path.Combine(GetEnviromentTemp(), sandbox + string.Format(PIPE_NAME, pipe));
}
if (!IsUnix()) return sandbox + string.Format(PIPE_NAME, pipe);
return Path.Combine(GetTemporaryDirectory(), sandbox + string.Format(PIPE_NAME, pipe));
}

/// <summary>
/// Gets the name of the possible sandbox enviroment the pipe maybe in.
/// Gets the name of the possible sandbox enviroment the pipe might be located within. If the platform doesn't support sandboxed Discord, then it will return null.
/// </summary>
/// <returns></returns>
private string GetPipeSandbox()
public static string GetPipeSandbox()
{
switch (Environment.OSVersion.Platform)
{
Expand All @@ -464,10 +475,10 @@ private string GetPipeSandbox()
}

/// <summary>
/// Gets the enviroment temporary path.
/// Gets the temporary path for the current enviroment. Only applicable for UNIX based systems.
/// </summary>
/// <returns></returns>
private string GetEnviromentTemp()
private static string GetTemporaryDirectory()
{
string temp = null;
temp = temp ?? Environment.GetEnvironmentVariable("XDG_RUNTIME_DIR");
Expand All @@ -477,5 +488,22 @@ private string GetEnviromentTemp()
temp = temp ?? "/tmp";
return temp;
}

/// <summary>
/// Returns true if the current OS platform is Unix based (Unix or MacOSX).
/// </summary>
/// <returns></returns>
public static bool IsUnix()
{
switch (Environment.OSVersion.Platform)
{
default:
return false;

case PlatformID.Unix:
case PlatformID.MacOSX:
return true;
}
}
}
}
1 change: 1 addition & 0 deletions DiscordRPC/Message/SubscribeMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ internal SubscribeMessage(ServerEvent evt)
case ServerEvent.ActivitySpectate:
Event = EventType.Spectate;
break;

}
}
}
Expand Down
73 changes: 44 additions & 29 deletions DiscordRPC/RPC/Payload/ServerEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

namespace DiscordRPC.RPC.Payload
{
/// <summary>
/// See https://discordapp.com/developers/docs/topics/rpc#rpc-server-payloads-rpc-events for documentation
/// </summary>
internal enum ServerEvent
/// <summary>
/// See https://discordapp.com/developers/docs/topics/rpc#rpc-server-payloads-rpc-events for documentation
/// </summary>
internal enum ServerEvent
{

/// <summary>
/// Sent when the server is ready to accept messages
/// </summary>
Expand Down Expand Up @@ -39,42 +40,56 @@ internal enum ServerEvent
[EnumValue("ACTIVITY_JOIN_REQUEST")]
ActivityJoinRequest,

#region RPC Protocols
//Old things that are obsolete
/*
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
GuildStatus,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
GuildCreate,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
ChannelCreate,
#if INCLUDE_FULL_RPC
//Old things that are obsolete
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
[EnumValue("GUILD_STATUS")]
GuildStatus,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
VoiceChannelSelect,
[EnumValue("GUILD_CREATE")]
GuildCreate,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
VoiceStateCreated,
[EnumValue("CHANNEL_CREATE")]
ChannelCreate,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
VoiceStateUpdated,
[EnumValue("VOICE_CHANNEL_SELECT")]
VoiceChannelSelect,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
VoiceStateDelete,
[EnumValue("VOICE_STATE_CREATED")]
VoiceStateCreated,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
VoiceSettingsUpdate,
[EnumValue("VOICE_STATE_UPDATED")]
VoiceStateUpdated,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
VoiceConnectionStatus,
[EnumValue("VOICE_STATE_DELETE")]
VoiceStateDelete,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
SpeakingStart,
[EnumValue("VOICE_SETTINGS_UPDATE")]
VoiceSettingsUpdate,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
SpeakingStop,
[EnumValue("VOICE_CONNECTION_STATUS")]
VoiceConnectionStatus,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
MessageCreate,
[EnumValue("SPEAKING_START")]
SpeakingStart,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
MessageUpdate,
[EnumValue("SPEAKING_STOP")]
SpeakingStop,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
MessageDelete,
[EnumValue("MESSAGE_CREATE")]
MessageCreate,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
NotificationCreate,
[EnumValue("MESSAGE_UPDATE")]
MessageUpdate,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
CaptureShortcutChange
*/
#endregion
}
[EnumValue("MESSAGE_DELETE")]
MessageDelete,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
[EnumValue("NOTIFICATION_CREATE")]
NotificationCreate,
[Obsolete("This value is appart of the RPC API and is not supported by this library.", true)]
[EnumValue("CAPTURE_SHORTCUT_CHANGE")]
CaptureShortcutChange
#endif
}
}
Loading