-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.js
More file actions
1 lines (1 loc) · 18.1 KB
/
Copy pathmain.js
File metadata and controls
1 lines (1 loc) · 18.1 KB
1
var w=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var M=Object.prototype.hasOwnProperty;var A=(l,s)=>{for(var e in s)w(l,e,{get:s[e],enumerable:!0})},G=(l,s,e,t)=>{if(s&&typeof s=="object"||typeof s=="function")for(let a of I(s))!M.call(l,a)&&a!==e&&w(l,a,{get:()=>s[a],enumerable:!(t=D(s,a))||t.enumerable});return l};var B=l=>G(w({},"__esModule",{value:!0}),l);var O={};A(O,{default:()=>v});module.exports=B(O);var r=require("obsidian"),E="gchat-native-view",_=8e3,R=["https://www.googleapis.com/auth/chat.spaces.readonly","https://www.googleapis.com/auth/chat.messages","https://www.googleapis.com/auth/chat.memberships","https://www.googleapis.com/auth/userinfo.profile","https://www.googleapis.com/auth/contacts.readonly"].join(" "),x={clientId:"",clientSecret:"",accessToken:"",refreshToken:"",tokenExpiry:0,activeSpaceName:"",openIn:"right"},S=class{constructor(s){this._userNameCache=new Map;this.plugin=s}get settings(){return this.plugin.settings}isAuthed(){return!!this.settings.accessToken}authUrl(){return`https://accounts.google.com/o/oauth2/v2/auth?${new URLSearchParams({client_id:this.settings.clientId,redirect_uri:"http://localhost",response_type:"code",scope:R,access_type:"offline",prompt:"consent"})}`}async exchangeCode(s){var t,a;let e=await(0,r.requestUrl)({url:"https://oauth2.googleapis.com/token",method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code:s,client_id:this.settings.clientId,client_secret:this.settings.clientSecret,redirect_uri:"http://localhost",grant_type:"authorization_code"}).toString()});if(e.status>=400)throw new Error((a=(t=e.json)==null?void 0:t.error_description)!=null?a:e.text);this.applyTokens(e.json),await this.plugin.saveSettings()}async refreshAccessToken(){if(!this.settings.refreshToken)throw new Error("Not authenticated. Sign in first.");let s=await(0,r.requestUrl)({url:"https://oauth2.googleapis.com/token",method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:this.settings.clientId,client_secret:this.settings.clientSecret,refresh_token:this.settings.refreshToken,grant_type:"refresh_token"}).toString()});if(s.status>=400)throw new Error("Token refresh failed. Re-authenticate in settings.");this.applyTokens(s.json),await this.plugin.saveSettings()}applyTokens(s){this.settings.accessToken=s.access_token,this.settings.tokenExpiry=Date.now()+s.expires_in*1e3,s.refresh_token&&(this.settings.refreshToken=s.refresh_token)}async token(){if(!this.settings.accessToken)throw new Error("Not signed in. Go to Settings \u2192 Google Chat.");return Date.now()>this.settings.tokenExpiry-6e4&&await this.refreshAccessToken(),this.settings.accessToken}async get(s){let e=await this.token(),t;try{t=await(0,r.requestUrl)({url:s,headers:{Authorization:`Bearer ${e}`},throw:!1})}catch(a){throw new Error(`Network error: ${a}`)}if(t.status===401)return await this.refreshAccessToken(),this.get(s);if(t.status>=400)throw new Error(`${t.status}: ${t.text}`);return t.json}async post(s,e){let t=await this.token(),a=await(0,r.requestUrl)({url:s,method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify(e)});if(a.status>=400)throw new Error(`${a.status}: ${a.text}`);return a.json}async listSpaces(){var e;return(e=(await this.get("https://chat.googleapis.com/v1/spaces?pageSize=100")).spaces)!=null?e:[]}async getMessages(s,e){var i;let t=`https://chat.googleapis.com/v1/${s}/messages?pageSize=50&orderBy=createTime desc`;e&&(t+=`&pageToken=${e}`);let a=await this.get(t);return{messages:((i=a.messages)!=null?i:[]).reverse(),nextPageToken:a.nextPageToken}}async getNewMessages(s,e){var n;let t=encodeURIComponent(`createTime > "${e}"`),a=`https://chat.googleapis.com/v1/${s}/messages?pageSize=50&filter=${t}&orderBy=createTime asc`;return(n=(await this.get(a)).messages)!=null?n:[]}async sendMessage(s,e){return this.post(`https://chat.googleapis.com/v1/${s}/messages`,{text:e})}async getUserDisplayName(s){var t,a,i;if(this._userNameCache.has(s))return this._userNameCache.get(s);let e=s.replace(/^(people|users)\//,"");try{let c=(i=(a=(t=(await this.get(`https://people.googleapis.com/v1/people/${e}?personFields=names`)).names)==null?void 0:t[0])==null?void 0:a.displayName)!=null?i:"";return c&&this._userNameCache.set(s,c),c||"Direct Message"}catch(n){return"Direct Message"}}async getDmDisplayName(s){var e,t,a;try{let[i,n]=await Promise.all([this.get(`https://chat.googleapis.com/v1/${s}/members?pageSize=20`),this.get("https://people.googleapis.com/v1/people/me?personFields=names").catch(()=>({}))]),c=(e=n.resourceName)==null?void 0:e.replace(/^(people|users)\//,""),o=((t=i.memberships)!=null?t:[]).find(g=>{var p,h;return((p=g.member)==null?void 0:p.type)==="HUMAN"&&((h=g.member)==null?void 0:h.name)&&(!c||g.member.name.replace("users/","")!==c)});return(a=o==null?void 0:o.member)!=null&&a.name?this.getUserDisplayName(o.member.name):"Direct Message"}catch(i){return null}}async getProfile(){return this.get("https://people.googleapis.com/v1/people/me?personFields=names,photos")}};function L(l){let s=new Date(l),e=new Date;return s.toDateString()===e.toDateString()?s.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):s.toLocaleDateString([],{month:"short",day:"numeric"})+" "+s.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}function U(l){var e,t;let s=(t=(e=l.spaceType)!=null?e:l.type)!=null?t:"";return s==="DIRECT_MESSAGE"?"user":s==="GROUP_CHAT"?"users":"hash"}function P(l){return l.split(" ").map(s=>s[0]).join("").slice(0,2).toUpperCase()}function N(l){let s=["#4285F4","#EA4335","#FBBC04","#34A853","#9C27B0","#FF5722","#009688","#2196F3"],e=0;for(let t of l)e=e*31+t.charCodeAt(0)&268435455;return s[e%s.length]}var T=class extends r.ItemView{constructor(e,t){super(e);this.spaces=[];this.activeSpace=null;this.messages=[];this.myDisplayName="";this.pollTimer=null;this.plugin=t}getViewType(){return E}getDisplayText(){return"Google Chat"}getIcon(){return"message-square"}async onOpen(){this.build(),this.plugin.api.isAuthed()?await this.loadSpaces():this.showSignIn()}build(){let e=this.containerEl.children[1];e.empty(),e.addClass("gc-root");let t=e.createEl("div",{cls:"gc-sidebar"}),a=t.createEl("div",{cls:"gc-side-header"});a.createEl("span",{cls:"gc-side-title",text:"Google Chat"});let i=a.createEl("button",{cls:"gc-icon-btn",attr:{title:"Settings"}});(0,r.setIcon)(i,"settings"),i.addEventListener("click",()=>{var f;(f=this.app.setting)==null||f.openTabById(this.plugin.manifest.id)});let n=t.createEl("div",{cls:"gc-search-box"}),c=n.createEl("span",{cls:"gc-search-icon"});(0,r.setIcon)(c,"search");let o=n.createEl("input",{cls:"gc-search-input",attr:{placeholder:"Search spaces\u2026",type:"text"}});o.addEventListener("input",()=>this.filterSpaces(o.value)),this.spaceListEl=t.createEl("div",{cls:"gc-space-list"});let g=e.createEl("div",{cls:"gc-main"}),p=g.createEl("div",{cls:"gc-header"}),h=p.createEl("div",{cls:"gc-header-left"}),d=h.createEl("span",{cls:"gc-header-icon"});(0,r.setIcon)(d,"hash"),this.headerTitleEl=h.createEl("span",{cls:"gc-header-title",text:"Select a space"});let u=p.createEl("div",{cls:"gc-header-right"}).createEl("button",{cls:"gc-icon-btn",attr:{title:"Refresh"}});(0,r.setIcon)(u,"refresh-cw"),u.addEventListener("click",()=>{this.activeSpace&&this.loadMessages(this.activeSpace)}),this.messagesEl=g.createEl("div",{cls:"gc-messages"});let k=g.createEl("div",{cls:"gc-input-area"}).createEl("div",{cls:"gc-input-wrap"});this.inputEl=k.createEl("textarea",{cls:"gc-input",attr:{placeholder:"Message\u2026",rows:"1"}}),this.inputEl.addEventListener("input",()=>{this.inputEl.style.height="auto",this.inputEl.style.height=Math.min(this.inputEl.scrollHeight,120)+"px",this.sendBtn.disabled=!this.inputEl.value.trim()}),this.inputEl.addEventListener("keydown",f=>{f.key==="Enter"&&!f.shiftKey&&(f.preventDefault(),this.send())}),this.sendBtn=k.createEl("button",{cls:"gc-send-btn",attr:{disabled:"true",title:"Send (Enter)"}}),(0,r.setIcon)(this.sendBtn,"send"),this.sendBtn.addEventListener("click",()=>this.send())}showSignIn(){this.messagesEl.empty();let e=this.messagesEl.createEl("div",{cls:"gc-empty"});(0,r.setIcon)(e.createEl("div",{cls:"gc-empty-icon"}),"message-square"),e.createEl("div",{cls:"gc-empty-title",text:"Sign in to Google Chat"}),e.createEl("div",{cls:"gc-empty-sub",text:"Go to Settings \u2192 Google Chat to connect your account."}),e.createEl("button",{cls:"gc-cta-btn",text:"Open Settings"}).addEventListener("click",()=>{var a;(a=this.app.setting)==null||a.openTabById(this.plugin.manifest.id)})}async loadSpaces(){this.spaceListEl.empty(),this.spaceListEl.createEl("div",{cls:"gc-loading",text:"Loading spaces\u2026"});try{if(this.spaces=await this.plugin.api.listSpaces(),this.renderSpaceList(this.spaces),this.plugin.settings.activeSpaceName){let t=this.spaces.find(a=>a.name===this.plugin.settings.activeSpaceName);t&&this.selectSpace(t)}let e=this.spaces.filter(t=>{var a;return((a=t.spaceType)!=null?a:t.type)==="DIRECT_MESSAGE"&&!t.displayName});e.length&&(await Promise.all(e.map(async t=>{let a=await this.plugin.api.getDmDisplayName(t.name);a&&(t.displayName=a)})),this.renderSpaceList(this.spaces))}catch(e){this.spaceListEl.empty(),this.spaceListEl.createEl("div",{cls:"gc-error-msg",text:String(e)})}}renderSpaceList(e){this.spaceListEl.empty();let t=e.filter(n=>{var c,o;return((c=n.spaceType)!=null?c:n.type)==="SPACE"||((o=n.spaceType)!=null?o:n.type)==="ROOM"}),a=e.filter(n=>{var c;return((c=n.spaceType)!=null?c:n.type)==="DIRECT_MESSAGE"}),i=e.filter(n=>{var c;return((c=n.spaceType)!=null?c:n.type)==="GROUP_CHAT"});t.length&&this.renderSpaceGroup("Spaces",t),i.length&&this.renderSpaceGroup("Group chats",i),a.length&&this.renderSpaceGroup("Direct messages",a),e.length||this.spaceListEl.createEl("div",{cls:"gc-empty-spaces",text:"No spaces found."})}renderSpaceGroup(e,t){var a;this.spaceListEl.createEl("div",{cls:"gc-group-label",text:e});for(let i of t){let n=this.spaceListEl.createEl("div",{cls:`gc-space-row ${i.name===((a=this.activeSpace)==null?void 0:a.name)?"gc-space-active":""}`,attr:{"data-name":i.name}}),c=n.createEl("span",{cls:"gc-space-icon"});(0,r.setIcon)(c,U(i)),n.createEl("span",{cls:"gc-space-name",text:i.displayName||"Direct Message"}),n.addEventListener("click",()=>this.selectSpace(i))}}filterSpaces(e){let t=e.trim()?this.spaces.filter(a=>(a.displayName||"").toLowerCase().includes(e.toLowerCase())):this.spaces;this.renderSpaceList(t)}async selectSpace(e){this.activeSpace=e,this.plugin.settings.activeSpaceName=e.name,await this.plugin.saveSettings(),this.spaceListEl.querySelectorAll(".gc-space-row").forEach(t=>{t.toggleClass("gc-space-active",t.getAttribute("data-name")===e.name)}),this.headerTitleEl.textContent=e.displayName||"Direct Message",this.stopPoll(),await this.loadMessages(e),this.startPoll(e)}async resolveSenderNames(e){let t=[...new Set(e.map(a=>{var i;return(i=a.sender)==null?void 0:i.name}).filter(Boolean))];await Promise.all(t.map(async a=>{let i=await this.plugin.api.getUserDisplayName(a);e.filter(n=>{var c;return((c=n.sender)==null?void 0:c.name)===a}).forEach(n=>{n.sender.displayName=i})}))}async loadMessages(e){this.messagesEl.empty(),this.messagesEl.createEl("div",{cls:"gc-loading",text:"Loading messages\u2026"});try{let{messages:t}=await this.plugin.api.getMessages(e.name);this.messages=t,await this.resolveSenderNames(this.messages),this.renderMessages()}catch(t){this.messagesEl.empty(),this.messagesEl.createEl("div",{cls:"gc-error-msg",text:String(t)})}}renderMessages(){var a,i,n,c;if(this.messagesEl.empty(),!this.messages.length){this.messagesEl.createEl("div",{cls:"gc-empty-messages",text:"No messages yet."});return}let e="",t="";for(let o of this.messages){let g=new Date(o.createTime).toDateString();g!==t&&(this.messagesEl.createEl("div",{cls:"gc-date-divider",text:new Date(o.createTime).toLocaleDateString([],{weekday:"long",month:"long",day:"numeric"})}),t=g,e="");let p=(i=(a=o.sender)==null?void 0:a.displayName)!=null?i:"Unknown",h=p===e;e=p;let d=this.messagesEl.createEl("div",{cls:`gc-msg-row ${h?"gc-msg-grouped":""}`});if(h)d.createEl("div",{cls:"gc-avatar-spacer"});else{let y=d.createEl("div",{cls:"gc-avatar"});y.style.background=N(p),y.textContent=P(p)}let m=d.createEl("div",{cls:"gc-bubble"});if(!h){let y=m.createEl("div",{cls:"gc-msg-meta"});y.createEl("span",{cls:"gc-msg-sender",text:p}),y.createEl("span",{cls:"gc-msg-time",text:L(o.createTime)})}let u=(c=(n=o.text)!=null?n:o.formattedText)!=null?c:"";m.createEl("div",{cls:"gc-msg-body",text:u})}this.messagesEl.scrollTop=this.messagesEl.scrollHeight}appendNewMessages(e){var a,i,n,c;if(!e.length)return;this.messages.push(...e);let t=this.messagesEl.scrollHeight-this.messagesEl.scrollTop-this.messagesEl.clientHeight<80;for(let o of e){let g=(i=(a=o.sender)==null?void 0:a.displayName)!=null?i:"Unknown",p=this.messagesEl.createEl("div",{cls:"gc-msg-row gc-msg-new"}),h=p.createEl("div",{cls:"gc-avatar"});h.style.background=N(g),h.textContent=P(g);let d=p.createEl("div",{cls:"gc-bubble"}),m=d.createEl("div",{cls:"gc-msg-meta"});m.createEl("span",{cls:"gc-msg-sender",text:g}),m.createEl("span",{cls:"gc-msg-time",text:L(o.createTime)});let u=(c=(n=o.text)!=null?n:o.formattedText)!=null?c:"";d.createEl("div",{cls:"gc-msg-body",text:u})}t&&(this.messagesEl.scrollTop=this.messagesEl.scrollHeight)}async send(){let e=this.inputEl.value.trim();if(!(!e||!this.activeSpace)){this.inputEl.value="",this.inputEl.style.height="auto",this.sendBtn.disabled=!0;try{let t=await this.plugin.api.sendMessage(this.activeSpace.name,e);this.appendNewMessages([t])}catch(t){new r.Notice(`Failed to send: ${t}`),this.inputEl.value=e,this.sendBtn.disabled=!1}}}startPoll(e){this.pollTimer=window.setInterval(async()=>{if(!this.messages.length)return;let t=this.messages[this.messages.length-1].createTime;try{let a=await this.plugin.api.getNewMessages(e.name,t);this.appendNewMessages(a)}catch(a){}},_)}stopPoll(){this.pollTimer!==null&&(clearInterval(this.pollTimer),this.pollTimer=null)}async refresh(){await this.loadSpaces()}async onClose(){this.stopPoll()}},b=class extends r.Modal{constructor(s,e,t){super(s),this.authUrl=e,this.onCode=t,this.modalEl.addClass("gc-auth-modal")}onOpen(){let{contentEl:s}=this;s.createEl("div",{cls:"gc-auth-header",text:"Sign in with Google"});let e=document.createElement("webview");e.setAttribute("src",this.authUrl),e.setAttribute("partition","persist:gc-auth"),e.style.width="100%",e.style.height="520px",e.style.border="none",s.appendChild(e),e.addEventListener("did-navigate",t=>{this.handleRedirect(t.url)}),e.addEventListener("will-navigate",t=>{this.handleRedirect(t.url)}),e.addEventListener("did-fail-load",t=>{t.validatedURL&&t.validatedURL.startsWith("http://localhost")&&this.handleRedirect(t.validatedURL)}),e.addEventListener("did-navigate-in-page",t=>{this.handleRedirect(t.url)})}handleRedirect(s){if(s.startsWith("http://localhost"))try{let t=new URL(s).searchParams.get("code");t&&(this.close(),this.onCode(t))}catch(e){}}onClose(){this.contentEl.empty()}},C=class extends r.PluginSettingTab{constructor(s,e){super(s,e),this.plugin=e}display(){let{containerEl:s}=this;s.empty(),s.createEl("p",{cls:"gc-settings-note",text:"Create a project in Google Cloud Console, enable the Google Chat API and People API, create OAuth 2.0 credentials (Desktop app type), and paste the Client ID and Secret below."}),new r.Setting(s).setName("Client ID").addText(e=>e.setPlaceholder("123\u2026apps.googleusercontent.com").setValue(this.plugin.settings.clientId).onChange(async t=>{this.plugin.settings.clientId=t.trim(),await this.plugin.saveSettings()})),new r.Setting(s).setName("Client Secret").addText(e=>{e.inputEl.type="password",e.setPlaceholder("GOCSPX-\u2026").setValue(this.plugin.settings.clientSecret).onChange(async t=>{this.plugin.settings.clientSecret=t.trim(),await this.plugin.saveSettings()})}),this.plugin.settings.accessToken?new r.Setting(s).setName("Status").setDesc("\u2713 Connected to Google Chat").addButton(e=>e.setButtonText("Sign out").onClick(async()=>{this.plugin.settings.accessToken="",this.plugin.settings.refreshToken="",this.plugin.settings.tokenExpiry=0,await this.plugin.saveSettings(),this.display(),new r.Notice("Signed out.")})):new r.Setting(s).setName("Sign in").setDesc("Opens Google in your browser. Sign in and paste the code back here.").addButton(e=>e.setButtonText("Sign in with Google").setCta().onClick(async()=>{if(!this.plugin.settings.clientId||!this.plugin.settings.clientSecret){new r.Notice("Enter Client ID and Secret first.");return}let t=this.plugin.api.authUrl();new b(this.app,t,async a=>{try{await this.plugin.api.exchangeCode(a),new r.Notice("Connected to Google Chat!"),this.display(),this.plugin.refreshView()}catch(i){new r.Notice(`Auth failed: ${i}`,8e3)}}).open()})),new r.Setting(s).setName("Open in").setDesc("Where the Google Chat panel opens.").addDropdown(e=>e.addOption("right","Right sidebar").addOption("left","Left sidebar").addOption("tab","New tab").setValue(this.plugin.settings.openIn).onChange(async t=>{this.plugin.settings.openIn=t,await this.plugin.saveSettings()})),new r.Setting(s).setName("Reload plugin").setDesc("Disable and re-enable to apply changes.").addButton(e=>e.setButtonText("Reload").onClick(async()=>{e.setButtonText("Reloading\u2026").setDisabled(!0),await this.app.plugins.disablePlugin(this.plugin.manifest.id),await this.app.plugins.enablePlugin(this.plugin.manifest.id)}))}},v=class extends r.Plugin{constructor(){super(...arguments);this.settings=x}async onload(){await this.loadSettings(),this.api=new S(this),this.registerView(E,e=>new T(e,this)),this.addRibbonIcon("message-square","Google Chat",()=>this.openChat()),this.addCommand({id:"open-google-chat",name:"Open Google Chat",callback:()=>this.openChat()}),this.addSettingTab(new C(this.app,this))}async openChat(){var i,n;let{workspace:e}=this.app,t=e.getLeavesOfType(E);if(t.length){e.revealLeaf(t[0]);return}let a;switch(this.settings.openIn){case"left":a=(i=e.getLeftLeaf(!0))!=null?i:e.getLeaf(!0);break;case"tab":a=e.getLeaf(!0);break;case"floating":a=e.getLeaf(!0);break;default:a=(n=e.getRightLeaf(!1))!=null?n:e.getLeaf(!1)}await a.setViewState({type:E,active:!0}),e.revealLeaf(a)}async refreshView(){let e=this.app.workspace.getLeavesOfType(E);for(let t of e)await t.view.refresh()}async loadSettings(){this.settings=Object.assign({},x,await this.loadData())}async saveSettings(){await this.saveData(this.settings)}};