PDA

View Full Version : TwitterBot


cbk1994
06-11-2008, 07:05 AM
Links approved by Moonie.

http://www.seodisco.com/images/twitter-logo.png

Twitter (http://twitter.com/) is a social-networking site which allows you to post about what you're doing, or to send short messages to all of your friends. For example, if you are walking down the street and see a monkey, you can pull out your phone, and send a text message to Twitter saying "There's a monkey walking down the street!" which will then show up on your Twitter page, and be sent to everyone watching you (and, possibly, to their mobile devices).

TwitterBot is a script which does 3 things. I'll break it up and describe each thing that it does.

1. Access recent Tweets and display them.
TwitterBot reads the Twitter RSS feed for each of the members specified. It figures out which Tweets are new, and then displays them by stating the message in RC chat, and also by alerting every user on the alert list, and PMing them the contents. For example, I can send a Twitter message from my phone, saying "Hey, guys. I'll be back in half an hour; did you get any work done?".

2. Sending messages
Twitter does not work in a classic PM-style; instead, you post an update, and everyone sees it. So, there is no need to reply when you can just send a message. Because of the way the Twitter API is set up, you have to use a PHP file to send a message; I take care of all this for you, however. I will explain this later. To send a message, you can say "/npc twitter sendmessage Hello, we got a lot done! I can't wait to show you when you get back!". This would then be sent to my phone, where I can reply.

3. Commands
TwitterBot comes with two pretty suckish commands, but it would be easy to add more on to. The commands work where you request information, and the bot returns it. So, if I send a Twitter update that says ".playercount", it would tell me the current playercount on my server. If I send one that says ".players", it would tell me all the accounts on my server. So, I can see that the graphics admin is currently on; I can then send a message asking them if they finished a graphic yet.

Script
Copy and paste this code in to a wNPC named "TwitterBot", and customize the options at the top. I will explain these below.

function onCreated()
{
this.username = "twitter_user_name"; // The name of your Twitter account to send from
this.password = "twitter_password"; // The password of your Twitter account to send from
this.server = "Server Name"; // The name of the server ... I guess you could spoof this if you really wanted to
this.url = "http://techxonline.net/twitter.php"; // URL of your PHP file ...
// Feel free to use the link to my site, but remember it might
// go down. Also, if you are worried about security, you may
// want to host it yourself

this.users = { "twitter_user_1", "twitter_user_2" }; // Twitter names of people to check for Tweets
this.alert = { "account1", "account2" }; // Accounts to notify when there is a new Tweet
this.checkspeed = 5; // How often new Tweets are checked for. I recommend 5 or 10

setTimer( 1 ); // No need to touch this
}
function onTimeOut()
{
for ( temp.user : this.users )
{
getPosts( user );
}
setTimer( this.checkspeed );
}
function getPosts( user )
{
temp.url = findRSS( user );
temp.source = requestHTTP( "twitter.com", 80, url );
this.catchevent( source, "onReceiveData", "onSourceReceived" );
}
function findRSS( user )
{
return "/statuses/user_timeline/" @ user @ ".rss";
}
function onSourceReceived( data )
{
if ( data.name.starts( "HTTP_twitter.com" ) )
{
displayData( parseData( data.data ));
}
}
function parseData( data )
{
temp.inItem = false;
temp.items = null;
temp.item = null;

for ( temp.line : data )
{
line = line.trim();
if ( line == "<item>" )
{
if ( inItem )
{
echo( "Error: Invalid RSS" );
return;
}
inItem = true;
}
else if ( line == "</item>" )
{
inItem = false;
items.add( item );
item = null;
}
else if ( inItem )
{
temp.tags = { "description", "link" };

for ( temp.tag : tags )
{
if ( line.starts( "<" @ tag @ ">" ) )
{
temp.value = line.substring( tag.length() + 2, line.length() - ( tag.length() * 2 ) - 5 );
item.add( { tag, value } );

break;
}
}

}
}

return items;
}
function displayData( data )
{
for ( temp.item : data )
{
if ( this.received.index( @ item[1][1] ) == -1 )
{
temp.msg = item[0][1];

for ( temp.i = 0; temp.i < msg.length(); temp.i ++ )
{
if ( msg.substring( temp.i, 1 ) == ":" )
{
this.ends = temp.i;
}
}

msg = msg.substring( this.ends + 1 ).trim();
if ( msg.starts( "." ) )
{
temp.send = null;

switch ( msg.substring( 1 ) )
{
case "playercount":
{
send = "Player count:" SPC allplayerscount;
break;
}
case "players":
{
send = "Players currently online: ";
for ( temp.pl : allplayers )
{
send @= pl.communityname @ " ";
}
break;
}
default:
{
send = "Unknown command! Try .players or .playercount";
break;
}
}

sendMessage( send SPC "from $BOT on #Graal/" @ this.server );

return;
}
sendtorc( "Twitter Update:" SPC item[0][1] );
this.received.add( item[1][1] );

for ( temp.a : this.alert )
{
temp.pl = findPlayer( a );
pl.chat = "Twitter Update (see PM from NPC-Server)!";
pl.sendPM( item[0][1] );
}
}
}
}
function sendMessage( msg, acc )
{
requesturl( this.url @ "?user=" @ this.username @ "&pass=" @ this.password @ "&status=" @ msg );
}
public function callFunc( p, acc )
{
switch ( p[1] )
{
case "sendMessage":
{
temp.send = p[2];

if ( p.size() > 1 )
{
for ( temp.param = 3; param < p.size(); param ++ )
{
send @= " " @ p[param];
}
}

sendMessage( send SPC "... from" SPC acc SPC "on #Graal/" @ this.server );
sendToRC( "Message sent:" SPC send SPC "by" SPC acc );
break;
}
}
}



I will now explain the things you need to change. They are all located in the onCreated() block at the top of the script.

this.username - This is the username of your Twitter account which you will be sending messages through. I highly recommend creating a new account.

this.password - The password of the username; yes, it must be stored in clear text. This is why I recommend you create a new account.

this.server - The name of the server you are currently on.

this.url - The URL of the PHP file (see below).

this.users - The list of Twitter accounts that you want to monitor Tweets from.

this.alert - These are the accounts that should receive and alert and be PMed Tweets when they arrive.

this.checkspeed - This is the speed at which TwitterBot checks for new messages; I recommend 5 or 10.

This is all you will need to change in this script.

Now, open the Control-NPC script, and add at the bottom (or to the existing onRCChat function) this code:


function onRCChat()
{
if ( params[0] == "twitter" )
{
findNPC( "TwitterBot" ).callFunc( params, player.account );
}
}


Now, there is only one thing left to discuss: the PHP script.

I have a PHP file hosted on my server which will work fine with this script; however, I warn you that it may go down, and may be slow. It is hosted in a computer at my house, and therefor any power outages will put it down. I cannot guarantee that it will always be there, either.

If you are worried about security, I strongly recommend that you use the script I am providing and host it on your own server. This will also probably result in better up-time and speed.

Paste this in a file called twitter.php -- be sure to change this.url in the script to reflect this.

<?php
$username = $_GET[ 'user' ];
$password = $_GET[ 'pass' ];

$message = $_GET[ 'status' ];

$url = 'http://twitter.com/statuses/update.xml';

$curl_handle = curl_init();
curl_setopt($curl_handle, CURLOPT_URL, "$url");
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_POST, 1);
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, "status=$message");
curl_setopt($curl_handle, CURLOPT_USERPWD, "$username:$password");
$buffer = curl_exec($curl_handle);
curl_close($curl_handle);
?>

