-
Notifications
You must be signed in to change notification settings - Fork 8.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: make.com/integromat app #8897
Changes from all commits
aa59464
6d9c0fa
be0a13d
e639b88
21f3c61
75a4731
a47f36a
cacd62b
993f8bb
684e231
c356f18
c0ea35f
ea6f486
2a5d2ea
f112033
e208d90
e63430d
486a24c
d7067a1
89c8193
c41dbe6
f5911d8
a25f97a
b0f89df
1ef52c2
5c94655
3171b26
fb59ff0
02e037e
b696af8
1f85a27
9536f33
01ba41e
230ebbd
70c1f3e
398b6d0
613b3ae
d92a6ab
2d7f054
28c570b
2a3d58f
cc25243
4058cbc
6bfabe4
84d8504
f21ae3b
6ace33e
d4bb915
c4bfe98
e0a8cf9
786ca13
a236eca
bb29b20
789b06a
421f601
2d63712
2bc478b
0a50ce6
4a84a16
fdcc6a8
d58d71b
c35c0aa
711c533
ef684b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--- | ||
items: | ||
- 1.jpeg | ||
- 2.jpeg | ||
- 3.jpeg | ||
- 4.jpeg | ||
- 5.jpeg | ||
--- | ||
|
||
Workflow automation for everyone. Use the Cal.com app in Make to automate your workflows when a booking is created, rescheduled, cancelled or when a meeting has ended. You can also get all your booking with the 'List Bookings' module.<br /><br />**After Installation:** Have you lost your API key? You can always generate a new key on the <a href="/apps/make/setup">**<ins>Make Setup Page</ins>**</a> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Setting up Make Integration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @aar2dee2 I don't see the instructions on how to create the app on make.com. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just updated the readme. Request @CarinaWolli to look at point 5 - how did add the app to scenarios once you had the invite link? |
||
|
||
|
||
1. Install the app from the Cal app store and generate an API key. Copy the API key. | ||
2. Go to `/admin/apps/automation` in Cal and set the `invite_link` for Make to `https://www.make.com/en/hq/app-invitation/6cb2772b61966508dd8f414ba3b44510` to use the app. | ||
3. Create a [Make account](https://www.make.com/en/login), if you don't have one. | ||
4. Go to `Scenarios` in the sidebar and click on **Create a new scenario**. | ||
5. Search for `Cal.com` in the apps list and select from the list of triggers - Booking Created, Booking Deleted, Booking Rescheduled, Meeting Ended | ||
6. To create a **connection** you will need your Cal deployment url and the app API Key generated above. You only need to create a **connection** once, all webhooks can use that connection. | ||
7. Setup the webhook for the desired event in Make. | ||
8. To delete a webhook, go to `Webhooks` in the left sidebar in Make, pick the webhook you want to delete and click **delete**. | ||
|
||
## Localhost or Self-hosting | ||
|
||
Localhost urls can not be used as the base URL for api endpoints | ||
|
||
Possible solution: using [https://ngrok.com/](https://ngrok.com/) | ||
|
||
1. Create Account | ||
2. [Download](https://ngrok.com/download) ngrok and start a tunnel to your running localhost | ||
- Use forwarding url as your baseUrl for the URL endpoints | ||
3. Use the ngrok url as your Cal deployment url when creating the **Connection** in Make. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation"; | ||
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler"; | ||
|
||
import appConfig from "../config.json"; | ||
|
||
const handler: AppDeclarativeHandler = { | ||
appType: appConfig.type, | ||
variant: appConfig.variant, | ||
slug: appConfig.slug, | ||
supportsMultipleInstalls: false, | ||
handlerType: "add", | ||
redirect: { | ||
newTab: true, | ||
url: "/apps/make/setup", | ||
}, | ||
createCredential: ({ appType, user, slug, teamId }) => | ||
createDefaultInstallation({ appType, userId: user.id, slug, key: {}, teamId }), | ||
}; | ||
|
||
export default handler; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export { default as add } from "./add"; | ||
export { default as listBookings } from "./subscriptions/listBookings"; | ||
export { default as deleteSubscription } from "./subscriptions/deleteSubscription"; | ||
export { default as addSubscription } from "./subscriptions/addSubscription"; | ||
export { default as me } from "./subscriptions/me"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import type { NextApiRequest, NextApiResponse } from "next"; | ||
|
||
import findValidApiKey from "@calcom/features/ee/api-keys/lib/findValidApiKey"; | ||
import { addSubscription } from "@calcom/features/webhooks/lib/scheduleTrigger"; | ||
import { defaultHandler, defaultResponder } from "@calcom/lib/server"; | ||
|
||
async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
const apiKey = req.query.apiKey as string; | ||
|
||
if (!apiKey) { | ||
return res.status(401).json({ message: "No API key provided" }); | ||
} | ||
|
||
const validKey = await findValidApiKey(apiKey, "make"); | ||
|
||
if (!validKey) { | ||
return res.status(401).json({ message: "API key not valid" }); | ||
} | ||
|
||
const { subscriberUrl, triggerEvent } = req.body; | ||
|
||
const createAppSubscription = await addSubscription({ | ||
appApiKey: validKey, | ||
triggerEvent: triggerEvent, | ||
subscriberUrl: subscriberUrl, | ||
appId: "make", | ||
}); | ||
|
||
if (!createAppSubscription) { | ||
return res.status(500).json({ message: "Could not create subscription." }); | ||
} | ||
|
||
res.status(200).json(createAppSubscription); | ||
} | ||
|
||
export default defaultHandler({ | ||
POST: Promise.resolve({ default: defaultResponder(handler) }), | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import type { NextApiRequest, NextApiResponse } from "next"; | ||
import z from "zod"; | ||
|
||
import findValidApiKey from "@calcom/features/ee/api-keys/lib/findValidApiKey"; | ||
import { deleteSubscription } from "@calcom/features/webhooks/lib/scheduleTrigger"; | ||
import { defaultHandler, defaultResponder } from "@calcom/lib/server"; | ||
|
||
const querySchema = z.object({ | ||
apiKey: z.string(), | ||
id: z.string(), | ||
}); | ||
|
||
async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
aar2dee2 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const { apiKey, id } = querySchema.parse(req.query); | ||
|
||
if (!apiKey) { | ||
return res.status(401).json({ message: "No API key provided" }); | ||
} | ||
|
||
const validKey = await findValidApiKey(apiKey, "make"); | ||
|
||
if (!validKey) { | ||
return res.status(401).json({ message: "API key not valid" }); | ||
} | ||
|
||
const deleteEventSubscription = await deleteSubscription({ | ||
appApiKey: validKey, | ||
webhookId: id, | ||
appId: "make", | ||
}); | ||
|
||
if (!deleteEventSubscription) { | ||
return res.status(500).json({ message: "Could not delete subscription." }); | ||
} | ||
res.status(204).json({ message: "Subscription is deleted." }); | ||
} | ||
|
||
export default defaultHandler({ | ||
DELETE: Promise.resolve({ default: defaultResponder(handler) }), | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import type { NextApiRequest, NextApiResponse } from "next"; | ||
|
||
import findValidApiKey from "@calcom/features/ee/api-keys/lib/findValidApiKey"; | ||
import { listBookings } from "@calcom/features/webhooks/lib/scheduleTrigger"; | ||
import { defaultHandler, defaultResponder } from "@calcom/lib/server"; | ||
|
||
async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
const apiKey = req.query.apiKey as string; | ||
|
||
if (!apiKey) { | ||
return res.status(401).json({ message: "No API key provided" }); | ||
} | ||
|
||
const validKey = await findValidApiKey(apiKey, "make"); | ||
|
||
if (!validKey) { | ||
return res.status(401).json({ message: "API key not valid" }); | ||
} | ||
const bookings = await listBookings(validKey); | ||
|
||
if (!bookings) { | ||
return res.status(500).json({ message: "Unable to get bookings." }); | ||
} | ||
if (bookings.length === 0) { | ||
const requested = validKey.teamId ? "teamId: " + validKey.teamId : "userId: " + validKey.userId; | ||
return res.status(404).json({ | ||
message: `There are no bookings to retrieve, please create a booking first. Requested: \`${requested}\``, | ||
}); | ||
} | ||
res.status(201).json(bookings); | ||
} | ||
|
||
export default defaultHandler({ | ||
GET: Promise.resolve({ default: defaultResponder(handler) }), | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import type { NextApiRequest, NextApiResponse } from "next"; | ||
|
||
import findValidApiKey from "@calcom/features/ee/api-keys/lib/findValidApiKey"; | ||
import prisma from "@calcom/prisma"; | ||
|
||
export default async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
const apiKey = req.query.apiKey as string; | ||
|
||
if (!apiKey) { | ||
return res.status(401).json({ message: "No API key provided" }); | ||
} | ||
|
||
const validKey = await findValidApiKey(apiKey, "make"); | ||
|
||
if (!validKey) { | ||
return res.status(401).json({ message: "API key not valid" }); | ||
} | ||
|
||
if (req.method === "GET") { | ||
try { | ||
const user = await prisma.user.findFirst({ | ||
where: { | ||
id: validKey.userId, | ||
}, | ||
select: { | ||
username: true, | ||
}, | ||
}); | ||
res.status(201).json(user); | ||
} catch (error) { | ||
console.error(error); | ||
return res.status(500).json({ message: "Unable to get User." }); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"/*": "Don't modify slug - If required, do it using cli edit command", | ||
"name": "Make", | ||
"slug": "make", | ||
"type": "make_automation", | ||
"logo": "icon.svg", | ||
"url": "https://cal.com/apps/make", | ||
"variant": "automation", | ||
"categories": ["automation"], | ||
"publisher": "aa2dee2", | ||
"email": "support@cal.com", | ||
"description": "Automate workflows", | ||
"isTemplate": false, | ||
"__createdUsingCli": true, | ||
"__template": "basic", | ||
"imageSrc": "icon.svg", | ||
"dirName": "make" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * as api from "./api"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"$schema": "https://json.schemastore.org/package.json", | ||
"private": true, | ||
"name": "@calcom/make", | ||
"version": "0.0.0", | ||
"main": "./index.ts", | ||
"description": "Workflow automation for everyone. Use the Cal.com Make app to trigger your workflows when a booking is created, rescheduled, or cancelled, or after a meeting ends.", | ||
"dependencies": { | ||
"@calcom/lib": "*" | ||
}, | ||
"devDependencies": { | ||
"@calcom/types": "*", | ||
"@types/node-schedule": "^2.1.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import type { GetStaticPropsContext } from "next"; | ||
|
||
import getAppKeysFromSlug from "../../../_utils/getAppKeysFromSlug"; | ||
|
||
export interface IMakeSetupProps { | ||
inviteLink: string; | ||
} | ||
|
||
export const getStaticProps = async (ctx: GetStaticPropsContext) => { | ||
if (typeof ctx.params?.slug !== "string") return { notFound: true } as const; | ||
let inviteLink = ""; | ||
const appKeys = await getAppKeysFromSlug("make"); | ||
if (typeof appKeys.invite_link === "string") inviteLink = appKeys.invite_link; | ||
|
||
return { | ||
props: { | ||
inviteLink, | ||
}, | ||
}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo here. It's app
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx. will fix in a different PR