Skip to content

Commit 7ff129a

Browse files
committed
WIP
1 parent cdc81b4 commit 7ff129a

File tree

10 files changed

+240
-63
lines changed

10 files changed

+240
-63
lines changed

Build

SailthruSDK.sln

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".config", ".config", "{DEA9
3737
EndProject
3838
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libs", "libs", "{3E233261-9EBB-4F79-B840-BD73052C8428}"
3939
EndProject
40-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SailthruSDK", "libs\SailthruSDK\SailthruSDK.csproj", "{562C63D3-F1F8-4929-B856-1463283DFC93}"
40+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SailthruSDK", "libs\SailthruSDK\SailthruSDK.csproj", "{562C63D3-F1F8-4929-B856-1463283DFC93}"
4141
EndProject
4242
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "repo", "repo", "{D4D1448C-41ED-4E4C-B967-7D26421DEC43}"
4343
ProjectSection(SolutionItems) = preProject
@@ -53,7 +53,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "repo", "repo", "{D4D1448C-4
5353
EndProject
5454
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{89340FB5-E457-4182-A510-7F1D8DD97371}"
5555
EndProject
56-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SailthruSDK.Tests", "tests\SailthruSDK.Tests\SailthruSDK.Tests.csproj", "{2E0DE426-D135-4710-80B5-173338D364C6}"
56+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SailthruSDK.Tests", "tests\SailthruSDK.Tests\SailthruSDK.Tests.csproj", "{2E0DE426-D135-4710-80B5-173338D364C6}"
57+
EndProject
58+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SailthruSDK.Extensions.DependencyInjection", "libs\SailthruSDK.Extensions.DependencyInjection\SailthruSDK.Extensions.DependencyInjection.csproj", "{806DCE4B-D0BD-4AA5-B8BC-502B69ABFAF3}"
5759
EndProject
5860
Global
5961
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -77,6 +79,10 @@ Global
7779
{2E0DE426-D135-4710-80B5-173338D364C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
7880
{2E0DE426-D135-4710-80B5-173338D364C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
7981
{2E0DE426-D135-4710-80B5-173338D364C6}.Release|Any CPU.Build.0 = Release|Any CPU
82+
{806DCE4B-D0BD-4AA5-B8BC-502B69ABFAF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
83+
{806DCE4B-D0BD-4AA5-B8BC-502B69ABFAF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
84+
{806DCE4B-D0BD-4AA5-B8BC-502B69ABFAF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
85+
{806DCE4B-D0BD-4AA5-B8BC-502B69ABFAF3}.Release|Any CPU.Build.0 = Release|Any CPU
8086
EndGlobalSection
8187
GlobalSection(SolutionProperties) = preSolution
8288
HideSolutionNode = FALSE
@@ -88,6 +94,7 @@ Global
8894
{DEA98DC1-8E8C-4024-8D6D-3ADDA19B64BF} = {82F51994-2872-4E64-A51F-5785E6E01840}
8995
{562C63D3-F1F8-4929-B856-1463283DFC93} = {3E233261-9EBB-4F79-B840-BD73052C8428}
9096
{2E0DE426-D135-4710-80B5-173338D364C6} = {89340FB5-E457-4182-A510-7F1D8DD97371}
97+
{806DCE4B-D0BD-4AA5-B8BC-502B69ABFAF3} = {3E233261-9EBB-4F79-B840-BD73052C8428}
9198
EndGlobalSection
9299
GlobalSection(ExtensibilityGlobals) = postSolution
93100
SolutionGuid = {B7D62062-4558-4545-9EE0-3A9B24CFD70D}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="FluentValidation" />
9+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
10+
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
11+
<PackageReference Include="Microsoft.Extensions.Options" />
12+
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
13+
<PackageReference Include="Microsoft.Extensions.Http" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\SailthruSDK\SailthruSDK.csproj" />
18+
</ItemGroup>
19+
20+
</Project>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
namespace Microsoft.Extensions.DependencyInjection
2+
{
3+
using System;
4+
using System.Net.Http;
5+
using System.Net.Http.Headers;
6+
7+
using FluentValidation;
8+
9+
using Microsoft.Extensions.Configuration;
10+
using Microsoft.Extensions.Options;
11+
12+
using SailthruSDK;
13+
14+
/// <summary>
15+
/// Provides extensions for the <see cref="IServiceCollection"/>
16+
/// </summary>
17+
public static class ServiceCollectionExtensions
18+
{
19+
/// <summary>
20+
/// Adds Sailthru services to the given services collection.
21+
/// </summary>
22+
/// <param name="services">The services collection.</param>
23+
/// <param name="configure">The configure delegate.</param>
24+
/// <returns>The services collection.</returns>
25+
public static IServiceCollection AddSailthru(
26+
IServiceCollection services,
27+
Action<SailthruSettings> configure)
28+
{
29+
Ensure.IsNotNull(services, nameof(services));
30+
Ensure.IsNotNull(configure, nameof(configure));
31+
32+
services.Configure(configure);
33+
34+
AddCoreServices(services);
35+
36+
return services;
37+
}
38+
39+
/// <summary>
40+
/// Adds Sailthru services to the given services collection.
41+
/// </summary>
42+
/// <param name="services">The services collection.</param>
43+
/// <param name="settings">The Sailthru settings.</param>
44+
/// <returns>The services collection.</returns>
45+
public static IServiceCollection AddSailthru(
46+
IServiceCollection services,
47+
SailthruSettings settings)
48+
{
49+
Ensure.IsNotNull(services, nameof(services));
50+
Ensure.IsNotNull(settings, nameof(settings));
51+
52+
services.AddSingleton(Options.Create(settings));
53+
54+
AddCoreServices(services);
55+
56+
return services;
57+
}
58+
59+
/// <summary>
60+
/// Adds Sailthru services to the given services collection.
61+
/// </summary>
62+
/// <param name="services">The services collection.</param>
63+
/// <param name="configurationSection">The configuration section.</param>
64+
/// <returns>The services collection.</returns>
65+
public static IServiceCollection AddSailthru(
66+
IServiceCollection services,
67+
IConfigurationSection configurationSection)
68+
{
69+
Ensure.IsNotNull(services, nameof(services));
70+
Ensure.IsNotNull(configurationSection, nameof(configurationSection));
71+
72+
services.Configure<SailthruSettings>(configurationSection);
73+
74+
AddCoreServices(services);
75+
76+
return services;
77+
}
78+
79+
static void AddCoreServices(IServiceCollection services)
80+
{
81+
services.AddHttpClient<SailthruClient>(
82+
"Sailthru",
83+
(sp, http) => ConfigureHttpClient(sp, http));
84+
}
85+
86+
static void ConfigureHttpClient(IServiceProvider services, HttpClient http)
87+
{
88+
var settings = services.GetRequiredService<IOptions<SailthruSettings>>().Value;
89+
SailthruSettingsValidator.Instance.ValidateAndThrow(settings);
90+
91+
http.BaseAddress = new Uri(settings.BaseUrl);
92+
http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
93+
}
94+
}
95+
}

libs/SailthruSDK/Models/SailthruUser.cs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,55 @@
11
namespace SailthruSDK
22
{
3+
using System;
34
using System.Net.Http;
45
using System.Threading;
56
using System.Threading.Tasks;
67

8+
/// <summary>
9+
/// Represents a Sailthru user.
10+
/// </summary>
711
public class SailthruUser
812
{
13+
/// <summary>
14+
/// Gets recent user activity.
15+
/// </summary>
16+
public SailthruUserActivity? Activity { get; }
17+
}
18+
19+
/// <summary>
20+
/// Represents sailthru user activity.
21+
/// </summary>
22+
public struct SailthruUserActivity
23+
{
24+
/// <summary>
25+
/// The date and time the user's most recent click.
26+
/// </summary>
27+
public DateTimeOffset? ClickTime { get; }
28+
29+
/// <summary>
30+
/// The date and time of the user's profile creation.
31+
/// </summary>
32+
public DateTimeOffset? CreateTime { get; }
33+
34+
/// <summary>
35+
/// The date and time the user's most recent log in.
36+
/// </summary>
37+
public DateTimeOffset? LoginTime { get; }
38+
39+
/// <summary>
40+
/// The date and time the user's most recent email open.
41+
/// </summary>
42+
public DateTimeOffset? OpenTime { get; }
43+
44+
/// <summary>
45+
/// The date and time the user was added to their first list.
46+
/// </summary>
47+
public DateTimeOffset? SignupTime { get; }
948

49+
/// <summary>
50+
/// The date and time the user's most recent view.
51+
/// </summary>
52+
public DateTimeOffset? ViewTime { get; }
1053
}
1154

1255
/// <summary>
@@ -118,8 +161,17 @@ public static class SailthruUserExtensions
118161
SailthruEndpoints.User,
119162
model);
120163

121-
var response = await client.SendAsync(request, cancellationToken)
164+
var response = await client.SendAsync<GetUserRequest, SailthruUser>(
165+
request,
166+
cancellationToken)
122167
.ConfigureAwait(false);
168+
169+
if (response is { IsError: true })
170+
{
171+
return default;
172+
}
173+
174+
return response.Result;
123175
}
124176
}
125177
}

libs/SailthruSDK/SailthruClient.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ public SailthruClient(HttpClient http, IOptions<SailthruSettings> settings)
3535
_settings = Ensure.IsNotNull(settings, nameof(settings)).Value;
3636
}
3737

38-
internal async Task<SailthruResponse> SendAsync<TModel>(SailthruRequest<TModel> request, CancellationToken cancellationToken = default)
39-
where TModel : notnull
38+
internal async Task<SailthruResponse<TResponse>> SendAsync<TRequest, TResponse>(
39+
SailthruRequest<TRequest> request,
40+
CancellationToken cancellationToken = default)
41+
where TRequest : notnull
4042
{
4143
Ensure.IsNotNull(request, nameof(request));
4244

@@ -50,6 +52,13 @@ internal async Task<SailthruResponse> SendAsync<TModel>(SailthruRequest<TModel>
5052

5153
var httpResponse = await _http.SendAsync(httpRequest, cancellationToken)
5254
.ConfigureAwait(false);
55+
56+
if (httpResponse.IsSuccessStatusCode)
57+
{
58+
return SailthruResponse<TResponse>.Success();
59+
}
60+
61+
return SailthruResponse<TResponse>.Error();
5362
}
5463
}
5564
}

