Skip to content

Commit

Permalink
Add support for active hours (#220)
Browse files Browse the repository at this point in the history
Adds active hours to restrict monitoring of a feed to a specific time
window during the day. Addresses #189

```YAML
feeds:
    - name: GitHub Status
      url: https://www.githubstatus.com/history.rss
      interval: 600
      active_hours:
        start_time: '09:30'
        end_time: '17:00'
```
  • Loading branch information
VerifiedJoseph authored Jul 17, 2024
1 parent 269547d commit 57b76d4
Show file tree
Hide file tree
Showing 19 changed files with 756 additions and 123 deletions.
34 changes: 30 additions & 4 deletions docs/feeds.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# Feeds File

A YAML file named `feeds.yaml` is used to configure the RSS, ATOM and JSON feeds that Vigilant should monitor.
A YAML file named `feeds.yaml` is used to configure the RSS, ATOM and JSON feeds that Vigilant should monitor. An [example file](../feeds.example.yaml) is available.

By default Vigilant looks for a `feeds.yaml` file in the project's main folder, this behavior can be overridden with an [environment variable](configuration.md#feeds-file).

An [example file](../feeds.example.yaml) is available.

Each entry in the YAML file must have a name, URL and interval parameter. All other parameters are optional.
Each entry in the YAML file must have a name, URL and interval parameter.

```YAML
feeds:
Expand All @@ -17,16 +15,44 @@ feeds:
- name: GitHub Status
url: https://www.githubstatus.com/history.rss
interval: 600
active_hours:
start_time: '09:30'
end_time: '17:00'
```
## Parameters
### Standard
| Name | Required | Description |
| ----------------- | -------- | ----------------------------------------------------------------------------- |
| `name` | **Yes** | Feed name |
| `url` | **Yes** | Feed URL |
| `interval` | **Yes** | Interval between feed checks in seconds. Minimum value is `300` (5 minutes). |
| `title_prefix` | No | Text to prepend to notification titles. |

### Notification services

| Name | Required | Description |
| ----------------- | -------- | ----------------------------------------------------------------------------- |
| `gotify_token` | No | Gotify application token. Overrides token set with an environment variable. |
| `gotify_priority` | No | Gotify message priority. Overrides default value and/or environment variable. |
| `ntfy_topic` | No | Ntfy topic. Overrides topic set with an environment variable. |
| `ntfy_token` | No | Ntfy access token. Overrides token set with an environment variable. |
| `ntfy_priority` | No | Ntfy message priority. Overrides default value and/or environment variable. |

### Active hours

Use active hours to restrict feed monitoring to a specific window of time.

Both parameters are required when configuring an active hours window.

| Name | Description |
| ------------------------ | ------------------------------------------------------------ |
| `active_hours.start_time`| Start time for active hours in 24-hour format. e.g: `09:00` |
| `active_hours.end_time` | End time for active hours in 24-hour format. e.g: `16:30` |

#### Limitations

- The active hours window must start and end on the same day.
- Only 24-hour time formats are supported.
7 changes: 7 additions & 0 deletions feeds.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@ feeds:
- name: Met Office weather warnings
url: http://www.metoffice.gov.uk/public/data/PWSCache/WarningsRSS/Region/UK
interval: 1900

- name: GitHub status
url: https://www.githubstatus.com/history.rss
interval: 600
active_hours:
start_time: 09:30
end_time: 17:00
86 changes: 86 additions & 0 deletions src/ActiveHours.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace Vigilant;

use DateTime;
use DateTimeZone;

class ActiveHours
{
private Logger $logger;

private DateTime $now;
private DateTime $start;
private DateTime $end;

private DateTimeZone $timezone;
private bool $enabled = false;

/**
* @param DateTime $now Current time and date
* @param ?string $startTime Start time
* @param ?string $endTime End time
* @param string $timezone Timezone
* @param Logger $logger
*/
public function __construct(DateTime $now, ?string $startTime, ?string $endTime, string $timezone, Logger $logger)
{
$this->logger = $logger;

$this->now = $now;
$this->timezone = new DateTimeZone($timezone);

$this->process($startTime, $endTime);
}

/**
* Returns boolean indicating if time is in active hours window
* @return bool
*/
public function isEnabled(): bool
{
return $this->enabled;
}

/**
* Returns start time
* @param string $format Format accepted by date()
* @return string
*/
public function getStartTime(string $format = 'Y-m-d H:i:s e'): string
{
return $this->start->format($format);
}

/**
* Returns end time
* @param string $format Format accepted by date()
* @return string
*/
public function getEndTime(string $format = 'Y-m-d H:i:s e'): string
{
return $this->end->format($format);
}

/**
* @param ?string $startTime Start time
* @param ?string $endTime End time
*/
private function process(?string $startTime, ?string $endTime): void
{
if ($startTime !== null && $endTime !== null) {
$this->start = new DateTime($startTime, $this->timezone);
$this->end = new DateTime($endTime, $this->timezone);

if ($this->now >= $this->start && $this->now <= $this->end) {
$this->enabled = true;
}

$this->logger->debug('Active hours details:');
$this->logger->debug('Current time: ' . $this->now->format('Y-m-d H:i:s e'));
$this->logger->debug('Start time: ' . $this->start->format('Y-m-d H:i:s e'));
$this->logger->debug('End time: ' . $this->end->format('Y-m-d H:i:s e'));
$this->logger->debug('Enabled: ' . ($this->enabled ? 'true' : 'false'));
}
}
}
7 changes: 4 additions & 3 deletions src/Check.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,17 @@ public function getMessages(): array
}

