Skip to content

Commit 3df95af

Browse files
authored
feat: support random minutes per day with fixed total count (#10)
* feat: support random minutes per day with fixed total count * chore: bump version
1 parent 138feac commit 3df95af

7 files changed

Lines changed: 97 additions & 37 deletions

File tree

README.md

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,23 @@ schedule:
5757
```
5858

5959
## 完整参数说明
60-
| Configuration | Instruction | Default | Required |
61-
|-----------------|---------------------|---------|----------|
62-
| id | 任务的唯一标识 | | Yes |
63-
| url | 需要轮询的数据文件地址 | | Yes |
64-
| options | fetch的options | | No |
65-
| every | 每隔几分钟执行一次,默认每次执行 | 1 | No |
66-
| random | 执行时间是否加入随机Delay | No | No |
67-
| enable | 是否启用 | Yes | No |
68-
| record | 是否保存 | Yes | No |
69-
| filters | 文件差异比较时,需要忽略的属性 | | No |
70-
| condition | 文件差异比较时,需满足的额外条件 | | No |
71-
| format | 保存时是否格式化 | No | No |
72-
| notify | 是否启用通知 | No | No |
73-
| notifyCondition | 通知的额外条件 | | No |
74-
| errorCondition | 异常条件,满足时会记录以及发送消息通知 | | No |
60+
| Configuration | Instruction | Default | Required |
61+
|-----------------|---------------------------|---------|----------|
62+
| id | 任务的唯一标识 | | Yes |
63+
| url | 需要轮询的数据文件地址 | | Yes |
64+
| options | fetch的options | | No |
65+
| every | 每隔几分钟执行一次,默认每次执行 | 1 | No |
66+
| random | 执行时间(秒)是否加入随机Delay | False | No |
67+
| randomMin | 是否在随机分钟时执行,需配合perDay使用 | | No |
68+
| perDay | 每天随机运行的总次数,需配合randomMin使用 | | No |
69+
| enable | 是否启用 | True | No |
70+
| record | 是否保存 | True | No |
71+
| filters | 文件差异比较时,需要忽略的属性 | | No |
72+
| condition | 文件差异比较时,需满足的额外条件 | | No |
73+
| format | 保存时是否格式化 | False | No |
74+
| notify | 是否启用通知 | False | No |
75+
| notifyCondition | 通知的额外条件 | | No |
76+
| errorCondition | 异常条件,满足时会记录以及发送消息通知 | | No |
7577

7678
## Actions参数说明
7779
| Repository secrets | Instruction | Required |

README_en.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,24 @@ For example, Linux's cron:
5454
}
5555
```
5656

57-
## Full Parameter Description
58-
| Configuration | Instruction | Default | Required |
59-
|-----------------|----------------------------------------------------------|---------|----------|
60-
| id | Unique identifier for the task | | Yes |
61-
| url | URL of the data file to poll | | Yes |
62-
| options | Fetch options | | No |
63-
| every | Execution interval in minutes (default: every execution) | 1 | No |
64-
| random | Whether to add random delay to execution time | No | No |
65-
| enable | Whether to enable the task | Yes | No |
66-
| record | Whether to save the data | Yes | No |
67-
| filters | Properties to ignore during file comparison | | No |
68-
| condition | Additional conditions for file comparison | | No |
69-
| format | Whether to format the saved data | No | No |
70-
| notify | Whether to enable notifications | No | No |
71-
| notifyCondition | Additional conditions for notifications | | No |
72-
| errorCondition | Error conditions that trigger logging and notifications | | No |
57+
# Complete Parameter Description
58+
| Configuration | Instruction | Default | Required |
59+
|-----------------|----------------------------------------------------------------|---------|----------|
60+
| id | Unique identifier for the task | | Yes |
61+
| url | URL of the data file to poll | | Yes |
62+
| options | Fetch options | | No |
63+
| every | Execution interval in minutes (default: every execution) | 1 | No |
64+
| random | Whether to add random delay (in seconds) to execution time | False | No |
65+
| randomMin | Whether to execute at random minutes (requires perDay) | | No |
66+
| perDay | Total number of random executions per day (requires randomMin) | | No |
67+
| enable | Whether to enable the task | True | No |
68+
| record | Whether to save the data | True | No |
69+
| filters | Properties to ignore during file comparison | | No |
70+
| condition | Additional conditions for file comparison | | No |
71+
| format | Whether to format the saved data | False | No |
72+
| notify | Whether to enable notifications | False | No |
73+
| notifyCondition | Additional conditions for notifications | | No |
74+
| errorCondition | Error conditions that trigger logging and notifications | | No |
7375

7476
## Actions Parameter Description
7577
| Repository Secrets | Instruction | Required |

config.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
"id": "simple_get",
44
"url": "https://www.baidu.com"
55
},
6+
{
7+
"id": "10_times_daily_in_random_time",
8+
"url": "https://dummyjson.com/test",
9+
"random": true,
10+
"randomMin": true,
11+
"perDay": 10
12+
},
613
{
714
"id": "simple_get",
815
"url": "https://dummyjson.com/test",

detect.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import fs from 'fs';
22
import os from 'os';
3-
import {areJsonEqual, executeWithDelay, getCurrentDateTimeStringPath, readDataFile, writeDataFile} from "./utils.js";
3+
import {areJsonEqual, executeWithDelay, generateDailyMinutes, getCurrentDateTimeStringPath, readDataFile, writeDataFile} from "./utils.js";
44

55
const args = process.argv.slice(2);
66
const DATA_ROOT = args.length > 0 ? (!args[0].endsWith('/') ? args[0] + '/' : args[0]) : './';
@@ -11,10 +11,11 @@ const data = [];
1111

1212
const main = async (isRandom) => {
1313
console.log(`main(random:${!!isRandom}) start`);
14-
const minutes = new Date().getHours() * 60 + new Date().getMinutes();
14+
const date = new Date();
15+
const minutesOfDay = date.getHours() * 60 + date.getMinutes();
1516
const configs = readDataFile(`${DATA_ROOT}config.json`);
16-
for (const {id, url, options, format, filters, condition, notify, notifyCondition, errorCondition, every = 1, random, record = true, enable} of configs) {
17-
if (enable === false || minutes % every !== 0 || !!isRandom !== !!random) {
17+
for (const {id, url, options, format, filters, condition, notify, notifyCondition, errorCondition, every, random, record = true, randomMin, perDay, enable} of configs) {
18+
if (enable === false || !!isRandom !== !!random || (every && minutesOfDay % every !== 0) || (randomMin && perDay && !generateDailyMinutes(date, perDay).includes(minutesOfDay))) {
1819
console.log(`monitor id: ${id} skipped`);
1920
continue;
2021
}

notify.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ async function main() {
1717
method: 'POST',
1818
body: Object.entries(data).map(([key, value]) => `${key}=${value}`).join('&')
1919
};
20-
await fetch(`${notifyServer}/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2`, options);
20+
try {
21+
await fetch(`${notifyServer}/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2`, options);
22+
} catch (error) {
23+
console.error('Fetch request failed:', error.message);
24+
}
2125
} else {
2226
if (!notifyServer) console.log('notify_server required');
2327
if (!notifyToken) console.log('notify_token required');

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "monitor",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"description": "Monitor data file and record changed versions",
55
"type": "module",
66
"scripts": {

utils.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,47 @@ export const executeWithDelay = (fn, ...args) => {
107107
}, delay);
108108
});
109109
}
110+
111+
export const generateDailyMinutes = (date, count = 10) => {
112+
// 参数验证和规范化
113+
if (count < 1) count = 1;
114+
if (count > 1440) count = 1440;
115+
116+
// 将日期转换为一致的字符串格式(YYYY-MM-DD)
117+
const dateStr = typeof date === 'string' ? date : date.toISOString().slice(0, 10);
118+
const normalizedDate = new Date(dateStr + 'T00:00:00Z'); // 使用UTC时间确保一致性
119+
120+
// 创建确定性的种子(使用日期字符串的哈希值)
121+
let seed = 0;
122+
for (let i = 0; i < dateStr.length; i++) {
123+
seed = ((seed << 5) - seed) + dateStr.charCodeAt(i);
124+
seed = seed & seed; // 转换为32位整数
125+
}
126+
seed = Math.abs(seed);
127+
128+
// 使用确定性随机数生成器
129+
const minutes = new Set();
130+
let attempts = 0;
131+
const maxAttempts = count * 10; // 防止无限循环
132+
133+
while (minutes.size < count && attempts < maxAttempts) {
134+
// 简单的LCG算法,确保确定性
135+
seed = (seed * 1664525 + 1013904223) % 2147483647;
136+
137+
// 生成0-1439之间的分钟数
138+
const minute = Math.abs(seed) % 1440;
139+
minutes.add(minute);
140+
141+
attempts++;
142+
}
143+
144+
// 如果因为重复而无法生成足够数量,补充剩余的数字
145+
if (minutes.size < count) {
146+
for (let i = 0; i < 1440 && minutes.size < count; i++) {
147+
minutes.add(i);
148+
}
149+
}
150+
151+
// 转换为数组并排序
152+
return Array.from(minutes).sort((a, b) => a - b).slice(0, count);
153+
}

0 commit comments

Comments
 (0)