alaingilbert / Turntable-API

Allows you to create bots for turntable.fm
http://alaingilbert.github.com/Turntable-API/
MIT License
318 stars 97 forks source link

Private Message Functions #192

Closed ghost closed 11 years ago

ghost commented 11 years ago

Everyone in the Christian Anything room on Turntable.fm want my bot to have Private Message functions and I do not know how to code it so can you guys, please help me.

alaingilbert commented 11 years ago

Go there : https://github.com/alaingilbert/Turntable-API

ctrl+F (search) : private message

ghost commented 11 years ago

Thanks for the small tip, it only helps a little bit.

alaingilbert commented 11 years ago

What you do not understand exactly ?! The documentation is pretty clear, when you receive a pmmed signal, you received a private message. If you want to send a private message, you have to do something like bot.pm(MSG, RECEIVER_ID)...

ghost commented 11 years ago

yeah, but doesn't the bot need to know the sender id of the person who sent him the message.

alaingilbert commented 11 years ago

If you read the doc, and if you click on the data (in the "pmmed" signal documentation) https://github.com/alaingilbert/Turntable-API/blob/master/turntable_data/pmmed.js This is the data that you receive. And as you can see, there is a senderid that you can use.

ghost commented 11 years ago

ok, do i need to code up something so that Cloud9 won't think that senderid is a undeclared value.

MikeWills commented 11 years ago

See https://github.com/MikeWills/Uglee/blob/master/functions.js#L19

ghost commented 11 years ago

ok, so what happens when I put this into my code

MikeWills commented 11 years ago

My link is an example get you on the right path. NOT copy-paste code. I also handle if a person can't get PMs like if they are on Android. So you can see an example of that (I am sure the next question you have after implementing PM). My method allows me to send to PM or chat depending on how the person talked to the bot.

ghost commented 11 years ago

ok, cool. Thank You.

technobly commented 11 years ago

