Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
66de93e
sendMessage template to continue from.
Jul 10, 2023
9842aa9
.NET send_tweet function initial commit
Jul 11, 2023
bdd6e88
included the tweetinviapi in the csproj file.
Jul 12, 2023
4503d89
send discord message initial commit
Jul 12, 2023
f542bc3
discord error fixed
Jul 17, 2023
88a906b
sendTweet error checking
Jul 17, 2023
d517329
added api calls to for send_sms with twilio
gyamposudodzi Jul 18, 2023
90b6266
Merge branch 'main' of https://github.com/TEAM-DODZI-EPHRAIM-OLUWAFEM…
gyamposudodzi Jul 18, 2023
4af24d1
completed the Twilio SMS fxn
gyamposudodzi Jul 18, 2023
92f2aeb
changed name from Twiliosms to send_sms_twilio
gyamposudodzi Jul 18, 2023
bc4cf20
Updated README doc for sendMessage function .NET
Jul 18, 2023
857bb98
added notes and completed variables
Jul 19, 2023
42ddb2b
changed twilio naming coventions and added namespace to twilio file
Jul 19, 2023
48b442d
index.cs initial commit
Jul 25, 2023
b289bbb
Update README.md with project cloning instructions
Jul 25, 2023
e116532
changes to index.cs and function bug fixes
Aug 7, 2023
b9e4b4a
Merge branch 'main' of https://github.com/TEAM-DODZI-EPHRAIM-OLUWAFEM…
Aug 7, 2023
086ed33
Bug fixes in the function files
Aug 9, 2023
ec74b3b
minor changes to the sms function
Aug 9, 2023
c9fcb12
bug fix
Aug 9, 2023
b9ef6ac
bug fix
Aug 9, 2023
f620b20
Update README.md: completed deployment steps.
Aug 15, 2023
b3a033e
Update README.md: added JSON expression
Aug 15, 2023
b17bbd5
Update README.md
Aug 15, 2023
773e5c3
Update to error handling
Aug 15, 2023
78eca1b
Finishing touches
Aug 15, 2023
85ec9b1
changes to readme
Aug 15, 2023
55489aa
Changes to deployment in readme
Aug 16, 2023
d92afa7
changes to naming conventions, and change in index.cs file
Aug 16, 2023
5436cdc
change sendmessage from common library to sendmessagefunction that is…
Aug 16, 2023
04f3bfe
included launchsettings
Aug 16, 2023
ba2a177
added updated readme
Aug 17, 2023
372c4be
fixed readme typo
Aug 17, 2023
cc6f351
faulty sendmessage function removed
Aug 17, 2023
5afeedf
renamed SendMessageFunction to SendMessage
Aug 17, 2023
39b2a88
Delete dotnet/.vscode directory
Sep 20, 2023
aa69247
Delete .vscode directory
Sep 20, 2023
923d0f7
Delete dotnet/SendMessage/obj directory
Sep 20, 2023
aaa1f84
Delete dotnet/SendMessage/Properties directory
Sep 20, 2023
1097174
Delete dotnet/dotnet.sln
Sep 20, 2023
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
50 changes: 50 additions & 0 deletions dotnet/SendMessage/Index.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Newtonsoft.Json;
using SendMessageFunction;

public async Task<RuntimeResponse> Main(RuntimeRequest req, RuntimeResponse res)
{
string? channel = "type";
string? message = "";
string? recipient = "";
string? subject = "";
object response = true;
object responsemessage = "";
Dictionary<string, object> result = new Dictionary<string, object>();

if (string.IsNullOrEmpty(req.Payload))
{
return res.Json(new()
{
{"success", false},
{"message", req.Variables}
});
}

var payload = JsonConvert.DeserializeObject<Dictionary<string, string>>(req.Payload);
payload.TryGetValue("type", out channel);
payload.TryGetValue("message", out message);
payload.TryGetValue("receiver", out recipient);

if (channel == "Discord"){
result = await DiscordWebhook.SendDiscordMessage(req.Variables, message);
}
else if(channel == "Email"){
payload.TryGetValue("subject", out subject);
result = await Mail.SendMail(req.Variables, recipient, message, subject);
}
else if(channel == "Twitter"){
result = await TwitterSender.SendTweet(req.Variables, message);
}
else if(channel == "SMS"){
result = await SendSmsTwilio.SendSMS(req.Variables, recipient, message);
}

result.TryGetValue("success", out response!);
result.TryGetValue("message", out responsemessage!);

return res.Json(new()
{
{"success", response},
{"message", responsemessage}
});
}
143 changes: 143 additions & 0 deletions dotnet/SendMessage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# 📬 Send Message using a specific channel

A .NET Cloud Function for sending a message using a specific channel to a receiver.

Supported channels include, `SMS`, `Email` ,`Disocrd` and `Twitter`.

## Examples

### Example input: (Discord)

```json
{
"type": "Discord",
"message": "Programming is fun!"
}
```

### Example input: (SMS)

```json
{
"type": "SMS",
"receiver": "+123456789",
"message": "Programming is fun!"
}
```

### Example input: (Email)

```json
{
"type": "Email",
"receiver": "[email protected]",
"subject": "Programming is fun!",
"message": "Programming is fun!"
}
```

### Example input: (Twitter)

```json
{
"type": "Twitter",
"message": "Programming is fun!"
}
```

### Example output: (Success)

```json
{
"success": true
}
```

### Example output: (Failure)

```json
{
"success": false,
"message": "Receiver is not a valid email."
}
```

## 📝 Variables

List of variables used by this cloud function:

### Twilio

- **TWILIO_ACCOUNT_SID** - Acount SID from Twilio
- **TWILIO_AUTH_TOKEN** - Auth Token from Twilio
- **TWILIO_SENDER** - Sender Phone Number from Twilio

### Discord

- **DISCORD_WEBHOOK_URL** - Webhook URL for Discord

### Mailgun

- **MAILGUN_API_KEY** - API Key for Mailgun
- **MAILGUN_DOMAIN** - Domain Name from Mailgun

### Twitter

- **TWITTER_API_KEY** - API Key for Twitter
- **TWITTER_API_KEY_SECRET** - API Key Secret for Twitter
- **TWITTER_ACCESS_TOKEN** - Access Token from Twitter
- **TWITTER_ACCESS_KEY_SECRET** - Access Token Secret from Twitter

## 🚀 Deployment

<!-- To do:
1. Update the deployment section -->

There are two ways of deploying the Appwrite function, both having the same results, but each using a different process.

### Using CLI

Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`.

Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy.

### Manual Deployment

Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it using the following command. In order to create a tar ball. Enter this command to build the code.
```
docker run --rm --interactive --tty \
-e INTERNAL_RUNTIME_ENTRYPOINT=Index.cs \
--volume $PWD:/usr/code \
openruntimes/dotnet:v2-6.0 sh \
/usr/local/src/build.sh
```
Then
```
tar -czf code.tar.gz --exclude code.tar.gz .
```

After creating `.tar.gz` file, visit Appwrite Console, click on the `Create deployment` button and switch to the `Manual` tab. There, set the `entrypoint` to `Index.cs`, and upload the file we just generated.

### Executing the function without the Appwrite Console

After you have built the code with the command above, run the following up command to start a server to listen to your request on your local host.
```
docker run --rm --interactive --tty \
-p 3000:3000 \
-e INTERNAL_RUNTIME_KEY=secret-key \
-e INTERNAL_RUNTIME_ENTRYPOINT=Index.cs \
--volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro \
openruntimes/dotnet:v2-6.0 \
sh /usr/local/src/start.sh
```
Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers.

Sample execution using curl
```
curl -X POST http://localhost:3000/ -d '{"variables": {"DISCORD_WEBHOOK_URL":"YOUR_DISCORD_WEBHOOK_URL"},"payload": "{\"type\": \"Discord\",\"message\": \"Programming is fun!\",}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json"
```

## 📝 Notes

- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions).
- This example is compatible with C# and .NET.
13 changes: 13 additions & 0 deletions dotnet/SendMessage/SendMessageFunction.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TweetinviAPI" Version="5.0.4" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />

</ItemGroup>
</Project>
8 changes: 8 additions & 0 deletions dotnet/SendMessage/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions dotnet/SendMessage/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
43 changes: 43 additions & 0 deletions dotnet/SendMessage/src/SendDiscordMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Text;


namespace SendMessageFunction
{
public class DiscordWebhook{
public static async Task<Dictionary<string, object>> SendDiscordMessage(Dictionary<string,string> variables, string? message)
{
if(message == null)
{
return new Dictionary<string, object> {{"success", false}, {"message","Missing message"}};
}

string webhook = variables["DISCORD_WEBHOOK_URL"];

if(webhook == null)
{
return new Dictionary<string, object> {{"success", false}, {"message","Missing webhook"}};
}

try{
using (HttpClient httpclient = new HttpClient()){
var contentofmessage = new StringContent(
"{\"content\": \"" + message + "\"}",
Encoding.UTF8,
"application/json"
);
HttpResponseMessage response = await httpclient.PostAsync(webhook, contentofmessage);
response.EnsureSuccessStatusCode();
return new Dictionary<string, object> {{"success" , true}, {"message", "Your message was sent"}};
}

}
catch (Exception e)
{
Console.WriteLine(e);
return new Dictionary<string, object> {{"success", false}, {"message", e.ToString()}};
}


}
}
}
58 changes: 58 additions & 0 deletions dotnet/SendMessage/src/SendMail.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System.Text;
using System.Net.Http.Headers;


namespace SendMessageFunction
{

public class Mail
{
public static async Task<Dictionary<string,object>> SendMail(Dictionary<string,string> variables, string? email, string? message, string? subject)
{
if(email == null || message == null || subject == null)
{
return new Dictionary<string,object> {{"success", false}, {"message","Missing email, subject, or message"}};
}

string domain = variables["MAILGUN_DOMAIN"];
string apiKey = variables["MAILGUN_API_KEY"];
HttpResponseMessage? response;

if(domain == null)
{
return new Dictionary<string,object> {{"success", false}, {"message","Missing Mailgun domain"}};
}
if(apiKey == null)
{
return new Dictionary<string,object> {{"success", false}, {"message","Missing Mailgun API key"}};
}
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"api:{apiKey}")));

var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{"from", "<[email protected]>"},
{"to", email},
{"subject", subject},
{"text", message}
});

response = await client.PostAsync($"https://api.mailgun.net/v3/{domain}/messages", content);
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
return new Dictionary<string, object> {{"success" , true}, {"message", "Your message was sent"}};
}

}
catch (Exception e)
{
return new Dictionary<string, object> {{"success" , false}, {"message" , e.ToString()}};
}


}
}
}
Loading