├── .gitignore
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── src
├── App.js
├── alert.svg
├── assistant.js
├── favicon.ico
├── index.css
├── index.js
├── logo.svg
└── skills
│ ├── time.js
│ └── whatsup.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 |
6 | # production
7 | build
8 |
9 | # misc
10 | .DS_Store
11 | npm-debug.log
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Basic code for RobinJS
2 |
3 | The code in this repository is the result of the tutorial - [How to write a modular Alexa clone in 40 lines of code](https://medium.com/@Jense5_/how-to-write-a-modular-alexa-clone-in-40-lines-of-javascript-12bb290f34eb).
4 |
5 | A preview is [also available](https://robinjs.party). Have fun!
6 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | RobinJS
8 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "robinjs-preact-website",
3 | "version": "0.1.0",
4 | "private": true,
5 | "devDependencies": {
6 | "preact-scripts": "0.3.0-alpha",
7 | "react-test-renderer": "^15.3.0",
8 | "surge": "^0.20.1"
9 | },
10 | "dependencies": {
11 | "detect-browser": "^2.1.0",
12 | "preact": "^5.6.0"
13 | },
14 | "scripts": {
15 | "start": "preact-scripts start",
16 | "build": "preact-scripts build",
17 | "eject": "preact-scripts eject",
18 | "test": "preact-scripts test"
19 | },
20 | "eslintConfig": {
21 | "extends": "./node_modules/preact-scripts/config/eslint.js"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import { h, Component } from 'preact';
2 | import { detect } from 'detect-browser';
3 | import logo from './logo.svg';
4 | import alert from './alert.svg';
5 |
6 | const browser = detect();
7 |
8 | class App extends Component {
9 | render() {
10 | const icon = (!browser || browser.name !== 'chrome') ? alert : logo;
11 | return (
12 |
13 |
14 |
15 |
16 | { (!browser || browser.name !== 'chrome')
17 | ? 'Uh - Oh'
18 | : 'Hi, I am Robin!'
19 | }
20 |
21 |
22 | { (!browser || browser.name !== 'chrome')
23 | ? 'You need Chrome to use this website!'
24 | : 'Start your sentence with "Robin", and I will reply.'
25 | }
26 |
27 |
28 |
29 | );
30 | }
31 | }
32 |
33 | export default App;
34 |
--------------------------------------------------------------------------------
/src/alert.svg:
--------------------------------------------------------------------------------
1 | alert
--------------------------------------------------------------------------------
/src/assistant.js:
--------------------------------------------------------------------------------
1 | const defaults = {
2 | skills: [],
3 | name: 'Robin',
4 | language: 'en-US',
5 | reply: "Sorry, I don't know that one.",
6 | };
7 |
8 | export default class Assistant {
9 | constructor(config = {}) {
10 | this.config = { ...defaults, ...config };
11 | // eslint-disable-next-line
12 | this.recognizer = new webkitSpeechRecognition();
13 | this.recognizer.lang = this.config.language;
14 | this.recognizer.addEventListener('end', () => {
15 | this.recognizer.start();
16 | });
17 | this.recognizer.addEventListener('result', (instance) => {
18 | const transcript = Array.from(instance.results)
19 | .map(result => result[0])
20 | .map(result => result.transcript)
21 | .map(str => str.toLowerCase())[0];
22 | const words = transcript.split(' ');
23 | if (words[0] === this.config.name.toLocaleLowerCase()) {
24 | this.process(words.slice(1).join(' '));
25 | }
26 | });
27 | }
28 | start() {
29 | this.recognizer.start();
30 | }
31 | process(sentence) {
32 | for (const skill of this.config.skills)
33 | if (skill.trigger(sentence))
34 | return skill.resolve(sentence).then(s => this.say(s));
35 | return this.say(this.config.reply);
36 | }
37 | say(sentence) {
38 | const filtered = sentence.replace(/[&\/\\#,+()$~%.'"*?<>{}]/g, '');
39 | const msg = new SpeechSynthesisUtterance(filtered);
40 | window.speechSynthesis.speak(msg);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jense5/robinjs-website/091bc229c3057228f16a5240c215d03e73bd9b68/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Lato');
2 |
3 | html, body, #root {
4 | margin: 0;
5 | padding: 0;
6 | height: 100%;
7 | font-family: 'Lato', sans-serif;
8 | }
9 |
10 | .App {
11 | text-align: center;
12 | height: 100%;
13 | display: flex;
14 | justify-content: center;
15 | align-items: center;
16 | flex-direction: row;
17 | }
18 |
19 | .App-logo {
20 | height: 200px;
21 | }
22 |
23 | .Subtitle {
24 | font-style: italic;
25 | }
26 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { h, render } from 'preact';
2 | import { detect } from 'detect-browser';
3 | import App from './App';
4 | import Assistant from './assistant';
5 | import './index.css';
6 |
7 | const browser = detect();
8 |
9 | if (browser && browser.name === 'chrome') {
10 | const assistant = new Assistant({
11 | skills: [
12 | require('./skills/time'),
13 | require('./skills/whatsup'),
14 | ],
15 | });
16 | assistant.start();
17 | }
18 |
19 | render(
20 | ,
21 | document.getElementById('root')
22 | );
23 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 | active support
--------------------------------------------------------------------------------
/src/skills/time.js:
--------------------------------------------------------------------------------
1 | module.exports.trigger = (sen) => (sen === 'what time is it');
2 | module.exports.resolve = () => new Promise((resolve) => {
3 | const now = new Date();
4 | const minutes = now.getMinutes() > 0 ? ':' + now.getMinutes() : '';
5 | resolve(`It is ${now.getHours()}${minutes}.`);
6 | });
7 |
--------------------------------------------------------------------------------
/src/skills/whatsup.js:
--------------------------------------------------------------------------------
1 | module.exports.trigger = (sen) => (sen === 'how are you');
2 | module.exports.resolve = () => new Promise((resolve) => {
3 | resolve("I'm good, how about you?'");
4 | });
5 |
--------------------------------------------------------------------------------