add bark notification

This commit is contained in:
ygguorun
2022-10-18 20:01:57 +08:00
parent 6c0ed92ac8
commit 91195fb999
36 changed files with 538 additions and 41 deletions

View File

@@ -0,0 +1,20 @@
<app-sub-page pageTitle="Bark 通知">
<ng-template appSubPageContent>
<app-page-section>
<app-notifier-settings [settings]="notifierSettings" keyOfSettings="barkNotification"></app-notifier-settings>
</app-page-section>
<app-page-section name="Bark">
<app-bark-settings [settings]="barkSettings"></app-bark-settings>
</app-page-section>
<app-page-section name="事件">
<app-event-settings [settings]="notificationSettings" keyOfSettings="barkNotification"></app-event-settings>
</app-page-section>
<app-page-section name="消息">
<app-message-template-settings [settings]="messageTemplateSettings" keyOfSettings="barkNotification">
</app-message-template-settings>
</app-page-section>
</ng-template>
</app-sub-page>

View File

@@ -0,0 +1,2 @@
@use '../../shared/styles/setting';

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BarkNotificationSettingsComponent } from './bark-notification-settings.component';
describe('BarkNotificationSettingsComponent', () => {
let component: BarkNotificationSettingsComponent;
let fixture: ComponentFixture<BarkNotificationSettingsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [BarkNotificationSettingsComponent]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(BarkNotificationSettingsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,53 @@
import {
Component,
OnInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import pick from 'lodash-es/pick';
import {
KEYS_OF_MESSAGE_TEMPLATE_SETTINGS,
KEYS_OF_NOTIFICATION_SETTINGS,
KEYS_OF_NOTIFIER_SETTINGS,
KEYS_OF_BARK_SETTINGS,
MessageTemplateSettings,
NotificationSettings,
NotifierSettings,
BarkNotificationSettings,
BarkSettings,
} from '../../shared/setting.model';
@Component({
selector: 'app-bark-notification-settings',
templateUrl: './bark-notification-settings.component.html',
styleUrls: ['./bark-notification-settings.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BarkNotificationSettingsComponent implements OnInit {
barkSettings!: BarkSettings;
notifierSettings!: NotifierSettings;
notificationSettings!: NotificationSettings;
messageTemplateSettings!: MessageTemplateSettings;
constructor(
private changeDetector: ChangeDetectorRef,
private route: ActivatedRoute
) { }
ngOnInit(): void {
this.route.data.subscribe((data) => {
const settings = data.settings as BarkNotificationSettings;
this.barkSettings = pick(settings, KEYS_OF_BARK_SETTINGS);
this.notifierSettings = pick(settings, KEYS_OF_NOTIFIER_SETTINGS);
this.notificationSettings = pick(settings, KEYS_OF_NOTIFICATION_SETTINGS);
this.messageTemplateSettings = pick(
settings,
KEYS_OF_MESSAGE_TEMPLATE_SETTINGS
);
this.changeDetector.markForCheck();
});
}
}

View File

@@ -0,0 +1,33 @@
<form nz-form [formGroup]="settingsForm">
<nz-form-item class="setting-item">
<nz-form-label class="setting-label align-required" nzFor="server" nzNoColon>server</nz-form-label>
<nz-form-control class="setting-control input" nzHasFeedback [nzErrorTip]="serverErrorTip"
[nzWarningTip]="syncFailedWarningTip" [nzValidateStatus]="
serverControl.valid && !syncStatus.server ? 'warning' : serverControl
">
<input id="server" type="url" placeholder="默认为官方服务器 https://api.day.app" nz-input formControlName="server" />
<ng-template #serverErrorTip let-control>
<ng-container *ngIf="control.hasError('pattern')">
server 无效
</ng-container>
</ng-template>
</nz-form-control>
</nz-form-item>
<nz-form-item class="setting-item">
<nz-form-label class="setting-label" nzFor="pushkey" nzNoColon nzRequired>pushkey</nz-form-label>
<nz-form-control class="setting-control input" nzHasFeedback [nzErrorTip]="pushkeyErrorTip"
[nzWarningTip]="syncFailedWarningTip" [nzValidateStatus]="
pushkeyControl.valid && !syncStatus.pushkey ? 'warning' : pushkeyControl
">
<input id="pushkey" type="text" placeholder="" required nz-input formControlName="pushkey" />
<ng-template #pushkeyErrorTip let-control>
<ng-container *ngIf="control.hasError('required')">
请输入 pushkey
</ng-container>
<ng-container *ngIf="control.hasError('pattern')">
pushkey 无效
</ng-container>
</ng-template>
</nz-form-control>
</nz-form-item>
</form>

View File

@@ -0,0 +1,6 @@
@use '../../../shared/styles/setting';
.setting-label {
max-width: 5em !important;
width: 5em !important;
}

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BarkSettingsComponent } from './bark-settings.component';
describe('BarkSettingsComponent', () => {
let component: BarkSettingsComponent;
let fixture: ComponentFixture<BarkSettingsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [BarkSettingsComponent]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(BarkSettingsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,87 @@
import {
Component,
OnInit,
ChangeDetectionStrategy,
Input,
OnChanges,
ChangeDetectorRef,
} from '@angular/core';
import {
FormBuilder,
FormControl,
FormGroup,
Validators,
} from '@angular/forms';
import mapValues from 'lodash-es/mapValues';
import { BarkSettings } from '../../../shared/setting.model';
import { filterValueChanges } from '../../../shared/rx-operators';
import {
SettingsSyncService,
SyncStatus,
calcSyncStatus,
} from '../../../shared/services/settings-sync.service';
import { SYNC_FAILED_WARNING_TIP } from 'src/app/settings/shared/constants/form';
@Component({
selector: 'app-bark-settings',
templateUrl: './bark-settings.component.html',
styleUrls: ['./bark-settings.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BarkSettingsComponent implements OnInit, OnChanges {
@Input() settings!: BarkSettings;
syncStatus!: SyncStatus<BarkSettings>;
readonly settingsForm: FormGroup;
readonly syncFailedWarningTip = SYNC_FAILED_WARNING_TIP;
constructor(
formBuilder: FormBuilder,
private changeDetector: ChangeDetectorRef,
private settingsSyncService: SettingsSyncService
) {
this.settingsForm = formBuilder.group({
server: ['', [Validators.pattern(/^https?:\/\/.+/)]],
pushkey: [
'',
[
Validators.required,
Validators.pattern(
/^[a-zA-Z\d]+$/
),
],
],
});
}
get serverControl() {
return this.settingsForm.get('server') as FormControl;
}
get pushkeyControl() {
return this.settingsForm.get('pushkey') as FormControl;
}
ngOnChanges(): void {
this.syncStatus = mapValues(this.settings, () => true);
console.log(this.settings);
this.settingsForm.setValue(this.settings);
}
ngOnInit(): void {
this.settingsSyncService
.syncSettings(
'barkNotification',
this.settings,
this.settingsForm.valueChanges.pipe(
filterValueChanges<Partial<BarkSettings>>(this.settingsForm)
)
)
.subscribe((detail) => {
this.syncStatus = { ...this.syncStatus, ...calcSyncStatus(detail) };
this.changeDetector.markForCheck();
});
}
}

View File

@@ -1,20 +1,12 @@
<a class="setting-item" routerLink="email-notification"
><span class="setting-label">邮箱通知</span
><span class="setting-control"> <i nz-icon nzType="right"></i> </span
></a>
<a class="setting-item" routerLink="serverchan-notification"
><span class="setting-label">ServerChan 通知</span
><span class="setting-control"><i nz-icon nzType="right"></i></span
></a>
<a class="setting-item" routerLink="pushdeer-notification"
><span class="setting-label">PushDeer 通知</span
><span class="setting-control"><i nz-icon nzType="right"></i></span
></a>
<a class="setting-item" routerLink="pushplus-notification"
><span class="setting-label">pushplus 通知</span
><span class="setting-control"><i nz-icon nzType="right"></i></span
></a>
<a class="setting-item" routerLink="telegram-notification"
><span class="setting-label">telegram 通知</span
><span class="setting-control"><i nz-icon nzType="right"></i></span
></a>
<a class="setting-item" routerLink="email-notification"><span class="setting-label">邮箱通知</span><span
class="setting-control"> <i nz-icon nzType="right"></i> </span></a>
<a class="setting-item" routerLink="serverchan-notification"><span class="setting-label">ServerChan 通知</span><span
class="setting-control"><i nz-icon nzType="right"></i></span></a>
<a class="setting-item" routerLink="pushdeer-notification"><span class="setting-label">PushDeer 通知</span><span
class="setting-control"><i nz-icon nzType="right"></i></span></a>
<a class="setting-item" routerLink="pushplus-notification"><span class="setting-label">pushplus 通知</span><span
class="setting-control"><i nz-icon nzType="right"></i></span></a>
<a class="setting-item" routerLink="telegram-notification"><span class="setting-label">telegram 通知</span><span
class="setting-control"><i nz-icon nzType="right"></i></span></a>
<a class="setting-item" routerLink="bark-notification"><span class="setting-label">Bark 通知</span><span
class="setting-control"><i nz-icon nzType="right"></i></span></a>

View File

@@ -66,6 +66,7 @@ export class PushdeerSettingsComponent implements OnInit, OnChanges {
ngOnChanges(): void {
this.syncStatus = mapValues(this.settings, () => true);
console.log(this.settings);
this.settingsForm.setValue(this.settings);
}

View File

@@ -32,7 +32,8 @@ export class EventSettingsComponent implements OnInit, OnChanges {
| 'serverchanNotification'
| 'pushdeerNotification'
| 'pushplusNotification'
| 'telegramNotification';
| 'telegramNotification'
| 'barkNotification';
syncStatus!: SyncStatus<NotificationSettings>;

View File

@@ -38,7 +38,8 @@ export class MessageTemplateSettingsComponent implements OnInit, OnChanges {
| 'serverchanNotification'
| 'pushdeerNotification'
| 'pushplusNotification'
| 'telegramNotification';
| 'telegramNotification'
| 'barkNotification';
messageTypes!: MessageType[];
beganMessageTemplateSettings!: CommonMessageTemplateSettings;
@@ -50,7 +51,7 @@ export class MessageTemplateSettingsComponent implements OnInit, OnChanges {
private changeDetector: ChangeDetectorRef,
private message: NzMessageService,
private settingService: SettingService
) {}
) { }
ngOnInit(): void {
switch (this.keyOfSettings) {

View File

@@ -32,7 +32,8 @@ export class NotifierSettingsComponent implements OnInit, OnChanges {
| 'serverchanNotification'
| 'pushdeerNotification'
| 'pushplusNotification'
| 'telegramNotification';
| 'telegramNotification'
| 'barkNotification';
syncStatus!: SyncStatus<NotifierSettings>;

View File

@@ -7,6 +7,7 @@ import { PushplusNotificationSettingsResolver } from './shared/services/pushplus
import { TelegramNotificationSettingsResolver } from './shared/services/telegram-notification-settings.resolver';
import { ServerchanNotificationSettingsResolver } from './shared/services/serverchan-notification-settings.resolver';
import { PushdeerNotificationSettingsResolver } from './shared/services/pushdeer-notification-settings.resolver';
import { BarkNotificationSettingsResolver } from './shared/services/bark-notification-settings.resolver';
import { WebhookSettingsResolver } from './shared/services/webhook-settings.resolver';
import { SettingsComponent } from './settings.component';
import { EmailNotificationSettingsComponent } from './notification-settings/email-notification-settings/email-notification-settings.component';
@@ -14,6 +15,7 @@ import { ServerchanNotificationSettingsComponent } from './notification-settings
import { PushdeerNotificationSettingsComponent } from './notification-settings/pushdeer-notification-settings/pushdeer-notification-settings.component';
import { PushplusNotificationSettingsComponent } from './notification-settings/pushplus-notification-settings/pushplus-notification-settings.component';
import { TelegramNotificationSettingsComponent } from './notification-settings/telegram-notification-settings/telegram-notification-settings.component';
import { BarkNotificationSettingsComponent } from './notification-settings/bark-notification-settings/bark-notification-settings.component';
import { WebhookManagerComponent } from './webhook-settings/webhook-manager/webhook-manager.component';
const routes: Routes = [
@@ -52,6 +54,13 @@ const routes: Routes = [
settings: TelegramNotificationSettingsResolver,
},
},
{
path: 'bark-notification',
component: BarkNotificationSettingsComponent,
resolve: {
settings: BarkNotificationSettingsResolver,
},
},
{
path: 'webhooks',
component: WebhookManagerComponent,
@@ -72,4 +81,4 @@ const routes: Routes = [
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class SettingsRoutingModule {}
export class SettingsRoutingModule { }

View File

@@ -70,6 +70,9 @@ import { BiliApiSettingsComponent } from './bili-api-settings/bili-api-settings.
import { BaseApiUrlEditDialogComponent } from './bili-api-settings/base-api-url-edit-dialog/base-api-url-edit-dialog.component';
import { BaseLiveApiUrlEditDialogComponent } from './bili-api-settings/base-live-api-url-edit-dialog/base-live-api-url-edit-dialog.component';
import { BasePlayInfoApiUrlEditDialogComponent } from './bili-api-settings/base-play-info-api-url-edit-dialog/base-play-info-api-url-edit-dialog.component';
import { BarkNotificationSettingsComponent } from './notification-settings/bark-notification-settings/bark-notification-settings.component';
import { BarkSettingsComponent } from './notification-settings/bark-notification-settings/bark-settings/bark-settings.component';
import { BarkNotificationSettingsResolver } from './shared/services/bark-notification-settings.resolver';
@NgModule({
declarations: [
@@ -98,6 +101,8 @@ import { BasePlayInfoApiUrlEditDialogComponent } from './bili-api-settings/base-
PushplusSettingsComponent,
TelegramNotificationSettingsComponent,
TelegramSettingsComponent,
BarkNotificationSettingsComponent,
BarkSettingsComponent,
NotifierSettingsComponent,
WebhookManagerComponent,
WebhookEditDialogComponent,
@@ -147,7 +152,8 @@ import { BasePlayInfoApiUrlEditDialogComponent } from './bili-api-settings/base-
PushdeerNotificationSettingsResolver,
PushplusNotificationSettingsResolver,
TelegramNotificationSettingsResolver,
BarkNotificationSettingsResolver,
WebhookSettingsResolver,
],
})
export class SettingsModule {}
export class SettingsModule { }

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { BarkNotificationSettingsResolver } from './bark-notification-settings.resolver';
describe('TelegramNotificationSettingsResolverService', () => {
let service: BarkNotificationSettingsResolver;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(BarkNotificationSettingsResolver);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,46 @@
import { Injectable } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import {
ActivatedRouteSnapshot,
Resolve,
RouterStateSnapshot,
} from '@angular/router';
import { Observable } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { NGXLogger } from 'ngx-logger';
import { NzNotificationService } from 'ng-zorro-antd/notification';
import { retry } from '../../../shared/rx-operators';
import { BarkNotificationSettings } from '../setting.model';
import { SettingService } from './setting.service';
@Injectable()
export class BarkNotificationSettingsResolver
implements Resolve<BarkNotificationSettings>
{
constructor(
private logger: NGXLogger,
private notification: NzNotificationService,
private settingService: SettingService
) { }
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<BarkNotificationSettings> {
return this.settingService.getSettings(['barkNotification']).pipe(
map((settings) => settings.barkNotification),
retry(3, 300),
catchError((error: HttpErrorResponse) => {
this.logger.error(
'Failed to get bark notification settings:',
error
);
this.notification.error('获取 bark 通知设置出错', error.message, {
nzDuration: 0,
});
throw error;
})
);
}
}

View File

@@ -169,7 +169,17 @@ export const KEYS_OF_TELEGRAM_SETTINGS = ['token', 'chatid'] as const;
export interface NotifierSettings {
enabled: boolean;
}
export interface BarkSettings {
server: string;
pushkey: string;
}
export const KEYS_OF_BARK_SETTINGS = ['server', 'pushkey'] as const;
export interface PushplusSettings {
token: string;
topic: string;
}
export const KEYS_OF_NOTIFIER_SETTINGS = ['enabled'] as const;
export interface NotificationSettings {
@@ -202,6 +212,8 @@ export type PushplusMessageType =
| MarkdownMessageType
| HtmlMessageType;
export type TelegramMessageType = MarkdownMessageType | HtmlMessageType;
export type BarkMessageType = TextMessageType;
export interface MessageTemplateSettings {
beganMessageType: string;
@@ -307,6 +319,20 @@ export interface TelegramMessageTemplateSettings {
errorMessageTitle: string;
errorMessageContent: string;
}
export interface BarkMessageTemplateSettings {
beganMessageType: BarkMessageType;
beganMessageTitle: string;
beganMessageContent: string;
endedMessageType: BarkMessageType;
endedMessageTitle: string;
endedMessageContent: string;
spaceMessageType: BarkMessageType;
spaceMessageTitle: string;
spaceMessageContent: string;
errorMessageType: BarkMessageType;
errorMessageTitle: string;
errorMessageContent: string;
}
export type EmailNotificationSettings = EmailSettings &
NotifierSettings &
@@ -333,6 +359,11 @@ export type TelegramNotificationSettings = TelegramSettings &
NotificationSettings &
TelegramMessageTemplateSettings;
export type BarkNotificationSettings = BarkSettings &
NotifierSettings &
NotificationSettings &
BarkMessageTemplateSettings;
export interface WebhookEventSettings {
liveBegan: boolean;
liveEnded: boolean;
@@ -371,6 +402,7 @@ export interface Settings {
pushdeerNotification: PushdeerNotificationSettings;
pushplusNotification: PushplusNotificationSettings;
telegramNotification: TelegramNotificationSettings;
barkNotification: BarkNotificationSettings;
webhooks: WebhookSettings[];
}