• Welcome to Valhalla Legends Archive.
 

PHP Bnet Stats Function Source

Started by Don Cullen, May 28, 2004, 03:17 PM

Previous topic - Next topic

Don Cullen

If possible, please make this post a sticky so people requesting PHP bnet info can refer to this post. Muy gracias.

------------------

This PHP function was coded by Donald Cullen, AKA DM-Kyro for the gaming clan based at www.dementedminds.org.

You are free to use this script as you wish, as long as proper due credit is given. But please do not distribute. This code was uploaded to thank the bot development forum @ vL for all of their assistance, not for people to rip off.

------------------

   function getstats($account, $realm, $game){
      ##############################################################
      #
      # Function to obtain and return stats
      #
      # Parameters:   $account is the battle.net alias you're checking
      #       $realm is the server you'll be querying
      #       $game is the game stats you want from
      #
      # Bugs: 2 (non-fixable)
      #
      # Explaination:    Every once in a while, all attempts
      #      to connect to the server will be
      #      refused for unknown reasons for a
      #      certain unknown length of time. Also
      #      frequent rapid connections will
      #      (Included failed ones!) result in the
      #      server the script is hosted on being
      #      ipbanned.
      #
      # Returns:    Stats in one string. If error results,
      #      including bnet errors, it will return
      #      "abort" along with the reason.
      ##############################################################
   
      ##   Configuration phase
   
      $cfgServer = "$realm.battle.net";
      $cfgPort = 6112;
      $cfgTimeOut = 1;
      $cfgUser = "WhateverName";
      $cfgPassword = "WhateverPassword";
      $terminate = FALSE;
      $refusalreason = "";
   
      if($game == "STAR" || $game == "SEXP" || $game == "WAR3" || $game == "W3XP"){
         $loopx = 3;
      } else if($game == "W2BN"){
         $loopx = 4;
      } else {
         $terminate = true;
         $refusalreason = "Unknown $game abbreviation.";
      }
   
      ##   Parameter verification phase
   
      if(!$account || !$realm || !$game){
         $terminate = true;
         $refusalreason = "Missing information.";
      }
   
      ##   Connection phase
   
      if(!$terminate){
            $usenet_handle = fsockopen("tcp://".$cfgServer, $cfgPort, $errno, $errstr, $cfgTimeOut);

         if(!$usenet_handle) {
            $terminate = true;
            $refusalreason = "Connection Failed.";
         }
      }
   
      ##   Login phase
   
      if(!$terminate){
         $constring = chr(3).chr(4);
         $enter = chr(10).chr(13);
         fputs($usenet_handle, $constring);
         if(!$cfgUser){
            fputs($usenet_handle, "anonymous".$enter);
         } else {
            fputs($usenet_handle, $cfgUser.$enter);
               fputs($usenet_handle, $cfgPassword.$enter);
         }
   
         $skip = 0;
         $abort = FALSE;
         $sd = 0;
         while($skipa != 4 && !$abort){
            if(false === ($info = fgets($usenet_handle))){
               $terminate = true;
               $refusalreason = "Socket read failed! Reason: ".socket_strerror($ret);
               $abort = true;
            }
            $refuse = strpos($info, "refused");
            if($refuse){
               $terminate = true;
               $refusalreason = "Connection was refused.";
               $abort = true;
            }
            $badlogin = strpos($info, "Login Incorrect");
            if($badlogin){
               $terminate = true;
               $refusalreason = "Invalid login.";
               $abort = true;
            }
            $tmp =  substr($info, 0, 4);
            $tmp = "a$tmp";
            $res = strpos($info, "1018");
            if(strpos($tmp, "1018")){
               $skipa++;
            }
            $sd++;
            if ($sd == 40){
               $abort = TRUE;
            }
         }
      }
   
      ##   Stats Phase
   
      if(!$terminate){
           fputs($usenet_handle, "/stats ".$account." ".$game.$enter);
         $skipa = 0;
         $abort = FALSE;
         $sd = 0;
         while($skipa != $loopx && !$abort){
            $info = fgets($usenet_handle);
            $tmp =  substr($info, 0, 4);
            $tmp = "a$tmp";
            if(strpos($tmp, "1018")){
               $bneterrchk = substr($info, 0, 18);
               if($bneterrchk == "1018 INFO \"INVALID"){
                  $temp = ltrim(rtrim(substr($info, 11)));
                  $temp = substr($temp, 0, strlen($temp) - 1);
                  $terminate = TRUE;
                  $refusalreason = "BNET: Account mismatch! ".$temp;
                  $abort = TRUE;
               } else {
                  $skipa++;
                  $temp = ltrim(rtrim(substr($info, 11)));
                  $temp = substr($temp, 0, strlen($temp) - 1);
                  $retu = $retu." | ".$temp;
               }
            }
            if(strpos($tmp, "1019")){
               $temp = ltrim(rtrim(substr($info, 12)));
               $temp = substr($temp, 0, strlen($temp) - 1);
               $terminate = TRUE;
               $refusalreason = "BNET: ".$temp;
               $abort = TRUE;
            }
            $sd++;
            if ($sd == 7){
               $terminate = TRUE;
               $refusalreason = "Timed out.";
            }
         }
      }
   
      ##   Finalization Phase and Error handling
   
      if($usenet_handle != ""){
         fclose($usenet_handle);
      }
      if(!$terminate){
         return $retu;
      } else {
         $error = "abort ".$refusalreason;
         return $error;
      }
   }


