Giter Site home page Giter Site logo

ringcentral-csharp-client's Introduction

ringcentral-csharp-client

Build status Coverage Status NuGet Version Chat

RingCentral C# client.

Notice: any issues or questions, please do let me know by creating an issue.

Feel free to โญ and ๐Ÿด this repository.

Installation

Install-Package RingCentral.Client

API Reference

RingCentral API Reference is where you can find all the endpoints, requests, parameters and all kinds of necessary details.

Please note: as a guest reader, you can only read the basic version of API Reference. Please do login if you want to get information about Advanced API endpoints.

Initialization

using RingCentral;

rc = new RestClient("clientId", "clientSecret");

By default the clients talk to sandbox server. If you want production server:

rc = new RestClient("clientId", "clientSecret", true);

Or you can specify the server url explicitly:

rc = new RestClient("clientId", "clientSecret", "https://platform.devtest.ringcentral.com");

Authorization

await rc.Authorize("username", "extension", "password");

If you use direct number as username, leave extension empty.

Auto refresh

By default, there is a background timer calling rc.Refresh() periodically, so the authorization never expires.

But if you would like to call Refresh manually:

rc.AutoRefreshToken = false;

Token Revoke

When you no longer need a token, don't forget to revoke it: rc.Revoke().

Map URI to code

This client library is built around URIs. Please read this part carefully and make sure you get it before continuing.

Let's go to the RingCentral API Reference to find an example.

We can see that the URI pattern is:

/restapi/v1.0/account/{accountId}/extension/{extensionId}/call-log/{callRecordId}

An real example of the URI could be:

/restapi/v1.0/account/~/extension/130829004/call-log/ASsQ3xLOZfrLBwM

Let's map the URI above to code:

rc.Restapi("v1.0").Account("~").Extension("130829004").CallLog("ASsQ3xLOZfrLBwM");

It's just a one-to-one mapping:

mapping

Default ID

The default ID for Restapi is v1.0, the default ID for Account and Extension is ~.

We can omit arguments to use default value:

rc.Restapi().Account().Extension("130829004").CallLog("ASsQ3xLOZfrLBwM");

You can also break it into multiple lines if you don't like long-chained method calls:

var account = rc.Restapi().Account();
var extension = account.Extension("130829004");
var callLog = extension.CallLog("ASsQ3xLOZfrLBwM");

Anonymous types vs Pre-defined types

For example, the following line is for sending fax:

var response = await extension.Fax().Post(requestBody, attachments);

To create the requestBody object, you can define it as following:

var requestBody = new FaxPath.PostParameters
{
    to = new CallerInfo[] { new CallerInfo { phoneNumber = "123456789" } }
}

Or, you can define it using anonymous types:

var requestBody = new
{
    to = new object[] { new { phoneNumber = "123456789" } }
}

Both are OK. The anonymous types approach is shorter while you can take advantages of IDE intellisense with pre-defined types approach. You can choose based on your preferences.

Talk to API Server

var extension = rc.Restapi().Account().Extension();

GET

List all of the inbound call Logs
var callLogs = await extension.CallLog().List(new { direction = "Inbound" });

Or if you prefer the query parameters as a typed model:

var callLogs = await extension.CallLog().List(new CallLog.ListParameters { direction = "Inbound" });

All the HTTP calls are by default async, so you should use the await keyword of C#.

Get a call log by ID
var callLog = await extension.CallLog("ASsQ3xLOZfrLBwM").Get();

You can inspect the attributes of the returned callLog object because it is a model instead of a string:

Console.WriteLine(callLog.id);
Console.WriteLine(callLog.direction);
Console.WriteLine(callLog.startTime);

POST

Send an SMS
var requestBody = new {
    text = "hello world",
    from = new { phoneNumber = phoneNumber },
    to = new object[] { new { phoneNumber = phoneNumber } }
};
var response = await extension.Sms().Post(requestBody);

PUT

Update message status
var requestBody = new { readStatus = "Read" };
var response = await extension.MessageStore(messageId).Put(requestBody);

