├── Procfile
├── setup.cfg
├── requirements.txt
├── .gitignore
├── static
├── images
│ ├── dark-mosaic.png
│ ├── grid-pattern.png
│ ├── inspiration-geometry.png
│ └── pattern-pentagon-fade.png
├── env_errors.html
├── css
│ └── style.css
└── index.html
├── example_creds.py
├── tests
└── audiosocket_test.py
├── creds.py
├── LICENSE
├── README.md
└── server.py
/Procfile:
--------------------------------------------------------------------------------
1 | web: ./server.py
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [tool:pytest]
2 | testpaths = tests
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | nexmo==1.4.0
2 | tornado==4.4.2
3 | phonenumbers==7.7.5
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .cache
3 | __pycache__
4 | configuration
5 | private.key
6 | venv
7 |
--------------------------------------------------------------------------------
/static/images/dark-mosaic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nexmo-community/audiosocket-demo/HEAD/static/images/dark-mosaic.png
--------------------------------------------------------------------------------
/static/images/grid-pattern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nexmo-community/audiosocket-demo/HEAD/static/images/grid-pattern.png
--------------------------------------------------------------------------------
/static/images/inspiration-geometry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nexmo-community/audiosocket-demo/HEAD/static/images/inspiration-geometry.png
--------------------------------------------------------------------------------
/static/images/pattern-pentagon-fade.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nexmo-community/audiosocket-demo/HEAD/static/images/pattern-pentagon-fade.png
--------------------------------------------------------------------------------
/example_creds.py:
--------------------------------------------------------------------------------
1 |
2 | API_KEY= 'XXX'
3 | API_SECRET = 'XXX'
4 | APP_ID = 'XXX-XXX-XXX'
5 | PRIVATE_KEY_PATH = './private.key'
6 | with open(PRIVATE_KEY_PATH, "r") as kf:
7 | PRIVATE_KEY = kf.read()
--------------------------------------------------------------------------------
/tests/audiosocket_test.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | # This isn't very nice:
4 | sys.path.insert(0, '.')
5 |
6 | import server
7 |
8 |
9 | def test_format_number():
10 | assert server.format_number('447700900704') == '07700 900704'
11 |
--------------------------------------------------------------------------------
/static/env_errors.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Environment Errors
6 |
7 |
8 | Environment Errors
9 | The following environment variables are missing:
10 |
11 | {% for missing_env in missing_envs %}
12 | - {{ missing_env }}
13 | {% end %}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/creds.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 |
4 |
5 | class Config(object):
6 | def __init__(self):
7 | self.missing_keys = []
8 | self.api_key = self._load('API_KEY')
9 | self.api_secret = self._load('API_SECRET')
10 | self.app_id = self._load('APP_ID')
11 | self.private_key = self._load('PRIVATE_KEY')
12 | self.phone_number = self._load('PHONE_NUMBER')
13 | self.host = self._load('HOST')
14 | self.port = self._load('PORT', 8000)
15 |
16 | def _load(self, key, default=None):
17 | val = os.getenv(key, default)
18 | if val is None:
19 | self.missing_keys.append(key)
20 | logging.error("Missing environment variable %s", key)
21 | return val
22 |
23 | @property
24 | def fully_configured(self):
25 | return not self.missing_keys
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Sam Machin
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 |
--------------------------------------------------------------------------------
/static/css/style.css:
--------------------------------------------------------------------------------
1 | * { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
2 |
3 | html {
4 | height: 100%;
5 | }
6 | body {
7 | color: #fff;
8 | margin: 0;
9 | padding: 2em 0 2em;
10 | font-family: 'Noto Sans', sans-serif;
11 | background: #517fa4;
12 | background: -webkit-linear-gradient(to bottom, #516395 , #020527);
13 | background: url(../images/pattern-pentagon-fade.png) left top repeat-x,
14 | linear-gradient(to bottom, #8E54E9 , #020527);
15 | position: relative;
16 | }
17 | .main {
18 | width: 100%;
19 | position: absolute;
20 | top: 0;
21 | left: 0;
22 | }
23 | h1, h2, h3 {
24 | margin: 0;
25 | text-rendering: optimizeLegibility;
26 | }
27 | header {
28 | margin: 1em auto;
29 | text-align: center;
30 | z-index: 1;
31 | }
32 | header h1 {
33 | font-family: 'Alfa Slab One';
34 | font-size: 2.6em;
35 | font-weight: normal;
36 | }
37 | canvas {
38 | width: 100%;
39 | background: transparent;
40 | }
41 | footer {
42 | position: fixed;
43 | bottom: 1em;
44 | right: 1em;
45 | opacity: 0.75;
46 | }
47 | footer a {
48 | color: pink;
49 | }
50 | input {
51 | display: block;
52 | -webkit-appearance: none;
53 | -moz-appearance: none;
54 | border: none;
55 | border-radius: 4px;
56 | color: #333;
57 | font-size: 1.1em;
58 | }
59 | button {
60 | display: block;
61 | -webkit-appearance: none;
62 | -moz-appearance: none;
63 | background: transparent;
64 | color: #fff;
65 | border: 4px solid #fff;
66 | border-radius: 50%;
67 | width: 200px;
68 | height: 200px;
69 | font-size: 140px;
70 | opacity: 0.4;
71 | outline: 0;
72 |
73 | position: absolute;
74 | top: calc(50% - 50px);
75 | left: calc(50% - 100px);
76 | }
77 | button:hover {
78 | opacity: 0.8;
79 | }
80 | button:active {
81 | text-shadow: 0 0 30px rgba(255, 255, 255, 0.8);
82 | }
83 | .active header > p, .active button {
84 | display: none;
85 | }
86 |
--------------------------------------------------------------------------------
/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Audio Socket Visualisation
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
16 |
21 |
22 |
25 |
26 |
122 |
123 |