Skip to content

Commit 899073e

Browse files
committed
Add message confirmation methods
1 parent 9e3bd0b commit 899073e

4 files changed

Lines changed: 130 additions & 15 deletions

File tree

API.Test/MessagesTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ public void GetMessageInbox()
4141
{
4242
Client.LoginAsync(s_Server, s_LoginName, s_UserName, s_Password).Wait();
4343

44-
Task<MessagePreview[]> messages = Client.GetMessageInboxAsync();
44+
Task<(MessagePreview[], MessagePreview[])> messages = Client.GetMessageInboxAsync();
4545
messages.Wait();
46-
if (messages.Result.Length > 0)
46+
if (messages.Result.Item1.Length > 0)
4747
Assert.Pass();
4848
else
4949
Assert.Fail();
@@ -67,9 +67,9 @@ public void GetFullMessage()
6767
{
6868
Client.LoginAsync(s_Server, s_LoginName, s_UserName, s_Password).Wait();
6969

70-
Task<MessagePreview[]> messages = Client.GetMessageInboxAsync();
70+
Task<(MessagePreview[], MessagePreview[])> messages = Client.GetMessageInboxAsync();
7171
messages.Wait();
72-
Task<Message> msg = messages.Result.First(msg => msg.Subject == "Test").GetFullMessageAsync(Client);
72+
Task<Message> msg = messages.Result.Item1.First(msg => msg.Subject == "Test").GetFullMessageAsync(Client);
7373
msg.Wait();
7474
_ = msg.Result;
7575
return;
@@ -106,10 +106,10 @@ public void GetReplyForm()
106106
{
107107
Client.LoginAsync(s_Server, s_LoginName, s_UserName, s_Password).Wait();
108108

109-
Task<MessagePreview[]> messages = Client.GetMessageInboxAsync();
109+
Task<(MessagePreview[], MessagePreview[])> messages = Client.GetMessageInboxAsync();
110110
messages.Wait();
111111

112-
Task<Message> drafts = Client.GetReplyFormAsync(messages.Result[0]);
112+
Task<Message> drafts = Client.GetReplyFormAsync(messages.Result.Item1[0]);
113113
drafts.Wait();
114114
if (drafts.Result != null)
115115
Assert.Pass();
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using Newtonsoft.Json;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using WebUntisAPI.Client.Converter;
8+
9+
namespace WebUntisAPI.Client.Models.Messages
10+
{
11+
/// <summary>
12+
/// Informations about a confirmed message
13+
/// </summary>
14+
public class ConfirmationInformations
15+
{
16+
/// <summary>
17+
/// Is it allowed to delete the message
18+
/// </summary>
19+
[JsonProperty("allowMessageDeletion")]
20+
public bool AllowMessageDeletion { get; set; }
21+
22+
/// <summary>
23+
/// Is it allowed to send a request confirmation
24+
/// </summary>
25+
[JsonProperty("allowSendRequestConfirmation")]
26+
public bool AllowSendRequestConfirmation { get; set; }
27+
28+
/// <summary>
29+
/// The datetime where you confirmed the message
30+
/// </summary>
31+
[JsonProperty("confirmationDate")]
32+
[JsonConverter(typeof(APIDateTimeJsonConverter))]
33+
public DateTime ConfirmationDate { get; set; }
34+
35+
/// <summary>
36+
/// The name of the user that confirmed hte message
37+
/// </summary>
38+
[JsonProperty("confirmerUserDisplayName")]
39+
public string ConfirmerUserName { get; set; }
40+
41+
/// <summary>
42+
/// The id of the user that confirmed the message (this id isn't the id if from <see cref="IUser.Id"/>)
43+
/// </summary>
44+
[JsonProperty("confirmerUserId")]
45+
public int ConfirmerUserId { get; set; }
46+
47+
/// <summary>
48+
/// Is a reply of the message allowed
49+
/// </summary>
50+
[JsonProperty("isReplyAllowed")]
51+
public bool IsReplyAllowed { get; set; }
52+
}
53+
}

WebUntisAPI.Client/Models/Messages/Message.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,14 @@ private MessagePerson Recipient
115115
/// </summary>
116116
[JsonProperty("replyHistory")]
117117
public List<Message> ReplyHistory { get; set; } = new List<Message>();
118+
119+
/// <summary>
120+
/// Informations about a confirmation of the message
121+
/// </summary>
122+
/// <remarks>
123+
/// When the message won't request a confirmation and was never confirmed the value is <see langword="null"/>
124+
/// </remarks>
125+
[JsonProperty("requestConfirmation")]
126+
public ConfirmationInformations ConfirmationInformations { get; set; } = null;
118127
}
119128
}

WebUntisAPI.Client/WebUntisClient.Messages.cs

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,70 @@ public async Task<Dictionary<string, MessagePerson[]>> GetMessagePeopleAsync(Can
6565
}
6666

6767
/// <summary>
68-
/// Get the you message inbox
68+
/// Get the your message inbox
6969
/// </summary>
7070
/// <param name="ct">Cancellation token</param>
71-
/// <returns>The message previews</returns>
71+
/// <returns>The first value (messageInbox) are the normal inbox and the second value (confirmationMessages) are the messages that request a confirmation with <see cref="ConfirmMessageAsync(Message, CancellationToken)"/></returns>
7272
/// <exception cref="ObjectDisposedException">Thrown when the instance was disposed</exception>
7373
/// <exception cref="UnauthorizedAccessException">Thrown when you're logged in</exception>
7474
/// <exception cref="HttpRequestException">Thrown when an error happened while the http request</exception>
75-
public async Task<MessagePreview[]> GetMessageInboxAsync(CancellationToken ct = default)
75+
public async Task<(MessagePreview[] messageInbox, MessagePreview[] confirmationMessages)> GetMessageInboxAsync(CancellationToken ct = default)
7676
{
7777
string responseString = await MakeAPIGetRequestAsync("/WebUntis/api/rest/view/v1/messages", ct);
7878

79-
JArray jsonMsg = JObject.Parse(responseString).Value<JArray>("incomingMessages");
80-
return new JsonSerializer().Deserialize<List<MessagePreview>>(jsonMsg.CreateReader()).ToArray();
79+
JObject responseObject = JObject.Parse(responseString);
80+
MessagePreview[] inboxMsg = responseObject["incomingMessages"].ToObject<MessagePreview[]>();
81+
MessagePreview[] readConfirmMsg = responseObject["readConfirmationMessages"].ToObject<MessagePreview[]>();
82+
83+
return (inboxMsg, readConfirmMsg);
84+
}
85+
86+
/// <summary>
87+
/// Confirm a recived message
88+
/// </summary>
89+
/// <remarks>
90+
/// You should only use this for confirmation requested messages
91+
/// </remarks>
92+
/// <param name="message">The message to confirm</param>
93+
/// <param name="ct">Cancellation token</param>
94+
/// <returns>Informations about the confirm</returns>
95+
/// <exception cref="ObjectDisposedException">Thrown when the instance was disposed</exception>
96+
/// <exception cref="UnauthorizedAccessException">Thrown when you're logged in</exception>
97+
/// <exception cref="HttpRequestException">Thrown when an error happened while the http request</exception>
98+
public async Task<ConfirmationInformations> ConfirmMessageAsync(Message message, CancellationToken ct = default)
99+
{
100+
if (_disposedValue)
101+
throw new ObjectDisposedException(GetType().FullName);
102+
103+
if (!LoggedIn)
104+
throw new UnauthorizedAccessException("You're not logged in");
105+
106+
HttpRequestMessage request = new HttpRequestMessage()
107+
{
108+
Method = HttpMethod.Post,
109+
RequestUri = new Uri(ServerUrl + $"/WebUntis/api/rest/view/v1/messages/{message.Id}/read-confirmation")
110+
};
111+
request.Headers.Add("JSESSIONID", _sessonId);
112+
request.Headers.Add("schoolname", _schoolName);
113+
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _bearerToken);
114+
115+
HttpResponseMessage response = await _client.SendAsync(request, ct);
116+
117+
// Check cancellation token
118+
if (ct.IsCancellationRequested)
119+
return default;
120+
121+
// Verify response
122+
if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden)
123+
{
124+
_ = LogoutAsync();
125+
throw new UnauthorizedAccessException("You're not logged in");
126+
}
127+
128+
if (response.StatusCode != HttpStatusCode.OK)
129+
throw new HttpRequestException($"There was an error while the http request (Code: {response.StatusCode}).");
130+
131+
return JObject.Parse(await response.Content.ReadAsStringAsync()).ToObject<ConfirmationInformations>();
81132
}
82133