DELETE

Delete message by ID
var response = await extension.MessageStore(messageId).Delete();

What if I want plain HTTP without those fancy models?

var endpoint = rc.Restapi().Dictionary().Timezone("6").Endpoint(); // "/restapi/v1.0/dictionary/timezone/6"
var response = await rc.Get(endpoint); // make http request
var statusCode = response.StatusCode; // check status code
var str = await response.Content.ReadAsStringAsync(); // get response string

Subscription

var subscription = rc.Restapi().Subscription().New();
subscription.EventFilters.Add("/restapi/v1.0/account/~/extension/~/message-store");
subscription.EventFilters.Add("/restapi/v1.0/account/~/extension/~/presence?detailedTelephonyState=true");
subscription.NotificationEvent += (sender, args) => {
    var message = args.message;
    dynamic jObject = JObject.Parse(message);
    var eventString = (string)jObject.@event;
    if(new Regex("/account/\\d+/extension/\\d+/message-store").Match(eventString).Success) {
        var bodyString = JsonConvert.SerializeObject(jObject.body);
        // If you want to play with raw json string, you can ignore the content below
        var messageEvent = JsonConvert.DeserializeObject<MessageEvent>(bodyString); // deserialize body to MessageEvent object.
        Console.WriteLine(messageEvent.changes[0].type);
    }
};
await subscription.Register();

The subscription will renew itself automatically before it expires. In rare cases you might need to renew it manually:

await subscription.Renew();

Send Fax

var attachment1 = new Attachment { fileName = "test.txt", contentType = "text/plain", bytes = Encoding.UTF8.GetBytes("hello world") };
var attachment2 = new Attachment { fileName = "test.pdf", contentType = "application/pdf", bytes = File.ReadAllBytes("test.pdf") };
var attachments = new Attachment[] { attachment1, attachment2 };
var response = await extension.Fax().Post(new FaxPath.PostParameters
{
    to = new CallerInfo[] { new CallerInfo { phoneNumber = Config.Instance.receiver } }
}, attachments);

Binary data

Create/Update profile image

// create
var bytes = File.ReadAllBytes("test.png");
var response = await extension.ProfileImage().Post(bytes, "test.png");

// update
var bytes = File.ReadAllBytes("test.png");
var response = await extension.ProfileImage().Put(bytes, "test.png");

Get message content

var response = await extension.MessageStore().List()
var messages = response.records;

// sms
var message = messages.Where(m => m.type == "SMS" && m.attachments != null && m.attachments.Length > 0).First();
var content = await extension.MessageStore(message.id).Content(message.attachments[0].id).Get();
var str = System.Text.Encoding.UTF8.GetString(content.data);

// fax
message = messages.Where(m => m.type == "Fax" && m.attachments != null && m.attachments.Length > 0).First();
content = await extension.MessageStore(message.id).Content(message.attachments[0].id).Get();
File.WriteAllBytes("test.pdf", content.data);

Download call recording

var account = rc.Restapi().Account();

// List call Logs
var queryParams = new CallLogPath.ListParameters
{
    type = "Voice",
    view = "Detailed",
    dateFrom = DateTime.UtcNow.AddDays(-100).ToString("o"),
    withRecording = true,
    perPage = 10,
};
var callLogs = await account.CallLog().List(queryParams);

// download a call recording
var callLog = callLogs.records[0];
var content = await account.Recording(callLog.recording.id).Content().Get();
File.WriteAllBytes("test.wav", content.data);

Exception handling

try
{
    await ...
}
catch (FlurlHttpException fhe)
{
    string errorMessage = fhe.GetResponseString();
    Console.WriteLine(errorMessage);
    if (fhe.Call.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
    {
        Console.WriteLine("The resource doesn't exist");
    }
}

Sample code

The unit test project contains lots of useful code snippets. Such as this test class.

License

MIT

ringcentral-csharp-client's People

Contributors

tylerlong avatar grokify avatar rbnswartz avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.