Keyword Count


#1

Hi all,
I was looking for a way to show the keyword use frequency count in the response.
And, I wanted it to behave like how (count) works in commands.

For example,
Command: !hello
Response: @(pointtouser) Hello! [+(count)]
Usage:

StinkingBanana: !hello
Bot: @StinkingBanana Hello! [+1234]

Instead of using commands, I wanted it to work using keywords

For example,
Keywowrd: ^[hH]ello.*
Regex: On
Response: What's up? [+(count)]
Usage:

StinkingBanana: Hello my friend :D
Bot: What's up?  [+1234]

I looked into wordcounter, but it does not work like the way I wanted or I just could not figure it out.
So anyway, I decided to make my own.

The result will give you the following features:

  1. The keywords web panel will show Count, Keyword, and Response
    and three buttons on the left for each keyword:
  • [+] button: to add count by 1
  • [-] button: to decrease count by 1
  • [reset] button: to reset count to 0
  1. When you try to add keyword in the kewords web panel, the keywords modal will have one extra input field allowing you to set the initial count for the keyword.

  2. When you try to edit keyword in the kewords web panel, the keywords modal will have one extra input field allowing you to set the count for the keyword.

  3. You can use (keywordcount) in the keyword response to show count.

I will show you how I did it.
[!] BEFORE YOU BEGIN, PLEASE BE SURE TO MAKE A COMPLETE BACKUP OF YOUR BOT

You will need to modify 4 files.

1.scripts\commands\customCommands.js


Add the following code block

if (message.match(/\(keywordcount\s(.+)\)/g)) {
    var input_keyword = message.match(/\(keywordcount\s(.+)\)/)[1];
    var keyword_info = JSON.parse($.inidb.get('keywords', input_keyword));

    if('count' in keyword_info){
        ++keyword_info["count"];
    }
    else{
        keyword_info["count"] = 1;
    }
    $.inidb.set('keywords', input_keyword, JSON.stringify(keyword_info));
    
    message = $.replace(message, message.match(/\(keywordcount\s(.+)\)/)[0], keyword_info["count"]);
}

after line 201~204

if (message.match(/\(count\)/g)) {
    $.inidb.incr('commandCount', event.getCommand(), 1);
    message = $.replace(message, '(count)', $.inidb.get('commandCount', event.getCommand()));
}

2.scripts\handlers\keywordHandler.js


Add the following code in 2 places

json.response = $.replace(json.response, '(keywordcount)', '(keywordcount ' + json.keyword + ')');

right before each

$.say($.tags(event, json.response, false));

3.web\panel\js\keywordsPanel.js


Find the following code

var spinIcon = '<i style="color: var(--main-color)" class="fa fa-spinner fa-spin" />',
    keywords = [],
    cooldowns = [],
    currentKey = '';

Change to

var spinIcon = '<i style="color: var(--main-color)" class="fa fa-spinner fa-spin" />',
    keywords = [],
    responses = [],
    counts = [],
    isRegexs = [],
    cooldowns = [],
    currentKey = '';

Find the following code