83134
/// <summary>
@@ -101,13 +152,14 @@ public async Task<MessagePreview[]> GetSentMessagesAsync(CancellationToken ct =
101152
/// </summary>
102153
/// <param name="draft">The draft that you want to send</param>
103154
/// <param name="recipients">The recipients for the message</param>
155+
/// <param name="requestConfirmation">Is a confirmation requested (You need the permission)</param>
104156
/// <param name="timeout">The time out for the attachment download (when the draft had attachments they must be downloaded to send them)</param>
105157
/// <param name="ct">Cancellation token</param>
106158
/// <returns>The preview of the sent message</returns>
107159
/// <exception cref="ObjectDisposedException">Thrown when the instance was disposed</exception>
108160
/// <exception cref="UnauthorizedAccessException">Thrown when you're logged in</exception>
109161
/// <exception cref="HttpRequestException">Thrown when an error happened while the http request</exception>
110-
public async Task<MessagePreview> SendMessageAsync(Draft draft, MessagePerson[] recipients, TimeSpan timeout, CancellationToken ct = default)
162+
public async Task<MessagePreview> SendMessageAsync(Draft draft, MessagePerson[] recipients, bool requestConfirmation, TimeSpan timeout, CancellationToken ct = default)
111163
{
112164
Tuple<string, Stream>[] attachments = new Tuple<string, Stream>[0];
113165
if (draft.Attachments.Count > 0)
@@ -121,7 +173,7 @@ public async Task<MessagePreview> SendMessageAsync(Draft draft, MessagePerson[]
121173
attachments = attachmentTasks.Select(attachment => new Tuple<string, Stream>(attachment.Key, attachment.Value.Result)).ToArray();
122174
}
123175

124-
return await SendMessageAsync(draft.Subject, draft.Content, recipients, draft.ForbidReply, attachments, ct);
176+
return await SendMessageAsync(draft.Subject, draft.Content, recipients, requestConfirmation, draft.ForbidReply, attachments, ct);
125177
}
126178

127179
/// <summary>
@@ -131,13 +183,14 @@ public async Task<MessagePreview> SendMessageAsync(Draft draft, MessagePerson[]
131183
/// <param name="content">The content (use <![CDATA[<br>]]> for line breaks</param>
132184
/// <param name="recipients">The recipients for the message</param>
133185
/// <param name="forbidReply">Is a reply forbidden (it need a permission to to that)</param>
186+
/// <param name="requestConfirmation">Is a confirmation requested (You need the permission)</param>
134187
/// <param name="attachments">The attachments to send (Item1 is the name and Item2 the content)</param>
135188
/// <param name="ct">Cancellation token</param>
136189
/// <returns>The preview of the sent message</returns>
137190
/// <exception cref="ObjectDisposedException">Thrown when the instance was disposed</exception>
138191
/// <exception cref="UnauthorizedAccessException">Thrown when you're logged in</exception>
139192
/// <exception cref="HttpRequestException">Thrown when an error happened while the http request</exception>
140-
public async Task<MessagePreview> SendMessageAsync(string subject, string content, MessagePerson[] recipients, bool forbidReply, Tuple<string, Stream>[] attachments = null, CancellationToken ct = default)
193+
public async Task<MessagePreview> SendMessageAsync(string subject, string content, MessagePerson[] recipients, bool requestConfirmation, bool forbidReply, Tuple<string, Stream>[] attachments = null, CancellationToken ct = default)
141194
{
142195
// Check for disposing
143196
if (_disposedValue)
@@ -162,7 +215,7 @@ public async Task<MessagePreview> SendMessageAsync(string subject, string conten
162215
writer.WriteValue(content);
163216

164217
writer.WritePropertyName("requestConfirmation");
165-
writer.WriteValue(false);
218+
writer.WriteValue(requestConfirmation);
166219

167220
writer.WritePropertyName("recipientUserIds");
168221
writer.WriteStartArray();

0 commit comments

Comments
 (0)