function handleJoinRequest($cookie, $group, $username, $choice, $save = 'hxcsrf.txt', $requestId = -1) { $xcsrf = file_exists($save) ? file_get_contents($save) : ''; $url = "http://www.roblox.com/My/GroupAdmin.aspx?gid={$group}"; switch ($choice) { case 'Accept': $choiceNumber = 1; break; case 'Decline': $choiceNumber = 2; break; default: die('Invalid choice.'); } if ($requestId === -1) { // This is so that if the function is being re called with the request ID already received you don't go through the whole process again (because it takes up a lot of time) $curl = curl_init($url); curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_COOKIEFILE => $cookie, CURLOPT_COOKIEJAR => $cookie)); $response = curl_exec($curl); $nextPost = getPostArray(substr($response, curl_getinfo($curl, CURLINFO_HEADER_SIZE)), array('ctl00$ctl00$cphRoblox$cphMyRobloxContent$JoinRequestsSearchBox' => $username, 'ctl00$ctl00$cphRoblox$cphMyRobloxContent$JoinRequestsSearchButton' => 'Search')); curl_close($curl); $curl = curl_init($url); curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $nextPost, CURLOPT_COOKIEFILE => $cookie, CURLOPT_COOKIEJAR => $cookie)); $response = curl_exec($curl); $doc = new DOMDocument(); $doc->loadHTML($response); $find = new DomXPath($doc); $nodes = $find->query("//span[contains(@class,'btn-control btn-control-medium accept-join-request')][1]"); foreach ($nodes as $node) { $requestId = $node->getAttribute('data-rbx-join-request'); } } $curl = curl_init('http://www.roblox.com/group/handle-join-request'); $post = array('groupJoinRequestId' => $requestId, 'accept' => $choiceNumber == 1 ? true : false); curl_setopt_array($curl, array(CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($post), CURLOPT_HEADER => true, CURLOPT_HTTPHEADER => array("X-CSRF-TOKEN: {$xcsrf}", 'Content-Length: ' . strlen(json_encode($post)), 'Content-Type: application/json; charset=UTF-8'), CURLOPT_COOKIEFILE => $cookie, CURLOPT_COOKIEJAR => $cookie, CURLOPT_RETURNTRANSFER => true)); $response = curl_exec($curl); $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); $responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); if ($responseCode != 200) { if ($responseCode == 403) { // 403 XCSRF Token Validation Failed $header = http_parse_headers(substr($response, 0, $headerSize)); $xcsrf = $header['X-CSRF-TOKEN']; file_put_contents($save, $xcsrf); return handleJoinRequest($cookie, $group, $username, $choice, $save, $requestId); } } $text = $choiceNumber == 1 ? 'ed' : 'd'; return "{$choice}{$text} {$username}'s join request."; }
function shout($cookie, $group, $msg) { $url = "http://www.roblox.com/My/Groups.aspx?gid={$group}"; $curl = curl_init($url); curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_COOKIEFILE => $cookie, CURLOPT_COOKIEJAR => $cookie, CURLOPT_FOLLOWLOCATION => true)); $response = curl_exec($curl); $nextPost = getPostArray($response, array('ctl00$cphRoblox$GroupStatusPane$StatusTextBox' => $msg, 'ctl00$cphRoblox$GroupStatusPane$StatusSubmitButton' => 'Group Shout')); curl_close($curl); $curl = curl_init($url); curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $nextPost, CURLOPT_COOKIEFILE => $cookie, CURLOPT_COOKIEJAR => $cookie)); if (curl_exec($curl)) { return "Shouted {$msg}."; } return 'Failure'; }
function getPlayers($ranks, $raw, $group, $rank, $limit, $online) { $players = array(); $role = getRoleSet($ranks, $rank); $start = time(); $url = "http://www.roblox.com/Groups/group.aspx?gid={$group}"; $curl = curl_init($url); // Start off by just getting the page // We need the correct validation before sending other requests curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_USERAGENT => 'Mozilla')); $response = curl_exec($curl); // Include __VIEWSTATE, __EVENTVALIDATION, and __VIEWSTATEGENERATOR in the next post array // Set the rank we want to search from while we're at it $nextPost = getPostArray($response, array('ctl00$cphRoblox$rbxGroupRoleSetMembersPane$dlRolesetList' => $role, 'ctl00$cphRoblox$rbxGroupRoleSetMembersPane$currentRoleSetID' => $role, '__ASYNCPOST' => 'true')); curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $nextPost)); $response = curl_exec($curl); $doc = new DOMDocument(); $doc->loadHTML($response); $find = new DomXPath($doc); // Do a dance to get the number of pages foreach ($find->query("(//div[contains(@id,'ctl00_cphRoblox_rbxGroupRoleSetMembersPane_dlUsers_Footer_ctl01_Div1')]//div[contains(@class,'paging_pagenums_container')])[1]") as $node) { $pages = $node->textContent; } if (!isset($pages)) { $pages = 1; } curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $nextPost)); $response = curl_exec($curl); for ($i = 1; $i <= $pages; $i++) { if ($limit != -1 && count($players) >= $limit) { break; } $players = getPlayersOnPage($response, $players, $limit, $online); // __VIEWSTATE and __EVENTVALIDATION are not updated as inputs, rather some weird format I don't recognize preg_match('#\\|__VIEWSTATE\\|(.*?)\\|.*\\|__EVENTVALIDATION\\|(.*?)\\|#', $response, $inputs); $nextPost = array('__VIEWSTATE' => $inputs[1], '__EVENTVALIDATION' => $inputs[2], '__ASYNCPOST' => 'true', 'ctl00$cphRoblox$rbxGroupRoleSetMembersPane$currentRoleSetID' => $role, 'ctl00$cphRoblox$rbxGroupRoleSetMembersPane$dlUsers_Footer$ctl01$HiddenInputButton' => '', 'ctl00$cphRoblox$rbxGroupRoleSetMembersPane$dlUsers_Footer$ctl01$PageTextBox' => $i + 1); curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $nextPost)); $response = curl_exec($curl); } if (!$raw) { echo 'Get time: ' . (time() - $start) . ' seconds<br>Players: ' . count($players) . '<br><br>'; } return $players; }
function getPlayers($ranks, $raw, $group, $rank, $limit, $online, $multiLimit) { $players = array(); $role = getRoleSet($ranks, $rank); $start = time(); $url = "http://www.roblox.com/Groups/group.aspx?gid={$group}"; $curl = curl_init($url); // Start off by just getting the page // We need the correct validation before sending other requests curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_USERAGENT => 'Mozilla')); $response = curl_exec($curl); // Include __VIEWSTATE, __EVENTVALIDATION, and __VIEWSTATEGENERATOR in the next post array // Set the rank we want to search from while we're at it $nextPost = getPostArray($response, array('ctl00$cphRoblox$rbxGroupRoleSetMembersPane$dlRolesetList' => $role, 'ctl00$cphRoblox$rbxGroupRoleSetMembersPane$currentRoleSetID' => $role, '__ASYNCPOST' => 'true')); $vs = $nextPost['__VIEWSTATE']; $ev = $nextPost['__EVENTVALIDATION']; curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $nextPost)); $response = curl_exec($curl); $doc = new DOMDocument(); $doc->loadHTML($response); $find = new DomXPath($doc); // Do a dance to get the number of pages foreach ($find->query("(//div[contains(@id,'ctl00_cphRoblox_rbxGroupRoleSetMembersPane_dlUsers_Footer_ctl01_Div1')]//div[contains(@class,'paging_pagenums_container')])[1]") as $node) { $pages = $node->textContent; } if (!isset($pages)) { $pages = 1; } curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $nextPost)); $response = curl_exec($curl); curl_close($curl); $players = getPlayersOnPage($response, $players, $limit, $online); if ($pages > $multiLimit) { $maxml = ceil($pages / $multiLimit); } else { $maxml = 1; } for ($ml = 0; $ml < $maxml; $ml++) { if ($limit != -1 && count($players) >= $limit) { break; } $requests = array(); $multi = curl_multi_init(); $max = ($ml + 1) * $multiLimit; if ($max > $pages) { $max = $pages - 1; } for ($i = 1 + $ml * $multiLimit; $i <= $max; $i++) { if ($limit != -1 && count($players) >= $limit) { break; } $nextPost = array('__VIEWSTATE' => $vs, '__EVENTVALIDATION' => $ev, '__ASYNCPOST' => 'true', 'ctl00$cphRoblox$rbxGroupRoleSetMembersPane$currentRoleSetID' => $role, 'ctl00$cphRoblox$rbxGroupRoleSetMembersPane$dlUsers_Footer$ctl01$HiddenInputButton' => '', 'ctl00$cphRoblox$rbxGroupRoleSetMembersPane$dlUsers_Footer$ctl01$PageTextBox' => $i + 1); $curl = curl_init($url); curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $nextPost, CURLOPT_USERAGENT => 'Mozilla')); array_push($requests, $curl); curl_multi_add_handle($multi, $curl); } do { curl_multi_exec($multi, $running); curl_multi_select($multi); } while ($running > 0); foreach ($requests as $index => $request) { $data = curl_multi_getcontent($request); $players = getPlayersOnPage($data, $players, $limit, $online); curl_close($request); curl_multi_remove_handle($multi, $request); } curl_multi_close($multi); } if (!$raw) { echo 'Get time: ' . (time() - $start) . ' seconds<br>Players: ' . count($players) . '<br><br>'; } return $players; }
function getPostArray($array) { foreach ($array as $key => $value) { echo "{$key} => {$value}<br>"; if (is_array($value)) { //If $value is an array, get it also getPostArray($value); } } }