html = '<table style="width: 100%"><tr><th>Keyword</th><th>Response</th><th style="float: right;"></td>';
for (idx in msgObject['results'].sort(sortKeywordsTable)) {
    var json = JSON.parse(msgObject['results'][idx]['value']),
        keyword = json.keyword;
        response = json.response;

    keywords[idx] = keyword;
    html += '<tr>' +
        '<td>' + (keyword.length > 15 ?  keyword.substring(0, 15) + '...' : keyword) + '</td>' +
        '<td>' + (response.length > 45 ?  response.substring(0, 45) + '...' : response) + '</td>' +
        '<td style="float: right;"><button type="button" class="btn btn-default btn-xs" onclick="$.editKeywordnew(\'' + keyword.replace(/\'/g, '__apos__').replace(/\\/g, '\\\\') + '\', \'' + response.replace(/\'/g, '__apos__').replace(/\\/g, '\\\\') + '\')"><i class="fa fa-edit" /> </button>' +
        '<button type="button" id="deleteKeyword_' + idx + '" class="btn btn-default btn-xs" onclick="$.deleteKeyword(\'' + idx + '\')"><i class="fa fa-trash" /> </button></td> ' +
        '</tr>';
}
html += '</table>';

Change to

html = '<table style="width: 100%"><tr><th></th><th></th><th></th><th>Count</th><th>Keyword</th><th>Response</th><th style="float: right;"></td>';
for (idx in msgObject['results'].sort(sortKeywordsTable)) {
    var json = JSON.parse(msgObject['results'][idx]['value']),
        keyword = json.keyword,
        response = json.response,
        isRegex = json.isRegex,
        count = json.count;

    keywords[idx] = keyword;
    responses[idx] = response;
    counts[idx] = count;
    isRegexs[idx] = isRegex;

    html += '<tr>' +
        '<td><button type="button" id="incrKeywordCount_' + idx + '" class="btn btn-default btn-xs" onclick="$.incrKeywordCount(\'' + idx + '\')"><i class="fa fa-plus" /> </button></td>' +
        '<td><button type="button" id="decrKeywordCount_' + idx + '" class="btn btn-default btn-xs" onclick="$.decrKeywordCount(\'' + idx + '\')"><i class="fa fa-minus" /> </button></td>' +
        '<td><button type="button" id="resetKeywordCount_' + idx + '" class="btn btn-default btn-xs" onclick="$.resetKeywordCount(\'' + idx + '\')"><i class="fa fa-undo" /> </button></td>' +
        '<td>' + (count == undefined ? 0 : count) + '</td>' +
        '<td>' + (keyword.length > 15 ?  keyword.substring(0, 15) + '...' : keyword) + '</td>' +
        '<td>' + (response.length > 45 ?  response.substring(0, 45) + '...' : response) + '</td>' +
        '<td style="float: right;"><button type="button" class="btn btn-default btn-xs" onclick="$.editKeywordnew(\'' + idx + '\')"><i class="fa fa-edit" /> </button>' +
        '<button type="button" id="deleteKeyword_' + idx + '" class="btn btn-default btn-xs" onclick="$.deleteKeyword(\'' + idx + '\')"><i class="fa fa-trash" /> </button></td> ' +
        '</tr>';
}
html += '</table>';

Overwrite the function doQuery to

function doQuery() {
    keywords = [];
    responses = [];
    counts = [];
    isRegexs = [];
    cooldowns = [];

    sendDBKeys('keywords_cooldown', 'coolkey');
}

Add the following code in the function addKeywordnew()

$('#keyword-count').val('0');

after

$('#keyword-cooldown').val('5');

Add the following after the function addKeywordnew

/**
    * @function incrKeywordCount
    * @param {String} idx
    */
function incrKeywordCount(idx) {
    $('#incrKeywordCount_' + idx).html(spinIcon);
    setTimeout(function() {
        sendDBUpdate('keywords_incrKeywordCount', 'keywords', keywords[idx], JSON.stringify({
            keyword: keywords[idx],
            response: responses[idx],
            isRegex: isRegexs[idx],
            count: +counts[idx]+1
        }));
    }, TIMEOUT_WAIT_TIME);
    setTimeout(function() { doQuery(); sendWSEvent('keywords', './handlers/keywordHandler.js', null, []); }, TIMEOUT_WAIT_TIME * 2);
}

/**
    * @function decrKeywordCount
    * @param {String} idx
    */
function decrKeywordCount(idx) {
    $('#decrKeywordCount_' + idx).html(spinIcon);
    setTimeout(function() {
        sendDBUpdate('keywords_decrKeywordCount', 'keywords', keywords[idx], JSON.stringify({
            keyword: keywords[idx],
            response: responses[idx],
            isRegex: isRegexs[idx],
            count: (counts[idx]-1 < 0 ? 0 : counts[idx]-1)
        }));
    }, TIMEOUT_WAIT_TIME);
    setTimeout(function() { doQuery(); sendWSEvent('keywords', './handlers/keywordHandler.js', null, []); }, TIMEOUT_WAIT_TIME * 2);
}

/**
    * @function resetKeywordCount
    * @param {String} idx
    */
function resetKeywordCount(idx) {
    $('#resetKeywordCount_' + idx).html(spinIcon);
    setTimeout(function() {
        sendDBUpdate('keywords_resetKeywordCount', 'keywords', keywords[idx], JSON.stringify({
            keyword: keywords[idx],
            response: responses[idx],
            isRegex: isRegexs[idx],
            count: 0
        }));
    }, TIMEOUT_WAIT_TIME);
    setTimeout(function() { doQuery(); sendWSEvent('keywords', './handlers/keywordHandler.js', null, []); }, TIMEOUT_WAIT_TIME * 2);
}

Overwrite the function updateKeyword to

function updateKeyword() {
    var keyword = $('#keyword-name').val(),
        response = $('#keyword-response').val(),
        isRegex = $('#keyword-regex').is(':checked'),
        count = parseInt($('#keyword-count').val()),
        cooldown = parseInt($('#keyword-cooldown').val());

    if (cooldown < 5) {
        cooldown = String(5);
    } else {
        cooldown = String(cooldown);
    }

    if (count < 0) {
        count = String(0);
    } else {
        count = String(count);
    }

    if (response.length < 1 || keyword.length < 1) {
        return;
    }

    sendDBDelete('keyword_rm', 'keywords', currentKey);
    setTimeout(function() {
        sendDBUpdate('keyword_update', 'keywords', (isRegex ? 'regex:' : '') + keyword, JSON.stringify({
            keyword: (isRegex ? 'regex:' : '') + keyword,
            response: response,
            isRegex: isRegex,
            count: count
        }));
        sendDBUpdate('keyword_cooldown_up', 'coolkey', (isRegex ? 'regex:' : '') + keyword, cooldown);
    }, TIMEOUT_WAIT_TIME);
    setTimeout(function() { doQuery(); sendWSEvent('keywords', './handlers/keywordHandler.js', null, []); }, TIMEOUT_WAIT_TIME * 2);
}

Overwrite the function editKeyword to

function editKeywordnew(idx) {
    $('#keyword-modal-title').html('Edit Keyword');

    currentKey = keywords[idx];
    
    $('#keyword-name').val(keywords[idx].replace('regex:', ''));
    $('#keyword-response').val(responses[idx]);
    $('#keyword-cooldown').val(isNaN(parseInt(cooldowns[idx])) ? 5 : cooldowns[idx]);
    $('#keyword-count').val(isNaN(parseInt(counts[idx])) ? 0 : counts[idx]);
    $('#keyword-regex').prop('checked', isRegexs[idx]);
    $('#keyword-modal').modal('toggle');
}

Add the following codes

$.incrKeywordCount = incrKeywordCount;
$.decrKeywordCount = decrKeywordCount;
$.resetKeywordCount = resetKeywordCount;

after

$.updateKeyword = updateKeyword;

4.web\panel\keywords.html

Add the following codes

<lable><b>Count</b></lable>
<div class="form-group" onkeypress="return event.keyCode != 13">
    <input id="keyword-count" type="number" min="0" class="form-control" placeholder="Count" data-toggle="tooltip" 
    title="Count" />
</div>

after

<lable><b>Cooldown</b></lable>
<div class="form-group" onkeypress="return event.keyCode != 13">
    <input id="keyword-cooldown" type="number" min="5" max="0" class="form-control" placeholder="Coodlown" data-toggle="tooltip" 
    title="Cooldown of the keyword. Minimum is five seconds." />
</div>

[!] Tutorial complete. Restart your bot, and you are done :smiley:
Be sure to use (keywordcount) in your response, so the count gets increased.
Or you could manually edit the count in the keyword panel.

Final Note:
If anything does not work, please post below and give me as many details as possible. So, I could help as much as possible.

Edit:
I have created a PR @ https://github.com/PhantomBot/PhantomBot/pull/1909


#2

just a question…why dont you make a pull request for this on the main github?


#3

Edit3:

Hi, Alixe

I have created a PR @ https://github.com/PhantomBot/PhantomBot/pull/1909
Thank you.