Skip to content

Instantly share code, notes, and snippets.

@ecwyne
Created October 6, 2021 20:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ecwyne/50e735385495091da4e6b98d5eb9168b to your computer and use it in GitHub Desktop.
Save ecwyne/50e735385495091da4e6b98d5eb9168b to your computer and use it in GitHub Desktop.
Paul Response Tap
import fetch from 'isomorphic-unfetch';
import { stringify } from 'querystring';
import pLimit from 'p-limit';
const limit = pLimit(2);
export class RTap {
private auth: string;
constructor(private accountId: number | string, secret: string) {
this.auth = `Basic ${Buffer.from(secret).toString('base64')}`;
}
private get = async <T>(
path: string,
body: Record<string, any>,
needAccount: boolean,
) => {
const url = `https://dashboard.responsetap.com/api/1${
needAccount ? `/accounts/${this.accountId}` : ''
}${path}?${stringify(body)}`;
return limit(() =>
fetch(url, {
headers: {
Authorization: this.auth,
'Content-Type': 'application/json',
Accept: 'application/json',
},
}).then(r => r.json() as Promise<T>),
);
};
private put = async <T>(
path: string,
body: Record<string, any>,
needAccount: boolean,
) => {
const url = `https://dashboard.responsetap.com/api/1${
needAccount ? `/accounts/${this.accountId}` : ''
}${path}`;
return fetch(url, {
method: 'PUT',
headers: {
Authorization: this.auth,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(body),
}).then(r => r.json() as Promise<T>);
};
private post = async (
path: string,
body: Record<string, any>,
needAccount: boolean,
) => {
const url = `https://dashboard.responsetap.com/api/1${
needAccount ? `/accounts/${this.accountId}` : ''
}${path}`;
return fetch(url, {
method: 'POST',
headers: {
Authorization: this.auth,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(body),
}).then(r => r.text());
};
websites = () => this.get<Website[]>('/websites', {}, true);
destinations = () => this.get<Destination[]>('/destinations', {}, true);
numberPlaceholders = (sourceId: number) =>
this.get<NumberPlaceholder[]>(
`/sources/${sourceId}/numberPlaceHolders`,
{},
true,
);
numberPlaceholderFeatures = (
sourceId: number,
numberPlaceHolderId: number,
) =>
this.get<NumberPlaceholderFeatures>(
`/sources/${sourceId}/numberPlaceHolders/${numberPlaceHolderId}/features`,
{},
true,
);
updateOnCall = (
sourceId: number,
numberPlaceHolderId: number,
ids: number[],
) =>
this.post(
`/sources/${sourceId}/numberPlaceHolders/${numberPlaceHolderId}/urlCallbacksOnCallFeatures`,
{ selectedCallbackUrlIds: ids },
true,
);
updatePostCall = (
sourceId: number,
numberPlaceHolderId: number,
ids: number[],
) =>
this.post(
`/sources/${sourceId}/numberPlaceHolders/${numberPlaceHolderId}/urlCallbacksPostCallFeatures`,
{ selectedCallbackUrlIds: ids },
true,
);
enableRecordings = (sourceId: number, numberPlaceHolderId: number) =>
this.post(
`/sources/${sourceId}/numberPlaceHolders/${numberPlaceHolderId}/callRecordings?termsAccepted=True`,
{},
true,
);
updatePlaceholder = async (
sourceId: number,
placeholderId: number,
update: Partial<NumberPlaceholderUpdate>,
) => {
return { sourceId, placeholderId, update };
};
cdrids = async (
fromDate: string,
toDate: string,
comparison: {
type?:
| 'CUSTOMER_NUMBER'
| 'VISITOR_ID'
| 'MEDIUM'
| 'CHANNEL'
| 'CAMPAIGN'
| 'ADVERT_REFERENCE'
| 'CALL_DURATION'
| 'DISPOSITION'
| 'BENCHMARK'
| 'TALK_TIME';
comparisonValue?:
| 'BETWEEN'
| 'GREATER_THAN'
| 'LESS_THAN'
| 'LIKE'
| 'EXACT';
value?: string | number;
} = {},
) =>
this.get<{ cdrUniqueIds: string[] }>(
`/cdrids`,
{ fromDate, toDate, ...comparison },
true,
);
call = async (callId: string) =>
this.get<Call>(`/calls/${callId}`, {}, true);
nthDailyCall = async (callDate: string, dailyCallId: number) =>
this.get<FullCallRecord>(
'/fullCallRecords',
{ callDate, dailyCallId },
true,
);
sources = () =>
this.get<
{
sourceId: number;
sourceName: string;
}[]
>('/sources', {}, true);
visit = (visitorId: string | number, visitId: string | number) =>
this.get<Visit>(`/visitor/${visitorId}/visit/${visitId}`, {}, true);
visitor = (visitorId: number | string) =>
this.get<Visitor>(`/visitor/${visitorId}`, {}, true).then(res =>
res.visitorId ? res : null,
);
}
export interface NumberPlaceholder {
defaultDisplayNumber: string;
description: string;
destinationId: number;
exampleDisplayNumber: string;
numberLayoutFormatId: number;
numberPlaceHolderId: number;
numberPrefixId: number;
prefixDisplayFormatId: number;
trackingType: string;
}
interface NumberPlaceholderUpdate {
defaultDisplayNumber: string;
description: string;
destinationId: number;
destinationNumber: string;
numberLayoutId: number;
numberPrefixId: number;
prefixDisplayFormatId: number;
trackingType: string;
}
export interface NumberPlaceholderFeatures {
callRecodings: 'ON';
postCallIvr: number | null;
benchmarkFeatureForm: number | null;
callWhisperFeatureForm: number | null;
googleAnalyticsFeatureForm: number | null;
missedCallEmailsFeatureForm: number | null;
postCallUrlCallbacksFeatureForm?: {
selectedCallbackUrlIds: number[];
};
onCallUrlCallbacksFeatureForm?: {
selectedCallbackUrlIds: number[];
};
routingProfileFeatureForm: number | null;
}
interface Website {
attributionWindow: number;
name: string;
url: string;
websiteId: number;
}
export interface Destination {
accountId: number;
destinationId: number;
number: string;
}
export interface FullCallRecord {
adReference: string;
benchmarkDescription: string;
benchmarkLabel: string;
benchmarkViewedId: string;
businessNumber: string;
callDate: number;
callDuration: number;
callId: string;
callTalkTime: number;
callerId: string;
campaignName: string;
cdrId: string;
channelName: string;
cookies: string;
currencySymbol: string;
customVariables: string;
customerNumber: string;
disposition: string;
goalName: string;
goalValue: string;
landingPage: string;
leadValue: string;
locationFormattedBusinessNumber: string;
locationFormattedCustomerNumber: string;
locationFormattedTrackingNumber: string;
mediumName: string;
mediumTypeName: string;
numberGroupId: string;
numberGroupName: string;
recorded: boolean;
referrer: string;
salesValue: string;
searchPhrase: string;
sourceId: string;
trackingNumber: string;
visitId: string;
visitorId: string;
}
export interface Call {
cdrId: string;
visitorId: string;
visitId: string;
customerNumber: string;
locationFormattedCustomerNumber?: string | null;
trackingNumber: string;
locationFormattedTrackingNumber?: string | null;
businessNumber: string;
locationFormattedBusinessNumber?: string | null;
campaignName: string;
searchPhrase?: string | null;
callDate: number;
callDuration: number;
callTalkTime: number;
disposition: string;
salesValue?: string | null;
leadValue?: string | null;
goalName?: string | null;
goalValue?: string | null;
recorded: true;
sourceId: string;
channelName: string;
mediumName: string;
mediumTypeName: string;
adReference: string;
landingPage: string;
referrer: string;
numberGroupId: string;
numberGroupName: string;
callId: string;
benchmarkViewedId?: string | null;
benchmarkLabel?: string | null;
benchmarkDescription?: string | null;
customVariables?: string | null;
cookies?: string | null;
currencySymbol?: string | null;
callerId: string;
status: string;
}
export interface Visit {
calls: Call[];
endTime: number;
goalCount: number;
landingPageImpressions: {
pageImpressionId: number;
impressionDateTime: number;
windowLocation: string;
referrer: string;
referringHost: string;
referringDomain: string;
advertReference: {
advertReferenceId: number;
advertReference: string;
mediumType: string;
};
impressionParams: {
name: string;
value: string;
}[];
searchPhrase: string;
hasCookies: false;
}[];
pageImpressions: {
pageImpressionId: number;
impressionDateTime: number;
windowLocation: string;
}[];
startTime: number;
visitId: number;
websiteId: number;
}
export interface Visitor {
visitIds: number[];
visitorId: number;
websiteId: number;
browser: string | null;
browserLanguage: string | null;
displayColourDepth: string | null;
displayResolution: string | null;
flashVersion: string | null;
javaVersion: string | null;
operatingSystem: string | null;
userAgent: string | null;
}
@ecwyne
Copy link
Author

ecwyne commented Oct 6, 2021

I additionally get call recordings at https://dashboard.responsetap.com/api/1/accounts/{{accountId}}/calls/{{cdrId}}/recording

@ecwyne
Copy link
Author

ecwyne commented Oct 6, 2021

You can also see the details of the webhooks we have sent onCall and postCall on our account.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment