Guest User

Untitled

a guest
May 9th, 2016
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 47.75 KB | None | 0 0
  1. <?php
  2.  
  3. namespace App\Classes\Steam;
  4.  
  5. use App\Jobs\DepositConfirm;
  6. use App\Models\Item;
  7. use App\Models\Round;
  8. use App\Models\RoundDeposits;
  9. use App\Models\Trade;
  10. use App\Models\TradeLog;
  11. use App\Models\User;
  12. use Crypt_RSA;
  13. use DateTime;
  14. use Illuminate\Support\Facades\Cache;
  15. use Illuminate\Support\Facades\File;
  16. use Illuminate\Support\Facades\Log;
  17. use Illuminate\Support\Facades\Queue;
  18. use Math_BigInteger;
  19.  
  20. class SteamBot extends SteamBase
  21. {
  22.  
  23. public function __construct(array $data)
  24. {
  25. parent::__construct($data);
  26.  
  27. if (!is_null($this->login)) {
  28. $auth = $this->steamAuth();
  29. $this->auth = $auth;
  30. $this->session_id = $auth['session_id'];
  31. $this->account_steamid = $auth['steamid'];
  32. $this->account_tradelink = $auth['tradelink'];
  33. $this->account_name = $auth['account_name'];
  34. $this->custom_acc_url = $auth['account_custom_name'];
  35. }
  36. }
  37.  
  38. private function steamAuth($emailauth = false)
  39. {
  40.  
  41. $cache_name = 'steam_bot_'.$this->bot_id;
  42.  
  43. if (!Cache::has($cache_name)) {
  44.  
  45. $rsa = json_decode(
  46. $this->openPage(
  47. $this->get_rsa_url,
  48. ['postdata' => ['username' => $this->login, 'donotcache' => time()]]
  49. )
  50. );
  51.  
  52. if (isset($rsa->success)) {
  53. if (!$rsa->success) {
  54. return ['error' => 'Error while retrieving RSA key'];
  55. }
  56.  
  57. $password = $this->encryptPassword(
  58. $this->password,
  59. ['mod' => $rsa->publickey_mod, 'exp' => $rsa->publickey_exp]
  60. );
  61.  
  62. $params = [
  63. 'password' => $password,
  64. 'username' => $this->login,
  65. 'twofactorcode' => '',
  66. 'loginfriendlyname' => '',
  67. 'rsatimestamp' => $rsa->timestamp,
  68. 'remember_login' => 'true',
  69. 'captchagid' => -1,
  70. 'captcha_text' => '',
  71. 'donotcache' => time(),
  72. 'emailauth' => @$emailauth['code'],
  73. 'emailsteamid' => @$emailauth['emailsteamid']
  74. ];
  75.  
  76. $login = json_decode($this->openPage($this->login_url, ['postdata' => $params]), true);
  77.  
  78. if ($login['success']) {
  79. $params = $login['transfer_parameters'];
  80. $params['remember_login'] = 'true';
  81. $cookie = $this->openPage($login['transfer_url'], ['postdata' => $params]);
  82.  
  83. $offer_page = $this->openPage("http://steamcommunity.com/id/me/tradeoffers/privacy");
  84. $pattern = '/\<input size="45" type="text" class="trade_offer_access_url" id="trade_offer_access_url" value="(.*?)" readonly\>/';
  85.  
  86. preg_match($pattern, $offer_page, $trade);
  87. preg_match('/sessionid ([a-z0-9]{24})/', file_get_contents($this->bot_cookie_file), $session_id);
  88. preg_match(
  89. '/<span class="profile_small_header_name"><a class="whiteLink" href="(.+?)">(.+?)<\/a><\/span>/',
  90. $offer_page,
  91. $name
  92. );
  93. //var_dump($name);
  94.  
  95. if (isset($name[1], $name[2], $params['steamid'], $trade[1], $session_id[1])) {
  96. $return = [
  97. 'account_custom_name' => $name[1],
  98. 'account_name' => $name[2],
  99. 'steamid' => $params['steamid'],
  100. 'session_id' => @$session_id[1],
  101. 'tradelink' => $trade[1]
  102. ];
  103.  
  104. Cache::put($cache_name, $return, 15);
  105.  
  106. return $return;
  107. }
  108.  
  109. }
  110. }
  111.  
  112. return false;
  113. } else {
  114. return Cache::get($cache_name);
  115. }
  116. }
  117.  
  118. public function openPage($url, $flags = null)
  119. {
  120. if (is_null($flags)) {
  121. $flags = false;
  122. }
  123. $flags['ref'] = (isset($flags['ref']) ? $flags['ref'] : $this->default_ref);
  124. $flags = [
  125. 'postdata' => @$flags['postdata'],
  126. 'ref' => @$flags['ref'],
  127. 'return_headers' => @$flags['return_headers'],
  128. 'return_only_cookies' => @$flags['return_only_cookies'],
  129. 'timeout' => @$flags['timeout']
  130. ];
  131.  
  132. $s = curl_init();
  133. curl_setopt($s, CURLOPT_FOLLOWLOCATION, true);
  134. curl_setopt($s, CURLOPT_URL, $url);
  135. curl_setopt($s, CURLOPT_COOKIEJAR, $this->bot_cookie_file);
  136. curl_setopt($s, CURLOPT_COOKIEFILE, $this->bot_cookie_file);
  137. curl_setopt($s, CURLOPT_RETURNTRANSFER, true);
  138. curl_setopt($s, CURLOPT_SSL_VERIFYPEER, false);
  139. curl_setopt($s, CURLOPT_SSL_VERIFYHOST, false);
  140. curl_setopt($s, CURLOPT_HEADER, $flags['return_headers'] || $flags['return_only_cookies']);
  141. curl_setopt($s, CURLOPT_USERAGENT, $this->default_useragent);
  142.  
  143. if ($flags['timeout']) {
  144. curl_setopt($s, CURLOPT_CONNECTTIMEOUT, $flags['timeout']);
  145. }
  146.  
  147. if ($flags['postdata']) {
  148. curl_setopt($s, CURLOPT_POST, true);
  149. curl_setopt($s, CURLOPT_POSTFIELDS, http_build_query($flags['postdata']));
  150. }
  151. if ($flags['ref']) {
  152. curl_setopt($s, CURLOPT_REFERER, $flags['ref']);
  153. }
  154.  
  155. $cookie = $this->cookie;
  156. $cookie .= $this->additional_cookie;
  157. curl_setopt($s, CURLOPT_COOKIE, $cookie);
  158.  
  159. $res = curl_exec($s);
  160. curl_close($s);
  161.  
  162. if ($flags['return_only_cookies']) {
  163. $res = $this->parseCookie($res, true);
  164. }
  165.  
  166. return $res;
  167. }
  168.  
  169. private function parseCookie($string, $into_array = false)
  170. {
  171. preg_match_all("/Set-Cookie: (.*?)=(.*?);/i", $string, $res);
  172. $cookie = null;
  173. if (count($res) > 0) {
  174. foreach ($res[1] as $key => $value) {
  175. if (!$into_array) {
  176. $cookie .= $value.'='.$res[2][$key].'; ';
  177. if (strstr($value, 'steamMachineAuth')) {
  178. file_put_contents($this->bot_cookie_file, $value.'='.$res[2][$key].';');
  179. }
  180. } else {
  181. $cookie[$value] = $res[2][$key];
  182. }
  183. }
  184. }
  185.  
  186. return $cookie;
  187. }
  188.  
  189. private function encryptPassword($password, $keys)
  190. {
  191. if ($password && is_array($keys)) {
  192. $RSA = new Crypt_RSA();
  193. $RSA->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
  194. $n = new math_biginteger($keys['mod'], 16);
  195. $e = new math_biginteger($keys['exp'], 16);
  196.  
  197. $key = ['modulus' => $n, 'publicExponent' => $e];
  198. $RSA->loadKey($key, CRYPT_RSA_PUBLIC_FORMAT_RAW);
  199.  
  200. return base64_encode($RSA->encrypt($password, false));
  201. }
  202.  
  203. return false;
  204. }
  205.  
  206. public function botReload()
  207. {
  208. for ($i = 1; $i < 5; $i++) {
  209. @unlink($this->bot_cookie_file);
  210. $auth = $this->steamAuth();
  211.  
  212. echo 'New session id: '.$auth['session_id'].PHP_EOL;
  213.  
  214. if (isset($auth['session_id'], $auth['steamid'], $auth['tradelink'])) {
  215. break;
  216. }
  217. }
  218.  
  219. return $i;
  220. }
  221.  
  222. public function updateBotInventory($bot_id)
  223. {
  224. $inventory = json_decode(
  225. $this->openPage(
  226. sprintf($this->get_inventory, $this->account_steamid, $this->app_id),
  227. ['timeout' => 1]
  228. )
  229. );
  230. Cache::forget("bot_inventory_{$bot_id}");
  231. if ($inventory) {
  232. $inventory = $inventory->rgInventory;
  233. $bot_inventory = collect();
  234. foreach ($inventory as $asset_id => $val) {
  235. $bot_inventory->push(['asset_id' => $asset_id, 'class_id' => $val->classid, 'reserved' => false]);
  236. }
  237. $bot_inventory = $this->updateBotInventoryInformation($bot_inventory);
  238. Cache::forever("bot_inventory_{$bot_id}", $bot_inventory);
  239. }
  240. }
  241.  
  242. public function updateBotInventoryInformation($inventory)
  243. {
  244. $trades = Trade::getSending();
  245. $reserved_items = [];
  246. $bot_inventory = collect($inventory);
  247. foreach ($trades as $trade) {
  248. $items = collect(json_decode($trade->items));
  249. $status = $this->getTradeOffer($trade->trade_id)['response']['offer']['trade_offer_state'];
  250. if($status == 3) {
  251. Trade::setDone($trade->trade_id);
  252. }
  253. foreach ($items as $item) {
  254. $reserved_items[] = $item->asset_id;
  255. }
  256. }
  257. foreach ($reserved_items as $asset_id) {
  258. $bot_inventory->transform(
  259. function ($item) use ($asset_id) {
  260. if ($item['asset_id'] == $asset_id) {
  261. $item['reserved'] = true;
  262. }
  263.  
  264. return $item;
  265. }
  266. );
  267. }
  268.  
  269. return $bot_inventory;
  270. }
  271.  
  272. public function getAccountInventory(
  273. $steam_id,
  274. $cache = false,
  275. $sort_by_price = false,
  276. $nocache = false,
  277. $display_info = true,
  278. $lang = false
  279. ) {
  280. $cached_inventory = storage_path('/framework/inventories/').$steam_id.'.json';
  281.  
  282. if (time() - @filemtime($cached_inventory) > $this->inventory_cache_time || $nocache) {
  283. $json_inventory = $this->openPage(
  284. sprintf($this->get_inventory, $steam_id, $this->app_id),
  285. ['timeout' => 1]
  286. );
  287. } else {
  288. return json_decode(file_get_contents($cached_inventory), true, JSON_UNESCAPED_UNICODE);
  289. }
  290.  
  291. $inventory = json_decode($json_inventory, true, JSON_UNESCAPED_UNICODE);
  292. $items = [];
  293. $info = ['total_price' => 0, 'total_items' => 0];
  294.  
  295. if (isset($inventory['rgInventory'])) {
  296. foreach ($inventory['rgInventory'] as $asset_id => $val) {
  297. $desc = $inventory['rgDescriptions']["{$val['classid']}_{$val['instanceid']}"];
  298. $key = $val['classid'];
  299.  
  300. if (isset($items['items'][$key])) {
  301. $items['items'][$key]['count']++;
  302. $items['items'][$key]['asset_id'][] = (string)$asset_id;
  303. } else {
  304. if ($cache == true) {
  305. $item_info = Item::find($val['classid']);
  306. if (!empty($item_info)) {
  307. $item_info = $item_info->toArray();
  308. } else {
  309. $item_info = $this->itemGetInfo($val['classid'], true, true);
  310. }
  311. if (!$lang) {
  312. if (isset($item_info['en_name'])) {
  313. $name = $item_info['en_name'];
  314. } else {
  315. $name = null;
  316. }
  317. } else {
  318. if (isset($item_info[$lang.'_name'])) {
  319. $name = $item_info[$lang.'_name'];
  320. } else {
  321. if (isset($item_info['en_name'])) {
  322. $name = $item_info['en_name'];
  323. } else {
  324. $name = null;
  325. }
  326. }
  327. }
  328. } else {
  329. $item_info = $this->itemGetInfo($val['classid']);
  330. $name = $item_info['name'];
  331. }
  332. $items['items'][$key] = [
  333. 'asset_id' => [(string)$asset_id],
  334. 'classid' => $key,
  335. 'count' => 1,
  336. 'item_name' => $name,
  337. 'item_price' => $item_info['price'],
  338. 'rarity' => $item_info['rarity'],
  339. 'quality' => $item_info['quality'],
  340. ];
  341. }
  342. $info['total_price'] += $items['items'][$key]['item_price'];
  343. $info['total_items']++;
  344. }
  345.  
  346. if ($display_info) {
  347. $items['info'] = $info;
  348. }
  349. }
  350. if ($sort_by_price) {
  351. if (isset($items['items'])) {
  352. $items['items'] = collect($items['items'])->sortByDesc('item_price')->toArray();
  353. } else {
  354. $items['items'] = [];
  355. }
  356. $sortedItems = [];
  357. $number = 0;
  358. foreach ($items['items'] as $key => $item) {
  359. $number++;
  360. $sortedItems[$number] = $item;
  361. }
  362. unset($items['items']);
  363. $items['items'] = $sortedItems;
  364. }
  365.  
  366. if (!$nocache) {
  367. File::put($cached_inventory, json_encode($items), JSON_UNESCAPED_UNICODE);
  368. }
  369.  
  370. return $items;
  371. }
  372.  
  373. public function itemGetInfo($class_id, $updateData = false, $updatePrice = false, $lang = false)
  374. {
  375. $array = [];
  376.  
  377. $item = Item::getInfo($class_id);
  378.  
  379. if ((empty($item)) OR (empty($item->ru_name)) OR (empty($item->en_name)) OR ($updateData)) {
  380. $result = json_decode(
  381. mb_convert_encoding(
  382. $this->openPage(
  383. sprintf($this->item_info_by_class, $this->app_id, $this->api_key, $class_id),
  384. ['timeout' => 3]
  385. ),
  386. "UTF-8",
  387. "auto"
  388. ),
  389. true,
  390. JSON_UNESCAPED_UNICODE
  391. );
  392. $condition = !preg_match('/Сувенирный/', @$result['result'][$class_id]['market_name']) || preg_match(
  393. '/Сувенирный набор/',
  394. @$result['result'][$class_id]['market_name']
  395. );
  396.  
  397. if (isset($result['result'][$class_id]['market_hash_name']) && $condition) {
  398. $en_name = $result['result'][$class_id]['market_hash_name'];
  399. $ru_name = $result['result'][$class_id]['market_name'];
  400.  
  401. preg_match('/\((.*?)\)/', $ru_name, $exterior);
  402. $quality = explode(',', $result['result'][$class_id]['type']);
  403. if (strpos($result['result'][$class_id]['type'], 'Нож') !== false) {
  404. $quality[] = 'Нож';
  405. }
  406.  
  407. $exterior = (isset($exterior[1]) ? $exterior[1] : '');
  408. $quality = (is_array($quality) ? end($quality) : '');
  409. $array = [
  410. 'id' => $class_id,
  411. 'ru_name' => $ru_name,
  412. 'en_name' => $en_name,
  413. 'rarity' => $this->defineRarity($quality),
  414. 'quality' => $this->defineQuality($exterior),
  415. 'last_update_time' => $this->date
  416. ];
  417. if (empty($item)) {
  418. Item::addItem($array);
  419. } else {
  420. unset($array['id']);
  421. Item::updateItem($class_id, $array);
  422. }
  423. }
  424. } else {
  425. $array = $item->toArray();
  426. }
  427.  
  428. if (isset($array['last_update_time'])) {
  429. $date = new DateTime($array['last_update_time']);
  430. $updateTime = time() > $date->modify("+{$this->item_cache_time} minutes")->getTimestamp();
  431. } else {
  432. $updateTime = true;
  433. }
  434.  
  435. if (((!isset($array['price'])) OR ($updateTime) OR ($updatePrice)) AND !empty($array)) {
  436. $res = json_decode(
  437. $this->openPage(
  438. sprintf($this->get_item_price, $this->currency, $this->app_id, urlencode($array['en_name'])),
  439. ['timeout' => 2]
  440. )
  441. );
  442.  
  443. if (isset($res->success)) {
  444.  
  445. $price = null;
  446.  
  447. if (isset($res->lowest_price)) {
  448. $price = $res->lowest_price;
  449. } elseif (isset($res->median_price)) {
  450. $price = $res->median_price;
  451. }
  452.  
  453. switch ($this->currency) {
  454. case 5:
  455. $price = floatval(str_replace([',', ' руб.'], ['.', null], $price));
  456. break;
  457.  
  458. default:
  459. $price = floatval(str_replace('$', null, $price));
  460. }
  461.  
  462. $array['price'] = $price;
  463. Item::updatePrice($class_id, $price);
  464. }
  465. }
  466.  
  467. if (@$array['price'] && @$array['en_name']) {
  468. if (!$lang) {
  469. $name = $array['en_name'];
  470. } else {
  471. $name = $array["{$lang}_name"];
  472. }
  473.  
  474. return [
  475. 'price' => $array['price'],
  476. //'ru_name' => $array['ru_name'],
  477. 'name' => $name,
  478. 'rarity' => $array['rarity'],
  479. 'quality' => $array['quality']
  480. ];
  481. }
  482.  
  483. return false;
  484. }
  485.  
  486. public function defineQuality($quality)
  487. {
  488. $quality = trim(mb_strtolower($quality));
  489.  
  490. switch ($quality) {
  491. case 'немного поношенное':
  492. $return = 'mw';
  493. break;
  494.  
  495. case 'прямо с завода':
  496. $return = 'fn';
  497. break;
  498.  
  499. case 'после полевых испытаний':
  500. $return = 'ft';
  501. break;
  502.  
  503. case 'поношенное':
  504. $return = 'ww';
  505. break;
  506.  
  507. case 'закаленное в боях':
  508. $return = 'bs';
  509. break;
  510.  
  511. default:
  512. $return = '';
  513. }
  514.  
  515. return $return;
  516. }
  517.  
  518. public function defineRarity($rarity)
  519. {
  520. $rarity = trim(mb_strtolower($rarity));
  521.  
  522. switch ($rarity) {
  523. case 'нож':
  524. case 'контрабандное':
  525. $return = 'knife';
  526. break;
  527.  
  528. case 'базового класса':
  529. case 'ширпотреб':
  530. $return = 'consumer';
  531. break;
  532.  
  533. case 'промышленное качество':
  534. $return = 'uncommon';
  535. break;
  536.  
  537. case 'армейское качество':
  538. case 'высшего класса':
  539. $return = 'mil-spec';
  540. break;
  541.  
  542. case 'тайное':
  543. $return = 'restricted';
  544. break;
  545.  
  546. case 'засекреченное':
  547. case 'экзотичного вида':
  548. $return = 'covert';
  549. break;
  550.  
  551. case 'запрещенное':
  552. case 'примечательного типа':
  553. $return = 'exceedingly-rare';
  554. break;
  555.  
  556. default:
  557. $return = 'consumer';
  558. }
  559.  
  560. return $return;
  561. }
  562.  
  563. public function getItemsValue($steam_id, $no_cache = false)
  564. {
  565. $cache = "inventory_{$steam_id}";
  566. $result = false;
  567.  
  568. if (!Cache::has($cache) || $no_cache) {
  569. $attempts = 0;
  570. foreach ($this->itemValueServer as $server) {
  571. $url = "http://{$server}.appspot.com/ParseInv?id={$steam_id}&app={$this->app_id}";
  572. $file_headers = @get_headers($url);
  573. if (strtolower($file_headers[0]) === strtolower('HTTP/1.0 200 Ok')) {
  574. $json_inventory = file_get_contents($url);
  575.  
  576. $result = collect(json_decode($json_inventory))->sortBy('price', JSON_UNESCAPED_UNICODE);
  577. if (($result['success'] !== false) OR ($attempts > count($this->itemValueServer))) {
  578. Cache::put($cache, $json_inventory, $this->inventory_cache_time);
  579. break;
  580. } else {
  581. $result = ['error' => trans('notify.steam_unavailable')];
  582. }
  583. }
  584. $attempts++;
  585. }
  586. } else {
  587. $result = collect(json_decode(Cache::get($cache), JSON_UNESCAPED_UNICODE))->sortBy('price');
  588. }
  589.  
  590. return $result;
  591. }
  592.  
  593. public function sortItemsByPrice($price, $partner_id, $items_count, $trade_link, $comment, $start_items = 0)
  594. {
  595. $items = [];
  596.  
  597. foreach ($this->getAccountInventory($this->account_steamid, $price, true) as $key => $value) {
  598. if (is_array(@$value['asset_id'])) {
  599. foreach ($value['asset_id'] as $asset_id) {
  600. $items[] = ['appid' => $this->app_id, 'contextid' => 2, 'amount' => 1, 'assetid' => $asset_id];
  601. }
  602. }
  603. }
  604. $items = array_slice($items, $start_items * $items_count, $items_count);
  605.  
  606. return $this->tradeSend($partner_id, $comment, $trade_link, $items);
  607. }
  608.  
  609. public function tradeSend($partner_id, $trade_offer_message, $trade_offer_link, $items)
  610. {
  611. $send_url = "https://steamcommunity.com/tradeoffer/new/send";
  612. preg_match(
  613. '/https:\/\/steamcommunity.com\/tradeoffer\/new\/\?partner=(.*)&token=(.*)/',
  614. $trade_offer_link,
  615. $token
  616. );
  617.  
  618. $data = [
  619. 'sessionid' => $this->session_id,
  620. 'serverid' => 1,
  621. 'partner' => $partner_id,
  622. 'tradeoffermessage' => $trade_offer_message,
  623. 'json_tradeoffer' => $this->getItemsList($items),
  624. 'captcha' => '',
  625. 'trade_offer_create_params' => json_encode(['trade_offer_access_token' => $token[2]]),
  626. ];
  627.  
  628. return json_decode(
  629. $this->openPage($send_url, ['postdata' => $data, 'ref' => $trade_offer_link], ['timeout' => 4])
  630. );
  631. }
  632.  
  633. private function getItemsList($array)
  634. {
  635. $array = [
  636. 'newversion' => true,
  637. 'version' => 2,
  638. 'me' => ['assets' => $array, 'currency' => [], 'ready' => false],
  639. 'them' => ['assets' => [], 'currency' => [], 'ready' => false]
  640. ];
  641.  
  642. return json_encode($array);
  643. }
  644.  
  645. public function setDeposit()
  646. {
  647. return $this->trade_offer;
  648. }
  649.  
  650. public function confirmTrade($trade_id)
  651. {
  652. $status = false;
  653. if (isset($trade_id)) {
  654. $deposit = RoundDeposits::findDeposit($trade_id);
  655.  
  656. $sender_steam_id = (string)$deposit->user;
  657. $user_data = User::getInfo($sender_steam_id);
  658. $reason = trans('notify.steam_error', [], 'messages', $user_data->language);
  659. $deposit->items = json_decode($deposit->items);
  660. if ($user_data) {
  661. if (count($deposit->items) > 0) {
  662. if (!is_null(isset($user_data->trade_offer))) {
  663. if ($deposit->total_items <= config('roulette.steam_helper.max_item_count')
  664. && $deposit->total_sum >= config('roulette.steam_helper.min_bet')
  665. ) {
  666. RoundDeposits::setProgress($trade_id, true);
  667. Queue::push(new DepositConfirm($trade_id));
  668. $status = true;
  669. } else {
  670. $reason = trans('notify.wrong_conditions', [], 'messages', $user_data->language);
  671. }
  672. } else {
  673. $reason = trans('notify.set_trade_url', [], 'messages', $user_data->language);
  674. }
  675. }
  676. } else {
  677. $reason = trans('notify.user_404', [], 'messages', $user_data->language);
  678. }
  679. if (!$status) {
  680. $result = [
  681. 'result' => trans('notify.trade_not_confirmed', [], 'messages', $user_data->language),
  682. 'reason' => $reason,
  683. 'user' => $sender_steam_id,
  684. 'error' => true
  685. ];
  686. $this->sockets->notify($result);
  687. }
  688. }
  689. }
  690.  
  691. public function tradeDeclineByUser($trade_id)
  692. {
  693. $deposit = RoundDeposits::findDeposit($trade_id);
  694. $return = json_decode($this->tradeDecline($trade_id));
  695. $user_data = User::getInfo($deposit->user);
  696. if (isset($return->strError)) {
  697. Log::info(['result' => 'Deposit error', 'steam_response' => "$return->strError"]);
  698. $this->sockets->notify(
  699. [
  700. 'result' => trans('notify.steam_lag', [], 'messages', $user_data->language),
  701. 'steam_response' => trans('notify.trade_lag', [], 'messages', $user_data->language),
  702. 'user' => $deposit->user,
  703. 'error' => true
  704. ]
  705. );
  706.  
  707. return false;
  708. } else {
  709. $result = [
  710. 'message' => trans('notify.trade_declined', [], 'messages', $user_data->language),
  711. 'user' => $deposit->user
  712. ];
  713. $this->sockets->notify(
  714. [
  715. 'result' => 'trade_declined',
  716. 'user' => $deposit->user,
  717. 'trade_id' => $trade_id,
  718. 'hidden' => true,
  719. 'remove' => true
  720. ]
  721. );
  722. $this->sockets->notify($result);
  723.  
  724. return true;
  725. }
  726. }
  727.  
  728. public function getTradeOffer($trade_id)
  729. {
  730.  
  731. // 1 - инвалид, 2 - гуд, 3 - обмен принят тем, кому был отправлен, 4 - контрпредложение, 5 - истек срок, 6 - отправщик отменил трейд, 7 - получатель отменил трейд, 8 - вещи больше не актуальны, 9 - подтверждение по мылу, 10 - получатель отменил
  732.  
  733. $res = json_decode(
  734. $this->openPage(sprintf($this->get_trade_offer, $this->api_key, $trade_id), ['timeout' => 3]),
  735. true,
  736. JSON_UNESCAPED_UNICODE
  737. );
  738.  
  739. return $res;
  740.  
  741. }
  742.  
  743. /**
  744. * @param bool|true $incoming
  745. * @return array|mixed
  746. */
  747. public function getTradesList($incoming = true)
  748. {
  749. $deposits_confirm = RoundDeposits::all();
  750. if (isset($deposits_confirm)) {
  751. foreach ($deposits_confirm as $deposit) {
  752. if (date('Y-m-d H:i:s') > $deposit->created_at) {
  753. $user_data = User::getInfo($deposit->user);
  754. RoundDeposits::find($deposit->trade_id)->delete();
  755. $this->tradeDecline($deposit->trade_id);
  756. $result = [
  757. 'result' => trans('notify.trade_declined', [], 'messages', $user_data->language),
  758. 'reason' => trans('notify.trade_expired', [], 'messages', $user_data->language),
  759. 'user' => $deposit->user,
  760. 'trade_id' => $deposit->trade_id,
  761. 'error' => true
  762. ];
  763. $this->sockets->notify($result);
  764. }
  765. }
  766. }
  767.  
  768.  
  769. // 1 - инвалид, 2 - гуд, 3 - обмен принят тем, кому был отправлен, 4 - контрпредложение, 5 - истек срок, 6 - отправщик отменил трейд, 7 - получатель отменил трейд, 8 - вещи больше не актуальны, 9 - подтверждение по мылу, 10 - получатель отменил
  770.  
  771. $get_var = ($incoming ? 'get_received_offers=1' : 'get_sent_offers=1');
  772. $result_key = ($incoming ? 'trade_offers_received' : 'trade_offers_sent');
  773.  
  774. $res = json_decode(
  775. $this->openPage(sprintf($this->get_trades_list, $this->api_key, $get_var, time()), ['timeout' => 3]),
  776. true,
  777. JSON_UNESCAPED_UNICODE
  778. );
  779.  
  780. if (count($res['response']) > 0) {
  781.  
  782. $res = $res['response'][$result_key];
  783. foreach ($res as $key => $value) {
  784. if ($res[$key]['trade_offer_state'] == 2) {
  785. $res[$key]['items'] = [];
  786. $res[$key]['total_items'] = 0;
  787. $res[$key]['total_sum'] = 0;
  788. $res[$key]['items_without_price'] = 0;
  789. $error = false;
  790. $reason = null;
  791. $user = (string)$this->convertSteamId($res[$key]['accountid_other']);
  792. $user_data = User::getInfo($user);
  793.  
  794. if (isset($res[$key]['items_to_receive'])) {
  795. foreach ($res[$key]['items_to_receive'] as $item) {
  796. if ($item['appid'] == $this->app_id) {
  797. $info = $this->itemGetInfo($item['classid']);
  798. if (!$info) {
  799. $res[$key]['items_without_price']++;
  800. $error = true;
  801. $reason = trans('notify.no_price_item', [], 'messages', $user_data->language);
  802. } else {
  803. $res[$key]['total_items']++;
  804. $res[$key]['total_sum'] += $info['price'];
  805.  
  806. $res[$key]['items'][] = [
  807. 'price' => $info['price'],
  808. 'assetid' => (string)$item['assetid'],
  809. 'classid' => (string)$item['classid']
  810. ];
  811. }
  812. } else {
  813. $reason = trans('notify.wrong_appid', [], 'messages', $user_data->language);
  814. $error = true;
  815. }
  816. }
  817.  
  818. if ($res[$key]['total_items'] > config('roulette.steam_helper.max_item_count')) {
  819. $error = true;
  820. $reason = trans(
  821. 'notify.wrong_conditions.max_items',
  822. [
  823. 'max' => config('roulette.steam_helper.max_item_count'),
  824. 'current' => $res[$key]['total_items']
  825. ],
  826. 'messages',
  827. $user_data->language
  828. );
  829. }
  830.  
  831. if ($res[$key]['total_sum'] < config('roulette.steam_helper.min_bet')) {
  832. $error = true;
  833. $reason = trans(
  834. 'notify.wrong_conditions.low_price',
  835. [
  836. 'min' => config('roulette.steam_helper.min_bet'),
  837. 'current' => $res[$key]['total_sum']
  838. ],
  839. 'messages',
  840. $user_data->language
  841. );
  842. }
  843.  
  844.  
  845. if (!$error) {
  846. $trade_id = $res[$key]['tradeofferid'];
  847. $tradeExist = RoundDeposits::find($trade_id);
  848. if (is_null($tradeExist)) {
  849. $user = (string)$this->convertSteamId($res[$key]['accountid_other']);
  850. $items = collect($res[$key]['items'])->sortByDesc('price')->toArray();
  851. $sortedItems = [];
  852. foreach ($items as $item) {
  853. $sortedItems[] = $item;
  854. }
  855. unset($res[$key]['items']);
  856. $res[$key]['items'] = $sortedItems;
  857. unset($items, $sortedItems);
  858. /*на серверах стима время идет по другому гейб чертов наркоман
  859. $date = new DateTime(date('Y-m-d H:i:s', $res[$key]['time_created']));*/
  860. $date = new DateTime(date('Y-m-d H:i:s'));
  861. $trade_decline_time = config('roulette.trade_decline_time');
  862. $created_at = date(
  863. 'Y-m-d H:i:s',
  864. $date->modify("+{$trade_decline_time} seconds")->getTimestamp()
  865. );
  866. RoundDeposits::create(
  867. [
  868. 'trade_id' => $trade_id,
  869. 'items' => json_encode($res[$key]['items']),
  870. 'total_items' => $res[$key]['total_items'],
  871. 'total_sum' => $res[$key]['total_sum'],
  872. 'user' => $user,
  873. 'bot_id' => $this->bot_id,
  874. 'created_at' => $created_at,
  875. ]
  876. );
  877. $result = [
  878. 'result' => 'trade_confirm',
  879. 'trade_id' => $trade_id,
  880. 'items' => json_encode($res[$key]['items']),
  881. 'user' => $user,
  882. 'hidden' => true
  883. ];
  884. $this->sockets->notify($result);
  885. unset($user, $result);
  886. }
  887. unset($trade_id);
  888. } else {
  889. $user = (string)$this->convertSteamId($res[$key]['accountid_other']);
  890. $this->tradeDecline($res[$key]['tradeofferid']);
  891. $result = [
  892. 'message' => trans(
  893. 'notify.trade_declined',
  894. [],
  895. 'messages',
  896. $user_data->language
  897. ),
  898. 'reason' => $reason,
  899. 'user' => $user,
  900. 'error' => true
  901. ];
  902. $this->sockets->notify($result);
  903. unset($res[$key]);
  904. }
  905. }
  906.  
  907. unset($res[$key]['items_to_receive']);
  908. } else {
  909. $user = (string)$this->convertSteamId($res[$key]['accountid_other']);
  910. /*проверяем остался ли такой трейд в базе*/
  911. $trade_id = $res[$key]['tradeofferid'];
  912. $round_deposit = RoundDeposits::find($trade_id);
  913. if (isset($round_deposit)) {
  914. $this->tradeDecline($trade_id);
  915. $result = [
  916. 'user' => $user,
  917. 'trade_id' => $trade_id,
  918. 'error' => true,
  919. 'hidden' => true,
  920. 'remove' => true
  921. ];
  922. $this->sockets->notify($result);
  923. $round_deposit->delete();
  924. }
  925.  
  926. unset($res[$key], $user);
  927. }
  928. }
  929.  
  930. return $res;
  931. }
  932.  
  933. return [];
  934. }
  935.  
  936. public function tradeDecline($tradeOfferId)
  937. {
  938. $data = ['tradeofferid' => $tradeOfferId];
  939. $decline_url = "https://api.steampowered.com/IEconService/DeclineTradeOffer/v1/?key={$this->api_key}";
  940.  
  941. return $this->openPage($decline_url, ['postdata' => $data, 'timeout' => 3]);
  942. }
  943.  
  944. public function convertSteamId($steam_id)
  945. {
  946. return bcadd($steam_id, "76561197960265728");
  947. }
  948.  
  949. public function tradeAccept($partner, $tradeOfferId)
  950. {
  951. $accept_url = "https://steamcommunity.com/tradeoffer/{$tradeOfferId}/accept";
  952. $ref = "https://steamcommunity.com/tradeoffer/{$tradeOfferId}/";
  953. $data = [
  954. 'sessionid' => $this->session_id,
  955. 'tradeofferid' => $tradeOfferId,
  956. 'serverid' => 1,
  957. 'captcha' => '',
  958. 'partner' => $partner
  959. ];
  960. $result = $this->openPage($accept_url, ['postdata' => $data, 'ref' => $ref, 'timeout' => 3]);
  961.  
  962. return $result;
  963. }
  964.  
  965. public function tradeCancel($tradeOfferId)
  966. {
  967. $cancel_trade = "https://steamcommunity.com/tradeoffer/{$tradeOfferId}/cancel";
  968. $ref = "https://steamcommunity.com/tradeoffer/{$tradeOfferId}/";
  969. $data = ['sessionid' => $this->session_id];
  970.  
  971. return $this->openPage($cancel_trade, ['postdata' => $data, 'ref' => $ref, 'timeout' => 3]);
  972. }
  973.  
  974. public function userBlock($steamid)
  975. {
  976. $data = ['sessionID' => $this->session_id, 'steamid' => $steamid];
  977.  
  978. return $this->openPage('http://steamcommunity.com/actions/BlockUserAjax', ['postdata' => $data]);
  979. }
  980.  
  981. public function userUnblock($steamid)
  982. {
  983. $data = ['action' => 'unignore', 'friends['.$steamid.']' => 1];
  984.  
  985. return $this->openPage(
  986. $this->custom_acc_url.'/friends/blocked/?success=unignore&c=1',
  987. ['postdata' => $data, 'ref' => $this->custom_acc_url.'/friends/blocked/?success=unignore&c=1']
  988. );
  989. }
  990.  
  991. public function profileEdit($nickname, $summary, $custom_url = '')
  992. {
  993. $data = [
  994. 'personaName' => $nickname,
  995. 'sessionID' => $this->session_id,
  996. 'type' => 'profileSave',
  997. 'summary' => $summary,
  998. 'customURL' => $custom_url,
  999. 'primary_group_steamid' => 0,
  1000. 'favorite_badge_badgeid' => '',
  1001. 'weblink_1_title' => '',
  1002. 'weblink_1_url' => '',
  1003. 'weblink_2_title' => '',
  1004. 'weblink_2_url' => '',
  1005. 'weblink_3_title' => '',
  1006. 'weblink_3_url' => '',
  1007. 'real_name' => '',
  1008. 'country' => '',
  1009. 'state' => '',
  1010. 'city' => '',
  1011. 'profile_background' => '',
  1012. 'favorite_badge_communityitemid' => ''
  1013. ];
  1014.  
  1015. $auth = $this->auth;
  1016. $auth['account_name'] = $nickname;
  1017. $auth['account_custom_name'] = ($custom_url ? 'http://steamcommunity.com/id/'.$custom_url : $auth['account_custom_name']);
  1018. $this->cache->set('auth', $auth);
  1019.  
  1020. return $this->openPage($this->custom_acc_url.'/edit', ['postdata' => $data]);
  1021. }
  1022.  
  1023. public function steamStatus()
  1024. {
  1025. $cache = "steam_status";
  1026.  
  1027. if (!Cache::has($cache)) {
  1028. $url = "https://crowbar.steamdb.info/Barney";
  1029. $data = $this->openPage($url);
  1030.  
  1031. $result = collect(json_decode($data))["services"]->csgo;
  1032. Cache::put($cache, $data, 1);
  1033. } else {
  1034. $result = collect(json_decode(Cache::get($cache)))["services"]->csgo;
  1035. }
  1036.  
  1037. if (strtolower($result->title) == "webapi offline") {
  1038. $this->sockets->send('steam_status', $result);
  1039. }
  1040. }
  1041.  
  1042. public function checkTrades($errors = false)
  1043. {
  1044. if (!$errors) {
  1045. $trades = Trade::where('status', 'new')->get();
  1046. } else {
  1047. $trades = Trade::where('status', 'error')->get();
  1048. }
  1049.  
  1050. $this->updateBotInventory($this->bot_id);
  1051. $bot_inventory = collect(Cache::get("bot_inventory_{$this->bot_id}"));
  1052. foreach ($trades as $key => $trade) {
  1053. $reason = 'Trade not found';
  1054. if (str_contains($trade['type'], 'reward')) {
  1055. $round_id = json_decode($trade['type'])->reward;
  1056. $round = Round::getInfo($round_id);
  1057. $winner = User::getInfo($round->winner);
  1058. foreach (json_decode($trade['items']) as $item) {
  1059. $items[] = (array)$item;
  1060. }
  1061. if (!empty($items)) {
  1062. $item_error = false;
  1063. $reason_items = '';
  1064. $items_commission = [];
  1065. foreach ($items as $item) {
  1066. if (!isset($item['commission'])) {
  1067. $bot_item_asset = $bot_inventory->where('asset_id', "{$item['assetid']}")->where(
  1068. 'reserved',
  1069. false
  1070. )->first();
  1071. $bot_item = $bot_inventory->where('class_id', "{$item['classid']}")->where(
  1072. 'reserved',
  1073. false
  1074. )->first();
  1075. $item_info = Item::find($item['classid']);
  1076. if (!is_null($bot_item_asset)) {
  1077. $items_to_send[] = [
  1078. 'appid' => $this->app_id,
  1079. 'contextid' => '2',
  1080. 'amount' => 1,
  1081. 'assetid' => $bot_item_asset['asset_id']
  1082. ];
  1083. $bot_inventory->transform(
  1084. function ($item) use ($bot_item_asset) {
  1085. if ($item['asset_id'] == $bot_item_asset['asset_id']) {
  1086. $item['reserved'] = true;
  1087. }
  1088.  
  1089. return $item;
  1090. }
  1091. );
  1092. } elseif (is_null($bot_item_asset) && $bot_item) {
  1093. $items_to_send[] = [
  1094. 'appid' => $this->app_id,
  1095. 'contextid' => '2',
  1096. 'amount' => 1,
  1097. 'assetid' => $bot_item['asset_id']
  1098. ];
  1099. $bot_inventory->transform(
  1100. function ($item) use ($bot_item) {
  1101. if ($item['asset_id'] == $bot_item['asset_id']) {
  1102. $item['reserved'] = true;
  1103. }
  1104.  
  1105. return $item;
  1106. }
  1107. );
  1108. } else {
  1109. $reason_items .= " {$item_info->en_name}";
  1110. $item_error = true;
  1111. }
  1112. } else {
  1113. $items_commission[] = $item;
  1114. }
  1115. }
  1116. if (!$item_error) {
  1117. if (!empty($items_to_send)) {
  1118. $trade_items = collect($items_to_send)->map(
  1119. function ($item) use ($bot_inventory) {
  1120. return [
  1121. 'asset_id' => $item['assetid'],
  1122. 'class_id' => $bot_inventory->where('asset_id', $item['assetid'])->first(
  1123. )['class_id']
  1124. ];
  1125. }
  1126. );
  1127. $commission_items = collect($items_commission)->map(
  1128. function ($item) use ($bot_inventory) {
  1129. return [
  1130. 'asset_id' => $item['assetid'],
  1131. 'class_id' => $item['classid']
  1132. ];
  1133. }
  1134. );
  1135. $res = $this->tradeSend(
  1136. $winner->id,
  1137. trans('steam_message.win', ['round' => $round_id]),
  1138. $winner->trade_offer,
  1139. $items_to_send
  1140. );
  1141. if (isset($res->tradeofferid)) {
  1142. Trade::where('id', $trade['id'])->update(
  1143. [
  1144. 'status' => 'sending',
  1145. 'items' => $trade_items,
  1146. 'commission' => $commission_items,
  1147. 'trade_id' => $res->tradeofferid
  1148. ]
  1149. );
  1150. Round::where('id', $round_id)->update(
  1151. ['status' => 'done']
  1152. );
  1153. $result = ['result' => 'Trade sent', 'reason' => ''];
  1154. } else {
  1155. if (isset($res->strError)) {
  1156. $reason = (string)$res->strError;
  1157. }
  1158. }
  1159. } else {
  1160. $reason = 'Cant find items in bot inventory';
  1161. }
  1162. } else {
  1163. $reason = "Items cant be found:{$reason_items}";
  1164. }
  1165. } else {
  1166. $reason = 'Cant load trade items';
  1167. }
  1168. if (!isset($result)) {
  1169. $result = ['result' => 'Trade not sent', 'reason' => $reason, 'error' => true];
  1170. Round::where('id', $round_id)->update(
  1171. ['status' => 'error']
  1172. );
  1173. Trade::where('id', $trade['id'])->update(['status' => 'error']);
  1174. $bot_inventory->transform(
  1175. function ($botItem) {
  1176. if(isset($items_to_send)) {
  1177. foreach ($items_to_send as $item) {
  1178. if ($botItem['asset_id'] == $item['asset_id']) {
  1179. $botItem['reserved'] = false;
  1180. }
  1181. }
  1182. }
  1183. return $botItem;
  1184. }
  1185. );
  1186. }
  1187. }
  1188. TradeLog::create(
  1189. ['trade_id' => $trade['id'], 'result' => $result['result'], 'response' => $result['reason']]
  1190. );
  1191. unset($items);
  1192. unset($items_to_send);
  1193. unset($result);
  1194. }
  1195. }
  1196. }
Add Comment
Please, Sign In to add comment