@Turntablelover basically you need to make your commands modular first. One way would be to put them into a function, and then call that function from the bot.on('pmmed', function (data){ and bot.on('speak', function(data) {

You would pass the data.text and data.userid (or data.senderid if from PMMED) to that function.

ex.

bot.on('pmmed', function (data){
  run_commands(data.text.trim(), data.senderid, true);
});

bot.on('speak', function (data){
  run_commands(data.text.trim(), data.userid, false);
});

function run_commands(text, userid, frompm) {
  // parse commands here just like when you were in bot.on('speak' ...
  // variable frompm would be set true if you called this function from PM, 
  // so you know how to send data back to someone.  You would use
  // bot.pm vs. bot.speak potentially

}
ghost commented 11 years ago

got error message, in this location, this.ws.send("~m~" + msg.length + "~m~" + msg); TypeError: Cannot call method 'send' of undefined

Izzmo commented 11 years ago

WebSocket is undefined? Are you sure you are connected?

alaingilbert commented 11 years ago

I would say, are you sure you didn't repeat the same error as the other time (https://github.com/alaingilbert/Turntable-API/issues/180#issuecomment-17108865)

ghost commented 11 years ago

i think so, I tried looking for solutions through Google and it didn't help.

technobly commented 11 years ago

Let's see your code... minus your auth info

ghost commented 11 years ago
bot.on('speak', function (data) {
  // Get the data
  data.name;
  var text = data.text;

  // Respond to "/God" command
  if (text.match(/^\/God$/)) {
    bot.speak('God is bigger than the boogieman');
  }
});

bot.on('speak', function (data) {
  // Get the data
  data.name;
  var text = data.text;

  // Respond to "/Boaz" command
  if (text.match(/^\/Boaz$/)) {
    bot.speak('Even though he is my bot brother, Boaz is a lying liar');
  }
});

bot.on('speak', function (data) {
  // Get the data
  data.name;
  var text = data.text;

  // Respond to "/rules" command
  if (text.match(/^\/rules$/)) {
    bot.speak('Room Rules for Christian Anything are at http://goo.gl/ub4xz');
  }
});

bot.on('speak', function (data) {
  // Get the data
  data.name;
  var text = data.text;

  // Respond to "/love" command
  if (text.match(/^\/love$/)) {
    bot.speak('I love this room');
  }
});

bot.on('speak', function (data) {
  // Get the data
  data.name;
  var text = data.text;

  // Respond to "/Pi" command
  if (text.match(/^\/Pi$/)) {
    bot.speak('Pi=3.141592653589793238462643383279502884');
  }
});

//Checks if the user is a bot admin
global.IsAdmin = function (userid) {
  if ((userid) !== -1) {
    return true;
  } else {
    if (userid === '4e16f5414fe7d0665b0cacea') {
      return true;
    }
    return false;
  }

  //Checks if the user is a moderator
  global.IsMod = function (userid, callback) {
    bot.roomInfo(function (data) {
      var moderators = data.room.metadata.moderator_id;
      if ((userid)) {
        callback(true);
        return;
      }
      if (moderators.indexOf(userid) != -1) {
        callback(true);
        return;
      } else {
        callback(false);
        return;
      }
    });
  };

};

// Define default value for global variable 'isOn'
var isOn = true;

bot.on('speak', function (data) {
  var name = data.name;
  var text = data.text;

  //If the bot is ON
  if (isOn) {
    if (text.match(/^\/status$/)) {
      bot.speak('The bot is currently turned on.');
    }

    if (text.match(/^\/off$/)) {
      bot.speak('The bot is turned off.');
      // Set the status to off
      false;
    }

    // ADD other functions here for when the bot is turned on. Like, for example:
    // Respond to "/hello" command
    if (text.match(/^\/hello$/)) {
      bot.speak('Hey! How are you @' + name + ' ?');
    }
  }

  //If the bot is OFF
  if (!isOn) {
    if (text.match(/^\/status$/)) {
      bot.speak('The bot is currently turned off.');
    }

    if (text.match(/^\/on$/)) {
      bot.speak('The bot is turned now on.');
      // Set the status to on
      true;
    }

    // ADD other functions here for when the bot is turned off.
  }
});

bot.on('speak', function (data) {
  var text = data.text;
  if (text.match(/^\/go$/)) {
    // Bot gets on the DJ table (if there's a spot open) on /go command
    bot.addDj();
  }
  if (text.match(/^\/please stop$/)) {
    // Bot jumps off the table on /please stop command
    bot.remDj(USERID);
  }
  if (text.match(/^\/skip$/)) {
    // Bot skips it's own song (if bot is the current DJ) on /skip command
    bot.skip();
  }
  if (text.match(/^\/addsong$/)) {
    // Bot adds song to the bottom of it's DJ queue on /addsong command
    bot.playlistAll(function (data) {
      bot.playlistAdd(data.list.length);
    });
    bot.snag();
  }
});

bot.on('newsong', function (data) {
  bot.becomeFan(data.room.metadata.current_dj);
});

var snagIfNotInPlaylist = function () {
  bot.playlistAll(function (data) {
    var found = false;
    for (var i = 0; i < data.list.length; i++) {
      if (data.list[i]._id == bot.currentSongId) {
        found = true;
        break;
      }
    }
    if (!found) {
      bot.snag();
    }
  });
};

bot.on('registered', function (data) {
  for (var i = 0; i < data.user.length; ++i) {
    var user = data.user[i];
    if (user.name.match(/ttstats/i)) {
      bot.bootUser(user.userid, 'Beat it, bot!');
      console.log("[ BANNED ] : " + user.name + " " + user.userid);
    }
  }
});

bot.on('speak', function (data) {
  if (data.text.match(/VeggieBot/i)) {
    switch (Math.round(Math.random() * 2)) {
    case 0:
      bot.speak('Exterminate, Exterminate');
      break;
    case 1:
      bot.speak('This room is so cold');
      break;
    case 2:
      bot.speak('Always eat your vegetables');
      break;
    case 3:
      bot.speak('Oh, where is my hairbrush');
      break;
    case 4:
      bot.speak('You would make a good dalek');
      break;
    case 5:
      bot.speak('HELP! Boaz traded my cat for a new battery pack');
      break;
    case 6:
      bot.speak('Duty, honour, and good sauce');
      break;
    case 7:
      bot.speak('YOU... SHALL... NOT... PASS');
      break;
    case 8:
      bot.speak('Chase Mccain? YOUR A LEGEND!');
      break;
    case 9:
      bot.speak('I find your lack of faith disturbing');
      break;
    case 10:
      bot.speak('Go Green Ranger Go');
      break;
    case 11:
      bot.speak('You were that Flobbit? That Flobbit who bought everything mail order?');
      break;
    case 12:
      bot.speak('[evil face] We aint had nothing but maggoty bread for three stinking days [brightening up] Id love a cookie.');
    }
  }
});

var theUsersList = {};

bot.on('roomChanged', function (data) {
  // Reset the users list
  theUsersList = {};

  var users = data.users;
  for (var i = 0; i < users.length; i++) {
    var user = users[i];
    theUsersList[user.userid] = user;
  }
});

bot.on('registered', function (data) {
  var user = data.user[0];
  theUsersList[user.userid] = user;
});

bot.on('deregistered', function (data) {
  var user = data.user[0];
  delete theUsersList[user.userid];
});

bot.on('registered', function (data) {
  setTimeout(function () {
    bot.speak(data.user[0].name + ', welcome to christian anything! BoazV2, our main bot, will let you sign up for a DJ Spot.'); //send it in the chatbox
    bot.pm('welcome to christian anything!', data.user[0].userid); //send it in the pm

  }, 3 * 1000); //slow it down 3 seconds
});

bot.on('pmmed', function (data) {
  run_commands(data.text.trim(), data.senderid, true);
});

bot.on('speak', function (data) {
  run_commands(data.text.trim(), data.userid, false);
});

function run_commands(text, userid, frompm) {}
// parse commands here just like when you were in bot.on('speak' ...
// variable frompm would be set true if you called this function from PM, 
// so you know how to send data back to someone. You would use
// bot.pm vs. bot.speak potentially

// Get the data

var text = text;

// Respond to "/God" command
if ((/^\/God$/)) {
  bot.pm('God is bigger than the boogieman');
}
Izzmo commented 11 years ago

Man.. you really need to indent your code dude. If it is already, then use GitHub markdown tags for code around it so it's correct :wink:

ghost commented 11 years ago

sorry about the ugly code i put up

Izzmo commented 11 years ago

@Turntablelover press 'M' on your keyboard when replying, or read GitHub Flavored Markdown

ghost commented 11 years ago

ok, do i just press m or do i have to do something with it

Izzmo commented 11 years ago

You press "m" (don't click on the textbox though) and the cheatsheet should appear.

samuri51 commented 11 years ago

you need to put your code inside one of these, except without the forward slash

/```js

//code goes here

/```

ghost commented 11 years ago

I edited my earlier comment with my code

samuri51 commented 11 years ago

looks the same to me?

samuri51 commented 11 years ago

what is your question exactly? the pm event works almost exactly the same as the speak event with two main differences.

  1. data.senderid is the person who has sent the pm
  2. data.userid is the person who is receiving the pm

it says what does here https://github.com/alaingilbert/Turntable-API/blob/master/turntable_data/pmmed.js

to access each field you assign a variable name to your callback function such as data then append a field name to it such as data.senderid, data.userid, data.text, etc. look at that link for all the names of the object fields

ghost commented 11 years ago

I want to get private message functions on my bot so listeners can do commands to him through PM

samuri51 commented 11 years ago

first thing is that with your vegibot switch statement where it says math.random() * 2 it should be math.random() * 12 in this case to access all of those sayings, make it the same number as the number of sayings. it means it will generate a random whole number between 0 and whatever your * number is

ghost commented 11 years ago

ok, I changed it. what else should i change.

technobly commented 11 years ago

TRY THIS... untested, but I think you'll like what I've done. There may be some errors... dunno... but you can learn from it ;-)

// Define default value for global variable 'isOn'
var isOn = true;
var theUsersList = {};
var veggieList = [
    'Exterminate, Exterminate!', 'This room is so cold.', 'Always eat your vegetables.', 'Oh, where is my hairbrush?',
    'You would make a good dalek.', 'HELP! Boaz traded my cat for a new battery pack.', 'Duty, honour, and good sauce.',
    'YOU... SHALL... NOT... PASS', 'Chase Mccain? YOUR A LEGEND!', 'I find your lack of faith disturbing.',
    'Go Green Ranger Go.', 'You were that Flobbit? That Flobbit who bought everything mail order?',
    ':imp: We ain\'t had nothing but maggoty bread for three stinking days :smiley: I\'d love a :cookie:'
];

bot.on('speak', function (data) {
  run_commands(data, false);
});

bot.on('pmmed', function (data) {
  run_commands(data, true);
});

function run_commands(data, frompm) {
  // Get the data
  if(frompm) var userid = data.senderid;
  else var userid = data.userid;
  var name = data.name;
  var text = data.text.trim();

  // parse commands here just like when you were in bot.on('speak' ...
  // variable frompm would be set true if you called this function from PM, 
  if (text.match(/^\/status$/)) {
    if (isOn) bot.talk('The bot is currently turned on.', userid, frompm);
    else talk('The bot is currently turned off.', userid, frompm);
  } else if (text.match(/^\/off$/)) {
    talk('The bot is turned off.', userid, frompm);
    // Set the status to off
    isOn = false;
  } else if (text.match(/^\/on$/)) {
    talk('The bot is turned now on.', userid, frompm);
    // Set the status to on
    isOn = true;
  }
  // Respond to "/God" command
  else if (text.match(/^\/God$/)) {
    talk('God is bigger than the boogieman', userid, frompm);
  }
  // Respond to "/Boaz" command
  else if (text.match(/^\/Boaz$/)) {
    talk('Even though he is my bot brother, Boaz is a lying liar', userid, frompm);
  }
  // Respond to "/rules" command
  else if (text.match(/^\/rules$/)) {
    talk('Room Rules for Christian Anything are at http://goo.gl/ub4xz', userid, frompm);
  }
  // Respond to "/love" command
  else if (text.match(/^\/love$/)) {
    talk('I love this room', userid, frompm);
  }
  // Respond to "/Pi" command
  else if (text.match(/^\/Pi$/)) {
    talk('Pi=3.141592653589793238462643383279502884', userid, frompm);
  }
  // Go command
  else if (text.match(/^\/go$/)) {
    // Bot gets on the DJ table (if there's a spot open) on /go command
    bot.addDj();
  }
  // Stop
  else if (text.match(/^\/please stop$/)) {
    // Bot jumps off the table on /please stop command
    bot.remDj(USERID);
  }
  // Skip
  else if (text.match(/^\/skip$/)) {
    // Bot skips it's own song (if bot is the current DJ) on /skip command
    bot.skip();
  }
  // Addsong command
  else if (text.match(/^\/addsong$/)) {
    // Bot adds song to the bottom of it's DJ queue on /addsong command
    bot.playlistAll(function (data) {
      bot.playlistAdd(data.list.length);
    });
    bot.snag();
  }
  // VeggieBot command
  else if (text.match(/VeggieBot/i)) {
    talk(randomItem(veggieList), userid, frompm);
  }
}

bot.on('roomChanged', function (data) {
  // Reset the users list
  theUsersList = {};

  var users = data.users;
  for (var i = 0; i < users.length; i++) {
    var user = users[i];
    theUsersList[user.userid] = user;
  }
});

bot.on('registered', function (data) {
  for (var i = 0; i < data.user.length; ++i) {
    var user = data.user[i];
    theUsersList[user.userid] = user;

    if (user.name.match(/ttstats/i)) {
      bot.bootUser(user.userid, 'Beat it, bot!');
      console.log("[ BANNED ] : " + user.name + " " + user.userid);
    }

    setTimeout(function () {
      bot.speak(user.name + ', welcome to christian anything! BoazV2, our main bot, will let you sign up for a DJ Spot.'); //send it in the chatbox
      bot.pm('welcome to christian anything!', user.userid); //send it in the pm

    }, 3 * 1000); //slow it down 3 seconds
  }
});

bot.on('deregistered', function (data) {
  var user = data.user[0];
  delete theUsersList[user.userid];
});

//Processes the bot speak
function talk(text, userid, replypm) {
  if (replypm) bot.pm(text, userid);
  else bot.speak(text);
}

//Checks if the user is a bot admin
function IsAdmin(userid) {
  if (userid === '4e16f5414fe7d0665b0cacea') {
    return true;
  } else return false;
}

//Checks if the user is a moderator
function IsMod(userid, callback) {
  bot.roomInfo(false, function (data) {
    var moderators = data.room.metadata.moderator_id;
    if (moderators.indexOf(userid) != -1) {
      callback(true);
      return;
    } else {
      callback(false);
      return;
    }
  });
};

bot.on('newsong', function (data) {
  bot.becomeFan(data.room.metadata.current_dj);

  snagIfNotInPlaylist();
});

function snagIfNotInPlaylist() {
  bot.playlistAll(function (data) {
    var found = false;
    for (var i = 0; i < data.list.length; i++) {
      if (data.list[i]._id == bot.currentSongId) {
        found = true;
        break;
      }
    }
    if (!found) {
      bot.snag();
    }
  });
};

function randomItem(list) {
  return list[Math.floor(Math.random() * list.length)];
};
samuri51 commented 11 years ago

as far as things working in the pm its very similiar to the chatbox, to go off of your example there are many different ways of going about it... here is example

you could define a separate function like this and call it inside of the event


//pass in 0 or 1 for speak function or pm and data as
// second arg to get data from callback function
global.helloFunction = function(int, data)
{
    if(int === 0) //speak function dependant instructions go here
    {
       bot.pm('hello', data.userid);
    }
    else if(int === 1) //pm stuff goes here
    {
        bot.pm('hello', data.senderid); 
    }
};

bot.on('pmmed', function (data)
{
    if (data.text.match(/^\/hello$/))
    {
        helloFunction(1, data); //you use this by using the same name as your function above...
    }
});

bot.on('speak', function (data)
{
    if (data.text.match(/^\/hello$/))
    {
        helloFunction(0, data); //you use this by using the same name as your function above...
    }
});

or you could redefine it inside of the event literally

bot.on('pmmed', function (data)
{
    var text = data.text; //text detected in the bots pm

    if (text.match(/^\/hello$/))
    {
        //data.senderid is the person who pmmed the bot, so it plugs their id into the getProfile function
        //and says their name in the chatbox
        bot.getProfile(data.senderid, function(data2)
        {
            bot.speak('Hey! How are you @' + data2.name + ' ?');
        });

        bot.pm('hello', data.senderid); //send this text back to the sender...        
    }
})

or you could define it in a separate file and import it... you might wanna try the simpler methods first though

samuri51 commented 11 years ago

an +1 to dubbytt's method or random sayings :p, much less typing

ghost commented 11 years ago

ok, thank you, and your examples work great samuri51

alaingilbert commented 11 years ago

TypeError: Cannot call method 'send' of undefined Means that you are trying to send a command before the bot has authenticate.

I did a commit that will log an error instead of crashing the application. (c6795ca38749402d45fae17e7762af50b7bc1d6c) Though, if you have this error in your log, it's clear that one of your bot feature isn't working.

ghost commented 11 years ago

ok, everything is working now, thanks to samuri51