Compare commits
2 Commits
160d180b00
...
998f639a55
| Author | SHA1 | Date | |
|---|---|---|---|
| 998f639a55 | |||
| 90a2805339 |
@@ -1,2 +1,136 @@
|
|||||||
# donetick-notifier
|
# donetick-notifier
|
||||||
|
|
||||||
|
A small PowerShell notifier for [Donetick](https://github.com/donetick/donetick) chores.
|
||||||
|
|
||||||
|
The notifier checks the Donetick external API for chores, groups tasks that are overdue or due today, and sends summary notifications through an Apprise-compatible webhook.
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
- Fetches chores from `https://<DONETICKHOST>:<DONETICKPORT>/eapi/v1/chore`.
|
||||||
|
- Authenticates to Donetick with the `secretkey` header.
|
||||||
|
- Sends one Apprise notification for overdue tasks, when any exist.
|
||||||
|
- Sends one Apprise notification for tasks due today, when any exist.
|
||||||
|
- Runs once and exits.
|
||||||
|
|
||||||
|
Because the container runs once and exits, schedule it with cron, systemd timers, Kubernetes CronJobs, Gitea Actions, or another scheduler if you want recurring notifications.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
All configuration is provided through environment variables.
|
||||||
|
|
||||||
|
| Variable | Required | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `DONETICKHOST` | Yes | Donetick host name or IP address. Do not include `https://`. |
|
||||||
|
| `DONETICKPORT` | Yes | Donetick HTTPS port. |
|
||||||
|
| `DONETICKAPIKEY` | Yes | Donetick external API key. Sent as the `secretkey` header. |
|
||||||
|
| `APPRISEWEBHOOKURL` | Yes | Apprise webhook URL that accepts notification posts. |
|
||||||
|
| `APPRISEWEBHOOKTAG` | Yes | Apprise tag value to include with each notification. |
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
The published image is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
docker.io/blinkfink182/donetick-notifier
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Once
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker run --rm \
|
||||||
|
--name donetick-notifier \
|
||||||
|
-e DONETICKHOST=host.docker.internal \
|
||||||
|
-e DONETICKPORT=8787 \
|
||||||
|
-e DONETICKAPIKEY=your-donetick-api-key \
|
||||||
|
-e APPRISEWEBHOOKURL=https://apprise.example.com/notify/config \
|
||||||
|
-e APPRISEWEBHOOKTAG=all \
|
||||||
|
docker.io/blinkfink182/donetick-notifier:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Compose
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
donetick-notifier:
|
||||||
|
container_name: donetick-notifier
|
||||||
|
image: docker.io/blinkfink182/donetick-notifier:latest
|
||||||
|
environment:
|
||||||
|
DONETICKHOST: host.docker.internal
|
||||||
|
DONETICKPORT: "8787"
|
||||||
|
DONETICKAPIKEY: your-donetick-api-key
|
||||||
|
APPRISEWEBHOOKURL: https://apprise.example.com/notify/config
|
||||||
|
APPRISEWEBHOOKTAG: all
|
||||||
|
```
|
||||||
|
|
||||||
|
Run it with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker compose run --rm donetick-notifier
|
||||||
|
```
|
||||||
|
|
||||||
|
If Donetick and Apprise are running on the same Docker network, use the service names instead of `host.docker.internal`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
donetick-notifier:
|
||||||
|
image: docker.io/blinkfink182/donetick-notifier:latest
|
||||||
|
environment:
|
||||||
|
DONETICKHOST: donetick
|
||||||
|
DONETICKPORT: "8787"
|
||||||
|
DONETICKAPIKEY: your-donetick-api-key
|
||||||
|
APPRISEWEBHOOKURL: http://apprise:8000/notify/config
|
||||||
|
APPRISEWEBHOOKTAG: all
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build Locally
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker build -t donetick-notifier .
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker run --rm \
|
||||||
|
-e DONETICKHOST=host.docker.internal \
|
||||||
|
-e DONETICKPORT=8787 \
|
||||||
|
-e DONETICKAPIKEY=your-donetick-api-key \
|
||||||
|
-e APPRISEWEBHOOKURL=https://apprise.example.com/notify/config \
|
||||||
|
-e APPRISEWEBHOOKTAG=all \
|
||||||
|
donetick-notifier
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run Without Docker
|
||||||
|
|
||||||
|
PowerShell 7 or newer is recommended.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$env:DONETICKHOST = "donetick.example.com"
|
||||||
|
$env:DONETICKPORT = "8787"
|
||||||
|
$env:DONETICKAPIKEY = "your-donetick-api-key"
|
||||||
|
$env:APPRISEWEBHOOKURL = "https://apprise.example.com/notify/config"
|
||||||
|
$env:APPRISEWEBHOOKTAG = "all"
|
||||||
|
|
||||||
|
pwsh ./Start-DoneTickNotifier.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
|
||||||
|
This repository includes Gitea workflows for:
|
||||||
|
|
||||||
|
- Building and pushing the Docker image.
|
||||||
|
- Running security checks with Gitleaks, Semgrep, and Trivy.
|
||||||
|
- Creating Gitea issues for security findings when configured with a `GITEA_TOKEN`.
|
||||||
|
- Sending Apprise notifications for Docker build success or failure.
|
||||||
|
|
||||||
|
The Docker build workflow tags images as:
|
||||||
|
|
||||||
|
| Branch or ref | Image tag |
|
||||||
|
| --- | --- |
|
||||||
|
| `main` | `latest` |
|
||||||
|
| refs beginning with `v` | matching ref name, such as `v1.0.0` |
|
||||||
|
| all other refs | `test` |
|
||||||
|
|
||||||
|
## AI Assistance Disclosure
|
||||||
|
|
||||||
|
OpenAI Codex was used to help create this README and the Gitea pipeline files in this repository.
|
||||||
|
|
||||||
|
All released application code is written by the repository owner.
|
||||||
|
|||||||
+57
-39
@@ -3,6 +3,7 @@
|
|||||||
[string] $dtAPIKey = $ENV:DONETICKAPIKEY
|
[string] $dtAPIKey = $ENV:DONETICKAPIKEY
|
||||||
[string] $appriseWebhookURL = $ENV:APPRISEWEBHOOKURL
|
[string] $appriseWebhookURL = $ENV:APPRISEWEBHOOKURL
|
||||||
[string] $appriseWebhookTag = $ENV:APPRISEWEBHOOKTAG
|
[string] $appriseWebhookTag = $ENV:APPRISEWEBHOOKTAG
|
||||||
|
[int[]] $notificationTimes = $ENV:NOTIFICATIONTIMES | Sort-Object
|
||||||
|
|
||||||
|
|
||||||
function Send-Notification
|
function Send-Notification
|
||||||
@@ -50,54 +51,71 @@ function Get-Chores
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$today = (Get-Date "23:59:59")
|
while ($true) {
|
||||||
$chores = Get-Chores
|
$today = (Get-Date "23:59:59")
|
||||||
|
$chores = Get-Chores
|
||||||
$overdueTasks = @()
|
|
||||||
$todaysTasks = @()
|
$overdueTasks = @()
|
||||||
|
$todaysTasks = @()
|
||||||
foreach($chore in $chores)
|
|
||||||
{
|
foreach($chore in $chores)
|
||||||
if ($chore.nextDueDate)
|
|
||||||
{
|
{
|
||||||
$dueDate = Get-Date $chore.nextDueDate
|
if ($chore.nextDueDate)
|
||||||
if (($dueDate - $today).Days -lt 0) #OVERDUE
|
|
||||||
{
|
{
|
||||||
write-host "$($chore.name) $dueDate is overdue!"
|
$dueDate = Get-Date $chore.nextDueDate
|
||||||
$overdueTasks += $chore
|
if (($dueDate - $today).Days -lt 0) #OVERDUE
|
||||||
|
{
|
||||||
|
write-host "$($chore.name) $dueDate is overdue!"
|
||||||
|
$overdueTasks += $chore
|
||||||
|
}
|
||||||
|
elseif (($dueDate - $today) -lt 1) #due today
|
||||||
|
{
|
||||||
|
write-host "$($chore.name) $dueDate is due today!"
|
||||||
|
$todaysTasks += $chore
|
||||||
|
# Send-Notification -title "TASK DUE TODAY" -content "$($chore.Name) is due today!"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write-host "$($chore.name) $dueDate is due in the future"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
elseif (($dueDate - $today) -lt 1) #due today
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($overdueTasks.Count -ne 0)
|
||||||
|
{
|
||||||
|
Write-Host "Sending a notification for $($overdueTasks.Count) overdue tasks"
|
||||||
|
$content = "The following tasks are overdue!`n"
|
||||||
|
foreach($overdueTask in $overdueTasks)
|
||||||
{
|
{
|
||||||
write-host "$($chore.name) $dueDate is due today!"
|
$content += "$($overdueTask.Name) was due $(Get-Date $overdueTask.nextDueDate -Format "MM/dd/yyyy HH:mm")`n"
|
||||||
$todaysTasks += $chore
|
|
||||||
# Send-Notification -title "TASK DUE TODAY" -content "$($chore.Name) is due today!"
|
|
||||||
}
|
}
|
||||||
else
|
Send-Notification -title "OVERDUE TASKS" -content $content
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($todaysTasks.Count -ne 0)
|
||||||
|
{
|
||||||
|
Write-Host "Sending a notification for $($todaysTasks.Count) tasks due today"
|
||||||
|
$content = "The following tasks are due today!`n"
|
||||||
|
foreach($task in $todaysTasks)
|
||||||
{
|
{
|
||||||
write-host "$($chore.name) $dueDate is due in the future"
|
$content += "$($task.Name) is due $(Get-Date $task.nextDueDate -Format "MM/dd/yyyy HH:mm")`n"
|
||||||
}
|
}
|
||||||
|
Send-Notification -title "TODAY'S TASKS" -content $content
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
Write-Host "Finding next notification time..."
|
||||||
|
foreach($time in $notificationTimes)
|
||||||
if ($overdueTasks.Count -ne 0)
|
|
||||||
{
|
|
||||||
Write-Host "Sending a notification for $($overdueTasks.Count) overdue tasks"
|
|
||||||
$content = "The following tasks are overdue!`n"
|
|
||||||
foreach($overdueTask in $overdueTasks)
|
|
||||||
{
|
{
|
||||||
$content += "$($overdueTask.Name) was due $(Get-Date $overdueTask.nextDueDate -Format "MM/dd/yyyy HH:mm")`n"
|
$now = Get-Date
|
||||||
|
$diff = $now.Hour - $time
|
||||||
|
if ($diff -lt 0) # next notification time
|
||||||
|
{
|
||||||
|
Write-Host "Next notification time is $time`:00"
|
||||||
|
$sleepTime = ($diff * -1) * 60
|
||||||
|
Write-Host "Sleeping for $sleepTime seconds"
|
||||||
|
Start-Sleep -Seconds $sleepTime
|
||||||
|
continue # leave loop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Send-Notification -title "OVERDUE TASKS" -content $content
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($todaysTasks.Count -ne 0)
|
|
||||||
{
|
|
||||||
Write-Host "Sending a notification for $($todaysTasks.Count) tasks due today"
|
|
||||||
$content = "The following tasks are due today!`n"
|
|
||||||
foreach($task in $todaysTasks)
|
|
||||||
{
|
|
||||||
$content += "$($task.Name) is due $(Get-Date $task.nextDueDate -Format "MM/dd/yyyy HH:mm")`n"
|
|
||||||
}
|
|
||||||
Send-Notification -title "TODAY'S TASKS" -content $content
|
|
||||||
}
|
}
|
||||||
+2
-1
@@ -9,4 +9,5 @@ services:
|
|||||||
- DONETICKPORT=8787 # donetick port
|
- DONETICKPORT=8787 # donetick port
|
||||||
- DONETICKAPIKEY=adminpass # donetick API key
|
- DONETICKAPIKEY=adminpass # donetick API key
|
||||||
- APPRISEWEBHOOKURL=https://apprisehost/notify/config # apprise notification url
|
- APPRISEWEBHOOKURL=https://apprisehost/notify/config # apprise notification url
|
||||||
- APPRISEWEBHOOKTAG=all # apprise notification tag
|
- APPRISEWEBHOOKTAG=all # apprise notification tag
|
||||||
|
- NOTIFICATIONTIMES=8,12,17 # hours when notifications will be sent
|
||||||
Reference in New Issue
Block a user