natureco-cli 5.20.4 → 5.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,200 +1,200 @@
1
- /**
2
- * mac_alarm - macOS Clock app ile alarm kur (v5.1.1)
3
- *
4
- * macOS alarm — saat uygulamasi uzerinden alarm kurar
5
- * Eski reminder_add date parse edemiyordu. Bu tool AppleScript ile
6
- * Clock.app'in events sistemine yazar (alarm orada saklanir).
7
- */
8
-
9
- const { spawn } = require("child_process");
10
- const os = require("os");
11
-
12
- const IS_MAC = os.platform() === "darwin";
13
-
14
- function runAppleScript(script) {
15
- return new Promise((resolve, reject) => {
16
- const proc = spawn("osascript", ["-e", script]);
17
- let out = ""; let err = "";
18
- proc.stdout.on("data", d => out += d);
19
- proc.stderr.on("data", d => err += d);
20
- proc.on("close", code => code === 0 ? resolve(out.trim()) : reject(new Error(err.trim() || "osascript error")));
21
- });
22
- }
23
-
24
- /**
25
- * Tarih/saat ayristir — esnek formatlar kabul eder
26
- * @param input - "18:00", "18:30 tomorrow", "2026-06-22 18:00", "+1 hour"
27
- * @returns { hours, minutes, date, formattedDate, formattedTime }
28
- */
29
- function parseAlarmTime(input) {
30
- const now = new Date();
31
- let target = new Date();
32
- let hours = 0, minutes = 0;
33
-
34
- // Format: "18:00" veya "18:30 tomorrow"
35
- const hmMatch = input.match(/(\d{1,2}):(\d{2})(?:\s+(tomorrow|yarın|today|bugün|next\s+(\w+)))?/i);
36
- if (hmMatch) {
37
- hours = parseInt(hmMatch[1]);
38
- minutes = parseInt(hmMatch[2]);
39
- const dayShift = hmMatch[3];
40
- if (dayShift && /tomorrow|yarın/i.test(dayShift)) {
41
- target.setDate(target.getDate() + 1);
42
- }
43
- } else if (input.match(/^\d{1,2}$/)) {
44
- hours = parseInt(input);
45
- minutes = 0;
46
- } else if (input.match(/^\+(\d+)\s*(hour|minute|day)/i)) {
47
- const m = input.match(/\+(\d+)\s*(hour|minute|day)/i);
48
- const n = parseInt(m[1]);
49
- const unit = m[2].toLowerCase();
50
- if (unit === "hour") target.setHours(target.getHours() + n);
51
- else if (unit === "minute") target.setMinutes(target.getMinutes() + n);
52
- else if (unit === "day") target.setDate(target.getDate() + n);
53
- hours = target.getHours();
54
- minutes = target.getMinutes();
55
- } else {
56
- // ISO date parse
57
- const parsed = new Date(input);
58
- if (!isNaN(parsed)) {
59
- target = parsed;
60
- hours = target.getHours();
61
- minutes = target.getMinutes();
62
- } else {
63
- throw new Error("Gecersiz zaman formati. Ornekler: '18:00', 'tomorrow 09:30', '+1 hour', '2026-06-23 07:00'");
64
- }
65
- }
66
-
67
- // Eger saat dakika parse edildiyse target'a uygula
68
- if (hmMatch) {
69
- target.setHours(hours, minutes, 0, 0);
70
- }
71
-
72
- const pad = (n) => String(n).padStart(2, "0");
73
- return {
74
- hours, minutes,
75
- date: target.toISOString().slice(0, 10),
76
- formattedDate: `${pad(target.getMonth() + 1)}/${pad(target.getDate())}/${target.getFullYear()}`,
77
- formattedTime: `${pad(hours)}:${pad(minutes)}:00`,
78
- humanReadable: target.toLocaleString("tr-TR"),
79
- timestamp: target.getTime(),
80
- };
81
- }
82
-
83
- async function setAlarm({ time, label = "Alarm", calendarName = "Calendar" }) {
84
- if (!IS_MAC) return { success: false, error: "Bu tool sadece macOS'ta calisir" };
85
- if (!time) return { success: false, error: "time gerekli (ornek: '18:00', 'tomorrow 09:30', '+1 hour')" };
86
-
87
- let parsed;
88
- try { parsed = parseAlarmTime(time); }
89
- catch (e) { return { success: false, error: e.message }; }
90
-
91
- // AppleScript ile macOS Calendar'a all-day etkinlik olarak alarm ekle
92
- // (Reminder ile ayni sonuc, daha guvenilir cunku Calendar otomasyon izni Reminders'dan once verilir)
93
- // Dual: Calendar event (gorunurluk) + Reminders (bildirim + alarm)
94
- // Once Calendar'a basit etkinlik (alarm'siz, ama gorunur), sonra Reminders alarm
95
- const calendarScript = `
96
- tell application "Calendar"
97
- set targetCal to first calendar whose writable is true
98
- set startDate to date "${parsed.formattedDate} ${parsed.formattedTime}"
99
- set endDate to startDate + (1 * minutes)
100
- set newEvent to make new event at end of events of targetCal with properties {summary:"⏰ ${label.replace(/"/g, "'")} - NatureCo", start date:startDate, end date:endDate, allday event:false}
101
- save
102
- return id of newEvent
103
- end tell
104
- `;
105
-
106
- // Reminders'a bildirim + sesli alarm
107
- const reminderScript = `
108
- tell application "Reminders"
109
- set targetList to default list
110
- set startDate to date "${parsed.formattedDate} ${parsed.formattedTime}"
111
- set newReminder to make new reminder at end of targetList with properties {name:"⏰ ${label.replace(/"/g, "'")} - NatureCo", body:"NatureCo CLI tarafindan ${parsed.humanReadable} icin kuruldu", due date:startDate}
112
- save
113
- return id of newReminder
114
- end tell
115
- `;
116
-
117
- try {
118
- const results = { calendar: null, reminders: null, errors: [] };
119
-
120
- // Calendar'a ekle (gorunurluk)
121
- try {
122
- results.calendar = await runAppleScript(calendarScript);
123
- } catch (e) {
124
- results.errors.push(`Calendar: ${e.message}`);
125
- }
126
-
127
- // Reminders'a ekle (bildirim + sesli alarm)
128
- try {
129
- results.reminders = await runAppleScript(reminderScript);
130
- } catch (e) {
131
- results.errors.push(`Reminders: ${e.message}`);
132
- }
133
-
134
- const success = !!(results.calendar || results.reminders);
135
- return {
136
- success,
137
- eventId: results.reminders || results.calendar,
138
- calendarEventId: results.calendar,
139
- reminderId: results.reminders,
140
- message: success
141
- ? `⏰ Alarm kuruldu: ${parsed.humanReadable} — "${label}"`
142
- : `Alarm kurulamadi: ${results.errors.join('; ')}`,
143
- calendar: calendarName,
144
- targetTime: parsed.humanReadable,
145
- targetTimestamp: parsed.timestamp,
146
- errors: results.errors.length > 0 ? results.errors : undefined,
147
- };
148
- } catch (e) {
149
- if (e.message.includes("-1728") || e.message.includes("not authorized")) {
150
- return {
151
- success: false,
152
- error: "Calendar erisim izni yok. System Preferences -> Security & Privacy -> Privacy -> Automation -> natureco -> Calendar -> ON",
153
- };
154
- }
155
- return { success: false, error: e.message };
156
- }
157
- }
158
-
159
- async function listAlarms() {
160
- if (!IS_MAC) return { success: false, error: "Sadece macOS" };
161
- const script = `
162
- tell application "Calendar"
163
- set nowDate to current date
164
- set futureEvents to {}
165
- repeat with cal in calendars
166
- repeat with e in events of cal
167
- if start date of e > nowDate and (summary of e starts with "⏰") then
168
- copy (start date of e as string) & " | " & (summary of e) to end of futureEvents
169
- end if
170
- end repeat
171
- end repeat
172
- return futureEvents
173
- end tell
174
- `;
175
- try {
176
- const result = await runAppleScript(script);
177
- const alarms = result.split(", ").filter(Boolean);
178
- return { success: true, count: alarms.length, alarms };
179
- } catch (e) {
180
- return { success: false, error: e.message };
181
- }
182
- }
183
-
184
- module.exports = {
185
- name: "mac_alarm",
186
- description: "macOS Clock/Calendar uzerinden alarm kur. '18:00', 'tomorrow 09:30', '+1 hour' gibi formatlari kabul eder.",
187
- inputSchema: {
188
- type: "object",
189
- properties: {
190
- action: { type: "string", description: "set/list (default: set)", enum: ["set", "list"] },
191
- time: { type: "string", description: "Alarm zamani: '18:00', 'tomorrow 09:30', '+1 hour', '2026-06-23 07:00'" },
192
- label: { type: "string", description: "Alarm etiketi (default: 'Alarm')" },
193
- },
194
- required: [],
195
- },
196
- async execute(params) {
197
- if (params.action === "list") return listAlarms();
198
- return setAlarm(params);
199
- },
1
+ /**
2
+ * mac_alarm - macOS Clock app ile alarm kur (v5.1.1)
3
+ *
4
+ * macOS alarm — saat uygulamasi uzerinden alarm kurar
5
+ * Eski reminder_add date parse edemiyordu. Bu tool AppleScript ile
6
+ * Clock.app'in events sistemine yazar (alarm orada saklanir).
7
+ */
8
+
9
+ const { spawn } = require("child_process");
10
+ const os = require("os");
11
+
12
+ const IS_MAC = os.platform() === "darwin";
13
+
14
+ function runAppleScript(script) {
15
+ return new Promise((resolve, reject) => {
16
+ const proc = spawn("osascript", ["-e", script]);
17
+ let out = ""; let err = "";
18
+ proc.stdout.on("data", d => out += d);
19
+ proc.stderr.on("data", d => err += d);
20
+ proc.on("close", code => code === 0 ? resolve(out.trim()) : reject(new Error(err.trim() || "osascript error")));
21
+ });
22
+ }
23
+
24
+ /**
25
+ * Tarih/saat ayristir — esnek formatlar kabul eder
26
+ * @param input - "18:00", "18:30 tomorrow", "2026-06-22 18:00", "+1 hour"
27
+ * @returns { hours, minutes, date, formattedDate, formattedTime }
28
+ */
29
+ function parseAlarmTime(input) {
30
+ const now = new Date();
31
+ let target = new Date();
32
+ let hours, minutes;
33
+
34
+ // Format: "18:00" veya "18:30 tomorrow"
35
+ const hmMatch = input.match(/(\d{1,2}):(\d{2})(?:\s+(tomorrow|yarın|today|bugün|next\s+(\w+)))?/i);
36
+ if (hmMatch) {
37
+ hours = parseInt(hmMatch[1]);
38
+ minutes = parseInt(hmMatch[2]);
39
+ const dayShift = hmMatch[3];
40
+ if (dayShift && /tomorrow|yarın/i.test(dayShift)) {
41
+ target.setDate(target.getDate() + 1);
42
+ }
43
+ } else if (input.match(/^\d{1,2}$/)) {
44
+ hours = parseInt(input);
45
+ minutes = 0;
46
+ } else if (input.match(/^\+(\d+)\s*(hour|minute|day)/i)) {
47
+ const m = input.match(/\+(\d+)\s*(hour|minute|day)/i);
48
+ const n = parseInt(m[1]);
49
+ const unit = m[2].toLowerCase();
50
+ if (unit === "hour") target.setHours(target.getHours() + n);
51
+ else if (unit === "minute") target.setMinutes(target.getMinutes() + n);
52
+ else if (unit === "day") target.setDate(target.getDate() + n);
53
+ hours = target.getHours();
54
+ minutes = target.getMinutes();
55
+ } else {
56
+ // ISO date parse
57
+ const parsed = new Date(input);
58
+ if (!isNaN(parsed)) {
59
+ target = parsed;
60
+ hours = target.getHours();
61
+ minutes = target.getMinutes();
62
+ } else {
63
+ throw new Error("Gecersiz zaman formati. Ornekler: '18:00', 'tomorrow 09:30', '+1 hour', '2026-06-23 07:00'");
64
+ }
65
+ }
66
+
67
+ // Eger saat dakika parse edildiyse target'a uygula
68
+ if (hmMatch) {
69
+ target.setHours(hours, minutes, 0, 0);
70
+ }
71
+
72
+ const pad = (n) => String(n).padStart(2, "0");
73
+ return {
74
+ hours, minutes,
75
+ date: target.toISOString().slice(0, 10),
76
+ formattedDate: `${pad(target.getMonth() + 1)}/${pad(target.getDate())}/${target.getFullYear()}`,
77
+ formattedTime: `${pad(hours)}:${pad(minutes)}:00`,
78
+ humanReadable: target.toLocaleString("tr-TR"),
79
+ timestamp: target.getTime(),
80
+ };
81
+ }
82
+
83
+ async function setAlarm({ time, label = "Alarm", calendarName = "Calendar" }) {
84
+ if (!IS_MAC) return { success: false, error: "Bu tool sadece macOS'ta calisir" };
85
+ if (!time) return { success: false, error: "time gerekli (ornek: '18:00', 'tomorrow 09:30', '+1 hour')" };
86
+
87
+ let parsed;
88
+ try { parsed = parseAlarmTime(time); }
89
+ catch (e) { return { success: false, error: e.message }; }
90
+
91
+ // AppleScript ile macOS Calendar'a all-day etkinlik olarak alarm ekle
92
+ // (Reminder ile ayni sonuc, daha guvenilir cunku Calendar otomasyon izni Reminders'dan once verilir)
93
+ // Dual: Calendar event (gorunurluk) + Reminders (bildirim + alarm)
94
+ // Once Calendar'a basit etkinlik (alarm'siz, ama gorunur), sonra Reminders alarm
95
+ const calendarScript = `
96
+ tell application "Calendar"
97
+ set targetCal to first calendar whose writable is true
98
+ set startDate to date "${parsed.formattedDate} ${parsed.formattedTime}"
99
+ set endDate to startDate + (1 * minutes)
100
+ set newEvent to make new event at end of events of targetCal with properties {summary:"⏰ ${label.replace(/"/g, "'")} - NatureCo", start date:startDate, end date:endDate, allday event:false}
101
+ save
102
+ return id of newEvent
103
+ end tell
104
+ `;
105
+
106
+ // Reminders'a bildirim + sesli alarm
107
+ const reminderScript = `
108
+ tell application "Reminders"
109
+ set targetList to default list
110
+ set startDate to date "${parsed.formattedDate} ${parsed.formattedTime}"
111
+ set newReminder to make new reminder at end of targetList with properties {name:"⏰ ${label.replace(/"/g, "'")} - NatureCo", body:"NatureCo CLI tarafindan ${parsed.humanReadable} icin kuruldu", due date:startDate}
112
+ save
113
+ return id of newReminder
114
+ end tell
115
+ `;
116
+
117
+ try {
118
+ const results = { calendar: null, reminders: null, errors: [] };
119
+
120
+ // Calendar'a ekle (gorunurluk)
121
+ try {
122
+ results.calendar = await runAppleScript(calendarScript);
123
+ } catch (e) {
124
+ results.errors.push(`Calendar: ${e.message}`);
125
+ }
126
+
127
+ // Reminders'a ekle (bildirim + sesli alarm)
128
+ try {
129
+ results.reminders = await runAppleScript(reminderScript);
130
+ } catch (e) {
131
+ results.errors.push(`Reminders: ${e.message}`);
132
+ }
133
+
134
+ const success = !!(results.calendar || results.reminders);
135
+ return {
136
+ success,
137
+ eventId: results.reminders || results.calendar,
138
+ calendarEventId: results.calendar,
139
+ reminderId: results.reminders,
140
+ message: success
141
+ ? `⏰ Alarm kuruldu: ${parsed.humanReadable} — "${label}"`
142
+ : `Alarm kurulamadi: ${results.errors.join('; ')}`,
143
+ calendar: calendarName,
144
+ targetTime: parsed.humanReadable,
145
+ targetTimestamp: parsed.timestamp,
146
+ errors: results.errors.length > 0 ? results.errors : undefined,
147
+ };
148
+ } catch (e) {
149
+ if (e.message.includes("-1728") || e.message.includes("not authorized")) {
150
+ return {
151
+ success: false,
152
+ error: "Calendar erisim izni yok. System Preferences -> Security & Privacy -> Privacy -> Automation -> natureco -> Calendar -> ON",
153
+ };
154
+ }
155
+ return { success: false, error: e.message };
156
+ }
157
+ }
158
+
159
+ async function listAlarms() {
160
+ if (!IS_MAC) return { success: false, error: "Sadece macOS" };
161
+ const script = `
162
+ tell application "Calendar"
163
+ set nowDate to current date
164
+ set futureEvents to {}
165
+ repeat with cal in calendars
166
+ repeat with e in events of cal
167
+ if start date of e > nowDate and (summary of e starts with "⏰") then
168
+ copy (start date of e as string) & " | " & (summary of e) to end of futureEvents
169
+ end if
170
+ end repeat
171
+ end repeat
172
+ return futureEvents
173
+ end tell
174
+ `;
175
+ try {
176
+ const result = await runAppleScript(script);
177
+ const alarms = result.split(", ").filter(Boolean);
178
+ return { success: true, count: alarms.length, alarms };
179
+ } catch (e) {
180
+ return { success: false, error: e.message };
181
+ }
182
+ }
183
+
184
+ module.exports = {
185
+ name: "mac_alarm",
186
+ description: "macOS Clock/Calendar uzerinden alarm kur. '18:00', 'tomorrow 09:30', '+1 hour' gibi formatlari kabul eder.",
187
+ inputSchema: {
188
+ type: "object",
189
+ properties: {
190
+ action: { type: "string", description: "set/list (default: set)", enum: ["set", "list"] },
191
+ time: { type: "string", description: "Alarm zamani: '18:00', 'tomorrow 09:30', '+1 hour', '2026-06-23 07:00'" },
192
+ label: { type: "string", description: "Alarm etiketi (default: 'Alarm')" },
193
+ },
194
+ required: [],
195
+ },
196
+ async execute(params) {
197
+ if (params.action === "list") return listAlarms();
198
+ return setAlarm(params);
199
+ },
200
200
  };