├── .gitignore ├── PusherRESTDotNet.1.2.dotCover ├── PusherRESTDotNet.Tests ├── AcceptanceTests │ └── PusherProviderTests.cs ├── App.config.template ├── Properties │ └── AssemblyInfo.cs ├── PusherRESTDotNet.Tests.csproj └── UnitTests │ ├── ObjectPusherRequestTests.cs │ └── PusherProviderTests.cs ├── PusherRESTDotNet.sln ├── PusherRESTDotNet ├── Authentication │ ├── AuthData.cs │ ├── AuthSignatureHelper.cs │ ├── BasicUserInfo.cs │ ├── PresenceChannelData.cs │ └── PusherAuthenticationHelper.cs ├── IPusherProvider.cs ├── ObjectPusherRequest.cs ├── Properties │ └── AssemblyInfo.cs ├── PusherProvider.cs ├── PusherRESTDotNet.csproj ├── PusherRESTDotNet.nuspec ├── PusherRequest.cs └── SimplePusherRequest.cs ├── README.md └── lib ├── Newtonsoft.Json.dll ├── Newtonsoft.Json.pdb ├── Newtonsoft.Json.xml ├── Rhino.Mocks.dll ├── Rhino.Mocks.xml ├── nunit.framework.dll └── nunit.framework.xml /.gitignore: -------------------------------------------------------------------------------- 1 | _ReSharper.*/ 2 | _UpgradeReport_Files 3 | UpgradeLog.XML 4 | Backup 5 | [Bb]in 6 | [Oo]bj 7 | *.suo 8 | *.user 9 | PusherDotNet.Tests/App.config 10 | PusherRESTDotNet/PusherRESTDotNet.1.0.nupkg 11 | packages/ 12 | PusherRESTDotNet.sln.docstates -------------------------------------------------------------------------------- /PusherRESTDotNet.1.2.dotCover: -------------------------------------------------------------------------------- 1 | 2 | 3 | C:\projects\pusherrestdotnet 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PusherRESTDotNet.Tests/AcceptanceTests/PusherProviderTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using System.Net; 4 | using NUnit.Framework; 5 | using PusherRESTDotNet.Authentication; 6 | 7 | namespace PusherRESTDotNet.Tests.AcceptanceTests 8 | { 9 | [TestFixture] 10 | public class PusherProviderTests 11 | { 12 | private PusherProvider _defaultProvider; 13 | string applicationId = ConfigurationManager.AppSettings["applicationId"]; 14 | string applicationKey = ConfigurationManager.AppSettings["applicationKey"]; 15 | string applicationSecret = ConfigurationManager.AppSettings["applicationSecret"]; 16 | 17 | public void SetupDefaultProvider() 18 | { 19 | if (String.IsNullOrEmpty(applicationId)) 20 | Assert.Fail("applicationId not specified in app.config appSettings"); 21 | if (String.IsNullOrEmpty(applicationKey)) 22 | Assert.Fail("applicationKey not specified in app.config appSettings"); 23 | if (String.IsNullOrEmpty(applicationSecret)) 24 | Assert.Fail("applicationSecret not specified in app.config appSettings"); 25 | 26 | _defaultProvider = new PusherProvider(applicationId, applicationKey, applicationSecret); 27 | } 28 | 29 | [Test] 30 | [Explicit("Set your credentials in app.config for this test to pass")] 31 | public void CanTriggerPush() 32 | { 33 | SetupDefaultProvider(); 34 | var request = new TestPusherRequest("test_channel", "my_event", @"{""some"":""data""}"); 35 | 36 | _defaultProvider.Trigger(request); 37 | } 38 | 39 | [Test] 40 | [Explicit("Set your credentials in app.config for this test to pass")] 41 | public void CanTriggerPushWithAnonymousObject() 42 | { 43 | SetupDefaultProvider(); 44 | var request = new ObjectPusherRequest("test_channel", "my_event", new 45 | { 46 | some = "data" 47 | }); 48 | 49 | _defaultProvider.Trigger(request); 50 | } 51 | 52 | [Test] 53 | [ExpectedException(typeof(WebException))] 54 | public void BlowsUpOnTriggerPushWithBadCredentials() 55 | { 56 | var request = new TestPusherRequest("test_channel", "my_event", @"{""some"":""data""}"); 57 | 58 | var provider = new PusherProvider("meh", "foo", "bar"); 59 | provider.Trigger(request); 60 | } 61 | 62 | public class TestPusherRequest : PusherRequest 63 | { 64 | private readonly string _jsonData; 65 | 66 | public TestPusherRequest(string channelName, string eventName, string jsonData) 67 | : base(channelName, eventName) 68 | { 69 | _jsonData = jsonData; 70 | } 71 | 72 | public override string JsonData 73 | { 74 | get { return _jsonData; } 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /PusherRESTDotNet.Tests/App.config.template: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PusherRESTDotNet.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PusherRESTDotNet.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("PusherRESTDotNet.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("423a5655-b69c-4668-86dc-f7d3f57bd0de")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PusherRESTDotNet.Tests/PusherRESTDotNet.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {29ADB209-999D-4A86-A006-01609B6B670D} 9 | Library 10 | Properties 11 | PusherRESTDotNet.Tests 12 | PusherDotNet.Tests 13 | v4.0 14 | 512 15 | false 16 | publish\ 17 | true 18 | Disk 19 | false 20 | Foreground 21 | 7 22 | Days 23 | false 24 | false 25 | true 26 | 0 27 | 1.0.0.%2a 28 | false 29 | true 30 | 31 | 32 | true 33 | full 34 | false 35 | bin\Debug\ 36 | DEBUG;TRACE 37 | prompt 38 | 4 39 | AllRules.ruleset 40 | 41 | 42 | pdbonly 43 | true 44 | bin\Release\ 45 | TRACE 46 | prompt 47 | 4 48 | AllRules.ruleset 49 | 50 | 51 | 52 | ..\lib\nunit.framework.dll 53 | 54 | 55 | ..\lib\Rhino.Mocks.dll 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | False 78 | Microsoft .NET Framework 4 %28x86 and x64%29 79 | true 80 | 81 | 82 | False 83 | .NET Framework 3.5 SP1 Client Profile 84 | false 85 | 86 | 87 | False 88 | .NET Framework 3.5 SP1 89 | false 90 | 91 | 92 | False 93 | Windows Installer 3.1 94 | true 95 | 96 | 97 | 98 | 99 | {FEDAD44D-208E-4F99-BE08-6C1257B59D4A} 100 | PusherRESTDotNet 101 | 102 | 103 | 104 | 111 | -------------------------------------------------------------------------------- /PusherRESTDotNet.Tests/UnitTests/ObjectPusherRequestTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace PusherRESTDotNet.Tests 4 | { 5 | [TestFixture] 6 | public class ObjectPusherRequestTests 7 | { 8 | [Test] 9 | public void SerializesObjectToJsonData() 10 | { 11 | var request = new ObjectPusherRequest("test_channel", "my_event", new { some = "data" }); 12 | 13 | Assert.That(request.JsonData, Is.EqualTo(@"{""some"":""data""}")); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /PusherRESTDotNet.Tests/UnitTests/PusherProviderTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using System.Net; 4 | using NUnit.Framework; 5 | using PusherRESTDotNet.Authentication; 6 | 7 | namespace PusherRESTDotNet.Tests.UnitTests 8 | { 9 | [TestFixture] 10 | public class PusherProviderTests 11 | { 12 | [Test] 13 | public void AuthenticationStringIsCorrectlyFormedForPrivateChannel() 14 | { 15 | var appId = "1000"; 16 | var appKey = "myAppKey"; 17 | var appSecret = "myAppSecret"; 18 | var channelName = "private-channel"; 19 | var socketId = "socket_id"; 20 | var helper = new PusherAuthenticationHelper(appId, appKey, appSecret); 21 | var expected = helper.CreateAuthenticatedString(socketId, channelName); 22 | 23 | IPusherProvider provider = new PusherProvider(appId, appKey, appSecret); 24 | string auth = provider.Authenticate(channelName, socketId); 25 | 26 | Assert.IsNotNullOrEmpty(auth); 27 | Assert.AreEqual(expected, auth); 28 | } 29 | 30 | [Test] 31 | public void AuthenticationStringIsCorrectlyFormedForPresenceChannel() 32 | { 33 | var appId = "1000"; 34 | var appKey = "myAppKey"; 35 | var appSecret = "myAppSecret"; 36 | var channelName = "presence-channel"; 37 | var presenceChannelData = new PresenceChannelData() 38 | { 39 | user_id = "leggetter", 40 | user_info = new { name = "Phil Leggetter", twitter = "@leggetter" } 41 | }; 42 | var socketId = "socket_id"; 43 | var helper = new PusherAuthenticationHelper(appId, appKey, appSecret); 44 | string expected = helper.CreateAuthenticatedString(socketId, channelName, presenceChannelData); 45 | 46 | IPusherProvider provider = new PusherProvider(appId, appKey, appSecret); 47 | string auth = provider.Authenticate(channelName, socketId, presenceChannelData); 48 | 49 | Assert.IsNotNullOrEmpty(auth); 50 | Assert.AreEqual(expected, auth); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /PusherRESTDotNet.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PusherRESTDotNet", "PusherRESTDotNet\PusherRESTDotNet.csproj", "{FEDAD44D-208E-4F99-BE08-6C1257B59D4A}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PusherRESTDotNet.Tests", "PusherRESTDotNet.Tests\PusherRESTDotNet.Tests.csproj", "{29ADB209-999D-4A86-A006-01609B6B670D}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Files", "Files", "{13FCFB53-1898-4AE9-B229-F917B8F52DB2}" 9 | ProjectSection(SolutionItems) = preProject 10 | PusherRESTDotNet\PusherRESTDotNet.nuspec = PusherRESTDotNet\PusherRESTDotNet.nuspec 11 | README.md = README.md 12 | EndProjectSection 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {FEDAD44D-208E-4F99-BE08-6C1257B59D4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {FEDAD44D-208E-4F99-BE08-6C1257B59D4A}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {FEDAD44D-208E-4F99-BE08-6C1257B59D4A}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {FEDAD44D-208E-4F99-BE08-6C1257B59D4A}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {29ADB209-999D-4A86-A006-01609B6B670D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {29ADB209-999D-4A86-A006-01609B6B670D}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {29ADB209-999D-4A86-A006-01609B6B670D}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {29ADB209-999D-4A86-A006-01609B6B670D}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /PusherRESTDotNet/Authentication/AuthData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Runtime.Serialization; 6 | 7 | namespace PusherRESTDotNet.Authentication 8 | { 9 | [DataContract] 10 | internal class AuthData 11 | { 12 | [DataMember] 13 | public string auth { get; set; } 14 | 15 | [DataMember] 16 | public string channel_data { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /PusherRESTDotNet/Authentication/AuthSignatureHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Security.Cryptography; 6 | 7 | namespace PusherRESTDotNet.Authentication 8 | { 9 | internal static class AuthSignatureHelper 10 | { 11 | public static string GetAuthString(string authData, string applicationSecretKey) 12 | { 13 | var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(applicationSecretKey)); 14 | var hash = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(authData)); 15 | 16 | return BytesToHex(hash); 17 | } 18 | 19 | private static string BytesToHex(IEnumerable byteArray) 20 | { 21 | return String.Concat(byteArray.Select(bytes => bytes.ToString("x2")).ToArray()); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /PusherRESTDotNet/Authentication/BasicUserInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Runtime.Serialization; 6 | 7 | namespace PusherRESTDotNet.Authentication 8 | { 9 | [DataContract] 10 | public class BasicUserInfo 11 | { 12 | [DataMember] 13 | public string name { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /PusherRESTDotNet/Authentication/PresenceChannelData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Runtime.Serialization; 6 | 7 | namespace PusherRESTDotNet.Authentication 8 | { 9 | [DataContract] 10 | public class PresenceChannelData 11 | { 12 | [DataMember] 13 | public string user_id { get; set; } 14 | 15 | [DataMember] 16 | public object user_info { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /PusherRESTDotNet/Authentication/PusherAuthenticationHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Newtonsoft.Json; 6 | 7 | namespace PusherRESTDotNet.Authentication 8 | { 9 | public class PusherAuthenticationHelper 10 | { 11 | private string applicationId; 12 | private string applicationKey; 13 | private string applicationSecret; 14 | 15 | public PusherAuthenticationHelper(string applicationId, string applicationKey, string applicationSecret) 16 | { 17 | this.applicationId = applicationId; 18 | this.applicationKey = applicationKey; 19 | this.applicationSecret = applicationSecret; 20 | } 21 | 22 | public string CreateAuthenticatedString(string socketID, string channelName) 23 | { 24 | string auth = AuthSignatureHelper.GetAuthString(socketID + ":" + channelName, applicationSecret); 25 | 26 | AuthData data = new AuthData(); 27 | data.auth = applicationKey + ":" + auth; 28 | 29 | string json = JsonConvert.SerializeObject(data); 30 | return json; 31 | } 32 | 33 | public string CreateAuthenticatedString(string socketID, string channelName, PresenceChannelData channelData) 34 | { 35 | string channel = (channelData == null?"":JsonConvert.SerializeObject(channelData)); 36 | string auth = AuthSignatureHelper.GetAuthString(socketID + ":" + channelName + ":" + channel, applicationSecret); 37 | 38 | AuthData data = new AuthData(); 39 | data.auth = applicationKey + ":" + auth; 40 | data.channel_data = channel; 41 | 42 | string json = JsonConvert.SerializeObject(data); 43 | return json; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /PusherRESTDotNet/IPusherProvider.cs: -------------------------------------------------------------------------------- 1 | using PusherRESTDotNet.Authentication; 2 | namespace PusherRESTDotNet 3 | { 4 | public interface IPusherProvider 5 | { 6 | /// 7 | /// Sends the request. Will throw a WebException if anything other than a 202 response is encountered 8 | /// 9 | /// 10 | void Trigger(PusherRequest request); 11 | 12 | /// 13 | /// Creates and authenticated string for the given channel name and socket ID 14 | /// 15 | /// The channel to be authenticated 16 | /// The socket ID to be authenticated 17 | /// An authenticated string 18 | string Authenticate(string channelName, string socketId); 19 | 20 | /// 21 | /// Creates and authenticated string for the given channel name, socket ID and channel data 22 | /// 23 | /// The channel to be authenticated 24 | /// The socket ID to be authenticated 25 | /// The presence channel data 26 | /// An authenticated string 27 | string Authenticate(string channelName, string socketId, PresenceChannelData presenceChannelData); 28 | } 29 | } -------------------------------------------------------------------------------- /PusherRESTDotNet/ObjectPusherRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.Script.Serialization; 3 | 4 | namespace PusherRESTDotNet 5 | { 6 | /// 7 | /// Provides a simple wrapper that provides JsonData by serializing an object using a 8 | /// 9 | public class ObjectPusherRequest : PusherRequest 10 | { 11 | private readonly string _serializedData; 12 | 13 | public ObjectPusherRequest(string channelName, string eventName, object data) 14 | : base(channelName, eventName) 15 | { 16 | _serializedData = new JavaScriptSerializer().Serialize(data); 17 | } 18 | 19 | public override string JsonData 20 | { 21 | get { return _serializedData; } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /PusherRESTDotNet/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PusherRESTDotNet")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("PusherRESTDotNet")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0508dca3-1235-4d46-b7e5-e9051e71c6a2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | [assembly: AssemblyVersion("1.1.0.*")] 33 | [assembly: AssemblyFileVersion("1.1.*.*")] 34 | -------------------------------------------------------------------------------- /PusherRESTDotNet/PusherProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Security.Cryptography; 6 | using System.Text; 7 | using PusherRESTDotNet.Authentication; 8 | 9 | namespace PusherRESTDotNet 10 | { 11 | public class PusherProvider : IPusherProvider 12 | { 13 | private const string _host = "api.pusherapp.com"; 14 | private readonly string _applicationId; 15 | private readonly string _applicationKey; 16 | private readonly string _applicationSecret; 17 | private readonly PusherAuthenticationHelper _authHelper; 18 | private readonly IWebProxy _webProxy; 19 | 20 | public PusherProvider(string applicationId, string applicationKey, string applicationSecret, IWebProxy webProxy = null) 21 | { 22 | if (String.IsNullOrEmpty(applicationId)) 23 | throw new ArgumentNullException("applicationId"); 24 | if (String.IsNullOrEmpty(applicationKey)) 25 | throw new ArgumentNullException("applicationKey"); 26 | if (String.IsNullOrEmpty(applicationSecret)) 27 | throw new ArgumentNullException("applicationSecret"); 28 | 29 | _applicationSecret = applicationSecret; 30 | _applicationKey = applicationKey; 31 | _applicationId = applicationId; 32 | _webProxy = webProxy; 33 | _authHelper = new PusherAuthenticationHelper(_applicationId, _applicationKey, _applicationSecret); 34 | } 35 | 36 | /// 37 | /// Sends the request. Will throw a WebException if anything other than a 202 response is encountered 38 | /// 39 | /// 40 | public void Trigger(PusherRequest request) 41 | { 42 | var requestUrl = String.Format("http://{0}{1}?{2}&auth_signature={3}", 43 | _host, 44 | GetBaseUri(request), 45 | GetQueryString(request), 46 | GetHmac256(request)); 47 | 48 | using(var client = new WebClient()) 49 | { 50 | if(_webProxy != null) 51 | { 52 | client.Proxy = _webProxy; 53 | } 54 | client.Encoding = Encoding.UTF8; 55 | client.UploadString(requestUrl, request.JsonData); 56 | } 57 | } 58 | 59 | private string GetBaseUri(PusherRequest request) 60 | { 61 | return String.Format("/apps/{0}/channels/{1}/events", _applicationId, request.ChannelName); 62 | } 63 | 64 | private string GetQueryString(PusherRequest request) 65 | { 66 | var output = String.Format("auth_key={0}&auth_timestamp={1}&auth_version=1.0&body_md5={2}&name={3}", 67 | _applicationKey, 68 | (int)((DateTime.UtcNow - new DateTime(1970,1,1)).TotalSeconds), 69 | GetMd5Hash(request.JsonData), 70 | request.EventName); 71 | 72 | return String.IsNullOrEmpty(request.SocketId) ? output : String.Format("{0}&socket_id={1}", output, request.SocketId); 73 | } 74 | 75 | private static string GetMd5Hash(string jsonData) 76 | { 77 | var hash = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(jsonData)); 78 | return BytesToHex(hash); 79 | } 80 | 81 | private string GetHmac256(PusherRequest request) 82 | { 83 | var data = String.Format("POST\n{0}\n{1}", GetBaseUri(request), GetQueryString(request)); 84 | var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(_applicationSecret)); 85 | var hash = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(data)); 86 | 87 | return BytesToHex(hash); 88 | } 89 | 90 | private static string BytesToHex(IEnumerable byteArray) 91 | { 92 | return String.Concat(byteArray.Select(bytes => bytes.ToString("x2")).ToArray()); 93 | } 94 | 95 | 96 | public string Authenticate(string channelName, string socketId) 97 | { 98 | return _authHelper.CreateAuthenticatedString(socketId, channelName); 99 | } 100 | 101 | 102 | public string Authenticate(string channelName, string socketId, PresenceChannelData presenceChannelData) 103 | { 104 | return _authHelper.CreateAuthenticatedString(socketId, channelName, presenceChannelData); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /PusherRESTDotNet/PusherRESTDotNet.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {FEDAD44D-208E-4F99-BE08-6C1257B59D4A} 9 | Library 10 | Properties 11 | PusherRESTDotNet 12 | PusherRESTDotNet 13 | v3.5 14 | 512 15 | publish\ 16 | true 17 | Disk 18 | false 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 0 26 | 1.0.0.%2a 27 | false 28 | false 29 | true 30 | 31 | 32 | true 33 | full 34 | false 35 | bin\Debug\ 36 | DEBUG;TRACE 37 | prompt 38 | 4 39 | AllRules.ruleset 40 | 41 | 42 | pdbonly 43 | true 44 | bin\Release\ 45 | TRACE 46 | prompt 47 | 4 48 | AllRules.ruleset 49 | 50 | 51 | 52 | ..\lib\Newtonsoft.Json.dll 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | False 80 | .NET Framework 3.5 SP1 Client Profile 81 | false 82 | 83 | 84 | False 85 | .NET Framework 3.5 SP1 86 | true 87 | 88 | 89 | False 90 | Windows Installer 3.1 91 | true 92 | 93 | 94 | 95 | 102 | -------------------------------------------------------------------------------- /PusherRESTDotNet/PusherRESTDotNet.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | Graham Scott, Phil Leggetter 7 | $author$ 8 | https://github.com/leggetter/pusher-rest-dotnet 9 | false 10 | The Pusher (http://pusher.com) REST library provides a simple way of pushing realtime messages into Pusher via the Pusher REST API. 11 | realtime push websockets REST API Pusher 12 | 13 | -------------------------------------------------------------------------------- /PusherRESTDotNet/PusherRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PusherRESTDotNet 4 | { 5 | /// 6 | /// Abstract base class for pusher requests 7 | /// 8 | public abstract class PusherRequest 9 | { 10 | protected PusherRequest(string channelName, string eventName) 11 | { 12 | ChannelName = channelName; 13 | EventName = eventName; 14 | } 15 | 16 | public string EventName { get; private set; } 17 | public string ChannelName { get; private set; } 18 | public string SocketId { get; set; } 19 | 20 | public abstract string JsonData { get; } 21 | } 22 | } -------------------------------------------------------------------------------- /PusherRESTDotNet/SimplePusherRequest.cs: -------------------------------------------------------------------------------- 1 | namespace PusherRESTDotNet 2 | { 3 | public class SimplePusherRequest : PusherRequest 4 | { 5 | private readonly string _jsonData; 6 | 7 | public SimplePusherRequest(string channelName, string eventName, string jsonData) 8 | : base(channelName, eventName) 9 | { 10 | _jsonData = jsonData; 11 | } 12 | 13 | public override string JsonData 14 | { 15 | get { return _jsonData; } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | THIS PROJECT IS DORMANT, PLEASE USE https://github.com/leggetter/pusher-dotnet-server INSTEAD 2 | 3 | 4 | The Pusher REST .NET project is implementation of the Pusher REST API in C#. 5 | 6 | It provides functionality to let you trigger events using the Pusher REST API in addition to 7 | [authenticating](http://pusher.com/docs/authenticating_users) user subscription request to 8 | [private](http://pusher.com/docs/private_channels) and [presence](http://pusher.com/docs/presence) channels. 9 | 10 | ## Trigger events 11 | 12 | Events can be triggered with any type of data which is then serialized to JSON. 13 | 14 | var provider = new PusherProvider(applicationId, applicationKey, applicationSecret); 15 | var request = new ObjectPusherRequest("test_channel", "my_event", new 16 | { 17 | some = "data" 18 | }); 19 | 20 | provider.Trigger(request); 21 | 22 | ## Authenticate Private Channels 23 | 24 | Assuming that the running application is an ASP.NET app then the private channels are 25 | authenticated using the `IPusherProvider.Authenticate` method with the values for the 26 | channel name and the socket ID retrieved from the `Request` object. 27 | 28 | var provider = new PusherProvider(appId, appKey, appSecret); 29 | string auth = provider.Authenticate(Request["channel_name"], Request["socket_id"); 30 | Response.Write(auth); 31 | 32 | ## Authenticate Presence Channels 33 | 34 | Presence channels are authenticated in much the same way as private channels. The only difference 35 | is that the channel data must also be passed to the `IPusherProvider.Authenticate` method so 36 | that it can be hashed within the authentication string. 37 | 38 | var provider = new PusherProvider(appId, appKey, appSecret); 39 | string auth = provider.Authenticate(Request["channel_name"], Request["socket_id"); 40 | Response.Write(auth); 41 | -------------------------------------------------------------------------------- /lib/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahamscott/pusherrestdotnet/f2af4bd6e0cddbedeb7b53928e323b3d883794a2/lib/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /lib/Newtonsoft.Json.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahamscott/pusherrestdotnet/f2af4bd6e0cddbedeb7b53928e323b3d883794a2/lib/Newtonsoft.Json.pdb -------------------------------------------------------------------------------- /lib/Rhino.Mocks.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahamscott/pusherrestdotnet/f2af4bd6e0cddbedeb7b53928e323b3d883794a2/lib/Rhino.Mocks.dll -------------------------------------------------------------------------------- /lib/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grahamscott/pusherrestdotnet/f2af4bd6e0cddbedeb7b53928e323b3d883794a2/lib/nunit.framework.dll --------------------------------------------------------------------------------