From 6cea7b2aff2507d5a83c2c24ec4fd89b8f32ff1d Mon Sep 17 00:00:00 2001 From: jleung Date: Sun, 26 Dec 2021 22:45:44 -0800 Subject: [PATCH] Add project files. --- TwilioSMSReceiver.sln | 25 ++++ .../Controllers/MSTeamsWebHooksController.cs | 117 ++++++++++++++++++ .../Controllers/SMSReceiverController.cs | 91 ++++++++++++++ TwilioSMSReceiver/Interfaces/BaseHandler.cs | 36 ++++++ .../Interfaces/IMessageHandler.cs | 9 ++ .../Interfaces/MSTeamsHandler.cs | 51 ++++++++ TwilioSMSReceiver/Interfaces/SMTPHandler.cs | 17 +++ ...0211227010718_InitialMigration.Designer.cs | 52 ++++++++ .../20211227010718_InitialMigration.cs | 36 ++++++ .../20211227015928_AddMMSData.Designer.cs | 85 +++++++++++++ .../Migrations/20211227015928_AddMMSData.cs | 53 ++++++++ ...227022011_AddIsBroadcastedFlag.Designer.cs | 87 +++++++++++++ .../20211227022011_AddIsBroadcastedFlag.cs | 44 +++++++ .../20211227034115_AddMSTeams.Designer.cs | 101 +++++++++++++++ .../Migrations/20211227034115_AddMSTeams.cs | 91 ++++++++++++++ .../Migrations/SMSDbCtxModelSnapshot.cs | 99 +++++++++++++++ TwilioSMSReceiver/Models/SMSModel.cs | 36 ++++++ TwilioSMSReceiver/Program.cs | 36 ++++++ .../Properties/launchSettings.json | 31 +++++ TwilioSMSReceiver/SMSDbCtx.cs | 16 +++ TwilioSMSReceiver/TwilioSMSReceiver.csproj | 27 ++++ TwilioSMSReceiver/WeatherForecast.cs | 13 ++ .../appsettings.Development.json | 8 ++ TwilioSMSReceiver/appsettings.json | 12 ++ 24 files changed, 1173 insertions(+) create mode 100644 TwilioSMSReceiver.sln create mode 100644 TwilioSMSReceiver/Controllers/MSTeamsWebHooksController.cs create mode 100644 TwilioSMSReceiver/Controllers/SMSReceiverController.cs create mode 100644 TwilioSMSReceiver/Interfaces/BaseHandler.cs create mode 100644 TwilioSMSReceiver/Interfaces/IMessageHandler.cs create mode 100644 TwilioSMSReceiver/Interfaces/MSTeamsHandler.cs create mode 100644 TwilioSMSReceiver/Interfaces/SMTPHandler.cs create mode 100644 TwilioSMSReceiver/Migrations/20211227010718_InitialMigration.Designer.cs create mode 100644 TwilioSMSReceiver/Migrations/20211227010718_InitialMigration.cs create mode 100644 TwilioSMSReceiver/Migrations/20211227015928_AddMMSData.Designer.cs create mode 100644 TwilioSMSReceiver/Migrations/20211227015928_AddMMSData.cs create mode 100644 TwilioSMSReceiver/Migrations/20211227022011_AddIsBroadcastedFlag.Designer.cs create mode 100644 TwilioSMSReceiver/Migrations/20211227022011_AddIsBroadcastedFlag.cs create mode 100644 TwilioSMSReceiver/Migrations/20211227034115_AddMSTeams.Designer.cs create mode 100644 TwilioSMSReceiver/Migrations/20211227034115_AddMSTeams.cs create mode 100644 TwilioSMSReceiver/Migrations/SMSDbCtxModelSnapshot.cs create mode 100644 TwilioSMSReceiver/Models/SMSModel.cs create mode 100644 TwilioSMSReceiver/Program.cs create mode 100644 TwilioSMSReceiver/Properties/launchSettings.json create mode 100644 TwilioSMSReceiver/SMSDbCtx.cs create mode 100644 TwilioSMSReceiver/TwilioSMSReceiver.csproj create mode 100644 TwilioSMSReceiver/WeatherForecast.cs create mode 100644 TwilioSMSReceiver/appsettings.Development.json create mode 100644 TwilioSMSReceiver/appsettings.json diff --git a/TwilioSMSReceiver.sln b/TwilioSMSReceiver.sln new file mode 100644 index 0000000..1675481 --- /dev/null +++ b/TwilioSMSReceiver.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31912.275 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwilioSMSReceiver", "TwilioSMSReceiver\TwilioSMSReceiver.csproj", "{223C45EA-FAAC-44B8-B7DF-5DAA257CB52E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {223C45EA-FAAC-44B8-B7DF-5DAA257CB52E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {223C45EA-FAAC-44B8-B7DF-5DAA257CB52E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {223C45EA-FAAC-44B8-B7DF-5DAA257CB52E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {223C45EA-FAAC-44B8-B7DF-5DAA257CB52E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D5214D99-4465-4695-A647-C41517BC8E9D} + EndGlobalSection +EndGlobal diff --git a/TwilioSMSReceiver/Controllers/MSTeamsWebHooksController.cs b/TwilioSMSReceiver/Controllers/MSTeamsWebHooksController.cs new file mode 100644 index 0000000..44a6674 --- /dev/null +++ b/TwilioSMSReceiver/Controllers/MSTeamsWebHooksController.cs @@ -0,0 +1,117 @@ +#nullable disable +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using TwilioSMSReceiver; +using TwilioSMSReceiver.Models; + +namespace TwilioSMSReceiver.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class MSTeamsWebHooksController : ControllerBase + { + private readonly SMSDbCtx _context; + + public MSTeamsWebHooksController(SMSDbCtx context, IWebHostEnvironment environment) + { + _context = context; + if (!environment.IsDevelopment()) + { + throw new InvalidOperationException("Not supported in production mode"); + } + } + + // GET: api/MSTeamsWebHooks + [HttpGet] + public async Task>> GetMSTeamsWebHooks() + { + return await _context.MSTeamsWebHooks.ToListAsync(); + } + + // GET: api/MSTeamsWebHooks/5 + [HttpGet("{id}")] + public async Task> GetMSTeamsWebHook(int id) + { + var mSTeamsWebHook = await _context.MSTeamsWebHooks.FindAsync(id); + + if (mSTeamsWebHook == null) + { + return NotFound(); + } + + return mSTeamsWebHook; + } + + // PUT: api/MSTeamsWebHooks/5 + // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 + [HttpPut("{id}")] + public async Task PutMSTeamsWebHook(int id, MSTeamsWebHook mSTeamsWebHook) + { + if (id != mSTeamsWebHook.Id) + { + return BadRequest(); + } + + _context.Entry(mSTeamsWebHook).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!MSTeamsWebHookExists(id)) + { + return NotFound(); + } + else + { + throw; + } + } + + return NoContent(); + } + + // POST: api/MSTeamsWebHooks + // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 + [HttpPost] + public async Task> PostMSTeamsWebHook([FromForm]string teamsHookUrl) + { + var mSTeamsWebHook = new MSTeamsWebHook + { + WebHookUri = teamsHookUrl + }; + _context.MSTeamsWebHooks.Add(mSTeamsWebHook); + await _context.SaveChangesAsync(); + + return CreatedAtAction("GetMSTeamsWebHook", new { id = mSTeamsWebHook.Id }, mSTeamsWebHook); + } + + // DELETE: api/MSTeamsWebHooks/5 + [HttpDelete("{id}")] + public async Task DeleteMSTeamsWebHook(int id) + { + var mSTeamsWebHook = await _context.MSTeamsWebHooks.FindAsync(id); + if (mSTeamsWebHook == null) + { + return NotFound(); + } + + _context.MSTeamsWebHooks.Remove(mSTeamsWebHook); + await _context.SaveChangesAsync(); + + return NoContent(); + } + + private bool MSTeamsWebHookExists(int id) + { + return _context.MSTeamsWebHooks.Any(e => e.Id == id); + } + } +} diff --git a/TwilioSMSReceiver/Controllers/SMSReceiverController.cs b/TwilioSMSReceiver/Controllers/SMSReceiverController.cs new file mode 100644 index 0000000..ffd8b81 --- /dev/null +++ b/TwilioSMSReceiver/Controllers/SMSReceiverController.cs @@ -0,0 +1,91 @@ +#nullable disable +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Twilio.AspNet.Common; +using TwilioSMSReceiver; +using TwilioSMSReceiver.Interfaces; +using TwilioSMSReceiver.Models; + +namespace TwilioSMSReceiver.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class SMSReceiverController : ControllerBase + { + private readonly SMSDbCtx _context; + private readonly IEnumerable _messageHandlers; + public SMSReceiverController(SMSDbCtx context, IEnumerable messageHandlers) + { + _context = context; + _messageHandlers = messageHandlers; + } + + // GET: api/SMSReceiver + [HttpGet] + public async Task>> GetSMSMessages() + { + return await _context.SMSMessages.Include(b => b.MMSContent).ToListAsync(); + } + + // GET: api/SMSReceiver/5 + [HttpGet("{id}")] + public async Task> GetSMSModel(int id) + { + var sMSModel = await _context.SMSMessages.FindAsync(id); + + if (sMSModel == null) + { + return NotFound(); + } + + return sMSModel; + } + // POST: api/SMSReceiver + // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 + [HttpPost] + public async Task> PostSMSModel([FromForm]SmsRequest smsRequest, [FromForm] int? numMedia) + { + var mmsItems = new List(); + var message = new SMSModel + { + MessageContents = smsRequest.Body, + SenderNumber = smsRequest.From, + ReceivedNumber = smsRequest.To, + TimeReceived = DateTime.UtcNow + }; + + if (numMedia != null) + { + for (var i = 0; i < numMedia; i++) + { + var uri = Request.Form[$"MediaUrl{i}"]; + + mmsItems.Add(new MMSModel { OriginalMMSData = uri }); + } + + message.MMSContent = mmsItems; + } + + _context.SMSMessages.Add(message); + await _context.SaveChangesAsync(); + + List _HandleAllMessages = new List(); + + foreach (var handler in _messageHandlers) + { + _HandleAllMessages.Add(handler.RelaySms(message)); + } + return Ok(); + } + + private bool SMSModelExists(int id) + { + return _context.SMSMessages.Any(e => e.Id == id); + } + } +} diff --git a/TwilioSMSReceiver/Interfaces/BaseHandler.cs b/TwilioSMSReceiver/Interfaces/BaseHandler.cs new file mode 100644 index 0000000..db50aa0 --- /dev/null +++ b/TwilioSMSReceiver/Interfaces/BaseHandler.cs @@ -0,0 +1,36 @@ +#nullable disable +using TwilioSMSReceiver.Models; + +namespace TwilioSMSReceiver.Interfaces +{ + public abstract class BaseHandler : IMessageHandler + { + protected readonly SMSDbCtx sMSDbCtx; + protected readonly ILogger _logger; + protected readonly IServiceProvider _serviceProvider; + + public BaseHandler(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + sMSDbCtx = _serviceProvider.CreateScope().ServiceProvider.GetService(); + _logger = _serviceProvider.CreateScope().ServiceProvider.GetService>(); + } + public virtual async Task RelaySms(SMSModel model) + { + if (sMSDbCtx.SMSMessages.Any(b => b.Id == model.Id)) + { + var message = + sMSDbCtx.SMSMessages.Where(b => b.Id == model.Id).First(); + if (!message.IsForwardedYet) + { + _logger.LogInformation($"Marking message with id {message.Id} as forwarded"); + message.IsForwardedYet = true; + sMSDbCtx.SMSMessages.Update(message); + await sMSDbCtx.SaveChangesAsync(); + return true; + } + } + return false; + } + } +} diff --git a/TwilioSMSReceiver/Interfaces/IMessageHandler.cs b/TwilioSMSReceiver/Interfaces/IMessageHandler.cs new file mode 100644 index 0000000..9651935 --- /dev/null +++ b/TwilioSMSReceiver/Interfaces/IMessageHandler.cs @@ -0,0 +1,9 @@ +using TwilioSMSReceiver.Models; + +namespace TwilioSMSReceiver.Interfaces +{ + public interface IMessageHandler + { + public Task RelaySms(SMSModel model); + } +} diff --git a/TwilioSMSReceiver/Interfaces/MSTeamsHandler.cs b/TwilioSMSReceiver/Interfaces/MSTeamsHandler.cs new file mode 100644 index 0000000..a7e38a8 --- /dev/null +++ b/TwilioSMSReceiver/Interfaces/MSTeamsHandler.cs @@ -0,0 +1,51 @@ +using TwilioSMSReceiver.Models; +using TeamsHook.NET; + +namespace TwilioSMSReceiver.Interfaces +{ + public class MSTeamsHandler : BaseHandler + { + public MSTeamsHandler(IServiceProvider serviceProvider) : base(serviceProvider) + { + } + + public override async Task RelaySms(SMSModel model) + { + var teams = sMSDbCtx.MSTeamsWebHooks; + if (!teams.Any()) + { + _logger.LogWarning("Teams Webhook list is empty!"); + return false; + } + List teamsPostRequests = new List(); + foreach (var teamHook in teams) + { + try + { + var teamsClient = new TeamsHookClient(); + var card = new MessageCard + { + Title = $"Incoming SMS from {model.SenderNumber}", + Summary = $"Sent to {model.ReceivedNumber}", + Text = $"{model.MessageContents}" + }; + + teamsPostRequests.Add(teamsClient.PostAsync(teamHook.WebHookUri, card)); + } catch (Exception ex) + { + _logger.LogError($"Webhook with URL {teamHook.WebHookUri} failed to post. Exception here {ex}"); + } + } + + try + { + await Task.WhenAll(teamsPostRequests); + } catch (Exception ex) + { + _logger.LogError($"Webhook failure {ex}"); + } + + return await base.RelaySms(model); + } + } +} diff --git a/TwilioSMSReceiver/Interfaces/SMTPHandler.cs b/TwilioSMSReceiver/Interfaces/SMTPHandler.cs new file mode 100644 index 0000000..dbb2542 --- /dev/null +++ b/TwilioSMSReceiver/Interfaces/SMTPHandler.cs @@ -0,0 +1,17 @@ +using TwilioSMSReceiver.Models; + +namespace TwilioSMSReceiver.Interfaces +{ + public class SMTPHandler : BaseHandler + { + public SMTPHandler(IServiceProvider serviceProvider) : base(serviceProvider) + { + } + + public override Task RelaySms(SMSModel model) + { + _logger.LogWarning("SMTP isn't implemented yet"); + return Task.FromResult(false); + } + } +} diff --git a/TwilioSMSReceiver/Migrations/20211227010718_InitialMigration.Designer.cs b/TwilioSMSReceiver/Migrations/20211227010718_InitialMigration.Designer.cs new file mode 100644 index 0000000..497e4f4 --- /dev/null +++ b/TwilioSMSReceiver/Migrations/20211227010718_InitialMigration.Designer.cs @@ -0,0 +1,52 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TwilioSMSReceiver; + +#nullable disable + +namespace TwilioSMSReceiver.Migrations +{ + [DbContext(typeof(SMSDbCtx))] + [Migration("20211227010718_InitialMigration")] + partial class InitialMigration + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.1"); + + modelBuilder.Entity("TwilioSMSReceiver.Models.SMSModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("MMSContentPath") + .HasColumnType("TEXT"); + + b.Property("MessageContents") + .HasColumnType("TEXT"); + + b.Property("ReceivedNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SenderNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TimeReceived") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SMSMessages"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TwilioSMSReceiver/Migrations/20211227010718_InitialMigration.cs b/TwilioSMSReceiver/Migrations/20211227010718_InitialMigration.cs new file mode 100644 index 0000000..08d718d --- /dev/null +++ b/TwilioSMSReceiver/Migrations/20211227010718_InitialMigration.cs @@ -0,0 +1,36 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TwilioSMSReceiver.Migrations +{ + public partial class InitialMigration : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "SMSMessages", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ReceivedNumber = table.Column(type: "TEXT", nullable: false), + SenderNumber = table.Column(type: "TEXT", nullable: false), + TimeReceived = table.Column(type: "TEXT", nullable: false), + MessageContents = table.Column(type: "TEXT", nullable: true), + MMSContentPath = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_SMSMessages", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "SMSMessages"); + } + } +} diff --git a/TwilioSMSReceiver/Migrations/20211227015928_AddMMSData.Designer.cs b/TwilioSMSReceiver/Migrations/20211227015928_AddMMSData.Designer.cs new file mode 100644 index 0000000..337cf84 --- /dev/null +++ b/TwilioSMSReceiver/Migrations/20211227015928_AddMMSData.Designer.cs @@ -0,0 +1,85 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TwilioSMSReceiver; + +#nullable disable + +namespace TwilioSMSReceiver.Migrations +{ + [DbContext(typeof(SMSDbCtx))] + [Migration("20211227015928_AddMMSData")] + partial class AddMMSData + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.1"); + + modelBuilder.Entity("TwilioSMSReceiver.Models.MMSModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("OriginalMMSData") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SMSModelId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SMSModelId"); + + b.ToTable("MMSModel"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.SMSModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("MessageContents") + .HasColumnType("TEXT"); + + b.Property("ReceivedNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SenderNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TimeReceived") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SMSMessages"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.MMSModel", b => + { + b.HasOne("TwilioSMSReceiver.Models.SMSModel", "ParentSMSMessage") + .WithMany("MMSContent") + .HasForeignKey("SMSModelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ParentSMSMessage"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.SMSModel", b => + { + b.Navigation("MMSContent"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TwilioSMSReceiver/Migrations/20211227015928_AddMMSData.cs b/TwilioSMSReceiver/Migrations/20211227015928_AddMMSData.cs new file mode 100644 index 0000000..c9ea355 --- /dev/null +++ b/TwilioSMSReceiver/Migrations/20211227015928_AddMMSData.cs @@ -0,0 +1,53 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TwilioSMSReceiver.Migrations +{ + public partial class AddMMSData : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "MMSContentPath", + table: "SMSMessages"); + + migrationBuilder.CreateTable( + name: "MMSModel", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + SMSModelId = table.Column(type: "INTEGER", nullable: false), + OriginalMMSData = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_MMSModel", x => x.Id); + table.ForeignKey( + name: "FK_MMSModel_SMSMessages_SMSModelId", + column: x => x.SMSModelId, + principalTable: "SMSMessages", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_MMSModel_SMSModelId", + table: "MMSModel", + column: "SMSModelId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "MMSModel"); + + migrationBuilder.AddColumn( + name: "MMSContentPath", + table: "SMSMessages", + type: "TEXT", + nullable: true); + } + } +} diff --git a/TwilioSMSReceiver/Migrations/20211227022011_AddIsBroadcastedFlag.Designer.cs b/TwilioSMSReceiver/Migrations/20211227022011_AddIsBroadcastedFlag.Designer.cs new file mode 100644 index 0000000..bc5b656 --- /dev/null +++ b/TwilioSMSReceiver/Migrations/20211227022011_AddIsBroadcastedFlag.Designer.cs @@ -0,0 +1,87 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TwilioSMSReceiver; + +#nullable disable + +namespace TwilioSMSReceiver.Migrations +{ + [DbContext(typeof(SMSDbCtx))] + [Migration("20211227022011_AddIsBroadcastedFlag")] + partial class AddIsBroadcastedFlag + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.1"); + + modelBuilder.Entity("TwilioSMSReceiver.Models.MMSModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("OriginalMMSData") + .HasColumnType("TEXT"); + + b.Property("SMSModelId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SMSModelId"); + + b.ToTable("MMSModel"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.SMSModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("IsForwardedYet") + .HasColumnType("INTEGER"); + + b.Property("MessageContents") + .HasColumnType("TEXT"); + + b.Property("ReceivedNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SenderNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TimeReceived") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SMSMessages"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.MMSModel", b => + { + b.HasOne("TwilioSMSReceiver.Models.SMSModel", "ParentSMSMessage") + .WithMany("MMSContent") + .HasForeignKey("SMSModelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ParentSMSMessage"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.SMSModel", b => + { + b.Navigation("MMSContent"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TwilioSMSReceiver/Migrations/20211227022011_AddIsBroadcastedFlag.cs b/TwilioSMSReceiver/Migrations/20211227022011_AddIsBroadcastedFlag.cs new file mode 100644 index 0000000..53ef876 --- /dev/null +++ b/TwilioSMSReceiver/Migrations/20211227022011_AddIsBroadcastedFlag.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TwilioSMSReceiver.Migrations +{ + public partial class AddIsBroadcastedFlag : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsForwardedYet", + table: "SMSMessages", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AlterColumn( + name: "OriginalMMSData", + table: "MMSModel", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsForwardedYet", + table: "SMSMessages"); + + migrationBuilder.AlterColumn( + name: "OriginalMMSData", + table: "MMSModel", + type: "TEXT", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + } + } +} diff --git a/TwilioSMSReceiver/Migrations/20211227034115_AddMSTeams.Designer.cs b/TwilioSMSReceiver/Migrations/20211227034115_AddMSTeams.Designer.cs new file mode 100644 index 0000000..1e7c01b --- /dev/null +++ b/TwilioSMSReceiver/Migrations/20211227034115_AddMSTeams.Designer.cs @@ -0,0 +1,101 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TwilioSMSReceiver; + +#nullable disable + +namespace TwilioSMSReceiver.Migrations +{ + [DbContext(typeof(SMSDbCtx))] + [Migration("20211227034115_AddMSTeams")] + partial class AddMSTeams + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.1"); + + modelBuilder.Entity("TwilioSMSReceiver.Models.MMSModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("OriginalMMSData") + .HasColumnType("TEXT"); + + b.Property("SMSModelId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SMSModelId"); + + b.ToTable("MMSMessages"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.MSTeamsWebHook", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("WebHookUri") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("MSTeamsWebHooks"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.SMSModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("IsForwardedYet") + .HasColumnType("INTEGER"); + + b.Property("MessageContents") + .HasColumnType("TEXT"); + + b.Property("ReceivedNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SenderNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TimeReceived") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SMSMessages"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.MMSModel", b => + { + b.HasOne("TwilioSMSReceiver.Models.SMSModel", "ParentSMSMessage") + .WithMany("MMSContent") + .HasForeignKey("SMSModelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ParentSMSMessage"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.SMSModel", b => + { + b.Navigation("MMSContent"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TwilioSMSReceiver/Migrations/20211227034115_AddMSTeams.cs b/TwilioSMSReceiver/Migrations/20211227034115_AddMSTeams.cs new file mode 100644 index 0000000..6a6eab1 --- /dev/null +++ b/TwilioSMSReceiver/Migrations/20211227034115_AddMSTeams.cs @@ -0,0 +1,91 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TwilioSMSReceiver.Migrations +{ + public partial class AddMSTeams : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_MMSModel_SMSMessages_SMSModelId", + table: "MMSModel"); + + migrationBuilder.DropPrimaryKey( + name: "PK_MMSModel", + table: "MMSModel"); + + migrationBuilder.RenameTable( + name: "MMSModel", + newName: "MMSMessages"); + + migrationBuilder.RenameIndex( + name: "IX_MMSModel_SMSModelId", + table: "MMSMessages", + newName: "IX_MMSMessages_SMSModelId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_MMSMessages", + table: "MMSMessages", + column: "Id"); + + migrationBuilder.CreateTable( + name: "MSTeamsWebHooks", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + WebHookUri = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_MSTeamsWebHooks", x => x.Id); + }); + + migrationBuilder.AddForeignKey( + name: "FK_MMSMessages_SMSMessages_SMSModelId", + table: "MMSMessages", + column: "SMSModelId", + principalTable: "SMSMessages", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_MMSMessages_SMSMessages_SMSModelId", + table: "MMSMessages"); + + migrationBuilder.DropTable( + name: "MSTeamsWebHooks"); + + migrationBuilder.DropPrimaryKey( + name: "PK_MMSMessages", + table: "MMSMessages"); + + migrationBuilder.RenameTable( + name: "MMSMessages", + newName: "MMSModel"); + + migrationBuilder.RenameIndex( + name: "IX_MMSMessages_SMSModelId", + table: "MMSModel", + newName: "IX_MMSModel_SMSModelId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_MMSModel", + table: "MMSModel", + column: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_MMSModel_SMSMessages_SMSModelId", + table: "MMSModel", + column: "SMSModelId", + principalTable: "SMSMessages", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/TwilioSMSReceiver/Migrations/SMSDbCtxModelSnapshot.cs b/TwilioSMSReceiver/Migrations/SMSDbCtxModelSnapshot.cs new file mode 100644 index 0000000..244ae07 --- /dev/null +++ b/TwilioSMSReceiver/Migrations/SMSDbCtxModelSnapshot.cs @@ -0,0 +1,99 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TwilioSMSReceiver; + +#nullable disable + +namespace TwilioSMSReceiver.Migrations +{ + [DbContext(typeof(SMSDbCtx))] + partial class SMSDbCtxModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.1"); + + modelBuilder.Entity("TwilioSMSReceiver.Models.MMSModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("OriginalMMSData") + .HasColumnType("TEXT"); + + b.Property("SMSModelId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SMSModelId"); + + b.ToTable("MMSMessages"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.MSTeamsWebHook", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("WebHookUri") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("MSTeamsWebHooks"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.SMSModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("IsForwardedYet") + .HasColumnType("INTEGER"); + + b.Property("MessageContents") + .HasColumnType("TEXT"); + + b.Property("ReceivedNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SenderNumber") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TimeReceived") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SMSMessages"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.MMSModel", b => + { + b.HasOne("TwilioSMSReceiver.Models.SMSModel", "ParentSMSMessage") + .WithMany("MMSContent") + .HasForeignKey("SMSModelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ParentSMSMessage"); + }); + + modelBuilder.Entity("TwilioSMSReceiver.Models.SMSModel", b => + { + b.Navigation("MMSContent"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TwilioSMSReceiver/Models/SMSModel.cs b/TwilioSMSReceiver/Models/SMSModel.cs new file mode 100644 index 0000000..c28b07f --- /dev/null +++ b/TwilioSMSReceiver/Models/SMSModel.cs @@ -0,0 +1,36 @@ +#nullable disable +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; + +namespace TwilioSMSReceiver.Models +{ + public class SMSModel + { + [Key] + public int Id { get; set; } + [Required] + public string ReceivedNumber { get; set; } + + [Required] + public string SenderNumber { get; set; } + public DateTime TimeReceived { get; set; } + public string? MessageContents { get; set; } + public ICollection MMSContent { get; set; } + public bool IsForwardedYet { get; set; } + } + + public class MMSModel + { + [Key] + public int Id { get; set; } + public int SMSModelId { get; set; } + public SMSModel ParentSMSMessage { get; set; } + public string OriginalMMSData { get; set; } + } + + public class MSTeamsWebHook + { + public int Id { get; set; } + public string WebHookUri { get; set; } + } +} diff --git a/TwilioSMSReceiver/Program.cs b/TwilioSMSReceiver/Program.cs new file mode 100644 index 0000000..2136acd --- /dev/null +++ b/TwilioSMSReceiver/Program.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore; +using TwilioSMSReceiver; +using TwilioSMSReceiver.Interfaces; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers().AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +builder.Services.AddDbContext(options => { + options.UseSqlite(builder.Configuration.GetConnectionString("SmsDBCtx")); +}); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddLogging(); +//builder.Services.AddSingleton(); +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/TwilioSMSReceiver/Properties/launchSettings.json b/TwilioSMSReceiver/Properties/launchSettings.json new file mode 100644 index 0000000..603918d --- /dev/null +++ b/TwilioSMSReceiver/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:17821", + "sslPort": 44325 + } + }, + "profiles": { + "TwilioSMSReceiver": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://[::]:7078;http://[::]:5078", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/TwilioSMSReceiver/SMSDbCtx.cs b/TwilioSMSReceiver/SMSDbCtx.cs new file mode 100644 index 0000000..bf722d3 --- /dev/null +++ b/TwilioSMSReceiver/SMSDbCtx.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; +using TwilioSMSReceiver.Models; + +namespace TwilioSMSReceiver +{ + public class SMSDbCtx : DbContext + { + public SMSDbCtx(DbContextOptions options) : base(options) + { + } + + public DbSet SMSMessages { get;set; } + public DbSet MMSMessages { get;set; } + public DbSet MSTeamsWebHooks { get;set; } + } +} diff --git a/TwilioSMSReceiver/TwilioSMSReceiver.csproj b/TwilioSMSReceiver/TwilioSMSReceiver.csproj new file mode 100644 index 0000000..294efa1 --- /dev/null +++ b/TwilioSMSReceiver/TwilioSMSReceiver.csproj @@ -0,0 +1,27 @@ + + + + net6.0 + enable + enable + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/TwilioSMSReceiver/WeatherForecast.cs b/TwilioSMSReceiver/WeatherForecast.cs new file mode 100644 index 0000000..906108a --- /dev/null +++ b/TwilioSMSReceiver/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace TwilioSMSReceiver +{ + public class WeatherForecast + { + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} \ No newline at end of file diff --git a/TwilioSMSReceiver/appsettings.Development.json b/TwilioSMSReceiver/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/TwilioSMSReceiver/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/TwilioSMSReceiver/appsettings.json b/TwilioSMSReceiver/appsettings.json new file mode 100644 index 0000000..840ab2b --- /dev/null +++ b/TwilioSMSReceiver/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "ConnectionStrings": { + "SmsDbCtx": "Data Source=smsdbctx.sqlite" + }, + "AllowedHosts": "*" +}