Skip to content

Commit

Permalink
added plugin-twilio this can send message using sms or whatsapp
Browse files Browse the repository at this point in the history
  • Loading branch information
juanc07 committed Jan 4, 2025
1 parent cb5de7a commit 1cb3af7
Show file tree
Hide file tree
Showing 10 changed files with 468 additions and 0 deletions.
6 changes: 6 additions & 0 deletions packages/plugin-twilio/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*

!dist/**
!package.json
!readme.md
!tsup.config.ts
78 changes: 78 additions & 0 deletions packages/plugin-twilio/ReadMe.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#The ENV file should contain this information

# Cache Configs
CACHE_STORE=database

# Discord Configuration
DISCORD_APPLICATION_ID=
DISCORD_API_TOKEN=

# AI Model API Keys
OPENAI_API_KEY=

# Twitter/X Configuration
TWITTER_USERNAME=
TWITTER_PASSWORD=
TWITTER_EMAIL=
TWITTER_POLL_INTERVAL=120 # How often (in seconds) the bot should check for interactions
TWITTER_SEARCH_ENABLE=FALSE # Enable timeline search, WARNING this greatly increases your chance of getting banned
#TWITTER_TARGET_USERS=

# Twilio Part
TWILIO_ACCOUNT_SID=
TWILIO_AUTH_TOKEN=
TWILIO_PHONE_NUMBER=
TWILIO_WHATSAPP_PHONE_NUMBER=

# Server Configuration
SERVER_PORT=3000

# How to use
1. create your .env file , if you don't have it yet and then populate it with the information above, make sure to fill in all information
2. Add this project into your eliza os project under packages
3. using terminal go inside plugin-twilio then type pnpm install twilio
4. go inside your agent folder update the package.json add this "@elizaos/plugin-twilio": "workspace:*"
5. add this inside your Agent index.ts import { twilioPlugin } from "@elizaos/plugin-twilio";
6. Add twilioPlugin in Agent Runtime still inside Agent index.ts
7. pnpm install
8. pnpm build
9. pmpn start --character="characters/nameofyouragentcharacterfile.character.json"

#Note: Make sure you have a twilio developer account and it is verified with verified phone number and have enough credits but they provide free small credits when your account is new
visit twilio: https://www.twilio.com
twilio quick start guides: https://www.twilio.com/docs/messaging/quickstart
twilio documentation: https://www.twilio.com/docs/messaging
Free Trial Account: https://www.twilio.com/docs/messaging/guides/how-to-use-your-free-trial-account

# For WhatsApp guides follow the link below you need to have a separate twilio whatsapp enabled phone number
https://www.twilio.com/docs/whatsapp
https://www.twilio.com/docs/whatsapp/quickstart/node
https://www.twilio.com/docs/whatsapp/getting-started#registering-a-whatsapp-sender
https://www.twilio.com/docs/verify/whatsapp


#Some Other Whats App Info that you might need
https://www.twilio.com/docs/whatsapp

#Twilio Phone Number guidelines
https://www.twilio.com/en-us/guidelines


# Clarification this project is intended to be use/place inside elizaos project packages, this can't work alone

# Sample implementation can be found here
https://github.com/juanc07/AgentSoulSpark

# Usage Sample

The message that you want to send must be inside a Single Quote or double quotes

Example 1:
Please send sms to [phone number], and my message is '[your message here]'
Please send whats app message to [phone number], and my message is '[your message here]'

Example 2:
Please send sms to [phone number], and my message is "[your message here]"
Please send whats app message to [phone number], and my message is "[your message here]"

#Note I haven't tested any other complex string or sentence yet, this could be improve ofcourse but for now it works that way
3 changes: 3 additions & 0 deletions packages/plugin-twilio/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import eslintGlobalConfig from "../../eslint.config.mjs";

export default [...eslintGlobalConfig];
20 changes: 20 additions & 0 deletions packages/plugin-twilio/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@elizaos/plugin-twilio",
"version": "0.1.7-alpha.2",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",
"dependencies": {
"@elizaos/core": "workspace:*",
"tsup": "8.3.5",
"twilio": "^5.4.0"
},
"scripts": {
"build": "tsup --format esm --dts",
"dev": "tsup --format esm --dts --watch",
"lint": "eslint --fix --cache ."
},
"peerDependencies": {
"whatwg-url": "7.1.0"
}
}
3 changes: 3 additions & 0 deletions packages/plugin-twilio/src/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./helloWorld.ts";
export * from "./sendSms.ts";
export * from "./sendWhatsAppMessage.ts";
173 changes: 173 additions & 0 deletions packages/plugin-twilio/src/actions/sendSms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import {
ActionExample,
generateText,
HandlerCallback,
IAgentRuntime,
Memory,
ModelClass,
State,
type Action,
} from "@elizaos/core";
import twilio from 'twilio';

export const sendSmsAction: Action = {
name: "SendSms",
similes: [
"SendSms"
],
validate: async (_runtime: IAgentRuntime, _message: Memory) => {
return true;
},
description:
"Send SMS to the mobile number provided by the user",
handler: async (
_runtime: IAgentRuntime,
_message: Memory,
_state: State,
_options:{[key:string]: unknown},
_callback: HandlerCallback,
): Promise<boolean> => {
// Check if environment variables are set
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;

console.log("CHECK _message: ",_message.content.text);

if (!accountSid || !authToken) {
console.error('TWILIO_ACCOUNT_SID or TWILIO_AUTH_TOKEN is not set');
return false;
}

// Extract the mobile number from the message
const mobileNumberRegex = /(?:\+|00)(\d{1,3})\s?(\d{3,5})\s?(\d{4,10})/; // This regex matches numbers like +1 123 4567890 or 001 123 4567890
const text = (_message.content as { text?: string })?.text || '';
const matches = text.match(mobileNumberRegex);

const messageRegex = /(['"])(.*?)\1/;
const messageMatch = text.match(messageRegex);

let mobileNumberProvidedByUser = null;
let messageToSendFromUser = null;

if(messageMatch){
messageToSendFromUser = messageMatch[2];
}
if (matches) {
// Combine the parts of the number into a single string, removing spaces and plus signs
mobileNumberProvidedByUser = `+${matches[1]}${matches[2]}${matches[3]}`;
}else{
const alternativeMobileNumberRegex = /\b(\d{3})[-.]?(\d{3})[-.]?(\d{4})\b/; // For formats like 123-456-7890 or 123.456.7890
if (!mobileNumberProvidedByUser) {
const alternativeMatches = text.match(alternativeMobileNumberRegex);
if (alternativeMatches) {
mobileNumberProvidedByUser = `${alternativeMatches[1]}${alternativeMatches[2]}${alternativeMatches[3]}`;
}
}
}

const twilioNumber = process.env.TWILIO_PHONE_NUMBER; // Your Twilio phone number

console.log('check target mobile number: ', mobileNumberProvidedByUser);
console.log('check messageToSendFromUser: ', messageToSendFromUser);
console.log('check twilioNumber: ', twilioNumber);

if (!twilioNumber) {
console.error('Twilio phone number is missing');

_callback({
text: `Sorry there was an issue send sms, please try again later`,
});
return false;
}

const recentMessages = `Extract the phone number from the user recent messages ${_state.recentMessages}`;

if (!mobileNumberProvidedByUser) {
console.error('Mobile number is missing will try to get the phone number or mobile number from recent messages');

mobileNumberProvidedByUser = await generateText(
{
runtime: _runtime,
context: recentMessages,
modelClass: ModelClass.SMALL,
stop: ["\n"],
customSystemPrompt: "only extract the message that the user intend to send and only get the last one"
}
);
}

if (!mobileNumberProvidedByUser) {
console.error('Mobile number is missing');

_callback({
text: `Sorry, there was an issue send sms, please try again later`,
});
return false;
}

const recentUserMessages = `Extract the message intended for SMS or text: ${_state.recentMessages}`;

if (!messageToSendFromUser) {
console.error('messageToSendFromUser is missing will try to get the user message from recent messages');

messageToSendFromUser = await generateText(
{
runtime: _runtime,
context: recentUserMessages,
modelClass: ModelClass.SMALL,
stop: ["\n"]
}
);
}

if(messageToSendFromUser==null){
console.error('messageToSendFromUser is empty or null');

_callback({
text: `Sorry there was an issue sending the WhatsApp message, please try again later`,
});
return false;
}

try {
// Initialize Twilio client
const client = twilio(accountSid, authToken);

// Send the SMS
const message= await client.messages.create({
body: messageToSendFromUser, // The message body
to: mobileNumberProvidedByUser, // The recipient's phone number
from: twilioNumber, // Your Twilio phone number
});

console.log("message body: ", message);

const messageFromAgent = `SMS sent successfully to ${mobileNumberProvidedByUser}`;

// Call the callback to notify the user
_callback({
text: messageFromAgent,
});

return true;
} catch (error) {
console.error('Failed to send SMS:', error);
_callback({
text: `Failed to send SMS to ${mobileNumberProvidedByUser}`,
});
return false;
}
},
examples: [
[
{
user: "{{user1}}",
content: { text: "please send my message via sms to target mobile number" },
},
{
user: "{{user2}}",
content: { text: "", action: "SEND_SMS" },
},
],
] as ActionExample[][],
} as Action;
Loading

0 comments on commit 1cb3af7

Please sign in to comment.