<?php 
/*    Whatpulse Stats to UBB-Code Parser by lucb1e
        Version: 3 (Beta)
        Description: This file requests data from the Whatpulse API and puts it in the database.
        Last modified: See ./
        
        == Licence ==
        Code is completely free* to use for non-commercial** projects as long as credits to lucb1e.com are provided.
        Prohibited to use in commercial projects unless otherwise arranged with me via a 3rd-party logged medium such as private messages on GMOT.nl or e-mail (whatpulse@lucb1e.com).
        In the event of a licence change, any copies made before the change will remain under the old licence. You cannot change the licence yourself, even when you make a copy and host it yourself.
        *Free here is meant in the way of: free of charge and free to: modify, use, distribute, et cetera, provided that credits are given as mentioned above.
        **A commercial project is any project that is profited on in the sense of getting money. Wether that is via ads, paid users or another way does not matter.
    */
    
    // Settings
    // Subteam to look for
    
$subteam "GMOT";
    
    
// URL to file_get_contents the stats from.
    
$api_url "http://api.whatpulse.org/team.php?TeamID=1295&members=yes&format=json";
    
    
// Timestamp when the stats were obtained. In case they're being loaded from a file and not downloaded from the API, you might want to temporarily set a custom time (namely, the file's modification time).
    
$retrievaltime time();
    
    
// End of settings
    
    // Stuff to check before parsing
    
if (isset($_GET["source"])) {
        
highlight_file(__FILE__);
        exit;
    }
    
    if (
$_SERVER["REMOTE_ADDR"] != "")
        die(
"Not run from localhost; script killed. To view the source of this page, append ?source to the URL.");
    
    if (
file_exists("database_locked.php"))
        die(
"Database locked. Not updating.");
    
    
// Start parsing!
    
$time_start microtime(true);
    
    
// Retrieve the data from Whatpulse
    
$i 0;
    
$sane false;
    do {
        
$sane true;
        
$data file_get_contents($api_url);
        if (
$i 0) {
            echo 
"What the hell $i\r\n";
            
sleep($i 5);
        }
        echo 
$data "\r\n";
        
        if (
strlen($data) < 1024 250) { // It used to be ~400KB, this would be oddly small
            
$sane false;
        }
        
        
$tmpdata json_decode($datatrue);
        if (
json_last_error() != JSON_ERROR_NONE) {
            
$sane false;
        }
        
        if (!isset(
$tmpdata["Members"]) || !isset($tmpdata["Members"]["Member1000"]) || !isset($tmpdata["Members"]["Member1000"]["Clicks"])) {
            
$sane false;
        }
    }
    while (!
$sane && $i++ < 10);
    
    if (
strlen($data) < 1024 250 || strlen($data) > 1024 1024 10)
        die(
"Error: Whatpulse API data seems to be invalid (errorcode 1.0)");
    
    
$time_dataretrieval microtime(true);
    
    
// Parse the JSON and check for errors
    
$data json_decode($datatrue);
    if (
json_last_error() != JSON_ERROR_NONE)
        die(
"Error: Whatpulse API data seems to be invalid (errorcode 2." json_last_error() . ")");
    
    
// Sanity check on the data.
    
if (!isset($data["Members"]) || !isset($data["Members"]["Member1000"]) || !isset($data["Members"]["Member1000"]["Clicks"]))
        die(
"Error: Whatpulse API seems to have changed to something incompatible (errorcode 3.0)");
    
    if (!
$sane) {
        die(
"We're not supposed to get here :|");
    }
    
    
// So far so good; fire up the database connection and do some preparations.
    
require("sqlconn.php");
    
$db->query("UPDATE 3_users SET status = 'ex-member' WHERE status = 'just-left'") or die("Error: Query failure (errorcode 4.4)");
    
    
// Temporarily set everyone to just-left. After this we'll loop through the data and update everyone, so everyone who is still in will become 'normal-member' again. Everyone who isn't will, aptly, remain just-left.
    
$db->query("UPDATE 3_users SET status = 'just-left' WHERE status != 'ex-member'") or die("Error: Query failure (errorcode 4.5)");
    
    
// Start parsing the members into the database!
    
$seqnum $db->query("SELECT MAX(seqnum) FROM 3_updates") or die("Error: Query failure (errorcode 4.8)");
    
$seqnum $seqnum->fetch_row()[0] + 1;
    
    
$userquery $db->prepare("INSERT INTO 3_users
        VALUES (?, ?, 'just-joined')
        ON DUPLICATE KEY
        UPDATE username = ?,
            status = CASE status WHEN 'ex-member' THEN 'returned' ELSE 'normal-member' END"
);
    
    if (!
$userquery)
        die(
"Error: Query preparation failure (errorcode 4.3)");
    
    
$updatequery $db->prepare("INSERT INTO 3_updates
        VALUES (
$seqnum, ?, ?, ?, ?, ?, ?, ?, ?)");
    
    if (!
$updatequery)
        die(
"Error: Query preparation failure (errorcode 4.2)");
    
    foreach (
$data["Members"] as $member) {
        if (
stripos($member["Username"], "[" $subteam "]") !== 0)
            continue; 
// Not a member of the subteam we're looking for; skip this record
        
        
$members[$member["Keys"]] = $member;
    }
    
    
krsort($members);
    
    
$rank 1;
    foreach (
$members as $member) {
        if (
stripos($member["Username"], "[" $subteam "]") !== 0)
            continue; 
// Not a member of the subteam we're looking for; skip this record
        
        
$userquery->bind_param("iss",
            
$member["UserID"],
            
$member["Username"],
            
$member["Username"]);
        
        if (!
$userquery->execute()) { // Error :o
            
$fid fopen("database_locked.php""w"); // SHUT. DOWN. EVERYTHING. D:
            
fwrite($fid"<?php //" $userquery->error);
            
fclose($fid);
            die(
"Error: Query failure (errorcode 4.0)");
        }
        
        
$lastpulse strtotime($member["LastPulse"]); //Because it needs to be passed by reference in bind_param()
        
        
$updatequery->bind_param("iiiiiiii",
            
$member["UserID"],
            
$lastpulse,
            
$rank,
            
$member["Keys"],
            
$member["Clicks"],
            
$member["UploadMB"],
            
$member["DownloadMB"],
            
$member["UptimeSeconds"]);
        
        if (!
$updatequery->execute()) {
            
$fid fopen("database_locked.php""w"); // SHUT. DOWN. EVERYTHING. D:
            
fwrite($fid"<?php //" $updatequery->error);
            
fclose($fid);
            die(
"Error: Query failure (errorcode 4.6)");
        }
        
        
$rank++;
    }
    
    
$time_total microtime(true);
    
    
$time1 round(($time_dataretrieval $time_start) * 1000);
    
$time2 round(($time_total $time_start) * 1000);
    
    
$db->query("INSERT INTO 3_global VALUES($retrievaltime$time1$time2)") or die("Error: Query failure (errorcode 4.7)");