Skip to content
Merged
Changes from all commits
Commits
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
222 changes: 111 additions & 111 deletions streamerbot/4.examples/http-post.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,172 +20,172 @@ Read more about the `Execute C# Code` sub-action

1. Basic understanding of writing C# code

Since all of this *has* to be implemented in a C# code module, basic understanding of writing C# code and using common libraries is required. I will only give the most basic example, you will likely need to adapt it to your usecase.
Since all of this *has* to be implemented in a C# code module, basic understanding of writing C# code and using common libraries is required. I will only give the most basic example, you will likely need to adapt it to your use case.

2. Understanding on how to use C# in sub-actions

Be it a single use `Execute C# Code` block for a single instance of needing to send a request, or a more persistent C# module with different actions triggering different `Execute C# Method` sub-actions - you need to know how use this feature in your normal action flow.
Be it a single use `Execute C# Code` block for a single instance of needing to send a request, or a more persistent C# module with different actions triggering different `Execute C# Method` sub-actions - you need to know how use this feature in your normal action flow.

The following tutorial will only focus on the magic happening inside of the C# code module.
The following tutorial will only focus on the magic happening inside of the C# code module.

## Instructions

1. Setup the HTTPClient
1. Set up the HTTPClient

```cs [Basic Setup]
using System;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
```cs [Basic Setup]
using System;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class CPHInline {
// You can set the timeout to any length you need
private static readonly HttpClient _httpClient = new HttpClient{Timeout = TimeSpan.FromSeconds(30)};
public class CPHInline {
// You can set the timeout to any length you need
private static readonly HttpClient _httpClient = new HttpClient{Timeout = TimeSpan.FromSeconds(30)};

public void Init() {
// Ensure we are working with a clean slate
_httpClient.DefaultRequestHeaders.Clear();
}
public void Init() {
// Ensure we are working with a clean slate
_httpClient.DefaultRequestHeaders.Clear();
}

public void Dispose() {
// Free up allocations
_httpClient.Dispose();
}
public void Dispose() {
// Free up allocations
_httpClient.Dispose();
}

public bool Execute() {
// ...
return true;
}
public bool Execute() {
// ...
return true;
}
```
}
```

::tip
While people using the HTTPClient in a `using` statement or creating a new one within the executed function may be a common occurence, it is heavily discouraged to do so. [Read More](https://extensions.streamer.bot/t/httpclient-and-you/1369)
::
::tip
While people using the HTTPClient in a `using` statement or creating a new one within the executed function may be a common occurence, it is heavily discouraged to do so. [Read More](https://extensions.streamer.bot/t/httpclient-and-you/1369)
::

2. Setup the sending of your payload

We are going to send a `%userName%` and `%userId%` pair (from common triggers) as `PUT` request to our fictional logging website.
We are going to send a `%userName%` and `%userId%` pair (from common triggers) as `PUT` request to our fictional logging website.

```cs [Send PUT payload in Execute method]
public bool Execute() {
// Get the arguments - or abort if it does not exist
if(!CPH.TryGetArg("userName", out string userName)) return false;
if(!CPH.TryGetArg("userId", out string userId)) return false;
```cs [Send PUT payload in Execute method]
public bool Execute() {
// Get the arguments - or abort if it does not exist
if(!CPH.TryGetArg("userName", out string userName)) return false;
if(!CPH.TryGetArg("userId", out string userId)) return false;

// Build a wrapper object as payload
var data = new {
id = userId,
name = userName
};
// Build a wrapper object as payload
var data = new {
id = userId,
name = userName
};

// Serialize JSON
string json = JsonConvert.SerializeObject(data);
// Serialize JSON
string json = JsonConvert.SerializeObject(data);

// Create web request payload
var payload = new StringContent(json, Encoding.UTF8, "application/json");
// Create web request payload
var payload = new StringContent(json, Encoding.UTF8, "application/json");

// Finally, send request
HttpResponseMessage response = _httpClient.PutAsync("https://my-logging-server.com", payload).GetAwaiter().GetResult();
// Finally, send request
HttpResponseMessage response = _httpClient.PutAsync("https://my-logging-server.com", payload).GetAwaiter().GetResult();

// Do with the response what you need to.
// ...
// Do with the response what you need to.
// ...

return true;
}
```
return true;
}
```

To use different request types, simply use the methods `GetAsync()`, `PutAsync()`, `PostAsync()` or `DeleteAsync()`.
To use different request types, simply use the methods `GetAsync()`, `PutAsync()`, `PostAsync()` or `DeleteAsync()`.

3. The PATCH request

Specifically the built-in handling for the `PATCH` request type may not be available in the .net versions used by StreamerBot. In this case, you need a workaround.
Specifically the built-in handling for the `PATCH` request type may not be available in the .net versions used by StreamerBot. In this case, you need a workaround.

```cs [PATCH workaround]
// ...
```cs [PATCH workaround]
// ...

// Finally, send the request
var request = new HttpRequestMessage(new HttpMethod("PATCH"), "https://my-logging-server.com"){
Content = payload
};
HttpResponseMessage response = _httpClient.SendAsync(request).GetAwaiter().GetResult();
// Finally, send the request
var request = new HttpRequestMessage(new HttpMethod("PATCH"), "https://my-logging-server.com"){
Content = payload
};
HttpResponseMessage response = _httpClient.SendAsync(request).GetAwaiter().GetResult();

// ...
```
// ...
```

4. Additional Headers

If you need to additionally include specific headers - like submitting an authorization token for the Twitch API or Discord API - make sure to clear and set the headers on each call you make.
If you need to additionally include specific headers - like submitting an authorization token for the Twitch API or Discord API - make sure to clear and set the headers on each call you make.

You can also send individual headers with each request itself, but that requires you to always use the `SendAsync` method and building your own `HttpRequestMessage`.
You can also send individual headers with each request itself, but that requires you to always use the `SendAsync` method and building your own `HttpRequestMessage`.

If your code only does a static request whose headers never change, resetting the headers is **not strictly necessary**. But it's good practice to not forget later when you need it.
If your code only does a static request whose headers never change, resetting the headers is **not strictly necessary**. But it's good practice to not forget later when you need it.

```cs [Header management]
public bool Execute() {
// Making a call to the Twitch API to get all currently live streams
string token = CPH.TwitchOAuthToken;
string clientId = CPH.TwitchClientId;
```cs [Header management]
public bool Execute() {
// Making a call to the Twitch API to get all currently live streams
string token = CPH.TwitchOAuthToken;
string clientId = CPH.TwitchClientId;

// Clear our old headers
_httpClient.DefaultRequestHeaders.Clear();
// Clear our old headers
_httpClient.DefaultRequestHeaders.Clear();

// Now set your Twitch API authorization
_httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer "+token);
_httpClient.DefaultRequestHeaders.Add("Client-Id", clientId);
// Now set your Twitch API authorization
_httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer "+token);
_httpClient.DefaultRequestHeaders.Add("Client-Id", clientId);

// Send your request
HttpResponseMessage response = _httpClient.GetAsync("https://api.twitch.tv/helix/streams").GetAwaiter().GetResult();
// Send your request
HttpResponseMessage response = _httpClient.GetAsync("https://api.twitch.tv/helix/streams").GetAwaiter().GetResult();

// Do with the response what you need to.
// ...
// Do with the response what you need to.
// ...

return true;
}
```
return true;
}
```

5. Handling the response

Since you have to do the entire request handling yourself, that includes handling the response.
Since you have to do the entire request handling yourself, that includes handling the response.

- If you don't need to know what the server responded, you can ignore it like in the examples above.
- If you don't need to know what the server responded, you can ignore it like in the examples above.

- If you need to know if the request succeeded or are expecting data in return, follow the below example.
- If you need to know if the request succeeded or are expecting data in return, follow the below example.

```cs [Response handling]
public bool Execute() {
// ...all your data preparation
```cs [Response handling]
public bool Execute() {
// ...all your data preparation

HttpResponseMessage response = _httpClient.GetAsync("https://api.twitch.tv/helix/streams").GetAwaiter().GetResult();
HttpResponseMessage response = _httpClient.GetAsync("https://api.twitch.tv/helix/streams").GetAwaiter().GetResult();

// Check if our request was successful
try {
if(!response.IsSuccessStatusCode) {
// It was not. Abort.
CPH.LogError($"{response.StatusCode} - {response.ReasonPhrase}");
return false;
}
// Check if our request was successful
try {
if(!response.IsSuccessStatusCode) {
// It was not. Abort.
CPH.LogError($"{response.StatusCode} - {response.ReasonPhrase}");
return false;
}

// Get the response data
string content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
// Get the response data
string content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

// Usually, data is JSON. So you would decode it now.
JObject parsed = JObject.Parse(content);
// Usually, data is JSON. So you would decode it now.
JObject parsed = JObject.Parse(content);

// And then do with the data whatever you need.
// ...
// And then do with the data whatever you need.
// ...

return true;
} catch (Exception e) {
// Something went wrong
CPH.LogError(e.Message);
return false;
}
return true;
} catch (Exception e) {
// Something went wrong
CPH.LogError(e.Message);
return false;
}
```
}
```

## Tips & Tricks

Expand Down
Loading