diff --git a/src/Ombi.Core/Models/UI/WhatsAppNotificationsViewModel.cs b/src/Ombi.Core/Models/UI/TwilioSettingsViewModel.cs similarity index 62% rename from src/Ombi.Core/Models/UI/WhatsAppNotificationsViewModel.cs rename to src/Ombi.Core/Models/UI/TwilioSettingsViewModel.cs index 048ec1dfa..5e19535ad 100644 --- a/src/Ombi.Core/Models/UI/WhatsAppNotificationsViewModel.cs +++ b/src/Ombi.Core/Models/UI/TwilioSettingsViewModel.cs @@ -7,8 +7,14 @@ namespace Ombi.Core.Models.UI /// /// The view model for the notification settings page /// - /// - public class WhatsAppNotificationsViewModel : WhatsAppSettings + /// + public class TwilioSettingsViewModel + { + public int Id { get; set; } + public WhatsAppSettingsViewModel WhatsAppSettings { get; set; } = new WhatsAppSettingsViewModel(); + } + + public class WhatsAppSettingsViewModel : WhatsAppSettings { /// /// Gets or sets the notification templates. diff --git a/src/Ombi.Mapping/Profiles/SettingsProfile.cs b/src/Ombi.Mapping/Profiles/SettingsProfile.cs index f460ce78b..f336db5f9 100644 --- a/src/Ombi.Mapping/Profiles/SettingsProfile.cs +++ b/src/Ombi.Mapping/Profiles/SettingsProfile.cs @@ -20,6 +20,8 @@ namespace Ombi.Mapping.Profiles CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/WhatsAppNotification.cs b/src/Ombi.Notifications/Agents/WhatsAppNotification.cs index 116120e99..860acc8d0 100644 --- a/src/Ombi.Notifications/Agents/WhatsAppNotification.cs +++ b/src/Ombi.Notifications/Agents/WhatsAppNotification.cs @@ -13,9 +13,9 @@ using Ombi.Api.Twilio; namespace Ombi.Notifications.Agents { - public class WhatsAppNotification : BaseNotification + public class WhatsAppNotification : BaseNotification { - public WhatsAppNotification(IWhatsAppApi api, ISettingsService sn, ILogger log, + public WhatsAppNotification(IWhatsAppApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s , IRepository sub, IMusicRequestRepository music, @@ -30,66 +30,66 @@ namespace Ombi.Notifications.Agents private IWhatsAppApi Api { get; } private ILogger Logger { get; } - protected override bool ValidateConfiguration(WhatsAppSettings settings) + protected override bool ValidateConfiguration(TwilioSettings settings) { - if (!settings.Enabled) + if (!settings.WhatsAppSettings?.Enabled ?? false) { return false; } - return !settings.AccountSid.IsNullOrEmpty() && !settings.AuthToken.IsNullOrEmpty() && !settings.From.IsNullOrEmpty(); + return !settings.WhatsAppSettings.AccountSid.IsNullOrEmpty() && !settings.WhatsAppSettings.AuthToken.IsNullOrEmpty() && !settings.WhatsAppSettings.From.IsNullOrEmpty(); } - protected override async Task NewRequest(NotificationOptions model, WhatsAppSettings settings) + protected override async Task NewRequest(NotificationOptions model, TwilioSettings settings) { await Run(model, settings, NotificationType.NewRequest); } - protected override async Task NewIssue(NotificationOptions model, WhatsAppSettings settings) + protected override async Task NewIssue(NotificationOptions model, TwilioSettings settings) { await Run(model, settings, NotificationType.Issue); } - protected override async Task IssueComment(NotificationOptions model, WhatsAppSettings settings) + protected override async Task IssueComment(NotificationOptions model, TwilioSettings settings) { await Run(model, settings, NotificationType.IssueComment); } - protected override async Task IssueResolved(NotificationOptions model, WhatsAppSettings settings) + protected override async Task IssueResolved(NotificationOptions model, TwilioSettings settings) { await Run(model, settings, NotificationType.IssueResolved); } - protected override async Task AddedToRequestQueue(NotificationOptions model, WhatsAppSettings settings) + protected override async Task AddedToRequestQueue(NotificationOptions model, TwilioSettings settings) { await Run(model, settings, NotificationType.ItemAddedToFaultQueue); } - protected override async Task RequestDeclined(NotificationOptions model, WhatsAppSettings settings) + protected override async Task RequestDeclined(NotificationOptions model, TwilioSettings settings) { await Run(model, settings, NotificationType.RequestDeclined); } - protected override async Task RequestApproved(NotificationOptions model, WhatsAppSettings settings) + protected override async Task RequestApproved(NotificationOptions model, TwilioSettings settings) { await Run(model, settings, NotificationType.RequestApproved); } - protected override async Task AvailableRequest(NotificationOptions model, WhatsAppSettings settings) + protected override async Task AvailableRequest(NotificationOptions model, TwilioSettings settings) { await Run(model, settings, NotificationType.RequestAvailable); } - protected override async Task Send(NotificationMessage model, WhatsAppSettings settings) + protected override async Task Send(NotificationMessage model, TwilioSettings settings) { try { var whatsApp = new WhatsAppModel { Message = model.Message, - From = settings.From, + From = settings.WhatsAppSettings.From, To = ""// TODO }; - await Api.SendMessage(whatsApp, settings.AccountSid, settings.AuthToken); + await Api.SendMessage(whatsApp, settings.WhatsAppSettings.AccountSid, settings.WhatsAppSettings.AuthToken); } catch (Exception e) { @@ -97,7 +97,7 @@ namespace Ombi.Notifications.Agents } } - protected override async Task Test(NotificationOptions model, WhatsAppSettings settings) + protected override async Task Test(NotificationOptions model, TwilioSettings settings) { var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!"; var notification = new NotificationMessage @@ -107,7 +107,7 @@ namespace Ombi.Notifications.Agents await Send(notification, settings); } - private async Task Run(NotificationOptions model, WhatsAppSettings settings, NotificationType type) + private async Task Run(NotificationOptions model, TwilioSettings settings, NotificationType type) { var parsed = await LoadTemplate(NotificationAgent.WhatsApp, type, model); if (parsed.Disabled) diff --git a/src/Ombi.Settings/Settings/Models/Notifications/WhatsAppSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/TwilioSettings.cs similarity index 61% rename from src/Ombi.Settings/Settings/Models/Notifications/WhatsAppSettings.cs rename to src/Ombi.Settings/Settings/Models/Notifications/TwilioSettings.cs index caa862c41..d4b0d69ba 100644 --- a/src/Ombi.Settings/Settings/Models/Notifications/WhatsAppSettings.cs +++ b/src/Ombi.Settings/Settings/Models/Notifications/TwilioSettings.cs @@ -1,10 +1,15 @@ namespace Ombi.Settings.Settings.Models.Notifications { - public class WhatsAppSettings : Settings + public class TwilioSettings : Settings + { + public WhatsAppSettings WhatsAppSettings { get; set; } + } + + public class WhatsAppSettings { public bool Enabled { get; set; } + public string From { get; set; } public string AccountSid { get; set; } public string AuthToken { get; set; } - public string From { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts index 5472a6c7c..a6c14ae3b 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts @@ -27,11 +27,16 @@ export interface INotificationTemplates { } export enum NotificationAgent { - Email, - Discord, - Pushbullet, - Pushover, - Telegram, + Email = 0, + Discord = 1, + Pushbullet = 2, + Pushover = 3, + Telegram = 4, + Slack = 5, + Mattermost = 6, + Mobile = 7, + Gotify = 8, + WhatsApp = 9 } export enum NotificationType { @@ -47,6 +52,7 @@ export enum NotificationType { IssueResolved = 9, IssueComment = 10, Newsletter = 11, + WhatsApp = 12, } export interface IDiscordNotifcationSettings extends INotificationSettings { @@ -85,6 +91,18 @@ export interface IPushbulletNotificationSettings extends INotificationSettings { channelTag: string; } +export interface ITwilioSettings extends ISettings { + whatsAppSettings: IWhatsAppSettings; +} + +export interface IWhatsAppSettings { + enabled: number; + from: string; + accountSid: string; + authToken: string; + notificationTemplates: INotificationTemplates[]; +} + export interface IPushoverNotificationSettings extends INotificationSettings { accessToken: string; notificationTemplates: INotificationTemplates[]; diff --git a/src/Ombi/ClientApp/src/app/services/settings.service.ts b/src/Ombi/ClientApp/src/app/services/settings.service.ts index fb50f3e89..4eec29081 100644 --- a/src/Ombi/ClientApp/src/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/src/app/services/settings.service.ts @@ -36,6 +36,7 @@ import { IUpdateSettings, IUserManagementSettings, IVoteSettings, + ITwilioSettings, } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @@ -254,6 +255,15 @@ export class SettingsService extends ServiceHelpers { .post(`${this.url}/notifications/telegram`, JSON.stringify(settings), {headers: this.headers}); } + public getTwilioSettings(): Observable { + return this.http.get(`${this.url}/notifications/twilio`, {headers: this.headers}); + } + + public saveTwilioSettings(settings: ITwilioSettings): Observable { + return this.http + .post(`${this.url}/notifications/twilio`, JSON.stringify(settings), {headers: this.headers}); + } + public getJobSettings(): Observable { return this.http.get(`${this.url}/jobs`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.html index 1fd475a38..02551a345 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.html @@ -1,36 +1,26 @@ - - + +

