mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-13 15:07:49 +00:00
Compare commits
5 commits
d81c1b99f1
...
3cdc267809
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cdc267809 | ||
|
|
1298814521 | ||
|
|
a5cb38421e | ||
|
|
e6d66af298 | ||
|
|
d4b5cf99d5 |
10 changed files with 227 additions and 63 deletions
|
|
@ -20,6 +20,14 @@ class Device extends Model
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the MAC address attribute, normalizing to uppercase.
|
||||||
|
*/
|
||||||
|
public function setMacAddressAttribute(?string $value): void
|
||||||
|
{
|
||||||
|
$this->attributes['mac_address'] = $value ? mb_strtoupper($value) : null;
|
||||||
|
}
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'battery_notification_sent' => 'boolean',
|
'battery_notification_sent' => 'boolean',
|
||||||
'proxy_cloud' => 'boolean',
|
'proxy_cloud' => 'boolean',
|
||||||
|
|
|
||||||
|
|
@ -37,21 +37,32 @@ class Playlist extends Model
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check weekday
|
// Get user's timezone or fall back to app timezone
|
||||||
if ($this->weekdays !== null && ! in_array(now()->dayOfWeek, $this->weekdays)) {
|
$timezone = $this->device->user->timezone ?? config('app.timezone');
|
||||||
|
$now = now($timezone);
|
||||||
|
|
||||||
|
// Check weekday (using timezone-aware time)
|
||||||
|
if ($this->weekdays !== null && ! in_array($now->dayOfWeek, $this->weekdays)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->active_from !== null && $this->active_until !== null) {
|
if ($this->active_from !== null && $this->active_until !== null) {
|
||||||
$now = now();
|
// Create timezone-aware datetime objects for active_from and active_until
|
||||||
|
$activeFrom = $now->copy()
|
||||||
|
->setTimeFrom($this->active_from)
|
||||||
|
->timezone($timezone);
|
||||||
|
|
||||||
|
$activeUntil = $now->copy()
|
||||||
|
->setTimeFrom($this->active_until)
|
||||||
|
->timezone($timezone);
|
||||||
|
|
||||||
// Handle time ranges that span across midnight
|
// Handle time ranges that span across midnight
|
||||||
if ($this->active_from > $this->active_until) {
|
if ($activeFrom > $activeUntil) {
|
||||||
// Time range spans midnight (e.g., 09:01 to 03:58)
|
// Time range spans midnight (e.g., 09:01 to 03:58)
|
||||||
if ($now >= $this->active_from || $now <= $this->active_until) {
|
if ($now >= $activeFrom || $now <= $activeUntil) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} elseif ($now >= $this->active_from && $now <= $this->active_until) {
|
} elseif ($now >= $activeFrom && $now <= $activeUntil) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,13 @@ class Plugin extends Model
|
||||||
$model->uuid = Str::uuid();
|
$model->uuid = Str::uuid();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static::updating(function ($model): void {
|
||||||
|
// Reset image cache when markup changes
|
||||||
|
if ($model->isDirty('render_markup')) {
|
||||||
|
$model->current_image = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class IcalResponseParser implements ResponseParser
|
||||||
$filteredEvents = array_values(array_filter($events, function (array $event) use ($windowStart, $windowEnd): bool {
|
$filteredEvents = array_values(array_filter($events, function (array $event) use ($windowStart, $windowEnd): bool {
|
||||||
$startDate = $this->asCarbon($event['DTSTART'] ?? null);
|
$startDate = $this->asCarbon($event['DTSTART'] ?? null);
|
||||||
|
|
||||||
if (!$startDate instanceof \Carbon\Carbon) {
|
if (! $startDate instanceof Carbon) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
100
composer.lock
generated
100
composer.lock
generated
|
|
@ -62,16 +62,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "aws/aws-sdk-php",
|
"name": "aws/aws-sdk-php",
|
||||||
"version": "3.369.1",
|
"version": "3.369.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||||
"reference": "b2d04cf1184a96839a8ab62ec6e3cf2d62a278e3"
|
"reference": "2aa1ef195e90140d733382e4341732ce113024f5"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/b2d04cf1184a96839a8ab62ec6e3cf2d62a278e3",
|
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2aa1ef195e90140d733382e4341732ce113024f5",
|
||||||
"reference": "b2d04cf1184a96839a8ab62ec6e3cf2d62a278e3",
|
"reference": "2aa1ef195e90140d733382e4341732ce113024f5",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -85,7 +85,7 @@
|
||||||
"mtdowling/jmespath.php": "^2.8.0",
|
"mtdowling/jmespath.php": "^2.8.0",
|
||||||
"php": ">=8.1",
|
"php": ">=8.1",
|
||||||
"psr/http-message": "^1.0 || ^2.0",
|
"psr/http-message": "^1.0 || ^2.0",
|
||||||
"symfony/filesystem": "^v6.4.3 || ^v7.1.0 || ^v8.0.0"
|
"symfony/filesystem": "^v5.4.45 || ^v6.4.3 || ^v7.1.0 || ^v8.0.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"andrewsville/php-token-reflection": "^1.4",
|
"andrewsville/php-token-reflection": "^1.4",
|
||||||
|
|
@ -153,9 +153,9 @@
|
||||||
"support": {
|
"support": {
|
||||||
"forum": "https://github.com/aws/aws-sdk-php/discussions",
|
"forum": "https://github.com/aws/aws-sdk-php/discussions",
|
||||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.369.1"
|
"source": "https://github.com/aws/aws-sdk-php/tree/3.369.4"
|
||||||
},
|
},
|
||||||
"time": "2025-12-22T19:13:21+00:00"
|
"time": "2025-12-29T19:07:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bnussbau/laravel-trmnl-blade",
|
"name": "bnussbau/laravel-trmnl-blade",
|
||||||
|
|
@ -950,24 +950,24 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "graham-campbell/result-type",
|
"name": "graham-campbell/result-type",
|
||||||
"version": "v1.1.3",
|
"version": "v1.1.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/GrahamCampbell/Result-Type.git",
|
"url": "https://github.com/GrahamCampbell/Result-Type.git",
|
||||||
"reference": "3ba905c11371512af9d9bdd27d99b782216b6945"
|
"reference": "e01f4a821471308ba86aa202fed6698b6b695e3b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945",
|
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b",
|
||||||
"reference": "3ba905c11371512af9d9bdd27d99b782216b6945",
|
"reference": "e01f4a821471308ba86aa202fed6698b6b695e3b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.2.5 || ^8.0",
|
"php": "^7.2.5 || ^8.0",
|
||||||
"phpoption/phpoption": "^1.9.3"
|
"phpoption/phpoption": "^1.9.5"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28"
|
"phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -996,7 +996,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/GrahamCampbell/Result-Type/issues",
|
"issues": "https://github.com/GrahamCampbell/Result-Type/issues",
|
||||||
"source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3"
|
"source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -1008,7 +1008,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-07-20T21:45:45+00:00"
|
"time": "2025-12-27T19:43:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/guzzle",
|
"name": "guzzlehttp/guzzle",
|
||||||
|
|
@ -1617,16 +1617,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/framework",
|
"name": "laravel/framework",
|
||||||
"version": "v12.43.1",
|
"version": "v12.44.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/framework.git",
|
"url": "https://github.com/laravel/framework.git",
|
||||||
"reference": "195b893593a9298edee177c0844132ebaa02102f"
|
"reference": "592bbf1c036042958332eb98e3e8131b29102f33"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/framework/zipball/195b893593a9298edee177c0844132ebaa02102f",
|
"url": "https://api.github.com/repos/laravel/framework/zipball/592bbf1c036042958332eb98e3e8131b29102f33",
|
||||||
"reference": "195b893593a9298edee177c0844132ebaa02102f",
|
"reference": "592bbf1c036042958332eb98e3e8131b29102f33",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -1835,7 +1835,7 @@
|
||||||
"issues": "https://github.com/laravel/framework/issues",
|
"issues": "https://github.com/laravel/framework/issues",
|
||||||
"source": "https://github.com/laravel/framework"
|
"source": "https://github.com/laravel/framework"
|
||||||
},
|
},
|
||||||
"time": "2025-12-16T18:53:08+00:00"
|
"time": "2025-12-23T15:29:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/prompts",
|
"name": "laravel/prompts",
|
||||||
|
|
@ -3885,16 +3885,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpoption/phpoption",
|
"name": "phpoption/phpoption",
|
||||||
"version": "1.9.4",
|
"version": "1.9.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/schmittjoh/php-option.git",
|
"url": "https://github.com/schmittjoh/php-option.git",
|
||||||
"reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d"
|
"reference": "75365b91986c2405cf5e1e012c5595cd487a98be"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d",
|
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be",
|
||||||
"reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d",
|
"reference": "75365b91986c2405cf5e1e012c5595cd487a98be",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -3944,7 +3944,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/schmittjoh/php-option/issues",
|
"issues": "https://github.com/schmittjoh/php-option/issues",
|
||||||
"source": "https://github.com/schmittjoh/php-option/tree/1.9.4"
|
"source": "https://github.com/schmittjoh/php-option/tree/1.9.5"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -3956,7 +3956,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-08-21T11:53:16+00:00"
|
"time": "2025-12-27T19:41:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpseclib/phpseclib",
|
"name": "phpseclib/phpseclib",
|
||||||
|
|
@ -7723,26 +7723,26 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "vlucas/phpdotenv",
|
"name": "vlucas/phpdotenv",
|
||||||
"version": "v5.6.2",
|
"version": "v5.6.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/vlucas/phpdotenv.git",
|
"url": "https://github.com/vlucas/phpdotenv.git",
|
||||||
"reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af"
|
"reference": "955e7815d677a3eaa7075231212f2110983adecc"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
|
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc",
|
||||||
"reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
|
"reference": "955e7815d677a3eaa7075231212f2110983adecc",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-pcre": "*",
|
"ext-pcre": "*",
|
||||||
"graham-campbell/result-type": "^1.1.3",
|
"graham-campbell/result-type": "^1.1.4",
|
||||||
"php": "^7.2.5 || ^8.0",
|
"php": "^7.2.5 || ^8.0",
|
||||||
"phpoption/phpoption": "^1.9.3",
|
"phpoption/phpoption": "^1.9.5",
|
||||||
"symfony/polyfill-ctype": "^1.24",
|
"symfony/polyfill-ctype": "^1.26",
|
||||||
"symfony/polyfill-mbstring": "^1.24",
|
"symfony/polyfill-mbstring": "^1.26",
|
||||||
"symfony/polyfill-php80": "^1.24"
|
"symfony/polyfill-php80": "^1.26"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"bamarni/composer-bin-plugin": "^1.8.2",
|
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||||
|
|
@ -7791,7 +7791,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/vlucas/phpdotenv/issues",
|
"issues": "https://github.com/vlucas/phpdotenv/issues",
|
||||||
"source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2"
|
"source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -7803,7 +7803,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-04-30T23:37:27+00:00"
|
"time": "2025-12-27T19:49:13+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "voku/portable-ascii",
|
"name": "voku/portable-ascii",
|
||||||
|
|
@ -10122,16 +10122,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-code-coverage",
|
"name": "phpunit/php-code-coverage",
|
||||||
"version": "12.5.1",
|
"version": "12.5.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||||
"reference": "c467c59a4f6e04b942be422844e7a6352fa01b57"
|
"reference": "4a9739b51cbcb355f6e95659612f92e282a7077b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c467c59a4f6e04b942be422844e7a6352fa01b57",
|
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4a9739b51cbcb355f6e95659612f92e282a7077b",
|
||||||
"reference": "c467c59a4f6e04b942be422844e7a6352fa01b57",
|
"reference": "4a9739b51cbcb355f6e95659612f92e282a7077b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -10146,7 +10146,7 @@
|
||||||
"sebastian/environment": "^8.0.3",
|
"sebastian/environment": "^8.0.3",
|
||||||
"sebastian/lines-of-code": "^4.0",
|
"sebastian/lines-of-code": "^4.0",
|
||||||
"sebastian/version": "^6.0",
|
"sebastian/version": "^6.0",
|
||||||
"theseer/tokenizer": "^2.0"
|
"theseer/tokenizer": "^2.0.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^12.5.1"
|
"phpunit/phpunit": "^12.5.1"
|
||||||
|
|
@ -10187,7 +10187,7 @@
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||||
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
||||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.1"
|
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.2"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -10207,7 +10207,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-12-08T07:17:58+00:00"
|
"time": "2025-12-24T07:03:04+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-file-iterator",
|
"name": "phpunit/php-file-iterator",
|
||||||
|
|
@ -10561,16 +10561,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "rector/rector",
|
"name": "rector/rector",
|
||||||
"version": "2.2.14",
|
"version": "2.3.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/rectorphp/rector.git",
|
"url": "https://github.com/rectorphp/rector.git",
|
||||||
"reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d"
|
"reference": "f7166355dcf47482f27be59169b0825995f51c7d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/rectorphp/rector/zipball/6d56bb0e94d4df4f57a78610550ac76ab403657d",
|
"url": "https://api.github.com/repos/rectorphp/rector/zipball/f7166355dcf47482f27be59169b0825995f51c7d",
|
||||||
"reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d",
|
"reference": "f7166355dcf47482f27be59169b0825995f51c7d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -10609,7 +10609,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/rectorphp/rector/issues",
|
"issues": "https://github.com/rectorphp/rector/issues",
|
||||||
"source": "https://github.com/rectorphp/rector/tree/2.2.14"
|
"source": "https://github.com/rectorphp/rector/tree/2.3.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -10617,7 +10617,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-12-09T10:57:55+00:00"
|
"time": "2025-12-25T22:00:18+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/cli-parser",
|
"name": "sebastian/cli-parser",
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ class DevicePaletteFactory extends Factory
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => 'test-' . $this->faker->unique()->slug(),
|
'id' => 'test-'.$this->faker->unique()->slug(),
|
||||||
'name' => $this->faker->words(3, true),
|
'name' => $this->faker->words(3, true),
|
||||||
'grays' => $this->faker->randomElement([2, 4, 16, 256]),
|
'grays' => $this->faker->randomElement([2, 4, 16, 256]),
|
||||||
'colors' => $this->faker->optional()->passthrough([
|
'colors' => $this->faker->optional()->passthrough([
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ use Illuminate\Support\Str;
|
||||||
Route::get('/display', function (Request $request) {
|
Route::get('/display', function (Request $request) {
|
||||||
$mac_address = $request->header('id');
|
$mac_address = $request->header('id');
|
||||||
$access_token = $request->header('access-token');
|
$access_token = $request->header('access-token');
|
||||||
$device = Device::where('mac_address', $mac_address)
|
$device = Device::where('mac_address', mb_strtoupper($mac_address ?? ''))
|
||||||
->where('api_key', $access_token)
|
->where('api_key', $access_token)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ Route::get('/display', function (Request $request) {
|
||||||
if ($auto_assign_user) {
|
if ($auto_assign_user) {
|
||||||
// Create a new device and assign it to this user
|
// Create a new device and assign it to this user
|
||||||
$device = Device::create([
|
$device = Device::create([
|
||||||
'mac_address' => $mac_address,
|
'mac_address' => mb_strtoupper($mac_address ?? ''),
|
||||||
'api_key' => $access_token,
|
'api_key' => $access_token,
|
||||||
'user_id' => $auto_assign_user->id,
|
'user_id' => $auto_assign_user->id,
|
||||||
'name' => "{$auto_assign_user->name}'s TRMNL",
|
'name' => "{$auto_assign_user->name}'s TRMNL",
|
||||||
|
|
@ -204,7 +204,7 @@ Route::get('/setup', function (Request $request) {
|
||||||
], 404);
|
], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$device = Device::where('mac_address', $mac_address)->first();
|
$device = Device::where('mac_address', mb_strtoupper($mac_address))->first();
|
||||||
|
|
||||||
if (! $device) {
|
if (! $device) {
|
||||||
// Check if there's a user with assign_new_devices enabled
|
// Check if there's a user with assign_new_devices enabled
|
||||||
|
|
@ -219,7 +219,7 @@ Route::get('/setup', function (Request $request) {
|
||||||
|
|
||||||
// Create a new device and assign it to this user
|
// Create a new device and assign it to this user
|
||||||
$device = Device::create([
|
$device = Device::create([
|
||||||
'mac_address' => $mac_address,
|
'mac_address' => mb_strtoupper($mac_address),
|
||||||
'api_key' => Str::random(22),
|
'api_key' => Str::random(22),
|
||||||
'user_id' => $auto_assign_user->id,
|
'user_id' => $auto_assign_user->id,
|
||||||
'name' => "{$auto_assign_user->name}'s TRMNL",
|
'name' => "{$auto_assign_user->name}'s TRMNL",
|
||||||
|
|
@ -345,7 +345,7 @@ Route::post('/display/update', function (Request $request) {
|
||||||
Route::post('/screens', function (Request $request) {
|
Route::post('/screens', function (Request $request) {
|
||||||
$mac_address = $request->header('id');
|
$mac_address = $request->header('id');
|
||||||
$access_token = $request->header('access-token');
|
$access_token = $request->header('access-token');
|
||||||
$device = Device::where('mac_address', $mac_address)
|
$device = Device::where('mac_address', mb_strtoupper($mac_address ?? ''))
|
||||||
->where('api_key', $access_token)
|
->where('api_key', $access_token)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -954,3 +954,72 @@ test('setup endpoint handles non-existent device model gracefully', function ():
|
||||||
expect($device)->not->toBeNull()
|
expect($device)->not->toBeNull()
|
||||||
->and($device->device_model_id)->toBeNull();
|
->and($device->device_model_id)->toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('setup endpoint matches MAC address case-insensitively', function (): void {
|
||||||
|
// Create device with lowercase MAC address
|
||||||
|
$device = Device::factory()->create([
|
||||||
|
'mac_address' => 'a1:b2:c3:d4:e5:f6',
|
||||||
|
'api_key' => 'test-api-key',
|
||||||
|
'friendly_id' => 'test-device',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Request with uppercase MAC address should still match
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'id' => 'A1:B2:C3:D4:E5:F6',
|
||||||
|
])->get('/api/setup');
|
||||||
|
|
||||||
|
$response->assertOk()
|
||||||
|
->assertJson([
|
||||||
|
'status' => 200,
|
||||||
|
'api_key' => 'test-api-key',
|
||||||
|
'friendly_id' => 'test-device',
|
||||||
|
'message' => 'Welcome to TRMNL BYOS',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('display endpoint matches MAC address case-insensitively', function (): void {
|
||||||
|
// Create device with lowercase MAC address
|
||||||
|
$device = Device::factory()->create([
|
||||||
|
'mac_address' => 'a1:b2:c3:d4:e5:f6',
|
||||||
|
'api_key' => 'test-api-key',
|
||||||
|
'current_screen_image' => 'test-image',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Request with uppercase MAC address should still match
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'id' => 'A1:B2:C3:D4:E5:F6',
|
||||||
|
'access-token' => $device->api_key,
|
||||||
|
'rssi' => -70,
|
||||||
|
'battery_voltage' => 3.8,
|
||||||
|
'fw-version' => '1.0.0',
|
||||||
|
])->get('/api/display');
|
||||||
|
|
||||||
|
$response->assertOk()
|
||||||
|
->assertJson([
|
||||||
|
'status' => '0',
|
||||||
|
'filename' => 'test-image.bmp',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('screens endpoint matches MAC address case-insensitively', function (): void {
|
||||||
|
Queue::fake();
|
||||||
|
|
||||||
|
// Create device with uppercase MAC address
|
||||||
|
$device = Device::factory()->create([
|
||||||
|
'mac_address' => 'A1:B2:C3:D4:E5:F6',
|
||||||
|
'api_key' => 'test-api-key',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Request with lowercase MAC address should still match
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'id' => 'a1:b2:c3:d4:e5:f6',
|
||||||
|
'access-token' => $device->api_key,
|
||||||
|
])->post('/api/screens', [
|
||||||
|
'image' => [
|
||||||
|
'content' => '<div>Test content</div>',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response->assertOk();
|
||||||
|
Queue::assertPushed(GenerateScreenJob::class);
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -324,6 +324,30 @@ it('resetIfNotCacheable preserves image for standard devices', function (): void
|
||||||
expect($plugin->current_image)->toBe('test-uuid');
|
expect($plugin->current_image)->toBe('test-uuid');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('cache is reset when plugin markup changes', function (): void {
|
||||||
|
// Create a plugin with cached image
|
||||||
|
$plugin = App\Models\Plugin::factory()->create([
|
||||||
|
'current_image' => 'cached-uuid',
|
||||||
|
'render_markup' => '<div>Original markup</div>',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Create devices with standard dimensions (cacheable)
|
||||||
|
Device::factory()->count(2)->create([
|
||||||
|
'width' => 800,
|
||||||
|
'height' => 480,
|
||||||
|
'rotate' => 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Update the plugin markup
|
||||||
|
$plugin->update([
|
||||||
|
'render_markup' => '<div>Updated markup</div>',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Assert cache was reset when markup changed
|
||||||
|
$plugin->refresh();
|
||||||
|
expect($plugin->current_image)->toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('determines correct image format from device model', function (): void {
|
it('determines correct image format from device model', function (): void {
|
||||||
// Test BMP format detection
|
// Test BMP format detection
|
||||||
$bmpModel = DeviceModel::factory()->create([
|
$bmpModel = DeviceModel::factory()->create([
|
||||||
|
|
|
||||||
|
|
@ -130,3 +130,48 @@ test('playlist isActiveNow handles normal time ranges correctly', function (): v
|
||||||
Carbon::setTestNow(Carbon::create(2024, 1, 1, 20, 0, 0));
|
Carbon::setTestNow(Carbon::create(2024, 1, 1, 20, 0, 0));
|
||||||
expect($playlist->isActiveNow())->toBeFalse();
|
expect($playlist->isActiveNow())->toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('playlist scheduling respects user timezone preference', function (): void {
|
||||||
|
// Create a user with a timezone that's UTC+1 (e.g., Europe/Berlin)
|
||||||
|
// This simulates the bug where setting 00:15 doesn't work until one hour later
|
||||||
|
$user = User::factory()->create([
|
||||||
|
'timezone' => 'Europe/Berlin', // UTC+1 in winter, UTC+2 in summer
|
||||||
|
]);
|
||||||
|
|
||||||
|
$device = Device::factory()->create(['user_id' => $user->id]);
|
||||||
|
|
||||||
|
// Create a playlist that should be active from 00:15 to 01:00 in the user's timezone
|
||||||
|
$playlist = Playlist::factory()->create([
|
||||||
|
'device_id' => $device->id,
|
||||||
|
'is_active' => true,
|
||||||
|
'active_from' => '00:15',
|
||||||
|
'active_until' => '01:00',
|
||||||
|
'weekdays' => null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Set test time to 00:15 in the user's timezone (Europe/Berlin)
|
||||||
|
// In January, Europe/Berlin is UTC+1, so 00:15 Berlin time = 23:15 UTC the previous day
|
||||||
|
// But Carbon::setTestNow uses UTC by default, so we need to set it to the UTC equivalent
|
||||||
|
// For January 1, 2024 at 00:15 Berlin time (UTC+1), that's December 31, 2023 at 23:15 UTC
|
||||||
|
$berlinTime = Carbon::create(2024, 1, 1, 0, 15, 0, 'Europe/Berlin');
|
||||||
|
Carbon::setTestNow($berlinTime->utc());
|
||||||
|
|
||||||
|
// The playlist should be active at 00:15 in the user's timezone
|
||||||
|
// This test should pass after the fix, but will fail with the current bug
|
||||||
|
expect($playlist->isActiveNow())->toBeTrue();
|
||||||
|
|
||||||
|
// Test at 00:30 in user's timezone - should still be active
|
||||||
|
$berlinTime = Carbon::create(2024, 1, 1, 0, 30, 0, 'Europe/Berlin');
|
||||||
|
Carbon::setTestNow($berlinTime->utc());
|
||||||
|
expect($playlist->isActiveNow())->toBeTrue();
|
||||||
|
|
||||||
|
// Test at 01:15 in user's timezone - should NOT be active (past the end time)
|
||||||
|
$berlinTime = Carbon::create(2024, 1, 1, 1, 15, 0, 'Europe/Berlin');
|
||||||
|
Carbon::setTestNow($berlinTime->utc());
|
||||||
|
expect($playlist->isActiveNow())->toBeFalse();
|
||||||
|
|
||||||
|
// Test at 00:10 in user's timezone - should NOT be active (before start time)
|
||||||
|
$berlinTime = Carbon::create(2024, 1, 1, 0, 10, 0, 'Europe/Berlin');
|
||||||
|
Carbon::setTestNow($berlinTime->utc());
|
||||||
|
expect($playlist->isActiveNow())->toBeFalse();
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue