Created
March 15, 2021 14:49
-
-
Save asim/af104dd0e83b8c16bbb6918c8d9bab97 to your computer and use it in GitHub Desktop.
Revisions
-
asim created this gist
Mar 15, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,214 @@ import { NextApiRequest, NextApiResponse } from 'next' import call, { BaseURL } from '../../../../lib/micro' import TokenFromReq from '../../../../lib/token' export default async function handler(req: NextApiRequest, res: NextApiResponse) { const { query: { group_id } } = req if(req.method !== 'GET' && req.method !== 'PATCH') { res.status(405) return } // get the token from cookies const token = TokenFromReq(req) if(!token) { res.status(401).json({ error: "No token cookie set" }) return } // authenticate the request var user: any try { const rsp = await call("/users/Validate", { token }) user = rsp.user } catch ({ error, code }) { if(code === 400) code = 401 res.status(code).json({ error }) return } // load the group var group: any try { const rsp = await call("/groups/Read", { ids: [group_id] }) group = rsp.groups[group_id as string] } catch ({ error, code }) { console.error(`Error loading groups: ${error}, code: ${code}`) res.status(500).json({ error: "Error loading groups" }) return } if(!group) { res.status(404).json({ error: "Group not found"}) return } // ensure the user is a member of the group if(!group.member_ids?.includes(user.id)) { res.status(403).json({ error: "Not a member of this group" }) return } // update the groups name if(req.method === 'PATCH') { var body: { name?: string } = {} try { body = JSON.parse(req.body) } catch (error) { res.status(400).json({ error: "Error parsing request body" }) } if(!body.name?.length) { res.status(400).json({ error: "Name required" }) } try { await call("/groups/Update", { id: group.id, name: body.name }) } catch ({ error, code }) { console.error(`Error updating group: ${error}, code: ${code}`) res.status(500).json({ error: "Error updating group" }) return } // publish the message to the other users in the group try { group.member_ids.forEach(async(id: string) => { await call("/streams/Publish", { topic: id, message: JSON.stringify({ type: "group.updated", group_id: group.id, payload: { name: body.name }, }) }) }) res.status(200).json({}) return } catch ({ error, code }) { console.error(`Error publishing to stream: ${error}, code: ${code}`) res.status(500).json({ error: "Error publishing to stream"}) return } } // load the conversations and the recent messages within them var threads: any; try { const rsp = await call("/threads/ListConversations", { group_id }) threads = rsp.conversations || []; } catch ({ error, code }) { console.error(`Error loading conversations: ${error}, code: ${code}`) res.status(500).json({ error: "Error loading conversations" }) return } var messages: any = {} var user_ids: any = [...(group.member_ids || [])]; if(threads.length > 0) { try { const rsp = await call("/threads/RecentMessages", { conversation_ids: threads.map(s => s.id) }) if(rsp.messages) { user_ids.push(...rsp.messages.map(m => m.author_id)) messages = rsp.messages.reduce((res, m) => { return { ...res, [m.conversation_id]: [...(res[m.conversation_id] || []), m] } }, {}) } } catch ({ error, code }) { console.error(`Error loading recent messages: ${error}, code: ${code}`) res.status(500).json({ error: "Error loading recent messages" }) return } } // load the recent messages for all members var chatMessages: Record<string,any[]> = {} await Promise.all(group.member_ids.filter(id => user.id !== id).map(async (id: string) => { var chat_id: any try { const rsp = await call("/chats/CreateChat", { user_ids: [user.id, id] }) chat_id = rsp.chat.id } catch ({ error, code }) { console.error(`Error loading chat: ${error}, code: ${code}`) return } try { const rsp = await call("/chats/ListMessages", { chat_id }) chatMessages[id] = rsp.messages || [] } catch ({ error, code }) { console.error(`Error loading messages: ${error}, code: ${code}`) } })); // load the details of the users var users: any try { users = (await call("/users/Read", { ids: user_ids })).users } catch ({ error, code }) { console.error(`Error loading users: ${error}, code: ${code}`) res.status(500).json({ error: "Error loading users" }) return } // load the last time each thread and chat was seen var threadLastSeens = {} if (threads.length > 0) { try { const req = { user_id: user.id, resource_type: "thread", resource_ids: threads.map(s => s.id) } threadLastSeens = (await call("/seen/Read", req)).timestamps || {} } catch ({ error, code }) { console.error(`Error loading last seen: ${error}, code: ${code}`) res.status(500).json({ error: "Error loading last seen times"}) return } } var chatLastSeens = {} try { const req = { user_id: user.id, resource_type: "chat", resource_ids: Object.keys(users) } chatLastSeens = (await call("/seen/Read", req)).timestamps || {} } catch ({ error, code }) { console.error(`Error loading last seen: ${error}, code: ${code}`) res.status(500).json({ error: "Error loading last seen times"}) return } // generate a token for the websocket var websocket: any = { topic: user.id } try { websocket.token = (await call("/streams/Token", websocket)).token websocket.url = BaseURL.replace('http', 'ws') + "/streams/Subscribe" } catch ({ error, code }) { console.error(`Error loading websocket token: ${error}, code: ${code}`) res.status(500).json({ error: "Error loading websocket token"}) return } // return the data res.status(200).json({ id: group.id, name: group.name, members: group.member_ids.map(id => ({ ...users[id], current_user: users[id].id === user.id, chat: { last_seen: chatLastSeens[id], messages: (chatMessages[id] || []).map(m => ({ id: m.id, text: m.text, sent_at: m.sent_at, author: { ...users[m.author_id], current_user: m.author_id === user.id }, })), }, })), threads: threads.map(s => ({ id: s.id, topic: s.topic, last_seen: threadLastSeens[s.id], messages: (messages[s.id] || []).map(m => ({ id: m.id, text: m.text, sent_at: m.sent_at, author: { ...users[m.author_id], current_user: m.author_id === user.id }, })) })), websocket }) }