Skip to content

feat(zendesk-api-service): add function to fetch voice lines #120

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

Merged
merged 10 commits into from
May 14, 2025
Merged
27 changes: 13 additions & 14 deletions __tests__/services/sunshine-conversation-api-service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Capabilities,
IAuthor,
IContent,
IIntegrationSuncoTwilio,
IIntegrationWhatsApp,
ISendNotificationPayload,
IServiceConfig,
Expand Down Expand Up @@ -473,21 +474,19 @@ describe("SunshineConversationApiService", () => {
}
};

const notification: IIntegrationSuncoTwilio = {
id: "id",
status: "status",
"type": UserChannelTypes.Twilio,
accountSid: "accountSid",
phoneNumberSid: "phoneNumberSid",
messagingServiceSid: "messagingServiceSid",
displayName: "Twilio",
phoneNumber: "+12345678900"
};

// Sending twilio notification
await sunshineConversationApiService.sendNotification(
{
id: "id",
status: "status",
"type": UserChannelTypes.Twilio,
accountSid: "accountSid",
phoneNumberSid: "phoneNumberSid",
messagingServiceSid: "messagingServiceSid",
displayName: "Twilio",
phoneNumber: "+12345678900"
},
phoneNumberSample,
contentSample
);
await sunshineConversationApiService.sendNotification(notification, phoneNumberSample, contentSample);

expect(client.request).toHaveBeenCalledWith(options);
});
Expand Down
37 changes: 37 additions & 0 deletions __tests__/services/zendesk-api-service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,43 @@ describe("ZendeskService", () => {
expect(result).toEqual(locales);
});
});

describe("getVoiceLines", () => {
it("should call the API and return the voice lines", async () => {
const lines = [{ name: "line1" }];
requestMock.mockResolvedValueOnce({ lines });

const result = await service.getVoiceLines();

expect(requestMock).toHaveBeenCalledWith(`/api/v2/channels/voice/lines`);
expect(result).toEqual(lines);
});

it("should continue calling the API until next_page disappears", async () => {
const lines = [{ name: "line1" }];
requestMock
.mockResolvedValueOnce({ lines, next_page: "next_page" })
.mockResolvedValueOnce({ lines: [] });

const result = await service.getVoiceLines();

expect(requestMock).toHaveBeenCalledTimes(2);
expect(requestMock).toHaveBeenNthCalledWith(1, `/api/v2/channels/voice/lines`);
expect(requestMock).toHaveBeenNthCalledWith(2, "next_page");
expect(result).toEqual(lines);
});

it("should only call the API one time with fetchAllLines set to false", async () => {
const lines = [{ name: "line1" }];
requestMock.mockResolvedValueOnce({ lines, next_page: "next_page" });

const result = await service.getVoiceLines(false);

expect(requestMock).toHaveBeenCalledTimes(1);
expect(requestMock).toHaveBeenCalledWith(`/api/v2/channels/voice/lines`);
expect(result).toEqual(lines);
});
});
});
});
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zendesk/zaf-toolbox",
"version": "0.2.12",
"version": "0.3.0",
"description": "A toolbox for ZAF application built with 🩷 by Zendesk Labs",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
Expand Down
15 changes: 12 additions & 3 deletions src/models/sunshine-conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ export type IIntegration =
| IIntegrationIos
| IIntegrationMessageBirds
| IIntegrationMessenger
| IIntegrationTwillio
| IIntegrationTwilio
| IIntegrationTwitter
| IIntegrationWeb
| IIntegrationWhatsApp
Expand Down Expand Up @@ -548,8 +548,18 @@ export interface IIntegrationMessenger extends IIntegrationBase {
pageName?: string;
}

export interface IIntegrationTwillio extends IIntegrationBase {
export interface IIntegrationTwilio extends IIntegrationBase {
type: UserChannelTypes.Twilio;
phoneNumber: string;
isTalk?: boolean;
}

export interface IIntegrationTwilioTalk extends IIntegrationTwilio {
sms: boolean;
mms: boolean;
}

export interface IIntegrationSuncoTwilio extends IIntegrationTwilio {
/**
* Twilio Account SID.
*/
Expand All @@ -558,7 +568,6 @@ export interface IIntegrationTwillio extends IIntegrationBase {
* SID for specific phone number. One of messagingServiceSid or phoneNumberSid must be provided when creating a Twilio integration
*/
phoneNumberSid: string;
phoneNumber: string;
/**
* SID for specific messaging service. One of messagingServiceSid or phoneNumberSid must be provided when creating a Twilio integration.
*/
Expand Down
47 changes: 47 additions & 0 deletions src/models/zendesk-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,53 @@ export interface IOrganizationsResults extends IZendeskResponse {
organizations: IZendeskOrganizations[];
}

export interface ILinesResults extends IZendeskResponse {
lines: IZendeskLines[];
}

export interface IZendeskLines {
capabilities: {
emergency_address: boolean;
mms: boolean;
sms: boolean;
voice: boolean;
};
categorised_greetings: {
1: string;
2: string;
};
categorised_greetings_with_sub_settings: {
1: {
voicemail_off_inside_business_hours: string;
voicemail_off_outside_business_hours: string;
voicemail_on_inside_business_hours: string;
};
2: {
voicemail_off: string;
voicemail_on: string;
};
};
country_code: string;
created_at: string;
default_greeting_ids: string[];
default_group_id: number;
display_number: string;
external: boolean;
greeting_ids: number[];
group_ids: number[];
id: number;
line_type: string;
location: string;
name: string;
nickname: string;
// eslint-disable-next-line id-denylist
number: string;
recorded: boolean;
sms_group_id: number;
toll_free: boolean;
transcription: boolean;
}

export interface ILocalesResults {
locales: IZendeskLocale[];
}
21 changes: 17 additions & 4 deletions src/services/zendesk-api-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import {
IZendeskTag,
IZendeskLocale,
IZendeskGroup,
IZendeskOrganizations
IZendeskOrganizations,
ILinesResults,
IZendeskLines,
IZendeskResponse
} from "@models/index";
import { convertContentMessageToHtml } from "@utils/convert-content-message-to-html";
import { getFromClient } from "@utils/get-from-client";
Expand All @@ -40,16 +43,15 @@ export class ZendeskApiService {
* @param extractArrayFn Function to extract the array of items from the response.
* @returns A promise resolving to a flattened array of all items.
*/
private async fetchAllPaginatedResults<TResponse, TItem>(
private async fetchAllPaginatedResults<TResponse extends IZendeskResponse, TItem>(
url: string,
fetchAll: boolean,
extractArrayFn: (response: TResponse) => TItem[]
): Promise<TItem[]> {
const results: TResponse[] = [await this.client.request<string, TResponse>(url)];

if (fetchAll) {
while (true) {
const nextPage = (results[results.length - 1] as TResponse & { next_page?: string }).next_page;
const nextPage = results[results.length - 1].next_page;
if (!nextPage) break;
results.push(await this.client.request<string, TResponse>(nextPage));
}
Expand Down Expand Up @@ -253,4 +255,15 @@ export class ZendeskApiService {

return results.locales;
}

/**
* Fetch all voice lines
*/
public async getVoiceLines(fetchAllLines = true): Promise<IZendeskLines[]> {
return this.fetchAllPaginatedResults<ILinesResults, IZendeskLines>(
`/api/v2/channels/voice/lines`,
fetchAllLines,
(response) => response.lines
);
}
}