/**
* Returns next check date in readable format (`Y-m-d H:i:s`)
* Returns next check date
* @param string $format Format accepted by date()
* @return string
*/
public function getNextCheckDate(): string
public function getNextCheckDate(string $format = 'Y-m-d H:i:s'): string
{
$date = new DateTime();
$date->setTimestamp($this->cache->getNextCheck());
$date->setTimezone(new DateTimeZone($this->config->getTimezone()));

return $date->format('Y-m-d H:i:s');
return $date->format($format);
}

public function check(): void
Expand Down
51 changes: 40 additions & 11 deletions src/Feed/Details.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@

final class Details
{
/**
* @var array<string, mixed> $details Feed details from feeds.yaml
*/
/** @var array<string, mixed> $details Feed details from feeds.yaml */
private array $details = [];

/**
* Constructor
*
* @param array<string, mixed> $feed
*/
public function __construct(array $feed)
Expand Down Expand Up @@ -120,7 +116,40 @@ public function getNtfyPriority(): ?int
}

/**
* Has entry got a ntfy token
* Returns active hours start time
*
* @return ?string
*/
public function getActiveHoursStartTime(): ?string
{
return $this->details['active_hours']['start_time'] ?? null;
}

/**
* Returns active hours end time
*
* @return ?string
*/
public function getActiveHoursEndTime(): ?string
{
return $this->details['active_hours']['end_time'] ?? null;
}

/**
* Returns boolean indicating if active hours are configured for the feed
* @return bool
*/
public function hasActiveHours(): bool
{
if ($this->getActiveHoursStartTime() !== null && $this->getActiveHoursEndTime() !== null) {
return true;
}

return false;
}

/**
* Check if entry has a ntfy token parameter
*
* @return bool
*/
Expand All @@ -130,7 +159,7 @@ public function hasNtfyToken(): bool
}

/**
* Has entry got a ntfy topic
* Check if entry has a ntfy topic parameter
*
* @return bool
*/
Expand All @@ -140,7 +169,7 @@ public function hasNtfyTopic(): bool
}

/**
* Has entry got a ntfy priority
* Check if entry has a ntfy priority parameter
*
* @return bool
*/
Expand All @@ -150,7 +179,7 @@ public function hasNtfyPriority(): bool
}

/**
* Has entry got Gotify token
* Check if entry has a Gotify token parameter
*
* @return bool
*/
Expand All @@ -160,7 +189,7 @@ public function hasGotifyToken(): bool
}

/**
* Has entry got Gotify priority
* Check if entry has a Gotify priority parameter
*
* @return bool
*/
Expand All @@ -170,7 +199,7 @@ public function hasGotifyPriority(): bool
}

/**
* Has entry got a value
* heck if entry has a parameter
*
* @return bool
*/
Expand Down
67 changes: 48 additions & 19 deletions src/Feed/Feed.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,49 @@

namespace Vigilant\Feed;

use DateTime;
use DateTimeZone;
use Vigilant\Check;
use Vigilant\Fetch;
use Vigilant\ActiveHours;
use Vigilant\Config;
use Vigilant\Logger;
use Vigilant\Feed\Validate;
use Vigilant\Feed\Details;

final class Feed
{
/**
* @var Config
*/
/** @var Details Feed details class instance */
public Details $details;

/** @var ActiveHours ActiveHours class instance */
public ActiveHours $activeHours;

/** @var Check Check class instance */
public Check $check;

/** @var Config Config class instance */
private Config $config;

/**
* @var array<string, mixed> $feed Feed entry from feeds.yaml
*/
/** @var Logger Logger class instance */
private Logger $logger;

/** @var array<string, mixed> $feed Feed entry from feeds.yaml */
private array $feed = [];

/**
* Constructor
*
* @param array<string, mixed> $feed
* @param Config $config
* @param Logger $logger
*/
public function __construct(array $feed, Config $config)
public function __construct(array $feed, Config $config, Logger $logger)
{
$this->feed = $feed;
$this->config = $config;
$this->logger = $logger;

$this->validate();
}

/**
* Get details for feed entry
*
* @return Details
*/
public function getDetails(): Details
{
return new Details($this->feed);
$this->initiate();
}

/**
Expand All @@ -52,4 +57,28 @@ private function validate(): void
$this->config->getMinCheckInterval()
);
}

private function initiate(): void
{
$this->details = new Details($this->feed);
$this->check = new Check(
$this->details,
new Fetch(),
$this->config,
$this->logger
);

$now = new DateTime(
'now',
new DateTimeZone($this->config->getTimezone())
);

$this->activeHours = new ActiveHours(
$now,
$this->details->getActiveHoursStartTime(),
$this->details->getActiveHoursEndTime(),
$this->config->getTimezone(),
$this->logger
);
}
}
Loading

0 comments on commit 57b76d4

Please sign in to comment.