Skip to content

Instantly share code, notes, and snippets.

@abeppu
Last active February 6, 2021 19:06
Show Gist options
  • Save abeppu/6958565 to your computer and use it in GitHub Desktop.
Save abeppu/6958565 to your computer and use it in GitHub Desktop.
Implementation of @FeelBetterBot
var Twit = require("twit");
var config = require('./oauthconfig');
console.log("config:");
console.log(config);
var T = new Twit({
consumer_key: config.consumer_key,
consumer_secret: config.consumer_secret,
access_token: config.access_token,
access_token_secret: config.access_token_secret
});
var cb = function(err, reply) {
if(err){
console.log(err);
}
}
/** Actual message logic **/
// TODO : think of more things to put here, possibly balance out all the "Feel better!"
var feelBetter = "Feel better!";
var worthwhile = "You are a valuable, worthwhile human being!";
var mmap = { "i need a hug" : "*hug*",
"i hate myself" : "You deserve to love yourself!",
"makes me feel worthless" : worthwhile,
"i'm worthless" : worthwhile,
"i'm so worthless" : worthwhile,
"i feel worthless" : worthwhile,
"i feel like crap" : feelBetter,
"i feel like shit" : feelBetter,
"i feel crappy" : feelBetter,
"i feel shitty" : feelBetter,
"i feel terrible" : feelBetter,
"i feel horrible" : feelBetter };
function streamFilterTrack() {
var trackparts = [];
for(var key in mmap){
trackparts.push(key);
}
return trackparts.join(",");
}
function millis() {
return (new Date()).valueOf();
}
var minTimeNextTweet = millis();
var mean = 45 * 60 * 1000; // 45 minutes in millis
function gammaDraw(shape, scale){
// parameterized such that shape * scale = mean
// shape must be an integer ( TODO : allow shape to be double > 0)
var x = 0;
// sum k draws from gamma(1,1) = exp(1)
for(var i=0;i<shape;i++){
x = x - Math.log(Math.random());
}
// scale to beta
return scale * x;
}
function waitTime() {
var shape = 15; // peaky curve, not like an exponential
var minWait = 5 * 60 * 1000; // always wait at least 5 minutes
return minWait + gammaDraw(shape, (mean - minWait)/ shape);
}
var isGood = function(tweet) {
return ( // should not be retweet
! tweet.retweeted_status &&
// should not be directed at other specific users
! tweet.entities.user_mentions.length > 0);
}
var maybeResponse = function(tweettext) {
var lower = tweettext.toLowerCase();
for(var key in mmap) {
// if our phrase is in text, return associated response
if(lower.indexOf(key) >= 0) {
return mmap[key];
}
}
return false;
}
function log(prefix){
return function(msg){
console.log(prefix);
};
}
var stream;
function setupStream(){
stream = T.stream("statuses/filter", {track : streamFilterTrack()});
stream.on('warning', log("warning"));
stream.on('reconnect', log("reconnect"));
stream.on('disconnect', function(msg){
stream = setupStream();
stream.start();
});
stream.on("tweet", function (tweet) {
if( isGood(tweet) ) {
var response = maybeResponse(tweet.text);
var now = millis();
if( response && (now > minTimeNextTweet)) {
var wait = waitTime();
console.log( "next tweet in " + wait / (60 * 1000) + " minutes");
minTimeNextTweet = millis() + wait;
var replyToId = tweet.id_str;
var userName = tweet.user.screen_name;
var reply = { status : "@"+ userName+ " "+response,
in_reply_to_status_id : replyToId};
console.log(reply);
T.post("statuses/update", reply, cb);
}
}
});
return stream;
}
stream = setupStream();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment