-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.min.js
1 lines (1 loc) · 28.2 KB
/
index.min.js
1
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).GcalSync=t()}(this,(function(){"use strict";const e={name:"gcal-sync",github_repository:"lucasvtiradentes/gcal-sync",version:"1.11.0",build_date_time:"28/01/2024 19:00:37"},t=e=>e.reduce(((e,t)=>e.concat(t)),[]);function i(e,t){const i=e.filter((e=>!t.includes(e))),n=t.filter((t=>!e.includes(t)));return i.concat(n)}const n=(e,t,i)=>e.reduce(((e,n)=>{const s=n[t],o=n[i];return e[s]=o,e}),{});var s;const o={DEBUG_MODE:!0,MAX_GCAL_TASKS:2500,REQUIRED_GITHUB_VALIDATIONS_COUNT:3,IS_TEST_ENVIRONMENT:"object"==typeof process&&(null===(s=null===process||void 0===process?void 0:process.env)||void 0===s?void 0:s.NODE_ENV)},r=[{key:"today_ticktick_added_tasks",initial_value:[]},{key:"today_ticktick_updated_tasks",initial_value:[]},{key:"today_ticktick_completed_tasks",initial_value:[]},{key:"today_github_added_commits",initial_value:[]},{key:"today_github_deleted_commits",initial_value:[]},{key:"last_released_version_alerted",initial_value:""},{key:"last_released_version_sent_date",initial_value:""},{key:"last_daily_email_sent_date",initial_value:""},{key:"github_commits_tracked_to_be_added",initial_value:[]},{key:"github_commits_tracked_to_be_deleted",initial_value:[]},{key:"github_commit_changes_count",initial_value:""}],a=n(r,"key","initial_value"),c=n(r,"key","key"),d={invalid_configs:"schema invalid",production_only:"This method cannot run in non-production environments",incorrect_ics_calendar:"The link you provided is not a valid ICS calendar: ",abusive_google_calendar_api_use:"Due to the numerous operations in the last few hours, the google api is not responding.",invalid_ics_calendar_link:"You provided an invalid ICS calendar link: ",invalid_github_token:"You provided an invalid github token",invalid_github_username:"You provided an invalid github username"},l="ticktick_sync",m="github_sync";const _={tableStyle:'style="border: 1px solid #333; width: 90%"',tableRowStyle:'style="width: 100%"',tableRowColumnStyle:'style="border: 1px solid #333"'},u=e=>"date"in e?e.date:e.dateTime;function g(e){return e.added_tasks.length+e.updated_tasks.length+e.completed_tasks.length+e.commits_added.length+e.commits_deleted.length}function p(t){let i="";return i=`Hi!<br/><br/>there were ${g(t)} changes made to your google calendar:<br/>\n`,i+=function(e){const t=e.added_tasks,i=e.updated_tasks,n=e.completed_tasks,s=e=>0===e.length?"":`${e.map((e=>{const t=[u(e.start).split("T")[0],e.extendedProperties.private.calendar,`<a href="${e.htmlLink}">${e.summary}</a>`].map((e=>`<td ${_.tableRowColumnStyle}> ${e}</td>`)).join("\n");return`<tr ${_.tableRowStyle}">\n${t}\n</tr>`})).join("\n")}`,o=`<tr ${_.tableRowStyle}">\n<th ${_.tableRowColumnStyle} width="80px">date</th><th ${_.tableRowColumnStyle} width="130px">calendar</th><th ${_.tableRowColumnStyle} width="auto">task</th>\n</tr>`;let r="";return r+=t.length>0?`<br/>added ticktick events : ${t.length}<br/><br/> \n <center>\n<table ${_.tableStyle}>\n${o}\n${s(t)}\n</table>\n</center>\n`:"",r+=i.length>0?`<br/>updated ticktick events : ${i.length}<br/><br/> \n <center>\n<table ${_.tableStyle}>\n${o}\n${s(i)}\n</table>\n</center>\n`:"",r+=n.length>0?`<br/>completed ticktick events: ${n.length}<br/><br/> \n <center>\n<table ${_.tableStyle}>\n${o}\n${s(n)}\n</table>\n</center>\n`:"",r}(t),i+=function(e){const t=e.commits_added,i=e.commits_deleted,n=e=>0===e.length?"":`${e.map((e=>{const{repositoryLink:t,commitMessage:i,repositoryName:n}=e.extendedProperties.private,s=[u(e.start).split("T")[0],`<a href="${t}">${n}</a>`,`<a href="${e.htmlLink}">${i}</a>`].map((e=>`<td ${_.tableRowColumnStyle}> ${e}</td>`)).join("\n");return`<tr ${_.tableRowStyle}">\n${s}\n</tr>`})).join("\n")}`,s=`<tr ${_.tableRowStyle}">\n<th ${_.tableRowColumnStyle} width="80px">date</th><th ${_.tableRowColumnStyle} width="130px">repository</th><th ${_.tableRowColumnStyle} width="auto">commit</th>\n</tr>`;let o="";return o+=t.length>0?`<br/>added commits events : ${t.length}<br/><br/> \n <center>\n<table ${_.tableStyle}>\n${s}\n${n(t)}\n</table>\n</center>\n`:"",o+=i.length>0?`<br/>removed commits events : ${i.length}<br/><br/> \n <center>\n<table ${_.tableStyle}>\n${s}\n${n(i)}\n</table>\n</center>\n`:"",o}(t),i+=`<br/>Regards,<br/>your <a href='https://github.com/${e.github_repository}'>${e.name}</a> bot`,i}function h(e){return{shouldSyncGithub:e.configs[m].commits_configs.should_sync,shouldSyncTicktick:e.configs[l].should_sync}}function f(e){const t=PropertiesService.getScriptProperties().getProperty(e);let i;try{i=JSON.parse(t)}catch(e){i=t}return i}function b(e,t){const i="string"==typeof t?t:JSON.stringify(t);PropertiesService.getScriptProperties().setProperty(e,i)}function y(e){const t=ScriptApp.getProjectTriggers().find((t=>t.getHandlerFunction()===e));t&&ScriptApp.deleteTrigger(t)}function k(e){MailApp.sendEmail(e)}const v=new class{constructor(){this.logs=[]}info(e,...t){o.IS_TEST_ENVIRONMENT||(console.log(e,...t),this.logs.push(e))}error(e,...t){o.IS_TEST_ENVIRONMENT||(console.error(e,...t),this.logs.push(e))}};function $(e){const t=e.split("T");return{year:t[0].substring(0,4),month:t[0].substring(4,6),day:t[0].substring(6,8),hours:t[1]?t[1].substring(0,2):"00",minutes:t[1]?t[1].substring(2,4):"00",seconds:t[1]?t[1].substring(4,6):"00"}}function T(e,t){const i=function(e){const t=new Date;return t.setHours(t.getHours()+e),t}(t),n=60*Number(i.getHours())+Number(i.getMinutes()),s=e.split(":");return n>=60*Number(s[0])+Number(s[1])}function S(t,i){const{shouldSyncGithub:n,shouldSyncTicktick:s}=h(t),o=i.added_tasks.length+i.updated_tasks.length+i.completed_tasks.length;if(s&&o>0){const e=f(c.today_ticktick_added_tasks),t=f(c.today_ticktick_updated_tasks),n=f(c.today_ticktick_completed_tasks);b(c.today_ticktick_added_tasks,[...e,...i.added_tasks]),b(c.today_ticktick_updated_tasks,[...t,...i.updated_tasks]),b(c.today_ticktick_completed_tasks,[...n,...i.completed_tasks]),v.info(`added ${o} new ticktick items to today's stats`)}const r=i.commits_added.length+i.commits_deleted.length;if(n&&r>0){const e=f(c.today_github_added_commits),t=f(c.today_github_deleted_commits);b(c.today_github_added_commits,[...e,...i.commits_added]),b(c.today_github_deleted_commits,[...t,...i.commits_deleted]),v.info(`added ${r} new github items to today's stats`)}!function(t,i,n){var s;const o=t.user_email;if(t.configs.settings.per_sync_emails.email_session&&n>0){k(function(t,i){const n=p(i);return{to:t,name:`${e.name}`,subject:`session report - ${g(i)} modifications - ${e.name}`,htmlBody:n}}(o,i))}const r=T(t.configs.settings.per_day_emails.time_to_send,t.timezone_offset),a=t.today_date===f(c.last_daily_email_sent_date);if(r&&t.configs.settings.per_day_emails.email_daily_summary&&!a){b(c.last_daily_email_sent_date,t.today_date);k(function(t,i,n){const s=p(i);return{to:t,name:`${e.name}`,subject:`daily report for ${n} - ${g(i)} modifications - ${e.name}`,htmlBody:s}}(o,{added_tasks:f(c.today_ticktick_added_tasks),updated_tasks:f(c.today_ticktick_updated_tasks),completed_tasks:f(c.today_ticktick_completed_tasks),commits_added:f(c.today_github_added_commits),commits_deleted:f(c.today_github_deleted_commits)},t.today_date)),b(c.today_github_added_commits,[]),b(c.today_github_deleted_commits,[]),b(c.today_ticktick_added_tasks,[]),b(c.today_ticktick_completed_tasks,[]),b(c.today_ticktick_updated_tasks,[]),v.info("today stats were reseted!")}const d=t.today_date===f(c.last_released_version_sent_date),l=e=>Number(e.replace("v","").split(".").join("")),m=()=>{var t;const i=UrlFetchApp.fetch(`https://api.github.com/repos/${e.github_repository}/releases?per_page=1`);return null!==(t=JSON.parse(i.getContentText())[0])&&void 0!==t?t:{tag_name:e.version}};if(r&&t.configs.settings.per_day_emails.email_new_gcal_sync_release&&!d){b(c.last_released_version_sent_date,t.today_date);const i=m(),n=l(i.tag_name),r=l(e.version),a=null!==(s=f(c.last_released_version_alerted))&&void 0!==s?s:"";if(n>r&&n.toString()!=a){k(function(t,i){const n=`Hi!\n <br/><br/>\n a new <a href="https://github.com/${e.github_repository}">${e.name}</a> version is available: <br/>\n <ul>\n <li>new version: ${i.tag_name}</li>\n <li>published at: ${i.published_at}</li>\n <li>details: <a href="https://github.com/${e.github_repository}/releases">here</a></li>\n </ul>\n to update, replace the old version number in your apps scripts <a href="https://script.google.com/">gcal sync project</a> to the new version: ${i.tag_name.replace("v","")}<br/>\n and also check if you need to change the setup code in the <a href='https://github.com/${e.github_repository}#installation'>installation section</a>.\n <br /><br />\n Regards,\n your <a href='https://github.com/${e.github_repository}'>${e.name}</a> bot\n `;return{to:t,name:`${e.name}`,subject:`new version [${i.tag_name}] was released - ${e.name}`,htmlBody:n}}(o,i)),b(c.last_released_version_alerted,n.toString())}}}(t,i,o+r);const{added_tasks:a,updated_tasks:d,completed_tasks:l,commits_added:m,commits_deleted:_,commits_tracked_to_be_added:u,commits_tracked_to_be_deleted:y}=i;return{added_tasks:a.length,updated_tasks:d.length,completed_tasks:l.length,commits_added:m.length,commits_deleted:_.length,commits_tracked_to_be_added:u.length,commits_tracked_to_be_deleted:y.length}}function w(e,t){var i;const n=[];let s=1,o=!1;for(;!1===o;){const r=`https://api.github.com/search/commits?q=author:${e}&page=${s}&sort=committer-date&per_page=100`;let a;a=""!==t?UrlFetchApp.fetch(r,{muteHttpExceptions:!0,headers:{Authorization:`Bearer ${t}`}}):UrlFetchApp.fetch(r,{muteHttpExceptions:!0});const c=null!==(i=JSON.parse(a.getContentText()))&&void 0!==i?i:{};if(200!==a.getResponseCode()){if("Validation Failed"===c.message)throw new Error(d.invalid_github_username);if("Bad credentials"===c.message)throw new Error(d.invalid_github_token);throw new Error(c.message)}const l=c.items;if(0===l.length){o=!0;break}if(n.push(...l),s++,s>10){o=!0;break}}return n.map((e=>({commitDate:e.commit.author.date,commitMessage:e.commit.message.split("\n")[0],commitId:e.html_url.split("commit/")[1],commitUrl:e.html_url,repository:e.repository.full_name,repositoryLink:`https://github.com/${e.repository.full_name}`,repositoryId:e.repository.id,repositoryName:e.repository.name,repositoryOwner:e.repository.owner.login,repositoryDescription:e.repository.description,isRepositoryPrivate:e.repository.private,isRepositoryFork:e.repository.fork})))}function I(e){const t={":art:":"🎨",":zap:":"⚡️",":fire:":"🔥",":bug:":"🐛",":ambulance:":"🚑️",":sparkles:":"✨",":memo:":"📝",":rocket:":"🚀",":lipstick:":"💄",":tada:":"🎉",":white_check_mark:":"✅",":lock:":"🔒️",":closed_lock_with_key:":"🔐",":bookmark:":"🔖",":rotating_light:":"🚨",":construction:":"🚧",":green_heart:":"💚",":arrow_down:":"⬇️",":arrow_up:":"⬆️",":pushpin:":"📌",":construction_worker:":"👷",":chart_with_upwards_trend:":"📈",":recycle:":"♻️",":heavy_plus_sign:":"➕",":heavy_minus_sign:":"➖",":wrench:":"🔧",":hammer:":"🔨",":globe_with_meridians:":"🌐",":pencil2:":"✏️",":poop:":"💩",":rewind:":"⏪️",":twisted_rightwards_arrows:":"🔀",":package:":"📦️",":alien:":"👽️",":truck:":"🚚",":page_facing_up:":"📄",":boom:":"💥",":bento:":"🍱",":wheelchair:":"♿️",":bulb:":"💡",":beers:":"🍻",":speech_balloon:":"💬",":card_file_box:":"🗃️",":loud_sound:":"🔊",":mute:":"🔇",":busts_in_silhouette:":"👥",":children_crossing:":"🚸",":building_construction:":"🏗️",":iphone:":"📱",":clown_face:":"🤡",":egg:":"🥚",":see_no_evil:":"🙈",":camera_flash:":"📸",":alembic:":"⚗️",":mag:":"🔍️",":label:":"🏷️",":seedling:":"🌱",":triangular_flag_on_post:":"🚩",":goal_net:":"🥅",":dizzy:":"💫",":wastebasket:":"🗑️",":passport_control:":"🛂",":adhesive_bandage:":"🩹",":monocle_face:":"🧐",":coffin:":"⚰️",":test_tube:":"🧪",":necktie:":"👔",":stethoscope:":"🩺",":bricks:":"🧱",":technologist:":"🧑💻",":money_with_wings:":"💸",":thread:":"🧵",":safety_vest:":"🦺"};let i=e;for(const[e,n]of Object.entries(t))i=i.replace(e,n);return i}const E=()=>{var e;return null!==(e=Calendar.CalendarList.list({showHidden:!0}).items)&&void 0!==e?e:[]},C=e=>E().find((t=>t.summary===e)),D=e=>{const t=Calendar;if(t.CalendarList.list({showHidden:!0}).items.filter((e=>"owner"===e.accessRole)).map((e=>e.summary)).includes(e))throw new Error(`calendar ${e} already exists!`);const i=t.newCalendar();i.summary=e,i.timeZone=t.Settings.get("timezone").value;return t.Calendars.insert(i)};function x(e){return E().find((t=>t.summary===e))}function N(e){const t=e.reduce(((e,t)=>{const i=function(e){const t=Calendar.Events.list(e.id,{maxResults:o.MAX_GCAL_TASKS}).items.map((e=>function(e){var t,i,n,s,o;return{id:e.id,summary:e.summary,description:null!==(t=e.description)&&void 0!==t?t:"",htmlLink:e.htmlLink,attendees:null!==(i=e.attendees)&&void 0!==i?i:[],reminders:null!==(n=e.reminders)&&void 0!==n?n:{},visibility:null!==(s=e.visibility)&&void 0!==s?s:"default",start:e.start,end:e.end,created:e.created,updated:e.updated,colorId:e.colorId,extendedProperties:null!==(o=e.extendedProperties)&&void 0!==o?o:{}}}(e)));return t}(x(t));return[...e,...i]}),[]);return t}function R(e,t){return Calendar.Events.insert(t,e.id)}function A(e,t,i){const n=function(e,t){const i=Calendar.Events.get(e.id,t);return i}(e,t.id),s=Object.assign(Object.assign({},n),i);return Calendar.Events.update(s,e.id,t.id)}function O(e,t,i){P(e,i),Utilities.sleep(2e3);return R(t,i)}function P(e,t){Calendar.Events.remove(e.id,t.id)}function M(){b("github_commit_changes_count","0"),b("github_commits_tracked_to_be_added",[]),b("github_commits_tracked_to_be_deleted",[])}function U(e,t){return t.sort(((e,t)=>Number(new Date(t.commitDate))-Number(new Date(e.commitDate)))).filter((t=>t.repository.includes(e[m].username))).filter((t=>!1===e[m].commits_configs.ignored_repos.includes(t.repositoryName)))}function G(e){v.info("syncing github commits");const t={githubCommits:w(e[m].username,e[m].personal_token),githubGcalCommits:N([e[m].commits_configs.commits_calendar])},n=f("github_commit_changes_count"),s=Number(n)+1;null===n&&M(),b("github_commit_changes_count",s.toString()),1===s?v.info(`checking commit changes: ${s}/${o.REQUIRED_GITHUB_VALIDATIONS_COUNT}`):s>1&&s<o.REQUIRED_GITHUB_VALIDATIONS_COUNT?v.info(`confirming commit changes: ${s}/${o.REQUIRED_GITHUB_VALIDATIONS_COUNT}`):s===o.REQUIRED_GITHUB_VALIDATIONS_COUNT&&v.info(`making commit changes if succeed: ${s}/${o.REQUIRED_GITHUB_VALIDATIONS_COUNT}`);const r=U(e,t.githubCommits),a=x(e[m].commits_configs.commits_calendar),c=Object.assign(Object.assign({},function({filteredRepos:e,currentGithubSyncIndex:t,githubCalendar:n,githubGcalCommits:s,parseCommitEmojis:r}){const a={commits_tracked_to_be_added:[],commits_added:[]};for(const t of e){if(!s.filter((e=>e.extendedProperties.private.repository===t.repository)).find((e=>e.extendedProperties.private.commitDate===t.commitDate&&I(e.extendedProperties.private.commitMessage)===I(t.commitMessage)))){const e=r?I(t.commitMessage):t.commitMessage,i={private:{commitMessage:e,commitDate:t.commitDate,repository:t.repository,repositoryName:t.repositoryName,repositoryLink:t.repositoryLink,commitId:t.commitId}},n={summary:`${t.repositoryName} - ${e}`,description:`repository: https://github.com/${t.repository}\ncommit: ${t.commitUrl}`,start:{dateTime:t.commitDate},end:{dateTime:t.commitDate},reminders:{useDefault:!1,overrides:[]},extendedProperties:i};a.commits_tracked_to_be_added.push(n)}}if(1===t)return b("github_commits_tracked_to_be_added",a.commits_tracked_to_be_added.map((e=>e))),a;const c=f("github_commits_tracked_to_be_added").map((e=>e.extendedProperties.private.commitId)),d=a.commits_tracked_to_be_added.map((e=>e.extendedProperties.private.commitId));if(i(c,d).length>0)return v.info("reset github commit properties due differences in added commits"),M(),a;if(t===o.REQUIRED_GITHUB_VALIDATIONS_COUNT&&a.commits_tracked_to_be_added.length>0){v.info(`adding ${a.commits_tracked_to_be_added.length} commits to gcal`);for(let e=0;e<a.commits_tracked_to_be_added.length;e++)try{const t=a.commits_tracked_to_be_added[e],i=R(n,t);a.commits_added.push(i),v.info(`${e+1}/${a.commits_tracked_to_be_added.length} add new commit to gcal: ${t.extendedProperties.private.commitDate} - ${i.extendedProperties.private.repositoryName} - ${i.extendedProperties.private.commitMessage}`)}catch(e){throw new Error(e.message)}finally{M()}}return a}({currentGithubSyncIndex:s,githubCalendar:a,githubGcalCommits:t.githubGcalCommits,filteredRepos:r,parseCommitEmojis:e[m].commits_configs.parse_commit_emojis})),function({githubGcalCommits:e,githubCalendar:t,currentGithubSyncIndex:n,filteredRepos:s}){const r={commits_deleted:[],commits_tracked_to_be_deleted:[]};if(e.forEach((e=>{const t=e.extendedProperties.private;s.filter((e=>e.repository===t.repository)).find((e=>e.commitDate===t.commitDate&&I(e.commitMessage)===I(t.commitMessage)))||r.commits_tracked_to_be_deleted.push(e)})),1===n)return b("github_commits_tracked_to_be_deleted",r.commits_tracked_to_be_deleted),r;const a=f("github_commits_tracked_to_be_deleted").map((e=>e.extendedProperties.private.commitId)),c=r.commits_tracked_to_be_deleted.map((e=>e.extendedProperties.private.commitId));if(i(a,c).length>0)return v.info("reset github commit properties due differences in deleted commits"),M(),r;if(n===o.REQUIRED_GITHUB_VALIDATIONS_COUNT&&r.commits_tracked_to_be_deleted.length>0){v.info(`deleting ${r.commits_tracked_to_be_deleted.length} commits on gcal`);for(let e=0;e<r.commits_tracked_to_be_deleted.length;e++)try{const i=r.commits_tracked_to_be_deleted[e];P(t,i),r.commits_deleted.push(i),v.info(`${e+1}/${r.commits_tracked_to_be_deleted.length} deleted commit on gcal: ${i.extendedProperties.private.commitDate} - ${i.extendedProperties.private.repositoryName} - ${i.extendedProperties.private.commitMessage}`)}catch(e){throw new Error(e.message)}finally{M()}}return r}({currentGithubSyncIndex:s,githubCalendar:a,githubGcalCommits:t.githubGcalCommits,filteredRepos:r}));return 0===c.commits_tracked_to_be_added.length&&0===c.commits_tracked_to_be_deleted.length&&(v.info("reset github commit properties due found no commits tracked"),M()),c}const j=(e,t,i)=>{const n=e.slice(e.search(t)).replace(t,"");return n.slice(0,n.search(i))},L=(e,t)=>{const i=e.replace("webcal://","https://"),n=UrlFetchApp.fetch(i,{validateHttpsCertificates:!1,muteHttpExceptions:!0}),s=n.getContentText()||"";if(200!==n.getResponseCode())throw new Error(d.invalid_ics_calendar_link+i);if(-1===s.search("BEGIN:VCALENDAR"))throw new Error(d.incorrect_ics_calendar);const o=s.split("BEGIN:VEVENT\r\n").filter((e=>e.search("SUMMARY")>-1)),r=(s.search("SUMMARY:No task.")>0?[]:o.reduce(((e,t)=>{const i=t.split("BEGIN:VALARM\r\n");return[...e,{CALNAME:j(s,"X-WR-CALNAME:","\r\n"),DSTAMP:j(t,"DTSTAMP:","\r\n"),DTSTART:j(t,"DTSTART;","\r\n"),DTEND:j(t,"DTEND;","\r\n"),SUMMARY:j(t,"SUMMARY:","\r\n"),UID:j(t,"UID:","\r\n"),DESCRIPTION:j(t,"DESCRIPTION:","\r\n"),SEQUENCE:j(t,"SEQUENCE:","\r\n"),TZID:j(t,"TZID:","\r\n"),ALARM_TRIGGER:1===i.length?"":j(i[1],"TRIGGER:","\r\n"),ALARM_ACTION:1===i.length?"":j(i[1],"ACTION:","\r\n"),ALARM_DESCRIPTION:1===i.length?"":j(i[1],"DESCRIPTION:","\r\n")}]}),[])).map((e=>{const i=function(e,t,i,n){let s=e,o=t;if(s=s.slice(s.search(":")+1),o=o.slice(o.search(":")+1),""===o){const e=$(s),t=new Date(Date.UTC(Number(e.year),Number(e.month)-1,Number(e.day),0,0,0));t.setDate(t.getDate()+1),o={date:t.toISOString().split("T")[0]},s={date:`${e.year}-${e.month}-${e.day}`}}else{const e=$(s),t=$(o),r=(e=>0===e?"":`${e<0?"-":"+"}${String(Math.abs(e)).padStart(2,"0")}:00`)(n);s={dateTime:`${e.year}-${e.month}-${e.day}T${e.hours}:${e.minutes}:${e.seconds}${r}`,timeZone:i},o={dateTime:`${t.year}-${t.month}-${t.day}T${t.hours}:${t.minutes}:${t.seconds}${r}`,timeZone:i}}return{finalDtstart:s,finalDtend:o}}(e.DTSTART,e.DTEND,e.TZID,t);return{id:e.UID,name:e.SUMMARY,description:e.DESCRIPTION,tzid:e.TZID,start:i.finalDtstart,end:i.finalDtend}}));return r};function H(e){v.info("syncing ticktick tasks");const t=e.configs[l].ics_calendars,i={ticktickTasks:F(t,e.timezone_offset),ticktickGcalTasks:N([...new Set(t.map((e=>e.gcal)))])},n=Object.assign(Object.assign({},function({ticktickGcalTasks:e,ticktickTasks:t}){const i={added_tasks:[],updated_tasks:[]};for(const n of t){const t=e.find((e=>e.extendedProperties.private.tickTaskId===n.id)),s=x(n.gcal);if(t){const e=s.summary!==t.extendedProperties.private.calendar,o=Q(n,t),r=x(n.gcal_done),a={private:{calendar:n.gcal,completedCalendar:n.gcal_done,tickTaskId:n.id}},c={summary:n.name,description:V(n),start:n.start,end:n.end,extendedProperties:a,colorId:(null==n?void 0:n.color)?null==n?void 0:n.color.toString():void 0};if(e){const e=O(s,r,Object.assign(Object.assign({},t),c));i.updated_tasks.push(e)}else if(o.length>0){const e=A(s,t,c);i.updated_tasks.push(e)}}else{const e=z(s,n);i.added_tasks.push(e)}}return i}(i)),function({ticktickGcalTasks:e,ticktickTasks:t}){const i={completed_tasks:[]},n=e.filter((e=>{var t,i;return null===(i=null===(t=e.extendedProperties)||void 0===t?void 0:t.private)||void 0===i?void 0:i.tickTaskId}));for(const e of n){if(!t.map((e=>e.id)).includes(e.extendedProperties.private.tickTaskId)){const t=O(x(e.extendedProperties.private.calendar),x(e.extendedProperties.private.completedCalendar),Object.assign(Object.assign({},e),{colorId:void 0}));i.completed_tasks.push(t)}}return i}(i));return n}const B=e=>{let t=e;return t=t.replace(/\\,/g,","),t=t.replace(/\\;/g,";"),t=t.replace(/\\"/g,'"'),t=t.replace(/\\\\/g,"\\"),t},V=e=>`task: https://ticktick.com/webapp/#q/all/tasks/${e.id.split("@")[0]}${e.description?"\n\n"+e.description.replace(/\\n/g,"\n"):""}`;function z(e,t){const i=function(e){const t={private:{calendar:e.gcal,completedCalendar:e.gcal_done,tickTaskId:e.id}},i=(null==e?void 0:e.color)?{colorId:e.color.toString()}:{};return Object.assign({summary:B(e.name),description:V(e),start:e.start,end:e.end,reminders:{useDefault:!0},extendedProperties:t},i)}(t);try{return R(e,i)}catch(e){throw e.message.search("API call to calendar.events.insert failed with error: Required")>-1?new Error(d.abusive_google_calendar_api_use):new Error(e.message)}}function Q(e,t){return[{hasChanged:B(e.name)!==t.summary,field:"name"},{hasChanged:Object.keys(e.start).length!==Object.keys(t.start).length,field:"date format"},{hasChanged:e.start.date!==t.start.date||e.start.dateTime!==t.start.dateTime,field:"initial date"},{hasChanged:e.end.date!==t.end.date||e.end.dateTime!==t.end.dateTime,field:"final date"},{hasChanged:(()=>{let i=!1;return i=void 0===(null==e?void 0:e.color)?void 0!==t.colorId:e.color.toString()!==t.colorId,i})(),field:"color"}].filter((e=>e.hasChanged)).map((e=>e.field))}function Z(e,i){const n=[];for(const t of e){const e=L(t.link,i).map((e=>Object.assign(Object.assign({},e),t)));n.push(e)}return t(n)}function F(e,t){const i=Z(e.filter((e=>e.tag)),t),n=Z(e.filter((e=>e.ignoredTags)),t).filter((e=>{const t=i.map((e=>`${e.tag}${e.id}`));return!1===e.ignoredTags.some((i=>t.includes(`${i}${e.id}`)))})),s=Z(e.filter((e=>!e.tag&&!e.ignoredTags)),t);return[...i,...n,...s]}function Y(e){return"object"==typeof e&&null!==e}function q(e,t){if(!Y(e))return!1;for(const i in t){if(!(i in e))return v.error(`Missing key: ${i}`),!1;const n=typeof t[i],s=typeof e[i];if(Y(t[i])){if(!Y(e[i])||!q(e[i],t[i]))return v.error(`Invalid nested structure or type mismatch at key: ${i}`),!1}else if(n!==s)return v.error(`Type mismatch at key: ${i}. Expected ${n}, found ${s}`),!1}return!0}function J(e,t){return q(e,t)}const X={settings:{sync_function:"",skip_mode:!1,timezone_offset_correction:0,update_frequency:4,per_day_emails:{time_to_send:"15:00",email_new_gcal_sync_release:!1,email_daily_summary:!1},per_sync_emails:{email_errors:!1,email_session:!1}}},K={gcal:"",gcal_done:"",link:""},W={should_sync:!1,ics_calendars:[]},ee={username:"",commits_configs:{should_sync:!1,commits_calendar:"",ignored_repos:[],parse_commit_emojis:!1},personal_token:""};return class{constructor(t){if(this.extended_configs={timezone:"",timezone_offset:0,today_date:"",user_email:"",configs:{}},!function(e){if(!Y(e))return!1;const t={basic:!0,ticktick:!0,ticktickIcsItems:!0,github:!0,githubIgnoredRepos:!0};if(t.basic=J(e,X),t.github=J(e[m],ee),t.ticktick=J(e[l],W),"object"==typeof e[l]&&"ics_calendars"in e[l]&&Array.isArray(e[l].ics_calendars)){const i=e[l].ics_calendars.map((e=>J(e,K)));t.ticktickIcsItems=i.every((e=>!0===e))}if("object"==typeof e[m]&&"ignored_repos"in e[m]&&Array.isArray(e[m].ignored_repos)){const i=e[m].ignored_repos.map((e=>"string"==typeof e));t.githubIgnoredRepos=i.every((e=>!0===e))}return Object.values(t).every((e=>!0===e))}(t))throw new Error(d.invalid_configs);if("undefined"==typeof Calendar)throw new Error(d.production_only);const i=CalendarApp.getDefaultCalendar().getTimeZone();this.extended_configs.timezone=i,this.extended_configs.timezone_offset=function(e){const t=new Date,i=new Date(Date.UTC(t.getFullYear(),t.getMonth(),t.getDate(),t.getHours(),t.getMinutes(),t.getSeconds())),n=new Date(t.toLocaleString("en-US",{timeZone:e}));return(Number(n)-Number(i))/36e5}(i)+-1*t.settings.timezone_offset_correction;const n=function(e){const t=new Date,i=new Intl.DateTimeFormat("en-CA",{timeZone:e,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(t),n=e=>i.find((t=>t.type===e)).value;return`${n("year")}-${n("month")}-${n("day")}T${n("hour")}:${n("minute")}:${n("second")}.000`}(i);this.extended_configs.today_date=n.split("T")[0],this.extended_configs.user_email=Session.getActiveUser().getEmail(),this.extended_configs.configs=t,v.info(`${e.name} is running at version ${e.version}!`)}createMissingGASProperties(){const e=PropertiesService.getScriptProperties().getProperties();Object.keys(c).forEach((t=>{Object.keys(e).includes(t)||b(c[t],a[t])}))}createMissingGcalCalendars(){const{shouldSyncGithub:e,shouldSyncTicktick:t}=h(this.extended_configs);(e=>{let t=!1;e.forEach((e=>{C(e)||(D(e),v.info(`created google calendar: [${e}]`),t=!0)})),t&&Utilities.sleep(2e3)})([...new Set([].concat(e?[this.extended_configs.configs[m].commits_configs.commits_calendar]:[]).concat(t?[...this.extended_configs.configs[l].ics_calendars.map((e=>e.gcal)),...this.extended_configs.configs[l].ics_calendars.map((e=>e.gcal_done))]:[]))])}handleError(t){if(this.extended_configs.configs.settings.per_sync_emails.email_errors){const i="string"==typeof t?t:t instanceof Error?t.message:JSON.stringify(t);k(function(t,i){const n=`Hi!\n <br/><br/>\n an error recently occurred: <br/><br/>\n <b>${i}</b>\n <br /><br />\n Regards,\n your <a href='https://github.com/${e.github_repository}'>${e.name}</a> bot\n `;return{to:t,name:`${e.name}`,subject:`an error occurred - ${e.name}`,htmlBody:n}}(this.extended_configs.user_email,i))}else v.error(t)}getSessionLogs(){return v.logs}getTicktickTasks(){return F(this.extended_configs.configs[l].ics_calendars,this.extended_configs.timezone_offset)}getGoogleEvents(){return N([...new Set(this.extended_configs.configs[l].ics_calendars.map((e=>e.gcal)))])}getGithubCommits(){const e=w(this.extended_configs.configs[m].username,this.extended_configs.configs[m].personal_token);return U(this.extended_configs.configs,e)}install(){var t,i;y(this.extended_configs.configs.settings.sync_function),t=this.extended_configs.configs.settings.sync_function,i=this.extended_configs.configs.settings.update_frequency,ScriptApp.newTrigger(t).timeBased().everyMinutes(i).create(),this.createMissingGASProperties(),v.info(`${e.name} was set to run function "${this.extended_configs.configs.settings.sync_function}" every ${this.extended_configs.configs.settings.update_frequency} minutes`)}uninstall(){y(this.extended_configs.configs.settings.sync_function),Object.keys(c).forEach((e=>{var t;t=c[e],PropertiesService.getScriptProperties().deleteProperty(t)})),v.info(`${e.name} automation was removed from appscript!`)}sync(){if(this.extended_configs.configs.settings.skip_mode)return v.info("skip_mode is set to true, skipping sync"),{};const{shouldSyncGithub:e,shouldSyncTicktick:t}=h(this.extended_configs);if(!e&&!t)return v.info("nothing to sync"),{};this.createMissingGcalCalendars(),this.createMissingGASProperties();const i=Object.assign(Object.assign(Object.assign({},{added_tasks:[],updated_tasks:[],completed_tasks:[],commits_added:[],commits_deleted:[],commits_tracked_to_be_added:[],commits_tracked_to_be_deleted:[]}),t&&H(this.extended_configs)),e&&G(this.extended_configs.configs));return S(this.extended_configs,i)}}}));