libs/SailthruSDK/SailthruRequest.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
/// <summary>
66
/// Represents a Sailthru request.
77
/// </summary>
8-
public class SailthruRequest<TModel>
9-
where TModel : notnull
8+
/// <typeparam name="TRequest">The request type.</typeparam>
9+
public class SailthruRequest<TRequest>
10+
where TRequest : notnull
1011
{
1112
public SailthruRequest(
1213
HttpMethod method,
1314
string endpoint,
14-
TModel model)
15+
TRequest model)
1516
{
1617
Method = method;
1718
Endpoint = Ensure.IsNotNullOrEmpty(endpoint, nameof(endpoint));
@@ -31,6 +32,6 @@ public SailthruRequest(
3132
/// <summary>
3233
/// Gets the model.
3334
/// </summary>
34-
public TModel Model { get; }
35+
public TRequest Model { get; }
3536
}
3637
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
namespace SailthruSDK
2+
{
3+
/// <summary>
4+
/// Represents a Sailthru response.
5+
/// </summary>
6+
/// <typeparam name="TResponse">The response type.</typeparam>
7+
internal class SailthruResponse<TResponse>
8+
{
9+
SailthruResponse(
10+
TResponse? result = default,
11+
bool isError = false)
12+
{
13+
IsError = isError;
14+
Result = result;
15+
}
16+
17+
/// <summary>
18+
/// Gets whether the response was an error.
19+
/// </summary>
20+
public bool IsError { get; }
21+
22+
/// <summary>
23+
/// Gets the Sailthru response result.
24+
/// </summary>
25+
public TResponse? Result { get; }
26+
27+
/// <summary>
28+
/// Creates a success response.
29+
/// </summary>
30+
/// <returns>The Sailthru response.</returns>
31+
public static SailthruResponse<TResponse> Success()
32+
=> new SailthruResponse<TResponse>();
33+
34+
/// <summary>
35+
/// Creates an error response.
36+
/// </summary>
37+
/// <returns>The Sailthru response.</returns>
38+
public static SailthruResponse<TResponse> Error()
39+
=> new SailthruResponse<TResponse>();
40+
}
41+
}
Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<PropertyGroup>
4-
<TargetFramework>netstandard2.0</TargetFramework>
5-
<DisableImplicitNamespaceImports>true</DisableImplicitNamespaceImports>
6-
</PropertyGroup>
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
<DisableImplicitNamespaceImports>true</DisableImplicitNamespaceImports>
6+
</PropertyGroup>
77

88
<ItemGroup>
99
<PackageReference Include="FluentValidation" />
10-
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
11-
<PackageReference Include="Microsoft.Extensions.Options" />
1210
<PackageReference Include="Microsoft.Extensions.Http" />
1311
<PackageReference Include="System.Text.Json" />
1412
</ItemGroup>
1513

16-
</Project>
14+
</Project>

0 commit comments

Comments
 (0)