Files
2026-06-27 15:38:31 +08:00

11 lines
29 KiB
JavaScript

/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
*/
var q=Object.defineProperty;var te=Object.getOwnPropertyDescriptor;var ie=Object.getOwnPropertyNames;var ne=Object.prototype.hasOwnProperty;var re=(o,t)=>{for(var e in t)q(o,e,{get:t[e],enumerable:!0})},se=(o,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ie(t))!ne.call(o,r)&&r!==e&&q(o,r,{get:()=>t[r],enumerable:!(i=te(t,r))||i.enumerable});return o};var ae=o=>se(q({},"__esModule",{value:!0}),o);var le={};re(le,{default:()=>B});module.exports=ae(le);var p=require("obsidian");var v=require("obsidian"),S=class extends v.Modal{constructor(e,i,r,n="",s){var d,c,l,h,g,y;super(e);this.defaultChannels=i;this.onSubmit=r;this.existing=s;this.title="";this.body="";this.year="";this.month="";this.day="";this.hour="";this.minute="";this.channels="";this.repeatFrequency="none";this.repeatInterval="1";let a=s?new Date(s.dueAt):new Date(Date.now()+60*60*1e3);this.title=(d=s==null?void 0:s.title)!=null?d:n,this.body=(c=s==null?void 0:s.body)!=null?c:n,this.channels=s?s.channels.join(", "):i.join(", "),this.repeatFrequency=(h=(l=s==null?void 0:s.repeat)==null?void 0:l.frequency)!=null?h:"none",this.repeatInterval=String((y=(g=s==null?void 0:s.repeat)==null?void 0:g.interval)!=null?y:1),this.year=String(a.getFullYear()),this.month=String(a.getMonth()+1).padStart(2,"0"),this.day=String(a.getDate()).padStart(2,"0"),this.hour=String(a.getHours()).padStart(2,"0"),this.minute=String(Math.ceil(a.getMinutes()/5)*5).padStart(2,"0"),this.minute==="60"&&(this.minute="00",this.hour=String((a.getHours()+1)%24).padStart(2,"0"))}onOpen(){let{contentEl:e}=this;e.empty(),e.createEl("h2",{text:this.existing?"Edit reminder":"Create reminder"}),this.renderReminderRow(e),new v.Setting(e).setName("Details").setDesc("Optional longer message.").addTextArea(i=>{i.setValue(this.body),i.inputEl.rows=3,i.onChange(r=>{this.body=r})}),new v.Setting(e).setName("Channels").setDesc("Comma separated provider IDs or types. Leave empty to use all enabled providers.").addText(i=>i.setValue(this.channels).onChange(r=>{this.channels=r})),new v.Setting(e).setName("Repeat").addDropdown(i=>i.addOption("none","None").addOption("daily","Daily").addOption("weekly","Weekly").addOption("monthly","Monthly").setValue(this.repeatFrequency).onChange(r=>{this.repeatFrequency=r})).addText(i=>i.setPlaceholder("Interval").setValue(this.repeatInterval).onChange(r=>{this.repeatInterval=r})),new v.Setting(e).addButton(i=>i.setButtonText(this.existing?"Save":"Create").setCta().onClick(async()=>{let r=this.getSelectedDate();if(!this.title.trim()||!r){new v.Notice("Title and valid due date are required.");return}await this.onSubmit({title:this.title.trim(),body:this.body.trim(),dueAt:r.toISOString(),channels:this.channels.split(",").map(n=>n.trim()).filter(Boolean),repeat:{frequency:this.repeatFrequency,interval:Math.max(1,Number(this.repeatInterval)||1)}}),this.close()}))}renderReminderRow(e){let i=new v.Setting(e).setName("Reminder").setDesc("Text, date, and time.");i.addText(r=>{r.setPlaceholder("Reminder text"),r.setValue(this.title),r.onChange(n=>{this.title=n,(!this.body||this.body===this.title)&&(this.body=n)})}),i.addDropdown(r=>{for(let n of this.range(new Date().getFullYear(),new Date().getFullYear()+3))r.addOption(String(n),String(n));r.setValue(this.year),r.onChange(n=>{this.year=n,this.ensureValidDay()})}),i.addDropdown(r=>{for(let n of this.range(1,12)){let s=String(n).padStart(2,"0");r.addOption(s,s)}r.setValue(this.month),r.onChange(n=>{this.month=n,this.ensureValidDay()})}),i.addDropdown(r=>{for(let n of this.range(1,31)){let s=String(n).padStart(2,"0");r.addOption(s,s)}r.setValue(this.day),r.onChange(n=>{this.day=n})}),i.addDropdown(r=>{for(let n of this.range(0,23)){let s=String(n).padStart(2,"0");r.addOption(s,s)}r.setValue(this.hour),r.onChange(n=>{this.hour=n})}),i.addDropdown(r=>{for(let n of this.range(0,55,5)){let s=String(n).padStart(2,"0");r.addOption(s,s)}r.setValue(this.minute),r.onChange(n=>{this.minute=n})})}getSelectedDate(){let e=new Date(`${this.year}-${this.month}-${this.day}T${this.hour}:${this.minute}:00`);return Number.isNaN(e.getTime())?null:e}ensureValidDay(){let e=new Date(Number(this.year),Number(this.month),0).getDate();Number(this.day)>e&&(this.day=String(e).padStart(2,"0"))}range(e,i,r=1){let n=[];for(let s=e;s<=i;s+=r)n.push(s);return n}};var N=require("obsidian");var oe=new Map([["sunday",0],["monday",1],["tuesday",2],["wednesday",3],["thursday",4],["friday",5],["saturday",6]]);function D(o,t=new Date){var d,c,l,h,g,y;let e=o.trim();if(!e)return null;let i=e.match(/^\+(\d+)\s*(m|min|minute|minutes|h|hour|hours|d|day|days)$/i);if(i){let u=Number(i[1]),w=i[2].toLowerCase(),R=w.startsWith("m")?u*6e4:w.startsWith("h")?u*36e5:u*864e5;return new Date(t.getTime()+R)}let r=e.match(/^tomorrow(?:\s+(\d{1,2})(?::(\d{2}))?)?$/i);if(r){let u=new Date(t);return u.setDate(u.getDate()+1),u.setHours(Number((d=r[1])!=null?d:9),Number((c=r[2])!=null?c:0),0,0),u}let n=e.match(/^next\s+(sunday|monday|tuesday|wednesday|thursday|friday|saturday)(?:\s+(\d{1,2})(?::(\d{2}))?)?$/i);if(n){let u=oe.get(n[1].toLowerCase());if(u===void 0)return null;let w=new Date(t),R=u-w.getDay()+7||7;return w.setDate(w.getDate()+R),w.setHours(Number((l=n[2])!=null?l:9),Number((h=n[3])!=null?h:0),0,0),w}let s=e.match(/^(\d{4}-\d{2}-\d{2})(?:[ T](\d{1,2})(?::(\d{2}))?)?$/);if(s){let u=(g=s[2])!=null?g:"9",w=(y=s[3])!=null?y:"0",R=new Date(`${s[1]}T${u.padStart(2,"0")}:${w.padStart(2,"0")}:00`);return Number.isNaN(R.getTime())?null:R}let a=new Date(e);return Number.isNaN(a.getTime())?null:a}function U(o){let t=new Date(o);return Number.isNaN(t.getTime())?o:t.toLocaleString()}function j(o,t,e=new Date){if(!t||t.frequency==="none")return null;let i=Math.max(1,t.interval||1),r=new Date(o);if(Number.isNaN(r.getTime()))return null;for(;r.getTime()<=e.getTime();)t.frequency==="daily"?r.setDate(r.getDate()+i):t.frequency==="weekly"?r.setDate(r.getDate()+7*i):t.frequency==="monthly"&&r.setMonth(r.getMonth()+i);return r.toISOString()}var W=/@remind\(([^)]+)\)/gi,Y=/(?:\uD83D\uDD14|\[!\s*reminder\s*\])\s*(\d{4}-\d{2}-\d{2}(?:[ T]\d{1,2}(?::\d{2})?)?)/i,A=class{parseMarkdown(t,e){return[...this.parseInline(t,e),...this.parseFrontmatter(t,e),...this.parseReminderBlocks(t,e)]}parseInline(t,e){let i=[];return t.split(/\r?\n/).forEach((n,s)=>{for(let d of n.matchAll(W)){let c=d[1].split(",").map(g=>g.trim()).filter(Boolean),l=D(c[0]);if(!l)continue;let h=n.replace(W,"").replace(/^[-*]\s+\[[ xX]\]\s+/,"").trim();i.push({title:h||"Reminder",body:h,dueAt:l.toISOString(),sourceFile:e,sourceLine:s+1,channels:this.parseChannels(c.slice(1)),priority:this.parsePriority(c),repeat:this.parseRepeat(c)})}let a=n.match(Y);if(a){let d=D(a[1]);if(!d)return;let c=n.replace(Y,"").replace(/^[-*]\s+\[[ xX]\]\s+/,"").trim();i.push({title:c||"Reminder",body:c,dueAt:d.toISOString(),sourceFile:e,sourceLine:s+1,channels:[],priority:"normal",repeat:void 0})}}),i}parseFrontmatter(t,e){let i=t.match(/^---\r?\n([\s\S]*?)\r?\n---/);return i?this.parseYamlLike(i[1],e,1):[]}parseReminderBlocks(t,e){let i=[],r=/```reminder\r?\n([\s\S]*?)```/gi;for(let n of t.matchAll(r)){let s=t.slice(0,n.index).split(/\r?\n/).length;i.push(...this.parseYamlLike(n[1],e,s))}return i}parseYamlLike(t,e,i){return(t.includes("reminders:")?this.parseReminderList(t):[this.parseKeyValueBlock(t)]).flatMap(n=>{var c,l,h,g,y;let s=(l=(c=n.at)!=null?c:n.date)!=null?l:n.dueAt;if(!s)return[];let a=D(s);if(!a)return[];let d=((g=(h=n.notify)!=null?h:n.channels)!=null?g:"").split(",").map(u=>u.trim()).filter(Boolean);return[{title:n.title||n.message||"Reminder",body:n.message||n.body||n.title||"",dueAt:a.toISOString(),sourceFile:e,sourceLine:i,channels:d,priority:this.normalizePriority(n.priority),repeat:this.parseRepeat([(y=n.repeat)!=null?y:""])}]})}parseReminderList(t){let e=[],i=null;for(let r of t.split(/\r?\n/)){let n=r.match(/^\s*-\s+(\w+):\s*(.+)$/);if(n){i={[n[1]]:n[2].trim()},e.push(i);continue}let s=r.match(/^\s+(\w+):\s*(.+)$/);s&&i&&(i[s[1]]=s[2].trim())}return e}parseKeyValueBlock(t){let e={},i=t.split(/\r?\n/),r=!1,n="";for(let s of i){if(/^\s*reminder:\s*$/.test(s)){r=!0;continue}let a=s.match(/^\s*-\s+(.+)$/);if(a&&n){e[n]=[e[n],a[1].trim()].filter(Boolean).join(",");continue}let d=s.match(/^\s*(\w+):\s*(.*)$/);d&&(r||!s.startsWith(" "))&&(e[d[1]]=d[2].trim(),n=d[1])}return e}parsePriority(t){let e=t.find(i=>/^(low|normal|high)$/i.test(i));return this.normalizePriority(e)}parseChannels(t){return t.filter(e=>!/^(low|normal|high)$/i.test(e)&&!/^(daily|weekly|monthly)(?::\d+)?$/i.test(e))}parseRepeat(t){let e=t.find(n=>/^(daily|weekly|monthly)(?::\d+)?$/i.test(n));if(!e)return;let[i,r]=e.toLowerCase().split(":");return{frequency:i,interval:Math.max(1,Number(r)||1)}}normalizePriority(t){return t==="low"||t==="high"||t==="normal"?t:"normal"}};var O=class{constructor(t,e,i,r=()=>{}){this.vault=t;this.store=e;this.providers=i;this.onChange=r;this.timer=null;this.parser=new A}start(){this.stop();let t=Math.max(10,this.store.getSettings().checkIntervalSeconds)*1e3;this.timer=window.setInterval(()=>{this.tick()},t),this.tick()}stop(){this.timer!==null&&(window.clearInterval(this.timer),this.timer=null)}async tick(){for(let t of this.store.getDue())await this.sendReminder(t)}async scanFile(t){let e=await this.vault.read(t),i=this.parser.parseMarkdown(e,t.path);return this.store.addMany(i)}async scanVault(){let t=0,e=this.vault.getMarkdownFiles();for(let i of e)t+=await this.scanFile(i);return t}async sendReminder(t){let e=this.store.getSettings().notificationProviders.filter(n=>n.enabled),i=e.filter(n=>t.channels.includes(n.id)||t.channels.includes(n.type)),r=i.length?i:t.channels.length===0?e:[];if(!r.length){let n=t.channels.length?`Reminder has no matching enabled provider: ${t.title}`:`Reminder has no enabled providers: ${t.title}`;new N.Notice(n),await this.store.markFailed(t.id,n),this.onChange();return}try{for(let n of r){let s=this.providers.get(n.type);if(!s)throw new Error(`Unknown provider: ${n.type}`);await s.send({title:t.title,message:t.body||t.title,sourceFile:t.sourceFile,sourceLine:t.sourceLine,priority:t.priority,dueAt:t.dueAt},n)}await this.completeSourceTask(t),await this.store.markSent(t.id),this.onChange()}catch(n){await this.store.markFailed(t.id,n),this.onChange(),new N.Notice(`Reminder failed: ${t.title}`)}}async completeSourceTask(t){if(!this.store.getSettings().markTaskCompleteOnSend||t.repeat||!t.sourceFile||!t.sourceLine)return;let e=this.vault.getAbstractFileByPath(t.sourceFile);if(!(e instanceof N.TFile))return;let r=(await this.vault.read(e)).split(/\r?\n/),n=t.sourceLine-1,s=r[n];!s||!/^\s*[-*]\s+\[\s\]/.test(s)||(r[n]=s.replace(/^(\s*[-*]\s+\[)\s(\])/,"$1x$2"),await this.vault.modify(e,r.join(`
`)))}};function H(o){let t=o.join("|"),e=0;for(let i=0;i<t.length;i+=1)e=(e<<5)-e+t.charCodeAt(i)|0;return`rem_${Math.abs(e).toString(36)}`}var T=[{id:"local",type:"local",name:"Local notice",enabled:!0,config:{}},{id:"telegram",type:"telegram",name:"Telegram Bot",enabled:!1,config:{botToken:"123456:ABCDEF_your_bot_token",chatId:"123456789",parseMode:"Markdown"}},{id:"ntfy",type:"ntfy",name:"ntfy.sh",enabled:!1,config:{serverUrl:"https://ntfy.sh",topic:"my-obsidian-reminders",token:"",priority:3,tags:["calendar","obsidian"]}},{id:"discord",type:"discord",name:"Discord Webhook",enabled:!1,config:{webhookUrl:"https://discord.com/api/webhooks/...",username:"Obsidian Reminder"}},{id:"webhook",type:"webhook",name:"Generic Webhook",enabled:!1,config:{method:"POST",url:"https://example.com/reminder",headers:{"Content-Type":"application/json"},bodyTemplate:{title:"{{title}}",message:"{{message}}",dueAt:"{{dueAt}}",sourceFile:"{{sourceFile}}"}}}],de={defaultChannels:[],scanVaultOnStartup:!0,scanOnFileChange:!0,checkIntervalSeconds:60,afterSend:"mark-sent",markTaskCompleteOnSend:!1,reminderSyntax:"@remind(YYYY-MM-DD HH:mm, provider)",notificationProviders:[T[0]]};function I(){return JSON.parse(JSON.stringify(de))}function z(o){let t=T.find(i=>i.type===o);if(!t)return null;let e=Date.now().toString(36);return{...t,id:`${t.type}-${e}`,config:JSON.parse(JSON.stringify(t.config))}}var J=2,x=class{constructor(t){this.plugin=t;this.data={dataVersion:J,settings:I(),reminders:[]}}async load(){var i,r,n,s,a;let t=await this.plugin.loadData(),e=I();this.data=this.migrate({dataVersion:(i=t==null?void 0:t.dataVersion)!=null?i:1,settings:{...e,...(r=t==null?void 0:t.settings)!=null?r:{},notificationProviders:(s=(n=t==null?void 0:t.settings)==null?void 0:n.notificationProviders)!=null?s:e.notificationProviders},reminders:(a=t==null?void 0:t.reminders)!=null?a:[]}),await this.save()}async save(){await this.plugin.saveData(this.data)}getSettings(){return this.data.settings}async updateSettings(t){this.data.settings=t,await this.save()}getAll(){return[...this.data.reminders].sort((t,e)=>t.dueAt.localeCompare(e.dueAt))}getDue(t=new Date){return this.data.reminders.filter(e=>(e.status==="pending"||e.status==="snoozed"||e.status==="failed")&&new Date(e.dueAt).getTime()<=t.getTime())}async add(t,e){var s,a,d,c;let i=new Date().toISOString(),r={id:H([(s=t.sourceFile)!=null?s:"manual",String((a=t.sourceLine)!=null?a:""),t.title,t.dueAt]),title:t.title,body:t.body,dueAt:t.dueAt,sourceFile:t.sourceFile,sourceLine:t.sourceLine,completed:!1,channels:t.channels.length?t.channels:e,priority:(d=t.priority)!=null?d:"normal",status:"pending",repeat:(c=t.repeat)!=null&&c.frequency&&t.repeat.frequency!=="none"?t.repeat:void 0,createdAt:i,updatedAt:i},n=this.data.reminders.find(l=>l.id===r.id);return n?(Object.assign(n,{...r,status:n.status,completed:n.completed,createdAt:n.createdAt,updatedAt:i}),await this.save(),n):(this.data.reminders.push(r),await this.save(),r)}async update(t,e){var r,n;let i=this.find(t);i&&(i.title=e.title,i.body=e.body,i.dueAt=e.dueAt,i.channels=e.channels,i.priority=(r=e.priority)!=null?r:"normal",i.repeat=(n=e.repeat)!=null&&n.frequency&&e.repeat.frequency!=="none"?e.repeat:void 0,i.status="pending",i.completed=!1,i.updatedAt=new Date().toISOString(),i.lastError=void 0,await this.save())}async addMany(t){let e=0;for(let i of t)await this.add(i,[]),e+=1;return e}async markSent(t){let e=this.find(t);if(!e)return;let i=j(e.dueAt,e.repeat);i?(e.dueAt=i,e.status="pending",e.completed=!1):(e.status=this.data.settings.afterSend==="mark-done"?"done":"sent",e.completed=this.data.settings.afterSend==="mark-done"),e.updatedAt=new Date().toISOString(),e.lastError=void 0,await this.save()}async markFailed(t,e){let i=this.find(t);i&&(i.status="failed",i.lastError=e instanceof Error?e.message:String(e),i.updatedAt=new Date().toISOString(),await this.save())}async complete(t){let e=this.find(t);e&&(e.completed=!0,e.status="done",e.updatedAt=new Date().toISOString(),await this.save())}async snooze(t,e){let i=this.find(t);i&&(i.dueAt=new Date(Date.now()+e*6e4).toISOString(),i.status="snoozed",i.updatedAt=new Date().toISOString(),await this.save())}async remove(t){this.data.reminders=this.data.reminders.filter(e=>e.id!==t),await this.save()}find(t){return this.data.reminders.find(e=>e.id===t)}migrate(t){var n,s;let e=I(),i={...e,...t.settings,notificationProviders:(n=t.settings.notificationProviders)!=null?n:e.notificationProviders,markTaskCompleteOnSend:(s=t.settings.markTaskCompleteOnSend)!=null?s:e.markTaskCompleteOnSend},r=t.reminders.map(a=>{var d,c,l,h,g,y;return{...a,channels:(d=a.channels)!=null?d:[],priority:(c=a.priority)!=null?c:"normal",status:(l=a.status)!=null?l:"pending",completed:(h=a.completed)!=null?h:!1,createdAt:(g=a.createdAt)!=null?g:new Date().toISOString(),updatedAt:(y=a.updatedAt)!=null?y:new Date().toISOString()}});return{dataVersion:J,settings:i,reminders:r}}};var P=require("obsidian");var b="reminder-notifier-view",k=class extends P.ItemView{constructor(e,i){super(e);this.plugin=i;this.showAll=!1}getViewType(){return b}getDisplayText(){return"Reminders"}getIcon(){return"list-checks"}async onOpen(){this.render()}refresh(){this.render()}render(){let e=this.containerEl.children[1];e.empty(),e.addClass("reminder-notifier-view"),new P.Setting(e).setName("Reminders").addButton(n=>n.setButtonText("New").setIcon("bell-plus").onClick(()=>{new S(this.app,this.plugin.store.getSettings().defaultChannels,async s=>{await this.plugin.store.add(s,this.plugin.store.getSettings().defaultChannels),this.refresh(),new P.Notice("Reminder created.")}).open()})).addButton(n=>n.setButtonText(this.showAll?"Active":"All").setIcon("filter").onClick(()=>{this.showAll=!this.showAll,this.render()}));let i=this.showAll?this.plugin.store.getAll():this.plugin.store.getAll().filter(n=>!["sent","done","cancelled"].includes(n.status));if(!i.length){e.createEl("p",{text:this.showAll?"No reminders.":"No active reminders."});return}let r=e.createDiv({cls:"reminder-notifier-list"});for(let n of i)this.renderReminder(r,n)}renderReminder(e,i){var s;let r=e.createDiv({cls:"reminder-notifier-item"});r.createDiv({cls:"reminder-notifier-item-title",text:i.title}),r.createDiv({cls:"reminder-notifier-item-meta",text:`${U(i.dueAt)} - ${i.status} - ${i.channels.join(", ")||"all enabled"}`}),(s=i.repeat)!=null&&s.frequency&&i.repeat.frequency!=="none"&&r.createDiv({cls:"reminder-notifier-item-meta",text:`Repeats ${i.repeat.frequency} every ${i.repeat.interval}`});let n=r.createDiv({cls:"reminder-notifier-actions"});new P.Setting(n).addButton(a=>a.setButtonText("Edit").setIcon("pencil").onClick(()=>{new S(this.app,i.channels,async d=>{await this.plugin.store.update(i.id,d),this.refresh(),new P.Notice("Reminder updated.")},i.title,i).open()})).addButton(a=>a.setButtonText("15m").setIcon("clock").onClick(async()=>{await this.plugin.store.snooze(i.id,15),this.refresh()})).addButton(a=>a.setButtonText("Done").setIcon("check").onClick(async()=>{await this.plugin.store.complete(i.id),this.refresh()})).addButton(a=>a.setButtonText("Delete").setIcon("trash").onClick(async()=>{await this.plugin.store.remove(i.id),this.refresh()}))}};var m=require("obsidian");var E=class extends m.PluginSettingTab{constructor(e,i){super(e,i);this.plugin=i}display(){let{containerEl:e}=this,i=this.plugin.store.getSettings();e.empty(),e.createEl("h2",{text:"Reminder Notifier"}),new m.Setting(e).setName("Scan vault on startup").addToggle(n=>n.setValue(i.scanVaultOnStartup).onChange(async s=>{i.scanVaultOnStartup=s,await this.plugin.store.updateSettings(i)})),new m.Setting(e).setName("Scan changed notes").addToggle(n=>n.setValue(i.scanOnFileChange).onChange(async s=>{i.scanOnFileChange=s,await this.plugin.store.updateSettings(i)})),new m.Setting(e).setName("Check interval").setDesc("Seconds between reminder checks.").addText(n=>n.setValue(String(i.checkIntervalSeconds)).onChange(async s=>{i.checkIntervalSeconds=Math.max(10,Number(s)||60),await this.plugin.store.updateSettings(i),this.plugin.restartScheduler()})),new m.Setting(e).setName("Default channels").setDesc("Comma separated provider IDs or types. Empty means every enabled provider.").addText(n=>n.setValue(i.defaultChannels.join(", ")).onChange(async s=>{i.defaultChannels=s.split(",").map(a=>a.trim()).filter(Boolean),await this.plugin.store.updateSettings(i)})),new m.Setting(e).setName("After send").addDropdown(n=>n.addOption("mark-sent","Mark as sent").addOption("mark-done","Mark as done").addOption("keep","Keep pending").setValue(i.afterSend).onChange(async s=>{i.afterSend=s,await this.plugin.store.updateSettings(i)})),new m.Setting(e).setName("Mark Markdown tasks complete").setDesc("When a non-repeating reminder from a task line is sent, replace [ ] with [x].").addToggle(n=>n.setValue(i.markTaskCompleteOnSend).onChange(async s=>{i.markTaskCompleteOnSend=s,await this.plugin.store.updateSettings(i)})),e.createEl("h3",{text:"Notification providers"});let r=T[0].type;new m.Setting(e).setName("Add from template").addDropdown(n=>{for(let s of T)n.addOption(s.type,s.name);n.onChange(s=>{r=s})}).addButton(n=>n.setButtonText("Add provider").onClick(async()=>{let s=z(r);s&&(i.notificationProviders.push(s),await this.plugin.store.updateSettings(i),this.display())}));for(let n of i.notificationProviders)this.renderProvider(n)}renderProvider(e){let i=this.plugin.store.getSettings(),r=this.containerEl.createDiv({cls:"reminder-notifier-provider"});r.createEl("h4",{text:e.name}),new m.Setting(r).setName("Enabled").addToggle(n=>n.setValue(e.enabled).onChange(async s=>{e.enabled=s,await this.plugin.store.updateSettings(i)})),new m.Setting(r).setName("ID").setDesc("Use this value in @remind(..., provider-id).").addText(n=>n.setValue(e.id).onChange(async s=>{e.id=s.trim(),await this.plugin.store.updateSettings(i)})),new m.Setting(r).setName("Name").addText(n=>n.setValue(e.name).onChange(async s=>{e.name=s,await this.plugin.store.updateSettings(i)})),new m.Setting(r).setName("Config JSON").setDesc("Secrets are stored locally in Obsidian plugin data.").addTextArea(n=>{n.inputEl.addClass("reminder-notifier-json"),n.setValue(JSON.stringify(e.config,null,2)),n.onChange(async s=>{try{e.config=JSON.parse(s),await this.plugin.store.updateSettings(i)}catch(a){}})}),new m.Setting(r).addButton(n=>n.setButtonText("Test notification").onClick(async()=>{try{await this.plugin.testProvider(e),new m.Notice("Test notification sent.")}catch(s){new m.Notice(s instanceof Error?s.message:String(s))}})).addButton(n=>n.setButtonText("Delete").onClick(async()=>{i.notificationProviders=i.notificationProviders.filter(s=>s!==e),await this.plugin.store.updateSettings(i),this.display()}))}};var K=require("obsidian");function C(o,t){var e,i,r,n,s,a;return typeof o=="string"?Object.entries({"{{title}}":t.title,"{{message}}":t.message,"{{body}}":t.message,"{{file}}":(e=t.sourceFile)!=null?e:"","{{sourceFile}}":(i=t.sourceFile)!=null?i:"","{{sourceLine}}":(n=(r=t.sourceLine)==null?void 0:r.toString())!=null?n:"","{{priority}}":(s=t.priority)!=null?s:"normal","{{dueAt}}":t.dueAt,"{{time}}":t.dueAt,"{{url}}":(a=t.url)!=null?a:""}).reduce((d,[c,l])=>d.split(c).join(l),o):Array.isArray(o)?o.map(d=>C(d,t)):o&&typeof o=="object"?Object.fromEntries(Object.entries(o).map(([d,c])=>[d,C(c,t)])):o}function f(o,t=""){return typeof o=="string"?o:t}var V=class{constructor(){this.id="discord";this.name="Discord webhook"}async send(t,e){let i=f(e.config.webhookUrl);if(!i)throw new Error("Discord webhookUrl is required.");await(0,K.requestUrl)({url:i,method:"POST",contentType:"application/json",body:JSON.stringify({username:f(e.config.username,"Obsidian Reminder"),content:`**${t.title}**
${t.message}`}),throw:!0})}async test(t){await this.send({title:"Obsidian Reminder Notifier",message:"Test notification",dueAt:new Date().toISOString()},t)}};var _=require("obsidian"),$=class{constructor(){this.id="local";this.name="Local Obsidian notice"}async send(t){new _.Notice(`${t.title}
${t.message}`,1e4)}async test(t){new _.Notice("Reminder Notifier test notification",5e3)}};var X=require("obsidian");function G(o){let t=o.trim()||"https://ntfy.sh";return(/^https?:\/\//i.test(t)?t:`https://${t}`).replace(/\/+$/,"")}var F=class{constructor(){this.id="ntfy";this.name="ntfy"}async send(t,e){var c;let i=G(f(e.config.serverUrl,"https://ntfy.sh")),r=f(e.config.topic).trim();if(!r)throw new Error("ntfy topic is required.");let n={Title:t.title,Priority:String((c=e.config.priority)!=null?c:ce(t.priority))},s=f(e.config.token).trim();s&&(n.Authorization=`Bearer ${s}`);let a=e.config.tags;Array.isArray(a)&&(n.Tags=a.join(","));let d=`${i}/${encodeURIComponent(r)}`;try{await(0,X.requestUrl)({url:d,method:"POST",headers:n,body:t.message,throw:!0})}catch(l){let h=l instanceof Error?l.message:String(l);throw new Error(`ntfy send failed for ${i}/${r}: ${h}`)}}async test(t){await this.send({title:"Obsidian Reminder Notifier",message:"Test notification",dueAt:new Date().toISOString()},t)}};function ce(o="normal"){return o==="high"?4:o==="low"?2:3}var Q=require("obsidian");var M=class{constructor(){this.id="telegram";this.name="Telegram"}async send(t,e){let i=f(e.config.botToken),r=f(e.config.chatId);if(!i||!r)throw new Error("Telegram botToken and chatId are required.");let n=`*${t.title}*
${t.message}`;await(0,Q.requestUrl)({url:`https://api.telegram.org/bot${i}/sendMessage`,method:"POST",contentType:"application/json",body:JSON.stringify({chat_id:r,text:n,parse_mode:f(e.config.parseMode,"Markdown"),disable_web_page_preview:!0}),throw:!0})}async test(t){await this.send({title:"Obsidian Reminder Notifier",message:"Test notification",dueAt:new Date().toISOString()},t)}};var Z=require("obsidian");var L=class{constructor(){this.id="webhook";this.name="Generic webhook"}async send(t,e){var a,d;let i=f(e.config.url);if(!i)throw new Error("Webhook URL is required.");let r=f(e.config.method,"POST").toUpperCase();if(!["POST","PUT","PATCH"].includes(r))throw new Error("Webhook method must be POST, PUT, or PATCH.");let n=C((a=e.config.headers)!=null?a:{"Content-Type":"application/json"},t),s=C((d=e.config.bodyTemplate)!=null?d:{title:"{{title}}",message:"{{message}}",dueAt:"{{dueAt}}",sourceFile:"{{sourceFile}}"},t);await(0,Z.requestUrl)({url:i,method:r,headers:n,body:typeof s=="string"?s:JSON.stringify(s),throw:!0})}async test(t){await this.send({title:"Obsidian Reminder Notifier",message:"Test notification",dueAt:new Date().toISOString()},t)}};function ee(){let o=[new $,new M,new F,new L,new V];return new Map(o.map(t=>[t.id,t]))}var B=class extends p.Plugin{constructor(){super(...arguments);this.providers=ee()}async onload(){if(this.store=new x(this),await this.store.load(),this.scheduler=new O(this.app.vault,this.store,this.providers,()=>this.refreshReminderViews()),this.registerView(b,e=>new k(e,this)),this.addSettingTab(new E(this.app,this)),this.registerCommands(),this.registerRibbonActions(),this.registerContextMenus(),this.registerFileWatcher(),this.store.getSettings().scanVaultOnStartup){let e=await this.scheduler.scanVault();e>0&&new p.Notice(`Reminder Notifier indexed ${e} reminders.`)}this.scheduler.start()}onunload(){var e;(e=this.scheduler)==null||e.stop()}restartScheduler(){this.scheduler.stop(),this.scheduler.start()}async testProvider(e){let i=this.providers.get(e.type);if(!i)throw new Error(`Unknown provider: ${e.type}`);await i.test(e)}async activateReminderView(){let e=this.app.workspace.getLeavesOfType(b)[0];if(e){this.app.workspace.revealLeaf(e);return}let i=this.app.workspace.getRightLeaf(!1);i&&(await i.setViewState({type:b,active:!0}),this.app.workspace.revealLeaf(i))}refreshReminderViews(){for(let e of this.app.workspace.getLeavesOfType(b)){let i=e.view;i instanceof k&&i.refresh()}}registerCommands(){this.addCommand({id:"create-reminder",name:"Create reminder",callback:()=>{new S(this.app,this.store.getSettings().defaultChannels,async e=>{await this.store.add(e,this.store.getSettings().defaultChannels),this.refreshReminderViews(),new p.Notice("Reminder created.")}).open()}}),this.addCommand({id:"create-reminder-from-selection",name:"Create reminder from selected text",editorCallback:e=>{let i=e.getSelection();new S(this.app,this.store.getSettings().defaultChannels,async r=>{await this.store.add(r,this.store.getSettings().defaultChannels),this.refreshReminderViews(),new p.Notice("Reminder created.")},i).open()}}),this.addCommand({id:"show-active-reminders",name:"Show active reminders",callback:()=>{this.activateReminderView()}}),this.addCommand({id:"show-all-reminders",name:"Show all reminders",callback:()=>{this.activateReminderView()}}),this.addCommand({id:"scan-current-note",name:"Scan current note for reminders",checkCallback:e=>{let i=this.app.workspace.getActiveFile();return i?(e||this.scanCurrentFile(i),!0):!1}}),this.addCommand({id:"scan-vault",name:"Scan vault for reminders",callback:async()=>{let e=await this.scheduler.scanVault();new p.Notice(`Indexed ${e} reminders.`)}}),this.addCommand({id:"test-notification-providers",name:"Test notification providers",callback:async()=>{let e=this.store.getSettings().notificationProviders.filter(i=>i.enabled);for(let i of e)await this.testProvider(i);new p.Notice(`Tested ${e.length} providers.`)}})}registerRibbonActions(){this.addRibbonIcon("bell-plus","Create reminder",()=>{new S(this.app,this.store.getSettings().defaultChannels,async e=>{await this.store.add(e,this.store.getSettings().defaultChannels),this.refreshReminderViews(),new p.Notice("Reminder created.")}).open()}),this.addRibbonIcon("list-checks","Show reminders",()=>{this.activateReminderView()})}registerContextMenus(){this.registerEvent(this.app.workspace.on("editor-menu",(e,i)=>{e.addSeparator(),e.addItem(r=>r.setTitle("Create reminder").setIcon("bell-plus").onClick(()=>{let n=i.getSelection();new S(this.app,this.store.getSettings().defaultChannels,async s=>{await this.store.add(s,this.store.getSettings().defaultChannels),this.refreshReminderViews(),new p.Notice("Reminder created.")},n).open()})),e.addItem(r=>r.setTitle("Show reminders").setIcon("list-checks").onClick(()=>{this.activateReminderView()}))}))}registerFileWatcher(){this.registerEvent(this.app.vault.on("modify",e=>{!this.store.getSettings().scanOnFileChange||!(e instanceof p.TFile)||e.extension!=="md"||this.scheduler.scanFile(e)}))}async scanCurrentFile(e){var s;let i=this.app.workspace.getActiveViewOfType(p.MarkdownView),r=(s=i==null?void 0:i.file)!=null?s:e,n=await this.scheduler.scanFile(r);new p.Notice(`Indexed ${n} reminders from ${r.basename}.`)}};