I was inspired by a friend (EFNet - steve nash aka oz) on IRC - he (or his friend(s)) had setup an incoming phone number that would just rickroll you. Nothing else.
Well, hell, that's easy to setup with Asterisk, but I was determined to do one better. Not only would I setup a phone number that would rickroll you, but I would also make the number call you back and rickroll you again.
With Asterisk, PHP, MySQL, and great SIP service, this is cake. First things first -- I made a new musiconhold class (musiconhold.conf):
Bam - if you call 630-206-1300, you will get rickrolled. However, if you notice the AGI(rickroll) on the second line of the extension logic - that's what makes this rickroll funnier.
I created a MySQL table:
And created an AGI with command line PHP -- in /var/lib/asterisk/agi-bin -- make sure it's got execute permission (chmod 755 it when yer done):
There. We now have incoming rickroll calls getting logged to a database. It sets the dialtime to the current time + 300 seconds (5 minutes) - so in 5 minutes, the cronjob will pick the call up and make it.
Here's where the fun comes in. We need a cronjob that uses the manager interface of Asterisk to initiate calls after they're read out of the database. Add this to manager.conf in asterisk:
Now we're ready for the evil. Here's the PHP cronjob (heavily commented so you can understand the flow) - I wrote a couple functions for sending manager commands so I could reuse the code in other stuff:
The comments should hopefully explain it all, if not, feel free to drop me a line w/ questions. Basically, the cronjob grabs all the upcoming calls, and then proceeds to make them. If its their first callback - it will set the callerID to the rickroll phone number (630-206-1300). If its their second/last - it will set the caller ID to a number similar to the caller's # - if you call from 303-555-1122, it will use the same NPA-NXX - 303-555, and then append 4 random #'s. I figured if someone notices rickroll is calling them back, they'll ignore the callback. A call phone a number in their same area code + prefix might make someone answer.
To install the cronjob - stick the cronjob bin (make sure it has execute permission) somewhere. /usr/local/bin works for me. Add this to your crontab:
The last piece is the extension context [rickroll]. In extensions.conf:
The code isn't super pretty, and I'm sure there are a thousand improvements that can be made to the code/logic, but for a quick one hour joke - its not too bad.
Feel free to comment/email with questions :)
Andy
Links for more information:
Asterisk
Asterisk AGI
Asterisk Dial Command
Asterisk extensions.conf
Asterisk manager
Well, hell, that's easy to setup with Asterisk, but I was determined to do one better. Not only would I setup a phone number that would rickroll you, but I would also make the number call you back and rickroll you again.
With Asterisk, PHP, MySQL, and great SIP service, this is cake. First things first -- I made a new musiconhold class (musiconhold.conf):
[rickroll]And the extension logic (extensions.conf) - this goes into your incoming SIP context:
mode=files
directory=/var/lib/asterisk/custom-moh/rickroll
exten => 6302061300,1,Answer
exten => 6302061300,n,AGI(rickroll)
exten => 6302061300,n,Ringing
exten => 6302061300,n,Wait(4)
exten => 6302061300,n,MusicOnHold(rickroll)
exten => 6302061300,n,Hangup
Bam - if you call 630-206-1300, you will get rickrolled. However, if you notice the AGI(rickroll) on the second line of the extension logic - that's what makes this rickroll funnier.
I created a MySQL table:
CREATE TABLE rickroll (
rickrollid bigint(20) NOT NULL auto_increment,
phonenum varchar(10) NOT NULL default '',
dialtime int(11) default NULL,
calls tinyint(4) default NULL,
PRIMARY KEY (rickrollid),
UNIQUE KEY (phonenum),
KEY (dialtime)
);
And created an AGI with command line PHP -- in /var/lib/asterisk/agi-bin -- make sure it's got execute permission (chmod 755 it when yer done):
#!/usr/bin/php -q
<?
$stdin = fopen('php://stdin', 'r');
$stdout = fopen('php://stdout', 'w');
while (!feof($stdin)) {
$temp = fgets($stdin);
$temp = str_replace("\n", "", $temp);
$s = explode(":", $temp);
$agivar[ $s[0] ] = trim($s[1]);
if (($temp == "") || ($temp == "\n")) {
break;
}
}
$mysql=mysql_connect("localhost","RICKROLLUSER","RICKROLLPASS","rickroll");
mysql_select_db("rickroll");
$callerid = $agivar[agi_callerid];
$newd = time() + 300;
$q = "INSERT INTO rickroll (phonenum, dialtime, calls) VALUES ('$callerid','$newd',0)";
$qid = mysql_query($q, $mysql);
mysql_close($mysql);
exit;
There. We now have incoming rickroll calls getting logged to a database. It sets the dialtime to the current time + 300 seconds (5 minutes) - so in 5 minutes, the cronjob will pick the call up and make it.
Here's where the fun comes in. We need a cronjob that uses the manager interface of Asterisk to initiate calls after they're read out of the database. Add this to manager.conf in asterisk:
[rickroll]
secret = MANAGER_PASSWORD_HERE
deny=0.0.0.0/0.0.0.0
permit=127.0.0.0/255.255.255.0
read = system,call,log,verbose,command,agent,user
write = system,call,log,verbose,command,agent,user
Now we're ready for the evil. Here's the PHP cronjob (heavily commented so you can understand the flow) - I wrote a couple functions for sending manager commands so I could reuse the code in other stuff:
#!/usr/bin/php -q
<?php
// Set some variables
$callerid = ""; // Holds the caller ID we'll use to rickroll the person back
$time = time(); // Current time - in epoch (seconds since 1970)
$del = array(); // Array of entries to delete/update after we call
// Connect to the database
$mysql=mysql_connect("localhost","RICKROLLUSER","RICKROLLPASS","rickroll");
mysql_select_db("rickroll");
// Open a socket to the manager interface of Asterisk.
$ast_man = fsockopen("127.0.0.1","5038", $errno, $errstr, 30);
// Read in the version string
$in = fread($ast_man, 4096);
// Login with the manager credentials we used in manager.conf
fwrite($ast_man, "Action: login\r\n");
fwrite($ast_man, "Username: rickroll\r\n");
fwrite($ast_man, "Secret: MANAGER_PASSWORD_HERE\r\n");
fwrite($ast_man, "Events: off\r\n\r\n");
// Get the response
$resp = get_response($ast_man);
// If we get a login error - die.
if ($resp['response'] != "Success") {
exit;
}
// Get the list of people that need a return call from Rick Astley
$q = "SELECT rickrollid, phonenum, dialtime, calls FROM rickroll WHERE dialtime < $time";
$qid = mysql_query($q, $mysql);
while ($r = mysql_fetch_assoc($qid)) {
// Set the variables from the array -- this is for pure laziness:
$rickrollid = $r['rickrollid'];
$phonenum = $r['phonenum'];
$calls = $r['calls'];
$dialtime = $r['dialtime'];
if ($calls == 0) {
// Never been called back yet -- set the caller ID to the rickroll #
$callerid = "6302061300";
} else {
// They got one callback already. This is the second (last) one -- so
// we'll randomize the last 4 digits of their phone # and use that as our
// caller ID.
$callerid = substr($phonenum, 0, 6) . rand(0,9) . rand(0,9) . rand(0,9) . rand(0,9);
}
// Set the array of asterisk manager parameters to initiate the call:
$evil = array('Action' => 'Originate',
'Channel' => "LOCAL/$phonenum@rickroll",
'Context' => 'rickroll',
'Exten' => '1000',
'Priority' => '1',
'Callerid' => $callerid,
'Timeout' => '30000');
// We're not going to call ourselves back.
if ($phonenum != '6302061300') {
send_command($ast_man, $evil);
}
// Add this phone number to the array - so we can update/delete the records
$del[] = array('phonenum' => $phonenum, 'calls' => $calls, 'rickrollid' => $rickrollid);
}
// Process the array of delete/updates
foreach($del as $r) {
if ($r['calls'] == 0) {
// This was their first call -- the next one will be done in a random amount of time.
// The next call will be in some random amount of time 15 minutes from now.
// I did 3 rand's of 0-300 to increase the odds of it not calling right back.
$newd = time() + rand(0,300) + rand(0,300) + rand(0,300);
// Update their entry in the database with the new call time.
$q = "UPDATE rickroll SET dialtime = $newd, calls = 1 WHERE rickrollid = " . $r['rickrollid'];
$qid = mysql_query($q, $mysql);
} else {
// Second call - just delete them from the table.
$q = "DELETE FROM rickroll WHERE rickrollid = " . $r['rickrollid'];
$qid = mysql_query($q, $mysql);
}
}
fclose($ast_man);
mysql_close($mysql);
exit;
function send_command($fp, $cmdarray) {
$_t = "";
foreach($cmdarray as $k => $v) {
$_t .= "$k: $v\r\n";
}
$_t .= "\r\n";
fwrite($fp, $_t);
}
function get_response($fp) {
$ret = "";
while(1) {
$pkt = fread($fp, 1);
$ret .= $pkt;
if (substr($ret, -4) == "\r\n\r\n") break;
}
$a = explode("\r\n", $ret);
foreach($a as $k => $v) {
if (strlen($v) < 5) {
unset($a[$k]);
} else {
list($param, $value) = explode(": ", $v, 2);
$p = strtolower($param);
$r[$p] = trim($value);
}
}
return $r;
}
The comments should hopefully explain it all, if not, feel free to drop me a line w/ questions. Basically, the cronjob grabs all the upcoming calls, and then proceeds to make them. If its their first callback - it will set the callerID to the rickroll phone number (630-206-1300). If its their second/last - it will set the caller ID to a number similar to the caller's # - if you call from 303-555-1122, it will use the same NPA-NXX - 303-555, and then append 4 random #'s. I figured if someone notices rickroll is calling them back, they'll ignore the callback. A call phone a number in their same area code + prefix might make someone answer.
To install the cronjob - stick the cronjob bin (make sure it has execute permission) somewhere. /usr/local/bin works for me. Add this to your crontab:
*/2 * * * * /usr/local/bin/cron_rickroll.php >> /tmp/rickroll.log 2>&1
The last piece is the extension context [rickroll]. In extensions.conf:
[rickroll]
; The extension we connect the called party to -- rickroll!
exten => 1000,1,Answer
exten => 1000,n,MusicOnHold(rickroll)
exten => 1000,n,Hangup
; The outbound calling of our rickroll victims - standard outdial
exten => _NXXNXXXXXX,1,Dial(SIP/1${EXTEN}@primary-sip-out)
exten => _NXXNXXXXXX,n,Dial(SIP/1${EXTEN}@secondary-sip-out)
exten => _NXXNXXXXXX,n,HangUp
The code isn't super pretty, and I'm sure there are a thousand improvements that can be made to the code/logic, but for a quick one hour joke - its not too bad.
Feel free to comment/email with questions :)
Andy
Links for more information:
Asterisk
Asterisk AGI
Asterisk Dial Command
Asterisk extensions.conf
Asterisk manager
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=df8f2bc3-9f16-4338-b8a0-8206d189adb3)
Leave a comment