/ emotes_xa22.php
emotes_xa22.php
  1  <?php
  2  http_response_code(404);
  3  echo('File not found.');
  4  die();
  5  //define('DEV_MODE', $_SERVER['REMOTE_ADDR'] === '51.159.28.165');
  6  //define('DEV_MODE', false);
  7  /*
  8  if (!DEV_MODE) {
  9    http_response_code(404);
 10    echo('File not found.');
 11    die();
 12  }
 13  else {
 14    ini_set('display_errors', 1);
 15    error_reporting(E_ALL & ~E_NOTICE);
 16  }
 17  */
 18  header('Content-Type: application/json');
 19  
 20  require_once 'lib/db.php';
 21  require_once 'lib/userpwd.php';
 22  
 23  define('XA_DOMAIN', ($_SERVER['HTTP_HOST'] === 'sys.4chan.org') ? '4chan.org' : '4channel.org');
 24  define('XA_PWD_TTL', 3600); // 1h
 25  define('XA_COOKIE_TTL', 172800); // 48h
 26  
 27  define('HMAC_SECRET', '58c7716fe310556e782b45610b4c1202f56df9f6de2bad92f7df17a7ae80a288');
 28  
 29  define('ERR_BAD_REQ', 'Bad Request');
 30  define('ERR_BAD_TKN', 'Cookies need to be enabled');
 31  define('ERR_NO_PTS', 'Not enough points');
 32  define('ERR_ALREADY_OWNED', 'You already have that emote');
 33  define('ERR_GENERIC', 'Internal Server Error');
 34  
 35  define('XA_ROLL_PRICE', 10);
 36  define('XA_TICK_POINTS', 20);
 37  define('XA_TICK_INTERVAL', 300);
 38  
 39  // ------------
 40  
 41  $emotes = [
 42    // Image emotes (type 2, 3): [ type, filename prefix, width, height ]
 43    // 81 emotes
 44    'AngryWojak' => [ 2, '03d18964', 27, 32 ],
 45    'Aquacry' => [ 2, '83cf2699', 30, 30 ],
 46    'AWOOOO' => [ 2, 'e2ad2cb7', 28, 32 ],
 47    'AYAYA' => [ 2, 'f93f9e5a', 32, 31 ],
 48    'AYAYAHyper' => [ 2, 'bc1ff2b8', 32, 32 ],
 49    'BOOBA' => [ 2, 'fb56168f', 32, 32 ],
 50    'BOOMER' => [ 2, '51ca59c2', 32, 32 ],
 51    'Bruh' => [ 2, '67905c4f', 32, 32 ],
 52    'Catcry' => [ 2, '967f06c9', 28, 28 ],
 53    'ChadYes' => [ 2, 'c7375c9d', 31, 32 ],
 54    'COPIUM' => [ 2, '4dfb5c71', 32, 31 ],
 55    'DontBully' => [ 2, '199f7d0e', 31, 32 ],
 56    'EZY' => [ 2, 'adf2d2f0', 28, 26 ],
 57    'FeelsBadMan' => [ 2, '59b6bba6', 30, 29 ],
 58    'FeelsGoodMan' => [ 2, 'cda7b2fb', 32, 24 ],
 59    'FeelsOkayMan' => [ 2, '08b66b75', 28, 27 ],
 60    'FeelsSpecialMan' => [ 2, '25086889', 28, 25 ],
 61    'FeelsStrongMan' => [ 2, '0ee6ba1c', 32, 31 ],
 62    'FeelsWeirdMan' => [ 2, 'ad2977e6', 28, 27 ],
 63    'gachiGASM' => [ 2, 'c291d202', 24, 28 ],
 64    'gachiHYPER' => [ 2, '634a21ba', 24, 28 ],
 65    'Gigachad' => [ 2, '7a95728b', 29, 32 ],
 66    'GoodNight' => [ 2, 'a6d16707', 31, 32 ],
 67    'Hahaa' => [ 2, 'af528e56', 28, 28 ],
 68    'HeavyBreathing' => [ 2, '4623886c', 32, 32 ],
 69    'KannaNom' => [ 2, '5de4addd', 32, 32 ],
 70    'KannaPolice' => [ 2, '98cf0be7', 32, 32 ],
 71    'KEKW' => [ 2, 'e54792d7', 32, 32 ],
 72    'KEKWait' => [ 2, 'c2cfb2e3', 32, 32 ],
 73    'MarisaFace' => [ 2, '857a9ea0', 24, 24 ],
 74    'MeguminHappy' => [ 2, 'a19762fc', 32, 32 ],
 75    'MikuStare' => [ 2, 'b674048b', 32, 32 ],
 76    'monkaChrist' => [ 2, '48c107b3', 28, 28 ],
 77    'monkaGIGA' => [ 2, 'de27847b', 28, 28 ],
 78    'monkaH' => [ 2, 'acb11630', 28, 28 ],
 79    'monkaHmm' => [ 2, 'd3c674ba', 32, 32 ],
 80    'monkaMEGA' => [ 2, '0b3318e4', 28, 28 ],
 81    'monkaOMEGA' => [ 2, 'bb299b4d', 32, 32 ],
 82    'monkaS' => [ 2, 'ed1cc57f', 28, 28 ],
 83    'monkaSpeed' => [ 2, '87c89650', 32, 30 ],
 84    'monkaW' => [ 2, 'b05923f5', 32, 32 ],
 85    'nepSmug' => [ 2, '57b01648', 32, 32 ],
 86    'OMEGALUL' => [ 2, 'c4035570', 31, 32 ],
 87    'peepoBlanket' => [ 2, '099390a2', 31, 32 ],
 88    'peepoClown' => [ 2, '8ea2d160', 32, 32 ],
 89    'peepoHappy' => [ 2, '68104e2a', 28, 20 ],
 90    'peepoWTF' => [ 2, '3d8675e9', 28, 19 ],
 91    'Pepega' => [ 2, '1ee7c5a1', 32, 25 ],
 92    'PepeHands' => [ 2, 'f2ecf801', 32, 32 ],
 93    'PepeLaugh' => [ 2, '51cbf903', 30, 29 ],
 94    'PepeLmao' => [ 2, '25908e08', 28, 28 ],
 95    'pepePoint' => [ 2, '90786369', 32, 32 ],
 96    'PepoG' => [ 2, '4459d60b', 32, 26 ],
 97    'pepoRope' => [ 2, '6ec0dd2c', 32, 31 ],
 98    'PepoThink' => [ 2, '9ecd704b', 32, 31 ],
 99    'pikachuS' => [ 2, '42faedcc', 32, 32 ],
100    'PillowNo' => [ 2, '1e4d8dfa', 32, 32 ],
101    'PillowYes' => [ 2, '6f5bc7e5', 32, 32 ],
102    'Pog' => [ 2, 'fad6951c', 28, 28 ],
103    'POGGERS' => [ 2, '6f0d4e37', 32, 32 ],
104    'PressF' => [ 2, 'f0a256b9', 32, 30 ],
105    'REEeee' => [ 2, 'b06b1566', 32, 32 ],
106    'REEEEE' => [ 2, 'ba70c4d9', 32, 28 ],
107    'ReimuGlare' => [ 2, 'bdf28159', 32, 32 ],
108    'ReimuPalm' => [ 2, '41a37aa0', 32, 32 ],
109    'SadCatW' => [ 2, 'd8f61d71', 32, 32 ],
110    'Sadge' => [ 2, 'e024965e', 28, 22 ],
111    'SeetheWojak' => [ 2, 'a9f848d3', 28, 32 ],
112    'Stonks' => [ 2, '53478ca5', 31, 32 ],
113    'ThisIsFine' => [ 2, 'd9bf8456', 28, 31 ],
114    'Thonk' => [ 2, 'ec538b5c', 32, 27 ],
115    'TooLewd' => [ 2, 'ddc55766', 32, 32 ],
116    'Tuturu' => [ 2, 'c72e8e84', 32, 32 ],
117    'umaruCry' => [ 2, '7242c342', 28, 28 ],
118    'WanWan' => [ 2, '8a527ac8', 32, 31 ],
119    'WeirdChamp' => [ 2, '3021a426', 31, 32 ],
120    'weSmart' => [ 2, '6476e57d', 27, 28 ],
121    'wojakNPC' => [ 2, '24edafcc', 32, 32 ],
122    'wojakWithered' => [ 2, 'ed7d4c3a', 32, 30 ],
123    'WTFF' => [ 2, '8b7cc3e0', 32, 32 ],
124    'YEP' => [ 2, 'e1899bbe', 32, 31 ],
125    'YesHoney' => [ 2, '2b414cf1', 31, 25 ],
126    // 28 emotes
127    'bane' => [ 3, 'c458ef22', 32, 32 ],
128    'bog' => [ 3, 'c2e2602a', 32, 32 ],
129    'cia' => [ 3, 'c69a1ef1', 32, 32 ],
130    'cockmongler' => [ 3, 'eda6f332', 22, 32 ],
131    'desu' => [ 3, '80692b94', 28, 32 ],
132    'desusmirk' => [ 3, '72694e0e', 41, 32 ],
133    'frodo' => [ 3, 'e9d526e8', 32, 32 ],
134    'goldface' => [ 3, '7081142e', 32, 32 ],
135    'happycat' => [ 3, '1d3f2a13', 27, 32 ],
136    'happyn' => [ 3, 'afd49202', 25, 32 ],
137    'jannydog' => [ 3, 'f0dcbf8a', 35, 32 ],
138    'koiwai' => [ 3, '1d7e369a', 44, 32 ],
139    'koiwaiwave' => [ 3, '0e313986', 31, 32 ],
140    'konata' => [ 3, 'eb07a2c8', 32, 32 ],
141    'laughingw' => [ 3, '6e6217c7', 32, 32 ],
142    'longcat' => [ 3, '0ee48fb4', 37, 32 ],
143    'longcata' => [ 3, '95c37417', 37, 30 ],
144    'longcatb' => [ 3, 'e77bc341', 37, 32 ],
145    'moetron' => [ 3, 'cf1d4b8d', 32, 32 ],
146    'mudkip' => [ 3, 'a4b23eff', 31, 32 ],
147    'shoopdw' => [ 3, '11339e7b', 23, 32 ],
148    'shoopdw2' => [ 3, '49bde730', 100, 32 ],
149    'troll' => [ 3, 'd89a0070', 37, 32 ],
150    'trollface' => [ 3, '7b4acfbf', 32, 26 ],
151    'yaranaika' => [ 3, 'a6955123', 32, 32 ],
152    'yaranaika2' => [ 3, '4d00227b', 32, 32 ],
153    
154    // Unicode emojis (type 1): [ type, html entity ]
155    // 58 emojis
156    'happy' => [ 1, '&#x1F600;' ],
157    'grin' => [ 1, '&#x1F604;' ],
158    'xd' => [ 1, '&#x1F606;' ],
159    'grinsweat' => [ 1, '&#x1F605;' ],
160    'rofl' => [ 1, '&#x1F923;' ],
161    'lmao' => [ 1, '&#x1F602;' ],
162    'smile' => [ 1, '&#x1F642;' ],
163    'wink' => [ 1, '&#x1F609;' ],
164    'glad' => [ 1, '&#x1F60A;' ],
165    'kiss' => [ 1, '&#x1F619;' ],
166    'crazy' => [ 1, '&#x1F92A;' ],
167    'think' => [ 1, '&#x1F914;' ],
168    'wot' => [ 1, '&#x1F928;' ],
169    'kay' => [ 1, '&#x1F610;' ],
170    'yikes' => [ 1, '&#x1F612;' ],
171    'eyeroll' => [ 1, '&#x1F644;' ],
172    'confused' => [ 1, '&#x1F615;' ],
173    'pensive' => [ 1, '&#x1F614;' ],
174    'disgust' => [ 1, '&#x1F922;' ],
175    'vomit' => [ 1, '&#x1F92E;' ],
176    'dizzy' => [ 1, '&#x1F635;' ],
177    'nerd' => [ 1, '&#x1F913;' ],
178    'worry' => [ 1, '&#x1F61F;' ],
179    'sad' => [ 1, '&#x1F641;' ],
180    'frown' => [ 1, '&#x2639;&#xFE0F;' ],
181    'wow' => [ 1, '&#x1F632;' ],
182    'blush' => [ 1, '&#x1F633;' ],
183    'cry' => [ 1, '&#x1F622;' ],
184    'plead' => [ 1, '&#x1F97A;' ],
185    'baw' => [ 1, '&#x1F62D;' ],
186    'shock' => [ 1, '&#x1F631;' ],
187    'anguish' => [ 1, '&#x1F627;' ],
188    'devil' => [ 1, '&#x1F608;' ],
189    'angry' => [ 1, '&#x1F620;' ],
190    'struggle' => [ 1, '&#x1F623;' ],
191    'proud' => [ 1, '&#x1F624;' ],
192    'smirk' => [ 1, '&#x1F60F;' ],
193    'drool' => [ 1, '&#x1F924;' ],
194    'love' => [ 1, '&#x1F60D;' ],
195    'skull' => [ 1, '&#x1F480;' ],
196    'clown' => [ 1, '&#x1F921;' ],
197    'alien' => [ 1, '&#x1F47D;' ],
198    'robot' => [ 1, '&#x1F916;' ],
199    'ok' => [ 1, '&#x1F44C;' ],
200    'fu' => [ 1, '&#x1F595;' ],
201    'thup' => [ 1, '&#x1F44D;' ],
202    'thdown' => [ 1, '&#x1F44E;' ],
203    'punch' => [ 1, '&#x1F44A;' ],
204    'pray' => [ 1, '&#x1F64F;' ],
205    'flex' => [ 1, '&#x1F4AA;' ],
206    'eyes' => [ 1, '&#x1F440;' ],
207    'drip' => [ 1, '&#x1F4A6;' ],
208    'wind' => [ 1, '&#x1F4A8;' ],
209    'fire' => [ 1, '&#x1F525;' ],
210    'clover' => [ 1, '&#x1F340;' ],
211    'anger' => [ 1, '&#x1F4A2;' ],
212    'perfect' => [ 1, '&#x1F4AF;' ],
213    'zzz' => [ 1, '&#x1F4A4;' ]
214  ];
215  
216  $emote_pools = [
217    // 58
218    ['happy','grin','xd','grinsweat','rofl','lmao','smile','wink','glad','kiss',
219    'crazy','think','wot','kay','yikes','eyeroll','confused','pensive','disgust',
220    'vomit','dizzy','nerd','worry','sad','frown','wow','blush','cry','plead','baw',
221    'shock','anguish','devil','angry','struggle','proud','smirk','drool','love',
222    'skull','clown','alien','robot','ok','fu','thup','thdown','punch','pray',
223    'flex','eyes','drip','wind','fire','clover','anger','perfect','zzz'],
224    
225    // 81
226    ['03d18964','83cf2699','e2ad2cb7','f93f9e5a','bc1ff2b8','fb56168f','51ca59c2',
227    '67905c4f','967f06c9','c7375c9d','4dfb5c71','199f7d0e','adf2d2f0','59b6bba6',
228    'cda7b2fb','08b66b75','25086889','0ee6ba1c','ad2977e6','c291d202','634a21ba',
229    '7a95728b','a6d16707','af528e56','4623886c','5de4addd','98cf0be7','e54792d7',
230    'c2cfb2e3','857a9ea0','a19762fc','b674048b','48c107b3','de27847b','acb11630',
231    'd3c674ba','0b3318e4','bb299b4d','ed1cc57f','87c89650','b05923f5','57b01648',
232    'c4035570','099390a2','8ea2d160','68104e2a','3d8675e9','1ee7c5a1','f2ecf801',
233    '51cbf903','25908e08','90786369','4459d60b','6ec0dd2c','9ecd704b','42faedcc',
234    '1e4d8dfa','6f5bc7e5','fad6951c','6f0d4e37','f0a256b9','b06b1566','ba70c4d9',
235    'bdf28159','41a37aa0','d8f61d71','e024965e','a9f848d3','53478ca5','d9bf8456',
236    'ec538b5c','ddc55766','c72e8e84','7242c342','8a527ac8','3021a426','6476e57d',
237    '24edafcc','ed7d4c3a','8b7cc3e0','e1899bbe','2b414cf1'],
238    
239    // 28
240    ['c458ef22','c2e2602a','c69a1ef1','eda6f332','80692b94','72694e0e','e9d526e8',
241    '7081142e','1d3f2a13','afd49202','f0dcbf8a','1d7e369a','0e313986','eb07a2c8',
242    '6e6217c7','0ee48fb4','95c37417','e77bc341','cf1d4b8d','a4b23eff','11339e7b',
243    '49bde730','d89a0070','7b4acfbf','a6955123','4d00227b']
244  ];
245  
246  // ------------
247  
248  function xa_error($msg, $extra = null) {
249    $data = array('status' => 'error', 'msg' => $msg);
250    
251    if ($extra) {
252      $data = array_merge($data, $extra);
253    }
254    
255    echo json_encode($data);
256    
257    die();
258  }
259  
260  function xa_success($data = null) {
261    $ret = array('status' => 'success');
262    
263    if ($data) {
264      $ret['data'] = $data;
265    }
266    
267    echo json_encode($ret);
268    
269    die();
270  }
271  
272  /**
273   * Sessions
274   */
275  function xa_start_session() {
276    // Recover previous session by sid
277    if (isset($_COOKIE['xa_sid']) && $_COOKIE['xa_sid']) {
278      $data = xa_recover_session_by_sid($_COOKIE['xa_sid']);
279      
280      if ($data) {
281        xa_success($data);
282      }
283    }
284    
285    $ip = $_SERVER['REMOTE_ADDR'];
286    
287    // Recover previous session by IP
288    $sid = hash_hmac('sha1', $ip, HMAC_SECRET);
289    
290    if (!$sid) {
291      xa_error(ERR_GENERIC . ' (ssx9)');
292    }  
293    
294    $data = xa_recover_session_by_sid($sid);
295    
296    if ($data) {
297      xa_set_sid_cookie($sid);
298      xa_success($data);
299    }
300    
301    // Create new session
302    $data = [];
303    
304    if (isset($_COOKIE['4chan_pass'])) {
305      $userpwd = new UserPwd($ip, XA_DOMAIN, $_COOKIE['4chan_pass']);
306      
307      if ($userpwd->maskLifetime() >= XA_PWD_TTL) {
308        $balance = 100;
309      }
310    }
311    else {
312      $balance = 0;
313    }
314    
315    $data['start_ts'] = $_SERVER['REQUEST_TIME'];
316    $data['balance'] = $balance;
317    $data['owned'] = [];
318    
319    $ret = xa_save_session($sid, $ip, $data);
320    
321    if (!$ret) {
322      xa_error(ERR_GENERIC . ' (ssx5)');
323    }
324    
325    xa_set_sid_cookie($sid);
326    xa_success($data);
327  }
328  
329  function xa_set_sid_cookie($sid) {
330    setcookie('xa_sid', $sid, $_SERVER['REQUEST_TIME'] + XA_COOKIE_TTL, '/', '.' . XA_DOMAIN, true);
331  }
332  
333  function xa_save_session($sid, $ip, $data) {
334    $sql = "INSERT INTO april_emotes (session_id, ip, data) VALUES('%s', '%s', '%s')";
335    
336    $data = json_encode($data);
337    
338    if (!$data) {
339      return false;
340    }
341    
342    return mysql_global_call($sql, $sid, $ip, $data);
343  }
344  
345  function xa_rebuild_owned_emotes($data) {
346    global $emotes;
347    
348    $owned_meta = [];
349    
350    if (!isset($data['owned'])) {
351      return $owned_meta;
352    }
353    
354    foreach ($data['owned'] as $key) {
355      $_e = $emotes[$key];
356      
357      if ($_e) {
358        $owned_meta[] = [$key, $_e[0], $_e[1]];
359      }
360    }
361    
362    return $owned_meta;
363  }
364  
365  function xa_recover_session_by_sid($sid) {
366    $sql = "SELECT data FROM april_emotes WHERE session_id = '%s' LIMIT 1";
367    
368    $res = mysql_global_call($sql, $sid);
369    
370    if (!$res) {
371      xa_error(ERR_GENERIC . ' (gsbs5)');
372    }
373    
374    $data = mysql_fetch_assoc($res)['data'];
375    
376    if (!$data) {
377      return null;
378    }
379    
380    $data = json_decode($data, true);
381    
382    if (!$data) {
383      xa_error(ERR_GENERIC . ' (gsbs4)');
384    }
385    
386    $data['owned'] = xa_rebuild_owned_emotes($data);
387    
388    return $data;
389  }
390  
391  /**
392   * Rolling
393   */
394  function xa_roll($size) {
395    global $emotes, $emote_pools;
396    
397    if (!isset($_COOKIE['xa_sid']) || !$_COOKIE['xa_sid']) {
398      xa_error(ERR_BAD_REQ);
399    }
400    
401    $sid = $_COOKIE['xa_sid'];
402    
403    $rolled_eids = [];
404    
405    for ($i = 0; $i < $size; $i++) { 
406      $_r = mt_rand(0, 99);
407      
408      if ($_r >= 90) {
409        // 28 emotes in pool 3
410        $rolled_eids[] = $emote_pools[2][mt_rand(0, count($emote_pools[2]) - 1)];
411      }
412      else if ($_r >= 50) {
413        // 81 emotes in pool 2
414        $rolled_eids[] = $emote_pools[1][mt_rand(0, count($emote_pools[1]) - 1)];
415      }
416      else {
417        // 58 emojis in pool 1
418        $rolled_eids[] = $emote_pools[0][mt_rand(0, count($emote_pools[0]) - 1)];
419      }
420    }
421    
422    mysql_global_call('START TRANSACTION');
423    
424    $sql = "SELECT data FROM april_emotes WHERE session_id = '%s' FOR UPDATE";
425    
426    $res = mysql_global_call($sql, $sid);
427    
428    if (!$res) {
429      mysql_global_call('COMMIT');
430      xa_error(ERR_GENERIC . ' (lbr8)');
431    }
432    
433    $data = mysql_fetch_assoc($res)['data'];
434    
435    if (!$data) {
436      mysql_global_call('COMMIT');
437      xa_error(ERR_BAD_REQ);
438    }
439    
440    $data = json_decode($data, true);
441  
442    if (!$data) {
443      mysql_global_call('COMMIT');
444      xa_error(ERR_GENERIC . ' (lbr9)');
445    }
446    
447    // Check if enough points
448    $full_balance = xa_get_full_balance($data);
449    $total_cost = $size * XA_ROLL_PRICE;
450    
451    if ($full_balance < $total_cost) {
452      mysql_global_call('COMMIT');
453      xa_error(ERR_NO_PTS, [ 'pts' => $data['balance'] ]);
454    }
455    
456    // Roll results to return to the client for visual purposes
457    $obtained = [];
458    
459    $recycled_points = 0;
460    
461    if (!isset($data['owned'])) {
462      $data['owned'] = [];
463    }
464    
465    foreach ($rolled_eids as $eid) {
466      $_e_meta = xa_get_emote_by_id($eid);
467      
468      list($key, $kind, $arg) = $_e_meta;
469      
470      // Emote already owned, recycle it
471      if (in_array($key, $data['owned'])) {
472        if ($kind === 3) {
473          $recycled_points += 10;
474        }
475        else {
476          $recycled_points += 5;
477        }
478      }
479      // New emote, add it to the owned list
480      else {
481        $data['owned'][] = $key;
482      }
483      
484      $obtained[] = $_e_meta;
485    }
486    
487    $data['balance'] += $recycled_points;
488    $data['balance'] -= $total_cost;
489    
490    $balance = $data['balance'];
491    
492    $data = json_encode($data);
493    
494    $sql = "UPDATE april_emotes SET data = '%s' WHERE session_id = '%s' LIMIT 1";
495    
496    $res = mysql_global_call($sql, $data, $sid);
497    
498    if (!$res) {
499      mysql_global_call('COMMIT');
500      xa_error(ERR_GENERIC . ' (lbr6)');
501    }
502    
503    mysql_global_call('COMMIT');
504    
505    xa_success(['obtained' => $obtained, 'balance' => $balance]);
506  }
507  
508  function xa_get_full_balance($data) {
509    $now = $_SERVER['REQUEST_TIME'];
510    $start_ts = (int)$data['start_ts'];
511    $tick_balance = floor(($now - $start_ts) / XA_TICK_INTERVAL) * XA_TICK_POINTS;
512    return $tick_balance + $data['balance'];
513  }
514  
515  function xa_get_emote_by_id($id) {
516    global $emotes;
517    
518    foreach ($emotes as $key => $meta) {
519      $_kind = $meta[0];
520      $_arg = $meta[1];
521      
522      // Emoji (type 1)
523      if ($_kind === 1) {
524        if ($key === $id) {
525          return [$key, $_kind, $_arg];
526        }
527      }
528      // Image emotes
529      else {
530        if ($_arg === $id) {
531          return [$key, $_kind, $_arg];
532        }
533      }
534    }
535    
536    return null;
537  }
538  
539  /**
540   * Buying
541   */
542  function xa_buy() {
543    global $emotes, $emote_pools;
544    
545    if (!isset($_COOKIE['xa_sid']) || !$_COOKIE['xa_sid']) {
546      xa_error(ERR_BAD_REQ);
547    }
548    
549    if (!isset($_POST['eid']) || !$_POST['eid']) {
550      xa_error(ERR_BAD_REQ);
551    }
552    
553    $obtained = xa_get_emote_by_id($_POST['eid']);
554    
555    if (!$obtained) {
556      xa_error(ERR_BAD_REQ);
557    }
558    
559    list($key, $kind, $arg) = $obtained;
560    
561    // Pool 1
562    if ($kind === 1) {
563      $total_cost = 50;
564    }
565    // Pool 2
566    else if ($kind === 2) {
567      $total_cost = 150;
568    }
569    // Pool 3
570    else {
571      $total_cost = 300;
572    }
573    
574    $sid = $_COOKIE['xa_sid'];
575    
576    mysql_global_call('START TRANSACTION');
577    
578    $sql = "SELECT data FROM april_emotes WHERE session_id = '%s' FOR UPDATE";
579    
580    $res = mysql_global_call($sql, $sid);
581    
582    if (!$res) {
583      mysql_global_call('COMMIT');
584      xa_error(ERR_GENERIC . ' (be0)');
585    }
586    
587    $data = mysql_fetch_assoc($res)['data'];
588    
589    if (!$data) {
590      mysql_global_call('COMMIT');
591      xa_error(ERR_BAD_REQ);
592    }
593    
594    $data = json_decode($data, true);
595  
596    if (!$data) {
597      mysql_global_call('COMMIT');
598      xa_error(ERR_GENERIC . ' (be1)');
599    }
600    
601    // Check if already owned
602    if (in_array($key, $data['owned'])) {
603      mysql_global_call('COMMIT');
604      xa_error(ERR_ALREADY_OWNED);
605    }
606    
607    // Check if enough points
608    $full_balance = xa_get_full_balance($data);
609    
610    if ($full_balance < $total_cost) {
611      mysql_global_call('COMMIT');
612      xa_error(ERR_NO_PTS, [ 'pts' => $data['balance'] ]);
613    }
614    
615    $data['owned'][] = $key;
616    $data['balance'] -= $total_cost;
617    
618    $balance = $data['balance'];
619    
620    $data = json_encode($data);
621    
622    $sql = "UPDATE april_emotes SET data = '%s' WHERE session_id = '%s' LIMIT 1";
623    
624    $res = mysql_global_call($sql, $data, $sid);
625    
626    if (!$res) {
627      mysql_global_call('COMMIT');
628      xa_error(ERR_GENERIC . ' (lbr6)');
629    }
630    
631    mysql_global_call('COMMIT');
632    
633    xa_success(['obtained' => $obtained, 'balance' => $balance]);
634  }
635  
636  // --------------
637  
638  if (!isset($_POST['action'])) {
639    xa_error(ERR_BAD_REQ);
640  }
641  
642  if (isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER'] != ''
643    && !preg_match('/^https?:\/\/([_a-z0-9]+)\.(4chan|4channel)\.org(\/|$)/', $_SERVER['HTTP_REFERER'])) {
644    xa_error(ERR_BAD_REQ . '(xr1)');
645  }
646  
647  // -------------
648  
649  $_action = $_POST['action'];
650  
651  if ($_action === 'start') {
652    xa_start_session();
653  }
654  else if ($_action === 'roll3') {
655    xa_roll(3);
656  }
657  else if ($_action === 'roll10') {
658    xa_roll(10);
659  }
660  else if ($_action === 'buy') {
661    xa_buy();
662  }
663  else {
664    xa_error(ERR_BAD_REQ);
665  }