feat: proactive notifications — email, NC Talk, Google Chat per user
notification.py now handles all three outbound channels. Email defaults to the user's login address (google_email from auth.json); an optional override can be set in channels.json. Google Chat uses an incoming webhook URL. NC Talk was already wired, just needs notification_room set. Settings page gains a Notifications section: channel dropdown, optional email override, NC room token, and Google Chat webhook URL. All stored in per-user channels.json. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -344,6 +344,55 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Notifications -->
|
||||
<div class="section">
|
||||
<h2>Notifications</h2>
|
||||
<p style="font-size:0.8rem; color:var(--pg-muted); margin-bottom:0.85rem; line-height:1.55;">
|
||||
Choose how Inara reaches out proactively — cron jobs, briefs, and future alerts.
|
||||
Email defaults to your login address when no override is set.
|
||||
</p>
|
||||
<form method="POST" action="/settings/notifications">
|
||||
<div class="field">
|
||||
<label for="notification_channel">Notification channel</label>
|
||||
<select id="notification_channel" name="notification_channel"
|
||||
data-value="{{ notify_channel }}"
|
||||
style="width:100%; padding:0.65rem 0.85rem; background:var(--pg-bg);
|
||||
border:1px solid var(--pg-border); border-radius:6px;
|
||||
color:var(--pg-text); font-size:0.95rem; outline:none;
|
||||
transition:border-color 0.15s;">
|
||||
<option value="">None (disabled)</option>
|
||||
<option value="email">Email</option>
|
||||
<option value="nextcloud">Nextcloud Talk</option>
|
||||
<option value="google_chat">Google Chat</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="notification_email">Email override
|
||||
<span style="color:var(--pg-dim); font-weight:400;">(optional)</span>
|
||||
</label>
|
||||
<input type="email" id="notification_email" name="notification_email"
|
||||
value="{{ notify_email_override }}"
|
||||
placeholder="Leave blank to use login email"
|
||||
autocomplete="off">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="nc_notification_room">Nextcloud Talk room token</label>
|
||||
<input type="text" id="nc_notification_room" name="nc_notification_room"
|
||||
value="{{ nc_notify_room }}"
|
||||
placeholder="Token from the Talk room URL"
|
||||
autocomplete="off" spellcheck="false">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="gc_outbound_webhook">Google Chat webhook URL</label>
|
||||
<input type="url" id="gc_outbound_webhook" name="gc_outbound_webhook"
|
||||
value="{{ gc_webhook }}"
|
||||
placeholder="https://chat.googleapis.com/v1/spaces/…"
|
||||
autocomplete="off" spellcheck="false">
|
||||
</div>
|
||||
<button type="submit">Save notification settings</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Browser cache -->
|
||||
<div class="section">
|
||||
<h2>Browser Cache</h2>
|
||||
@@ -411,6 +460,12 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Restore notification channel dropdown from injected value
|
||||
(function() {
|
||||
const sel = document.getElementById('notification_channel');
|
||||
if (sel) sel.value = sel.dataset.value || '';
|
||||
})();
|
||||
|
||||
// Password confirmation check
|
||||
document.getElementById('password-form').addEventListener('submit', e => {
|
||||
const np = document.getElementById('new_password').value;
|
||||
|
||||
Reference in New Issue
Block a user