PageSourceSearch

https://app.myarchivist.ai/_next/static/chunks/1857.69a878555d2460f0.js

js myarchivist.ai collected 2026-10-05 12:18:26 UTC 32,267 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1857],{71857:function(e,t,n){n.r(t),n.d(t,{default:function(){return $}});var s=n(56779),i=n(83415),r=n(34910),o=n(45856),l=n(18575),a=n(32825),c=n(38191),d=n(92229),h=n(84776),x=n(75862),m=n(26093),u=n(65228),p=n(24846),g=n(31925),j=n(13327),f=n(79544),Z=n(34072),y=n(76642),v=n(51983),b=n(77508),w=n(61215),S=n(80134),C=n(31004),I=n(48193),k=e=>{let{profileData:t}=e,[n,h]=(0,i.useState)(!1),[x,f]=(0,i.useState)(!1),[k,D]=(0,i.useState)(!1),A=(0,v.useSearchParams)().get("intent"),z=A?"/api/auth/discord/connect?quickstart=".concat(encodeURIComponent(A)):"/api/auth/discord/connect",W=async()=>{f(!1),h(!0);try{(await fetch("/api/auth/user",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"disconnect"})})).ok&&window.location.reload()}catch(e){console.error(e),h(!1)}};return(0,s.jsxs)(r.Z,{sx:{width:"100%",height:"auto",minHeight:"60px",display:"flex",alignItems:"center",backgroundColor:"transparent"},children:[(0,s.jsxs)(m.Z,{open:x,onClose:()=>f(!1),children:[(0,s.jsx)(u.Z,{children:"Disconnect Discord"}),(0,s.jsx)(p.Z,{children:(0,s.jsx)(c.Z,{children:"Are you sure you want to disconnect your Discord integration?"})}),(0,s.jsxs)(g.Z,{children:[(0,s.jsx)(d.Z,{onClick:()=>f(!1),color:"secondary",variant:"contained",children:"Cancel"}),(0,s.jsx)(d.Z,{onClick:W,color:"primary",variant:"contained",children:"Disconnect"})]})]}),(0,s.jsxs)(m.Z,{open:k,onClose:()=>D(!1),maxWidth:"sm",fullWidth:!0,children:[(0,s.jsx)(u.Z,{children:"Connect Discord"}),(0,s.jsxs)(p.Z,{children:[(0,s.jsx)(c.Z,{variant:"body2",color:"text.secondary",sx:{mb:3},children:"Choose how you'd like to connect your Discord account to Archivist."}),(0,s.jsxs)(l.Z,{spacing:2,children:[(0,s.jsx)(d.Z,{variant:"outlined",href:"/api/auth/discord/connect-account",startIcon:(0,s.jsx)(I.Z,{}),sx:{justifyContent:"flex-start",textTransform:"none",textAlign:"left",py:1.5,px:2},children:(0,s.jsxs)(r.Z,{children:[(0,s.jsx)(c.Z,{variant:"subtitle2",sx:{fontWeight:700},children:"Connect Account Only"}),(0,s.jsx)(c.Z,{variant:"caption",color:"text.secondary",children:"For Campaign Admins who need to use bot commands in the Campaign Owner's Archivist server, but do not need to install the Archivist bot."})]})}),(0,s.jsx)(d.Z,{variant:"contained",href:z,startIcon:(0,s.jsx)(j.Z,{}),sx:{justifyContent:"flex-start",textTransform:"none",textAlign:"left",py:1.5,px:2},children:(0,s.jsxs)(r.Z,{children:[(0,s.jsx)(c.Z,{variant:"subtitle2",sx:{fontWeight:700,color:"inherit"},children:"Connect Account & Install Bot"}),(0,s.jsx)(c.Z,{variant:"caption",sx:{color:"inherit",opacity:.85},children:"For Campaign Owners andCampaign Admins who want to install the Archivist bot to record sessions."})]})}),(0,s.jsxs)(r.Z,{sx:{display:"flex",alignItems:"flex-start",gap:1,mt:.5},children:[(0,s.jsx)(Z.Z,{sx:{color:"warning.main",fontSize:"1.1rem",mt:.2}}),(0,s.jsx)(c.Z,{variant:"caption",color:"text.secondary",sx:{fontStyle:"italic"},children:"Installing the bot requires Administrator permissions on the Discord server."})]})]})]}),(0,s.jsx)(g.Z,{children:(0,s.jsx)(d.Z,{onClick:()=>D(!1),children:"Cancel"})})]}),(0,s.jsx)(a.Z,{container:!0,spacing:2,alignItems:"center",sx:{width:"100%"},children:(null==t?void 0:t.discordUsername)?(0,s.jsx)(a.Z,{size:12,children:(0,s.jsxs)(r.Z,{sx:{display:"flex",flexDirection:"row",alignItems:"center",gap:.75,flexWrap:"nowrap",width:"fit-content",maxWidth:"100%"},children:[(0,s.jsx)(r.Z,{sx:{flex:"0 1 auto",minWidth:0},children:(0,s.jsxs)(r.Z,{sx:{display:"flex",flexDirection:"column",gap:.5},children:[(0,s.jsxs)(c.Z,{variant:"subtitle1",sx:{m:0},children:["User: ",null==t?void 0:t.discordUsername]}),(0,s.jsx)(b.Z,{href:"https://www.myarchivist.ai/documentation#discord",target:"_blank",rel:"noopener noreferrer",sx:{fontSize:"0.75rem",color:"#1976d2",textDecoration:"underline",fontStyle:"italic",fontWeight:"normal","&:hover":{color:"#1565c0"}},children:"Discord Bot Documents"})]})}),(0,s.jsx)(r.Z,{sx:{flexShrink:0},children:n?(0,s.jsx)(o.Z,{size:24}):(0,s.jsx)(w.Z,{title:"Disconnect Discord",children:(0,s.jsx)(S.Z,{color:"error",onClick:()=>f(!0),"aria-label":"Disconnect Discord",children:(0,s.jsx)(C.Z,{})})})})]})}):(0,s.jsx)(a.Z,{size:{xs:12},children:(0,s.jsxs)(r.Z,{sx:{display:"flex",flexDirection:"column",alignItems:"center",gap:1},children:[(0,s.jsx)(d.Z,{variant:"contained",color:"primary",onClick:()=>D(!0),children:"Connect Discord"}),(0,s.jsx)(b.Z,{href:"https://www.myarchivist.ai/documentation#discord",target:"_blank",rel:"noopener noreferrer",sx:{fontSize:"0.75rem",color:"#1976d2",textDecoration:"underline",fontStyle:"italic",fontWeight:"normal","&:hover":{color:"#1565c0"}},children:"Discord Bot Documents"}),(0,s.jsxs)(b.Z,{href:"/academy#discord-connection",sx:{fontSize:"0.75rem",color:"#1976d2",textDecoration:"underline",fontWeight:"normal",display:"inline-flex",alignItems:"center",gap:.5,"&:hover":{color:"#1565c0"}},children:[(0,s.jsx)(y.Z,{sx:{fontSize:"0.95rem"}}),"Watch the setup guide"]})]})})})]})},D=n(84926),A=n(40586),z=n(19980),W=n(73558),E=n(70513),G=n(75994),T=n(79917),U=n(60567),B=n(40017),P=n(6214),R=n(25962),O=n(42189),_=n(94527);let M=(0,s.jsx)(O.Z,{fontSize:"small"}),N=(0,s.jsx)(_.Z,{fontSize:"small"});var F=e=>{let{channels:t,guildId:n}=e,o=(0,T.Z)(),[l,a]=(0,i.useState)(t),[d,h]=(0,i.useState)([]),[x,m]=(0,i.useState)({open:!1,message:"",severity:"error"});(0,i.useEffect)(()=>{a(t)},[t]),(0,i.useEffect)(()=>{u()},[]);let u=async()=>{try{let e=await fetch("/api/worlds?includePlayerWorlds=true"),t=await e.json(),n=Array.isArray(t)?t.filter(e=>{var t;return null===(t=null==e?void 0:e.canManageWorld)||void 0===t||t}):[];h(n)}catch(e){console.error("Error fetching worlds:",e)}},p=(0,i.useMemo)(()=>[...l].sort((e,t)=>
1{let n=(e.category||"Uncategorized").toLowerCase(),s=(t.category||"Uncategorized").toLowerCase();return n!==s?n.localeCompare(s):(e.name||"").toLowerCase().localeCompare((t.name||"").toLowerCase())}),[l]),g=(0,i.useMemo)(()=>{let e={};for(let t of l)if(t.worldId){let n=d.find(e=>String(e.id)===String(t.worldId));e[t.channelId]={campaignId:t.worldId,campaignName:(null==n?void 0:n.title)||"another campaign"}}return e},[l,d]),j=async(e,t,n,s)=>{let i=[...e.map(e=>{let{channelId:t,value:s}=e;return fetch("/api/discord",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({channelId:t,[n]:s})})}),...t.map(e=>{let{channelId:t}=e;return fetch("/api/discord",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({channelId:t,[n]:null})})})];try{let e=(await Promise.all(i)).filter(e=>!e.ok);e.length>0&&(a(s),m({open:!0,message:"Failed to update ".concat(e.length," channel assignment(s). Changes have been reverted."),severity:"error"}))}catch(e){console.error("Error updating ".concat(n," channels:"),e),a(s),m({open:!0,message:"A network error occurred. Changes have been reverted.",severity:"error"})}},f=(e,t,n)=>{let s=String(e),i=new Set(l.filter(e=>String(e[t])===s).map(e=>e.channelId)),r=new Set(n.map(e=>e.channelId)),o=[...r].filter(e=>!i.has(e)).map(t=>({channelId:t,value:e})),c=[...i].filter(e=>!r.has(e)).map(e=>({channelId:e}));(o.length||c.length)&&(a(n=>n.map(n=>o.some(e=>e.channelId===n.channelId)?{...n,[t]:e}:c.some(e=>e.channelId===n.channelId)?{...n,[t]:null}:n)),j(o,c,t,l))},Z=(0,i.useMemo)(()=>[...d].sort((e,t)=>{let n=!!(null==e?void 0:e.archived);return!!(null==t?void 0:t.archived)!==n?n?1:-1:(e.title||"").localeCompare(t.title||"")}),[d]),y={xs:"1fr",md:"minmax(180px, 240px) minmax(0, 1fr) minmax(0, 1fr)"};return(0,s.jsxs)(r.Z,{sx:{mt:3},children:[(0,s.jsxs)(r.Z,{sx:{display:"flex",alignItems:"center",gap:1,mb:2},children:[(0,s.jsx)(c.Z,{variant:"h6",children:"Channel Settings"}),(0,s.jsx)(w.Z,{title:(0,s.jsxs)(c.Z,{sx:{fontFamily:"barlow",fontSize:"0.875rem",lineHeight:1.4,maxWidth:300,p:1},children:["Assign text channels to each campaign using the multi-select dropdowns.",(0,s.jsx)("br",{}),(0,s.jsx)("br",{}),(0,s.jsx)("strong",{children:"Ask Archivist"})," sets which channels can @mention Archivist to ask questions about that campaign. Each text channel can only be assigned to one campaign for Ask Archivist.",(0,s.jsx)("br",{}),(0,s.jsx)("br",{}),(0,s.jsx)("strong",{children:"Discord G.E.M.S."})," sets which channels receive Game Excerpts, Mentions, and Spotlights for that campaign."]}),children:(0,s.jsx)(S.Z,{size:"small",children:(0,s.jsx)(R.Z,{fontSize:"small"})})})]}),(0,s.jsxs)(r.Z,{sx:{display:{xs:"none",md:"grid"},gridTemplateColumns:y.md,gap:2,alignItems:"end",bgcolor:"dark"===o.palette.mode?o.palette.background.paper:o.palette.grey[200],p:1.5,borderRadius:1,mb:1},children:[(0,s.jsx)(c.Z,{variant:"subtitle2",sx:{fontWeight:600},children:"Campaign"}),(0,s.jsx)(c.Z,{variant:"subtitle2",sx:{fontWeight:600},children:"Ask Archivist"}),(0,s.jsx)(c.Z,{variant:"subtitle2",sx:{fontWeight:600},children:(0,s.jsxs)(r.Z,{sx:{display:"flex",alignItems:"center",gap:.5},children:[(0,s.jsx)("span",{children:"Discord G.E.M.S."}),(0,s.jsx)(w.Z,{title:(0,s.jsxs)(c.Z,{sx:{fontFamily:"barlow",fontSize:"0.875rem",lineHeight:1.4,maxWidth:300,p:1},children:["Choose which channels should receive Discord G.E.M.S. for each campaign.",(0,s.jsx)("br",{}),(0,s.jsx)("br",{}),"Discord G.E.M.S. (Game Excerpts, Mentions, and Spotlights) are session highlights posted to Discord after a session ends."]}),children:(0,s.jsx)(S.Z,{size:"small",sx:{p:.25},children:(0,s.jsx)(R.Z,{fontSize:"inherit"})})})]})})]}),0===Z.length&&(0,s.jsx)(c.Z,{variant:"body2",color:"text.secondary",sx:{py:2},children:"No campaigns available. Create a campaign to configure channel settings."}),Z.map((e,t)=>{let n=String(e.id),i=!!e.archived,o=p.filter(e=>String(e.worldId)===n),l=p.filter(e=>String(e.gemsCampaignId)===n),a=(e.language||"en").includes("en"),d=new Set(o.map(e=>e.channelId)),h=new Set(l.map(e=>e.channelId)),x=a||i;return(0,s.jsxs)(r.Z,{sx:{display:"grid",gridTemplateColumns:y,gap:{xs:1.5,md:2},alignItems:{md:"flex-start"},py:{xs:2,md:1.5},px:{xs:1,md:1.5},borderBottom:t<Z.length-1?1:0,borderColor:"divider"},children:[(0,s.jsxs)(r.Z,{sx:{minWidth:0},children:[(0,s.jsxs)(c.Z,{sx:{fontWeight:600,pt:{md:1},minWidth:0,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:[e.title,i?" (Archived)":""]}),i&&(0,s.jsx)(c.Z,{variant:"caption",color:"text.secondary",sx:{dis
1play:"block"},children:"Archived campaigns are remove-only."})]}),(0,s.jsxs)(r.Z,{children:[(0,s.jsx)(c.Z,{variant:"caption",sx:{display:{xs:"block",md:"none"},fontWeight:600,mb:.5},children:"Ask Archivist"}),(0,s.jsx)(U.Z,{multiple:!0,disableCloseOnSelect:!0,size:"small",options:p,value:o,onChange:(t,n)=>f(e.id,"worldId",n),isOptionEqualToValue:(e,t)=>e.channelId===t.channelId,getOptionLabel:e=>"#".concat(e.name),groupBy:e=>e.category||"Uncategorized",getOptionDisabled:e=>{let t=g[e.channelId];return!!(i&&!d.has(e.channelId)||t&&String(t.campaignId)!==n)},renderOption:(e,t,i)=>{let{selected:o}=i,{key:l,...a}=e,d=g[t.channelId],h=d&&String(d.campaignId)!==n;return(0,s.jsxs)("li",{...a,children:[(0,s.jsx)(B.Z,{icon:M,checkedIcon:N,sx:{mr:1},checked:o,disabled:h}),(0,s.jsxs)(r.Z,{sx:{minWidth:0},children:[(0,s.jsxs)(c.Z,{variant:"body2",children:["#",t.name]}),h&&(0,s.jsxs)(c.Z,{variant:"caption",color:"text.disabled",children:["Assigned to"," ",d.campaignName]})]})]},l)},renderInput:e=>(0,s.jsx)(P.Z,{...e,placeholder:o.length?"":"Select channels..."}),limitTags:2})]}),(0,s.jsxs)(r.Z,{children:[(0,s.jsx)(c.Z,{variant:"caption",sx:{display:{xs:"block",md:"none"},fontWeight:600,mb:.5},children:"Discord G.E.M.S."}),x?(0,s.jsx)(U.Z,{multiple:!0,disableCloseOnSelect:!0,size:"small",options:p,value:l,onChange:(t,n)=>f(e.id,"gemsCampaignId",n),isOptionEqualToValue:(e,t)=>e.channelId===t.channelId,getOptionLabel:e=>"#".concat(e.name),groupBy:e=>e.category||"Uncategorized",getOptionDisabled:e=>i&&!h.has(e.channelId),renderOption:(e,t,n)=>{let{selected:i}=n,{key:r,...o}=e;return(0,s.jsxs)("li",{...o,children:[(0,s.jsx)(B.Z,{icon:M,checkedIcon:N,sx:{mr:1},checked:i}),(0,s.jsxs)(c.Z,{variant:"body2",children:["#",t.name]})]},r)},renderInput:e=>(0,s.jsx)(P.Z,{...e,placeholder:l.length?"":"Select channels..."}),limitTags:2}):(0,s.jsx)(w.Z,{title:"Discord G.E.M.S. is only available for English campaigns",children:(0,s.jsx)(c.Z,{variant:"body2",color:"text.disabled",sx:{pt:1,fontStyle:"italic"},children:"English only"})})]})]},e.id)}),(0,s.jsx)(E.Z,{open:x.open,autoHideDuration:6e3,onClose:()=>m(e=>({...e,open:!1})),anchorOrigin:{vertical:"bottom",horizontal:"right"},children:(0,s.jsx)(G.Z,{onClose:()=>m(e=>({...e,open:!1})),severity:x.severity,sx:{width:"100%"},children:x.message})})]})},L=e=>{var t,n;let{profileData:l,onLoadingChange:h,onGuildCountChange:x}=e,[m,u]=(0,i.useState)([]),[p,g]=(0,i.useState)(""),[j,f]=(0,i.useState)(!0),[Z,y]=(0,i.useState)(!1),[v,b]=(0,i.useState)({open:!1,message:"",severity:"success"});(0,i.useEffect)(()=>{w()},[]),(0,i.useEffect)(()=>{h&&h(j)},[j,h]);let w=async()=>{try{let e=await fetch("/api/discord/user"),t=await e.json();if(console.log("Discord guilds response:",t),t.error){console.error("Error fetching guilds:",t.error),f(!1);return}let n=[];n=t.discordGuilds&&Array.isArray(t.discordGuilds)?t.discordGuilds:Array.isArray(t)?t:t.user&&t.user.discordGuilds?t.user.discordGuilds:Array.isArray(t)?t:[t],console.log("Processed guilds array:",n);let s=n.filter(e=>e&&"object"==typeof e);u(s),null==x||x(s.length),s.length>0&&g(s[0].discordGuildId||s[0].id),f(!1)}catch(e){console.error("Error in fetchGuilds:",e),null==x||x(0),f(!1)}},S=async()=>{y(!0);try{let t=(Array.isArray(m)?m:[m]).find(e=>e.discordGuildId===p||e.id===p);if(t){var e;let n=(null===(e=t.discordGuild)||void 0===e?void 0:e.guildId)||t.guildId||t.id;if(n){let e=await fetch("/api/discord/channel-refresh?guildId=".concat(encodeURIComponent(n)),{method:"GET",headers:{"Content-Type":"application/json"}}),t=await e.json();if(e.ok){let{summary:e}=t,n="Channels refreshed successfully!";if(e){let t=[];e.channelsAdded>0&&t.push("".concat(e.channelsAdded," added")),e.channelsUpdated>0&&t.push("".concat(e.channelsUpdated," updated")),e.channelsRemoved>0&&t.push("".concat(e.channelsRemoved," removed")),t.length>0?n+=" (".concat(t.join(", "),")"):n="Channels are up to date - no changes needed."}b({open:!0,message:n,severity:"success"}),await w()}else{let e=t.error||"Failed to refresh channels";b({open:!0,message:e,severity:"error"})}}else b({open:!0,message:"Unable to find guild ID",severity:"error"})}else b({open:!0,message:"No guild selected",severity:"error"})}catch(e){console.error("Error refreshing channels:",e),b({open:!0,message:"Network error while refreshing channels",severity:"error"})}y(!1)},C=()=>{b({...v,open:!1})};if(j)return(0,s.jsx)(o.Z,{});let I=Array.isArray(m)?m:[m],k=I.find(e=>e.discordGuildId===p||e.id===p),T=I.filter(e=>e&&(e.name||e.discordGuild&&e.discordGuild.name));return 0!==T.length||j?(0,s.jsxs)(r.Z,{children:[(0,s.jsx)(c.Z,{variant:"h6",mb:2,gutterBottom:!0,children:"Server Management"}),(0,s.jsxs)(a.Z,{container:!0,spacing:2,children:[(0,s.jsx)(a.Z,{size:{xs:12,md:6},children:(0,s.jsxs)(D.Z,{fullWidth:!0,children:[(0,s.jsx)(A.Z,{children:"Select Server"}),(0,s.jsxs)(z.Z,{value:p,onChange:e=>{if("new"===e.target.value){window.location.href="/api/auth/discord/connect";return}g(e.target.value)},label:"Select Server",children:[T.map(e=>{var t;return(0,s.jsx)(W.Z,{value:e.discordGuildId||e.id,children:(null===(t=e.discordGuild)||void 0===t?void 0:t.name)||e.name},e.discordGuildId||e.id)}),(0,s.jsx)(W.Z,{value:"new",children:"Add New Server..."})]})]})}),(0,s.jsx)(a.Z,{size:{xs:12,md:6},children:(0,s.jsx)(d.Z,{variant:"contained",onClick:S,disabled:Z||!p,sx:{mt:{xs:0,md:1}},children:Z?(0,s.jsx)(o.Z,{size:24}):"Refresh Channels"})}
1),k&&(0,s.jsx)(a.Z,{size:{xs:12},children:(0,s.jsx)(F,{channels:(null===(t=k.discordGuild)||void 0===t?void 0:t.textChannels)||k.textChannels||[],guildId:(null===(n=k.discordGuild)||void 0===n?void 0:n.guildId)||k.guildId||k.id})})]}),(0,s.jsx)(E.Z,{open:v.open,autoHideDuration:6e3,onClose:C,anchorOrigin:{vertical:"bottom",horizontal:"right"},children:(0,s.jsx)(G.Z,{onClose:C,severity:v.severity,sx:{width:"100%"},children:v.message})})]}):(0,s.jsxs)(r.Z,{children:[(0,s.jsx)(c.Z,{variant:"h6",mb:2,gutterBottom:!0,children:"Server Management"}),(0,s.jsx)(c.Z,{mb:2,children:"No Discord servers connected. Click the button below to connect a server."}),(0,s.jsx)(d.Z,{variant:"contained",onClick:()=>window.location.href="/api/auth/discord/connect",children:"Connect Discord Server"})]})},H=n(82020),q=n(7502),J=n(50461),V=n(44931),Y=n(78490);function K(){let[e,t]=(0,i.useState)([]),[n,a]=(0,i.useState)(!0),[h,x]=(0,i.useState)(null),[j,Z]=(0,i.useState)(!1),[v,w]=(0,i.useState)(""),[C,I]=(0,i.useState)(""),[k,D]=(0,i.useState)(!1),[A,z]=(0,i.useState)(null),[W,E]=(0,i.useState)(null),[T,U]=(0,i.useState)(null),B=(0,i.useCallback)(async()=>{a(!0),x(null);try{let e=await fetch("/api/discord/bots",{cache:"no-store"}),n=await e.json().catch(()=>({}));if(!e.ok)throw Error(n.error||"Failed to load companion bots");t(Array.isArray(n.bots)?n.bots:[])}catch(e){x(e.message||"Failed to load companion bots")}finally{a(!1)}},[]);(0,i.useEffect)(()=>{B()},[B]),(0,i.useEffect)(()=>{let e=()=>{B()},t=()=>{"visible"===document.visibilityState&&B()};return window.addEventListener("focus",e),document.addEventListener("visibilitychange",t),()=>{window.removeEventListener("focus",e),document.removeEventListener("visibilitychange",t)}},[B]);let R=()=>{Z(!1),z(null),w(""),I(""),U(null)},O=async()=>{if(v.trim()){D(!0),U(null);try{let e=!!A,t=await fetch(e?"/api/discord/bots/".concat(A):"/api/discord/bots",{method:e?"PATCH":"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e?{token:v.trim()}:{token:v.trim(),name:C.trim()||void 0})}),n=await t.json().catch(()=>({}));if(!t.ok)throw Error(n.error||"Failed to save bot");R(),await B()}catch(e){U(e.message||"Failed to save bot")}finally{D(!1)}}},_=async e=>{if(window.confirm("Remove this companion bot? Active sessions using it will be ended.")){E(e),x(null);try{let t=await fetch("/api/discord/bots/".concat(e),{method:"DELETE"}),n=await t.json().catch(()=>({}));if(!t.ok)throw Error(n.error||"Failed to remove bot");await B()}catch(e){x(e.message||"Failed to remove bot")}finally{E(null)}}},M=async e=>{try{await navigator.clipboard.writeText(e)}catch(e){}};return(0,s.jsxs)(l.Z,{spacing:2,children:[(0,s.jsxs)(r.Z,{sx:{display:"flex",flexDirection:{xs:"column",sm:"row"},alignItems:{xs:"stretch",sm:"flex-start"},justifyContent:"space-between",gap:2},children:[(0,s.jsxs)(r.Z,{sx:{minWidth:0,flex:1},children:[(0,s.jsxs)(r.Z,{sx:{display:"flex",alignItems:"center",gap:1,flexWrap:"wrap"},children:[(0,s.jsx)(c.Z,{variant:"h6",children:"Companion bots"}),(0,s.jsx)(H.Z,{size:"small",color:"info",label:"Beta"})]}),(0,s.jsxs)(c.Z,{variant:"body2",color:"text.secondary",sx:{mt:.5},children:["An Archivist companion bot is a Discord bot you create and connect here. Use one to record an additional simultaneous live session or as the identity and permission boundary for hosted Discord MCP. The official Archivist bot stays as the control plane for slash commands. Custom bots used for recording will need ",(0,s.jsx)("strong",{children:"Guilds"})," and ",(0,s.jsx)("strong",{children:"Guild Voice States"}),". Bots using the Discord MCP will need the privileged ",(0,s.jsx)("strong",{children:"Message Content"})," intent in order to read messages. Enable ",(0,s.jsx)("strong",{children:"Guild Members"})," if you want member search enabled. If the bot is already on a server, click Add to Discord again so that server picks up message read/write grants; existing installs keep the old recording-only permissions until you re-invite."]}),(0,s.jsxs)(b.Z,{href:"/academy#discord-byob",sx:{display:"inline-flex",alignItems:"center",gap:.5,mt:.75,fontSize:"0.8125rem"},children:[(0,s.jsx)(y.Z,{sx:{fontSize:"1rem"}}),"Watch how it works in Archivist Academy"]})]}),(0,s.jsxs)(l.Z,{direction:{xs:"column",sm:"row"},spacing:1,sx:{width:{xs:"100%",sm:"auto"},flexShrink:0},children:[(0,s.jsx)(d.Z,{variant:"outlined",startIcon:(0,s.jsx)(Y.Z,{}),onClick:()=>B(),disabled:n,sx:{width:{xs:"100%",sm:"auto"}},children:"Refresh status"}),(0,s.jsx)(d.Z,{variant:"contained",startIcon:(0,s.jsx)(q.Z,{}),onClick:()=>{z(null),U(null),Z(!0)}
1,sx:{width:{xs:"100%",sm:"auto"}},children:"Add companion bot"})]})]}),h&&(0,s.jsx)(G.Z,{severity:"error",onClose:()=>x(null),children:h}),n?(0,s.jsx)(r.Z,{sx:{display:"flex",justifyContent:"center",py:3},children:(0,s.jsx)(o.Z,{size:28})}):0===e.length?(0,s.jsx)(c.Z,{variant:"body2",color:"text.secondary",children:"No companion bots yet. Create a Discord Application, enable a Bot user, copy the token, and paste it here."}):(0,s.jsx)(l.Z,{spacing:1.5,children:e.map(e=>{let t=Array.isArray(e.guilds)?e.guilds.length:0;return(0,s.jsxs)(r.Z,{sx:{border:"1px solid",borderColor:"divider",borderRadius:1,p:1.5,display:"flex",flexDirection:{xs:"column",sm:"row"},alignItems:{xs:"stretch",sm:"center"},justifyContent:"space-between",gap:1.5},children:[(0,s.jsxs)(l.Z,{direction:"row",spacing:1,alignItems:"flex-start",justifyContent:"space-between",sx:{minWidth:0,flex:1},children:[(0,s.jsxs)(r.Z,{sx:{minWidth:0},children:[(0,s.jsx)(c.Z,{variant:"subtitle1",noWrap:!0,children:e.name}),(0,s.jsxs)(l.Z,{direction:"row",spacing:1,useFlexGap:!0,flexWrap:"wrap",sx:{mt:.5},children:[function(e){switch(e){case"configured":return(0,s.jsx)(H.Z,{size:"small",color:"success",label:"Token valid"});case"disabled":return(0,s.jsx)(H.Z,{size:"small",label:"Disabled"});case"invalid":return(0,s.jsx)(H.Z,{size:"small",color:"error",label:"Invalid"});case"error":return(0,s.jsx)(H.Z,{size:"small",color:"warning",label:"Error"});default:return(0,s.jsx)(H.Z,{size:"small",label:e||"Unknown"})}}(e.status),(0,s.jsx)(H.Z,{size:"small",variant:"outlined",label:t>0?"Installed in ".concat(t," server").concat(1===t?"":"s"):"Not installed"})]}),e.lastError&&(0,s.jsx)(c.Z,{variant:"caption",color:"error",sx:{display:"block",mt:.5},children:e.lastError})]}),(0,s.jsx)(S.Z,{size:"small",color:"error","aria-label":"Remove bot",disabled:W===e.id,onClick:()=>_(e.id),sx:{display:{xs:"inline-flex",sm:"none"},mt:-.5,mr:-.5,flexShrink:0},children:W===e.id?(0,s.jsx)(o.Z,{size:16}):(0,s.jsx)(V.Z,{fontSize:"small"})})]}),(0,s.jsxs)(l.Z,{direction:{xs:"column",sm:"row"},spacing:1,alignItems:{sm:"center"},sx:{flexShrink:0},children:[(0,s.jsxs)(l.Z,{direction:"row",spacing:1,alignItems:"center",sx:{width:{xs:"100%",sm:"auto"}},children:[(0,s.jsx)(d.Z,{size:"small",variant:"outlined",href:e.inviteUrl,target:"_blank",rel:"noopener noreferrer",endIcon:(0,s.jsx)(f.Z,{}),sx:{flex:{xs:1,sm:"none"}},children:"Add to Discord"}),(0,s.jsx)(S.Z,{size:"small","aria-label":"Copy invite URL",onClick:()=>M(e.inviteUrl),children:(0,s.jsx)(J.Z,{fontSize:"small"})})]}),(0,s.jsx)(d.Z,{size:"small",startIcon:(0,s.jsx)(Y.Z,{}),onClick:()=>{z(e.id),I(e.name),U(null),Z(!0)}
1,sx:{width:{xs:"100%",sm:"auto"}},children:"Replace token"}),(0,s.jsx)(S.Z,{size:"small",color:"error","aria-label":"Remove bot",disabled:W===e.id,onClick:()=>_(e.id),sx:{display:{xs:"none",sm:"inline-flex"}},children:W===e.id?(0,s.jsx)(o.Z,{size:16}):(0,s.jsx)(V.Z,{fontSize:"small"})})]})]},e.id)})}),(0,s.jsxs)(c.Z,{variant:"caption",color:"text.secondary",children:["Tokens are stored encrypted and never shown again."," ",(0,s.jsx)(b.Z,{href:"https://discord.com/developers/applications",target:"_blank",rel:"noopener noreferrer",children:"Discord Developer Portal"})]}),(0,s.jsxs)(m.Z,{open:j,onClose:R,fullWidth:!0,maxWidth:"sm",children:[(0,s.jsx)(u.Z,{children:A?"Replace bot token":"Add a companion bot"}),(0,s.jsx)(p.Z,{children:(0,s.jsxs)(l.Z,{spacing:2,sx:{mt:1},children:[T&&(0,s.jsx)(G.Z,{severity:"error",onClose:()=>U(null),children:T}),(0,s.jsx)(c.Z,{variant:"body2",color:"text.secondary",children:"Paste the bot token from the Discord Developer Portal. We validate it with Discord, encrypt it, and never return it."}),!A&&(0,s.jsx)(P.Z,{label:"Display name (optional)",value:C,onChange:e=>I(e.target.value),fullWidth:!0}),(0,s.jsx)(P.Z,{label:"Bot token",value:v,onChange:e=>w(e.target.value),fullWidth:!0,type:"password",autoComplete:"off",placeholder:"Paste Discord bot token"})]})}),(0,s.jsxs)(g.Z,{children:[(0,s.jsx)(d.Z,{onClick:R,disabled:k,children:"Cancel"}),(0,s.jsx)(d.Z,{variant:"contained",onClick:O,disabled:k||!v.trim(),children:k?(0,s.jsx)(o.Z,{size:18}):A?"Replace":"Add bot"})]})]})]})}let Q="https://www.youtube.com/embed/x9VisJGFets?si=oZNJu24RCspqzyJz",X="archivist:discordIntroDismissed:";var $=e=>{let{profileData:t}=e,n=(0,v.useSearchParams)(),b=(0,v.useRouter)(),[w,S]=(0,i.useState)(!1),[C,I]=(0,i.useState)(!1),[D,A]=(0,i.useState)(!!(null==t?void 0:t.discordUsername)),[z,W]=(0,i.useState)(null),E=n.get("intent"),G=n.get("status"),T=n.get("guildId"),U=n.get("channelId"),B=n.get("worldId");(0,i.useEffect)(()=>{let e=!(null==t?void 0:t.discordUsername)&&!function(e){if(!e)return!1;try{return"1"===window.sessionStorage.getItem("".concat(X).concat(e))}catch(e){return!1}}(E);"live_record"===E&&e&&S(!0),"play_by_post"===E&&e&&S(!0),"connected"===G&&T&&(null==t?void 0:t.discordUsername)&&I(!0)},[E,G,T,null==t?void 0:t.discordUsername]),(0,i.useEffect)(()=>{A(!!(null==t?void 0:t.discordUsername))},[null==t?void 0:t.discordUsername]);let P=()=>{S(!1),function(e){if(e)try{window.sessionStorage.setItem("".concat(X).concat(e),"1")}catch(e){}}(E);let e=new URLSearchParams(n.toString());e.delete("section"),e.set("section","discord"),b.replace("/profile?".concat(e.toString()))},R=()=>{I(!1);let e=new URLSearchParams(n.toString());e.delete("guildId"),e.delete("channelId"),e.delete("worldId"),e.delete("status"),e.delete("workflow"),e.delete("section"),e.set("section","discord"),b.replace("/profile?".concat(e.toString()))},O=T&&U?"https://discord.com/channels/".concat(T,"/").concat(U):null,_=!!(null==t?void 0:t.discordUsername),M=_&&D,N=_&&0===z,F=_&&z>0;return(0,s.jsxs)(r.Z,{children:[M&&(0,s.jsx)(r.Z,{sx:{display:"flex",justifyContent:"center",alignItems:"center",minHeight:"400px"},children:(0,s.jsx)(o.Z,{size:60})}),(0,s.jsx)(r.Z,{sx:{display:M?"none":"block"},children:_?(0,s.jsx)(r.Z,{sx:{maxWidth:1100,mx:"auto",width:"100%"},children:(0,s.jsxs)(a.Z,{container:!0,spacing:2,children:[(0,s.jsx)(a.Z,{size:{xs:12},children:(0,s.jsxs)(r.Z,{sx:{display:"flex",flexDirection:{xs:"column",sm:"row"},alignItems:{xs:"flex-start",sm:"center"},gap:2,flexWrap:"wrap",rowGap:2},children:[(0,s.jsx)(r.Z,{component:"img",src:"/Discord_Blue.png",alt:"Discord Integration",sx:{height:60,width:655/478*60,objectFit:"contain",flexShrink:0}}),(0,s.jsx)(r.Z,{sx:{flex:"1 1 auto",minWidth:0,maxWidth:{sm:480}},children:(0,s.jsx)(k,{profileData:t})}),F&&(0,s.jsxs)(l.Z,{spacing:.75,sx:{flexShrink:0,ml:{sm:"auto"},alignSelf:{xs:"stretch",sm:"center"},alignItems:{xs:"stretch",sm:"flex-end"},minWidth:{sm:220}},children:[(0,s.jsx)(c.Z,{variant:"caption",color:"text.secondary",sx:{fontWeight:700,letterSpacing:.2},children:"Archivist Academy"}),(0,s.jsx)(d.Z,{href:"/academy#record-on-discord",variant:"outlined",size:"small",startIcon:(0,s.jsx)(y.Z,{}),sx:{alignSelf:{xs:"stretch",sm:"flex-end"}},children:"How to Record on Discord"}),(0,s.jsx)(d.Z,{href:"/academy#discord-byob",variant:"outlined",size:"small",startIcon:(0,s.jsx)(y.Z,{}),sx:{alignSelf:{xs:"stretch",sm:"flex-end"}},children:"Set up a companion bot"})]})]})}),N&&(0,s.jsx)(a.Z,{size:{xs:12},children:(0,s.jsx)(h.Z,{children:(0,s.jsx)(x.Z,{children:(0,s.jsxs)(l.Z,{spacing:2,children:[(0,s.jsx)(c.Z,{variant:"body2",color:"text.secondary",children:"Your Discord account is connected. To record live sessions or import Play-by-Post content, install the Archivist bot on your Discord server."}
1),(0,s.jsxs)(r.Z,{sx:{display:"flex",alignItems:"flex-start",gap:1},children:[(0,s.jsx)(Z.Z,{sx:{color:"warning.main",fontSize:"1.1rem",mt:.2}}),(0,s.jsx)(c.Z,{variant:"caption",color:"text.secondary",sx:{fontStyle:"italic"},children:"Installing the bot requires Administrator permissions on the Discord server."})]}),(0,s.jsx)(r.Z,{children:(0,s.jsx)(d.Z,{variant:"contained",href:"/api/auth/discord/connect",startIcon:(0,s.jsx)(j.Z,{}),children:"Install Bot to Server"})})]})})})}),(0,s.jsx)(a.Z,{size:{xs:12},sx:{display:N?"none":"block"},children:(0,s.jsx)(h.Z,{children:(0,s.jsx)(x.Z,{children:(0,s.jsx)(L,{profileData:t,onLoadingChange:A,onGuildCountChange:W})})})}),!N&&(0,s.jsx)(a.Z,{size:{xs:12},children:(0,s.jsx)(h.Z,{children:(0,s.jsx)(x.Z,{children:(0,s.jsx)(K,{})})})})]})}):(0,s.jsx)(r.Z,{sx:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",minHeight:{xs:"52vh",sm:"58vh"},width:"100%",py:{xs:2,sm:4},px:2},children:(0,s.jsxs)(l.Z,{spacing:3,alignItems:"center",sx:{maxWidth:440,width:"100%",textAlign:"center"},children:[(0,s.jsx)(r.Z,{component:"img",src:"/Discord_Blue.png",alt:"Discord Integration",sx:{height:{xs:56,sm:72},width:{xs:655/478*56,sm:655/478*72},objectFit:"contain"}}),(0,s.jsx)(k,{profileData:t})]})})}),(0,s.jsxs)(m.Z,{open:w,onClose:P,children:[(0,s.jsx)(u.Z,{children:"play_by_post"===E?"Connect Discord for Play-by-Post Import":"Connect Discord to Archivist"}),(0,s.jsx)(p.Z,{children:"play_by_post"===E?(0,s.jsxs)(r.Z,{children:[(0,s.jsx)(c.Z,{gutterBottom:!0,children:"To import a Play-by-Post session, you'll need to:"}),(0,s.jsx)(c.Z,{gutterBottom:!0,sx:{pl:2},children:"1. Connect your Discord account to Archivist"}),(0,s.jsx)(c.Z,{gutterBottom:!0,sx:{pl:2},children:"2. Authorize the Archivist bot in your server*"}),(0,s.jsxs)(r.Z,{sx:{display:"flex",alignItems:"flex-start",gap:1,mt:1},children:[(0,s.jsx)(Z.Z,{sx:{color:"warning.main",fontSize:"1.2rem",mt:.1,ml:0}}),(0,s.jsx)(c.Z,{gutterBottom:!0,sx:{fontStyle:"italic",fontSize:"0.875rem"},children:"*Note: you must have Administrator permissions on that server"})]})]}):(0,s.jsxs)(r.Z,{children:[(0,s.jsx)(c.Z,{gutterBottom:!0,children:"To record live on Discord, you'll need to:"}),(0,s.jsx)(c.Z,{gutterBottom:!0,sx:{pl:2},children:"1. Connect your Discord account to Archivist"}),(0,s.jsx)(c.Z,{gutterBottom:!0,sx:{pl:2},children:"2. Authorize the Archivist bot in your server*"}),(0,s.jsxs)(r.Z,{sx:{display:"flex",alignItems:"flex-start",gap:1,mt:1},children:[(0,s.jsx)(Z.Z,{sx:{color:"warning.main",fontSize:"1.2rem",mt:.1,ml:0}}),(0,s.jsx)(c.Z,{gutterBottom:!0,sx:{fontStyle:"italic",fontSize:"0.875rem"},children:"*Note: you must have Administrator permissions on that server"})]})]})}),(0,s.jsx)(g.Z,{children:(0,s.jsx)(d.Z,{onClick:P,variant:"contained",children:"Got it"})})]}),(0,s.jsxs)(m.Z,{open:C,onClose:R,maxWidth:"sm",fullWidth:!0,PaperProps:{sx:{mx:{xs:1.25,sm:2}}},children:[(0,s.jsx)(u.Z,{children:"You're all set!"}),(0,s.jsxs)(p.Z,{sx:{pt:1,px:{xs:2,sm:3},pb:1.5},children:[O?(0,s.jsx)(c.Z,{gutterBottom:!0,children:"Archivist is installed on your server. We sent a welcome message to your Discord channel with instructions to get started."}):(0,s.jsx)(c.Z,{gutterBottom:!0,children:"Archivist is installed on your server. Watch the tutorial below to get started."}),Q&&(0,s.jsx)(r.Z,{sx:{position:"relative",width:"100%",pt:"56.25%",mt:2,borderRadius:1.5,overflow:"hidden"},children:(0,s.jsx)(r.Z,{component:"iframe",src:"".concat(Q,"?rel=0"),title:"Discord Setup Tutorial",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowFullScreen:!0,sx:{position:"absolute",top:0,left:0,width:"100%",height:"100%",border:0}})}),(0,s.jsxs)(l.Z,{spacing:1.5,sx:{mt:2.5},children:[O&&(0,s.jsx)(d.Z,{href:O,target:"_blank",rel:"noopener",variant:"contained",startIcon:(0,s.jsx)(f.Z,{}),sx:{borderRadius:2,px:{xs:1.75,sm:2.25},py:1,fontWeight:700,textTransform:"none"},children:"Open Discord Channel"}),"play_by_post"===E&&B&&T&&(0,s.jsx)(d.Z,{onClick:()=>{R(),b.push("/campaigns/".concat(B,"?newSession=true&sessionType=pbp&discordServerId=").concat(T,"&onboardingBypass=logSession"))},variant:"outlined",sx:{borderRadius:2,px:{xs:1.75,sm:2.25},py:1,fontWeight:700,textTransform:"none"},children:"Start Importing"})]})]}),(0,s.jsx)(g.Z,{sx:{px:{xs:2,sm:3},pb:{xs:2,sm:2.5}},children:(0,s.jsx)(d.Z,{onClick:R,children:"Close"})})]})]})}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.