Action
Send brrr
Last update
22 days ago
- Unlisted
Steps
-
script
// brrr Notification – Drafts Action (Advanced) // Replace with your personal webhook from the brrr app const WEBHOOK_URL = "xx"; const SOUNDS = [ "default", "system", "brrr", "bell_ringing", "bubble_ding", "bubbly_success_ding", "cat_meow", "calm1", "calm2", "cha_ching", "dog_barking", "door_bell", "duck_quack", "short_triple_blink", "upbeat_bells", "warm_soft_error" ]; // Apple enforces 4096 bytes total. brrr uses some overhead (~200 bytes safe estimate). const MAX_PAYLOAD_BYTES = 3800; function byteSize(str) { var bytes = 0; for (var i = 0; i < str.length; i++) { var code = str.charCodeAt(i); if (code < 0x80) bytes += 1; else if (code < 0x800) bytes += 2; else if (code < 0xD800 || code >= 0xE000) bytes += 3; else { // Surrogate pair (emoji etc.) = 4 bytes i++; bytes += 4; } } return bytes; } function run() { // --- Prompt --- const p = Prompt.create(); p.title = "Send brrr Notification"; p.addTextField("title", "Title", "", { placeholder: "Notification title" }); p.addTextField("subtitle", "Subtitle", "", { placeholder: "Optional subtitle" }); p.addTextView("message", "Message", draft.content, { height: 80 }); p.addSelect("sound", "Sound", SOUNDS, ["default"], false); p.addTextField("open_url", "Open URL", "", { placeholder: "https://... (optional)" }); p.addTextField("image_url", "Image URL", "", { placeholder: "https://... (iPhone/iPad only)" }); p.addSwitch("useExpiry", "Set Expiration Date?", false); p.addDatePicker("expiry", "Expiration", new Date(), { mode: "dateAndTime" }); p.addButton("Send 🔔"); if (!p.show() || p.buttonPressed !== "Send 🔔") { context.cancel("Cancelled"); return; } // --- Read values --- const title = p.fieldValues["title"].trim(); const subtitle = p.fieldValues["subtitle"].trim(); const message = p.fieldValues["message"].trim(); const sound = p.fieldValues["sound"][0]; const open_url = p.fieldValues["open_url"].trim(); const image_url = p.fieldValues["image_url"].trim(); // --- Build payload --- const payload = {}; if (title) payload.title = title; if (subtitle) payload.subtitle = subtitle; if (message) payload.message = message; if (sound) payload.sound = sound; if (open_url) payload.open_url = open_url; if (image_url) payload.image_url = image_url; if (p.fieldValues["useExpiry"]) { payload.expiration_date = p.fieldValues["expiry"].toISOString(); } // --- Guard: check total payload size against Apple's 4 KB limit --- const payloadJSON = JSON.stringify(payload); const payloadBytes = byteSize(payloadJSON); if (payloadBytes > MAX_PAYLOAD_BYTES) { const warn = Prompt.create(); warn.title = "⚠️ Payload Too Large"; warn.message = `Your payload is ${payloadBytes} bytes, but the limit is ~${MAX_PAYLOAD_BYTES} bytes (Apple enforces 4 KB total).\n\nPlease shorten your title, subtitle, or message and try again.`; warn.addButton("OK"); warn.show(); context.cancel("Payload too large"); return; } // --- Send request --- const http = HTTP.create(); const response = http.request({ url: WEBHOOK_URL, method: "POST", headers: { "Content-Type": "application/json" }, data: payload }); if (response.success && response.statusCode < 300) { app.displaySuccessMessage(`Notification sent! 🔔 (${payloadBytes} bytes)`); } else { let errorDetail = ""; if (response.error) { errorDetail = response.error; } else if (response.responseText) { try { const parsed = JSON.parse(response.responseText); errorDetail = parsed.error || parsed.message || response.responseText; } catch (_) { errorDetail = response.responseText; } } else { errorDetail = "Unknown error"; } const fullError = `HTTP ${response.statusCode}: ${errorDetail}`; context.fail(fullError); const errPrompt = Prompt.create(); errPrompt.title = "❌ brrr Failed"; errPrompt.message = fullError; errPrompt.addButton("OK"); errPrompt.show(); } } run();
Options
-
After Success Default Notification Info Log Level Info
Items available in the Drafts Directory are uploaded by community members. Use appropriate caution reviewing downloaded items before use.