Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/app-store/apps.keys-schemas.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
**/
import { appKeysSchema as alby_zod_ts } from "./alby/zod";
import { appKeysSchema as basecamp3_zod_ts } from "./basecamp3/zod";
import { appKeysSchema as campsite_zod_ts } from "./campsite/zod";
import { appKeysSchema as closecom_zod_ts } from "./closecom/zod";
import { appKeysSchema as dailyvideo_zod_ts } from "./dailyvideo/zod";
import { appKeysSchema as fathom_zod_ts } from "./fathom/zod";
Expand Down Expand Up @@ -50,6 +51,7 @@ import { appKeysSchema as zoomvideo_zod_ts } from "./zoomvideo/zod";
export const appKeysSchemas = {
alby: alby_zod_ts,
basecamp3: basecamp3_zod_ts,
campsite: campsite_zod_ts,
closecom: closecom_zod_ts,
dailyvideo: dailyvideo_zod_ts,
fathom: fathom_zod_ts,
Expand Down
2 changes: 2 additions & 0 deletions packages/app-store/apps.metadata.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import basecamp3_config_json from "./basecamp3/config.json";
import cal_ai_config_json from "./cal-ai/config.json";
import { metadata as caldavcalendar__metadata_ts } from "./caldavcalendar/_metadata";
import campfire_config_json from "./campfire/config.json";
import campsite_config_json from "./campsite/config.json";
import clic_config_json from "./clic/config.json";
import closecom_config_json from "./closecom/config.json";
import cron_config_json from "./cron/config.json";
Expand Down Expand Up @@ -103,6 +104,7 @@ export const appStoreMetadata = {
"cal-ai": cal_ai_config_json,
caldavcalendar: caldavcalendar__metadata_ts,
campfire: campfire_config_json,
campsite: campsite_config_json,
clic: clic_config_json,
closecom: closecom_config_json,
cron: cron_config_json,
Expand Down
2 changes: 2 additions & 0 deletions packages/app-store/apps.schemas.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
**/
import { appDataSchema as alby_zod_ts } from "./alby/zod";
import { appDataSchema as basecamp3_zod_ts } from "./basecamp3/zod";
import { appDataSchema as campsite_zod_ts } from "./campsite/zod";
import { appDataSchema as closecom_zod_ts } from "./closecom/zod";
import { appDataSchema as dailyvideo_zod_ts } from "./dailyvideo/zod";
import { appDataSchema as fathom_zod_ts } from "./fathom/zod";
Expand Down Expand Up @@ -50,6 +51,7 @@ import { appDataSchema as zoomvideo_zod_ts } from "./zoomvideo/zod";
export const appDataSchemas = {
alby: alby_zod_ts,
basecamp3: basecamp3_zod_ts,
campsite: campsite_zod_ts,
closecom: closecom_zod_ts,
dailyvideo: dailyvideo_zod_ts,
fathom: fathom_zod_ts,
Expand Down
1 change: 1 addition & 0 deletions packages/app-store/apps.server.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const apiHandlers = {
"cal-ai": import("./cal-ai/api"),
caldavcalendar: import("./caldavcalendar/api"),
campfire: import("./campfire/api"),
campsite: import("./campsite/api"),
clic: import("./clic/api"),
closecom: import("./closecom/api"),
cron: import("./cron/api"),
Expand Down
2 changes: 2 additions & 0 deletions packages/app-store/bookerApps.metadata.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
**/
import around_config_json from "./around/config.json";
import campfire_config_json from "./campfire/config.json";
import campsite_config_json from "./campsite/config.json";
import { metadata as dailyvideo__metadata_ts } from "./dailyvideo/_metadata";
import demodesk_config_json from "./demodesk/config.json";
import discord_config_json from "./discord/config.json";
Expand Down Expand Up @@ -45,6 +46,7 @@ import { metadata as zoomvideo__metadata_ts } from "./zoomvideo/_metadata";
export const appStoreMetadata = {
around: around_config_json,
campfire: campfire_config_json,
campsite: campsite_config_json,
dailyvideo: dailyvideo__metadata_ts,
demodesk: demodesk_config_json,
discord: discord_config_json,
Expand Down
8 changes: 8 additions & 0 deletions packages/app-store/campsite/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
items:
- 1.png
- 2.png
- 3.png
---

{DESCRIPTION}
45 changes: 45 additions & 0 deletions packages/app-store/campsite/api/add.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { NextApiRequest } from "next";
import { stringify } from "querystring";
import { z } from "zod";

import { WEBAPP_URL } from "@calcom/lib/constants";
import { defaultHandler, defaultResponder } from "@calcom/lib/server";

import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug";
import { encodeOAuthState } from "../../_utils/oauth/encodeOAuthState";

const campsiteAppKeysSchema = z.object({
client_id: z.string(),
client_secret: z.string(),
});

export const getCampsiteAppKeys = async () => {
const appKeys = await getAppKeysFromSlug("campsite");
return campsiteAppKeysSchema.parse(appKeys);
};

async function handler(req: NextApiRequest) {
// Get user
const user = req?.session?.user;
if (!user) {
return { status: 401, body: { error: "Unauthorized" } };
}

const { client_id } = await getCampsiteAppKeys();
const state = encodeOAuthState(req);

const params = {
response_type: "code",
client_id,
redirect_uri: `${WEBAPP_URL}/api/integrations/campsite/callback`,
state,
scope: "read_user write_call_room",
};
const query = stringify(params);
const url = `https://auth.campsite.co/oauth/authorize?${query}`;
return { url };
}

export default defaultHandler({
GET: Promise.resolve({ default: defaultResponder(handler) }),
});
73 changes: 73 additions & 0 deletions packages/app-store/campsite/api/callback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import type { NextApiRequest, NextApiResponse } from "next";

import { WEBAPP_URL } from "@calcom/lib/constants";
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
import prisma from "@calcom/prisma";

import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug";
import getInstalledAppPath from "../../_utils/getInstalledAppPath";
import createOAuthAppCredential from "../../_utils/oauth/createOAuthAppCredential";
import { decodeOAuthState } from "../../_utils/oauth/decodeOAuthState";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const state = decodeOAuthState(req);
const userId = req.session?.user.id;
if (!userId) {
return res.status(404).json({ message: "No user found" });
}
const { code } = req.query;
const { client_id, client_secret } = await getAppKeysFromSlug("campsite");

const result = await fetch(`https://auth.campsite.co/oauth/token`, {
method: "POST",
body: JSON.stringify({
grant_type: "authorization_code",
code,
client_id,
client_secret,
redirect_uri: `${WEBAPP_URL}/api/integrations/campsite/callback`,
}),
headers: {
"Content-Type": "application/json",
},
});

if (result.status !== 200) {
let errorMessage = "Something is wrong with the Campsite API";
try {
const responseBody = await result.json();
errorMessage = responseBody.error;
} catch (e) {}

res.status(400).json({ message: errorMessage });
return;
}

const responseBody = await result.json();
if (responseBody.error) {
res.status(400).json({ message: responseBody.error });
return;
}

/**
* With this we take care of no duplicate Campsite keys for a single user
* when creating a room using deleteMany if there is already a Campsite key
* */
await prisma.credential.deleteMany({
where: {
type: "campsite_conferencing",
userId,
appId: "campsite",
},
});

await createOAuthAppCredential(
{ appId: "campsite", type: "campsite_conferencing" },
{ access_token: responseBody.access_token },
req
);

res.redirect(
getSafeRedirectUrl(state?.returnTo) ?? getInstalledAppPath({ variant: "conferencing", slug: "campsite" })
);
}
2 changes: 2 additions & 0 deletions packages/app-store/campsite/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as add } from "./add";
export { default as callback } from "./callback";
23 changes: 23 additions & 0 deletions packages/app-store/campsite/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"/*": "Don't modify slug - If required, do it using cli edit command",
"name": "Campsite",
"slug": "campsite",
"type": "campsite_conferencing",
"logo": "icon.svg",
"url": "https://campsite.co",
"variant": "conferencing",
"categories": ["conferencing"],
"publisher": "Campsite",
"email": "support@campsite.co",
"appData": {
"location": {
"type": "integrations:{SLUG}_conferencing",
"label": "{TITLE}",
"linkType": "dynamic"
}
},
"description": "Campsite is an all-in-one communication app that helps async teams move faster. Posts, docs, calls, and chat in one place — finally. Everything is searchable and easy to find.",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "event-type-location-video-static"
}
2 changes: 2 additions & 0 deletions packages/app-store/campsite/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * as api from "./api";
export * as lib from "./lib";
47 changes: 47 additions & 0 deletions packages/app-store/campsite/lib/VideoApiAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { CalendarEvent, EventBusyDate } from "@calcom/types/Calendar";
import type { CredentialPayload } from "@calcom/types/Credential";
import type { PartialReference } from "@calcom/types/EventManager";
import type { VideoApiAdapter, VideoCallData } from "@calcom/types/VideoApiAdapter";

type CampsiteToken = {
access_token: string;
};
const CampsiteVideoApiAdapter = (credential: CredentialPayload): VideoApiAdapter => {
return {
createMeeting: async (_event: CalendarEvent): Promise<VideoCallData> => {
const keys = credential.key as CampsiteToken;
const { access_token } = keys;
const response = await fetch("https://api.campsite.co/v1/integrations/cal_dot_com/call_rooms", {
method: "POST",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
});
const callRoom = await response.json();

return {
type: "campsite_conferencing",
id: callRoom.id,
password: "",
url: callRoom.url,
};
},
updateMeeting: async (bookingRef: PartialReference, _event: CalendarEvent): Promise<VideoCallData> => {
return {
type: "campsite_conferencing",
id: bookingRef.externalCalendarId ? bookingRef.externalCalendarId : "",
password: "",
url: bookingRef.meetingUrl ? bookingRef.meetingUrl : "",
};
},
deleteMeeting: async (_uid: string): Promise<unknown> => {
return {};
},
getAvailability: async (_dateFrom?: string, _dateTo?: string): Promise<EventBusyDate[]> => {
return [];
},
};
};

export default CampsiteVideoApiAdapter;
1 change: 1 addition & 0 deletions packages/app-store/campsite/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as VideoApiAdapter } from "./VideoApiAdapter";
14 changes: 14 additions & 0 deletions packages/app-store/campsite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/campsite",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "*"
},
"devDependencies": {
"@calcom/types": "*"
},
"description": "Campsite is an all-in-one communication app that helps async teams move faster. Posts, docs, calls, and chat in one place — finally. Everything is searchable and easy to find."
}
Binary file added packages/app-store/campsite/static/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app-store/campsite/static/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app-store/campsite/static/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading