diff --git a/packages/client/src/components/Chat/OpenChatButton.tsx b/packages/client/src/components/Chat/OpenChatButton.tsx index fda27e1..33dd348 100644 --- a/packages/client/src/components/Chat/OpenChatButton.tsx +++ b/packages/client/src/components/Chat/OpenChatButton.tsx @@ -4,7 +4,7 @@ import { useAppContext } from "../../contexts/AppContext"; const OpenChatButton = () => { const { config } = useAppContext(); - const { notificationCount } = useChatContext(); + const { notificationCount, doLogin } = useChatContext(); return ( { color="danger" size="sm" > - {config?.chat?.element_host && ( - - )} + {config?.chat?.element_host && } ); }; diff --git a/packages/client/src/contexts/ChatContext.tsx b/packages/client/src/contexts/ChatContext.tsx index 825b8bb..7ca6165 100644 --- a/packages/client/src/contexts/ChatContext.tsx +++ b/packages/client/src/contexts/ChatContext.tsx @@ -7,6 +7,7 @@ import { useState, } from "react"; import { useAppContext } from "./AppContext"; +import { toast } from "react-toastify"; interface IMatrixUser { userId: string; @@ -38,6 +39,12 @@ export const ChatContext = ({ children }: PropsWithChildren) => { return; } + if (user?.userId) { + console.log("[ChatContext#doLogin] user logged in, opening element..."); + window.open(config.chat.element_host); + return; + } + const redirectUrl = window.location.protocol + "//" + window.location.host + "/chat_callback"; @@ -104,6 +111,59 @@ export const ChatContext = ({ children }: PropsWithChildren) => { console.log("[Chat] access token has been acquired"); setUser({ userId }); + + toast.success("Logged into chat"); + checkIfInGeneral(); + }; + + const checkIfInGeneral = async () => { + const generalAlias = config?.chat.general_alias; + if (!generalAlias) { + console.log("[ChatContext#checkIfInGeneral] no general alias in config"); + return; + } + + const accessToken = localStorage.getItem("matrix.access_token"); + if (!accessToken) return; + + const joinReq = await fetch( + `https://${config.chat.matrix_homeserver}/_matrix/client/v3/join/${generalAlias}`, + { + method: "POST", + headers: { + Authorization: "Bearer " + accessToken, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + reason: "Auto-joined via Canvas client", + }), + } + ); + const joinRes = await joinReq.json(); + console.log( + "[ChatContext#checkIfInGeneral] auto-join general response", + joinRes + ); + + if (joinReq.status === 200) { + toast.success(`Joined chat ${decodeURIComponent(generalAlias)}!`); + } else if (joinReq.status === 403) { + toast.error( + "Failed to join general chat! " + + joinRes.errcode + + " - " + + joinRes.error + ); + } else if (joinReq.status === 429) { + toast.warn("Auto-join general chat got ratelimited"); + } else { + toast.error( + "Failed to join general chat! " + + joinRes.errcode + + " - " + + joinRes.error + ); + } }; const checkForNotifs = async () => { diff --git a/packages/lib/src/net.ts b/packages/lib/src/net.ts index f3ef0e3..94070df 100644 --- a/packages/lib/src/net.ts +++ b/packages/lib/src/net.ts @@ -106,6 +106,11 @@ export type ClientConfig = { * @example https://chat.fediverse.events */ element_host: string; + /** + * URI encoded alias + * @example %23canvas-general:aftermath.gg + */ + general_alias: string; }; }; diff --git a/packages/server/src/lib/SocketServer.ts b/packages/server/src/lib/SocketServer.ts index 5826dc1..8202f57 100644 --- a/packages/server/src/lib/SocketServer.ts +++ b/packages/server/src/lib/SocketServer.ts @@ -72,6 +72,7 @@ const getClientConfig = (): ClientConfig => { enabled: true, matrix_homeserver: process.env.MATRIX_HOMESERVER, element_host: process.env.ELEMENT_HOST, + general_alias: process.env.MATRIX_GENERAL_ALIAS, }, }; }; diff --git a/packages/server/src/types.ts b/packages/server/src/types.ts index 1aae208..48570b5 100644 --- a/packages/server/src/types.ts +++ b/packages/server/src/types.ts @@ -54,6 +54,7 @@ declare global { MATRIX_HOMESERVER: string; ELEMENT_HOST: string; + MATRIX_GENERAL_ALIAS: string; } } }