function AddTheTime($user, $seconds, $message) { global $LANG; $paidUntil = AddPaidTime($user, $seconds); if ($paidUntil === false) { echo "Error adding {$seconds} to {$user}\n"; return false; } if ($paidUntil > time()) { $message .= "<br><br>" . sprintf(preg_replace('/\\{(\\d+)\\}/', '%$1$s', $LANG['paidExpires']), date('Y-m-d H:i:s e', $paidUntil)); } SendUserMessage($user, 'Subscription', $LANG['paidSubscription'], $message); echo "{$user}: {$message}\n"; return true; }
function VerifySubEmail($loginState, $code) { $userId = $loginState['id']; $lang = GetLang($loginState['locale']); $db = DBConnect(); $stmt = $db->prepare('SELECT ifnull(email,\'\') address, ifnull(emailverification,\'\') verification from tblUser where id = ?'); $stmt->bind_param('i', $userId); $stmt->execute(); $result = $stmt->get_result(); $row = $result->fetch_assoc(); $result->close(); $stmt->close(); if ($row === false) { // could not find user return ['status' => 'unknown']; } if ($row['address'] == '') { if ($row['verification']) { // asking user to verify an empty address, shouldn't happen $stmt = $db->prepare('update tblUser set emailverification=null where ifnull(email,\'\') =\'\' and id = ?'); $stmt->bind_param('i', $userId); $stmt->execute(); $stmt->close(); } return ['status' => 'unknown', 'address' => '']; } if (!$row['verification']) { // trying to verify an already-verified address? return ['status' => 'success', 'address' => $row['address']]; } $code = preg_replace('/\\D/', '', $code); if ($row['verification'] == $code) { $stmt = $db->prepare('update tblUser set emailverification=null, emailset=null where id = ?'); $stmt->bind_param('i', $userId); $stmt->execute(); $stmt->close(); SendUserMessage($userId, 'Email', $lang['emailAddressVerified'], sprintf($lang['emailAddressVerifiedMessage'], $row['address'])); return ['status' => 'success', 'address' => $row['address']]; } return ['status' => 'verify', 'address' => $row['address']]; }
function PaypalResultForUser($user, $paidUntil, $removed) { $db = DBConnect(); $stmt = $db->prepare('select locale from tblUser where id = ?'); $stmt->bind_param('i', $user); $stmt->execute(); $locale = null; $stmt->bind_result($locale); if (!$stmt->fetch()) { $locale = false; } $stmt->close(); if ($locale === false) { LogPaypalError("Could not find user {$user} to send result message"); return false; } if (is_null($locale)) { $locale = 'enus'; } $LANG = GetLang($locale); $message = $removed ? $LANG['subscriptionTimeRemovedMessage'] : $LANG['subscriptionTimeAddedMessage']; if ($paidUntil > time()) { $message .= "<br><br>" . sprintf(preg_replace('/\\{(\\d+)\\}/', '%$1$s', $LANG['paidExpires']), date('Y-m-d H:i:s e', $paidUntil)); } SendUserMessage($user, 'Subscription', $LANG['paidSubscription'], $message); }
function UpdateBitPayTransaction($bitPayJson, $isNew = false) { $isNew = !!$isNew; // force boolean if (!is_array($bitPayJson)) { $jsonString = $bitPayJson; $bitPayJson = json_decode($jsonString, true); if (json_last_error() != JSON_ERROR_NONE) { DebugMessage("Invalid BitPay JSON\n" . print_r($jsonString, true), E_USER_ERROR); return false; } } $requiredFields = ['btcDue', 'btcPaid', 'btcPrice', 'currency', 'currentTime', 'exceptionStatus', 'expirationTime', 'id', 'invoiceTime', 'posData', 'price', 'rate', 'status', 'url']; foreach ($requiredFields as $fieldName) { if (!array_key_exists($fieldName, $bitPayJson)) { DebugMessage("BitPay JSON missing required field: {$fieldName}\n" . print_r($bitPayJson, true), E_USER_ERROR); return false; } } $invoiced = floor($bitPayJson['invoiceTime'] / 1000); $expired = floor($bitPayJson['expirationTime'] / 1000); $db = DBConnect(); $stmt = $db->prepare('select id, user, subextended from tblBitPayTransactions where id = ?'); $stmt->bind_param('s', $bitPayJson['id']); $stmt->execute(); $txnId = $userId = $subExtended = null; $stmt->bind_result($txnId, $userId, $subExtended); if (!$stmt->fetch()) { $txnId = $userId = $subExtended = null; } $stmt->close(); if (is_null($txnId) != $isNew) { if ($isNew) { DebugMessage("New BitPay transaction already found in database:\n" . print_r($bitPayJson, true), E_USER_ERROR); } else { DebugMessage("Existing BitPay transaction not found in database:\n" . print_r($bitPayJson, true), E_USER_ERROR); } return false; } if ($isNew) { $userId = GetUserFromPublicHMAC($bitPayJson['posData'], $invoiced); if (is_null($userId)) { DebugMessage("Could not get valid user from BitPay posData:\n" . print_r($bitPayJson, true), E_USER_ERROR); return false; } } $sql = <<<'EOF' insert into tblBitPayTransactions ( id, user, price, currency, rate, btcprice, btcpaid, btcdue, status, exception, url, posdata, invoiced, expired, updated ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, from_unixtime(?), from_unixtime(?), now()) on duplicate key update user=ifnull(user,values(user)), price=values(price), currency=values(currency), rate=values(rate), btcprice=values(btcprice), btcpaid=values(btcpaid), btcdue=values(btcdue), status=values(status), exception=values(exception), url=values(url), posdata=values(posdata), invoiced=values(invoiced), expired=values(expired), updated=values(updated) EOF; $stmt = $db->prepare($sql); $exceptionStatus = $bitPayJson['exceptionStatus'] ?: null; $stmt->bind_param('sissssssssssii', $bitPayJson['id'], $userId, $bitPayJson['price'], $bitPayJson['currency'], $bitPayJson['rate'], $bitPayJson['btcPrice'], $bitPayJson['btcPaid'], $bitPayJson['btcDue'], $bitPayJson['status'], $exceptionStatus, $bitPayJson['url'], $bitPayJson['posData'], $invoiced, $expired); if (!$stmt->execute()) { DebugMessage("Error updating BitPay transaction record: " . print_r($bitPayJson, true), E_USER_ERROR); return false; } $stmt->close(); if ($userId && !$subExtended) { $stmt = $db->prepare('select locale from tblUser where id = ?'); $locale = null; $stmt->bind_param('i', $userId); $stmt->execute(); $stmt->bind_result($locale); if (!$stmt->fetch()) { $locale = 'enus'; } $stmt->close(); $LANG = GetLang($locale); if (in_array($bitPayJson['status'], ['confirmed', 'complete'])) { $paidUntil = AddPaidTime($userId, SUBSCRIPTION_PAID_ADDS_SECONDS); if ($paidUntil === false) { LogBitPayError($bitPayJson, "Failed to add paid time to {$userId}"); SendUserMessage($userId, 'Subscription', $LANG['paidSubscription'], $LANG['SubscriptionErrors']['paiderror']); return false; } else { $stmt = $db->prepare('update tblBitPayTransactions set subextended=1 where id=?'); $stmt->bind_param('s', $bitPayJson['id']); if (!$stmt->execute()) { LogBitPayError($bitPayJson, "Failed to mark transaction as extending the sub for {$userId}"); } else { $message = $LANG['subscriptionTimeAddedMessage']; $message .= "<br><br>" . sprintf(preg_replace('/\\{(\\d+)\\}/', '%$1$s', $LANG['paidExpires']), date('Y-m-d H:i:s e', $paidUntil)); SendUserMessage($userId, 'Subscription', $LANG['paidSubscription'], $message); } $stmt->close(); } } elseif (in_array($bitPayJson['status'], ['invalid']) || $bitPayJson['exceptionStatus']) { LogBitPayError($bitPayJson, "BitPay exception for {$userId}"); SendUserMessage($userId, 'Subscription', $LANG['paidSubscription'], $LANG['SubscriptionErrors']['paiderror']); } } return true; }
function CheckNextUser() { $db = DBConnect(); $sql = <<<'EOF' select * from tblUser u where watchesobserved > ifnull(watchesreported, '2000-01-01') and timestampadd(minute, greatest(if(paiduntil is null or paiduntil < now(), ?, ?), watchperiod), ifnull(watchesreported, '2000-01-01')) < now() order by ifnull(watchesreported, '2000-01-01'), watchesobserved limit 1 for update EOF; $db->begin_transaction(); $stmt = $db->prepare($sql); $freeFreq = SUBSCRIPTION_WATCH_MIN_PERIOD_FREE; $paidFreq = SUBSCRIPTION_WATCH_MIN_PERIOD; $stmt->bind_param('ii', $freeFreq, $paidFreq); $stmt->execute(); $result = $stmt->get_result(); $row = $result->fetch_assoc(); $result->close(); $stmt->close(); if (is_null($row)) { $db->rollback(); return 10; } $stmt = $db->prepare('update tblUser set watchesreported = ? where id = ?'); $userId = $row['id']; $now = date('Y-m-d H:i:s'); $stmt->bind_param('si', $now, $userId); $stmt->execute(); $stmt->close(); $db->commit(); $expectedReport = strtotime($row['watchesobserved']); if (!is_null($row['watchesreported'])) { $expectedReport = max($expectedReport, max(is_null($row['paiduntil']) || strtotime($row['paiduntil']) < time() ? SUBSCRIPTION_WATCH_MIN_PERIOD_FREE : SUBSCRIPTION_WATCH_MIN_PERIOD, $row['watchperiod']) * 60 + strtotime($row['watchesreported'])); } DebugMessage("User " . str_pad($row['id'], 7, ' ', STR_PAD_LEFT) . " (" . $row['name'] . ') checking for new watches/rares, overdue by ' . TimeDiff($expectedReport, array('parts' => 2, 'precision' => 'second'))); $subjects = []; $messages = []; $houseSubjects = []; $ret = ReportUserWatches($now, $row); if ($ret !== false) { $subjects[] = $ret[0]; $messages[] = $ret[1]; if ($ret[2]) { $houseSubjects[] = $ret[2]; } } $ret = ReportUserRares($now, $row); if ($ret !== false) { $subjects[] = $ret[0]; $messages[] = $ret[1]; if ($ret[2]) { $houseSubjects[] = $ret[2]; } } if (!count($messages)) { return 0; } $locale = $row['locale']; $LANG = GetLang($locale); $message = $row['name'] . ',<br>' . implode('<hr>', $messages) . '<br><hr>' . $LANG['notificationsMessage'] . '<br><br>'; $subject = implode(', ', $subjects); if (count($houseSubjects) == count($subjects)) { $houseSubjects = array_unique($houseSubjects); if (count($houseSubjects) == 1) { $subject .= ' - ' . $houseSubjects[0]; } } if (is_null($row['paiduntil']) || strtotime($row['paiduntil']) < time()) { $message .= $LANG['freeSubscriptionAccount']; $hoursNext = round((max(intval($row['watchperiod'], 10), SUBSCRIPTION_WATCH_MIN_PERIOD_FREE) + 5) / 60, 1); } else { $message .= sprintf(preg_replace('/\\{(\\d+)\\}/', '%$1$s', $LANG['paidExpires']), date('Y-m-d H:i:s e', strtotime($row['paiduntil']))); $hoursNext = round((max(intval($row['watchperiod'], 10), SUBSCRIPTION_WATCH_MIN_PERIOD) + 5) / 60, 1); } if ($hoursNext > 0.3) { $hoursNext = sprintf(preg_replace('/\\{(\\d+)\\}/', '%$1$s', $LANG['timeFuture']), $hoursNext . ' ' . ($hoursNext == 1 ? $LANG['timeHour'] : $LANG['timeHours'])); $message .= ' ' . sprintf(preg_replace('/\\{(\\d+)\\}/', '%$1$s', $LANG['notificationPeriodNext']), $hoursNext); } SendUserMessage($userId, 'marketnotification', $subject, $message); return 0; }