+ + + + + {{NotificationType[template.notificationType] | humanize}} + + - - - -
-
- -
-
- -
-
- -
- -
- -
-
+
+ Enable +
-
- -
- -
-
-
-
+ + + -
-
-
+ + + +
+ +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.html new file mode 100644 index 000000000..e28ec4115 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.html @@ -0,0 +1,21 @@ + + +
+
+ Twilio +
+ + + + + + + +
+
+ +
+
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.ts new file mode 100644 index 000000000..4f2364107 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.ts @@ -0,0 +1,55 @@ +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; + +import { INotificationTemplates, ITwilioSettings, NotificationType } from "../../../interfaces"; +import { TesterService } from "../../../services"; +import { NotificationService } from "../../../services"; +import { SettingsService } from "../../../services"; + +@Component({ + templateUrl: "./twilio.component.html", +}) +export class TwilioComponent implements OnInit { + public NotificationType = NotificationType; + public templates: INotificationTemplates[]; + public form: FormGroup; + + constructor(private settingsService: SettingsService, + private notificationService: NotificationService, + private fb: FormBuilder, + private testerService: TesterService) { } + + public ngOnInit() { + this.settingsService.getTwilioSettings().subscribe(x => { + this.templates = x.whatsAppSettings.notificationTemplates; + + this.form = this.fb.group({ + whatsAppSettings: this.fb.group({ + enabled: [x.whatsAppSettings.enabled], + accountSid: [x.whatsAppSettings.accountSid], + authToken: [x.whatsAppSettings.authToken], + from: [x.whatsAppSettings.from], + }), + }); + }); + } + + public onSubmit(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + const settings = form.value; + settings.whatsAppSettings.notificationTemplates = this.templates; + + this.settingsService.saveTwilioSettings(settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved the Twilio settings"); + } else { + this.notificationService.success("There was an error when saving the Twilio settings"); + } + }); + + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.html new file mode 100644 index 000000000..666cc4cfd --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.html @@ -0,0 +1,35 @@ +
+
+
+
+ Enable +
+ + +
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+ +
+
+
+ +
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.ts new file mode 100644 index 000000000..e77653d38 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.ts @@ -0,0 +1,37 @@ +import { Component, Input } from "@angular/core"; +import { FormGroup } from "@angular/forms"; +import { TesterService, NotificationService } from "../../../services"; +import { INotificationTemplates, NotificationType } from "../../../interfaces"; + + + +@Component({ + templateUrl: "./whatsapp.component.html", + selector: "app-whatsapp" +}) +export class WhatsAppComponent { + + public NotificationType = NotificationType; + @Input() public templates: INotificationTemplates[]; + @Input() public form: FormGroup; + + constructor(private testerService: TesterService, + private notificationService: NotificationService) { } + + + public test(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + this.testerService.mattermostTest(form.value).subscribe(x => { + if (x) { + this.notificationService.success( "Successfully sent a Mattermost message, please check the appropriate channel"); + } else { + this.notificationService.error("There was an error when sending the Mattermost message. Please check your settings"); + } + }); + + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/settings.module.ts b/src/Ombi/ClientApp/src/app/settings/settings.module.ts index e4be0c24e..bdf0596ac 100644 --- a/src/Ombi/ClientApp/src/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/src/app/settings/settings.module.ts @@ -55,6 +55,8 @@ import { MatMenuModule} from "@angular/material"; import { SharedModule } from "../shared/shared.module"; import { HubService } from "../services/hub.service"; import { LogsComponent } from "./logs/logs.component"; +import { TwilioComponent } from "./notifications/twilio/twilio.component"; +import { WhatsAppComponent } from "./notifications/twilio/whatsapp.component"; const routes: Routes = [ { path: "Ombi", component: OmbiComponent, canActivate: [AuthGuard] }, @@ -72,6 +74,7 @@ const routes: Routes = [ { path: "Pushbullet", component: PushbulletComponent, canActivate: [AuthGuard] }, { path: "Gotify", component: GotifyComponent, canActivate: [AuthGuard] }, { path: "Mattermost", component: MattermostComponent, canActivate: [AuthGuard] }, + { path: "Twilio", component: TwilioComponent, canActivate: [AuthGuard] }, { path: "UserManagement", component: UserManagementComponent, canActivate: [AuthGuard] }, { path: "Update", component: UpdateComponent, canActivate: [AuthGuard] }, { path: "CouchPotato", component: CouchPotatoComponent, canActivate: [AuthGuard] }, @@ -149,6 +152,8 @@ const routes: Routes = [ TheMovieDbComponent, FailedRequestsComponent, LogsComponent, + TwilioComponent, + WhatsAppComponent ], exports: [ RouterModule, diff --git a/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html index 41a5c5d66..21f01d010 100644 --- a/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html @@ -2,62 +2,63 @@ - - - - - - - + + + + + + + - - + + - - - + + + - - - + + + - + - - - - - - - - - - - + + + + + + + + + + + + - - - - - + + + + +
\ No newline at end of file diff --git a/src/Ombi/Controllers/V1/SettingsController.cs b/src/Ombi/Controllers/V1/SettingsController.cs index d3bf7845c..0575d0914 100644 --- a/src/Ombi/Controllers/V1/SettingsController.cs +++ b/src/Ombi/Controllers/V1/SettingsController.cs @@ -964,17 +964,21 @@ namespace Ombi.Controllers.V1 } /// - /// Gets the WhatsApp Notification Settings. + /// Gets the Twilio Notification Settings. /// /// - [HttpGet("notifications/whatsapp")] - public async Task WhatsAppNotificationSettings() + [HttpGet("notifications/twilio")] + public async Task TwilioNotificationSettings() { - var settings = await Get(); - var model = Mapper.Map(settings); + var settings = await Get(); + var model = Mapper.Map(settings); // Lookup to see if we have any templates saved - model.NotificationTemplates = BuildTemplates(NotificationAgent.WhatsApp); + if(model.WhatsAppSettings == null) + { + model.WhatsAppSettings = new WhatsAppSettingsViewModel(); + } + model.WhatsAppSettings.NotificationTemplates = BuildTemplates(NotificationAgent.WhatsApp); return model; } @@ -984,15 +988,15 @@ namespace Ombi.Controllers.V1 ///
/// The model. /// - [HttpPost("notifications/whatsapp")] - public async Task WhatsAppNotificationSettings([FromBody] WhatsAppNotificationsViewModel model) + [HttpPost("notifications/twilio")] + public async Task TwilioNotificationSettings([FromBody] TwilioSettingsViewModel model) { // Save the email settings - var settings = Mapper.Map(model); + var settings = Mapper.Map(model); var result = await Save(settings); // Save the templates - await TemplateRepository.UpdateRange(model.NotificationTemplates); + await TemplateRepository.UpdateRange(model.WhatsAppSettings.NotificationTemplates); return result; }