Browse Source

Add documentation.md for rendering in modal;

Implement functions for start/stop typing;
Add parameter to decide if messages should be saved after sending a botMessage;
Add birbmemes, animememes & codingmemes to message-reactions;
React to "meme" & "memes";
Add backupAnswer if no reaction is found;
Rename occurrences of "vue = this" to "Kara = this";
Implement lyrics command & max message height with scrolling;
master
Nero Ignis 5 years ago
parent
commit
2f020f2f62
  1. 158
      app.js
  2. 74
      documentation.md
  3. 31
      index.html

158
app.js

@ -55,7 +55,7 @@ let kara = new Vue({ @@ -55,7 +55,7 @@ let kara = new Vue({
this.askForName();
}
this.isTyping = false;
this.stopTyping();
} else {
this.welcomeBack();
}
@ -74,7 +74,8 @@ let kara = new Vue({ @@ -74,7 +74,8 @@ let kara = new Vue({
"Hi! I'm " + this.name + ". :)",
"Hi, nice to meet you! My name is " + this.name + ". :)"
]
)
),
false
);
},
welcomeBack() {
@ -85,7 +86,8 @@ let kara = new Vue({ @@ -85,7 +86,8 @@ let kara = new Vue({
"Welcome back! :)",
"Hey :) Good to see you :)",
]
)
),
false
);
},
@ -97,7 +99,8 @@ let kara = new Vue({ @@ -97,7 +99,8 @@ let kara = new Vue({
'Whats your name? :)',
'How can i call you?',
'How did your developers call you? :)'
])
]),
false
);
this.askedForName = true;
@ -114,8 +117,6 @@ let kara = new Vue({ @@ -114,8 +117,6 @@ let kara = new Vue({
"Nice to meet you, " + this.username + ". :D"
])
)
this.updateStorage();
},
// Messages / Chat
@ -142,14 +143,21 @@ let kara = new Vue({ @@ -142,14 +143,21 @@ let kara = new Vue({
this.scrollDown();
}, 1000);
this.stopTyping();
this.updateStorage();
},
botMessage(message) {
botMessage(message, save = true) {
this.addMessage(message, true);
if (this.talk) {
this.say(message);
}
this.stopTyping();
if (save) {
this.updateStorage();
}
},
userMessage(body) {
this.addMessage(body, false);
@ -174,13 +182,11 @@ let kara = new Vue({ @@ -174,13 +182,11 @@ let kara = new Vue({
this.react(message, true);
},
react(message, recursive = false) {
this.isTyping = true;
this.startTyping();
if (message.search('/') === 0 && !recursive) {
setTimeout(() => {
this.processCommands(message);
this.isTyping = false;
this.scrollDown();
}, 1000);
} else {
@ -199,7 +205,6 @@ let kara = new Vue({ @@ -199,7 +205,6 @@ let kara = new Vue({
this.updateStorage();
}
this.isTyping = false;
this.scrollDown();
}, 1800);
}
@ -315,7 +320,7 @@ let kara = new Vue({ @@ -315,7 +320,7 @@ let kara = new Vue({
}
if (this.includesAllOf(keywords, ['weather']) &&
this.includesOneOf(keywords, ['how', 'whats'])
this.includesOneOf(keywords, ['how','hows', 'what', 'whats'])
) {
this.checkWeather();
return false;
@ -331,22 +336,18 @@ let kara = new Vue({ @@ -331,22 +336,18 @@ let kara = new Vue({
return false;
}
if (this.includesAllOf(keywords, ['cat']) &&
this.includesOneOf(keywords, ['images', 'photos', 'send'])
) {
this.getRandomCat();
if (this.includesAllOf(keywords, ['birb', 'meme'])) {
this.getRandomMeme('birbmemes');
return false;
}
if (this.includesOneOf(keywords, ['doggo', 'dog', 'shiba']) &&
this.includesOneOf(keywords, ['images', 'photos', 'send'])
) {
this.getRandomShiba();
if (this.includesAllOf(keywords, ['anime', 'meme'])) {
this.getRandomMeme('animememes');
return false;
}
if (this.includesAllOf(keywords, ['dank', 'meme'])) {
this.getRandomMeme('dankmemes')
if (this.includesAllOf(keywords, ['coding', 'meme'])) {
this.getRandomMeme('codingmemes');
return false;
}
@ -403,7 +404,7 @@ let kara = new Vue({ @@ -403,7 +404,7 @@ let kara = new Vue({
return answer;
}
this.botMessage("I don't know what to say..");
this.rsaBackupAnswer(message);
},
// Forms
@ -413,7 +414,6 @@ let kara = new Vue({ @@ -413,7 +414,6 @@ let kara = new Vue({
this.location = this.settingsModal.location;
this.updateStorage();
// this.botMessage('Settings saved! :)');
this.scrollDown();
},
@ -506,7 +506,7 @@ let kara = new Vue({ @@ -506,7 +506,7 @@ let kara = new Vue({
if (commandFound) {
return;
}
let commandString = '/' + command;
let commandString = '/' + command.toLowerCase();
if (message.search(commandString) === 0) {
parameter = message.replace(commandString, '').trim();
@ -517,10 +517,10 @@ let kara = new Vue({ @@ -517,10 +517,10 @@ let kara = new Vue({
return parameter ? parameter : commandFound;
},
checkWeather() {
let vue = this;
let Kara = this;
if (!vue.location) {
vue.botMessage('Please set your location in the settings. ⚙');
if (!Kara.location) {
Kara.botMessage('Please set your location in the settings. ⚙');
return;
}
@ -529,17 +529,17 @@ let kara = new Vue({ @@ -529,17 +529,17 @@ let kara = new Vue({
axios.get(url)
.then(function (response) {
vue.botMessage('In ' + response.data.name + ' it\'s ' + response.data.main.temp.toFixed() + '°C with ' + response.data.weather[0].description + '.');
Kara.botMessage('In ' + response.data.name + ' it\'s ' + response.data.main.temp.toFixed() + '°C with ' + response.data.weather[0].description + '.');
})
.catch(function (error) {
alertify.notify(error, 'danger');
vue.botMessage('I couldn\'t check the weather for your location. 🤔');
Kara.botMessage('I couldn\'t check the weather for your location. 🤔');
})
this.updateStorage();
},
getRandomMeme(category = 'memes') {
let vue = this;
let Kara = this;
let url = 'https://meme-api.herokuapp.com/gimme/';
let categorySet = false;
@ -553,24 +553,24 @@ let kara = new Vue({ @@ -553,24 +553,24 @@ let kara = new Vue({
axios.get(url + category)
.then(function (response) {
vue.addImageMessage({
Kara.addImageMessage({
body: response.data.title,
src: response.data.url
}, true);
vue.lastMessageData = {
Kara.lastMessageData = {
meme: true,
category: category
};
})
.catch(function (error) {
vue.botMessage("Hmm.. i can't think of any good memes right now, sorry.. 😞");
Kara.botMessage("Hmm.. i can't think of any good memes right now, sorry.. 😞");
})
this.updateStorage();
},
tellJoke(category) {
let vue = this;
let Kara = this;
let categorySet = false;
if (category !== true && category !== false) {
@ -586,14 +586,14 @@ let kara = new Vue({ @@ -586,14 +586,14 @@ let kara = new Vue({
.then(function (response) {
let joke = response.data[0];
vue.botMessage(joke.setup);
Kara.botMessage(joke.setup);
setTimeout(() => {
vue.botMessage(joke.punchline);
vue.scrollDown();
Kara.botMessage(joke.punchline);
Kara.scrollDown();
}, 3500);
vue.lastMessageData = {
Kara.lastMessageData = {
joke: true,
category: category
};
@ -602,54 +602,54 @@ let kara = new Vue({ @@ -602,54 +602,54 @@ let kara = new Vue({
console.log(error);
if (categorySet) {
vue.botMessage("Sorry, i don't know any jokes about this topic.. 🙄");
Kara.botMessage("Sorry, i don't know any jokes about this topic.. 🙄");
} else {
vue.botMessage("I can't remember any jokes right now, sorry. 😢");
Kara.botMessage("I can't remember any jokes right now, sorry. 😢");
}
});
this.updateStorage();
},
startQuiz() {
let vue = this;
let Kara = this;
let url = 'https://jservice.io/api/random';
axios.get(url)
.then(function (response) {
let clue = response.data[0];
vue.botMessage('Okay! Here is your question from the category "' + clue.category.title + '":');
vue.botMessage(clue.question);
Kara.botMessage('Okay! Here is your question from the category "' + clue.category.title + '":');
Kara.botMessage(clue.question);
vue.lastMessageData = {
Kara.lastMessageData = {
isTrivia: true,
answer: clue.answer
};
})
.catch(function (error) {
vue.botMessage("It's not a good time for a quiz.");
Kara.botMessage("It's not a good time for a quiz.");
});
this.updateStorage();
},
startJeopardy() {
let vue = this;
let Kara = this;
let url = 'https://jservice.io/api/random';
axios.get(url)
.then(function (response) {
let clue = response.data[0];
vue.botMessage('Okay! Here we go. The category is "' + clue.category.title + '":');
vue.botMessage(clue.answer);
Kara.botMessage('Okay! Here we go. The category is "' + clue.category.title + '":');
Kara.botMessage(clue.answer);
vue.lastMessageData = {
Kara.lastMessageData = {
isJeopardy: true,
question: clue.question
};
})
.catch(function (error) {
vue.botMessage("It's not a good time for a quiz.");
Kara.botMessage("It's not a good time for a quiz.");
});
this.updateStorage();
@ -704,53 +704,74 @@ let kara = new Vue({ @@ -704,53 +704,74 @@ let kara = new Vue({
// Some Random API Commands
rsaRandomAnimalImage(animal, emoji = '😄') {
let vue = this;
let Kara = this;
Kara.startTyping();
axios.post('/api/curlJson', {
url: 'https://some-random-api.ml/img/' + animal
})
.catch((error) => {
vue.botMessage("Sorry, i can't find any good pictures right now 🙁" + emoji);
Kara.botMessage("Sorry, i can't find any good pictures right now 🙁" + emoji);
})
.then((response) => {
vue.addImageMessage({
Kara.addImageMessage({
body: emoji,
src: response.data.link
}, true);
})
},
rsaRandomAnimalFact(animal, emoji = '😄') {
let vue = this;
let Kara = this;
Kara.startTyping();
axios.post('/api/curlJson', {
url: 'https://some-random-api.ml/facts/' + animal
})
.catch((error) => {
vue.botMessage("Sorry, i can't think of any good facts right now 🙁" + emoji);
Kara.botMessage("Sorry, i can't think of any good facts right now 🙁" + emoji);
})
.then((response) => {
vue.botMessage(response.data.fact);
Kara.botMessage(response.data.fact);
})
},
rsaLyrics(searchFor) {
let vue = this;
let Kara = this;
Kara.startTyping();
axios.post('/api/curlJson', {
url: 'https://some-random-api.ml/lyrics/?title=' + searchFor.replace(' ', '%20')
})
.catch((error) => {
vue.botMessage("Hmm.. i just can't remember the lyrics, but i love that song! 🎵🎧");
Kara.botMessage("Hmm.. i just can't remember the lyrics, but i love that song! 🎵🎧");
})
.then((response) => {
vue.addImageMessage({
Kara.addImageMessage({
body: "Here you go!<br>" +
"<br>" +
response.data.title + ' from ' + response.data.author + '<br>' +
'<br>' +
response.data.lyrics,
src: response.data.thumbnail.genius
});
}, true);
})
},
rsaBackupAnswer(message) {
let Kara = this;
Kara.startTyping();
axios.post('/api/curlJson', {
url: 'https://some-random-api.ml/chatbot?message=' + message
})
.catch((error) => {
Kara.botMessage("I don't know what to say..");
})
.then((response) => {
Kara.botMessage(response.data.response);
});
},
// LocalStorage
@ -800,6 +821,13 @@ let kara = new Vue({ @@ -800,6 +821,13 @@ let kara = new Vue({
scrollTop: ($('#chat-box')[0].scrollHeight * 10)
}, 800);
},
startTyping() {
this.isTyping = true;
},
stopTyping() {
this.scrollDown();
this.isTyping = false;
},
oneOf(answers) {
let amountOfAnswers = answers.length;
let randomIndex = Math.floor(Math.random() * (amountOfAnswers));
@ -876,22 +904,22 @@ let kara = new Vue({ @@ -876,22 +904,22 @@ let kara = new Vue({
// Ajax calls for saving/receiving reactions & themes
getBootswatchThemes() {
let vue = this;
let Kara = this;
axios.get('https://bootswatch.com/api/4.json')
.then(function (response) {
vue.themes = response.data.themes;
Kara.themes = response.data.themes;
})
.catch(function (error) {
console.log(error);
})
},
getReactions() {
let vue = this;
let Kara = this;
axios.get('/reactions/get').then((response) => {
response.data.forEach((reaction) => {
vue.reactions.push(JSON.parse(reaction.reaction));
Kara.reactions.push(JSON.parse(reaction.reaction));
});
}).catch((error) => {
console.log(error);

74
documentation.md

@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
#### Commands
##### ```/clear```
Clears the chat.
##### ```/say```
Repeats your message.
##### ```/todo```
Adds a new todo to the list.\
Todos can be viewed by clicking on the clipboard-icon in the upper right.
##### ```/weather```
Tells you the weather in your location.\
Your location can be set in the settings.\
\
Can be triggered by messages like:
- _How is the weather?_
##### ```/joke```
Tells a joke with an opener and a delayed punchline.\
Categories are: general (default), knock-knock, programming
\
Can be triggered by messages like:
- _Tell me a joke_
- _Tell me a knock knock joke_
- _Tell me a programming joke_
##### ```/meme```
Sends a random meme from reddit.\
You can pass a subreddit of your choice (Yes, NSFW too..)
\
Some predefined meme-categories can be triggerd by:
- _Send me a coding meme_
- _Send me a dank meme_
- _Send me a birb meme_
##### ```/me```
Sends a classical "_User farted_" message.
##### Animal images & facts
There are a number of commands to receive random animal images & facts.\
Animals:\
_birb, dog, cat, fox, panda, red_panda & koala_
To get a fact or an image, use:
```/youranimalImg``` or ```/youranimalFact```
##### ```/lyrics```
Fetch lyrics for songs.\
Usage: ```/lyrics songname``` (you can also search for things like ```songname artist```)
##### ```/quiz```
Get a quiz-question and guess the answer.\
You can always give up by typing "i give up".
##### ```/jeopardy```
The opposite of ```/quiz```.\
Guess the right question to the given answer.
##### ```/dice```
Roll the dice!
---
#### Experimental
##### ```/talk```
Activate talking. Kara will now talk to you.\
The voice-language heavily depends on the device used.

31
index.html

@ -22,6 +22,9 @@ @@ -22,6 +22,9 @@
<div class="btn btn-sm btn-secondary" data-toggle="modal" data-target="#settingsModal">
<i class="fas fa-sliders-h"></i>
</div>
<div class="btn btn-sm btn-secondary" data-toggle="modal" data-target="#helpModal">
<i class="fas fa-question-circle"></i>
</div>
<div class="btn btn-sm btn-secondary" data-toggle="modal" data-target="#todoModal" v-if="todos.length > 0">
<i class="fas fa-clipboard"></i>
</div>
@ -157,6 +160,34 @@ @@ -157,6 +160,34 @@
</div>
</div>
</div>
<div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModal" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Documentation</h5>
</div>
<div class="modal-body">
<h6>Commands</h6>
<ul>
<li>/clear</li>
<li>/meme </li>
<li>/say </li>
<li>/joke</li>
<li>/weather</li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<hr/>
<h6></h6>
</div>
</div>
</div>
</div>
<link rel="stylesheet" :href="'https://maxcdn.bootstrapcdn.com/bootswatch/4.3.1/' + activeTheme + '/bootstrap.min.css'">
<link href="app.css" rel="stylesheet" type="text/css"/>
</div>

Loading…
Cancel
Save