Note that the CURl PHP extension will have to be enabled.

This is all you will need to know to run TwitterBot! Be sure to leave comments and criticism, and ask for help if you need it! Suggestions are also welcome so that I can make an improved version!

DrakilorP2P
06-11-2008, 01:51 PM
Nifty.

cbk1994
06-11-2008, 02:00 PM
Nifty.

Thanks ;o

Chompy
06-11-2008, 03:28 PM
That's pretty cool :p nice job

bscharff
06-12-2008, 11:37 PM
Extremely useful!

Very nice work!

Chompy
06-12-2008, 11:43 PM
Extremely useful!

It's isn't an extremely useful script though, unless you're addicted to Twitter or something.. :P
More like a nifty and a very nice script ^^

And that last line sounded a little bit sarcastic?

Anyways, again Chris, nifty script :p

cbk1994
06-13-2008, 12:19 AM
It's isn't an extremely useful script though, unless you're addicted to Twitter or something.. :P
More like a nifty and a very nice script ^^

That's true, but I like being able to talk to my server from my phone ;)

Thanks Bloo ;o

Chompy
06-13-2008, 12:24 AM
That's true, but I like being able to talk to my server from my phone ;)

I like the phone feature :) kudos to you

cbk1994
06-13-2008, 12:43 AM
I like the phone feature :) kudos to you

Now I just gotta make MySpaceBot ...

I'd never get a link approved ;)

bscharff
06-13-2008, 02:24 AM
Non-sarcasm
lol

I'll upload the PHP script to my server-- I'll post the link later.

Admins
03-26-2009, 05:29 PM
I'm wondering if you really need php? It's possible to make post-requests and similar with TSocket if it's enabled on the server.

Riot-Starter
03-26-2009, 06:38 PM
I'm wondering if you really need php? It's possible to make post-requests and similar with TSocket if it's enabled on the server.

While most likely possible (I've never used TSocket or seen any examples of its usage), I think that seems overkill for doing something like a POST request, especially given that to do a GET request we don't have to request anything like sockets.

Perhaps it wouldn't be out of line to request a function similar to requesturl for post data? Maybe something like, requestpost(url, "a=1&b=2") which would handle performing the POST request for us and wouldn't require us to request sockets be enabled.

Would probably also be nice to get a url encoding function (percent/form encoding) so data is properly encoded when performing the request.

Admins
03-26-2009, 07:48 PM
I think using TSocket is simplier, since the command would need to handle authentication, severel parameters etc.

This is a GET request with authentication:

temp.socket = new TSocket("MySocket");
temp.socket.connect(myip, 80);
temp.delim = char(13) @ char(10);
temp.socket.send("Get /index.php?test=123" @ temp.delim);
temp.socket.send("Authorization: Basic " @ base64encode("username:password") @ temp.delim);
temp.socket.send(temp.delim);
waitfor(temp.socket, "onClose", 10);
temp.answer = temp.socket.data.tokenize('\n');


The URL encoding is already done in the engine, can add a function to use it by script (urlencode)
Update: added urlencode(url) on Kingdoms, can upload a version for hosted servers end of the week along with the recent /scripthelp improvements.

Riot-Starter
03-26-2009, 07:55 PM
I think using TSocket is simplier, since the command would need to handle authentication, severel parameters etc.

This is a GET request with authentication:

temp.socket = new TSocket("MySocket");
temp.socket.connect(myip, 80);
temp.delim = char(13) @ char(10);
temp.socket.send("Get /index.php?test=123" @ temp.delim);
temp.socket.send("Authorization: Basic " @ base64encode("username:password") @ temp.delim);
temp.socket.send(temp.delim);
waitfor(temp.socket, "onClose", 10);
temp.answer = temp.socket.data.tokenize('\n');


The URL encoding is already done in the engine, can add a function to use it by script (urlencode)
Update: added urlencode(url) on Kingdoms, can upload a version for hosted servers end of the week along with the recent /scripthelp improvements.
I suppose it is rather simple, as I said I've never used TSocket, being as I haven't attempted to do any graalserver -> webserver communication since GS2 was rather new, and no server I have access too has TSocket enabled. I still don't particularly like the idea of having to request it to be enabled to use it for something like this though.

cbk1994
03-26-2009, 10:42 PM
I'm wondering if you really need php? It's possible to make post-requests and similar with TSocket if it's enabled on the server.

Yeah, I answered that when you mentioned it originally in another thread (when I was still writing this code).

The problem is that for it to be released on the Code Gallery, I wanted it to be as simple as possible, and code that would only work if you enabled sockets on their server didn't seem like a good solution.

fowlplay4
08-06-2009, 06:23 AM
Using this on Zodiac to track Nation Activity. Thanks! :)

Works great!

http://twitter.com/ZodiacGraal

xXziroXx
08-06-2009, 05:39 PM
Yeah, I answered that when you mentioned it originally in another thread (when I was still writing this code).

The problem is that for it to be released on the Code Gallery, I wanted it to be as simple as possible, and code that would only work if you enabled sockets on their server didn't seem like a good solution.

Now go tweak it, since afaik TSockets are enabled on all servers by default.

cbk1994
08-06-2009, 06:15 PM
afaik

No.

xXziroXx
08-06-2009, 06:21 PM
No.

I'm pretty sure of it.

cbk1994
08-06-2009, 06:27 PM
I'm pretty sure of it.

I'm fairly certain of the opposite; I put in a ticket a few days ago asking for it on Era and Era Dev, and Stefan responded with a need for the IP/server and port numbers that would need to be connected to.

EDIT:

Yep


The script of NPC Temp_Chris has been updated by cbk1994
Script connection to techxonline.net:80 is not allowed, blocking.

WhiteDragon
08-06-2009, 06:30 PM
I think cbk1994 is right -- Stefan's likely blocking all connections on non-graal ports via. iptables or a firewall of sorts, so unless he intends on opening the machines to all sorts of random traffic, he'll probably never just open the flood doors like that for TSocket.

xXziroXx
08-06-2009, 07:40 PM
Hm, my bad then. I was pretty sure I read a post from Stefan a while ago saying he enabled it by default, must've been something else, or simply my imagination.

WhiteDragon
08-06-2009, 08:29 PM
Hm, my bad then. I was pretty sure I read a post from Stefan a while ago saying he enabled it by default, must've been something else, or simply my imagination.
It's possible that the technology is enabled on all the servers, just he needs to config the machines for specific ip : ports.

fowlplay4
08-06-2009, 09:03 PM
If he implemented some sort simple post data feature to requesturl that would be great. I'd rather not mess around with sockets.

Soala
08-06-2009, 10:16 PM
Pretty cool ^^ Twitter rocks

cbk1994
08-06-2009, 10:32 PM
If he implemented some sort simple post data feature to requesturl that would be great. I'd rather not mess around with sockets.

Agreed, or at least have a server option or something to allow servers to be connected to without contacting Stefan.

Gambet
08-06-2009, 11:43 PM
If he opened the sockets to everyone then there would be risk of getting DDoS'd, so I would assume that he would be insecure about this stuff.

fowlplay4
08-07-2009, 02:09 AM
Just a notice but, messages sent should be URL encoded before being sent out. I don't believe that hard-coded functionality was out at the time of this release.

It's just a matter of replacing..

Line 154 with:


requesturl( this.url @ "?user=" @ this.username @ "&pass=" @ this.password @ "&status=" @ urlencode(msg) );

Twinny
08-07-2009, 01:18 PM
If he opened the sockets to everyone then there would be risk of getting DDoS'd, so I would assume that he would be insecure about this stuff.

If we had access to an ACL, it would alleviate a lot of the security concerns