Information on the function, as well as which part does what has already been explained inside the function. What the script basically does is open a php socket, connects to battle.net, logs in (if you're not anonymous), obtains stats info, then disconnects from battle.net. Reason for disconnection is because PHP is once-run based language- everything has to be done in one run- so if you don't close a socket at the end of the script, then any further attempts to connect to bnet will be refused since the first one is still open. Hence why the script disconnects at the end. It's mainly for re-usability.

Comments, criticism, questions, suggestions, are all welcome. Flames however are not.  :P
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

AC_Drkan

Not complaining but....

For some reason that script will not run. Its weird because it looks like it will connect but when i ran it i had it whisper to me when it was being used in addition to the /stats call.

i never got anything
"The Arguments of Today Result in the Wars of Tomorrow" - Quote By Muah.
<@Logan> I spent a minute looking at my own code by accident.
<@Logan> I was thinking "What the hell is this guy doing?"

<kow`> "There are 10 types of people in the world... those who understand binary and those who don't."
<SpaceRain> That's only 2 types of people, kow.
<SpaceRain> STUPID


<[TN]FBMachine> i got kicked out of barnes and noble once for moving all the bibles into the fiction section

God i love Bash.org.

MyndFyre

One suggestion -- and I'm not really certain about the scope and function of PHP sockets or anything, but more of a general design decision.

Say you have a members page for a clan, and want to look up the stats for 20 people at a time.

The way I would structure this is:

1.) Open a socket to Battle.net
2.) Log in
3.) Request stats for user 1
4.) Request stats for user 2
... etc.
23.) Close the socket.

It seems like what you're doing is making one connection per request, which is sub-optimal.  I didn't look at your code, so I could be incorrect -- it just seemed like that's how you described it.

Anyway, cheers.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Don Cullen

#3
mindfyre- yeah, way my site uses it, it looks up stats of an user upon request. *a* being the keyword (or letter? :P) here. i didnt design it in mind for multiple stats checking operations. but if i ever adapt it to be able to handle multiple users, yeah that's probably the way it should be done. thanks.

AC_Drkan- as for the code not working- did you attempt to debug it? because it works perfectly for me. suggestion, put in debugging code (ie, echoing where the script is as it goes thru code, also echoing var's contents, etc). Or maybe the script is aborting due to an error and you're not checking for the string "abort" since it returns that along with the reason why the script aborted (in other words, you should put in an error handler to trap abort events simply by checking to see if the first five letters of the string is abort and if so react based on that. if the script is indeed aborting, it most likely is aborting before it even starts the bnet rountines, so if thats the case, then the place to check would be near the start of the function before and during the login of bnet (not after since it is obviously aborting before it carries out commands).

[edited for clarity]
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.