Add support for tags and priorities + make default query and mapper
This commit is contained in:
@@ -2,6 +2,7 @@ import fs from "fs";
|
|||||||
import { BackendSettings } from "../types/config";
|
import { BackendSettings } from "../types/config";
|
||||||
import { Notification } from "../types/notification";
|
import { Notification } from "../types/notification";
|
||||||
import { Backend } from "./base";
|
import { Backend } from "./base";
|
||||||
|
import { TaskPriority } from "../types/task";
|
||||||
|
|
||||||
type Config = {
|
type Config = {
|
||||||
url: string;
|
url: string;
|
||||||
@@ -20,10 +21,27 @@ export class NtfySH extends Backend<Config> {
|
|||||||
fetch(`https://${config.url}/${config.topic || 'obsidian'}`, {
|
fetch(`https://${config.url}/${config.topic || 'obsidian'}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: notification.text,
|
body: notification.text,
|
||||||
headers: {
|
headers: {
|
||||||
'Title': notification.title,
|
'Authorization': `Bearer ${token}`,
|
||||||
'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 fs from "fs";
|
||||||
import { Task } from "../types/task";
|
import { Task } from "../types/task";
|
||||||
import { Notification, NotificationDatabase } from "../types/notification";
|
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.
|
* 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);
|
const data = serializeDatabase(tasks, mapper);
|
||||||
fs.writeFileSync(file, data);
|
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.
|
* 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 {
|
export function serializeDatabase(tasks: Task[], mapper?: string): string {
|
||||||
const transformer = new Function("$", `return ${mapper}`) as (task: Task) => Notification;
|
const transformer = mapper
|
||||||
|
? jsMapper<Task, Notification>(mapper, {})
|
||||||
|
: defaultMapper;
|
||||||
|
|
||||||
const output = tasks.map(wrapWithTimeFiller(transformer)).reduce((acc, n) => {
|
const output = tasks.map(wrapWithTimeFiller(transformer)).reduce((acc, n) => {
|
||||||
if (n.time) {
|
if (n.time) {
|
||||||
@@ -36,4 +40,13 @@ function wrapWithTimeFiller(mapper: (task: Task) => Notification): (task: Task)
|
|||||||
time: task.reminder ?? notification.time,
|
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 { Task as DefaultTask } from "../model";
|
||||||
import { ParseResult } from "../types/grammar";
|
import { ParseResult } from "../types/grammar";
|
||||||
import { Task, TaskPriority } from "../types/task";
|
import { Task, TaskPriority } from "../types/task";
|
||||||
|
import { jsMapper } from "../util";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all tasks from specified directory and filters them with optional query.
|
* 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
|
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));
|
const tasks = await Promise.all(directories.map(readTasksFromDirectory));
|
||||||
|
|
||||||
return tasks.flat().filter(t => filter ? filter(t) : true);
|
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.
|
* Read all files in specific directory and returns all tasks from those files.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export type Config = {
|
export type Config = {
|
||||||
sources: string[];
|
sources: string[];
|
||||||
query: string;
|
query?: string;
|
||||||
mapper: string;
|
mapper?: string;
|
||||||
databaseFile: string;
|
databaseFile: string;
|
||||||
backend: Record<string, unknown>;
|
backend: Record<string, unknown>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import dayjs, { Dayjs } from "dayjs"
|
import { TaskPriority } from "./task";
|
||||||
|
|
||||||
export type Notification = {
|
export type Notification = {
|
||||||
time?: string;
|
|
||||||
title: string;
|
|
||||||
text: string;
|
text: string;
|
||||||
|
time?: string;
|
||||||
|
title?: string;
|
||||||
|
priority?: TaskPriority;
|
||||||
|
tags?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NotificationDatabase = Record<string, Notification[]>;
|
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