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

Error: this.ws.send("~m~" + msg.length + "~m~" + msg); #180

Closed ghost closed 11 years ago

ghost commented 11 years ago

I got this error when I put in the code for randomizing my bot's playlist. I get this same error when I try to code up song stats, booting people functions, and private message functions.

Error name is : Cannot call method 'send' of undefined

alaingilbert commented 11 years ago

What does your code look like ? What is the complete stack trace ?

ghost commented 11 years ago

Code:

var Bot    = require('ttapi');
var AUTH   = 'xxx';
var USERID = 'xxx';
var ROOMID = '4e386d5814169c294618267b';
var bot = new Bot(AUTH, USERID, ROOMID);
bot.listen(process.env.Port,process.env.IP);

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;
        }
    });
};

};

//Speak - Puts text in to the chatroom.

global.Speak = function(text, userName, source, userid) {};
    var textOut = "God is awesome";

    if (undefined) {
        textOut =(/\{God\}/gi);
    } else {
        textOut;
    }

//SpeakRandom - Takes an array of options to speak and speaks one of them.

global.SpeakRandom = function(array, userName) {
    var textOut = ["God is so wonderful"];
    var rand = Math.ceil(Math.random() * array.length) - 1;

    if (userName !== undefined) {
        textOut = array[rand].replace(/\{random\}/gi, userName);
    } else {
        textOut = array[rand];
    }

    bot.Speak(textOut);
};

// 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(/^\/stop$/)) {
    // Bot jumps off the table on /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.playlistAll(function(playlist) {
  console.log("Playlist length: " + playlist.list.length);
  var i = 0;
  var reorder = setInterval(function() {
    if (i <= playlist.list.length) {
      var nextId = Math.ceil(Math.random() * playlist.list.length);
      bot.playlistReorder(i, nextId);
      console.log("Song " + i + " changed.");
      i++;
    } else {
      clearInterval(reorder);
      console.log("Reorder Ended");
      bot.speak("Reorder completed.");
    }
  }, 1000);
});

Stack Trace: Your code is running at 'http://tt-project.ttcloud.c9.io'. Important: use 'process.env.PORT' as the port and 'process.env.IP' as the host in your scripts! /var/lib/stickshift/516dbf2a4382ecf0ae000003/app-root/data/474680/node_modules/ttapi/lib/bot.js:310 this.ws.send("~m~" + msg.length + "~m~" + msg); ^ TypeError: Cannot call method 'send' of undefined at Bot._send (/var/lib/stickshift/516dbf2a4382ecf0ae000003/app-root/data/474680/node_modules/ttapi/lib/bot.js:310:15)
at Bot.playlistAll (/var/lib/stickshift/516dbf2a4382ecf0ae000003/app-root/data/474680/node_modules/ttapi/lib/bot.js:997:19) at Object. (/var/lib/stickshift/516dbf2a4382ecf0ae000003/app-root/data/474680/Bot/Turntable-API-master/examples/chat_bot.js:208:5) at Module._compile (module.js:449:26) at Object.Module._extensions..js (module.js:467:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:312:12) at Module.runMain (module.js:492:10) at process.startup.processNextTick.process._tickCallback (node.js:244:9)

ghost commented 11 years ago

Note: The bot runs fine on Turntable.fm when I don't have the randomizing playlist code in the code file.

alaingilbert commented 11 years ago

That error occurred because you are calling a bot function playlistAll before that the bot is ready.

What I mean is that : When you call

var bot = new Bot(AUTH, USERID, ROOMID);

The bot is not instantaneously ready. He is still creating the websocket connection (for a while). And right after, you call playlistAll before the websocket connection has been established...


Also, you can't call the playlistReorder let say 100 times in a row, turntable will block most of your requests (api rate limiting).

ghost commented 11 years ago

ok, thanks for the info. What should I do to fix it.

alaingilbert commented 11 years ago

Instead of having something like :

var bot = new Bot(AUTH, USERID, ROOMID);
bot.playlistAll(function (data) {
  ...
});

You should do something like :

var bot = new Bot(AUTH, USERID, ROOMID);
bot.on('ready', function () {
  bot.playlistAll(function (data) {
    ...
  });
});

And for the random playlist, you just have to choose a random id and put that song on the top of the playlist at the end of your song... something like that.