Reddit Class References

[mmdeveloper@mmPrivateCloud lockexchange.mmdeveloper.tech]$ grep -n -r 'reddit::' * | grep -v 'loginTransparency.html'
classes/components/com_login.php:101:                external\apis\reddit::init('', '', config::$reddit['oAuthClientID'], driver::$encryption->decrypt(config::$reddit['oAuthSecret']), '');
classes/components/com_login.php:111:                $redditAccessToken = external\apis\reddit::makeCURLRequest('POST', external\apis\reddit::$apiURLs['noAuthBase'] . external\apis\reddit::$apiURLs['no_accesstoken'], $params);
classes/components/com_login.php:117:                    external\apis\reddit::init('', '', config::$reddit['oAuthClientID'], config::$reddit['oAuthSecret'], $redditAccessToken->access_token);
classes/components/com_login.php:118:                    external\apis\reddit::useAuth('bearer');
classes/components/com_login.php:122:                    $myRedditAccountInfo = external\apis\reddit::makeCURLRequest('GET', external\apis\reddit::$apiURLs['oAuthBase'] . external\apis\reddit::$apiURLs['o_me']);
classes/components/com_login.php:133:                        $subRedditInfo = external\apis\reddit::getSubredditInfo('lockpicking');
classes/components/com_login.php:147:                        $_SESSION['flair'] = external\apis\reddit::getUserFlair($_SESSION['myRedditAccountInfo']->name, 'lockpicking');
classes/components/com_cron.php:148:        external\apis\reddit::init(driver::$encryption->decrypt(config::$reddit['lockpickingMod_username']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_password']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_clientID']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_clientSecret']), '');
classes/components/com_cron.php:149:        $ret = external\apis\reddit::getAccessToken();
classes/components/com_cron.php:150:        external\apis\reddit::useAuth('accessToken');
classes/components/com_cron.php:165:            $list = external\apis\reddit::getSubredditUsersFlair(array(
classes/components/com_cron.php:211:            external\apis\reddit::init(driver::$encryption->decrypt(config::$reddit['lockpickingMod_username']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_password']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_clientID']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_clientSecret']));
classes/components/com_cron.php:212:            $ret = external\apis\reddit::getAccessToken();
classes/components/com_cron.php:213:            external\apis\reddit::useAuth('accessToken');
classes/components/com_cron.php:216:                $posts = external\apis\reddit::getSubredditPosts('locklot', 'new', array(
classes/components/com_cron.php:279:                                        $url = external\apis\reddit::$apiURLs['oAuthBase'] . '/r/locklot/api/flair';
classes/components/com_cron.php:287:                                        external\apis\reddit::makeCURLRequest($url, $postParams);
classes/components/com_cron.php:325:                    external\apis\reddit::init(config::$reddit['bot_username'], driver::$encryption->decrypt(config::$reddit['bot_password']), config::$reddit['bot_clientID'], driver::$encryption->decrypt(config::$reddit['bot_secret']));
classes/components/com_cron.php:326:                    $ret = external\apis\reddit::getAccessToken();
classes/components/com_cron.php:349:                            external\apis\reddit::useAuth('accessToken');
classes/components/com_cron.php:352:                            $ret = external\apis\reddit::getUserAbout($usernames[$userIndex]->username);
classes/components/com_cron.php:366:                                $history = external\apis\reddit::getUserHistory(array (
classes/components/com_cron.php:555:                    external\apis\reddit::init(config::$reddit['bot_username'], driver::$encryption->decrypt(config::$reddit['bot_password']), config::$reddit['bot_clientID'], driver::$encryption->decrypt(config::$reddit['bot_secret']));
classes/components/com_cron.php:556:                    $ret = external\apis\reddit::getAccessToken();
classes/components/com_cron.php:559:                        external\apis\reddit::useAuth('accessToken');
classes/components/com_cron.php:560:                        $ret = external\apis\reddit::getMe();
classes/components/com_cron.php:566:                                $ret = external\apis\reddit::composePM($emailRecord->parameters['to']['name'], $emailRecord->parameters['subject'], $emailRecord->parameters['message']);
snippets/loginForm.php:8:$url = utility::parseTemplate(external\apis\reddit::$apiURLs['noAuthBase'] . external\apis\reddit::$apiURLs['oAuthURL'], $params);

Login Class (com_login)

   1 <?php
   2 
   3 /**
   4  * This is the authentication class
   5  * @package MMExtranet
   6  */
   7 
   8 class com_login {
   9 
  10     /**
  11      * The class response to a request
  12      * @var mixed
  13      */
  14     public static $response = array();
  15 
  16     /**
  17      * The username to use for authentication
  18      * @var string
  19      */
  20     private static $username = '';
  21 
  22     /**
  23      * The password to use for authentication
  24      * @var string
  25      */
  26     private static $password = '';
  27 
  28     /**
  29      * The TOTP challenge response for two-factor, if applicable
  30      * @var string
  31      */
  32     private static $totpChallenge = '';
  33 
  34     /**
  35      * Temporary pointer for the user information to store in the session
  36      * @var string
  37      */
  38     private static $userData = false;
  39 
  40     private static $errors = array();
  41 
  42     /**
  43      * overall request pause time, in microseconds, to try and prevent timing attacks
  44      * @var string
  45      */
  46     private static $requestOverallWaitTime = 1000000;
  47 
  48     /**
  49      * pointer to store a timer class
  50      * @var class
  51      */
  52     private static $timerPointer = null;
  53 
  54     /**
  55      * pre-process method for code routing
  56      * @access public
  57      */
  58     public static function preProcess() {
  59         $request = request::getRequest();
  60         switch ($request['task']) {
  61             case 'logout':
  62             /*case 'showLoginForm':*/
  63             case 'redditauth':
  64                 self::{$request['task']}();
  65                 break;
  66 
  67             /*case 'login':
  68             case 'prestagelogin':
  69                 self::$timerPointer = new timer();
  70                 self::$timerPointer->startTimer();
  71                 self::{$request['task']}();
  72                 break;*/
  73         }
  74     }
  75 
  76     /**
  77      * This method will perform all the oAuth communication between the server and reddit
  78      * @access public
  79      * @return void
  80      */
  81     private static function redditauth() {
  82         //get $_GET request from reddit
  83         $request = request::getRequest();
  84 
  85         //if error message from reddit
  86         if (isset($request['error']) === true && mb_strlen($request['error']) > 0) {
  87             response::userUIMessage('Error: ' . $request['error'], errors::alert_warning, config::$relative);
  88         }
  89         else {
  90             //validate oAuth state
  91             if (isset($request['state']) === false || isset($_SESSION['oAuthState']) === false || $request['state'] !== $_SESSION['oAuthState']) {
  92                 response::userUIMessage('Invalid oAuth2 State', errors::alert_warning, config::$relative);
  93             }
  94             else {
  95                 //debug
  96                 //$apiOutput = array();
  97                 //okay let's get the temporary bearer token
  98 
  99                 //init reddit class with our apps oAuth credentials
 100                 external\apis\reddit::init('', '', config::$reddit['oAuthClientID'], driver::$encryption->decrypt(config::$reddit['oAuthSecret']), '');
 101 
 102                 //POST params
 103                 $params = array (
 104                         'grant_type' => 'authorization_code',
 105                         'code' => $request['code'],
 106                         'redirect_uri' => config::$reddit['redirectURL']
 107                     );
 108 
 109                 //make CURL post to get oAuth access token for logged in user
 110                 $redditAccessToken = external\apis\reddit::makeCURLRequest('POST', external\apis\reddit::$apiURLs['noAuthBase'] . external\apis\reddit::$apiURLs['no_accesstoken'], $params);
 111 
 112                 //debug
 113                 //$apiOutput['redditAccessToken'] = $redditAccessToken;
 114 
 115                 if ($redditAccessToken !== null) {
 116                     external\apis\reddit::init('', '', config::$reddit['oAuthClientID'], config::$reddit['oAuthSecret'], $redditAccessToken->access_token);
 117                     external\apis\reddit::useAuth('bearer');
 118 
 119                     $_SESSION['bearerToken'] = $redditAccessToken->access_token;
 120                     //okay.. so who is this?
 121                     $myRedditAccountInfo = external\apis\reddit::makeCURLRequest('GET', external\apis\reddit::$apiURLs['oAuthBase'] . external\apis\reddit::$apiURLs['o_me']);
 122 
 123                     //debug
 124                     //$apiOutput['myRedditAccountInfo'] = $myRedditAccountInfo;
 125 
 126                     if ($myRedditAccountInfo !== false) {
 127                         unset($myRedditAccountInfo->features);
 128 
 129                         $_SESSION['myRedditAccountInfo'] = $myRedditAccountInfo;
 130 
 131                         //check subreddit subscription/ban/etc status
 132                         $subRedditInfo = external\apis\reddit::getSubredditInfo('lockpicking');
 133 
 134                         //debug
 135                         //$apiOutput['subRedditInfo'] = $subRedditInfo;
 136 
 137                         unset($subRedditInfo->data->description);
 138                         unset($subRedditInfo->data->description_html);
 139                         unset($subRedditInfo->data->submit_text);
 140                         unset($subRedditInfo->data->submit_text_html);
 141                         unset($subRedditInfo->data->public_description);
 142                         unset($subRedditInfo->data->public_description_html);
 143                         $_SESSION['subRedditInfo_lockpicking'] = $subRedditInfo;
 144 
 145                         //get user flair
 146                         $_SESSION['flair'] = external\apis\reddit::getUserFlair($_SESSION['myRedditAccountInfo']->name, 'lockpicking');
 147                         $_SESSION['flair']->current->flair_css_class = trim(mb_eregi_replace(regexpstore::notLettersNumbersSpaceHyphenUnderscore, '', $_SESSION['flair']->current->flair_css_class));
 148 
 149                         //debug
 150                         //$apiOutput['subRedditFlair'] = $_SESSION['flair'];
 151 
 152                         unset($_SESSION['flair']->choices);
 153 
 154                         //debug
 155                         //@file_put_contents(config::$path . '/tmp/' . $_SESSION['myRedditAccountInfo']->name, var_export($apiOutput, true));
 156 
 157                         if (self::isUserPermittedAccessToSystem($myRedditAccountInfo, $subRedditInfo) === true) {
 158                             //check for account in system, create account if needed
 159                             $sql = 'SELECT
 160                                         COUNT(*)
 161                                     FROM
 162                                         sys_users
 163                                     WHERE
 164                                         redditUserID = :str_redditUserID
 165                                     LIMIT 1';
 166 
 167                             $params = array (
 168                                     ':str_redditUserID' => $_SESSION['myRedditAccountInfo']->id
 169                                 );
 170 
 171                             $num = intval(driver::$db->loadResult($sql, $params));
 172 
 173                             //create account
 174                             $createdAccount = false;
 175                             if ($num === 0) {
 176                                 $sql = 'INSERT INTO
 177                                             sys_users
 178                                         (redditUserID, locationID, enabled, loginSource, username, email, nameFirst, nameLast, created)
 179                                         VALUES(:redditUserID, :int_locationID, 1, :int_loginSource, :username, :email, :nameFirst, :nameLast, NOW())';
 180 
 181                                 $params = array (
 182                                         ':redditUserID' => $_SESSION['myRedditAccountInfo']->id,
 183                                         ':int_locationID' => 1,
 184                                         ':int_loginSource' => 2,
 185                                         ':username' => mb_strtolower($_SESSION['myRedditAccountInfo']->name),
 186                                         ':email' => 'nobody@place.com',
 187                                         ':nameLast' => 'User',
 188                                         ':nameFirst' => 'Reddit'
 189                                     );
 190 
 191 
 192                                 //create profile
 193                                 $ret = driver::$db->justquery($sql, $params);
 194 
 195                                 if ($ret === false) {
 196                                     response::userUIMessage(errors::genericBadDataError, errors::alert_warning, request::getReferer());
 197                                 }
 198                                 else {
 199                                     $createdAccount = true;
 200                                 }
 201                             } else {}
 202 
 203                             //now log into this system as that person
 204                             $ret = self::loginFromRedditoAuth($_SESSION['myRedditAccountInfo']->id);
 205 
 206                             if ($ret['bool'] === false) {
 207                                 response::userUIMessage($ret['errorMessage'], errors::alert_warning, config::$relative);
 208                             }
 209                             else {
 210                                 //update lockpicking flair
 211                                 $sql = 'UPDATE
 212                                             sys_users
 213                                         SET
 214                                             lockpicking_flair_css_class = :str_lockpicking_flair_css_class,
 215                                             lockpicking_flair_text = :str_lockpicking_flair_text
 216                                         WHERE
 217                                             userID = :int_userID';
 218 
 219                                 $params = array (
 220                                         ':str_lockpicking_flair_css_class' => $_SESSION['flair']->current->flair_css_class,
 221                                         ':str_lockpicking_flair_text' => $_SESSION['flair']->current->flair_text,
 222                                         ':int_userID' => $_SESSION['my']->userID
 223                                     );
 224 
 225                                 driver::$db->justquery($sql, $params);
 226 
 227 
 228                                 session_regenerate_id();
 229 
 230 
 231                                 if ($createdAccount === false) {
 232                                     controller::redirect(config::$relative . '?' . security::generateToken());
 233                                 }
 234                                 else {
 235                                     controller::redirect(controller::makeURL(array('component' => 'myprofile', 'task' => 'editMyProfile')));
 236                                 }
 237                             }
 238                         }
 239                         else {
 240                             response::userUIMessage('Your Reddit account does not meet the minimum requirements to use this application. Request denied: ' . implode(', ', self::$errors), errors::alert_danger, config::$relative);
 241                         }
 242                     }
 243                     else {
 244                         response::userUIMessage('Invalid API Response', errors::alert_warning, config::$relative);
 245                     }
 246                 }
 247                 else {
 248                     response::userUIMessage('Error obtaining oAuth Token', errors::alert_warning, config::$relative);
 249                 }
 250             }
 251         }
 252         die();
 253     }
 254 
 255     /**
 256      * This method will check if we should allow this user to log into our system
 257      * @access public
 258      * @param object $myRedditAccountInfo the API response from reddit "me" endpoint
 259      * @param string $subRedditInfo the trimmed api response from a subreddits "about" endpoint
 260      * @return bool
 261      */
 262     private static function isUserPermittedAccessToSystem($myRedditAccountInfo, $subRedditInfo): bool {
 263         $return = true;
 264 
 265         if (config::$reddit['systemAccessPermittingRequirements']['requireUserNotBannedFromLockpickingSub'] === true && $subRedditInfo->data->user_is_banned === true) {
 266             self::$errors[] = 'banned from /r/lockpicking';
 267             $return = false;
 268         } else {}
 269 
 270         if (config::$reddit['systemAccessPermittingRequirements']['requireUserNotMutedFromLockpickingSub'] === true && $subRedditInfo->data->user_is_muted === true) {
 271             self::$errors[] = 'muted from /r/lockpicking';
 272             $return = false;
 273         } else {}
 274 
 275         if (config::$reddit['systemAccessPermittingRequirements']['requireSubscriptionToLockpickingSub'] === true && $subRedditInfo->data->user_is_subscriber !== true) {
 276             self::$errors[] = 'not subscribed to /r/lockpicking';
 277             $return = false;
 278         } else {}
 279 
 280         if (config::$reddit['systemAccessPermittingRequirements']['requireVerifiedEmail'] === true && $myRedditAccountInfo->has_verified_email !== true) {
 281             self::$errors[] = 'no verified email';
 282             $return = false;
 283         } else {}
 284 
 285 
 286         //check minimum account age
 287         try {
 288             $minAccountCreationDate = driver::$dto->sub(DateInterval::createFromDateString(config::$reddit['systemAccessPermittingRequirements']['minimumAccountAge']));
 289         }
 290         catch(Exception $e) {
 291             $minAccountCreationDate = false;
 292         }
 293 
 294         if ($minAccountCreationDate !== false) {
 295             $signupDate = driver::$dto->setTimestamp($myRedditAccountInfo->created_utc);
 296 
 297             if ($signupDate > $minAccountCreationDate) {
 298                 self::$errors[] = 'Reddit account too young';
 299                 $return = false;
 300             } else {}
 301         } else {}
 302 
 303         return $return;
 304     }
 305 
 306 
 307 
 308 
 309     private static function loginFromRedditoAuth($redditUserID) {
 310         $response = array (
 311                 'bool' => false,
 312                 'errorMessage' => ''
 313             );
 314 
 315 
 316             $sql = 'SELECT
 317                         U.userID,
 318                         U.redditUserID,
 319                         U.locationID,
 320                         U.username,
 321                         U.email,
 322                         U.nameFirst,
 323                         U.nameLast,
 324                         L.locationID AS _currentLocationID,
 325                         L.locationName AS _currentLocationName,
 326                         L.locationNameShort AS _currentLocationNameShort,
 327                         L.locationType AS _currentLocationType
 328                     FROM
 329                         sys_users AS U
 330                     INNER JOIN
 331                         sys_locations AS L
 332                             ON L.locationID = U.locationID
 333                             AND L.enabled = 1
 334                     WHERE
 335                         U.redditUserID = :redditUserID
 336                         AND U.failedLoginAttempts <= 3
 337                         AND U.enabled = 1
 338                     LIMIT 1';
 339             $params = array (
 340                     ':redditUserID' => $redditUserID
 341                 );
 342 
 343             self::$userData = driver::$db->loadFirstRow($sql, $params);
 344 
 345             if (self::$userData !== false) {
 346 
 347                 //throw user data in session
 348                 $_SESSION['my'] = self::$userData;
 349 
 350                 //cache security roles
 351                 $_SESSION['my']->userRoles = security::getUserRoles($_SESSION['my']->userID);
 352 
 353                 $_SESSION['previousSessions'] = array();
 354 
 355                 //generate security tokens
 356                 $server = request::getServer();
 357                 $_SESSION['ip'] = $server['REMOTE_ADDR'];
 358                 $_SESSION['userVerificationData'] = config::$userVerificationData;
 359                 $localtoken = security::generateToken();
 360                 $_SESSION['localtoken'] = $localtoken;
 361                 security::setSessionLengthCookie(config::$sessionCookieName, $localtoken);
 362 
 363                 $response['bool'] = true;
 364 
 365 
 366 
 367                 //record successful login
 368                     $sql = 'UPDATE
 369                                 sys_users
 370                             SET
 371                                 lastLogin = NOW()
 372                             WHERE
 373                                 userID = :int_userID';
 374 
 375                     $params = array (
 376                             ':int_userID' => self::$userData->userID
 377                         );
 378 
 379                     driver::$db->justquery($sql, $params);
 380             }
 381             else {
 382                 $response['errorMessage'] = errors::userAccountNotProvisioned;
 383             }
 384 
 385         return $response;
 386     }
 387 
 388 
 389 
 390 
 391 
 392 
 393 
 394 
 395 
 396 
 397     /**
 398      * shows an internal login UI
 399      * @access private
 400      */
 401     /*private static function showLoginForm() {
 402         if (security::isLoggedIn() === false) {
 403             $responseParams = array (
 404                         'pageTitle' => array ('Login'),
 405                         'includes' => array (
 406                                     config::$path . '/templates/com_login/showloginform.php'
 407                                 )
 408                     );
 409 
 410             response::setResponse($responseParams);
 411         }
 412         else {
 413             controller::redirect();
 414         }
 415     }*/
 416 
 417     /**
 418      * logs the user out
 419      * @access private
 420      */
 421     private static function logout() {
 422         security::logout();
 423         controller::redirect(config::$absolute . '?' . security::generateToken());
 424     }
 425 
 426     /**
 427      * requires two-factor auth or attempts to auth the user credentials
 428      * @access private
 429      */
 430     /*private static function prestagelogin() {
 431         security::verifyPost();
 432 
 433         $post = request::getPost();
 434 
 435         $response = array (
 436                 'bool' => false,
 437                 'useTOTP' => false
 438             );
 439 
 440         if (utility::areAllArrayKeysSet($post, 'login_username', 'login_password') === true) {
 441             self::$username = trim(mb_strtolower(stripslashes($post['login_username'])));
 442 
 443             $sql = 'SELECT
 444                         totpkey
 445                     FROM
 446                         sys_users
 447                     WHERE
 448                         username = :username
 449                         AND totpkey IS NOT NULL
 450                         AND enabled = 1
 451                     LIMIT 1';
 452             $params = array (
 453                     ':username' => self::$username
 454                 );
 455             $totpkey = driver::$db->loadResult($sql, $params);
 456 
 457             //we validate the token in two places because validation also removes the token
 458             if ($totpkey === false) { //no two-factor authentication
 459                 self::login();
 460             }
 461             else {
 462                 security::validateToken($post['token']);
 463                 $response['bool'] = true;
 464                 $response['useTOTP'] = true;
 465                 response::setResponse($response);
 466 
 467                 self::$timerPointer->stopTimer();
 468                 $diff = self::$timerPointer->getTimerResult();
 469                 usleep(max(0, (self::$requestOverallWaitTime - $diff)));
 470                 response::sendJSONResponseToBrowser();
 471             }
 472         } else {}
 473     }*/
 474 
 475     /**
 476      * performs the login routing based off auth source for the user
 477      * @access private
 478      */
 479     /*private static function login() {
 480         security::verifyPost();
 481 
 482         $post = request::getPost();
 483         $server = request::getServer();
 484 
 485         security::validateToken($post['token']);
 486 
 487         $response = array (
 488                 'bool' => false,
 489                 'errorMessage' => ''
 490             );
 491 
 492         if (utility::areAllArrayKeysSet($post, 'login_username', 'login_password') === true) {
 493             self::$username = trim(mb_strtolower(stripslashes($post['login_username'])));
 494             self::$password = $post['login_password'];
 495 
 496             if (empty($post['login_totp']) === false) {
 497                 self::$totpChallenge = trim($post['login_totp']);
 498             } else {}
 499 
 500             $sql = 'SELECT
 501                         U.userID,
 502                         U.locationID,
 503                         U.loginSource,
 504                         U.username,
 505                         U.password,
 506                         U.email,
 507                         U.nameFirst,
 508                         U.nameLast,
 509                         U.totpkey,
 510                         U.failedLoginAttempts,
 511                         L.locationID AS _currentLocationID,
 512                         L.locationName AS _currentLocationName,
 513                         L.locationNameShort AS _currentLocationNameShort,
 514                         L.locationType AS _currentLocationType
 515                     FROM
 516                         sys_users AS U
 517                     INNER JOIN
 518                         sys_locations AS L
 519                             ON L.locationID = U.locationID
 520                             AND L.enabled = 1
 521                     WHERE
 522                         U.username=:username
 523                         AND U.failedLoginAttempts < :int_allowableConsecutiveFailedLogins
 524                         AND U.enabled = 1
 525                     LIMIT 1';
 526             $params = array (
 527                     ':username' => self::$username,
 528                     ':int_allowableConsecutiveFailedLogins' => config::$allowableConsecutiveFailedLogins
 529                 );
 530 
 531             self::$userData = driver::$db->loadFirstRow($sql, $params);
 532 
 533             if (self::$userData !== false) {
 534                 self::$userData->loginSource = intval(self::$userData->loginSource);
 535 
 536                 list($errorMessage, $isValid) = self::validateCredentials();
 537 
 538                 if ($isValid === true) { //credentials are good
 539                     //throw user data in session
 540                     $_SESSION['my'] = self::$userData;
 541 
 542                     //cache security roles
 543                     $_SESSION['my']->userRoles = security::getUserRoles($_SESSION['my']->userID);
 544 
 545                     $_SESSION['previousSessions'] = array();
 546 
 547                     //generate security tokens
 548                     $server = request::getServer();
 549                     $_SESSION['ip'] = $server['REMOTE_ADDR'];
 550                     $_SESSION['userVerificationData'] = config::$userVerificationData;
 551                     $localtoken = security::generateToken();
 552                     $_SESSION['localtoken'] = $localtoken;
 553                     security::setSessionLengthCookie(config::$sessionCookieName, $localtoken, (config::$protocol === 'https'));
 554 
 555                     //record successful login
 556                     $sql = 'UPDATE
 557                                 sys_users
 558                             SET
 559                                 lastLogin = NOW(),
 560                                 failedLoginAttempts = 0,
 561                                 lockoutReason = \'\',
 562                                 lockoutDateTime = \'\'
 563                             WHERE
 564                                 userID = :int_userID';
 565 
 566                     $params = array (
 567                             ':int_userID' => self::$userData->userID
 568                         );
 569 
 570                     driver::$db->justquery($sql, $params);
 571 
 572                     if (empty($post['redirect']) === false) {
 573                         $response['redirectTo'] = $post['redirect'];
 574                     }
 575                     else {
 576                         $response['redirectTo'] = config::$absolute;
 577                     }
 578 
 579                     $response['bool'] = true;
 580                 }
 581                 else {
 582                     $response['errorMessage'] = $errorMessage;
 583                 }
 584             }
 585             else {
 586                 $response['errorMessage'] = errors::userAccountNotProvisioned;
 587             }
 588         }
 589         else {
 590             $response['errorMessage'] = errors::genericBadDataError;
 591         }
 592 
 593         $response['redirectTo'] = config::$absolute . '?' . security::generateToken();
 594 
 595         response::setResponse($response);
 596 
 597         self::$timerPointer->stopTimer();
 598         $diff = self::$timerPointer->getTimerResult();
 599         usleep(max(0, (self::$requestOverallWaitTime - $diff)));
 600         response::sendJSONResponseToBrowser();
 601     }*/
 602 
 603     /**
 604      * validates the username and password against the auth source
 605      * @access private
 606      * @return array a failure message and an authentication request response
 607      */
 608     /*private static function validateCredentials(): array {
 609         $returnMsg = '';
 610 
 611         $post = request::getPost();
 612 
 613         $post['domain'] = driver::$encryption->decrypt($post['domain']);
 614 
 615         if ($post['domain'] !== false && empty(config::$authDomains[self::$userData->loginSource]) === false) {
 616             $post['domain'] = intval($post['domain']);
 617             $logonDomainProperties = config::$authDomains[$post['domain']];
 618 
 619             switch($logonDomainProperties['authType']) {
 620                 case 'local':
 621                     if (frameworkpasswords::verify(self::$password, self::$userData->password) === false) {
 622                         $returnMsg = errors::invalidLogonCredentials;
 623                         $returnValue = false;
 624 
 625                         $sql = 'UPDATE
 626                                     sys_users
 627                                 SET
 628                                     failedLoginAttempts = failedLoginAttempts + 1
 629                                 WHERE
 630                                 userID = :userID';
 631                         $params = array (
 632                             ':userID' => self::$userData->userID
 633                         );
 634 
 635                         driver::$db->justquery($sql, $params);
 636                     }
 637                     else {
 638                         if (frameworkpasswords::needsRehash(self::$userData->password) === true) {
 639                             //update with rehashed password
 640                             $sql = 'UPDATE
 641                                         sys_users
 642                                     SET
 643                                         password = :str_password
 644                                     WHERE
 645                                         userID = :int_userID';
 646 
 647                             $params = array (
 648                                     ':str_password' => frameworkpasswords::hash(self::$password),
 649                                     ':int_userID' => self::$userData->userID
 650                                 );
 651 
 652                             driver::$db->justquery($sql, $params);
 653                         } else {}
 654                         $returnValue = true;
 655                     }
 656                     break;
 657 
 658                 case 'ad':
 659                     $ldapsPointer = new ldaps($logonDomainProperties['ldapServer'], $logonDomainProperties['port'], $logonDomainProperties['baseDN']);
 660 
 661                     $ldapbind = $ldapsPointer->bind(self::$username . '@' . $logonDomainProperties['suffix'], self::$password);
 662 
 663                     if ($ldapbind === false || self::$password == '' || self::$username == '') {
 664                         $returnMsg = errors::invalidLogonCredentials;
 665                         $returnValue = false;
 666                     }
 667                     else {
 668                         $returnValue = true;
 669                     }
 670                     break;
 671 
 672                 case 'ldap':
 673                     $ldapsPointer = new ldaps($logonDomainProperties['ldapServer'], $logonDomainProperties['port'], $logonDomainProperties['baseDN']);
 674 
 675                     //bind to their LDAPS instance with our account
 676                     $adminBind = $ldapsPointer->bind($logonDomainProperties['account'][0] . '@' . $logonDomainProperties['suffix'], $logonDomainProperties['account'][1]);
 677                     if ($adminBind === true) {
 678                         $filter = utility::parseTemplate($ldapsPointer->templates['byMail'], array('email' => ldap_escape(self::$username, null, LDAP_ESCAPE_FILTER)));
 679                         $attributes = $ldapsPointer->getAttributesByFilter($filter, array('userprincipalname', 'sn', 'givenname', 'useraccountcontrol', 'mail', 'samaccountname'));
 680 
 681                         //if exactly one match, awesome
 682                         if ($attributes['count'] == 1) {
 683                             $userID = $attributes[0]['userprincipalname'][0];
 684                             $temp = $ldapsPointer->bind($userID, self::$password);
 685 
 686                             if ($temp === true) {
 687                                 //now update their user profile with their LDAP information
 688                                 $nameFirst = trim($attributes[0]['givenname'][0]);
 689                                 $nameLast = trim($attributes[0]['sn'][0]);
 690 
 691                                 if (mb_strlen($nameFirst) > 0 && mb_strlen($nameLast) > 0 && $nameFirst !== self::$userData->nameFirst && $nameLast !== self::$userData->nameLast) {
 692                                     $sql = 'UPDATE
 693                                                 sys_users
 694                                             SET
 695                                                 nameLast = :nameLast,
 696                                                 nameFirst = :nameFirst
 697                                             WHERE
 698                                                 userID = :int_userID';
 699                                     $params = array (
 700                                             ':int_userID' => self::$userData->userID,
 701                                             ':nameLast' => $nameLast,
 702                                             ':nameFirst' => $nameFirst
 703                                         );
 704                                     $driver::$db->justquery($sql, $params);
 705 
 706                                     //update data already pulled from DB for session
 707                                     self::$userData->nameLast = $nameLast;
 708                                     self::$userData->nameFirst = $nameFirst;
 709                                 } else {}
 710 
 711                                 $returnValue = true;
 712                             }
 713                             else {
 714                                 $returnMsg = errors::invalidLogonCredentials;
 715                                 $returnValue = false;
 716                             }
 717                         }
 718                         else {
 719                             $returnMsg = 'There was more than one account with that email address.';
 720                             $returnValue = false;
 721                         }
 722                     }
 723                     else {
 724                         $returnMsg = 'Could not create administrative bind against LDAP server';
 725                         $returnValue = false;
 726                     }
 727                     break;
 728 
 729                 default:
 730                     $returnMsg = 'Unrecognized Authentication Source';
 731                     $returnValue = false;
 732                     break;
 733             }
 734         }
 735         else {
 736             $returnMsg = 'Unrecognized Authentication Source';
 737             $returnValue = false;
 738         }
 739 
 740         //two factor authentication if enabled
 741         if ($returnValue === true && empty(self::$userData->totpkey) === false) {
 742             self::$userData->totpkey = driver::$encryption->decrypt(self::$userData->totpkey);
 743             $result = totp::verifyOTP(self::$userData->totpkey, self::$totpChallenge);
 744 
 745             if ($result === false) {
 746                 $returnMsg = 'Two-Factor Code was invalid';
 747                 $returnValue = false;
 748             }
 749             else {
 750                 $returnValue = true;
 751             }
 752 
 753         } else {}
 754 
 755         return array($returnMsg, $returnValue);
 756     }*/
 757 }
 758 ?>

Reddit PM Notifications (com_cron)

   1 <?php
   2 
   3 /**
   4  * This is the command line class of MMIntranet (typically for maintenance)
   5  * @package MMExtranet
   6  * @subpackage Command Line Tasks Worker
   7  * @filesource
   8  * @version 1.0
   9  */
  10 
  11 if (!defined('allowExecutionCron')) {die('Attempted Security Violation');} else {}
  12 
  13 class com_cron {
  14 
  15     /**
  16      * The cache prefix for this class
  17      * @var string
  18      */
  19     private static $cachePrefix = 'cron.';
  20 
  21     /**
  22      * This method executes necessary methods based on request data
  23      * @access public
  24      * @author Matt Ford
  25      */
  26     public static function preProcess() {
  27         $request = request::getRequest();
  28         switch ($request['task']) {
  29             case 'cronByMinute':
  30             case 'cronByHour':
  31             case 'cronByDay':
  32             case 'cronByWeek':
  33             case 'calculateSubredditMetrics':
  34             case 'lockLotAutoEndListings':
  35                 self::{$request['task']}();
  36                 break;
  37 
  38             default:
  39                 die('object routing test complete');
  40                 break;
  41         }
  42 
  43         die();
  44     }
  45 
  46     /**
  47      * runs all cron tasks that should be executed each minute
  48      * @access private
  49      */
  50     private static function cronByMinute() {
  51         $cacheID = self::$cachePrefix . 'cronJob_cronByMinute';
  52         if (cache::hasCache($cacheID) === false) {
  53             //create 'lock file'
  54             cache::writeCache($cacheID, 0, '60 seconds');
  55 
  56             //cycle through mail queue
  57             //self::sendMail();
  58             self::sendRedditPMs();
  59 
  60             self::processLocklotUserSummaryRequests();
  61 
  62             //remove 'lock file'
  63             cache::deleteCache($cacheID);
  64         } else {}
  65     }
  66 
  67     /**
  68      * runs hourly cron tasks
  69      * @access private
  70      */
  71     private static function cronByHour() {
  72         /*$cacheID = self::$cachePrefix . 'cronJob_cronByHour';
  73         if (cache::hasCache($cacheID, true) === false) {
  74             //create 'lock file'
  75             cache::writeCache($cacheID, 0, '60 minutes', true);
  76 
  77 
  78             //auto unlock accounts after period of time
  79             driver::$db->justquery('UPDATE sys_users SET enabled=1, failedLoginAttempts=0, lockoutReason="", lockoutDateTime=NULL WHERE TIME_TO_SEC(TIMEDIFF(NOW(), lockoutDateTime)) >= 3600');
  80 
  81 
  82             //remove 'lock file'
  83             cache::deleteCache($cacheID);
  84         } else {}*/
  85     }
  86 
  87     /**
  88      * runs daily cron tasks
  89      * @access private
  90      */
  91     private static function cronByDay() {
  92         $cacheID = self::$cachePrefix . 'cronJob_cronByDay';
  93         if (cache::hasCache($cacheID, true) === false) {
  94             //create 'lock file'
  95             cache::writeCache($cacheID, 0, '24 hours', true);
  96 
  97 
  98             //clean up expired email queue
  99             driver::$db->justquery('DELETE FROM sys_mailqueue WHERE expiry <= NOW()');
 100 
 101             driver::$db->justquery('DELETE FROM locklot_usersummaries WHERE expiry <= NOW()');
 102 
 103             self::calculateSubredditMetrics();
 104 
 105 
 106             //remove 'lock file'
 107             cache::deleteCache($cacheID);
 108         } else {}
 109     }
 110 
 111     /**
 112      * runs weekly cron tasks
 113      * @access private
 114      */
 115     private static function cronByWeek() {
 116         /*$cacheID = self::$cachePrefix . 'cronJob_cronByWeek';
 117         if (cache::hasCache($cacheID, true) === false) {
 118             //create 'lock file'
 119             cache::writeCache($cacheID, 0, '7 days', true);
 120 
 121             //delete old fingerprints
 122             driver::$db->query('DELETE FROM fingerprints WHERE DATEDIFF(NOW(), lastused) >= 21');
 123 
 124             //prune very inactive accounts
 125             $users = driver::$db->query('SELECT userID, username FROM sys_users WHERE DATEDIFF(NOW(), lastLogin) >= 180');
 126             $toDelete = array('ids' => array());
 127             foreach ($users as $user) {
 128                 $toDelete['ids'][] = $user->userID;
 129             }
 130             $numToDelete = count($toDelete['ids']);
 131 
 132 
 133             if ($numToDelete > 0) {
 134                 $temp = implode(',', array_values($toDelete['ids']));
 135                 driver::$db->beginTransaction();
 136                 driver::$db->justquery('DELETE FROM sys_users WHERE userID IN(' . $temp . ')');
 137                 driver::$db->justquery('DELETE FROM sys_security_groups_members WHERE userID IN(' . $temp . ')');
 138                 //driver::$db->justquery('DELETE FROM fingerprints WHERE fingerprintuserID IN(' . $temp . ')');
 139                 driver::$db->commitTransaction();
 140             } else {}
 141 
 142             //remove 'lock file'
 143             cache::deleteCache($cacheID);
 144         } else {}*/
 145     }
 146 
 147     private static function calculateSubredditMetrics() {
 148         external\apis\reddit::init(driver::$encryption->decrypt(config::$reddit['lockpickingMod_username']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_password']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_clientID']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_clientSecret']), '');
 149         $ret = external\apis\reddit::getAccessToken();
 150         external\apis\reddit::useAuth('accessToken');
 151 
 152         $plotcolor = array (
 153                 'blackbelt' => '#000000',
 154                 'redbelt' => '#FF0000',
 155                 'brownbelt' => '#8B4513',
 156                 'purplebelt' => '#800080',
 157                 'bluebelt' => '#0000FF',
 158                 'greenbelt' => '#00FF00',
 159                 'orangebelt' => '#FF4500',
 160                 'yellowbelt' => '#FFFF00',
 161                 'whitebelt' => '#FFFFFF'
 162             );
 163 
 164         if ($ret !== false) {
 165             $list = external\apis\reddit::getSubredditUsersFlair(array(
 166                     'subreddit' => 'lockpicking'
 167                 ));
 168 
 169             driver::$db->justquery('DELETE FROM lockpicking_flairmetrics');
 170 
 171             $inserts = array();
 172             $params = array();
 173 
 174             $sql = 'INSERT INTO lockpicking_flairmetrics
 175                         (flairname, count, plotcolor)
 176                         VALUES';
 177 
 178             $limit = count($list);
 179             $index = 0;
 180 
 181             foreach ($list as $k => $v) {
 182                 $inserts[] = '(:flair_' . $index . ', :count_' . $index . ', :color_' . $index . ')';
 183                 $params[':flair_' . $index] = $k;
 184                 $params[':count_' . $index] = $v;
 185 
 186                 if (array_key_exists($k, $plotcolor) === true) {
 187                     $params[':color_' . $index] = $plotcolor[$k];
 188                 }
 189                 else {
 190                     $params[':color_' . $index] = '';
 191                 }
 192 
 193                 ++$index;
 194             }
 195 
 196             if (count($inserts) > 0) {
 197                 $sql .= implode(',', $inserts);
 198 
 199                 driver::$db->justquery($sql, $params);
 200             } else {}
 201         } else {}
 202     }
 203 
 204     private static function lockLotAutoEndListings() {
 205         $cacheID = self::$cachePrefix . 'cronJob_lockLotAutoEndListings';
 206 
 207         //if (cache::hasCache($cacheID) === false) {
 208             //create 'lock file'
 209             cache::writeCache($cacheID, 0, '1 minute');
 210 
 211             external\apis\reddit::init(driver::$encryption->decrypt(config::$reddit['lockpickingMod_username']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_password']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_clientID']), driver::$encryption->decrypt(config::$reddit['lockpickingMod_clientSecret']));
 212             $ret = external\apis\reddit::getAccessToken();
 213             external\apis\reddit::useAuth('accessToken');
 214 
 215             if ($ret !== false) {
 216                 $posts = external\apis\reddit::getSubredditPosts('locklot', 'new', array(
 217                         'limit' => 50
 218                     ));
 219 
 220                 if (is_array($posts) === true) {
 221                     $limit = count($posts);
 222 
 223                     $ebayItemIDs = array();
 224 
 225                     for ($i = 0; $i < $limit; $i++) {
 226                         if ($posts[$i]->data->link_flair_text !== 'Ended!') {
 227                             switch ($posts[$i]->data->domain) {
 228                                 case 'ebay.com':
 229                                     $posts[$i]->data->url = explode('/', $posts[$i]->data->url);
 230                                     $itemID = intval(trim(end($posts[$i]->data->url), '?'));
 231                                     if ($itemID > 0) {
 232                                         $ebayItemIDs[$itemID] = array (
 233                                                 'type' => $posts[$i]->kind,
 234                                                 'id' => $posts[$i]->data->id,
 235                                                 'title' => $posts[$i]->data->title,
 236                                                 'user' => $posts[$i]->data->author
 237                                             );
 238                                     } else {}
 239                                     break;
 240                             }
 241                         } else {}
 242                     }
 243 
 244                     $ebayItemIDs = array_chunk($ebayItemIDs, 10, true);
 245                     $chunks = count($ebayItemIDs);
 246 
 247                     if ($chunks > 0) {
 248                         for ($chunkIndex = 0; $chunkIndex < $chunks; $chunkIndex++) {
 249                             $url = 'http://open.api.ebay.com/shopping?';
 250                             $getParams = array (
 251                                     'callname' => 'GetMultipleItems',
 252                                     'responseencoding' => 'JSON',
 253                                     'appid' => '{REDACTED}',
 254                                     'siteid' => 0,
 255                                     'version' => 967,
 256                                     'ItemID' => implode(',', array_keys($ebayItemIDs[$chunkIndex]))
 257                                 );
 258 
 259                             $response = curl::makeSingleRequest('GET', $url . http_build_query($getParams));
 260                             $response = @json_decode($response);
 261 
 262                             if ($response !== false) {
 263                                 if (isset($response->Item) === true) {
 264                                     $toMarkEnded = array();
 265 
 266 
 267                                     $limit = count($response->Item);
 268 
 269                                     for ($i = 0; $i < $limit; $i++) {
 270                                         if ($response->Item[$i]->ListingStatus !== 'Active') {
 271                                             $toMarkEnded[] = $response->Item[$i]->ItemID;
 272                                         } else {}
 273                                     }
 274 
 275 
 276 
 277                                     $limit = count($toMarkEnded);
 278                                     for ($i = 0; $i < $limit; $i++) {
 279                                         $url = external\apis\reddit::$apiURLs['oAuthBase'] . '/r/locklot/api/flair';
 280                                         $postParams = array (
 281                                                 'api_type' => 'json',
 282                                                 'css_class' => 'red',
 283                                                 'link' => $ebayItemIDs[$chunkIndex][$toMarkEnded[$i]]['type'] . '_' . $ebayItemIDs[$chunkIndex][$toMarkEnded[$i]]['id'],
 284                                                 'text' => 'Ended!'
 285                                             );
 286 
 287                                         external\apis\reddit::makeCURLRequest($url, $postParams);
 288                                         sleep(2);
 289                                     }
 290                                 } else {}
 291                             } else {}
 292                         }
 293                     } else {}
 294                 } else {}
 295             } else {}
 296 
 297             //remove 'lock file'
 298             cache::deleteCache($cacheID);
 299         //} else {}
 300     }
 301 
 302     private static function processLocklotUserSummaryRequests() {
 303         $cacheID = self::$cachePrefix . 'cronJob_processLocklotUserSummaryRequests';
 304 
 305         if (cache::hasCache($cacheID) === false) {
 306             //create 'lock file'
 307             cache::writeCache($cacheID, 0, '1 minute');
 308 
 309             $sql = 'SELECT
 310                         username
 311                     FROM
 312                         locklot_usersummaries
 313                     WHERE
 314                         status = 0
 315                     ORDER BY
 316                         queued ASC
 317                     LIMIT 3';
 318 
 319             $usernames = driver::$db->query($sql);
 320 
 321             if ($usernames !== false) {
 322                 $numberUsers = count($usernames);
 323 
 324                 if ($numberUsers > 0) {
 325                     external\apis\reddit::init(config::$reddit['bot_username'], driver::$encryption->decrypt(config::$reddit['bot_password']), config::$reddit['bot_clientID'], driver::$encryption->decrypt(config::$reddit['bot_secret']));
 326                     $ret = external\apis\reddit::getAccessToken();
 327 
 328                     if ($ret !== false) {
 329                         for ($userIndex = 0; $userIndex < $numberUsers; ++$userIndex) {
 330                             cache::writeCache($cacheID, 0, '1 minute');
 331 
 332                             //set to processing
 333                             $sql = 'UPDATE
 334                                         locklot_usersummaries
 335                                     SET
 336                                         status = 1
 337                                     WHERE
 338                                         username = :str_username';
 339 
 340                             $params = array(
 341                                     ':str_username' => $usernames[$userIndex]->username
 342                                 );
 343 
 344                             driver::$db->justquery($sql, $params);
 345 
 346 
 347                             $stats = array();
 348 
 349                             external\apis\reddit::useAuth('accessToken');
 350 
 351                             //get user info
 352                             $ret = external\apis\reddit::getUserAbout($usernames[$userIndex]->username);
 353 
 354                             if ($ret !== false) {
 355                                 cache::writeCache($cacheID, 0, '1 minute');
 356                                 $stats['created'] = $ret->data->created_utc;
 357                                 $stats['linkKarma'] = $ret->data->link_karma;
 358                                 $stats['commentKarma'] = $ret->data->comment_karma;
 359 
 360                                 //check minimum account age
 361                                 $stats['signupDate'] = driver::$dto->setTimestamp($stats['created']);
 362                                 $stats['accountAge'] = driver::$dto->diff($stats['signupDate']);
 363 
 364 
 365                                 //get history on /r/lockpicking
 366                                 $history = external\apis\reddit::getUserHistory(array (
 367                                             'username' => $usernames[$userIndex]->username,
 368                                             'category' => 'overview'
 369                                         ), function($record) {
 370                                             if (in_array($record->data->subreddit, array('lockpicking')) === false) {
 371                                                 return 0;
 372                                             } else {}
 373                                     });
 374 
 375                                 $numberHistoryItems = count($history);
 376                                 $stats['numLockpickingPosts'] = $numberHistoryItems;
 377                                 $stats['lockpickingKarma'] = 0;
 378                                 $stats['oldest'] = driver::$now;
 379                                 $stats['newest'] = 0;
 380 
 381                                 if ($numberHistoryItems > 0) {
 382                                     for ($historyItemIndex = 0; $historyItemIndex < $numberHistoryItems; $historyItemIndex++) {
 383                                         //track oldest post
 384                                         $stats['oldest'] = min($stats['oldest'], $history[$historyItemIndex]['created']);
 385 
 386                                         //track newest post
 387                                         $stats['newest'] = max($stats['newest'], $history[$historyItemIndex]['created']);
 388 
 389                                         //track total karma from that sub
 390                                         $stats['lockpickingKarma'] += $history[$historyItemIndex]['score'];
 391 
 392                                         //update cache record
 393                                         cache::writeCache($cacheID, 0, '1 minute');
 394                                     }
 395                                 }
 396                                 else {
 397                                     $stats['oldest'] = $stats['newest'] = false;
 398                                 }
 399 
 400                                 if ($stats['oldest'] !== false) {
 401                                     $stats['oldest'] = driver::$dto->setTimestamp($stats['oldest']);
 402                                     $stats['oldest_disp'] = $stats['oldest']->format(config::$dateFormats['insert_mysqlDateTime']);
 403                                 }
 404                                 else {
 405                                     $stats['oldest_disp'] = '0000-00-00 00:00:00';
 406                                 }
 407 
 408                                 if ($stats['newest'] !== false) {
 409                                     $stats['newest'] = driver::$dto->setTimestamp($stats['newest']);
 410                                     $stats['newest_disp'] = $stats['newest']->format(config::$dateFormats['insert_mysqlDateTime']);
 411                                 }
 412                                 else {
 413                                     $stats['newest_disp'] = '0000-00-00 00:00:00';
 414                                 }
 415 
 416                                 if ($stats['oldest'] !== false && $stats['newest'] !== false) {
 417                                     $stats['lockpickingLifespan'] = $stats['oldest']->diff($stats['newest']);
 418                                     $stats['lockpickingLifespan'] = $stats['lockpickingLifespan']->days . ' Days';
 419                                 }
 420                                 else {
 421                                     $stats['lockpickingLifespan'] = '0';
 422                                 }
 423 
 424                                 //update DB record
 425                                 $sql = 'UPDATE
 426                                             locklot_usersummaries
 427                                         SET
 428                                             status = 2,
 429                                             accountAge = :int_accountAge,
 430                                             postKarma = :int_postKarma,
 431                                             commentKarma = :int_commentKarma,
 432                                             numLPContributions = :int_numLPContributions,
 433                                             oldestLPPost = :oldestLPPost,
 434                                             newestLPPost = :newestLPPost,
 435                                             daysLPLifespan = :int_daysLPLifespan,
 436                                             totalLPKarma = :int_totalLPKarma
 437                                         WHERE
 438                                             username = :str_username';
 439 
 440                                 $params = array(
 441                                         ':str_username' => $usernames[$userIndex]->username,
 442                                         ':int_accountAge' => $stats['accountAge']->days,
 443                                         ':int_postKarma' => $stats['linkKarma'],
 444                                         ':int_commentKarma' => $stats['commentKarma'],
 445                                         ':int_numLPContributions' => $stats['numLockpickingPosts'],
 446                                         ':oldestLPPost' => $stats['oldest_disp'],
 447                                         ':newestLPPost' => $stats['newest_disp'],
 448                                         ':int_daysLPLifespan' => $stats['lockpickingLifespan'],
 449                                         ':int_totalLPKarma' => $stats['lockpickingKarma']
 450                                     );
 451 
 452                                 driver::$db->justquery($sql, $params);
 453                             }
 454                             else {
 455                                 echo 'User does not exist' . "\n";
 456 
 457                                 //delete request
 458                                 $sql = 'DELETE FROM
 459                                             locklot_usersummaries
 460                                         WHERE
 461                                             username = :str_username';
 462 
 463                                 $params = array(
 464                                         ':str_username' => $usernames[$userIndex]->username
 465                                     );
 466 
 467                                 driver::$db->justquery($sql, $params);
 468                             }
 469 
 470 
 471                             //give the API a break
 472                             sleep(3);
 473                         }
 474                     }
 475                     else {
 476                         echo 'Error with oAuth handshake' . "\n";
 477                     }
 478                 } else {}
 479             }
 480             else {
 481                 var_dump($usernames);
 482             }
 483 
 484             //remove 'lock file'
 485             cache::deleteCache($cacheID);
 486         } else {}
 487     }
 488 
 489     /**
 490      * Loops over AD/LDAP auth sources and caches a user list. Not currently in use and hasn't been tested in a long time.
 491      * @access private
 492      */
 493     private static function cacheLDAPUsers() {
 494         /*$usesLDAP = false;
 495         foreach (controller_config::$authDomains as $domainID => $properties) {
 496             if ($properties['authType'] === 'ldap' || $properties['authType'] === 'ad') {
 497                 $usesLDAP = true;
 498                 break;
 499             } else {}
 500         }
 501 
 502         if ($usesLDAP === true) {
 503             foreach (controller_config::$authDomains as $domainID => $properties) {
 504                 if ($properties['authType'] === 'ldap' || $properties['authType'] === 'ad') {
 505                     $ldapsPointer = new ldaps($properties['ldapServer'], $properties['port'], $properties['baseDN']);
 506                     if ($ldapsPointer->connection === false) {
 507                         continue;
 508                     }
 509                     else {
 510                         $ldapbind = $ldapsPointer->bind($properties['account'][0], $properties['account'][1]);
 511                         if ($ldapbind === false) {
 512                             continue;
 513                         }
 514                         else {
 515                             $users[$properties['netBIOSName']] = array();
 516                             $records = $ldapsPointer->getAttributesByFilter($ldapsPointer->templates['enabledUsers'], array('samaccountname', 'mail', 'givenname', 'sn'), 0);
 517                             $limit = $records['count'];
 518                             for ($i = 0; $i < $limit; $i++) {
 519                                 $users[$properties['netBIOSName']][mb_strtolower($records[$i]['sn'][0] . $records[$i]['givenname'][0])] = array(
 520                                         'sn' => ucfirst($records[$i]['sn'][0]),
 521                                         'givenname' => ucfirst($records[$i]['givenname'][0]),
 522                                         'mail' => $records[$i]['mail'][0],
 523                                         'samaccountname' => $records[$i]['samaccountname'][0]
 524                                     );
 525                             }
 526                             $records = array();
 527                             ksort($users[$properties['netBIOSName']]);
 528                         }
 529                     }
 530                     $ldapsPointer->close();
 531                 } else {}
 532             }
 533         }
 534         else {
 535             $users = array();
 536         }
 537 
 538         cache::writeCache('ldapUsers', serialize($users), 0);*/
 539     }
 540 
 541     private static function sendRedditPMs() {
 542         $cacheID = self::$cachePrefix . 'cronJob_sendRedditPMs';
 543         if (cache::hasCache($cacheID) === false) {
 544             cache::writeCache($cacheID, 0, '5 minutes');
 545 
 546 
 547             $emailQueue = driver::$db->query('SELECT * FROM sys_mailqueue WHERE expiry >= NOW() LIMIT 25');
 548             if ($emailQueue !== false) {
 549                 $deleteQueue = array();
 550                 $updateQueue = array();
 551 
 552 
 553                 $limit = count($emailQueue);
 554                 if ($limit > 0) {
 555                     external\apis\reddit::init(config::$reddit['bot_username'], driver::$encryption->decrypt(config::$reddit['bot_password']), config::$reddit['bot_clientID'], driver::$encryption->decrypt(config::$reddit['bot_secret']));
 556                     $ret = external\apis\reddit::getAccessToken();
 557 
 558                     if ($ret !== false) {
 559                         external\apis\reddit::useAuth('accessToken');
 560                         $ret = external\apis\reddit::getMe();
 561 
 562                         if ($ret !== false) {
 563                             for ($i = 0; $i < $limit; $i++) {
 564                                 $emailRecord = $emailQueue[$i];
 565                                 $emailRecord->parameters = json_decode($emailRecord->parameters, true);
 566                                 $ret = external\apis\reddit::composePM($emailRecord->parameters['to']['name'], $emailRecord->parameters['subject'], $emailRecord->parameters['message']);
 567 
 568                                 if ($ret !== false) {
 569                                     $deleteQueue[] = $emailRecord->emailID;
 570                                 }
 571                                 else {
 572                                     $updateQueue[] = $emailRecord->emailID;
 573                                 }
 574 
 575                                 //throttle PMs to once every 2 seconds
 576                                 sleep(2);
 577                             }
 578 
 579                             if (count($deleteQueue) > 0) {
 580                                 $sql = 'DELETE FROM sys_mailqueue WHERE emailID IN(' . implode(',', $deleteQueue) . ')';
 581                                 driver::$db->justquery($sql);
 582                             } else {}
 583 
 584                             if (count($updateQueue) > 0) {
 585                                 $sql = 'UPDATE sys_mailqueue SET lastTry=NOW() WHERE emailID IN(' . implode(',', $updateQueue) . ')';
 586                                 driver::$db->justquery($sql);
 587                             } else {}
 588                         } else {}
 589                     } else {}
 590                 } else {}
 591             } else {}
 592 
 593 
 594             cache::deleteCache($cacheID);
 595         } else {}
 596     }
 597 
 598     /**
 599      * takes a chunk out of the mail queue for sending
 600      * @access private
 601      */
 602     private static function sendMail() {
 603         /*$cacheID = self::$cachePrefix . 'cronJob_sendMail';
 604         if (cache::hasCache($cacheID) === false) {
 605             cache::writeCache($cacheID, 0, '5 minutes');
 606 
 607 
 608             $emailQueue = driver::$db->query('SELECT * FROM sys_mailqueue WHERE expiry >= NOW() LIMIT 50');
 609             if ($emailQueue !== false) {
 610                 $deleteQueue = array();
 611                 $updateQueue = array();
 612 
 613 
 614                 $limit = count($emailQueue);
 615                 for ($i = 0; $i < $limit; $i++) {
 616                     $emailRecord = $emailQueue[$i];
 617                     $emailRecord->parameters = json_decode($emailRecord->parameters, true);
 618 
 619                     $ret = mail::sendMail($emailRecord->parameters['to'], $emailRecord->parameters['subject'], $emailRecord->parameters['message'], $emailRecord->parameters['headers'], $emailRecord->parameters['attachments'], $emailRecord->parameters['iCal']);
 620 
 621                     if ($ret === true) {
 622                         $deleteQueue[] = $emailRecord->emailID;
 623                     }
 624                     else {
 625                         $updateQueue[] = $emailRecord->emailID;
 626                     }
 627                 }
 628 
 629                 if (count($deleteQueue) > 0) {
 630                     $sql = 'DELETE FROM sys_mailqueue WHERE emailID IN(' . implode(',', $deleteQueue) . ')';
 631                     driver::$db->justquery($sql);
 632                 } else {}
 633 
 634                 if (count($updateQueue) > 0) {
 635                     $sql = 'UPDATE sys_mailqueue SET lastTry=NOW() WHERE emailID IN(' . implode(',', $updateQueue) . ')';
 636                     driver::$db->justquery($sql);
 637                 } else {}
 638             } else {}
 639 
 640 
 641             cache::deleteCache($cacheID);
 642         } else {}*/
 643     }
 644 }
 645 ?>

Reddit Class

   1 <?php
   2 namespace external\apis;
   3 
   4 /**
   5  * This is the reddit API class
   6  * @package MMExtranet
   7  */
   8 
   9 
  10 class reddit {
  11 
  12     /**
  13      * Reddit Username
  14      * @var string
  15      */
  16     private static $username = '';
  17 
  18     /**
  19      * Reddit Password (encrypted)
  20      * @var string
  21      */
  22     private static $password = '';
  23 
  24     /**
  25      * Reddit App Client-ID
  26      * @var string
  27      */
  28     private static $clientID = '';
  29 
  30     /**
  31      * Reddit App Client Secret
  32      * @var string
  33      */
  34     private static $clientSecret = '';
  35 
  36     /**
  37      * Reddit App Bearer Token
  38      * @var string
  39      */
  40     private static $bearerToken = '';
  41 
  42     /**
  43      * error messages bucket
  44      * @var array
  45      */
  46     public static $errors = array();
  47 
  48 
  49 
  50 
  51     /*
  52         API Endpoints
  53      */
  54     public static $apiURLs = array (
  55             'noAuthBase' => 'https://www.reddit.com',
  56             'oAuthBase' => 'https://oauth.reddit.com',
  57             'no_accesstoken' => '/api/v1/access_token',
  58 
  59             'oAuthURL' => '/api/v1/authorize?client_id=%%clientid%%&response_type=code&state=%%state%%&redirect_uri=%%redirecturl%%&duration=temporary&scope=identity read flair',
  60 
  61             'o_aboutuser' => '/user/%%username%%/about',
  62             'o_me' => '/api/v1/me',
  63             'o_submit' => '/api/submit',
  64             'o_delete' => '/api/del',
  65             'o_userhistory' => '/user/%%username%%/%%category%%?',
  66             'o_composepm' => '/api/compose',
  67             'o_subredditabout' => '/r/%%subreddit%%/about',
  68             'o_subredditposts' => '/r/%%subreddit%%/%%sort%%/?',
  69             'no_subredditposts' => '/r/%%subreddit%%/%%sort%%.json?',
  70             'no_subredditcomments' => '/r/%%subreddit%%/comments.json?',
  71             'o_subredditpostcomments' => '/r/%%subreddit%%/comments/%%postid%%?',
  72             'o_flairselector' => '/r/%%subreddit%%/api/flairselector',
  73             'o_userflairlist' => '/r/%%subreddit%%/api/flairlist?'
  74         );
  75 
  76 
  77     /**
  78      * oAuth Temporary Access Token JSON Object
  79      * @var object
  80      */
  81     private static $accesstoken = '';
  82 
  83     /**
  84      * Reddit Me object
  85      * @var object
  86      */
  87     public static $me = '';
  88 
  89     /**
  90      * cURL Authentication Type
  91      * @var array
  92      */
  93     public static $authType = '';
  94 
  95 
  96 
  97     /**
  98      * This method performs the oAuth initialization to obtain a temporary token
  99      * @access public
 100      * @param string \$username
 101      * @param string \$password
 102      * @param string \$clientID
 103      * @param string \$clientSecret
 104      * @param string \$bearerToken
 105      * @return void
 106      */
 107     public static function init(string $username, string $password, string $clientID, string $clientSecret, string $bearerToken = '') {
 108         self::$username = $username;
 109         self::$password = $password;
 110         self::$clientID = $clientID;
 111         self::$clientSecret = $clientSecret;
 112         self::$bearerToken = $bearerToken;
 113     }
 114 
 115     /**
 116      * This method will retrieve user contribution history
 117      *$history = external\apis\reddit::getUserHistory(array (
 118      *               'username' => $redditUsername,
 119      *               'category' => 'overview'
 120      *           ), function($record) {
 121      *               if (in_array($record->data->subreddit, array('lockpicking')) === false) {
 122      *                   return false;
 123      *               } else {}
 124      *
 125      *               return true;
 126      *       });
 127      * @access public
 128      * @param array $configParams array of config values such as username, category, max pages, return counts, etc
 129      * @param mixed $filterFunction anonymous function (or bool false) that returns boolean if record is to be counted. This function must accept one argument, an API result one at a time.
 130      * @param array $getParams array of GET parameters
 131      * @param array $records progressively growing array of matching records passed by reference
 132      * @return array
 133      */
 134     public static function getUserHistory(array $configParams = array(), $filterFunction = false, array $getParams = array()): array {
 135         $configParams['username'] = $configParams['username'] ?? '';
 136         $configParams['category'] = $configParams['category'] ?? 'overview';
 137         $configParams['currentPageNumber'] = $configParams['currentPageNumber'] ?? 0;
 138         $configParams['maxPages'] = $configParams['maxPages'] ?? 100;
 139         $getParams['limit'] = $getParams['limit'] ?? 100;
 140 
 141         $records = array();
 142 
 143         $break = false;
 144 
 145         while($break === false) {
 146             $url = self::$apiURLs['oAuthBase'] . self::parseTemplate(self::$apiURLs['o_userhistory'], array (
 147                     'username' => $configParams['username'],
 148                     'category' => $configParams['category']
 149                 ));
 150 
 151             $apiResponse = self::makeCURLRequest('GET', $url . http_build_query($getParams));
 152 
 153             if ($apiResponse !== false) {
 154                 ++$configParams['currentPageNumber'];
 155                 $apiResponse = $apiResponse->data;
 156 
 157                 $limit = count($apiResponse->children);
 158 
 159                 for ($i = 0; $i < $limit; $i++) {
 160                     $retVal = 1;
 161 
 162                     if ($filterFunction !== false && is_callable($filterFunction) === true) {
 163                         $retVal = $filterFunction($apiResponse->children[$i]);
 164                     } else {}
 165 
 166                     if ($retVal === -1) {
 167                         $break = true;
 168                         break;
 169                     }
 170                     elseif ($retVal === 0) {
 171                         //skip
 172                     }
 173                     else {
 174                         $records[] = array (
 175                                 'kind' => $apiResponse->children[$i]->kind,
 176                                 'id' => $apiResponse->children[$i]->data->id,
 177                                 'title' => ($apiResponse->children[$i]->data->link_title ?? $apiResponse->children[$i]->data->title ?? ''),
 178                                 'score' => $apiResponse->children[$i]->data->score,
 179                                 'created' => $apiResponse->children[$i]->data->created
 180                             );
 181                     }
 182                 }
 183 
 184                 $getParams['count'] = (empty($getParams['count']) === false) ? $getParams['count'] : 0;
 185                 $getParams['count'] += $i;
 186                 $getParams['after'] = $apiResponse->after;
 187 
 188                 if (empty($getParams['after']) === true || $configParams['maxPages'] === $configParams['currentPageNumber']) {
 189                     $break = true;
 190                 }
 191                 else {
 192                     sleep(1);
 193                 }
 194             }
 195             else {
 196                 $break = true;
 197             }
 198         }
 199 
 200         return $records;
 201     }
 202 
 203     /**
 204      * This method will retrieve user contribution history
 205      *$history = external\apis\reddit::getUserHistory(array (
 206      *               'username' => $redditUsername,
 207      *               'category' => 'overview'
 208      *           ), function($record) {
 209      *               if (in_array($record->data->subreddit, array('lockpicking')) === false) {
 210      *                   return false;
 211      *               } else {}
 212      *
 213      *               return true;
 214      *       });
 215      * @access public
 216      * @param array $configParams array of config values such as username, category, max pages, return counts, etc
 217      * @param mixed $filterFunction anonymous function (or bool false) that returns boolean if record is to be counted. This function must accept one argument, an API result one at a time.
 218      * @param array $getParams array of GET parameters
 219      * @param array $records progressively growing array of matching records passed by reference
 220      * @return array
 221      */
 222     public static function getSubredditUsersFlair(array $configParams = array(), $filterFunction = false, array $getParams = array()): array {
 223         $configParams['subreddit'] = $configParams['subreddit'] ?? '';
 224         $configParams['currentPageNumber'] = $configParams['currentPageNumber'] ?? 0;
 225         $configParams['maxPages'] = $configParams['maxPages'] ?? 200;
 226         $getParams['limit'] = $getParams['limit'] ?? 100;
 227 
 228         $records = array();
 229 
 230         $break = false;
 231 
 232         while($break === false) {
 233             $url = self::$apiURLs['oAuthBase'] . self::parseTemplate(self::$apiURLs['o_userflairlist'], array (
 234                     'subreddit' => $configParams['subreddit']
 235                 ));
 236 
 237             $apiResponse = self::makeCURLRequest('GET', $url . http_build_query($getParams));
 238 
 239             if ($apiResponse !== false) {
 240                 ++$configParams['currentPageNumber'];
 241 
 242 
 243                 $limit = count($apiResponse->users);
 244                 for ($i = 0; $i < $limit; $i++) {
 245                     $retVal = 1;
 246 
 247                     if ($filterFunction !== false && is_callable($filterFunction) === true) {
 248                         $retVal = $filterFunction($apiResponse->children[$i]);
 249                     } else {}
 250 
 251                     if ($retVal === -1) {
 252                         $break = true;
 253                         break;
 254                     }
 255                     elseif ($retVal === 0) {
 256                         //skip
 257                     }
 258                     else {
 259                         $apiResponse->users[$i]->flair_css_class = trim($apiResponse->users[$i]->flair_css_class);
 260                         $apiResponse->users[$i]->flair_css_class = mb_strtolower($apiResponse->users[$i]->flair_css_class);
 261                         $apiResponse->users[$i]->flair_css_class = ($apiResponse->users[$i]->flair_css_class === '') ? '[blank]' : $apiResponse->users[$i]->flair_css_class;
 262                         if (array_key_exists($apiResponse->users[$i]->flair_css_class, $records) === true) {
 263                             ++$records[$apiResponse->users[$i]->flair_css_class];
 264                         }
 265                         else {
 266                             $records[$apiResponse->users[$i]->flair_css_class] = 1;
 267                         }
 268                     }
 269                 }
 270 
 271                 $getParams['count'] = (empty($getParams['count']) === false) ? $getParams['count'] : 0;
 272                 $getParams['count'] += $i;
 273                 $getParams['after'] = $apiResponse->next ?? '';
 274 
 275                 if (empty($getParams['after']) === true || $configParams['maxPages'] === $configParams['currentPageNumber']) {
 276                     $break = true;
 277                 }
 278                 else {
 279                     sleep(1);
 280                 }
 281             }
 282             else {
 283                 $break = true;
 284             }
 285         }
 286 
 287         return $records;
 288     }
 289 
 290     /**
 291      * This method will retrieve posts from a subreddit
 292      * @access public
 293      * @param string $subreddit the subreddit in question
 294      * @param string $sort the posts sort direction
 295      * @param array $configParams array of config values for the GET request
 296      * @return array
 297      */
 298     public static function getSubredditPosts(string $subreddit, string $sort = 'new', array $getParams = array()): array {
 299         $getParams['limit'] = $getParams['limit'] ?? 50;
 300         $sort = (in_array($sort, array('new', 'hot')) === true) ? $sort : 'new';
 301 
 302         $url = self::$apiURLs['oAuthBase'] . self::parseTemplate(self::$apiURLs['o_subredditposts'], array (
 303                 'subreddit' => $subreddit,
 304                 'sort' => $sort
 305             ));
 306 
 307         $ret = self::makeCURLRequest('GET', $url . http_build_query($getParams));
 308 
 309         if ($ret !== false) {
 310             return $ret->data->children;
 311         }
 312         else {
 313             self::$errors[] = 'error hitting reddit API';
 314             return array();
 315         }
 316     }
 317 
 318     /**
 319      * This method will retrieve public posts from a subreddit
 320      * @access public
 321      * @param string $subreddit the subreddit in question
 322      * @param string $sort the posts sort direction
 323      * @param array $configParams array of config values for the GET request
 324      * @return array
 325      */
 326     public static function getSubredditPublicPosts(string $subreddit, string $sort = 'new', array $getParams = array()): array {
 327         $getParams['limit'] = $getParams['limit'] ?? 50;
 328         $sort = (in_array($sort, array('new', 'hot', 'rising', 'controversial', 'top', 'gilded')) === true) ? $sort : 'new';
 329 
 330         $url = self::$apiURLs['noAuthBase'] . self::parseTemplate(self::$apiURLs['no_subredditposts'], array (
 331                 'subreddit' => $subreddit,
 332                 'sort' => $sort
 333             ));
 334 
 335         $temp = self::$authType;
 336         self::useAuth('NONE');
 337         $ret = self::makeCURLRequest('GET', $url . http_build_query($getParams));
 338         self::useAuth($temp);
 339 
 340         if ($ret !== false) {
 341             return $ret->data->children;
 342         }
 343         else {
 344             self::$errors[] = 'error hitting reddit API';
 345             return array();
 346         }
 347     }
 348 
 349     /**
 350      * This method will retrieve comments from a subreddits specified posts
 351      * @access public
 352      * @param string $subreddit the subreddit in question
 353      * @param array $postIDs array of post IDs
 354      * @param array $getParams array of config values for the GET request
 355      * @return array
 356      */
 357     public static function getSubredditPostComments(string $subreddit, array $postIDs, array $getParams = array()): array {
 358         $getParams['depth'] = $getParams['depth'] ?? 6;
 359         $getParams['limit'] = $getParams['limit'] ?? 100;
 360         $getParams['sort'] = (in_array($getParams['sort'], array('new', 'top', 'controversial', 'old', 'best')) === true) ? $getParams['sort'] : 'new';
 361         $getParams['threaded'] = $getParams['threaded'] ?? false;
 362 
 363         $records = array();
 364 
 365         $limit_postIDs = count($postIDs);
 366         for ($i_postIDs = 0; $i_postIDs < $limit_postIDs; $i_postIDs++) {
 367             $url = self::$apiURLs['oAuthBase'] . self::parseTemplate(self::$apiURLs['o_subredditpostcomments'], array (
 368                     'subreddit' => $subreddit,
 369                     'postid' => $postIDs[$i_postIDs]
 370                 ));
 371 
 372             $apiResponse = self::makeCURLRequest('GET', $url . http_build_query($getParams));
 373 
 374             if ($apiResponse !== false) {
 375                 $records = array_merge($records, array(
 376                         'post' => array (
 377                                 'postID' => $postIDs[$i_postIDs]
 378                             ),
 379                         'comments' => $apiResponse[1]->data->children
 380                     ));
 381             } else {}
 382         }
 383 
 384         return $records;
 385     }
 386 
 387     /**
 388      * This method will retrieve comments from a subreddit
 389      * @access public
 390      * @param string $subreddit the subreddit in question
 391      * @param array $getParams array of config values for the GET request
 392      * @return array
 393      */
 394     public static function getSubredditPublicComments(string $subreddit, array $getParams = array()): array {
 395         $getParams['limit'] = $getParams['limit'] ?? 100;
 396         $getParams['sort'] = (in_array($getParams['sort'], array('new', 'top', 'controversial', 'old', 'best')) === true) ? $getParams['sort'] : 'new';
 397 
 398         $url = self::$apiURLs['noAuthBase'] . self::parseTemplate(self::$apiURLs['no_subredditcomments'], array (
 399                 'subreddit' => $subreddit
 400             ));
 401 
 402         $temp = self::$authType;
 403         self::useAuth('NONE');
 404         $ret = self::makeCURLRequest('GET', $url . http_build_query($getParams));
 405         self::useAuth($temp);
 406 
 407         if ($ret !== false) {
 408             return $ret->data->children;
 409         }
 410         else {
 411             self::$errors[] = 'error hitting reddit API';
 412             return array();
 413         }
 414     }
 415 
 416     /**
 417      * This method will retrieve user 'about' information
 418      * @access public
 419      * @param string $username reddit username
 420      * @return mixed
 421      */
 422     public static function getUserAbout(string $username) {
 423         $params = array (
 424                 'username' => $username
 425             );
 426 
 427         $url = self::$apiURLs['oAuthBase'] . self::parseTemplate(self::$apiURLs['o_aboutuser'], $params);
 428 
 429         $ret = self::makeCURLRequest('GET', $url);
 430 
 431         if ($ret !== false) {
 432             return $ret;
 433         }
 434         else {
 435             self::$errors[] = 'error hitting reddit API';
 436             return false;
 437         }
 438     }
 439 
 440     /**
 441      * This method will retrieve subreddit information
 442      * @access public
 443      * @param string $username reddit username
 444      * @param string $subreddit subreddit name
 445      * @return mixed
 446      */
 447     public static function getUserFlair(string $username, string $subreddit) {
 448         $params = array (
 449                 'subreddit' => $subreddit
 450             );
 451 
 452         $url = self::$apiURLs['oAuthBase'] . self::parseTemplate(self::$apiURLs['o_flairselector'], $params);
 453 
 454         $params = array (
 455                 'name' => $username
 456             );
 457 
 458         $ret = self::makeCURLRequest('POST', $url, $params);
 459 
 460         if ($ret !== false) {
 461             return $ret;
 462         }
 463         else {
 464             self::$errors[] = 'error hitting reddit API';
 465             return false;
 466         }
 467     }
 468 
 469     /**
 470      * This method will retrieve subreddit information
 471      * @access public
 472      * @param string $subreddit subreddit name
 473      * @return mixed
 474      */
 475     public static function getSubredditInfo(string $subreddit) {
 476         $params = array (
 477                 'subreddit' => $subreddit
 478             );
 479 
 480         $ret = self::makeCURLRequest('GET', self::$apiURLs['oAuthBase'] . self::parseTemplate(self::$apiURLs['o_subredditabout'], $params));
 481 
 482         if ($ret !== false) {
 483             return $ret;
 484         }
 485         else {
 486             self::$errors[] = 'error hitting reddit API';
 487             return false;
 488         }
 489     }
 490 
 491     /**
 492      * This method will make a new PM
 493      * @access public
 494      * @param string $to username message is for
 495      * @param string $subject the message subject
 496      * @param string $message the PM content
 497      * @return mixed
 498      */
 499     public static function composePM(string $to, string $subject, string $message) {
 500         $params = array (
 501                 'api_type' => 'json',
 502                 'to' => $to,
 503                 'subject' => $subject,
 504                 'text' => $message
 505             );
 506 
 507         $ret = self::makeCURLRequest('POST', self::$apiURLs['oAuthBase'] . self::$apiURLs['o_composepm'], $params);
 508 
 509         if ($ret !== false) {
 510             return $ret;
 511         }
 512         else {
 513             self::$errors[] = 'error hitting reddit API';
 514             return false;
 515         }
 516     }
 517 
 518     /**
 519      * This method will make a new post
 520      * @access public
 521      * @param array $params array of post parameters per the reddit API standards
 522      * @return mixed
 523      */
 524     public static function makePost(array $params) {
 525         $ret = self::makeCURLRequest('POST', self::$apiURLs['oAuthBase'] . self::$apiURLs['o_submit'], $params);
 526 
 527         if ($ret !== false) {
 528             return $ret;
 529         }
 530         else {
 531             self::$errors[] = 'error hitting reddit API';
 532             return false;
 533         }
 534     }
 535 
 536     /**
 537      * This method will grab a ME object from reddit (karma, settings, etc)
 538      * @access public
 539      * @return bool
 540      */
 541     public static function getMe() {
 542         $ret = self::makeCURLRequest('GET', self::$apiURLs['oAuthBase'] . self::$apiURLs['o_me']);
 543         if ($ret !== false) {
 544             self::$me = $ret;
 545             return true;
 546         }
 547         else {
 548             self::$errors[] = 'error hitting reddit API';
 549             return false;
 550         }
 551     }
 552 
 553     /**
 554      * This method will grab a ME object from reddit (karma, settings, etc)
 555      * @access public
 556      * @param string $fullname the reddit fullname of a post or comment (such as t1_asdfsdf)
 557      * @return mixed
 558      */
 559     public static function deleteSubmission(string $fullname) {
 560         $params = array (
 561                 'id' => $fullname
 562             );
 563 
 564         $ret = self::makeCURLRequest('POST', self::$apiURLs['oAuthBase'] . self::$apiURLs['o_delete'], $params);
 565         if ($ret !== false) {
 566             return $ret;
 567         }
 568         else {
 569             self::$errors[] = 'error hitting reddit API';
 570             return false;
 571         }
 572     }
 573 
 574     /**
 575      * This method will obtain a temporary oAuth access token
 576      * @access public
 577      * @return bool
 578      */
 579     public static function getAccessToken() {
 580         $params = array (
 581                 'grant_type' => 'password',
 582                 'username' => self::$username,
 583                 'password' => self::$password
 584             );
 585 
 586         $curlOptions = array (
 587                 CURLOPT_USERPWD => self::$clientID .