Skip to content

Commit

Permalink
Merge pull request #18 from peoray/campaign-endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
peoray authored Nov 16, 2023
2 parents b155046 + 084cff0 commit c5819c2
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 4 deletions.
68 changes: 65 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ const response = await termii.message.fetchContacts('phonebook_id', 2)
console.log(response) // IFetchContactsResponse
```

Find more details about the parameters and response for the above method [here](https://developers.termii.com/phonebook#fetch-contacts-by-phonebook-id)
Find more details about the parameters and response for the above method [here](https://developers.termii.com/contacts#fetch-contacts-by-phonebook-id)

#### Add single contacts to phonebook

Expand All @@ -309,7 +309,7 @@ const response = await termii.message.createContact('phonebook_id', payload)
console.log(response) // ICreateContactResponse
```

Find more details about the parameters and response for the above method [here](https://developers.termii.com/phonebook#add-single-contacts-to-phonebook)
Find more details about the parameters and response for the above method [here](https://developers.termii.com/contacts#add-single-contacts-to-phonebook)

#### Delete contact

Expand All @@ -321,7 +321,69 @@ const response = await termii.message.deleteContact('contact_id')
console.log(response) // IDeleteContactResponse
```

Find more details about the parameters and response for the above method [here](https://developers.termii.com/phonebook#delete-phonebook)
Find more details about the parameters and response for the above method [here](https://developers.termii.com/contacts#delete-phonebook)

### Campaign

Using the campaign APIs, you can view, manage and send a campaign to a phonebook.

#### Fetch campaigns

```ts
// import the campaign interfaces from the sdk
import type { IFetchCampaignsResponse } from 'termii-nodejs-client';

const response = await termii.message.fetchCampaigns()

// to fetch another page - pass the page number to the method
const response = await termii.message.fetchCampaigns(2)
console.log(response) // IFetchCampaignsResponse
```

Find more details about the parameters and response for the above method [here](https://developers.termii.com/campaign#fetch-campaigns)

#### Fetch campaign history

```ts
// import the campaign interfaces from the sdk
import type { fetchCampaignHistoryResponseData } from 'termii-nodejs-client';

const response = await termii.message.fetchCampaigns('campaign_id')

// to fetch another page - pass the page number to the method after campaign ID
const response = await termii.message.fetchCampaigns('campaign_id', 2)
console.log(response) // fetchCampaignHistoryResponseData
```

Find more details about the parameters and response for the above method [here](https://developers.termii.com/campaign#fetch-campaign-history)

#### Send a campaign

```ts
// import the campaign interfaces from the sdk
import type { ISendCampaign, ISendCampaignResponse } from 'termii-nodejs-client';

const payload: ISendCampaign = {
api_key: "Your API KEY",
country_code: "234",
sender_id: "Termii",
message: "Welcome to Termii.",
channel: "generic",
message_type: "Plain",
phonebook_id: "2d9f4a02-85b8-45e5-9f5b-30f93ef472e2",
delimiter: ",",
remove_duplicate: "yes",
campaign_type: "personalized",
schedule_time: "30-06-2021 6:00",
schedule_sms_status: "scheduled"
}

const response = await termii.message.sendCampaign(payload)

console.log(response) // ISendCampaignResponse
```

Find more details about the parameters and response for the above method [here](https://developers.termii.com/campaign#send-a-campaign)


## License
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "termii-nodejs-client",
"version": "0.2.0",
"version": "0.3.0",
"description": "Nodejs SDK wrapper for Termii API written with Typescript support",
"author": "Emmanuel Raymond",
"module": "dist/termii.esm.js",
Expand Down
125 changes: 125 additions & 0 deletions src/services/messaging/campaign/campaign.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { Campaign } from './campaign'
import {
IFetchCampaignHistoryResponse,
IFetchCampaignsResponse,
ISendCampaign,
ISendCampaignResponse,
} from '../../../types'

const campaignInstance = new Campaign('api-key')

const fetchCampaignsResponseData: IFetchCampaignsResponse = {
data: [
{
campaign_id: 'C60e30b2c806da',
phone_book: 'test',
sender: 'Termii',
camp_type: 'scheduled',
channel: '-',
total_recipients: 0,
run_at: '2022-07-05 00:00:00',
status: 'Scheduled',
created_at: '2021-07-05T13:37:48.000000Z',
},
],
links: {
first: 'https://api.ng.termii.com/api/sms/campaigns?page=1',
last: 'https://api.ng.termii.com/api/sms/campaigns?page=1',
prev: null,
next: null,
},
meta: {
current_page: 1,
from: 1,
last_page: 1,
path: 'https://api.ng.termii.com/api/sms/campaigns',
per_page: 15,
to: 11,
total: 11,
},
}

const fetchCampaignHistoryResponseData: IFetchCampaignHistoryResponse = {
data: [
{
id: 64,
sender: 'Termii',
receiver: '2347089509657',
message: 'Hi This is from Termii Campaign',
message_abbreviation: 'Hi This is from Termii Campaign',
amount: 1,
channel: 'Generic',
sms_type: 'plain',
message_id:
'0011551727393226622357573897694282599004522965786793671662369098835884420487860904021011663',
status: 'Sent',
date_created: '2020-01-26 07:24:29',
last_updated: '2020-01-26 07:24:29',
},
],
links: {
first: 'https://api.ng.termii.com/api/sms/campaigns/C5dbae7faa2b65?page=1',
last: 'https://api.ng.termii.com/api/sms/campaigns/C5dbae7faa2b65?page=1',
prev: null,
next: null,
},
meta: {
current_page: 1,
from: 1,
last_page: 1,
path: 'https://api.ng.termii.com/api/sms/campaigns/C5dbae7faa2b65',
per_page: 15,
to: 1,
total: 1,
},
}

const payload: ISendCampaign = {
country_code: '234',
sender_id: 'Termii',
message: 'Welcome to Termii.',
channel: 'generic',
message_type: 'Plain',
phonebook_id: '2d9f4a02-85b8-4d84-9f5b-30f93ef472e2',
delimiter: ',',
remove_duplicate: 'yes',
campaign_type: 'personalized',
schedule_time: '30-06-2024 6:00',
schedule_sms_status: 'scheduled',
}

const sendCampaignResponse: ISendCampaignResponse = {
message: 'Your campaign has been scheduled',
}

describe('Contact', () => {
it('should fetch list of campaigns', async () => {
try {
const response = await campaignInstance.fetchCampaigns()

expect(response).toEqual(fetchCampaignsResponseData)
} catch (error) {
expect(error).toBeInstanceOf(Error)
}
})

it('should fetch list of campaign history', async () => {
try {
const response = await campaignInstance.fetchCampaignHistory('12345678')

expect(response).toEqual(fetchCampaignHistoryResponseData)
} catch (error) {
expect(error).toBeInstanceOf(Error)
}
})

it('should send a campaign', async () => {
try {
const response = await campaignInstance.sendCampaign(payload)

expect(response).toEqual(sendCampaignResponse)
} catch (error) {
expect(error).toBeInstanceOf(Error)
}
})
})
68 changes: 68 additions & 0 deletions src/services/messaging/campaign/campaign.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { TermiiCore } from '../../../api'
import {
IFetchCampaignsResponse,
IFetchCampaignHistoryResponse,
ISendCampaign,
ISendCampaignResponse,
} from '../../../types'
import { IAxiosStruct, handleErrors } from '../../../utils'

export class Campaign extends TermiiCore {
constructor(apiKey: string) {
super(apiKey)
}

public async fetchCampaigns(page?: number): Promise<IFetchCampaignsResponse> {
try {
const requestObj: IAxiosStruct = {
method: 'GET',
url: `sms/campaigns`,
page,
}

const response = await this.useRequest(requestObj)

return response?.data as IFetchCampaignsResponse
} catch (error) {
return handleErrors(error)
}
}

public async fetchCampaignHistory(
campaign_id: string,
page?: number
): Promise<IFetchCampaignHistoryResponse> {
try {
const requestObj: IAxiosStruct = {
method: 'GET',
url: `sms/campaigns/${campaign_id}`,
page,
}

const response = await this.useRequest(requestObj)

return response?.data as IFetchCampaignHistoryResponse
} catch (error) {
console.error(error)
return handleErrors(error)
}
}

public async sendCampaign(
data: ISendCampaign
): Promise<ISendCampaignResponse> {
try {
const requestObj: IAxiosStruct = {
method: 'POST',
url: `/sms/campaigns/send`,
data,
}

const response = await this.useRequest(requestObj)

return response?.data as ISendCampaignResponse
} catch (error) {
return handleErrors(error)
}
}
}
15 changes: 15 additions & 0 deletions src/services/messaging/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Number } from './number/number'
import { Template } from './template/template'
import { Phonebook } from './phonebook/phonebook'
import { Contact } from './contact/contact'
import { Campaign } from './campaign/campaign'

/**
* The MessageHandler class handles message-related functionalities by providing access to message and sender ID instances.
Expand All @@ -15,6 +16,7 @@ export class MessageHandler {
private templateInstance: Template // Instance to handle sending message with template
private phonebookInstance: Phonebook // Instance to manage phonebooks
private contactInstance: Contact // Instance to manage contacts
private campaignInstance: Campaign // Instance to manage Campaigns

/**
* Constructs a MessageHandler instance.
Expand All @@ -29,6 +31,7 @@ export class MessageHandler {
this.templateInstance = new Template(apiKey)
this.phonebookInstance = new Phonebook(apiKey)
this.contactInstance = new Contact(apiKey)
this.campaignInstance = new Campaign(apiKey)
}

/**
Expand Down Expand Up @@ -94,6 +97,18 @@ export class MessageHandler {
deleteContact: this.contactInstance.deleteContact.bind(
this.contactInstance
),
// Method to fetch campaigns
fetchCampaigns: this.campaignInstance.fetchCampaigns.bind(
this.campaignInstance
),
// Method to fetch campaign history
fetchCampaignHistory: this.campaignInstance.fetchCampaignHistory.bind(
this.campaignInstance
),
// Method to send campaign
sendCampaign: this.campaignInstance.sendCampaign.bind(
this.campaignInstance
),
}
}
}
48 changes: 48 additions & 0 deletions src/types/campaign.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { BaseMetaResponse, MessageResponse } from './constants'

interface Campaign {
campaign_id: string
phone_book: string
sender: string
camp_type: string
channel: string
total_recipients: number
run_at: string
status: string
created_at: string
}

interface CampaignHistory {
id: number
sender: string
receiver: string
message: string
message_abbreviation: string
amount: number
channel: string
sms_type: string
message_id: string
status: string
date_created: string
last_updated: string
}

export interface IFetchCampaignsResponse extends BaseMetaResponse<Campaign> {}
export interface IFetchCampaignHistoryResponse
extends BaseMetaResponse<CampaignHistory> {}

export interface ISendCampaign {
country_code: string
sender_id: string
message: string
channel: string
message_type: string
phonebook_id: string
delimiter: string
remove_duplicate: string
campaign_type: string
schedule_time: string
schedule_sms_status: string
}

export interface ISendCampaignResponse extends MessageResponse {}
1 change: 1 addition & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './number'
export * from './template'
export * from './phonebook'
export * from './contact'
export * from './campaign'

0 comments on commit c5819c2

Please sign in to comment.