7
Spying on your BF3 BattleLog friends made easy with PHP + Zend Framework
No comments · Posted by Adam Lundrigan in Zend Framework
BattlelogNotifier on GitHub: https://github.com/adamlundrigan/BattlelogNotifier
Why?
I enjoy first-person shooters. I especially love Battlefield 3, and I enjoy it most when playing online with my friends. After a couple of failed gaming sessions where I signed on just as they were signing off, I’d had enough; there had to be a better way…so late one night Battlelog Notifier was born.
What?
Battlelog Notifier is a simple server script which scrapes my Battlelog periodically to find out the status of my friends and sends a DM to my Twitter account whenever it detects that one or more of them has started playing. No more missing out on the action!
How?
Thanks to the awesomesauce that is Zend Framework, it’s quite easy, really. All I have to do is harness Zend_Http_Client to send a POST request to the login page:
// Log into battlelog require_once "Zend/Http/Client.php"; $c = new Zend_Http_Client(); $r = $c->setCookieJar() ->setUri('https://battlelog.battlefield.com/bf3/gate/login/') ->setParameterPost('redirect', '') ->setParameterPost('email', YOUR_BATTLELOG_EMAIL) ->setParameterPost('password', YOUR_BATTLELOG_PASSWORD) ->setParameterPost('remember', '1') ->setParameterPost('submit', 'Sign In') ->request('POST'); $contents = $r->getBody();
As it turns out, Battlelog’s page source contains beautiful hunks of JSON that describe pretty much the entire state of the page at the time it was generated. So I do some hacked-together regex magic:
// Hunt down and chop out the correct JSON bit if ( preg_match_all('{<script type="text/javascript">([^<]+)</script>}s', $contents, $Matches) ) { foreach ( $Matches[1] as $K=>$ScriptContents ) { // The JSON we are looking for has a username key... if ( preg_match('{"username":}s', $ScriptContents) ) { // ... and resides inside a call to feed.likeitems.surface_2_2.render if ( preg_match('{feed\.likeitems\.surface_2_2\.render\(([^)]*)\)}s', $ScriptContents, $FunctionMatches) ) { // ... and is, of course, delimited by curly braces if ( preg_match('{\{.*\}}s', $FunctionMatches[1], $JSONMatches) ) { // Decode the captured JSON bit $Data = Zend_Json::decode($JSONMatches[0]); // If it's an array... if ( is_array($Data) ) { // ...we now have ALL THE THINGS! } } } } } }
Since we now have everything we need to know from battlelog, we can use it. $LastUserInfo is $Data['users'] from the previous script run, so that we can tell if someone has sign in/out or started/stopped playing.
$Started = array(); $Stopped = array(); foreach ( $Data['users'] as $UID=>$UserInfo ) { if ( $UserInfo['presence']['isPlaying'] && !@$LastUserInfo[$UID]['presence']['isPlaying'] ) { $Started[] = $UserInfo['username']; } elseif ( !$UserInfo['presence']['isPlaying'] && @$LastUserInfo[$UID]['presence']['isPlaying'] ) { $Stopped[] = $UserInfo['username']; } }
Now all that is left to do is send the DM using Zend_Oauth and Zend_Service_Twitter:
$token = new Zend_Oauth_Token_Access; $token->setParams(array( 'oauth_token' => YOUR_OAUTH_TOKEN, 'oauth_token_secret' => YOUR_OAUTH_SECRET )); $twitter = new Zend_Service_Twitter(array( 'consumerKey' => YOUR_TWITTER_CONSUMER_KEY, 'consumerSecret' => YOUR_TWITTER_CONSUMER_SECRET, 'accessToken' => $token )); $msg = ''; if ( count($Started) > 0 ) $msg .= implode(", ",$Started) . (count($Started)>1 ? ' have' : ' has') . ' started playing BF3. '; if ( count($Stopped) > 0 ) $msg .= implode(", ",$Stopped) . (count($Stopped)>1 ? ' have' : ' has') . ' stopped playing BF3.'; if ( !empty($msg) ) $twitter->directMessage->new(YOUR_TWITTER_ID, $msg);
And the end result is a nice notification on Twitter:

BF3 · PHP · Zend Framework · Zend_Http_Client · Zend_Oauth · Zend_Service_Twitter

