Fonoster
🚀 The open-source alternative to Twilio.
Install / Use
/learn @fonoster/FonosterREADME
Fonoster: The open-source alternative to Twilio
Fonoster is researching an innovative Programmable Telecommunications Stack that will allow businesses to connect telephony services with the Internet entirely through a cloud-based utility.
<a href="https://discord.gg/mpWSRUhG7e"><img alt="Fonoster community banner" src="https://raw.githubusercontent.com/fonoster/.github/main/profile/community.png"></img></a>
<a href="https://github.com/fonoster/fonoster/blob/main/CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/Code%20of%20Conduct-v1.0-ff69b4.svg?color=%2347b96d" alt="Code Of Conduct"></a>
Features
The most notable features of Fonoster are:
- [x] Multitenancy
- [x] Easy deployment of PBX functionalities
- [x] Programmable Voice Applications
- [x] NodeJS SDK
- [x] Support for Amazon Simple Storage Service (S3)
- [x] Secure API endpoints with Let's Encrypt
- [x] Authentication with OAuth2
- [X] Authentication with JWT
- [x] Role-Based Access Control (RBAC)
- [x] Plugins-based Command-line Tool
- [x] Support for Google Speech APIs
Code Examples
A Voice Application is a server that controls a call's flow. A Voice Application can use any combination of the following verbs:
Answer- Accepts an incoming callHangup- Closes the callPlay: Takes a URL with a media file and streams the sound back to the calling partyPlayDtmf- Takes a DTMF sequence and plays it back to the calling partySay- Takes a text, synthesizes the text into audio, and streams back the resultGather- Waits for DTMF or speech events and returns back the resultSGather- Returns a stream for future DTMF and speech resultsStream- Creates a bidirectional stream to send and receive audio from a callerDial- Passes the call to an Agent or a Number at the PSTNRecord- It records the voice of the calling party and saves the audio on the Storage sub-systemMute- It tells the channel to stop sending media, effectively muting the channelUnmute- It tells the channel to allow media flow
Voice Application Example:
const VoiceServer = require("@fonoster/voice").default;
const {
GatherSource,
VoiceRequest,
VoiceResponse
} = require("@fonoster/voice");
new VoiceServer().listen(async (req: VoiceRequest, voice: VoiceResponse) => {
const { ingressNumber, sessionRef, appRef } = req;
await voice.answer();
await voice.say("Hi there! What's your name?");
const { speech: name } = await voice.gather({
source: GatherSource.SPEECH
});
await voice.say("Nice to meet you " + name + "!");
await voice.say("Please enter your 4 digit pin.");
const { digits } = await voice.gather({
maxDigits: 4,
finishOnKey: "#"
});
await voice.say("Your pin is " + digits);
await voice.hangup();
});
// Your app will live at tcp://127.0.0.1:50061
// and you can easily publish it to the Internet with:
// ngrok tcp 50061
Everything in Fonoster is an API first, and initiating a call is no exception. You can use the SDK to start a call with a few lines of code.
Example of originating a call with the SDK:
const SDK = require("@fonoster/sdk");
async function main(request) {
const apiKey = "your-api-key";
const apiSecret = "your-api-secret"
const accessKeyId = "WO00000000000000000000000000000000";
const client = new SDK.Client({ accessKeyId });
await client.loginWithApiKey(apiKey, apiSecret);
const calls = new SDK.Calls(client);
const response = await calls.createCall(request);
console.log(response); // successful response
}
const request = {
from: "+18287854037",
to: "+17853178070",
appRef: "3e61ecb7-a1b6-4a93-84c3-4f1979165bca",
// Optional metadata to be sent to the Voice Application
metadata: {
name: "John Doe",
message: "Please call me back."
}
};
main(request).catch(console.error);
Getting Started
To get started with Fonoster, use the following resources:
- Deploying Fonoster with Docker
- Guide for Early Access User
- Getting started with Fonoster
- How we created an open-source alternative to Twilio and why it matters
Give a Star! ⭐
Please give it a star if you like this project or plan to use it. Thanks 🙏
Bugs and Feedback
For bugs, questions, and discussions, please use the Github Issues
Contributing
For contributing, please see the following links:
<!-- readme: contributors -start --> <table> <tr> <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> <a href=https://github.com/psanders> <img src=https://avatars.githubusercontent.com/u/539774?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Pedro Sanders/> <br /> <sub style="font-size:14px"><b>Pedro Sanders</b></sub> </a> </td> <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> <a href=https://github.com/efraa> <img src=https://avatars.githubusercontent.com/u/40646537?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Efrain Peralta/> <br /> <sub style="font-size:14px"><b>Efrain Peralta</b></sub> </a> </td> <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> <a href=https://github.com/angelbencosme> <img src=https://avatars.githubusercontent.com/u/6846866?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Angel M. Bencosme/> <br /> <sub style="font-size:14px"><b>Angel M. Bencosme</b></sub> </a> </td> <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> <a href=https://github.com/whernandez> <img src=https://avatars.githubusercontent.com/u/37089069?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Wandy Hernandez/> <br /> <sub style="font-size:14px"><b>Wandy Hernandez</b></sub> </a> </td> <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> <a href=https://github.com/obrucheoghene> <img src=https://avatars.githubusercontent.com/u/111436934?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Obruche Wilfred Oghenechohwo/> <br /> <sub style="font-size:14px"><b>Obruche Wilfred Oghenechohwo</b></sub> </a> </td> <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> <a href=https://github.com/wardner> <img src=https://avatars.githubusercontent.com/u/51765669?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Wardner Lara/> <br /> <sub style="font-size:14px"><b>Wardner Lara</b></sub> </a> </td> </tr> <tr> <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> <a href=https://github.com/rihernandez> <img src=https://avatars.githubusercontent.com/u/27718122?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Richard HC/> <br /> <sub style="font-size:14px"><b>Richard HC</b></sub> </a> </td> <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> <a href=https://github.com/Nageswari-droid> <img src=https://avatars.githubusercontent.com/u/65342122?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Nageswari/> <br /> <sub style="font-size:14px"><b>Nageswari</b></sub> </a> </td> <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> <a href=https://github.com/xquanluu> <img src=https://avatars.githubusercontent.com/u/110280845?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Hoan Luu Huu/> <br /> <sub style="font-size:14px"><b>Hoan Luu Huu</b></sub> </a> </td> <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> <a href=https://github.com/speedymonster> <img src=https://avatars.githubusercontent.com/u/31810381?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Speedy Monster/> <br /> <sub style="font-size:14px"><b>Speedy Monster</b></sub> </a> </td> <td align="center" sty