# msgapi-sdk-net
Version: 2.0.2

## Installation
- Install Microsoft .NET Framework 4.8 or later

## Troubleshooting
To solve potential installation problems, please make sure you have installed the following:
- .NET Framework 4.8 runtime: https://dotnet.microsoft.com/en-us/download/dotnet-framework/net48
- Microsoft Visual C++ Redistributable package: https://aka.ms/vs/17/release/vc_redist.x64.exe

If upon running your project an error is shown stating that platform components are missing (e.g., “libsodium”), make sure you are building against a supported system architecture and the appropriate `libsodium.dll` (can be found in the `lib` folder) is present in your chosen architecture’s `bin` folder.
Alternatively, you may copy the appropriate `libsodium.dll` library into a directory available from your PATH or `System32` folder.

If a text message is sent with the wrong characters, please ensure your command line is using UTF8 encoding.

If an error code (0x)80131040 occurs while trying to use `Threema.MsgApi.dll`, the console application or the VB Script, it might be necessary to manually clear all registry subkeys of `Computer\HKEY_CLASSES_ROOT\CLSID\{097F1D26-B38E-4501-845D-6DE7DBFB2EAA}\InprocServer32` before trying to register the DLL with `regasm.exe`.

PowerShell (powershell):
PS C:\>$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding

Command Prompt (cmd):
C:\>chcp 65001

### Register MsgApi as COM Component
regasm.exe Threema.MsgApi.dll /codebase

- `regasm.exe` can be found in either of the following directories depending on the operating system architecture: in `C:\Windows\Microsoft.NET\Framework\v4.0.30319` when running on a 32 bit machine, or in `C:\Windows\Microsoft.NET\Framework64\v4.0.30319` for 64 bit.

### Add msgapi to Assembly Cache
- Manage your assembly cache with `gacutil.exe`

#### Is Threema.MsgApi Already Installed
gacutil.exe /l Threema.MsgApi

#### Install Assembly
gacutil.exe /i C:\..\Threema.MsgApi.dll

## Releases

### Building a Release Zip

For the release script to run correctly, it must be run from a (non-elevated) Developer Command Prompt using the following command: `powershell .\Threema-MsgApi-Sdk-Net-Release.ps1`
There must be a `releases` folder in the parent directory from where the PowerShell script is run.

## SDK Usage

### Generate Key Pair

> &#x26a0;&#xfe0f; *IMPORTANT* &#x26a0;&#xfe0f;\
> <b>Create a backup (or preferably multiple backups) of your private key!</b> If you lose it, your custom Threema ID will be unusable. We have no way to recover lost private keys for you, and it is also not possible to assign a new key to an existing ID.\
> This means that after requesting an E2E Gateway ID with a public key, <b>if the corresponding private key is lost, nobody will ever be able to use this Gateway ID again!</b>

#### Console
.\Threema.MsgApi.Console\bin\Debug\Threema.MsgApi.Console.exe -g .\privatekey.txt .\publickey.txt [apiUrl]

#### VB Script
CScript.exe .\MsgApiSdk.vbs -g .\privatekey.txt .\publickey.txt

### Send End-to-End Encrypted Text Message

#### Console
echo "Test Threema Message" | .\Threema.MsgApi.Console\bin\Debug\Threema.MsgApi.Console.exe -S <id> <from> <secret> .\privatekey.txt

#### VB Script
echo "Test Threema Message" | CScript.exe .\MsgApiSdk.vbs -S <id> <from> <secret> .\privatekey.txt

#### PowerShell
```powershell
$assembly = [Reflection.Assembly]::LoadFile("C:\path\to\Threema.MsgApi.dll")
$instance = New-Object Threema.MsgApi.APIConnector -ArgumentList "*YOUR_GATEWAY_THREEMA_ID", "YOUR_GATEWAY_THREEMA_ID_SECRET"
$instance.SendTextMessageSimple($threemaId, "Simple Text from PowerShell")
...
```

#### Public Key Store Config
There is an SQLite solution implemented which can be enabled in `app.config`

### Code Examples

#### Creating a Connection
```csharp
// TODO: implement your own public key store, or use the SQLite implementation "PublicKeyStoreDb" (fallback when unspecified), to get better performance.
var connector = new APIConnector("*YOUR_GATEWAY_THREEMA_ID", "YOUR_GATEWAY_THREEMA_ID_SECRET");
// The User-Agent used for API requests can be customized. It can also be set to the empty string which removes the “User-Agent” header from all requests, default: threema-msgapi-sdk-net/2.0.2.
connector.UserAgent = "threema-msgapi-sdk-net";
```

#### Sending a Text Message to a Threema ID (Basic Mode)
```csharp
// Connection setup...
// (...)

// Send Simple Message
var messageId = connector.SendTextMessageSimple(threemaId, "Simple Text");
```

#### Sending a Text Message to a Threema ID (End-To-End Mode)
```csharp
// Connection setup...
// (...)

// Specify your private key in hex below, or read it from the env
byte[] privateKey = new Key(Key.KeyType.PRIVATE, DataUtils.HexStringToByteArray(Environment.GetEnvironmentVariable("GATEWAY_PRIVATE_KEY")));
// OR
byte[] privateKey = DataUtils.ReadKeyFile("/path/to/my/private.key", Key.KeyType.PRIVATE);

// Create the E2EHelper
var e2EHelper = new E2EHelper(connector, privateKey.key);

// The recipient’s Threema ID
var threemaId = "ABCDEFGH";

// Send Text Message
var messageId = e2EHelper.SendTextMessage(threemaId, new TextMessage("E2E Text"));
```

#### Sending a Group File Message to a Threema ID (End-To-End Mode)
```csharp
// Connection setup + private key...
// (...)

// Create E2EHelper
// (...)

// Compose File Message
var caption = "End-To-End Encrypted Caption";
var groupId = new GroupId(Encoding.UTF8.GetBytes("AGROUPID"), Encoding.UTF8.GetBytes("*ASENDER"));
FileInfo fileToSend = new FileInfo("C:\\Users\\MyUser\\Downloads\\file.jpg");
FileInfo thumbnailFileToSend = new FileInfo("C:\\Users\\MyUser\\Downloads\\thumb.jpg");
var messageIds = e2EHelper.SendGroupFileMessage(groupId, new[] { threemaId }, fileToSend, thumbnailFileToSend, caption, FileRenderingType.Media);

foreach (var id in messageIds)
{
    Console.WriteLine("Message Id: " + id);
}

// ...
```

#### Receiving a Message
```csharp
// Connection setup and private key...
// (...)

var res = e2EHelper.ReceiveMessage(threemaId, "5fcb7acb4b26e834", DataUtils.HexStringToByteArray("abdef9921234124..."), DataUtils.HexStringToByteArray("23f2e354155..."), @"C:\Message_Downloads");

switch (res.Message.GetTypeCode())
{
    case TextMessage.TYPE_CODE:
        var text = ((TextMessage)res.Message).Text;
        // ...
        break;
    case FileMessage.TYPE_CODE:
        var metadata = ((FileMessage)res.Message).Metadata;
        // ...
        break;
    default:
        throw new UnsupportedMessageTypeException();
}

// ...
```

#### More Examples
For more code examples, please refer to the `E2ETest.cs` source file of the `Threema.MsgApi.Test` project inside the .NET solution.
