2022-04-06 12:37:06 +00:00
import { WebClient } from "@slack/web-api" ;
import { NextApiRequest , NextApiResponse } from "next" ;
2022-06-11 21:30:52 +00:00
import { z } from "zod" ;
2022-04-06 12:37:06 +00:00
2022-08-26 00:48:50 +00:00
import { DailyLocationType } from "@calcom/app-store/locations" ;
2022-07-12 14:32:27 +00:00
import dayjs from "@calcom/dayjs" ;
2022-04-06 12:37:06 +00:00
import { WEBAPP_URL } from "@calcom/lib/constants" ;
import db from "@calcom/prisma" ;
2022-06-11 21:30:52 +00:00
import type { BookingCreateBody } from "@calcom/prisma/zod-utils" ;
2022-04-06 12:37:06 +00:00
import { WhereCredsEqualsId } from "../WhereCredsEqualsID" ;
import { getUserEmail } from "../utils" ;
export default async function createEvent ( req : NextApiRequest , res : NextApiResponse ) {
const {
user ,
view : {
state : { values } ,
2022-06-11 21:30:52 +00:00
id : view_id ,
2022-04-06 12:37:06 +00:00
} ,
2022-06-11 21:30:52 +00:00
response_url ,
2022-04-06 12:37:06 +00:00
} = JSON . parse ( req . body . payload ) ;
// This is a mess I have no idea why slack makes getting infomation this hard.
const {
eventName : {
event_name : { value : selected_name } ,
} ,
eventType : {
"create.event.type" : {
selected_option : { value : selected_event_id } ,
} ,
} ,
selectedUsers : {
invite_users : { selected_users } ,
} ,
eventDate : {
event_date : { selected_date } ,
} ,
eventTime : {
event_start_time : { selected_time } ,
} ,
} = values ;
// Im sure this query can be made more efficient... The JSON filtering wouldnt work when doing it directly on user.
const foundUser = await db . credential
2022-08-31 19:44:47 +00:00
. findFirstOrThrow ( {
2022-04-06 12:37:06 +00:00
. . . WhereCredsEqualsId ( user . id ) ,
} )
. user ( {
select : {
username : true ,
email : true ,
timeZone : true ,
locale : true ,
eventTypes : {
where : {
id : parseInt ( selected_event_id ) ,
} ,
select : {
id : true ,
length : true ,
locations : true ,
} ,
} ,
credentials : {
. . . WhereCredsEqualsId ( user . id ) ,
} ,
} ,
} ) ;
2022-06-11 21:30:52 +00:00
const SlackCredentialsSchema = z . object ( {
access_token : z.string ( ) ,
} ) ;
2022-04-06 12:37:06 +00:00
2022-06-11 21:30:52 +00:00
const slackCredentials = SlackCredentialsSchema . parse ( foundUser ? . credentials [ 0 ] . key ) ; // Only one slack credential for user
2022-04-06 12:37:06 +00:00
const access_token = slackCredentials ? . access_token ;
// https://api.slack.com/authentication/best-practices#verifying since we verify the request is coming from slack we can store the access_token in the DB.
const client = new WebClient ( access_token ) ;
// This could get a bit weird as there is a 3 second limit until the post times ou
// Compute all users that have been selected and get their email.
2022-06-11 21:30:52 +00:00
const invitedGuestsEmails = selected_users . map ( ( userId : string ) = > getUserEmail ( client , userId ) ) ;
2022-04-06 12:37:06 +00:00
const startDate = dayjs ( ` ${ selected_date } ${ selected_time } ` , "YYYY-MM-DD HH:mm" ) ;
const PostData : BookingCreateBody = {
start : dayjs ( startDate ) . format ( ) ,
end : dayjs ( startDate )
. add ( foundUser ? . eventTypes [ 0 ] ? . length ? ? 0 , "minute" )
. format ( ) ,
eventTypeId : foundUser?.eventTypes [ 0 ] ? . id ? ? 0 ,
user : foundUser?.username ? ? "" ,
email : foundUser?.email ? ? "" ,
name : foundUser?.username ? ? "" ,
guests : await Promise . all ( invitedGuestsEmails ) ,
2022-08-26 00:48:50 +00:00
location : DailyLocationType , // Defaulting to daily video to make this a bit more usefull than in-person
2022-04-06 12:37:06 +00:00
timeZone : foundUser?.timeZone ? ? "" ,
language : foundUser?.locale ? ? "en" ,
customInputs : [ { label : "" , value : "" } ] ,
metadata : { } ,
notes : "This event was created with slack." ,
} ;
2022-06-11 21:30:52 +00:00
const response = await fetch ( ` ${ WEBAPP_URL } /api/book/event ` , {
2022-04-06 12:37:06 +00:00
method : "POST" ,
body : JSON.stringify ( PostData ) ,
headers : {
"Content-Type" : "application/json" ,
} ,
2022-06-11 21:30:52 +00:00
} ) ;
const body = await response . json ( ) ;
client . chat . postMessage ( {
token : access_token ,
channel : user.id ,
text : body.errorCode ? ` Error: ${ body . errorCode } ` : "Booking has been created." ,
} ) ;
return res . status ( 200 ) . send ( "" ) ;
2022-04-06 12:37:06 +00:00
}