kissyjpf_rtm-sync/main.js
2026-06-04 09:49:25 +09:00

26 lines
17 KiB
JavaScript

/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var Z=Object.defineProperty;var it=Object.getOwnPropertyDescriptor;var rt=Object.getOwnPropertyNames;var at=Object.prototype.hasOwnProperty;var ot=(S,p)=>{for(var t in p)Z(S,t,{get:p[t],enumerable:!0})},lt=(S,p,t,o)=>{if(p&&typeof p=="object"||typeof p=="function")for(let r of rt(p))!at.call(S,r)&&r!==t&&Z(S,r,{get:()=>p[r],enumerable:!(o=it(p,r))||o.enumerable});return S};var ct=S=>lt(Z({},"__esModule",{value:!0}),S);var ut={};ot(ut,{default:()=>X});module.exports=ct(ut);var f=require("obsidian");function I(S){function p(w,k){return w<<k|w>>>32-k}function t(w,k){let x=w&1073741824,A=k&1073741824,E=w&2147483648,C=k&2147483648,b=(w&1073741823)+(k&1073741823);return x&A?b^2147483648^E^C:x|A?b&1073741824?b^3221225472^E^C:b^1073741824^E^C:b^E^C}function o(w,k,x){return w&k|~w&x}function r(w,k,x){return w&x|k&~x}function c(w,k,x){return w^k^x}function d(w,k,x){return k^(w|~x)}function m(w,k,x,A,E,C,b){return w=t(w,t(t(o(k,x,A),E),b)),t(p(w,C),k)}function g(w,k,x,A,E,C,b){return w=t(w,t(t(r(k,x,A),E),b)),t(p(w,C),k)}function y(w,k,x,A,E,C,b){return w=t(w,t(t(c(k,x,A),E),b)),t(p(w,C),k)}function u(w,k,x,A,E,C,b){return w=t(w,t(t(d(k,x,A),E),b)),t(p(w,C),k)}function h(w){let k,x=w.length,A=x+8,C=((A-A%64)/64+1)*16,b=Array(C-1),J=0,N=0;for(;N<x;)k=(N-N%4)/4,J=N%4*8,b[k]=b[k]|w.charCodeAt(N)<<J,N++;return k=(N-N%4)/4,J=N%4*8,b[k]=b[k]|128<<J,b[C-2]=x<<3,b[C-1]=x>>>29,b}function F(w){let k="",x="",A,E;for(E=0;E<=3;E++)A=w>>>E*8&255,x="0"+A.toString(16),k=k+x.substr(x.length-2,2);return k}function T(w){w=w.replace(/\r\n/g,`
`);let k="";for(let x=0;x<w.length;x++){let A=w.charCodeAt(x);A<128?k+=String.fromCharCode(A):A>127&&A<2048?(k+=String.fromCharCode(A>>6|192),k+=String.fromCharCode(A&63|128)):(k+=String.fromCharCode(A>>12|224),k+=String.fromCharCode(A>>6&63|128),k+=String.fromCharCode(A&63|128))}return k}let a=Array(),l,P,D,$,v,n,i,s,e,B=7,R=12,L=17,_=22,M=5,O=9,j=14,W=20,V=4,K=11,U=16,H=23,G=6,q=10,Q=15,Y=21;for(S=T(S),a=h(S),n=1732584193,i=4023233417,s=2562383102,e=271733878,l=0;l<a.length;l+=16)P=n,D=i,$=s,v=e,n=m(n,i,s,e,a[l+0],B,3614090360),e=m(e,n,i,s,a[l+1],R,3905402710),s=m(s,e,n,i,a[l+2],L,606105819),i=m(i,s,e,n,a[l+3],_,3250441966),n=m(n,i,s,e,a[l+4],B,4118548399),e=m(e,n,i,s,a[l+5],R,1200080426),s=m(s,e,n,i,a[l+6],L,2821735955),i=m(i,s,e,n,a[l+7],_,4249261313),n=m(n,i,s,e,a[l+8],B,1770035416),e=m(e,n,i,s,a[l+9],R,2336552879),s=m(s,e,n,i,a[l+10],L,4294925233),i=m(i,s,e,n,a[l+11],_,2304563134),n=m(n,i,s,e,a[l+12],B,1804603682),e=m(e,n,i,s,a[l+13],R,4254626195),s=m(s,e,n,i,a[l+14],L,2792965006),i=m(i,s,e,n,a[l+15],_,1236535329),n=g(n,i,s,e,a[l+1],M,4129170786),e=g(e,n,i,s,a[l+6],O,3225465664),s=g(s,e,n,i,a[l+11],j,643717713),i=g(i,s,e,n,a[l+0],W,3921069994),n=g(n,i,s,e,a[l+5],M,3593408605),e=g(e,n,i,s,a[l+10],O,38016083),s=g(s,e,n,i,a[l+15],j,3634488961),i=g(i,s,e,n,a[l+4],W,3889429448),n=g(n,i,s,e,a[l+9],M,568446438),e=g(e,n,i,s,a[l+14],O,3275163606),s=g(s,e,n,i,a[l+3],j,4107603335),i=g(i,s,e,n,a[l+8],W,1163531501),n=g(n,i,s,e,a[l+13],M,2850285829),e=g(e,n,i,s,a[l+2],O,4243563512),s=g(s,e,n,i,a[l+7],j,1735328473),i=g(i,s,e,n,a[l+12],W,2368359562),n=y(n,i,s,e,a[l+5],V,4294588738),e=y(e,n,i,s,a[l+8],K,2272392833),s=y(s,e,n,i,a[l+11],U,1839030562),i=y(i,s,e,n,a[l+14],H,4259657740),n=y(n,i,s,e,a[l+1],V,2763975236),e=y(e,n,i,s,a[l+4],K,1272893353),s=y(s,e,n,i,a[l+7],U,4139469664),i=y(i,s,e,n,a[l+10],H,3200236656),n=y(n,i,s,e,a[l+13],V,681279174),e=y(e,n,i,s,a[l+0],K,3936430074),s=y(s,e,n,i,a[l+3],U,3572445317),i=y(i,s,e,n,a[l+6],H,76029189),n=y(n,i,s,e,a[l+9],V,3654602809),e=y(e,n,i,s,a[l+12],K,3873151461),s=y(s,e,n,i,a[l+15],U,530742520),i=y(i,s,e,n,a[l+2],H,3299628645),n=u(n,i,s,e,a[l+0],G,4096336452),e=u(e,n,i,s,a[l+7],q,1126891415),s=u(s,e,n,i,a[l+14],Q,2878612391),i=u(i,s,e,n,a[l+5],Y,4237533241),n=u(n,i,s,e,a[l+12],G,1700485571),e=u(e,n,i,s,a[l+3],q,2399980690),s=u(s,e,n,i,a[l+10],Q,4293915773),i=u(i,s,e,n,a[l+1],Y,2240044497),n=u(n,i,s,e,a[l+8],G,1873313359),e=u(e,n,i,s,a[l+15],q,4264355552),s=u(s,e,n,i,a[l+6],Q,2734768916),i=u(i,s,e,n,a[l+13],Y,1309151649),n=u(n,i,s,e,a[l+4],G,4149444226),e=u(e,n,i,s,a[l+11],q,3174756917),s=u(s,e,n,i,a[l+2],Q,718787259),i=u(i,s,e,n,a[l+9],Y,3951481745),n=t(n,P),i=t(i,D),s=t(s,$),e=t(e,v);return(F(n)+F(i)+F(s)+F(e)).toLowerCase()}var dt="https://www.rememberthemilk.com/services/auth/",nt="https://api.rememberthemilk.com/services/rest/",mt={apiKey:"",sharedSecret:"",authToken:"",defaultDueForNewTask:"none",noteCreationFolder:"",importWithNotesAndLink:!1},X=class extends f.Plugin{constructor(){super(...arguments);this.timeline=null}async onload(){await this.loadSettings(),this.addSettingTab(new et(this.app,this)),this.addCommand({id:"import-rtm-tasks",name:"Download all incomplete tasks",editorCallback:async(t,o)=>{this.checkAuth()&&await this.fetchAndProcessTasks("status:incomplete",!1,r=>{this.insertTasksToEditor(t,r)})}}),this.addCommand({id:"select-rtm-tasks",name:"Select and import tasks",editorCallback:async(t,o)=>{this.checkAuth()&&await this.fetchAndProcessTasks("status:incomplete",!0,r=>{this.insertTasksToEditor(t,r)})}}),this.addCommand({id:"import-rtm-tasks-custom",name:"Download tasks (Custom Filter)",editorCallback:async(t,o)=>{this.checkAuth()&&new tt(this.app,async r=>{await this.fetchAndProcessTasks(r,!0,c=>{this.insertTasksToEditor(t,c)})}).open()}}),this.addCommand({id:"create-note-from-rtm-task",name:"Create note from RTM task",callback:async()=>{this.checkAuth()&&await this.fetchAndProcessTasks("status:incomplete",!0,t=>{this.createNotesFromTasks(t)})}}),this.addCommand({id:"add-rtm-task",name:"Add cursor line to RTM",editorCallback:async(t,o)=>{this.checkAuth()&&await this.addTaskFromEditor(t,o)}}),this.addCommand({id:"complete-rtm-task",name:"Complete task at cursor",editorCallback:async(t,o)=>{this.checkAuth()&&await this.completeTaskInEditor(t)}})}checkAuth(){return!this.settings.apiKey||!this.settings.sharedSecret?(new f.Notice("Please set your API Key and Secret in settings."),!1):this.settings.authToken?!0:(new f.Notice("Please authenticate with RTM from settings."),!1)}async fetchListsMap(){let t={};try{let o=await this.callRtmApi("rtm.lists.getList");if(o.rsp.lists&&o.rsp.lists.list){let r=Array.isArray(o.rsp.lists.list)?o.rsp.lists.list:[o.rsp.lists.list];for(let c of r)c&&c.id&&c.name&&(t[c.id]=c.name)}}catch(o){console.error("List fetch error:",o)}return t}async fetchAndProcessTasks(t,o,r){new f.Notice("Fetching tasks...");try{let c=await this.fetchListsMap(),d=await this.callRtmApi("rtm.tasks.getList",{filter:t,notes:"1"});if(!d.rsp.tasks||!d.rsp.tasks.list){new f.Notice("No tasks found.");return}let m=[],g=Array.isArray(d.rsp.tasks.list)?d.rsp.tasks.list:[d.rsp.tasks.list];for(let y of g){if(!y.taskseries)continue;let u=Array.isArray(y.taskseries)?y.taskseries:[y.taskseries];for(let h of u){let F=h.name,T=Array.isArray(h.task)?h.task[0]:h.task,a=y.id;!a&&h.list_id&&(a=h.list_id),a||(a="MISSING");let l="";T.due&&T.due!==""&&(l=`\u{1F4C5} ${T.due.split("T")[0]}`);let P="";T.start&&T.start!==""&&(P=`\u{1F6EB} ${T.start.split("T")[0]}`);let D="";switch(T.priority){case"1":D="\u{1F53A}";break;case"2":D="\u{1F53C}";break;case"3":D="\u{1F53D}";break}let $="",v=c[a];v&&($=v);let n=[];h.tags&&h.tags.tag&&(Array.isArray(h.tags.tag)?h.tags.tag:[h.tags.tag]).forEach(e=>n.push(e));let i=[];h.notes&&h.notes.note&&(Array.isArray(h.notes.note)?h.notes.note:[h.notes.note]).forEach(e=>{let B=e.$t||e.toString();B&&i.push(B)}),m.push({name:F,due:l,start:P,priority:D,listName:$,tags:n,notes:i,rtmId:{list:a,series:h.id,task:T.id},rawPriority:T.priority,rawDue:T.due})}}o?new z(this.app,m,y=>{r(y)}).open():r(m)}catch(c){console.error(c),new f.Notice("Fetch error.")}}insertTasksToEditor(t,o){if(o.length===0){new f.Notice("No tasks selected.");return}let r="";for(let c of o){let d="";c.listName&&(d=` #${c.listName.replace(/[\s,.]+/g,"_")}`);let m=c.tags.map(h=>` #${h}`).join(""),g=`[\u{1F42E}](rtm:${c.rtmId.list}:${c.rtmId.series}:${c.rtmId.task})`,y=c.priority?` ${c.priority}`:"",u=c.due?` ${c.due}`:"";if(r+=`- [ ] ${g} ${c.name}${y}${u}${d}${m}
`,this.settings.importWithNotesAndLink){let h=`https://www.rememberthemilk.com/app/#all/${c.rtmId.task}`;r+=` - RTM Link: ${h}
`,c.notes&&c.notes.length>0&&c.notes.forEach(F=>{F.split(`
`).forEach(a=>{a.trim()!==""&&(r+=` - Note: ${a}
`)})})}}t.replaceSelection(r),new f.Notice(`${o.length} tasks inserted.`)}async createNotesFromTasks(t){if(t.length===0){new f.Notice("No tasks selected.");return}let o=0;for(let r of t){let c=r.name.replace(/[\\/:*?"<>|]/g,"-"),d=this.settings.noteCreationFolder.trim();d.endsWith("/")&&(d=d.slice(0,-1)),d.startsWith("/")&&(d=d.slice(1)),d&&await this.ensureFolderExists(d);let m=d?`${d}/${c}.md`:`${c}.md`;this.app.vault.getAbstractFileByPath(m)&&(m=d?`${d}/${c}-${Date.now()}.md`:`${c}-${Date.now()}.md`);let g=r.tags.map(h=>`#${h}`).join(" "),y=r.listName?`#${r.listName.replace(/[\s,.]+/g,"_")}`:"",u=`# ${r.name}
`;u+=`- **RTM Link**: [\u{1F42E} Open Task](rtm:${r.rtmId.list}:${r.rtmId.series}:${r.rtmId.task})
`,r.due&&(u+=`- **Due**: ${r.due}
`),r.start&&(u+=`- **Start**: ${r.start}
`),r.priority&&(u+=`- **Priority**: ${r.priority}
`),(y||g)&&(u+=`- **Tags**: ${y} ${g}
`),u+=`
---
`,r.notes.length>0?(u+=`## Notes
`,r.notes.forEach(h=>{u+=`${h}
`})):u+=`(No notes in RTM)
`;try{await this.app.vault.create(m,u),o++}catch(h){console.error(`Failed to create file: ${m}`,h),new f.Notice(`Failed to create note for "${r.name}"`)}}new f.Notice(`${o} notes created.`)}async addTaskFromEditor(t,o){let r=t.getCursor(),d=t.getLine(r.line).replace(/^[-*] \[[ x]\] /,"").replace(/^[-*] /,"").trim();if(!d){new f.Notice("Task name is empty.");return}new f.Notice(`Adding: ${d}`);let m=o.file?o.file.basename:"";try{let g=await this.getTimeline(),y=await this.callRtmApi("rtm.tasks.add",{timeline:g,name:d,parse:"1"}),u=Array.isArray(y.rsp.list)?y.rsp.list[0]:y.rsp.list,h=u.id,F=Array.isArray(u.taskseries)?u.taskseries[0]:u.taskseries,T=F.id,l=(Array.isArray(F.task)?F.task[0]:F.task).id;if(this.settings.defaultDueForNewTask==="today")try{await this.callRtmApi("rtm.tasks.setDueDate",{timeline:g,list_id:h,taskseries_id:T,task_id:l,due:"today",parse:"1"})}catch($){console.error("Failed to set due date",$)}if(m)try{await this.callRtmApi("rtm.tasks.notes.add",{timeline:g,list_id:h,taskseries_id:T,task_id:l,note_title:"Obsidian Link",note_text:`From Obsidian Note: [[${m}]]`})}catch($){console.error("Failed to add note to RTM task",$)}let D=`- [ ] ${`[\u{1F42E}](rtm:${h}:${T}:${l})`} ${d}`;t.setLine(r.line,D),new f.Notice("Added to RTM!")}catch(g){console.error("Add Task Error:",g),new f.Notice("Add error.")}}async completeTaskInEditor(t){let o=t.getCursor(),r=t.getLine(o.line),c=/\(rtm:([\w\d]+):([\w\d]+):([\w\d]+)\)/,d=r.match(c);if(!d){new f.Notice("Error: No RTM Link found.");return}let m=d[1],g=d[2],y=d[3];if(!m||m==="MISSING"){new f.Notice("Error: List ID invalid.");return}new f.Notice("Completing task...");try{let u=await this.getTimeline();await this.callRtmApi("rtm.tasks.complete",{timeline:u,list_id:m,taskseries_id:g,task_id:y});let h=r.replace("- [ ]","- [x]");t.setLine(o.line,h),new f.Notice("Task completed!")}catch(u){console.error("Completion Error:",u),new f.Notice("Completion error.")}}async getTimeline(){if(this.timeline)return this.timeline;let t=await this.callRtmApi("rtm.timelines.create");return this.timeline=t.rsp.timeline,this.timeline}async callRtmApi(t,o={}){var h;let r=this.settings.apiKey,c=this.settings.sharedSecret;if(!r||!c)throw new Error("API Key/Secret missing");let d={...o,method:t,api_key:r,format:"json",auth_token:this.settings.authToken},m=Object.keys(d).sort(),g=c;for(let F of m)g+=F+d[F];d.api_sig=I(g);let y=`${nt}?${new URLSearchParams(d).toString()}`,u=await(0,f.requestUrl)({url:y});if(u.json.rsp.stat!=="ok")throw console.error("API Error:",u.json),new Error(`API Error: ${(h=u.json.rsp.err)==null?void 0:h.msg}`);return u.json}async ensureFolderExists(t){if(!t)return;let o=t.split("/"),r="";for(let c of o)if(c&&(r=r===""?c:`${r}/${c}`,!this.app.vault.getAbstractFileByPath(r)))try{await this.app.vault.createFolder(r)}catch(d){console.error(`Failed to create folder: ${r}`,d)}}async loadSettings(){this.settings=Object.assign({},mt,await this.loadData())}async saveSettings(){await this.saveData(this.settings)}},z=class extends f.Modal{constructor(p,t,o){super(p),this.tasks=t,this.selected=new Array(t.length).fill(!1),this.onSubmit=o}onOpen(){let{contentEl:p}=this;p.createEl("h2",{text:`Select Tasks (${this.tasks.length})`});let t=p.createDiv();t.style.maxHeight="400px",t.style.overflowY="auto",t.style.marginBottom="10px",this.tasks.forEach((d,m)=>{var F;let g=t.createDiv();g.style.display="flex",g.style.alignItems="center",g.style.padding="5px 0",g.style.borderBottom="1px solid var(--background-modifier-border)";let y=g.createEl("input",{type:"checkbox"});y.checked=(F=this.selected[m])!=null?F:!1,y.onchange=T=>{this.selected[m]=T.target.checked};let u=g.createSpan();u.style.marginLeft="10px";let h=`<b>${d.name}</b>`;d.listName&&(h+=` <small style="color:var(--text-muted)">[${d.listName}]</small>`),d.due&&(h+=` <small style="color:var(--text-accent)">${d.due}</small>`),d.notes&&d.notes.length>0&&(h+=" <small>\u{1F4DD}</small>"),u.innerHTML=h});let o=p.createDiv();o.style.display="flex",o.style.justifyContent="flex-end",o.style.gap="10px";let r=o.createEl("button",{text:"Select All"});r.onclick=()=>{let d=this.selected.every(Boolean);this.selected.fill(!d),t.querySelectorAll('input[type="checkbox"]').forEach(g=>g.checked=!d),r.textContent=d?"Select All":"Deselect All"};let c=o.createEl("button",{text:"Process Selected"});c.className="mod-cta",c.onclick=()=>{let d=this.tasks.filter((m,g)=>this.selected[g]);this.onSubmit(d),this.close()}}onClose(){this.contentEl.empty()}},tt=class extends f.Modal{constructor(p,t){super(p),this.onSubmit=t}onOpen(){let{contentEl:p}=this;p.createEl("h3",{text:"Filter RTM Tasks"}),new f.Setting(p).setName("Search Query").setDesc("e.g. list:Inbox, due:today").addText(t=>t.setValue("status:incomplete").onChange(o=>{}).inputEl.addEventListener("keydown",o=>{o.key==="Enter"&&(this.onSubmit(t.getValue()),this.close())})),new f.Setting(p).addButton(t=>t.setButtonText("Search").setCta().onClick(()=>{let o=p.querySelector("input");o&&(this.onSubmit(o.value),this.close())}))}onClose(){this.contentEl.empty()}},et=class extends f.PluginSettingTab{constructor(p,t){super(p,t),this.plugin=t}display(){let{containerEl:p}=this;p.empty(),p.createEl("h2",{text:"Remember The Milk Settings"});let t="6/4/2026, 9:42:32 AM";p.createEl("p",{text:`Version: ${this.plugin.manifest.version} (Build: ${t})`,cls:"setting-item-description"}).style.marginBottom="2em",new f.Setting(p).setName("API Key").addText(o=>o.setValue(this.plugin.settings.apiKey).onChange(async r=>{this.plugin.settings.apiKey=r,await this.plugin.saveSettings()})),new f.Setting(p).setName("Shared Secret").addText(o=>o.setValue(this.plugin.settings.sharedSecret).onChange(async r=>{this.plugin.settings.sharedSecret=r,await this.plugin.saveSettings()})),new f.Setting(p).setName("Auth").addButton(o=>o.setButtonText("Start Auth").onClick(async()=>await this.startAuthProcess())),new f.Setting(p).setName("Default Due Date").setDesc("Setting for new tasks created from editor").addDropdown(o=>o.addOption("none","No Due Date").addOption("today","Today").setValue(this.plugin.settings.defaultDueForNewTask).onChange(async r=>{this.plugin.settings.defaultDueForNewTask=r,await this.plugin.saveSettings()})),new f.Setting(p).setName("Note Creation Folder").setDesc("Folder to create notes from RTM tasks.").addDropdown(o=>{o.addOption("","/ (Vault Root)"),this.app.vault.getAllLoadedFiles().filter(c=>c instanceof f.TFolder).forEach(c=>{c.path!=="/"&&o.addOption(c.path,c.path)}),o.setValue(this.plugin.settings.noteCreationFolder),o.onChange(async c=>{this.plugin.settings.noteCreationFolder=c,await this.plugin.saveSettings()})}),new f.Setting(p).setName("Import with Notes and RTM Link").setDesc("When inserting tasks to the editor, also include RTM task notes and links as sub-items.").addToggle(o=>o.setValue(this.plugin.settings.importWithNotesAndLink).onChange(async r=>{this.plugin.settings.importWithNotesAndLink=r,await this.plugin.saveSettings()}))}async startAuthProcess(){let p=this.plugin,t=p.settings.apiKey,o=p.settings.sharedSecret;if(!t||!o){new f.Notice("Enter keys first");return}let r={method:"rtm.auth.getFrob",api_key:t,format:"json"},c=o;Object.keys(r).sort().forEach(h=>c+=h+r[h]),r.api_sig=I(c);let m=(await(0,f.requestUrl)({url:`${nt}?${new URLSearchParams(r).toString()}`})).json.rsp.frob,g={api_key:t,perms:"delete",frob:m},y=o;Object.keys(g).sort().forEach(h=>y+=h+g[h]);let u=I(y);window.open(`${dt}?api_key=${t}&perms=delete&frob=${m}&api_sig=${u}`),new st(this.app,m,p,async()=>{this.display()}).open()}},st=class extends f.Modal{constructor(p,t,o,r){super(p),this.frob=t,this.plugin=o,this.onSuccess=r}onOpen(){let{contentEl:p}=this;new f.Setting(p).addButton(t=>t.setButtonText("Finish Auth").setCta().onClick(async()=>{let o=this.plugin.settings.apiKey,r=this.plugin.settings.sharedSecret,c={method:"rtm.auth.getToken",api_key:o,format:"json",frob:this.frob},d=r;Object.keys(c).sort().forEach(m=>d+=m+c[m]),c.api_sig=I(d);try{let m=await(0,f.requestUrl)({url:`${nt}?${new URLSearchParams(c).toString()}`});m.json.rsp.auth?(this.plugin.settings.authToken=m.json.rsp.auth.token,await this.plugin.saveSettings(),new f.Notice("Success!"),this.onSuccess(),this.close()):new f.Notice("Failed.")}catch(m){new f.Notice("Error.")}}))}onClose(){this.contentEl.empty()}};