Last active
June 3, 2021 21:47
-
-
Save jasonrush/98cfe641a3496d0d97b34bd3ca0b66cd to your computer and use it in GitHub Desktop.
A quick PHP class to get information about open tickets on Spiceworks Cloud HelpDesk.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class spiceworks { | |
// Information used to log in and get ticket info. | |
private $loginURL = 'https://accounts.spiceworks.com/sign_in'; | |
private $dataURLOpen = 'https://on.spiceworks.com/api/tickets?filter%5Bstatus%5D%5Beq%5D=open'; | |
private $dataURLWaiting = 'https://on.spiceworks.com/api/tickets?filter%5Bstatus%5D%5Beq%5D=waiting'; | |
private $cookiePath = ''; | |
private $authToken = ''; | |
private $isLoggedIn = false; | |
// Information set by users to log in. | |
private $useragent = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2'; | |
private $user = ""; | |
private $pass = ""; | |
// Information returned from Spiceworks to be consumed by users. | |
public $users = null; | |
public $tickets = null; | |
// Basic constructor, allowing requesting username and password, and optionally tell it to gather info immediately. | |
function __construct( $username = "", $password = "", $loadInfo = false ){ | |
if( "" != $username ){ | |
$this->setUser( $username ); | |
} | |
if( "" != $password ){ | |
$this->setPass( $password ); | |
} | |
if( $loadInfo ){ | |
$this->loadInfo(); | |
} | |
} | |
public function setUser( $username ){ | |
$this->user = $username; | |
} | |
public function setPass( $password ){ | |
$this->pass = $password; | |
} | |
public function setUseragent( $useragent ){ | |
$this->useragent = $useragent; | |
} | |
private function setCookiePath(){ | |
if( '' == $this->cookiePath){ | |
$convertedEmail = str_replace( '@', '__', $this->user ); | |
$this->cookiePath = sys_get_temp_dir() . "/php_curl_$convertedEmail.txt"; | |
} | |
} | |
public function findToken(){ | |
$this->setCookiePath(); | |
$ch = curl_init(); | |
curl_setopt( $ch, CURLOPT_URL, $this->loginURL ); | |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); | |
curl_setopt( $ch, CURLOPT_AUTOREFERER, true ); | |
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true ); | |
curl_setopt( $ch, CURLOPT_USERAGENT, $this->useragent ); | |
curl_setopt( $ch, CURLOPT_COOKIEJAR, $this->cookiePath ); | |
curl_setopt( $ch, CURLOPT_COOKIEFILE, $this->cookiePath ); | |
$result = curl_exec( $ch ); | |
curl_close( $ch ); | |
// Request the signin page so we can get an authenticity token | |
// Search the HTML code for 'name="authenticity_token"', then find 'value="xxxxxx"' to get the token. | |
// <form class="form-vertical login-form" action="/sign_in" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="JPjU9FvfmwoxpcsobwdgTQKPh6EmKgCnInHqvEUwMT7umhoAHRYa6BVn36tjoLIiifjN4v/taUpAdrZYXkVI8w==" /> | |
$lines = explode( PHP_EOL, $result ); | |
// Find line with token. | |
foreach( $lines as $line ){ | |
if( false !== strpos( $line, 'name="authenticity_token"')){ | |
$tokenLine = $line; | |
break; | |
} | |
} | |
// If this line is found, we are already logged in (using the cookie file). | |
if( false !== strpos( $result, '<li><a href="/users/reset_password_request">reset your password</a></li>' ) ){ | |
$this->isLoggedIn = true; | |
return; | |
} | |
// Find token within line. | |
$tokenSearchStart = strpos( $tokenLine, 'name="authenticity_token"' ) + 25; | |
$tokenStart = strpos( $tokenLine, 'value="', $tokenSearchStart ) + 7; | |
$tokenEnd = strpos( $tokenLine, '"', $tokenStart + 1 ); | |
// Save token. | |
$this->authToken = substr( $tokenLine, $tokenStart, $tokenEnd - $tokenStart ); | |
} | |
public function login( $username = "", $password = "" ){ | |
// If a token hasn't been found yet, get an authentication token. | |
if( ! $this->isLoggedIn && '' == $this->authToken ){ | |
$this->findToken(); | |
} | |
if( "" != $username ){ | |
$this->setUser( $username ); | |
} | |
if( "" != $password ){ | |
$this->setPass( $password ); | |
} | |
// Cookie path is based on username, and we need the cookie path set to properly login. | |
$this->setCookiePath(); | |
// Submit the signin form | |
$formData = array( | |
'utf8' => '✓', | |
'authenticity_token' => $this->authToken, | |
'email' => $this->user, | |
'password' => $this->pass, | |
'success' => 'https://on.spiceworks.com/auth/spiceworks/callback', | |
'permission_denied' => 'https://accounts.spiceworks.com/', | |
'policy' => 'hosted_help_desk', | |
'commit' => 'Log+in', | |
); | |
$ch = curl_init(); | |
curl_setopt( $ch, CURLOPT_URL, $this->loginURL ); | |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); | |
curl_setopt( $ch, CURLOPT_AUTOREFERER, true ); | |
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true ); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
curl_setopt($ch, CURLOPT_HEADER, 1); | |
curl_setopt( $ch, CURLOPT_POST, true ); | |
curl_setopt( $ch, CURLOPT_POSTFIELDS, $formData ); | |
curl_setopt( $ch, CURLOPT_USERAGENT, $this->useragent ); | |
curl_setopt( $ch, CURLOPT_COOKIEJAR, $this->cookiePath ); | |
curl_setopt( $ch, CURLOPT_COOKIEFILE, $this->cookiePath ); | |
$result = curl_exec( $ch ); | |
curl_close( $ch ); | |
if( false !== strpos( $result, '<script id="data" type="application/json">' ) ){ | |
$this->isLoggedIn = true; | |
} | |
return $this->isLoggedIn; | |
} | |
// Page through users and tickets JSON data and save to the appropriate object properties. | |
public function loadInfo(){ | |
if( ! $this->isLoggedIn ){ | |
$this->login() or die( 'Login failed within loadInfo()' ); | |
} | |
// Cycle through open tickets | |
$page = 1; | |
$readMorePages = true; | |
while( $readMorePages ){ | |
$ch = curl_init(); | |
$pagedURL = $this->dataURLOpen; | |
if( $page > 1 ){ | |
$pagedURL .= "&page=$page"; | |
} | |
curl_setopt( $ch, CURLOPT_URL, $pagedURL ); | |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); | |
curl_setopt( $ch, CURLOPT_AUTOREFERER, true ); | |
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true ); | |
curl_setopt( $ch, CURLOPT_USERAGENT, $this->useragent ); | |
curl_setopt( $ch, CURLOPT_COOKIEJAR, $this->cookiePath ); | |
curl_setopt( $ch, CURLOPT_COOKIEFILE, $this->cookiePath ); | |
$result = curl_exec( $ch ); | |
curl_close( $ch ); | |
$parseCount = $this->parseJsonString( $result ); | |
if( 0 == $parseCount ){ | |
$readMorePages = false; | |
} | |
$page++; | |
} | |
// Cycle through Waiting tickets | |
$page = 1; | |
$readMorePages = true; | |
while( $readMorePages ){ | |
$ch = curl_init(); | |
$pagedURL = $this->dataURLWaiting; | |
if( $page > 1 ){ | |
$pagedURL .= "&page=$page"; | |
} | |
curl_setopt( $ch, CURLOPT_URL, $pagedURL ); | |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); | |
curl_setopt( $ch, CURLOPT_AUTOREFERER, true ); | |
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true ); | |
curl_setopt( $ch, CURLOPT_USERAGENT, $this->useragent ); | |
curl_setopt( $ch, CURLOPT_COOKIEJAR, $this->cookiePath ); | |
curl_setopt( $ch, CURLOPT_COOKIEFILE, $this->cookiePath ); | |
$result = curl_exec( $ch ); | |
curl_close( $ch ); | |
$parseCount = $this->parseJsonString( $result ); | |
if( 0 == $parseCount ){ | |
$readMorePages = false; | |
} | |
$page++; | |
} | |
} | |
// For each page of JSON data passed, parse through it and add any new users and/or tickets. | |
private function parseJsonString( $jsonString ){ | |
$jsonData = json_decode( $jsonString ); | |
// Track how many new users/tickets are parsed so we can tell if we've hit an empty page. | |
$parseCount = 0; | |
// Add all types of users to $users property, indexed by ID. | |
// If there are no more pages, the assorted user object properties aren't even set, just an empty Tickets property. | |
if( isset( $jsonData->users ) ){ | |
foreach( $jsonData->users as $user ){ | |
if( ! isset( $this->users[ $user->id ] ) ){ | |
$this->users[ $user->id ] = $user; | |
$parseCount++; | |
} | |
} | |
} | |
if( isset( $jsonData->archived_users ) ){ | |
foreach( $jsonData->archived_users as $user ){ | |
if( ! isset( $this->users[ $user->id ] ) ){ | |
$this->users[ $user->id ] = $user; | |
$parseCount++; | |
} | |
} | |
} | |
if( isset( $jsonData->end_users ) ){ | |
foreach( $jsonData->end_users as $user ){ | |
if( ! isset( $this->users[ $user->id ] ) ){ | |
$this->users[ $user->id ] = $user; | |
$parseCount++; | |
} | |
} | |
} | |
// Allow accessing tickets by ID. | |
foreach( $jsonData->tickets as $ticket ){ | |
if( ! isset( $this->tickets[ $ticket->id ] ) ){ | |
$ticket->creator->first_name = $this->users[ $ticket->creator->id ]->first_name; | |
$ticket->creator->last_name = $this->users[ $ticket->creator->id ]->last_name; | |
$ticket->creator->name = $this->users[ $ticket->creator->id ]->name; | |
$ticket->creator->email = $this->users[ $ticket->creator->id ]->email; | |
if( isset( $this->users[ $ticket->creator->id ]->phone_number ) ){ | |
$ticket->creator->phone_number = $this->users[ $ticket->creator->id ]->phone_number; | |
} | |
$this->tickets[ $ticket->id ] = $ticket; | |
$parseCount++; | |
} | |
} | |
return $parseCount; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment