Skip to content

Commit

Permalink
enh(Zendesk) - add a CLI command to fetch a single ticket (#9641)
Browse files Browse the repository at this point in the history
* add a CLI command to fetch a single ticket from the Zendesk API

* add missing types

* remove a layer of types

* fix a typo

* fix types

add ZendeskResyncTicketsResponseSchema to the AdminResponseSchema

* fix types

add ZendeskFetchTicketResponseSchema to the AdminResponseSchema
  • Loading branch information
aubin-tchoi authored Jan 2, 2025
1 parent 6637829 commit 03e91b2
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 1 deletion.
43 changes: 42 additions & 1 deletion connectors/src/connectors/zendesk/lib/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@ import type {
ZendeskCheckIsAdminResponseType,
ZendeskCommandType,
ZendeskCountTicketsResponseType,
ZendeskFetchTicketResponseType,
ZendeskResyncTicketsResponseType,
} from "@dust-tt/types";

import { getZendeskSubdomainAndAccessToken } from "@connectors/connectors/zendesk/lib/zendesk_access_token";
import {
fetchZendeskCurrentUser,
fetchZendeskTicket,
fetchZendeskTicketCount,
getZendeskBrandSubdomain,
} from "@connectors/connectors/zendesk/lib/zendesk_api";
import { launchZendeskTicketReSyncWorkflow } from "@connectors/connectors/zendesk/temporal/client";
import { default as topLogger } from "@connectors/logger/logger";
import { ConnectorResource } from "@connectors/resources/connector_resource";
import { ZendeskConfigurationResource } from "@connectors/resources/zendesk_resources";
import {
ZendeskConfigurationResource,
ZendeskTicketResource,
} from "@connectors/resources/zendesk_resources";

export const zendesk = async ({
command,
Expand All @@ -23,6 +28,7 @@ export const zendesk = async ({
| ZendeskCheckIsAdminResponseType
| ZendeskCountTicketsResponseType
| ZendeskResyncTicketsResponseType
| ZendeskFetchTicketResponseType
> => {
const logger = topLogger.child({ majorCommand: "zendesk", command, args });

Expand Down Expand Up @@ -101,5 +107,40 @@ export const zendesk = async ({
}
return { success: true };
}
case "fetch-ticket": {
if (!connector) {
throw new Error(`Connector ${connectorId} not found`);
}
const brandId = args.brandId ? Number(args.brandId) : null;
if (!brandId) {
throw new Error(`Missing --brandId argument`);
}
const ticketId = args.ticketId ? Number(args.ticketId) : null;
if (!ticketId) {
throw new Error(`Missing --ticketId argument`);
}
const { accessToken, subdomain } =
await getZendeskSubdomainAndAccessToken(connector.connectionId);
const brandSubdomain = await getZendeskBrandSubdomain({
connectorId: connector.id,
brandId,
subdomain,
accessToken,
});

const ticket = await fetchZendeskTicket({
accessToken,
ticketId,
brandSubdomain,
});
const ticketOnDb = await ZendeskTicketResource.fetchByTicketId({
connectorId: connector.id,
ticketId,
});
return {
ticket: ticket as { [key: string]: unknown } | null,
isTicketOnDb: ticketOnDb !== null,
};
}
}
};
24 changes: 24 additions & 0 deletions connectors/src/connectors/zendesk/lib/zendesk_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,30 @@ export async function fetchZendeskTickets(
};
}

/**
* Fetches a single ticket from the Zendesk API.
*/
export async function fetchZendeskTicket({
accessToken,
brandSubdomain,
ticketId,
}: {
accessToken: string;
brandSubdomain: string;
ticketId: number;
}): Promise<ZendeskFetchedTicket | null> {
const url = `https://${brandSubdomain}.zendesk.com/api/v2/tickets/${ticketId}`;
try {
const response = await fetchFromZendeskWithRetries({ url, accessToken });
return response?.ticket ?? null;
} catch (e) {
if (isZendeskNotFoundError(e)) {
return null;
}
throw e;
}
}

/**
* Fetches the number of tickets in a Brand from the Zendesk API.
* Only counts tickets that have been solved, and that were updated within the retention period.
Expand Down
12 changes: 12 additions & 0 deletions types/src/connectors/admin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,14 @@ export const ZendeskCommandSchema = t.type({
t.literal("check-is-admin"),
t.literal("count-tickets"),
t.literal("resync-tickets"),
t.literal("fetch-ticket"),
]),
args: t.type({
connectorId: t.union([t.number, t.undefined]),
brandId: t.union([t.number, t.undefined]),
query: t.union([t.string, t.undefined]),
forceResync: t.union([t.literal("true"), t.undefined]),
ticketId: t.union([t.number, t.undefined]),
}),
});
export type ZendeskCommandType = t.TypeOf<typeof ZendeskCommandSchema>;
Expand All @@ -293,6 +295,14 @@ export const ZendeskResyncTicketsResponseSchema = t.type({
export type ZendeskResyncTicketsResponseType = t.TypeOf<
typeof ZendeskResyncTicketsResponseSchema
>;

export const ZendeskFetchTicketResponseSchema = t.type({
ticket: t.union([t.UnknownRecord, t.null]), // Zendesk type, can't be iots'd,
isTicketOnDb: t.boolean,
});
export type ZendeskFetchTicketResponseType = t.TypeOf<
typeof ZendeskFetchTicketResponseSchema
>;
/**
* </Zendesk>
*/
Expand Down Expand Up @@ -453,6 +463,8 @@ export const AdminResponseSchema = t.union([
IntercomForceResyncArticlesResponseSchema,
ZendeskCheckIsAdminResponseSchema,
ZendeskCountTicketsResponseSchema,
ZendeskResyncTicketsResponseSchema,
ZendeskFetchTicketResponseSchema,
]);

export type AdminResponseType = t.TypeOf<typeof AdminResponseSchema>;

0 comments on commit 03e91b2

Please sign in to comment.