function twitch_streams_get($game_name, $api_key) { if ($game_name === NULL) { return NULL; } $limit = 50; // Number of streams we request per query (Max 100) // $max_loops = 100; // Maximum number of loops before this code fails. // $loops = 0; $offset = 0; $ret_data = NULL; do { $retry = 4; $json_data = NULL; do { $retry--; // Assuming it's not the first loop, delay for 0.5-1.5 seconds, to play nice // if ($loops === 0) { rsleep(1.0, 0.5); } else { if ($loops === $max_loops) { echo "ERROR: Safe Twitch stream request limit exceeded. Are there nearly " . $limit * $loops . " streams? If so, you need to up the limit.\n"; return NULL; } } $loops++; // API only supports 100 streams per request // $api_url = "https://api.twitch.tv/kraken/streams/?game=" . $game_name . "&limit=" . $limit . "&offset=" . $offset . "&api_version=3"; $api_response = @file_get_contents($api_url); // @ surpresses PHP error: http://stackoverflow.com/a/15685966 // If we didn't get a correct response, then don't attempt to json decode. // if ($api_response === FALSE) { continue; } // Decode the Data // $json_data = json_decode($api_response, true); } while ($json_data === NULL && $retry !== 0); if ($json_data === NULL) { // If we can't get a complete set of Twitch streams, assume Twitch is down. // echo "ERROR: Unable to retieve streams via Twitch API (" . $loops . ")\n"; return NULL; } // If we currently have no data // if ($ret_data === NULL) { /* { // Confirm that the response matches our expected API version. Stored in the response header. // $expected_api_version = 3; $api_version = intval(http_find_header($http_response_header,'API-Version')); if ( $api_version !== $expected_api_version ) { echo "WARNING: Twitch API version mismatch. Expected: " . $expected_api_version . " Got: " . $api_version . "\n"; print_r($http_response_header); } } */ // Copy all Data // $ret_data = $json_data; // Keep a count of the number of requests that were needed to complete this query. // $ret_data['requests'] = 1; } else { // Update the total // $ret_data['_total'] = $json_data['_total']; // Append our list of streams to the returns list // $ret_data['streams'] = array_merge($ret_data['streams'], $json_data['streams']); // One more request was made // $ret_data['requests']++; } // Always increment our offset $offset += $limit; } while ($ret_data['_total'] > count($ret_data['streams'])); return $ret_data; }
function steam_curator_get($curator_id) { // Get the main HTML file for Avatar and Num Followers // // http://store.steampowered.com/curator/537829/ $main_url = "http://store.steampowered.com/curator/" . $curator_id . "/"; $main_html = file_get_html($main_url); if ($main_html === FALSE) { return NULL; } $ret = array(); $ret['followers'] = $main_html->find('.num_followers', 0)->plaintext; $ret['avatar'] = $main_html->find('.curator_avatar', 0)->src; // Use AJAX to get a 'next page' response, but of the first page w/ 20 elements // // http://store.steampowered.com/curators/ajaxgetcuratorrecommendations/537829//?query=&start=0&count=20 $game_url = "http://store.steampowered.com/curators/ajaxgetcuratorrecommendations/" . $curator_id . "//?query=&start=0&count=20"; $game_data = NULL; $retry = 4; do { rsleep(0.3); // Random Sleep, to make me less obvious I am a bot. // $game_data = @file_get_contents($game_url); } while ($game_data === FALSE && --$retry); if ($game_data === FALSE) { return NULL; } $game_json = json_decode($game_data); $game_html = str_get_html($game_json->results_html); $ret['games'] = array(); foreach ($game_html->find('.recommendation') as $elm) { $appid = $elm->attr['data-ds-appid']; // http://store.steampowered.com/apphoverpublic/201040?l=english&pagev6=true $more_url = "http://store.steampowered.com/apphoverpublic/" . $appid . "?l=english&pagev6=true"; $more_html = NULL; $retry = 4; do { rsleep(0.2); // Random Sleep, to make it less obvious I am a bot. // $more_html = file_get_html($more_url); } while ($more_html === FALSE && --$retry); if ($more_html === FALSE) { return NULL; } $rateup = 0; $comments = 0; $curator_url = ""; foreach ($elm->find('.recommendation_stats', 0)->find('.recommendation_stat') as $stat) { if (strpos($stat->find('img', 0)->src, 'rateup') !== FALSE) { $a =& $stat->find('a', 0); $curator_url = $a->href; $rateup = intval(trim($a->plaintext)); } else { if (strpos($stat->find('img', 0)->src, 'comment') !== FALSE) { $a =& $stat->find('a', 0); $curator_url = $a->href; $comments = intval(trim($a->plaintext)); } } } $discount = ""; $discount_available = $elm->find('.discount_pct', 0); if ($discount_available) { $discount = trim($discount_available->plaintext); } // Steam can be vague about what it returns for release dates, so have PHP parse it // $released_text = $more_html->find('.hover_release', 0)->plaintext; $released = strtotime(trim(substr($released_text, strpos($released_text, ":") + 1))); if ($released) { $released = date('Y-m-d', $released); } $ret['games'][] = array('appid' => $appid, 'banner' => $elm->find('.recommendation_app_small_cap', 0)->src, 'url' => $elm->find('.recommendation_details', 0)->find('a', 0)->href, 'info' => trim($elm->find('.recommendation_desc', 0)->plaintext), 'read_url' => $elm->find('.recommendation_readmore', 0)->find('a', 0)->href, 'name' => $more_html->find('h4', 0)->plaintext, 'released' => $released, 'desc' => trim($more_html->find('#hover_desc', 0)->plaintext), 'rateup' => $rateup, 'comments' => $comments, 'discount' => $discount, 'curator_url' => $curator_url); // If I want, I can build URLs like this to go to our personal curation comment pages. // http://steamcommunity.com/groups/ludum/curation/app/202730/ } return $ret; }