Compare commits
2 Commits
a270ee4ae5
...
8490e073f6
| Author | SHA1 | Date | |
|---|---|---|---|
|
8490e073f6
|
|||
|
298efc3345
|
@@ -1,10 +1,7 @@
|
||||
import dayjs from "dayjs";
|
||||
import { NotificationDatabase } from "../types/notification";
|
||||
import { Config } from "../types/config";
|
||||
import { NtfySH } from "./ntfy-sh";
|
||||
|
||||
export { Backend } from "./base";
|
||||
export { NtfySH } from "./ntfy-sh";
|
||||
import { NtfySH } from "./ntfy";
|
||||
|
||||
const backends = [
|
||||
new NtfySH()
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import { BackendSettings } from "../types/config";
|
||||
import { Notification } from "../types/notification";
|
||||
import { Backend } from "./base";
|
||||
|
||||
type Config = {
|
||||
url: string;
|
||||
token: string;
|
||||
topic?: string;
|
||||
} & BackendSettings;
|
||||
|
||||
export class NtfySH extends Backend<Config> {
|
||||
public name = "ntfy.sh";
|
||||
|
||||
protected requiredFields = ['url', 'token'] as const;
|
||||
|
||||
protected notify(config: Config, notification: Notification): void {
|
||||
fetch(`https://${config.url}/${config.topic || 'obsidian'}`, {
|
||||
method: 'POST',
|
||||
body: notification.text,
|
||||
headers: {
|
||||
'Title': notification.title,
|
||||
'Authorization': `Bearer ${config.token}`
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
47
src/backend/ntfy.ts
Normal file
47
src/backend/ntfy.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import fs from "fs";
|
||||
import { BackendSettings } from "../types/config";
|
||||
import { Notification } from "../types/notification";
|
||||
import { Backend } from "./base";
|
||||
import { TaskPriority } from "../types/task";
|
||||
|
||||
type Config = {
|
||||
url: string;
|
||||
tokenFile: string;
|
||||
topic?: string;
|
||||
} & BackendSettings;
|
||||
|
||||
export class NtfySH extends Backend<Config> {
|
||||
public name = "ntfy";
|
||||
|
||||
protected requiredFields = ['url', 'tokenFile'] as const;
|
||||
|
||||
protected notify(config: Config, notification: Notification): void {
|
||||
const token = fs.readFileSync(config.tokenFile, 'utf-8');
|
||||
|
||||
fetch(`https://${config.url}/${config.topic || 'obsidian'}`, {
|
||||
method: 'POST',
|
||||
body: notification.text,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Title': notification.title ?? "",
|
||||
'Priority': mapPriority(notification.priority),
|
||||
'Tags': notification.tags?.join(",") ?? ""
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function mapPriority(priority?: TaskPriority): string {
|
||||
if (!priority) {
|
||||
return 'default';
|
||||
}
|
||||
|
||||
return {
|
||||
[TaskPriority.LOWEST]: 'min',
|
||||
[TaskPriority.LOW]: 'low',
|
||||
[TaskPriority.NORMAL]: 'default',
|
||||
[TaskPriority.MEDIUM]: 'default',
|
||||
[TaskPriority.HIGH]: 'high',
|
||||
[TaskPriority.HIGHEST]: 'max',
|
||||
}[priority];
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
import fs from "fs";
|
||||
import { Task } from "../types/task";
|
||||
import { Notification, NotificationDatabase } from "../types/notification";
|
||||
import { jsMapper } from "../util";
|
||||
|
||||
|
||||
/**
|
||||
* Applies the mapper for each task from list, groups them by time and dumps the data into JSON formatted file.
|
||||
*/
|
||||
export function dumpDatabase(file: string, tasks: Task[], mapper: string) {
|
||||
export function dumpDatabase(file: string, tasks: Task[], mapper?: string) {
|
||||
const data = serializeDatabase(tasks, mapper);
|
||||
fs.writeFileSync(file, data);
|
||||
}
|
||||
@@ -13,8 +15,10 @@ export function dumpDatabase(file: string, tasks: Task[], mapper: string) {
|
||||
/**
|
||||
* Applies the mapper for each task from list, groups them by time and serializes into JSON format.
|
||||
*/
|
||||
export function serializeDatabase(tasks: Task[], mapper: string): string {
|
||||
const transformer = new Function("$", `return ${mapper}`) as (task: Task) => Notification;
|
||||
export function serializeDatabase(tasks: Task[], mapper?: string): string {
|
||||
const transformer = mapper
|
||||
? jsMapper<Task, Notification>(mapper, {})
|
||||
: defaultMapper;
|
||||
|
||||
const output = tasks.map(wrapWithTimeFiller(transformer)).reduce((acc, n) => {
|
||||
if (n.time) {
|
||||
@@ -36,4 +40,13 @@ function wrapWithTimeFiller(mapper: (task: Task) => Notification): (task: Task)
|
||||
time: task.reminder ?? notification.time,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function defaultMapper(task: Task): Notification {
|
||||
return {
|
||||
title: "Obsidian Tasks Reminder",
|
||||
text: task.label,
|
||||
priority: task.priority,
|
||||
tags: task.tags,
|
||||
};
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { parse } from "../generated/grammar/task";
|
||||
import { Task as DefaultTask } from "../model";
|
||||
import { ParseResult } from "../types/grammar";
|
||||
import { Task, TaskPriority } from "../types/task";
|
||||
import { jsMapper } from "../util";
|
||||
|
||||
/**
|
||||
* Returns all tasks from specified directory and filters them with optional query.
|
||||
@@ -20,21 +21,12 @@ export async function loadTasks(directories: string[], query?: string): Promise<
|
||||
HIGHEST: TaskPriority.HIGHEST
|
||||
};
|
||||
|
||||
const filter = query && createFilter(query, ctx);
|
||||
const filter = query && jsMapper<Task, boolean>(query, ctx);
|
||||
const tasks = await Promise.all(directories.map(readTasksFromDirectory));
|
||||
|
||||
return tasks.flat().filter(t => filter ? filter(t) : true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a filter function for tasks using a query string and context object.
|
||||
* All context' properties will be passed as variables to the query string.
|
||||
*/
|
||||
function createFilter(query: string, context: Record<string, unknown>): (task: Task) => boolean {
|
||||
const filter = new Function('$', ...Object.keys(context), `return ${query};`);
|
||||
return (task: Task) => filter(task, ...Object.values(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all files in specific directory and returns all tasks from those files.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export type Config = {
|
||||
sources: string[];
|
||||
query: string;
|
||||
mapper: string;
|
||||
query?: string;
|
||||
mapper?: string;
|
||||
databaseFile: string;
|
||||
backend: Record<string, unknown>;
|
||||
};
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import dayjs, { Dayjs } from "dayjs"
|
||||
import { TaskPriority } from "./task";
|
||||
|
||||
export type Notification = {
|
||||
time?: string;
|
||||
title: string;
|
||||
text: string;
|
||||
time?: string;
|
||||
title?: string;
|
||||
priority?: TaskPriority;
|
||||
tags?: string[];
|
||||
};
|
||||
|
||||
export type NotificationDatabase = Record<string, Notification[]>;
|
||||
4
src/util/index.ts
Normal file
4
src/util/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export function jsMapper<I, O>(code: string, context: Record<string, unknown>): (task: I) => O {
|
||||
const filter = new Function('$', ...Object.keys(context), `return ${code};`);
|
||||
return (task: I) => filter(task, ...Object.values(context));
|
||||
}
|
||||
Reference in New Issue
Block a user