15 |
16 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/React/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Vite/main.js:
--------------------------------------------------------------------------------
1 | import "@signalwire/app-kit";
2 | document.body.onload = addElement;
3 |
4 | function addElement() {
5 | const roomSession = document.createElement("sw-video-conference");
6 | roomSession.setAttribute("token", "vpt_25e...8dd");
7 | roomSession.setAttribute("user-name", "Joe");
8 | roomSession.setAttribute("device-picker", "false");
9 | roomSession.setupRoomSession = (rs) => {
10 | console.log("Setting up Room Session", rs);
11 |
12 | rs.on("room.joined", (e) =>
13 | console.log("Joined room:", e.room.display_name)
14 | );
15 | };
16 | document.getElementById("app").append(roomSession);
17 | }
18 |
--------------------------------------------------------------------------------
/Voice/Implement Coaching and Recording with NodeJS/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import { Route } from 'react-router';
4 | import { Layout } from './components/Layout';
5 | import { Dashboard } from './components/Dashboard';
6 |
7 | import './custom.css'
8 |
9 | export default class App extends Component {
10 | static displayName = App.name;
11 |
12 | render() {
13 | return (
14 |
15 |
16 |
17 |
18 |
19 | );
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Vue 3/src/assets/main.css:
--------------------------------------------------------------------------------
1 | @import "./base.css";
2 |
3 | #app {
4 | max-width: 1280px;
5 | margin: 0 auto;
6 | padding: 2rem;
7 |
8 | font-weight: normal;
9 | }
10 |
11 | a,
12 | .green {
13 | text-decoration: none;
14 | color: hsla(160, 100%, 37%, 1);
15 | transition: 0.4s;
16 | }
17 |
18 | @media (hover: hover) {
19 | a:hover {
20 | background-color: hsla(160, 100%, 37%, 0.2);
21 | }
22 | }
23 |
24 | @media (min-width: 1024px) {
25 | body {
26 | display: flex;
27 | place-items: center;
28 | }
29 |
30 | #app {
31 | display: grid;
32 | grid-template-columns: 1fr 2fr;
33 | padding: 0 2rem;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/.browserslistrc:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # For the full list of supported browsers by the Angular framework, please see:
6 | # https://angular.io/guide/browser-support
7 |
8 | # You can see what browsers were selected by your queries by running:
9 | # npx browserslist
10 |
11 | last 1 Chrome version
12 | last 1 Firefox version
13 | last 2 Edge major versions
14 | last 2 Safari major versions
15 | last 2 iOS major versions
16 | Firefox ESR
17 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/README.md:
--------------------------------------------------------------------------------
1 | # Using the AppKit with Angular
2 |
3 | This is the integration example of AppKit with Angular. The project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 14.1.3.
4 |
5 | Using the Angular CLI, you can run `ng serve` for a dev server which you can access at `http://localhost:4200/`. The application will automatically reload if you change any of the source files. Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
6 |
7 | For a full guide to this implementation, see the blog [Video Conference AppKit: Vue 3 Integration](https://signalwire.com/blogs/developers/video-conference-appkit-with-angular).
8 |
--------------------------------------------------------------------------------
/Video/Interactive-Live-Streaming/src/components/AudienceCount.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 |
3 | export default function AudienceCount({ roomSession }) {
4 | const [count, setCount] = useState(0);
5 |
6 | useEffect(() => {
7 | if (!roomSession) return;
8 |
9 | const onAudienceCount = (e) => {
10 | setCount(e.total);
11 | };
12 | roomSession.on("room.audience_count", onAudienceCount);
13 |
14 | return () => {
15 | roomSession.off("room.audience_count", onAudienceCount);
16 | };
17 | }, [roomSession]);
18 |
19 | return (
20 |
21 | Audience count: {count}
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/Fax/Retry Failed Faxes with Express-NodeJS/example.env:
--------------------------------------------------------------------------------
1 | # This is the full name of your SignalWire Space. e.g.: example.signalwire.com
2 | SIGNALWIRE_SPACE_URL=
3 |
4 | # Your Project ID - you can find it on the `API` page in your Dashboard.
5 | SIGNALWIRE_PROJECT_ID=
6 |
7 | # Your API token - you can generate one on the `API` page in your Dashboard
8 | SIGNALWIRE_API_TOKEN=
9 |
10 | # The phone number you'll be using for this Snippet. Must include the `+1` ex. `+11231231234`
11 | SIGNALWIRE_FROMNUMBER=+1<10dlc number>
12 | SIGNALWIRE_TONUMBER=+1<10dlc number>
13 |
14 | # If you have an Ngrok account you can include your auth token here.
15 | NGROKTOKEN=
16 |
17 | #If hosting this app, enter the host domain here and remove the ngrok tunnel
18 | DOMAIN=
--------------------------------------------------------------------------------
/Messaging/Sending SMS from the Browser - NodeJS/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SMS with SignalWire RealTime API
5 |
6 |
7 |
8 |
9 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Messaging/Sending SMS from the Browser - NodeJS Relay v4/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SMS with SignalWire RealTime API
5 |
6 |
7 |
8 |
9 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Vue 3/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-project",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "dev": "vite",
6 | "build": "run-p type-check build-only",
7 | "preview": "vite preview --port 4173",
8 | "build-only": "vite build",
9 | "type-check": "vue-tsc --noEmit"
10 | },
11 | "dependencies": {
12 | "@signalwire/app-kit": "^0.0.1-dev.202208231654.564d9a2.4",
13 | "vue": "^3.2.37"
14 | },
15 | "devDependencies": {
16 | "@types/node": "^16.11.47",
17 | "@vitejs/plugin-vue": "^3.0.1",
18 | "@vitejs/plugin-vue-jsx": "^2.0.0",
19 | "@vue/tsconfig": "^0.1.3",
20 | "npm-run-all": "^4.1.5",
21 | "typescript": "~4.7.4",
22 | "vite": "^3.0.4",
23 | "vue-tsc": "^0.39.5"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/React/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # Compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 | /bazel-out
8 |
9 | # Node
10 | /node_modules
11 | npm-debug.log
12 | yarn-error.log
13 |
14 | # IDEs and editors
15 | .idea/
16 | .project
17 | .classpath
18 | .c9/
19 | *.launch
20 | .settings/
21 | *.sublime-workspace
22 |
23 | # Visual Studio Code
24 | .vscode/*
25 | !.vscode/settings.json
26 | !.vscode/tasks.json
27 | !.vscode/launch.json
28 | !.vscode/extensions.json
29 | .history/*
30 |
31 | # Miscellaneous
32 | /.angular/cache
33 | .sass-cache/
34 | /connect.lock
35 | /coverage
36 | /libpeerconnection.log
37 | testem.log
38 | /typings
39 |
40 | # System files
41 | .DS_Store
42 | Thumbs.db
43 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
30 |
31 |
35 |
--------------------------------------------------------------------------------
/Video/Room Preview Demo/embed.js:
--------------------------------------------------------------------------------
1 | !function(e,r){e.swvr=e.swvr||function(r={}){
2 | Object.assign(e.swvr.p=e.swvr.p||{},r)}
3 | ;let t=r.currentScript,n=r.createElement("script")
4 | ;n.type="module",n.src="https://cdn.swire.io/video/rooms/index.js",
5 | n.onload=function(){let n=r.createElement("ready-room")
6 | ;n.params=e.swvr.p,t.parentNode.appendChild(n)},t.parentNode.insertBefore(n,t)
7 | ;let i=r.createElement("link")
8 | ;i.type="text/css",i.rel="stylesheet",i.href="https://cdn.swire.io/video/rooms/signalwire.css",
9 | t.parentNode.insertBefore(i,t),
10 | e.SignalWire=e.SignalWire||{},e.SignalWire.Prebuilt={VideoRoom:e.swvr}
11 | }(window,document);
12 |
13 | SignalWire.Prebuilt.VideoRoom({
14 | token: 'vpt_43a7bb37f75dbbd411821d472b9b8b90',
15 | // userName: 'your-name'
16 | });
17 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
2 | import '@signalwire/app-kit';
3 |
4 | @Component({
5 | selector: 'app-root',
6 | templateUrl: './app.component.html',
7 | styleUrls: ['./app.component.css'],
8 | })
9 | export class AppComponent implements OnInit {
10 | @ViewChild('videoComponent', { static: true }) videoComponent: ElementRef;
11 | title = 'angular-project';
12 | ngOnInit(): void {
13 | this.videoComponent.nativeElement.setupRoomSession = (rs) => {
14 | console.log('Setting up Room Session');
15 |
16 | rs.on('room.joined', (e) => {
17 | console.log('Joined room:', e.room_session.name);
18 | rs.videoMute();
19 | });
20 | };
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Messaging/Forward Messages - NodeJS/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forward-messages---nodejs",
3 | "version": "1.0.0",
4 | "description": "This super simple guide will show how you can handle incoming messages and forward them to another phone number. We will use the [SignalWire Javascript SDK](https://developer.signalwire.com/client-sdk/reference/js-exports) to handle the incoming message and [RELAY Realtime API]() to forward the message.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node index.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@signalwire/realtime-api": "^3.3.1",
14 | "body-parser": "^1.20.0",
15 | "dotenv": "^16.0.1",
16 | "express": "^4.18.1"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Video/Interactive-Live-Streaming/src/App.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import "./App.css";
3 | import { createBrowserRouter, RouterProvider } from "react-router-dom";
4 | import { ThemeProvider, createTheme } from "@mui/material/styles";
5 | import Prejoin from "./Prejoin";
6 | import InCall from "./InCall";
7 |
8 | const darkTheme = createTheme({
9 | palette: {
10 | mode: "dark",
11 | },
12 | });
13 |
14 | export default function App() {
15 | const router = createBrowserRouter([
16 | {
17 | path: "/",
18 | element: ,
19 | },
20 | {
21 | path: "in-call",
22 | element: ,
23 | },
24 | ]);
25 |
26 | return (
27 |
28 |
29 |
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/Video/Room Preview Demo/README.md:
--------------------------------------------------------------------------------
1 | # Demo for [Room Previews using Programmable Video Rooms](https://developer.signalwire.com/apis/docs/get-thumbnails-for-your-video-calls)
2 |
3 | This minimal demo uses Programmable Video Rooms and SignalWire Video REST APIs to fetch and preview room previews.
4 |
5 | To run this demo locally, make necessary adjustments ot the env.example file and rename it to `.env`. You can get the `PROJECT_ID` and `API_TOKEN` from your SignalWire Dashboard.
6 |
7 | Once you have made the adjustments, install the dependencies using `yarn install` and then start it via `yarn dev`.
8 |
9 | This sample code is explained in detail in the guide 📖 [Get Thumbnails for your Video Calls](https://developer.signalwire.com/apis/docs/get-thumbnails-for-your-video-calls)
10 | at SignalWire Developer Portal.
11 |
--------------------------------------------------------------------------------
/Video/Embed Video Rooms - Videoconferencing Widget/README.md:
--------------------------------------------------------------------------------
1 | # Embed Video Rooms: Videoconferencing Widget
2 |
3 | 📖 [Read the full guide](https://developer.signalwire.com/guides/video/creating-a-video-room)
4 |
5 | The SignalWire Video APIs give you full flexibility to build your own personalized video conferencing experience. But if you just need a basic video-conference widget, you can get started by copy-pasting a **Video Room Widget** from your SignalWire space. Video Rooms can be embedded in your CMS like **WordPress**, **Drupal**, or any other kind of **static HTML page**, simply by **copy-pasting** a snippet of HTML code.
6 |
7 | # Running the code
8 |
9 | Simply open [index.html](index.html) in your browser. We have configured a room with a demo account. **Make sure to replace the code snippet with your own!**
10 |
--------------------------------------------------------------------------------
/Voice/Make Appointment Reminder Calls with Ruby/views/layout.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | SignalWire Reminders
4 |
5 |
6 |
7 |
12 |
13 | <%= yield %>
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Voice/AI Agent with NodeJS/env.example:
--------------------------------------------------------------------------------
1 | # Project ID copied from the API Credentials in your SignalWire Space
2 | # Example: 7b98XXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
3 | PROJECT_ID=
4 |
5 | # API token copied from the API Credentials in your SignalWire Space
6 | # Example: PTda745XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 | API_TOKEN=
8 |
9 | # Your SignalWire Space URL copied from the API Credentials in your SignalWire Space
10 | # Example: spacename.signalwire.com
11 | SPACE_URL=
12 |
13 | # The URL of your deployed application, including the protocol extension
14 | # Example: https://example.ngrok.app
15 | HOST_APP=
16 |
17 | # 10-digit phone number for a sales department in the following format:
18 | # Example: 222-555-0110
19 | SALES_NUMBER=
20 |
21 | # 10-digit phone number for a support department in the following format:
22 | # Example: 222-555-0110
23 | SUPPORT_NUMBER=
--------------------------------------------------------------------------------
/Messaging/Text Subscription with Python/example.env:
--------------------------------------------------------------------------------
1 | # This is the full name of your SignalWire Space. e.g.: example.signalwire.com
2 | SIGNALWIRE_SPACE=
3 | # Your Project ID - you can find it on the `API` page in your Dashboard.
4 | SIGNALWIRE_PROJECT=
5 | # Your API token - you can generate one on the `API` page in your Dashboard
6 | SIGNALWIRE_TOKEN=
7 | # The phone number you'll be using for this Snippets. Must include the `+1` , e.g.: +15551234567
8 | SIGNALWIRE_NUMBER=
9 | # MailGun domain associated with your MailGun account
10 | MAILGUN_DOMAIN=
11 | # MailGun token associated with your MailGun Account
12 | MAILGUN_API_TOKEN=
13 | # Send Email From Address
14 | EMAIL_FROM=info@yourdomain.com
15 | # Send email to address for administrator notifications
16 | EMAIL_TO=youremail@yourdomain.com
17 | # Email subject for admin notifications
18 | EMAIL_SUBJECT=SMS TO EMAIL
19 |
--------------------------------------------------------------------------------
/Video/Interactive-Live-Streaming/src/App.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: rgb(37,37,37);
3 | color: rgb(204,204,204);
4 | }
5 |
6 | .App {
7 | text-align: center;
8 | }
9 |
10 | .App-logo {
11 | height: 40vmin;
12 | pointer-events: none;
13 | }
14 |
15 | @media (prefers-reduced-motion: no-preference) {
16 | .App-logo {
17 | animation: App-logo-spin infinite 20s linear;
18 | }
19 | }
20 |
21 | .App-header {
22 | background-color: #282c34;
23 | min-height: 100vh;
24 | display: flex;
25 | flex-direction: column;
26 | align-items: center;
27 | justify-content: center;
28 | font-size: calc(10px + 2vmin);
29 | color: white;
30 | }
31 |
32 | .App-link {
33 | color: #61dafb;
34 | }
35 |
36 | @keyframes App-logo-spin {
37 | from {
38 | transform: rotate(0deg);
39 | }
40 | to {
41 | transform: rotate(360deg);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/React/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { useLayoutEffect, useRef } from "react";
2 | import "./App.css";
3 | import "@signalwire/app-kit";
4 |
5 | function App() {
6 | const videoComponent = useRef();
7 |
8 | useLayoutEffect(() => {
9 | if (videoComponent.current) {
10 | videoComponent.current.setupRoomSession = (rs) => {
11 | console.log("Setting up Room Session");
12 |
13 | rs.on("room.joined", (e) =>
14 | console.log("Joined room:", e.room_session.name)
15 | );
16 | };
17 | }
18 | }, []);
19 |
20 | return (
21 |
22 |
28 |
29 | );
30 | }
31 |
32 | export default App;
33 |
--------------------------------------------------------------------------------
/Voice/Implement Coaching and Recording with NodeJS/example.env:
--------------------------------------------------------------------------------
1 | ## This is the full name of your SignalWire Space. e.g.: example.signalwire.com
2 | SIGNALWIRE_SPACE=
3 | # Your Project ID - you can find it on the `API` page in your Dashboard.
4 | SIGNALWIRE_PROJECT=
5 | # Your API token - you can generate one on the `API` page in your Dashboard
6 | SIGNALWIRE_TOKEN=
7 | # The name of your example conference
8 | CONFERENCE_NAME=
9 | # The inbound phone number you'll be using for this Snippets. Must include the `+1` , e$
10 | INBOUND_NUMBER=
11 | # The agent phone number you'll be using for this Snippets. Must include the `+1` , e$
12 | AGENT_NUMBER=
13 | # The supervisor phone number you'll be using for this Snippets. Must include the `+1` , e$
14 | SUPERVISOR_NUMBER=
15 | # Hostname, the ip address or Fully Qualified Domain Name of your host and port, for routing action urls
16 | HOSTNAME=
17 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: {
11 | context(path: string, deep?: boolean, filter?: RegExp): {
12 | (id: string): T;
13 | keys(): string[];
14 | };
15 | };
16 |
17 | // First, initialize the Angular testing environment.
18 | getTestBed().initTestEnvironment(
19 | BrowserDynamicTestingModule,
20 | platformBrowserDynamicTesting(),
21 | );
22 |
23 | // Then we find all the tests.
24 | const context = require.context('./', true, /\.spec\.ts$/);
25 | // And load the modules.
26 | context.keys().forEach(context);
27 |
--------------------------------------------------------------------------------
/Video/React-Native-Basic/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "start": "expo start --dev-client",
4 | "android": "expo run:android",
5 | "ios": "expo run:ios",
6 | "web": "expo start --web"
7 | },
8 | "dependencies": {
9 | "@signalwire-community/react-native": "^0.1.0",
10 | "@signalwire/js": "^3.13.1",
11 | "expo": "^45.0.0",
12 | "expo-dev-client": "~0.9.5",
13 | "expo-splash-screen": "~0.15.1",
14 | "expo-status-bar": "~1.3.0",
15 | "react": "17.0.2",
16 | "react-dom": "17.0.2",
17 | "react-native": "0.68.2",
18 | "react-native-get-random-values": "^1.8.0",
19 | "react-native-web": "0.17.7",
20 | "react-native-webrtc": "^1.94.1"
21 | },
22 | "devDependencies": {
23 | "@babel/core": "^7.12.9",
24 | "@config-plugins/react-native-webrtc": "^2.0.1"
25 | },
26 | "name": "basic_tutorial",
27 | "version": "1.0.0",
28 | "private": true
29 | }
30 |
--------------------------------------------------------------------------------
/Voice/Screen Calls Based on Block List with Python/app.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, request
2 | from signalwire.voice_response import VoiceResponse
3 | import os
4 |
5 | app = Flask(__name__)
6 |
7 |
8 | def get_blocklist():
9 | # there is a default here you can change if you don't want to use the environment variable
10 | return os.getenv('BLOCKLIST', '+1555778899').split(',')
11 |
12 |
13 | @app.route('/check', methods=['POST'])
14 | def check_number():
15 | response = VoiceResponse()
16 | from_number = request.form.get('From')
17 |
18 | if from_number not in get_blocklist():
19 | response.redirect(os.environ.get('REDIRECT_PATH',
20 | 'https://example.signalwire.com/laml-bins/55ab7685-e9c3-4449-b1f0-07ff083d041e'))
21 |
22 | else:
23 | response.hangup()
24 |
25 | return response.to_xml()
26 |
27 |
28 | if __name__ == "__main__":
29 | app.run()
--------------------------------------------------------------------------------
/Messaging/Sending SMS from the Browser - NodeJS/README.md:
--------------------------------------------------------------------------------
1 | # Send SMS from the browser with SignalWire APIs - Node JS
2 |
3 | A demo application that demonstrates how to send an SMS message using the SignalWire Messaging API.
4 |
5 | 📖 [Read the full guide](https://developer.signalwire.com/apis/docs/send-sms-from-the-browser-using-node-js?relay_version=relayv3)
6 |
7 | ## Setup
8 |
9 | 1. Use `yarn install` to install the dependencies.
10 | 2. Buy a new phone number from your SignalWire Dashboard. ([Guide](https://developer.signalwire.com/apis/docs/buying-a-phone-number))
11 | 3. Note the Project ID and API key from your SignalWire Dashboard. ([Guide](https://developer.signalwire.com/apis/docs/getting-started-with-the-signalwire-video-api-1#obtaining-your-api-key-and-project-id))
12 | 4. Rename the `env.sample` file as `.env` and fill in the Phone Number, Project ID and API key.
13 | 5. Run `yarn start` to start the demo application.
14 |
--------------------------------------------------------------------------------
/Messaging/Sending SMS from the Browser - NodeJS Relay v4/README.md:
--------------------------------------------------------------------------------
1 | # Send SMS from the browser with SignalWire APIs - Node JS
2 |
3 | A demo application that demonstrates how to send an SMS message using the SignalWire Messaging API.
4 |
5 | 📖 [Read the full guide](https://developer.signalwire.com/apis/docs/send-sms-from-the-browser-using-node-js?relay_version=relayv4)
6 |
7 | ## Setup
8 |
9 | 1. Use `yarn install` to install the dependencies.
10 | 2. Buy a new phone number from your SignalWire Dashboard. ([Guide](https://developer.signalwire.com/apis/docs/buying-a-phone-number))
11 | 3. Note the Project ID and API key from your SignalWire Dashboard. ([Guide](https://developer.signalwire.com/apis/docs/getting-started-with-the-signalwire-video-api-1#obtaining-your-api-key-and-project-id))
12 | 4. Rename the `env.sample` file as `.env` and fill in the Phone Number, Project ID and API key.
13 | 5. Run `yarn start` to start the demo application.
14 |
--------------------------------------------------------------------------------
/Voice/Answering Machine Detection with NodeJS/env.example:
--------------------------------------------------------------------------------
1 | # Project ID copied from the API Credentials in your SignalWire Space.
2 | # Example: 7b98XXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
3 | PROJECT_ID=
4 |
5 | # API token copied from the API Credentials in your SignalWire Space.
6 | # Example: PTda745XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 | API_TOKEN=
8 |
9 | # Your SignalWire Space URL copied from the API Credentials in your SignalWire Space.
10 | # Example: spacename.signalwire.com
11 | SPACE_URL=
12 |
13 | # The URL you would like to receive the AMD result.
14 | # Example: https://example.ngrok.app
15 | SERVER_URL=
16 |
17 | # A phone number from your SignalWire account for caller ID in E.164 format.
18 | # Example: +1XXXXXXXXXXX
19 | SW_NUMBER=
20 |
21 | # The test phone number to dial in E.164 format.
22 | # Example: +1XXXXXXXXXXX
23 | CUSTOMER_NUMBER=
24 |
25 | # A live agent's phone number in E.164 format.
26 | # Example: +1XXXXXXXXXXX
27 | AGENT_NUMBER=
--------------------------------------------------------------------------------
/Integrations/SignalWire API on Azure Function - NodeJS/SendVoice/index.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config()
2 | const {RestClient} = require('@signalwire/compatibility-api')
3 |
4 | const username = process.env.PROJECT_ID
5 | const token = process.env.API_TOKEN
6 | const spaceURL = process.env.SPACE_URL
7 |
8 | const client = RestClient(username, token, {signalwireSpaceUrl: spaceURL})
9 |
10 | module.exports = async function (context, req) {
11 |
12 | context.log('JavaScript HTTP trigger function processed a request.');
13 |
14 | const {receiver, sender, callUrl} = req.body
15 |
16 | let responseBody = {}
17 |
18 | await client.calls.create({to: receiver, from: sender, url: callUrl}).then(response => {
19 | responseBody = response
20 | }, error => {
21 | responseBody = error.message
22 | })
23 |
24 | context.res = {
25 | // status: 200, /* Defaults to 200 */
26 | body: responseBody
27 | };
28 | }
--------------------------------------------------------------------------------
/Messaging/Two Factor Authentication via SMS - NodeJS/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "two-factor-authentication-via-sms---node",
3 | "version": "1.0.0",
4 | "description": "Two Factor Authentication (2FA) can provide your users effective protection against many security threats that target user passwords and accounts. This application will generate a one-time password that is sent to the recipient's phone number via SMS. Application developers can enable two-factor authentication for their users with ease and without making any changes to the already existing application logic or database structure!",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node index.js",
9 | "dev": "nodemon index.js"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@signalwire/realtime-api": "^3.0.2",
15 | "dotenv": "^16.0.1",
16 | "express": "^4.18.1",
17 | "phone": "^3.1.22"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Video/RTMP-Streaming/index.css:
--------------------------------------------------------------------------------
1 | #logo {
2 | max-width: 200px;
3 | }
4 |
5 | #pvc {
6 | margin: 0 auto;
7 | width: 800px;
8 | height: 500px;
9 | display: flex;
10 | flex-direction: column-reverse;
11 | justify-content: flex-end;
12 | }
13 |
14 | #id {
15 | margin: 0 auto;
16 | }
17 |
18 | #note {
19 | color: #8e9292;
20 | }
21 |
22 | h1,
23 | #button-bar {
24 | margin: 5px auto;
25 | font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial,
26 | sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
27 | }
28 |
29 | #button-bar {
30 | display: none;
31 | }
32 |
33 | #streaming {
34 | display: none;
35 | }
36 |
37 | #stream-url {
38 | width: 400px;
39 | }
40 |
41 | #start,
42 | #stop {
43 | color: white;
44 | font-weight: 500;
45 | border: none;
46 | border-radius: 5px;
47 | padding: 8px;
48 | cursor: pointer;
49 | }
50 |
51 | #start {
52 | background-color: #044ef4;
53 | }
54 | #stop {
55 | display: none;
56 | background-color: rgb(211, 96, 96);
57 | }
58 |
--------------------------------------------------------------------------------
/Video/React-Native-Basic/README.md:
--------------------------------------------------------------------------------
1 | # Basic React Native Video Example using Community Components
2 |
3 | This example uses the components from [@signalwire-community/react](https://github.com/signalwire-community/react/) package to demonstrate a few simple features of the SignalWire Video SDK.
4 |
5 | 📖 [Read the full guide](https://developer.signalwire.com/guides/video-api/guides/using-video-api-react-native/)
6 |
7 | ## Usage
8 |
9 | To run the app, you need to have the Android development environment set up. You can find instructions on how to set up the environment [here](https://reactnative.dev/docs/environment-setup). Folow the "React Native CLI Quickstart" instructions.
10 |
11 | In the root of the project directory, run `yarn install` to install the dependencies, then `yarn android` to install and run the app.
12 |
13 | You will need to add a token to the TOKEN constant in `./App.js`. Follow the [guide](https://developer.signalwire.com/guides/video-api/guides/using-video-api-react-native/) for more details.
14 |
--------------------------------------------------------------------------------
/Video/Room Preview Demo/static/embed.js:
--------------------------------------------------------------------------------
1 | !(function (e, r) {
2 | e.swvr =
3 | e.swvr ||
4 | function (r = {}) {
5 | Object.assign((e.swvr.p = e.swvr.p || {}), r);
6 | };
7 | let t = r.currentScript,
8 | n = r.createElement("script");
9 | (n.type = "module"),
10 | (n.src = "https://cdn.signalwire.com/video/rooms/index.js"),
11 | (n.onload = function () {
12 | let n = r.createElement("ready-room");
13 | (n.params = e.swvr.p), t.parentNode.appendChild(n);
14 | }),
15 | t.parentNode.insertBefore(n, t);
16 | let i = r.createElement("link");
17 | (i.type = "text/css"),
18 | (i.rel = "stylesheet"),
19 | (i.href = "https://cdn.signalwire.com/video/rooms/signalwire.css"),
20 | t.parentNode.insertBefore(i, t),
21 | (e.SignalWire = e.SignalWire || {}),
22 | (e.SignalWire.Prebuilt = { VideoRoom: e.swvr });
23 | })(window, document);
24 |
25 | SignalWire.Prebuilt.VideoRoom({
26 | token: "vpt_cc56fea7323b3016b9b2db95e104fb38",
27 | // userName: 'your-name'
28 | });
29 |
--------------------------------------------------------------------------------
/Messaging/Two Factor Authentication via SMS - NodeJS Relay v4/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "two-factor-authentication-via-sms---node",
3 | "version": "1.0.0",
4 | "description": "Two Factor Authentication (2FA) can provide your users effective protection against many security threats that target user passwords and accounts. This application will generate a one-time password that is sent to the recipient's phone number via SMS. Application developers can enable two-factor authentication for their users with ease and without making any changes to the already existing application logic or database structure!",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "start": "node index.js",
10 | "dev": "nodemon index.js"
11 | },
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "@signalwire/realtime-api": "^4.0.0",
16 | "dotenv": "^16.0.1",
17 | "express": "^4.18.1",
18 | "phone": "^3.1.22"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Video/Interactive-Live-Streaming/src/components/MicrophoneButton.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import SplitButton from "./SplitButton";
3 | import MicOffIcon from "@mui/icons-material/MicOff";
4 | import MicIcon from "@mui/icons-material/Mic";
5 | import { useMembers, useWebRTC } from "@signalwire-community/react";
6 |
7 | export default function MicrophoneButton({ roomSession }) {
8 | const { microphones } = useWebRTC({
9 | camera: false,
10 | microphone: true,
11 | speaker: false,
12 | });
13 |
14 | const { members } = useMembers(roomSession);
15 |
16 | const self = members.find((m) => m.id === roomSession?.memberId);
17 |
18 | return (
19 | }
22 | unmutedIcon={}
23 | devices={microphones}
24 | onSetMuted={(muted) =>
25 | muted ? roomSession.audioMute() : roomSession.audioUnmute()
26 | }
27 | onDevicePicked={(deviceId) => roomSession.updateMicrophone({ deviceId })}
28 | />
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/Video/Interactive-Live-Streaming/src/components/CameraButton.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import SplitButton from "./SplitButton";
3 | import VideocamOffIcon from "@mui/icons-material/VideocamOff";
4 | import VideocamIcon from "@mui/icons-material/Videocam";
5 | import { useMembers, useWebRTC } from "@signalwire-community/react";
6 |
7 | export default function CameraButton({ roomSession }) {
8 | const { cameras } = useWebRTC({
9 | camera: true,
10 | microphone: false,
11 | speaker: false,
12 | });
13 |
14 | const { members } = useMembers(roomSession);
15 |
16 | const self = members.find((m) => m.id === roomSession?.memberId);
17 |
18 | return (
19 | }
22 | unmutedIcon={}
23 | devices={cameras}
24 | onSetMuted={(muted) =>
25 | muted ? roomSession.videoMute() : roomSession.videoUnmute()
26 | }
27 | onDevicePicked={(deviceId) => roomSession.updateCamera({ deviceId })}
28 | />
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/Fax/Forwarding Incoming Faxes to Email with Python/app.py:
--------------------------------------------------------------------------------
1 | import os
2 | import requests
3 | import pprint
4 |
5 | from flask import Flask, request
6 |
7 | app = Flask(__name__)
8 |
9 |
10 | # Listen on route '/fax-webhook' for incoming GET/POST requests when a fax comes in
11 | @app.route('/fax-webhook', methods=['POST'])
12 | def fax_webhook():
13 | # Forward incoming form data to email
14 | send_email(pprint.pformat(request.form, indent=4))
15 | return "200"
16 |
17 |
18 | # Send email using MailGun API
19 | def send_email(body):
20 | return requests.post(
21 | "https://api.mailgun.net/v3/" + os.environ['MAILGUN_DOMAIN'] + "/messages",
22 | auth=("api", os.environ['MAILGUN_API_TOKEN']),
23 | data={"from": os.environ['EMAIL_FROM'],
24 | "to": [os.environ['EMAIL_TO']],
25 | "subject": os.environ['EMAIL_SUBJECT'],
26 | "text": body})
27 |
28 |
29 | # Listen on '/' for default requests
30 | @app.route('/')
31 | def hello():
32 | return "Hello World!"
33 |
34 |
35 | if __name__ == '__main__':
36 | app.run()
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "strict": false,
9 | "noImplicitOverride": true,
10 | "noPropertyAccessFromIndexSignature": true,
11 | "noImplicitReturns": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "sourceMap": true,
14 | "declaration": false,
15 | "downlevelIteration": true,
16 | "experimentalDecorators": true,
17 | "moduleResolution": "node",
18 | "importHelpers": true,
19 | "target": "es2020",
20 | "module": "es2020",
21 | "lib": [
22 | "es2020",
23 | "dom"
24 | ],
25 | "allowSyntheticDefaultImports": true
26 | },
27 | "angularCompilerOptions": {
28 | "enableI18nLegacyMessageIdFormat": false,
29 | "strictInjectionParameters": true,
30 | "strictInputAccessModifiers": true,
31 | "strictTemplates": true
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/React/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cra",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@signalwire/app-kit": "^0.0.1-next.6",
7 | "@testing-library/jest-dom": "^5.16.5",
8 | "@testing-library/react": "^13.3.0",
9 | "@testing-library/user-event": "^13.5.0",
10 | "axios": "^0.27.2",
11 | "react": "^18.2.0",
12 | "react-dom": "^18.2.0",
13 | "react-scripts": "5.0.1",
14 | "web-vitals": "^2.1.4"
15 | },
16 | "scripts": {
17 | "start": "react-scripts start",
18 | "build": "react-scripts build",
19 | "test": "react-scripts test",
20 | "eject": "react-scripts eject"
21 | },
22 | "eslintConfig": {
23 | "extends": [
24 | "react-app",
25 | "react-app/jest"
26 | ]
27 | },
28 | "browserslist": {
29 | "production": [
30 | ">0.2%",
31 | "not dead",
32 | "not op_mini all"
33 | ],
34 | "development": [
35 | "last 1 chrome version",
36 | "last 1 firefox version",
37 | "last 1 safari version"
38 | ]
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Voice/Implement two-factor with Python/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2020 SIGNALWIRE, INC
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/Messaging/Two Factor Authentication via SMS - Python/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2020 SIGNALWIRE, INC
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/Messaging/Two Factor Authentication via SMS - NodeJS/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Two Factor Auth via SMS with SignalWire RealTime API
6 |
7 |
8 |
9 |
10 |
11 |
17 |
18 |
19 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Messaging/Two Factor Authentication via SMS - NodeJS Relay v4/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Two Factor Auth via SMS with SignalWire RealTime API
6 |
7 |
8 |
9 |
10 |
11 |
17 |
18 |
19 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 SignalWire
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Video/README.md:
--------------------------------------------------------------------------------
1 | # Video Guides
2 |
3 | [Embed Video Rooms - Videoconferencing Widget](./Embed%20Video%20Rooms%20-%20Videoconferencing%20Widget)
4 | Embed a videoconferencing widget in your website without any software development experience.
5 |
6 | [Create a Simple Video Demo](./Simple%20Video%20Demo)
7 | Develop a simple full-stack video demo with this step-by-step walk-through.
8 |
9 | [Room Previews using Programmable Video Communication](./Room%20Preview%20Demo)
10 | A very simple demonstration of getting and refreshing Room Previews.
11 |
12 | [Layout Positions](./Layout-Positions)
13 | This guide shows how to control positions and layouts in a video room.
14 |
15 | [RTMP Streaming](./RTMP-Streaming)
16 | A simple example of RTMP streaming from a PVC to the RTMP URL of your choice.
17 |
18 | [React Native Basic Component](./React-Native-Basic)
19 | Use components from SignalWire Community to create a simple video calling app with React Native.
20 |
21 | [AppKit Framework Examples](./AppKit-Framework-Examples/)
22 | Examples of AppKit, the library behind Programmable Video Conferences, integrated with popular front-end frameworks.
23 |
--------------------------------------------------------------------------------
/Video/Room Preview Demo/index.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config();
2 | const express = require("express");
3 | const app = express();
4 | const port = process.env.PORT ?? 3000;
5 | const axios = require("axios");
6 |
7 | const { PROJECT_ID, API_TOKEN, SPACE_URL } = process.env;
8 | const auth = { username: PROJECT_ID, password: API_TOKEN };
9 |
10 | app.get("/thumbURL", async (req, res) => {
11 | console.log(
12 | SPACE_URL + "/api/video/room_sessions?page_size=100&status=in-progress"
13 | );
14 | try {
15 | let roomsessions = await axios.get(
16 | "https://" +
17 | SPACE_URL +
18 | "/api/video/room_sessions?page_size=100&status=in-progress",
19 | { auth }
20 | );
21 | console.log(roomsessions.data.data);
22 | let thumbroom = roomsessions.data.data.find(
23 | (x) => x.room_id === "3c1e815c-3b3f-4bc5-a200-107ab367a924"
24 | );
25 | res.json(thumbroom);
26 | } catch (err) {
27 | console.log(err);
28 | res.status(500);
29 | }
30 | });
31 |
32 | app.use("/", express.static("static"));
33 |
34 | app.listen(port, () => {
35 | console.log(`Example app listening on port ${port}`);
36 | });
37 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
3 | "version": "2.0.0",
4 | "tasks": [
5 | {
6 | "type": "npm",
7 | "script": "start",
8 | "isBackground": true,
9 | "problemMatcher": {
10 | "owner": "typescript",
11 | "pattern": "$tsc",
12 | "background": {
13 | "activeOnStart": true,
14 | "beginsPattern": {
15 | "regexp": "(.*?)"
16 | },
17 | "endsPattern": {
18 | "regexp": "bundle generation complete"
19 | }
20 | }
21 | }
22 | },
23 | {
24 | "type": "npm",
25 | "script": "test",
26 | "isBackground": true,
27 | "problemMatcher": {
28 | "owner": "typescript",
29 | "pattern": "$tsc",
30 | "background": {
31 | "activeOnStart": true,
32 | "beginsPattern": {
33 | "regexp": "(.*?)"
34 | },
35 | "endsPattern": {
36 | "regexp": "bundle generation complete"
37 | }
38 | }
39 | }
40 | }
41 | ]
42 | }
43 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 | import { AppComponent } from './app.component';
3 |
4 | describe('AppComponent', () => {
5 | beforeEach(async () => {
6 | await TestBed.configureTestingModule({
7 | declarations: [
8 | AppComponent
9 | ],
10 | }).compileComponents();
11 | });
12 |
13 | it('should create the app', () => {
14 | const fixture = TestBed.createComponent(AppComponent);
15 | const app = fixture.componentInstance;
16 | expect(app).toBeTruthy();
17 | });
18 |
19 | it(`should have as title 'angular-project'`, () => {
20 | const fixture = TestBed.createComponent(AppComponent);
21 | const app = fixture.componentInstance;
22 | expect(app.title).toEqual('angular-project');
23 | });
24 |
25 | it('should render title', () => {
26 | const fixture = TestBed.createComponent(AppComponent);
27 | fixture.detectChanges();
28 | const compiled = fixture.nativeElement as HTMLElement;
29 | expect(compiled.querySelector('.content span')?.textContent).toContain('angular-project app is running!');
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/Voice/Answering Machine Detection with Ruby/app.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'sinatra'
3 | require 'signalwire'
4 |
5 | set :port, 8080
6 | set :bind, '0.0.0.0'
7 |
8 | get '/' do
9 | "It's working!"
10 | end
11 |
12 | post '/start' do
13 | response = Signalwire::Sdk::VoiceResponse.new
14 |
15 | case params[:AnsweredBy]
16 | when 'machine_end_other', 'machine_end_silence', 'machine_end_beep'
17 | puts "It's a machine!"
18 | # put in a little pause to allow the recording to start on the other end
19 | response.pause(length: 1)
20 | # replace messsage with whatever voicemail you want to leave
21 | response.say(message: "Hello! This is the County Medical Center. We are calling you to confirm your doctor appointment. Please call us back as soon as possible.")
22 | response.hangup
23 | when 'human'
24 | puts "We got ourselves a live human here!"
25 | response.dial do |dial|
26 | # defaulting to calling a time voice announcement number as an example
27 | dial.number(ENV.fetch('AGENT_NUMBER', '+12027621401'))
28 | end
29 | end
30 |
31 | # debug the LAML
32 | puts response.to_s
33 | response.to_s
34 | end
35 |
--------------------------------------------------------------------------------
/Voice/Dial By Voice Python/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 SignalWire
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Voice/Lenny Spam Filter Relay v4/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 SignalWire
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Vite/README.md:
--------------------------------------------------------------------------------
1 | # Using the AppKit with Vite.js
2 |
3 | This is the integration example of AppKit with Vite. We used `npm create vite@latest` and selected `Vanilla` and `JavaScript` when prompted. The scaffolding started us with the external file `main.js` where we could insert our `sw-video-conference` component with `innerHTML`.
4 |
5 | ```js
6 | import "./style.css";
7 | import "@signalwire/app-kit";
8 |
9 | document.querySelector("#app")!.innerHTML = `
10 |
16 | `;
17 | ```
18 |
19 | Just these few lines of code are enough to run a fully functional video conference room. To go one step forward and use the `setupRoomSession` callback function available on the `sw-video-conference` component, we used `document.createElement` to create the element, access the callback function, and get the Room Session object before adding it to the HTML.
20 |
21 | For a full guide to this implementation, see the blog [Video Conference AppKit: Vite Integration](https://signalwire.com/blogs/developers/video-conference-appkit-with-vite).
22 |
--------------------------------------------------------------------------------
/Voice/SIP Voicemail with Python/index.py:
--------------------------------------------------------------------------------
1 | from flask import Flask,Response,request
2 | from signalwire.voice_response import VoiceResponse
3 | app = Flask(__name__)
4 |
5 | @app.route("/", methods=["POST"])
6 | def index():
7 | response = VoiceResponse()
8 | response.say("Welcome to SignalWire. Please wait while we connect you to an agent.")
9 | dial = response.dial(timeout=15, action="/voicemail")
10 | dial.sip("sip:alice@example.com")
11 | return Response(str(response), mimetype="text/xml")
12 |
13 | @app.route("/voicemail", methods=["POST"])
14 | def voicemail():
15 | response = VoiceResponse()
16 | if request.form["DialCallStatus"] != "completed":
17 | response.say("The agent is currently unavailable, please leave a message.")
18 | response.record(action="/hangup")
19 | return Response(str(response), mimetype="text/xml")
20 |
21 | @app.route("/hangup", methods=["POST"])
22 | def hangup():
23 | if "RecordingUrl" in request.form:
24 | print("Recording Url:", request.form["RecordingUrl"])
25 | response = VoiceResponse()
26 | response.hangup()
27 | return Response(str(response), mimetype="text/xml")
28 |
29 | app.run(debug=True)
30 |
--------------------------------------------------------------------------------
/Video/Simple Video Demo/src/frontend/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: Montserrat;
3 | }
4 |
5 | input {
6 | width: 200px;
7 | }
8 |
9 | /* Hide all divs at start
10 | We'll use javascript to selectively display divs. */
11 | body>div.dynamic {
12 | display: none;
13 | }
14 |
15 | #root {
16 | /* width: 400px; */
17 | width: 90%;
18 | }
19 |
20 | #logo {
21 | width: 130px;
22 | margin-left: 10px;
23 | }
24 |
25 | #events {
26 | /* width: 100px; */
27 | height: 300px;
28 | border-left: dotted 2px gray;
29 | padding-left: 10px;
30 | }
31 |
32 | .body {
33 | display: grid;
34 | grid-template-columns: 70% 30%;
35 | margin-top: 20px;
36 | }
37 |
38 | .content {
39 | min-height: 300px;
40 | }
41 |
42 | .header {
43 | display: grid;
44 | grid-template-columns: 100px 1fr;
45 | gap: 0 50px;
46 | padding-top: 15px;
47 | }
48 |
49 | .content {
50 | display: flex;
51 | justify-content: center;
52 | align-items: center;
53 | }
54 |
55 | .header>div {
56 | display: flex;
57 | /* justify-content: center; */
58 | align-items: center;
59 | margin-left: 20px;
60 | }
61 |
62 | #instant_invite {
63 | font-size: 12px;
64 | font-family: monospace;
65 | }
--------------------------------------------------------------------------------
/Messaging/Forward Messages - NodeJS/README.md:
--------------------------------------------------------------------------------
1 | # Forward Messages to Another Phone Number with Node.js
2 |
3 | This super simple guide will show how you can handle incoming messages and forward them to another phone number. We will use the [SignalWire Javascript SDK](https://developer.signalwire.com/client-sdk/reference/js-exports) to handle the incoming message and [RELAY Realtime API](https://developer.signalwire.com/sdks/reference/realtime-sdk/) to forward the message.
4 |
5 | # Setup Your Environment File
6 |
7 | Copy from env.sample and fill in your values.
8 |
9 | You will need a SignalWire phone number as well as your API Credentials (API Token and Project ID) from within the API tab of your SignalWire Space.
10 |
11 | Save the new file as `.env`.
12 |
13 | # How to Run This Code
14 |
15 | You can run this code natively by cloning and using the `npm start` command in your terminal.
16 |
17 | You may also choose to run it on Docker by building the image with `docker build -t forwardsms .` followed by `docker run -it --rm -p 3000:3000 --name forwardsms --env-file .env forwardsms`
18 |
19 | # Code Walkthrough
20 |
21 | Read the full walkthrough on the [Forwarding Messages](https://developer.signalwire.com/apis/docs/how-to-forward-messages) guide.
22 |
--------------------------------------------------------------------------------
/Integrations/SignalWire API on Azure Function - NodeJS/README.md:
--------------------------------------------------------------------------------
1 | # SignalWire API on Azure Function- Node.Js
2 |
3 | This project makes use of SignalWire Compatibility API and NodeJs SDK to make voice call and send sms on Azure function using the HttpTrigger function.
4 |
5 | 📖 [Read the full guide](https://developer.signalwire.com/apis/docs/microsoft-azure-functions)
6 |
7 | # How to Run Application
8 |
9 | Follow the below steps to get started with this project.
10 |
11 | - Clone this project
12 | - Basic understanding of cloud concept
13 | - Follow the [Guide](https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-node) to set up your environment
14 | - Create `.env` file from the `.env.example` file
15 | - Get your Project ID, API token and Space URL. If you do not know where to find these values, check out our guide [here](https://developer.signalwire.com/apis/docs/navigating-your-space#api)!
16 |
17 | # Sign Up Here
18 |
19 | If you would like to test this example out, you can create a SignalWire account and space [here](https://m.signalwire.com/signups/new?s=1).
20 |
21 | Please feel free to reach out to us on our [Community Slack](https://signalwire.community/) or create a Support ticket if you need guidance!
22 |
23 |
--------------------------------------------------------------------------------
/Messaging/Forward Messages to Email - NodeJS/README.md:
--------------------------------------------------------------------------------
1 | # Forward Messages to Email with Node.js
2 |
3 | This super simple guide will show how you can handle incoming messages and forward them to an email address. We will use the [SignalWire Javascript SDK](https://developer.signalwire.com/sdks) to handle the incoming message and [MailGun API](https://www.mailgun.com/) to send an email.
4 |
5 | # Setup Your Environment File
6 |
7 | Copy from .env.sample and fill in your values.
8 |
9 | You will need a SignalWire phone number as well as your API Credentials (API Token, Space URL, and Project ID) from within the API tab of your SignalWire Space.
10 |
11 | You will also need your Credentials from the MailGun API.
12 |
13 | Save new file called .env
14 |
15 | # How to Run This Code
16 |
17 | You can run this code natively by cloning and using the `npm start` command in your terminal.
18 |
19 | You may also choose to run it on Docker by building the image with `docker build -t smstoemail .` followed by `docker run -it --rm -p 3000:3000 --name smstoemail --env-file .env smstoemail`
20 |
21 | # Code Walkthrough
22 |
23 | Read the full walkthrough on the [Forwarding Texts to Email - Node.js](https://developer.signalwire.com/apis/docs/forwarding-texts-to-email-nodejs?relay_version=relayv3) guide.
24 |
--------------------------------------------------------------------------------
/Video/Room Preview Demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Preview
5 |
6 |
10 |
11 |
12 |
13 |
14 |
Generating preview
15 |
16 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Messaging/Forward Messages to Email - NodeJS Relay v4/README.md:
--------------------------------------------------------------------------------
1 | # Forward Messages to Email with Node.js
2 |
3 | This super simple guide will show how you can handle incoming messages and forward them to an email address. We will use the [SignalWire Javascript SDK](https://developer.signalwire.com/sdks) to handle the incoming message and [MailGun API](https://www.mailgun.com/) to send an email.
4 |
5 | # Setup Your Environment File
6 |
7 | Copy from .env.sample and fill in your values.
8 |
9 | You will need a SignalWire phone number as well as your API Credentials (API Token, Space URL, and Project ID) from within the API tab of your SignalWire Space.
10 |
11 | You will also need your Credentials from the MailGun API.
12 |
13 | Save new file called .env
14 |
15 | # How to Run This Code
16 |
17 | You can run this code natively by cloning and using the `npm start` command in your terminal.
18 |
19 | You may also choose to run it on Docker by building the image with `docker build -t smstoemail .` followed by `docker run -it --rm -p 3000:3000 --name smstoemail --env-file .env smstoemail`
20 |
21 | # Code Walkthrough
22 |
23 | Read the full walkthrough on the [Forwarding Texts to Email - Node.js](https://developer.signalwire.com/apis/docs/forwarding-texts-to-email-nodejs?relay_version=relayv4) guide.
24 |
--------------------------------------------------------------------------------
/Messaging/Forward Messages to Email - NodeJS/index.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config();
2 | let { Messaging } = require("@signalwire/realtime-api");
3 | let formData = require("form-data");
4 | let mailgun = require("mailgun.js");
5 |
6 | const swClient = new Messaging.Client({
7 | project: process.env.PROJECT_ID,
8 | token: process.env.API_TOKEN,
9 | contexts: ["office"],
10 | });
11 |
12 | const Mailgun = new mailgun(formData);
13 | const mgClient = Mailgun.client({
14 | username: "api",
15 | key: process.env.MAILGUN_API_TOKEN,
16 | });
17 |
18 | swClient.on("message.received", (message) => {
19 | let date = new Date().toISOString();
20 | let body = message.body;
21 | let from = message.from;
22 | let to = message.to;
23 | let media = message.media;
24 | let data = {
25 | from: process.env.EMAIL_FROM,
26 | to: process.env.EMAIL_TO,
27 | subject: "Incoming Message to " + to,
28 | text: `At ${date} you received a message from ${from} to ${to}. The message body was: '${body}'. The included media was: ${media}`,
29 | };
30 |
31 | mgClient.messages
32 | .create(process.env.MAILGUN_DOMAIN, data)
33 | .then((res) => {
34 | console.log(data);
35 | console.log(res);
36 | })
37 | .catch((err) => {
38 | console.error(err);
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/Voice/Appointment Reminder using NodeJS and Relay V3/index.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config();
2 | const express = require('express');
3 | let { Task } = require('@signalwire/realtime-api')
4 |
5 | const PORT = process.env.PORT || 8080
6 | const app = express();
7 | const http = require('http').createServer(app);
8 |
9 | app.use(express.json());
10 | app.set('view engine', 'ejs');
11 |
12 | let {createSession, createChannel} = require("better-sse");
13 | const channel = createChannel();
14 |
15 | app.get("/", async (req, res, next) => {
16 | res.render('index', { destination: process.env.DEFAULT_DESTINATION })
17 | })
18 |
19 | app.post("/notify", async (req, res, next) => {
20 | channel.broadcast(req.body.message);
21 | res.json({ status: 'ok' });
22 | })
23 |
24 | app.post("/send", async (req, res, next) => {
25 | console.log(req.body);
26 | await Task.send({
27 | project: process.env.SIGNALWIRE_PROJECT_ID,
28 | token: process.env.SIGNALWIRE_TOKEN,
29 | context: 'office',
30 | message: {
31 | number: req.body.number,
32 | message: req.body.message,
33 | }
34 | })
35 |
36 | res.json({ status: 'ok' });
37 | });
38 |
39 | app.get("/sse", async (req, res) => {
40 | const session = await createSession(req, res);
41 | channel.register(session);
42 | });
43 |
44 | http.listen(PORT, '0.0.0.0', () => {
45 | console.log(`Listening to ${PORT}`);
46 | });
--------------------------------------------------------------------------------
/Voice/Multi-Factor Authentication in Ruby/app.rb:
--------------------------------------------------------------------------------
1 | require 'dotenv/load'
2 | require 'signalwire/sdk'
3 | require 'sinatra'
4 | require 'net/http'
5 | require 'uri'
6 | require 'json'
7 | require "sinatra/reloader" if development?
8 |
9 | def make_request(action, payload)
10 | uri = URI.parse("https://#{ENV['SIGNALWIRE_SPACE']}/api/relay/rest/mfa#{action}")
11 |
12 | request = Net::HTTP::Post.new(uri)
13 | request.basic_auth(ENV['SIGNALWIRE_PROJECT_KEY'], ENV['SIGNALWIRE_TOKEN'])
14 | request.set_form_data(payload)
15 |
16 | response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https", verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http|
17 | http.request(request)
18 | end
19 |
20 | if response.code.to_i < 400
21 | return JSON.parse(response.body)
22 | else
23 | return { "success" => false }
24 | end
25 | end
26 |
27 | get '/' do
28 | erb :index
29 | end
30 |
31 | post '/' do
32 | if params[:phone]
33 | # request the token
34 | payload = {
35 | "to" => params[:phone]
36 | }
37 | result = make_request("/#{params[:mode]}", payload)
38 | @verify = result["id"]
39 | elsif params[:verify]
40 | payload = {
41 | "token" => params[:code]
42 | }
43 | result = make_request("/#{params[:verify]}/verify", payload)
44 |
45 | @success = result["success"]
46 | @verify = params[:verify]
47 | end
48 |
49 | erb :index
50 | end
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-project",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "watch": "ng build --watch --configuration development",
9 | "test": "ng test"
10 | },
11 | "private": true,
12 | "dependencies": {
13 | "@angular/animations": "^14.1.0",
14 | "@angular/common": "^14.1.0",
15 | "@angular/compiler": "^14.1.0",
16 | "@angular/core": "^14.1.0",
17 | "@angular/forms": "^14.1.0",
18 | "@angular/platform-browser": "^14.1.0",
19 | "@angular/platform-browser-dynamic": "^14.1.0",
20 | "@angular/router": "^14.1.0",
21 | "@signalwire/app-kit": "^0.0.1-dev.202208231654.564d9a2.4",
22 | "@stencil/store": "^2.0.0",
23 | "@types/jest": "^28.1.8",
24 | "rxjs": "~7.5.0",
25 | "tslib": "^2.3.0",
26 | "zone.js": "~0.11.4"
27 | },
28 | "devDependencies": {
29 | "@angular-devkit/build-angular": "^14.1.3",
30 | "@angular/cli": "~14.1.3",
31 | "@angular/compiler-cli": "^14.1.0",
32 | "@stencil/core": "^2.17.4",
33 | "@types/jasmine": "~4.0.0",
34 | "jasmine-core": "~4.2.0",
35 | "karma": "~6.4.0",
36 | "karma-chrome-launcher": "~3.1.0",
37 | "karma-coverage": "~2.2.0",
38 | "karma-jasmine": "~5.1.0",
39 | "karma-jasmine-html-reporter": "~2.0.0",
40 | "typescript": "~4.7.2"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Voice/Make Appointment Reminder Calls with Ruby/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | concurrent-ruby (1.1.8)
5 | dotenv (2.7.6)
6 | eventmachine (1.2.7)
7 | faraday (1.4.1)
8 | faraday-excon (~> 1.1)
9 | faraday-net_http (~> 1.0)
10 | faraday-net_http_persistent (~> 1.1)
11 | multipart-post (>= 1.2, < 3)
12 | ruby2_keywords (>= 0.0.4)
13 | faraday-excon (1.1.0)
14 | faraday-net_http (1.0.1)
15 | faraday-net_http_persistent (1.1.0)
16 | faye-websocket (0.11.0)
17 | eventmachine (>= 0.12.0)
18 | websocket-driver (>= 0.5.1)
19 | has-guarded-handlers (1.6.3)
20 | jwt (2.2.3)
21 | logger (1.4.3)
22 | multipart-post (2.1.1)
23 | nokogiri (1.11.3-x86_64-darwin)
24 | racc (~> 1.4)
25 | racc (1.5.2)
26 | ruby2_keywords (0.0.4)
27 | signalwire (2.3.4)
28 | concurrent-ruby (~> 1.1)
29 | faye-websocket (~> 0.10)
30 | has-guarded-handlers (~> 1.6.3)
31 | logger (~> 1.3)
32 | twilio-ruby (~> 5.0)
33 | twilio-ruby (5.52.0)
34 | faraday (>= 0.9, < 2.0)
35 | jwt (>= 1.5, <= 2.5)
36 | nokogiri (>= 1.6, < 2.0)
37 | websocket-driver (0.7.3)
38 | websocket-extensions (>= 0.1.0)
39 | websocket-extensions (0.1.5)
40 |
41 | PLATFORMS
42 | x86_64-darwin-20
43 |
44 | DEPENDENCIES
45 | dotenv
46 | signalwire
47 |
48 | BUNDLED WITH
49 | 2.2.15
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Vite/src/typescript.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Messaging/Forward Messages to Email - NodeJS Relay v4/index.js:
--------------------------------------------------------------------------------
1 | import "dotenv/config";
2 | import { SignalWire } from "@signalwire/realtime-api";
3 |
4 | import formData from "form-data";
5 | import mailgun from "mailgun.js";
6 |
7 | const swClient = await SignalWire({
8 | project: process.env.PROJECT_ID,
9 | token: process.env.API_TOKEN,
10 | topics: ["office"],
11 | });
12 |
13 | const Mailgun = new mailgun(formData);
14 | const mgClient = Mailgun.client({
15 | username: "api",
16 | key: process.env.MAILGUN_API_TOKEN,
17 | });
18 |
19 | let messageClient = swClient.messaging;
20 |
21 | await messageClient.listen({
22 | topics: ["office"],
23 | onMessageReceived: async (message) => {
24 | let date = new Date().toISOString();
25 | let body = message.body;
26 | let from = message.from;
27 | let to = message.to;
28 | let media = message.media;
29 | let data = {
30 | from: process.env.EMAIL_FROM,
31 | to: process.env.EMAIL_TO,
32 | subject: "Incoming Message to " + to,
33 | text: `At ${date} you received a message from ${from} to ${to}. The message body was: '${body}'. The included media was: ${media}`,
34 | };
35 |
36 | mgClient.messages
37 | .create(process.env.MAILGUN_DOMAIN, data)
38 | .then((res) => {
39 | console.log(data);
40 | console.log(res);
41 | })
42 | .catch((err) => {
43 | console.error(err);
44 | });
45 | },
46 | });
47 |
--------------------------------------------------------------------------------
/Voice/Weather Phone IVR - NodeJS/README.md:
--------------------------------------------------------------------------------
1 | # Build your own Weather Phone IVR with Realtime API
2 |
3 | 📖 [Read the full guide](https://developer.signalwire.com/apis/docs/weather-phone-in-nodejs-with-signalwire-realtime-api)
4 |
5 | This code sample is a simple weather phone IVR application that uses the [SignalWire Realtime API](https://developer.signalwire.com/client-sdk/reference/rt-exports) to provide current weather report to the caller in Washington DC either as a phone call or text.
6 |
7 | ### 📞 Dial [+17712093222](tel:+17712093222) ☎ for a **live demo** of this code.
8 |
9 | ---
10 |
11 | ### To run this sample
12 |
13 | 1. Fill in the Project ID and the API token from your SignalWire dashboard in the `.env.sample` file.
14 | 2. Buy a number from the SignalWire Dashboard, configure it to use Relay with context `office`.
15 | 3. Add that number to the `.env.sample` file under `PHONE_NUMBER`.
16 | 4. Rename the `.env.sample` file to `.env`.
17 | 5. Run this with `yarn install` then `yarn start` in the project directory.
18 | Alternatively, you can use Docker instead:
19 |
20 | a. `docker build . -t weather-ivr` to build the container using the dockerfile already in the repo.
21 |
22 | b. `docker run -d weather-ivr` to run it.
23 |
24 | For more information on how to run this sample, or for a more detailed guide, please read the [guide](https://developer.signalwire.com/apis/docs/weather-phone-in-nodejs-with-signalwire-realtime-api).
25 |
--------------------------------------------------------------------------------
/Messaging/Forward Messages - NodeJS/index.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config();
2 | const { Messaging } = require("@signalwire/realtime-api");
3 |
4 | const client = new Messaging.Client({
5 | project: process.env.PROJECT_ID,
6 | token: process.env.API_TOKEN,
7 | contexts: ["office"],
8 | });
9 |
10 | const express = require("express");
11 | const app = express();
12 | const port = 3000;
13 | const bodyparser = require("body-parser");
14 |
15 | app.use(bodyparser.urlencoded({ extended: true }));
16 |
17 | client.on("message.received", async (message) => {
18 | console.log(message);
19 | const date = new Date().toLocaleDateString();
20 | const text = "'" + message.body + "'";
21 | const sender = message.from;
22 | let media;
23 | if (message.media) {
24 | media = message.media;
25 | text = "media only";
26 | }
27 |
28 | const data = {
29 | from: process.env.ORIGINAL_NUMBER,
30 | to: process.env.TO_NUMBER,
31 | context: "office",
32 | body: `At ${date} you received a message from ${sender} to ${process.env.ORIGINAL_NUMBER}. The message body was: ${text}.`,
33 | media,
34 | };
35 | console.log(data);
36 |
37 | try {
38 | const sendResult = await client.send(data);
39 | console.log("Forwarding message.", sendResult);
40 | } catch (error) {
41 | console.error("Message failed to send", error);
42 | }
43 | });
44 |
45 | app.listen(port, () => {
46 | console.log(`Server listening on port ${port}`);
47 | });
48 |
--------------------------------------------------------------------------------
/Chat/Using chat to send messages and make voice calls/frontend/app.css:
--------------------------------------------------------------------------------
1 | .chatPage {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | }
6 |
7 | .chatPage #messageEditor .dropdown {
8 | text-align: right;
9 | margin-top: 5px;
10 | }
11 |
12 | .chatPage #messageEditor #messageToSend {
13 | margin-top: 20px;
14 | }
15 |
16 | .chatPage #messageEditor {
17 | max-width: 500px;
18 | display: flex;
19 | flex-direction: column;
20 | width: 100%;
21 | }
22 |
23 | .chatPage #typing {
24 | height: 1.1em;
25 | margin-top: 1em;
26 | }
27 |
28 | #messagesContainer {
29 | flex: 1;
30 | flex-direction: column;
31 | }
32 |
33 | #channelsContainer {
34 | display: flex;
35 | justify-content: center;
36 | gap: 5px 20px;
37 | }
38 |
39 | #channelsContainer .channel {
40 | width: 600px;
41 | background-color: #e5e5e5;
42 | padding: 10px 15px 20px 15px;
43 | }
44 |
45 | #channelsContainer .channel .messages-list {
46 | height: 500px;
47 | overflow: scroll;
48 | }
49 |
50 | #channelsContainer .message {
51 | background: rgb(20, 127, 255);
52 | border-radius: 20px;
53 | padding: 10px 15px;
54 | color: white;
55 | margin-top: 10px;
56 | }
57 |
58 | #channelsContainer .channel-name {
59 | text-align: center;
60 | margin-bottom: 1em;
61 | }
62 |
63 | .message .message-meta {
64 | font-style: italic;
65 | font-size: 0.9em;
66 | opacity: 0.8;
67 | }
68 |
--------------------------------------------------------------------------------
/Chat/Using chat to send messages and make voice calls Relay v4/frontend/app.css:
--------------------------------------------------------------------------------
1 | .chatPage {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | }
6 |
7 | .chatPage #messageEditor .dropdown {
8 | text-align: right;
9 | margin-top: 5px;
10 | }
11 |
12 | .chatPage #messageEditor #messageToSend {
13 | margin-top: 20px;
14 | }
15 |
16 | .chatPage #messageEditor {
17 | max-width: 500px;
18 | display: flex;
19 | flex-direction: column;
20 | width: 100%;
21 | }
22 |
23 | .chatPage #typing {
24 | height: 1.1em;
25 | margin-top: 1em;
26 | }
27 |
28 | #messagesContainer {
29 | flex: 1;
30 | flex-direction: column;
31 | }
32 |
33 | #channelsContainer {
34 | display: flex;
35 | justify-content: center;
36 | gap: 5px 20px;
37 | }
38 |
39 | #channelsContainer .channel {
40 | width: 600px;
41 | background-color: #e5e5e5;
42 | padding: 10px 15px 20px 15px;
43 | }
44 |
45 | #channelsContainer .channel .messages-list {
46 | height: 500px;
47 | overflow: scroll;
48 | }
49 |
50 | #channelsContainer .message {
51 | background: rgb(20, 127, 255);
52 | border-radius: 20px;
53 | padding: 10px 15px;
54 | color: white;
55 | margin-top: 10px;
56 | }
57 |
58 | #channelsContainer .channel-name {
59 | text-align: center;
60 | margin-bottom: 1em;
61 | }
62 |
63 | .message .message-meta {
64 | font-style: italic;
65 | font-size: 0.9em;
66 | opacity: 0.8;
67 | }
68 |
--------------------------------------------------------------------------------
/Messaging/Sending SMS from the Browser - NodeJS/index.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config();
2 | let sw = require("@signalwire/realtime-api");
3 | let Messaging = sw.Messaging;
4 |
5 | const sendingPhoneNumber = process.env.PHONE_NUMBER;
6 |
7 | const client = new Messaging.Client({
8 | project: process.env.PROJECT_ID,
9 | token: process.env.API_TOKEN,
10 | });
11 |
12 | const express = require("express");
13 | const app = express();
14 | const port = 3000;
15 | const bodyparser = require("body-parser");
16 | const isE164PhoneNumber = require("is-e164-phone-number");
17 |
18 | app.use(bodyparser.urlencoded({ extended: true }));
19 | app.use("/", express.static("html"));
20 |
21 | app.post("/sendSMS", async (req, res) => {
22 | let { phoneno, body } = req.body;
23 | if (typeof body !== "string" || body === "") return res.send("Invalid body");
24 | if (!isE164PhoneNumber(phoneno)) return res.send("Invalid Phone Number");
25 |
26 | console.log("Sending message to phone number", phoneno);
27 | try {
28 | const status = await client.send({
29 | context: "office",
30 | from: sendingPhoneNumber, // The number you bought from SignalWire
31 | to: phoneno,
32 | body,
33 | });
34 |
35 | console.log(status);
36 | return res.send("Your SMS was sent");
37 | } catch (e) {
38 | console.error(e);
39 | return res.send("Error sending SMS");
40 | }
41 | });
42 |
43 | app.listen(port, () => {
44 | console.log(`Example app listening on port ${port}`);
45 | });
46 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Vite/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Voice/Weather Phone IVR - NodeJS Relay v4/README.md:
--------------------------------------------------------------------------------
1 | # Build your own Weather Phone IVR with Realtime API
2 |
3 | 📖 [Read the full guide](https://developer.signalwire.com/apis/docs/weather-phone-in-nodejs-with-signalwire-realtime-api?relay_version=relayv4)
4 |
5 | This code sample is a simple weather phone IVR application that uses the [SignalWire Realtime API](https://developer.signalwire.com/sdks/reference/realtime-sdk/relay-v4) to provide current weather report to the caller in Washington DC either as a phone call or text.
6 |
7 |
8 |
9 | ---
10 |
11 | ### To run this sample
12 |
13 | 1. Fill in the Project ID and the API token from your SignalWire dashboard in the `.env.sample` file.
14 | 2. Buy a number from the SignalWire Dashboard, configure it to use Relay with context `office`.
15 | 3. Add that number to the `.env.sample` file under `PHONE_NUMBER`.
16 | 4. Rename the `.env.sample` file to `.env`.
17 | 5. Run this with `yarn install` then `yarn start` in the project directory.
18 | Alternatively, you can use Docker instead:
19 |
20 | a. `docker build . -t weather-ivr` to build the container using the dockerfile already in the repo.
21 |
22 | b. `docker run -d weather-ivr` to run it.
23 |
24 | For more information on how to run this sample, or for a more detailed guide, please read the [guide](https://developer.signalwire.com/apis/docs/weather-phone-in-nodejs-with-signalwire-realtime-api?relay_version=relayv4).
25 |
--------------------------------------------------------------------------------
/Messaging/Sending SMS from the Browser - NodeJS Relay v4/index.js:
--------------------------------------------------------------------------------
1 | import "dotenv/config";
2 | import { SignalWire } from "@signalwire/realtime-api";
3 |
4 | const client = await SignalWire({
5 | project: process.env.PROJECT_ID,
6 | token: process.env.API_TOKEN,
7 | });
8 |
9 | let messageClient = client.messaging;
10 |
11 | const sendingPhoneNumber = process.env.PHONE_NUMBER;
12 |
13 | const express = require("express");
14 | const app = express();
15 | const port = 3000;
16 | const bodyparser = require("body-parser");
17 | const isE164PhoneNumber = require("is-e164-phone-number");
18 |
19 | app.use(bodyparser.urlencoded({ extended: true }));
20 | app.use("/", express.static("html"));
21 |
22 | app.post("/sendSMS", async (req, res) => {
23 | let { phoneno, body } = req.body;
24 | if (typeof body !== "string" || body === "") return res.send("Invalid body");
25 | if (!isE164PhoneNumber(phoneno)) return res.send("Invalid Phone Number");
26 |
27 | console.log("Sending message to phone number", phoneno);
28 | try {
29 | const status = await messageClient.send({
30 | topic: "office",
31 | from: sendingPhoneNumber, // The number you bought from SignalWire
32 | to: phoneno,
33 | body,
34 | });
35 |
36 | console.log(status);
37 | return res.send("Your SMS was sent");
38 | } catch (e) {
39 | console.error(e);
40 | return res.send("Error sending SMS");
41 | }
42 | });
43 |
44 | app.listen(port, () => {
45 | console.log(`Example app listening on port ${port}`);
46 | });
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 |
27 |
28 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
29 |
30 | # dependencies
31 | /node_modules
32 | /.pnp
33 | .pnp.js
34 |
35 | # testing
36 | /coverage
37 |
38 | # production
39 | /build
40 |
41 | # misc
42 | .DS_Store
43 | .env
44 | .env.local
45 | .env.development.local
46 | .env.test.local
47 | .env.production.local
48 |
49 | npm-debug.log*
50 | yarn-debug.log*
51 | yarn-error.log*
52 |
53 |
54 | # See http://help.github.com/ignore-files/ for more about ignoring files.
55 |
56 | # Compiled output
57 | /dist
58 | /tmp
59 | /out-tsc
60 | /bazel-out
61 |
62 | # Node
63 | /node_modules
64 | npm-debug.log
65 | yarn-error.log
66 |
67 | # IDEs and editors
68 | .idea/
69 | .project
70 | .classpath
71 | .c9/
72 | *.launch
73 | .settings/
74 | *.sublime-workspace
75 |
76 | # Visual Studio Code
77 | .vscode/*
78 | !.vscode/settings.json
79 | !.vscode/tasks.json
80 | !.vscode/launch.json
81 | !.vscode/extensions.json
82 | .history/*
83 |
84 | # Miscellaneous
85 | /.angular/cache
86 | .sass-cache/
87 | /connect.lock
88 | /coverage
89 | /libpeerconnection.log
90 | testem.log
91 | /typings
92 |
93 | # System files
94 | .DS_Store
95 | Thumbs.db
96 |
--------------------------------------------------------------------------------
/Video/RTMP-Streaming/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 |
27 |
28 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
29 |
30 | # dependencies
31 | /node_modules
32 | /.pnp
33 | .pnp.js
34 |
35 | # testing
36 | /coverage
37 |
38 | # production
39 | /build
40 |
41 | # misc
42 | .DS_Store
43 | .env
44 | .env.local
45 | .env.development.local
46 | .env.test.local
47 | .env.production.local
48 |
49 | npm-debug.log*
50 | yarn-debug.log*
51 | yarn-error.log*
52 |
53 |
54 | # See http://help.github.com/ignore-files/ for more about ignoring files.
55 |
56 | # Compiled output
57 | /dist
58 | /tmp
59 | /out-tsc
60 | /bazel-out
61 |
62 | # Node
63 | /node_modules
64 | npm-debug.log
65 | yarn-error.log
66 |
67 | # IDEs and editors
68 | .idea/
69 | .project
70 | .classpath
71 | .c9/
72 | *.launch
73 | .settings/
74 | *.sublime-workspace
75 |
76 | # Visual Studio Code
77 | .vscode/*
78 | !.vscode/settings.json
79 | !.vscode/tasks.json
80 | !.vscode/launch.json
81 | !.vscode/extensions.json
82 | .history/*
83 |
84 | # Miscellaneous
85 | /.angular/cache
86 | .sass-cache/
87 | /connect.lock
88 | /coverage
89 | /libpeerconnection.log
90 | testem.log
91 | /typings
92 |
93 | # System files
94 | .DS_Store
95 | Thumbs.db
96 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Vue 3/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 |
27 |
28 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
29 |
30 | # dependencies
31 | /node_modules
32 | /.pnp
33 | .pnp.js
34 |
35 | # testing
36 | /coverage
37 |
38 | # production
39 | /build
40 |
41 | # misc
42 | .DS_Store
43 | .env.local
44 | .env.development.local
45 | .env.test.local
46 | .env.production.local
47 |
48 | npm-debug.log*
49 | yarn-debug.log*
50 | yarn-error.log*
51 |
52 |
53 | # See http://help.github.com/ignore-files/ for more about ignoring files.
54 |
55 | # Compiled output
56 | /dist
57 | /tmp
58 | /out-tsc
59 | /bazel-out
60 |
61 | # Node
62 | /node_modules
63 | npm-debug.log
64 | yarn-error.log
65 |
66 | # IDEs and editors
67 | .idea/
68 | .project
69 | .classpath
70 | .c9/
71 | *.launch
72 | .settings/
73 | *.sublime-workspace
74 |
75 | # Visual Studio Code
76 | .vscode/*
77 | !.vscode/settings.json
78 | !.vscode/tasks.json
79 | !.vscode/launch.json
80 | !.vscode/extensions.json
81 | .history/*
82 |
83 | # Miscellaneous
84 | /.angular/cache
85 | .sass-cache/
86 | /connect.lock
87 | /coverage
88 | /libpeerconnection.log
89 | testem.log
90 | /typings
91 |
92 | # System files
93 | .DS_Store
94 | Thumbs.db
95 |
--------------------------------------------------------------------------------
/Video/Interactive-Live-Streaming/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "livewire-broadcasting",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@emotion/react": "^11.10.4",
7 | "@emotion/styled": "^11.10.4",
8 | "@mui/icons-material": "^5.10.6",
9 | "@mui/material": "^5.10.7",
10 | "@signalwire-community/react": "^1.4.2",
11 | "@signalwire/js": "^3.17.0",
12 | "@testing-library/jest-dom": "^5.16.5",
13 | "@testing-library/react": "^13.4.0",
14 | "@testing-library/user-event": "^13.5.0",
15 | "react": "^18.2.0",
16 | "react-dom": "^18.2.0",
17 | "react-router-dom": "^6.4.1",
18 | "react-scripts": "5.0.1",
19 | "web-vitals": "^2.1.4"
20 | },
21 | "resolutions": {
22 | "@signalwire/js": "^3.17.0"
23 | },
24 | "scripts": {
25 | "postinstall": "cd server && npm install",
26 | "start": "concurrently \"react-scripts start\" \"npm run start:server\"",
27 | "start:server": "cd server && npm run start",
28 | "build": "react-scripts build",
29 | "test": "react-scripts test",
30 | "eject": "react-scripts eject"
31 | },
32 | "eslintConfig": {
33 | "extends": [
34 | "react-app",
35 | "react-app/jest"
36 | ]
37 | },
38 | "browserslist": {
39 | "production": [
40 | ">0.2%",
41 | "not dead",
42 | "not op_mini all"
43 | ],
44 | "development": [
45 | "last 1 chrome version",
46 | "last 1 firefox version",
47 | "last 1 safari version"
48 | ]
49 | },
50 | "devDependencies": {
51 | "concurrently": "^7.4.0"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Video/RTMP-Streaming/index.js:
--------------------------------------------------------------------------------
1 | let roomSession;
2 | let stream;
3 |
4 | const stopStream = () => {
5 | if (stream) {
6 | stream.stop();
7 | }
8 | };
9 |
10 | const setRoomSession = (session) => {
11 | roomSession = session;
12 |
13 | document.getElementById("button-bar").style.display = "block";
14 |
15 | roomSession.on("room.left", () => {
16 | document.getElementById("button-bar").style.display = "none";
17 |
18 | stopStream();
19 | });
20 | };
21 |
22 | document.addEventListener("DOMContentLoaded", () => {
23 | document.getElementById("rtmp-form").onsubmit = async (e) => {
24 | e.preventDefault();
25 |
26 | const url = document.getElementById("stream-url").value;
27 | try {
28 | stream = await roomSession.startStream({ url });
29 | document.getElementById("streaming").style.display = "block";
30 | document.getElementById("start").style.display = "none";
31 | document.getElementById("stop").style.display = "inline";
32 | } catch (error) {
33 | console.log(error);
34 | alert(
35 | "There was an error starting the stream. Please check your URL and try again."
36 | );
37 | }
38 | };
39 |
40 | document.getElementById("stop").onclick = (e) => {
41 | e.preventDefault();
42 | try {
43 | stopStream();
44 | document.getElementById("streaming").style.display = "none";
45 | document.getElementById("start").style.display = "inline";
46 | document.getElementById("stop").style.display = "none";
47 | } catch (e) {
48 | console.log(e);
49 | }
50 | };
51 | });
52 |
--------------------------------------------------------------------------------
/Video/Room Preview Demo/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Preview
5 |
6 |
21 |
22 |
23 |
24 |
25 |
Generating preview
26 |
27 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/Video/AppKit-Framework-Examples/Angular/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | jasmine: {
17 | // you can add configuration options for Jasmine here
18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
19 | // for example, you can disable the random execution with `random: false`
20 | // or set a specific seed with `seed: 4321`
21 | },
22 | clearContext: false // leave Jasmine Spec Runner output visible in browser
23 | },
24 | jasmineHtmlReporter: {
25 | suppressAll: true // removes the duplicated traces
26 | },
27 | coverageReporter: {
28 | dir: require('path').join(__dirname, './coverage/angular-project'),
29 | subdir: '.',
30 | reporters: [
31 | { type: 'html' },
32 | { type: 'text-summary' }
33 | ]
34 | },
35 | reporters: ['progress', 'kjhtml'],
36 | port: 9876,
37 | colors: true,
38 | logLevel: config.LOG_INFO,
39 | autoWatch: true,
40 | browsers: ['Chrome'],
41 | singleRun: false,
42 | restartOnFileChange: true
43 | });
44 | };
45 |
--------------------------------------------------------------------------------
/Video/Interactive-Live-Streaming/src/components/Members.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import IconButton from "@mui/material/IconButton";
3 | import LogoutIcon from "@mui/icons-material/Logout";
4 | import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
5 | import { useMembers } from "@signalwire-community/react";
6 | import { Tooltip } from "@mui/material";
7 | import style from "./Members.module.css";
8 |
9 | export default function Members({ roomSession }) {
10 | const { members } = useMembers(roomSession);
11 |
12 | return (
13 |
14 | {members?.map((member) => (
15 |
16 | {member.name}
17 |
18 |
19 |
20 | ))}
21 |
22 | );
23 | }
24 |
25 | function SmallLeaveButton({ roomSession, member }) {
26 | return (
27 |
28 | roomSession?.removeMember({ memberId: member.id })}
32 | >
33 |
34 |
35 |
36 | );
37 | }
38 |
39 | function SmallDemoteButton({ roomSession, member }) {
40 | return (
41 |
42 | roomSession?.demote({ memberId: member.id })}
46 | >
47 |
48 |
49 |
50 | );
51 | }
52 |
--------------------------------------------------------------------------------
/Voice/Answering Machine Detection with Ruby/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | concurrent-ruby (1.1.8)
5 | daemons (1.3.1)
6 | eventmachine (1.2.7)
7 | faraday (1.3.0)
8 | faraday-net_http (~> 1.0)
9 | multipart-post (>= 1.2, < 3)
10 | ruby2_keywords
11 | faraday-net_http (1.0.1)
12 | faye-websocket (0.11.0)
13 | eventmachine (>= 0.12.0)
14 | websocket-driver (>= 0.5.1)
15 | has-guarded-handlers (1.6.3)
16 | jwt (2.2.2)
17 | logger (1.4.3)
18 | mini_portile2 (2.5.0)
19 | multipart-post (2.1.1)
20 | mustermann (1.1.1)
21 | ruby2_keywords (~> 0.0.1)
22 | nokogiri (1.11.2)
23 | mini_portile2 (~> 2.5.0)
24 | racc (~> 1.4)
25 | racc (1.5.2)
26 | rack (2.2.3)
27 | rack-protection (2.1.0)
28 | rack
29 | ruby2_keywords (0.0.4)
30 | signalwire (2.3.4)
31 | concurrent-ruby (~> 1.1)
32 | faye-websocket (~> 0.10)
33 | has-guarded-handlers (~> 1.6.3)
34 | logger (~> 1.3)
35 | twilio-ruby (~> 5.0)
36 | sinatra (2.1.0)
37 | mustermann (~> 1.0)
38 | rack (~> 2.2)
39 | rack-protection (= 2.1.0)
40 | tilt (~> 2.0)
41 | thin (1.8.0)
42 | daemons (~> 1.0, >= 1.0.9)
43 | eventmachine (~> 1.0, >= 1.0.4)
44 | rack (>= 1, < 3)
45 | tilt (2.0.10)
46 | twilio-ruby (5.48.0)
47 | faraday (>= 0.9, < 2.0)
48 | jwt (>= 1.5, <= 2.5)
49 | nokogiri (>= 1.6, < 2.0)
50 | websocket-driver (0.7.3)
51 | websocket-extensions (>= 0.1.0)
52 | websocket-extensions (0.1.5)
53 |
54 | PLATFORMS
55 | ruby
56 |
57 | DEPENDENCIES
58 | signalwire
59 | sinatra
60 | thin
61 |
62 | BUNDLED WITH
63 | 2.1.4
--------------------------------------------------------------------------------
/Voice/Lenny Spam Filter Relay v4/src/lenny.js:
--------------------------------------------------------------------------------
1 | import { Voice } from "@signalwire/realtime-api";
2 | const lennyConfig = {
3 | soundBase:
4 | "https://s3.us-east-2.amazonaws.com/files.signalwire.com/173aba80-58fc-415d-b6ed-df6e357e766f/d1a906e8-f5e5-4939-8c07-31105b56ec41/Files/Lenny",
5 | background: "backgroundnoise.mp3",
6 | responses: [
7 | "Lenny1.mp3",
8 | "Lenny2.mp3",
9 | "Lenny3.mp3",
10 | "Lenny4.mp3",
11 | "Lenny5.mp3",
12 | "Lenny6.mp3",
13 | "Lenny7.mp3",
14 | "Lenny8.mp3",
15 | "Lenny9.mp3",
16 | "Lenny10.mp3",
17 | "Lenny11.mp3",
18 | "Lenny12.mp3",
19 | "Lenny13.mp3",
20 | "Lenny14.mp3",
21 | "Lenny15.mp3",
22 | "Lenny16.mp3",
23 | ],
24 | };
25 |
26 | /**
27 | * Given a call object, connect the caller to Lenny and his ducks.
28 | *
29 | * @param {*} call
30 | * @returns asynchronously returns `void` when the call ends.
31 | */
32 | export async function lenny(call) {
33 | let i = 0;
34 |
35 | while (call.active) {
36 | await promptLenny(call, i);
37 | i += 1;
38 |
39 | if (i >= lennyConfig.responses.length) {
40 | i = 4;
41 | }
42 | }
43 | }
44 |
45 | async function promptLenny(call, responseId) {
46 | console.log("Prompting with: ", lennyConfig.responses[responseId]);
47 |
48 | await call
49 | .playAudio({
50 | url: lennyConfig.soundBase + "/" + lennyConfig.responses[responseId],
51 | volume: +20,
52 | })
53 | .onEnded();
54 |
55 | return await call.prompt({
56 | speech: { endSilenceTimeout: 1.0 },
57 | playlist: new Voice.Playlist().add(
58 | Voice.Playlist.Audio({
59 | url: lennyConfig.soundBase + "/" + lennyConfig.background,
60 | })
61 | ),
62 | });
63 | }
64 |
--------------------------------------------------------------------------------
/Integrations/SignalWire API on Azure Function - NodeJS/SendSMS/index.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config()
2 | const axios = require('axios')
3 |
4 | // PROJECT_ID and API_TOKEN are environment variable added in the .env file
5 | // Azure Functions uses the Application settings. You can access that from your
6 |
7 | const projectID = process.env.PROJECT_ID
8 | const token = process.env.API_TOKEN
9 | const spaceURL = process.env.SPACE_URL
10 |
11 |
12 | // Initialize the auth object for authentication when making
13 | // a call to signalwire api
14 | const auth = {
15 | username: projectID,
16 | password: token
17 | }
18 |
19 |
20 | // API url name to make our POST call too
21 | const apiUrl = `https://${spaceURL}/api/laml/2010-04-01/Accounts/${projectID}/Messages`
22 |
23 | module.exports = async function (context, req) {
24 | context.log('JavaScript HTTP trigger function processed a request.');
25 |
26 | // Get the receiver, sender and message params from the body
27 | // It makes use of the destructuring in NodeJs
28 | const {receiver, sender, message} = req.body
29 |
30 | // An empty object to save the response from axios
31 | let responseMessage = null
32 |
33 | // Axios call to the signalwire api
34 | await axios.post(apiUrl, {
35 | To: receiver,
36 | From: sender,
37 | Body: message
38 | }, {auth}).then(response=> {
39 |
40 | // appending response from the axios call to the {responseMessage} object
41 | responseMessage = response.data
42 |
43 | }, error => {
44 | console.log(error.message)
45 | })
46 |
47 | // return the response of the axios call in a json format
48 | context.res = {
49 | body: responseMessage
50 | }
51 |
52 | }
--------------------------------------------------------------------------------
/Voice/Implement Coaching and Recording with NodeJS/src/utils/appHelpers.js:
--------------------------------------------------------------------------------
1 | // create a Showdown instance to parse issue/pr body content
2 | const showdown = require('showdown')
3 |
4 | // Showdown parameters to jive well with Github flavored markdown
5 | export const converter = new showdown.Converter({
6 | tables: true,
7 | strikethrough: true,
8 | ghCompatibleHeaderId: true,
9 | literalMidWordUnderscores: true,
10 | ghCodeBlocks: true,
11 | tasklists: true,
12 | ghMentions: true,
13 | ghMentionsLink: 'https://github.com/{u}'
14 | })
15 |
16 | // helper function to properly encode query string for fetch
17 | export const encodeQueryString = (params) => {
18 | const keys = Object.keys(params)
19 | return keys.length ?
20 | "?" + keys
21 | .map(key => encodeURIComponent(key) +
22 | "=" + encodeURIComponent(params[key]))
23 | .join("&") :
24 | ""
25 | }
26 |
27 | // helper function to parse Link headers in to an object for use with pagniation
28 | export const parseLinkHeader = (header) => {
29 | if (header.length === 0) {
30 | throw new Error("input must not be of zero length");
31 | }
32 |
33 | // Split parts by comma and parse each part into a named link
34 | return header.split(/(?!\B"[^"]*),(?![^"]*"\B)/).reduce((links, part) => {
35 | const section = part.split(/(?!\B"[^"]*);(?![^"]*"\B)/);
36 | if (section.length < 2) {
37 | throw new Error("section could not be split on ';'");
38 | }
39 | const url = section[0].replace(/<(.*)>/, '$1').trim();
40 | const name = section[1].replace(/rel="(.*)"/, '$1').trim();
41 |
42 | links[name] = url;
43 |
44 | return links;
45 | }, {});
46 | }
--------------------------------------------------------------------------------
/Messaging/Send-SMS-Through-Google-Sheets/README.md:
--------------------------------------------------------------------------------
1 | # Send SMS Through Google Sheets
2 |
3 | ## Overview
4 | Do you store your customer’s information in an excel or Google Sheets spreadsheet? Wouldn’t it be handy to be able to send SMS to your customers directly from Google Sheets? With this guide we’ll show you how to integrate SignalWire API with Google Sheets API to track and contact customers regarding payments that are due. We’ll be using Google’s version of Javascript which is called Apps Script. You can modify this code however you need to fit your particular use case.
5 |
6 |
7 |
8 | ## What do you need to run this code?
9 |
10 | View the full walkthrough on our developer site [here](https://developer.signalwire.com/apis/docs/how-to-send-sms-from-google-sheets)!
11 |
12 | This guide uses Google Sheets so you'll need to have an active Google account.
13 |
14 | You will need a SignalWire phone number as well as your API Credentials (API Token, Space URL, and Project ID) which can all be found in an easily copyable format within the API tab of your SignalWire portal.
15 |
16 |
17 |
18 | ## How to Run Application
19 |
20 | ### Build and Run within Google Sheets
21 |
22 | 1. Copy the code from the Javascript file and paste it into the Apps Script Editor in Google Sheets.
23 |
24 | 2. Input your SignalWire credentials in the custom 'Credentials' menu.
25 |
26 | 3. Run the script from the custom 'Send SMS' menu.
27 |
28 |
29 |
30 | ## Sign Up Here
31 |
32 | If you would like to test this example out, you can create a SignalWire account and space [here](https://m.signalwire.com/signups/new?s=1).
33 |
34 | Please feel free to reach out to us on our [Community Slack](https://signalwire.community/) or create a Support ticket if you need guidance!
35 |
--------------------------------------------------------------------------------
/Video/Interactive-Live-Streaming/src/Prejoin.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { TextField, Button } from "@mui/material";
3 | import { useNavigate } from "react-router-dom";
4 | import style from "./Prejoin.module.css";
5 |
6 | export default function Prejoin() {
7 | const navigate = useNavigate();
8 | const [username, setUsername] = useState("");
9 |
10 | async function onJoinClicked(mod) {
11 | if (!username) return;
12 |
13 | const endpoint = mod ? "/get_member_token" : "/get_audience_token";
14 | const token = await fetch(`http://127.0.0.1:15000${endpoint}`, {
15 | method: "POST",
16 | headers: {
17 | "Content-Type": "application/json",
18 | },
19 | body: JSON.stringify({
20 | user_name: username,
21 | room_name: "my_live_stream",
22 | }),
23 | });
24 |
25 | navigate("/in-call", {
26 | state: {
27 | token: (await token.json()).token,
28 | userName: username,
29 | },
30 | });
31 | }
32 |
33 | return (
34 |