Advertisement
Guest User

Untitled

a guest
Jul 21st, 2017
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.91 KB | None | 0 0
  1. <?php
  2. // This file is for Ponychan's JSON API. Its syntax will be somewhat similar to 4chan's
  3. // at https://github.com/4chan/4chan-API but rather than static JSON files, this will be dynamic
  4. // written by Ly
  5.  
  6. require_once 'inc/functions.php';
  7. require_once 'inc/anti-bot.php';
  8. require_once 'inc/database.php';
  9.  
  10. class apireq
  11. {
  12. static $req_types = array(
  13. "boards" => "listBoards",
  14. "threads" => "listThreads",
  15. "thread" => "listPosts",
  16. "catalog" => "listCatalog"
  17. );
  18.  
  19. private $req_type = "";
  20. private $board = "";
  21. private $page = 0;
  22. private $thread = 0;
  23.  
  24. public function __construct()
  25. {
  26. if (isset($_GET["req"]) && strlen($_GET["req"]) > 0 && array_key_exists($_GET["req"], self::$req_types))
  27. $this->req_type = $_GET["req"];
  28. else
  29. $this->err("Unknown request type. Allowed request types: ".implode(" ,", array_keys(self::$req_types)));
  30.  
  31. if (isset($_GET["board"]) && strlen($_GET["board"]) > 0)
  32. $this->board = addslashes($_GET["board"]);
  33.  
  34. if (isset($_GET["thread"]) && strlen($_GET["thread"]) > 0 && is_numeric($_GET["thread"]))
  35. $this->thread = (int)$_GET["thread"];
  36.  
  37. if (isset($_GET["page"]) && strlen($_GET["page"]) > 0 && is_numeric($_GET["page"]))
  38. $this->page = ((int)$_GET["page"] > 0 ? (int)$_GET["page"] - 1 : 0);
  39.  
  40. $this->{self::$req_types[$this->req_type]}();
  41. }
  42.  
  43. private function listCatalog()
  44. {
  45. $errors = array();
  46.  
  47. if (strlen($this->board) === 0)
  48. $errors[] = "Board not specified.";
  49.  
  50. if (count($errors))
  51. $this->err($errors);
  52.  
  53. global $config;
  54.  
  55. $board = "posts_".$this->board;
  56.  
  57. $limit = $config["threads_per_page"] * $config["max_pages"];
  58.  
  59. $data = query("SELECT main.*, (SELECT COUNT(*) FROM `$board` rc WHERE rc.`thread` = main.`id`) as replyCount, (SELECT COUNT(*) FROM `$board` ic WHERE ic.`thread` = main.`id` AND `file` != 'deleted' AND `file` IS NOT NULL) as imageCount FROM `$board` main ".
  60. "WHERE `thread` IS NULL ".
  61. "ORDER BY `sticky` DESC, `bump` DESC ".
  62. "LIMIT $limit");
  63.  
  64. if (!$data)
  65. $this->err("Invalid board or database error.");
  66.  
  67. $results = array();
  68. $dlFor = array();
  69.  
  70. while ($result = $data->fetch(PDO::FETCH_OBJ))
  71. {
  72. $results[] = $result;
  73. $dlFor[] = $result->id;
  74. }
  75.  
  76. $data = query($this->generateUnionSQL($dlFor, $board, 1));
  77.  
  78. if (!$data)
  79. $this->err("Invalid board or database error.");
  80.  
  81. $endResults = array();
  82.  
  83. $repliesTo = array();
  84.  
  85. while ($result = $data->fetch(PDO::FETCH_OBJ))
  86. $repliesTo[(int)$result->thread][] = $result;
  87.  
  88. $pageNum = 0;
  89.  
  90. foreach ($results as $thread)
  91. {
  92. $thrPosts = array();
  93.  
  94. $imagesInPosts = 0;
  95.  
  96. if (isset($repliesTo[(int)$thread->id]))
  97. {
  98. foreach ($repliesTo[(int)$thread->id] as $reply)
  99. {
  100. $thrPosts[] = $this->getPost($reply);
  101. if (isset($thrPosts[count($thrPosts)-1]->filename))
  102. $imagesInPosts++;
  103. }
  104. }
  105.  
  106. if (!isset($endResults[$pageNum]))
  107. $endResults[$pageNum] = array(
  108. "page" => $pageNum+1,
  109. "threads" => array()
  110. );
  111.  
  112. $OP = $this->getOP($thread);
  113.  
  114. $endResults[$pageNum]["threads"][] = array(
  115. "posts" => array_merge(
  116. $OP,
  117. array(
  118. "last_replies" => $thrPosts,
  119. "omitted_posts" => $OP["replies"] - (isset($repliesTo[(int)$thread->id]) ? count($repliesTo[(int)$thread->id]) : 0),
  120. "ommited_images"=> $OP["images"] - $imagesInPosts
  121. )
  122. )
  123. );
  124.  
  125. if (count($endResults[$pageNum]["threads"]) >= $config["threads_per_page"])
  126. $pageNum++;
  127. }
  128.  
  129. $this->success($endResults);
  130. }
  131.  
  132. private function listBoards()
  133. {
  134. $data = query("SELECT * FROM `boards`");
  135.  
  136. if (!$data)
  137. $this->err("Couldn't fetch boards.");
  138.  
  139. $boards = array();
  140.  
  141. global $config;
  142.  
  143. while ($board = $data->fetch(PDO::FETCH_OBJ))
  144. {
  145. $boards[] = array(
  146. "board" => $board->uri,
  147. "title" => $board->title,
  148. "per_page" => $config["threads_per_page"],
  149. "pages" => $config["max_pages"],
  150. "max_filesize" => $config["max_filesize"],
  151. "max_webm_filesize" => $config["max_video_filesize"],
  152. "max_comment_chars" => $config["max_body"],
  153. "max_webm_duration" => $config["max_video_length"],
  154. "bump_limit" => $config["reply_limit"],
  155. "image_limit" => $config["image_hard_limit"],
  156. "cooldowns" => array(
  157. "replies" => $config["flood_time"],
  158. "images" => $config["flood_time"],
  159. "threads" => $config["flood_time_op"][0][1]
  160. ),
  161. "meta_description" => $board->subtitle,
  162. );
  163. }
  164.  
  165. $this->success(array("boards" => $boards));
  166. }
  167.  
  168. private function listThreads()
  169. {
  170. $errors = array();
  171.  
  172. if (strlen($this->board) === 0)
  173. $errors[] = "Board not specified.";
  174.  
  175. if (count($errors))
  176. $this->err($errors);
  177.  
  178. global $config;
  179.  
  180. $board = "posts_".$this->board;
  181.  
  182. $offset = $config["threads_per_page"] * $this->page;
  183.  
  184. $data = query("SELECT main.*, (SELECT COUNT(*) FROM `$board` rc WHERE rc.`thread` = main.`id`) as replyCount, (SELECT COUNT(*) FROM `$board` ic WHERE ic.`thread` = main.`id` AND `file` != 'deleted' AND `file` IS NOT NULL) as imageCount FROM `$board` main ".
  185. "WHERE `thread` IS NULL ".
  186. "ORDER BY `sticky` DESC, `bump` DESC ".
  187. "LIMIT ".$config["threads_per_page"]." OFFSET $offset");
  188.  
  189. if (!$data)
  190. $this->err("Invalid board or database error.");
  191.  
  192. $results = array();
  193. $dlFor = array();
  194.  
  195. while ($result = $data->fetch(PDO::FETCH_OBJ))
  196. {
  197. $results[] = $result;
  198. $dlFor[] = $result->id;
  199. }
  200.  
  201. $data = query($this->generateUnionSQL($dlFor, $board, 3));
  202.  
  203. if (!$data)
  204. $this->err("Invalid board or database error.");
  205.  
  206. $endResults = array();
  207.  
  208. $repliesTo = array();
  209.  
  210. while ($result = $data->fetch(PDO::FETCH_OBJ))
  211. $repliesTo[(int)$result->thread][] = $result;
  212.  
  213. foreach ($results as $thread)
  214. {
  215. $thrPosts = array();
  216.  
  217. $imagesInPosts = 0;
  218.  
  219. if (isset($repliesTo[(int)$thread->id]))
  220. {
  221. foreach ($repliesTo[(int)$thread->id] as $reply)
  222. {
  223. $thrPosts[] = $this->getPost($reply);
  224. if (isset($thrPosts[count($thrPosts)-1]->filename))
  225. $imagesInPosts++;
  226. }
  227. }
  228.  
  229. $OP = $this->getOP($thread);
  230.  
  231. $endResults[] = array(
  232. "posts" => array_merge(array(
  233. array_merge(
  234. $OP,
  235. array(
  236. "omitted_posts" => $OP["replies"] - (isset($repliesTo[(int)$thread->id]) ? count($repliesTo[(int)$thread->id]) : 0),
  237. "ommited_images"=> $OP["images"] - $imagesInPosts
  238. )
  239. )
  240. ), $thrPosts)
  241. );
  242. }
  243.  
  244. $this->success(array("threads" => $endResults));
  245. }
  246.  
  247. private function listPosts()
  248. {
  249. $errors = array();
  250.  
  251. if (strlen($this->board) === 0)
  252. $errors[] = "Board not specified.";
  253.  
  254. if ($this->thread === 0)
  255. $errors[] = "Thread not specified.";
  256.  
  257. if (count($errors))
  258. $this->err($errors);
  259.  
  260. global $config;
  261.  
  262. $board = "posts_".$this->board;
  263.  
  264. $data = query("SELECT main.*, (SELECT COUNT(*) FROM `$board` rc WHERE rc.`thread` = main.`id`) as replyCount, (SELECT COUNT(*) FROM `$board` ic WHERE ic.`thread` = main.`id` AND `file` != 'deleted' AND `file` IS NOT NULL) as imageCount FROM `$board` main ".
  265. "WHERE `id` = '{$this->thread}' OR `thread` = '{$this->thread}'".
  266. "ORDER BY `ID` ASC ");
  267.  
  268. if (!$data)
  269. $this->err("Invalid thread, board or database error.");
  270.  
  271. $results = array();
  272. $op = true;
  273.  
  274. while ($result = $data->fetch(PDO::FETCH_OBJ))
  275. {
  276. if ($op)
  277. {
  278. $op = false;
  279. $results[] = $this->getOP($result);
  280. }
  281. else
  282. $results[] = $this->getPost($result);
  283. }
  284.  
  285. $this->success(array("posts" => $results));
  286. }
  287.  
  288. private function generateUnionSQL($parentIDs, $board, $limit)
  289. {
  290. if (count($parentIDs) === 0)
  291. return "";
  292.  
  293. if (count($parentIDs) === 1)
  294. return "SELECT * FROM `$board` WHERE `thread` = '".$parentIDs[0]."' ORDER BY `id` ASC LIMIT $limit";
  295.  
  296. $union = "";
  297.  
  298. foreach ($parentIDs as $key => $ID)
  299. {
  300. $union .= "(SELECT * FROM `$board` WHERE `thread` = '".$ID."' ORDER BY `id` ASC LIMIT $limit)";
  301. if (count($parentIDs)-1 !== $key)
  302. $union .= " UNION ALL ";
  303. }
  304.  
  305. return $union;
  306. }
  307.  
  308. private function getOP($post)
  309. {
  310. return array_merge(array(
  311. "sticky" => (int)$post->sticky,
  312. "closed" => (int)$post->locked,
  313. "mature" => (int)$post->mature,
  314. "anon" => (int)$post->anon_thread,
  315. "replies" => (int)$post->replyCount,
  316. "images" => (int)$post->imageCount
  317. ), $this->getPost($post));
  318. }
  319.  
  320. private function getPost($post)
  321. {
  322. return array_merge(array(
  323. "no" => (int)$post->id,
  324. "now" => date("m/d/y(D)H:i:s"),
  325. "name" => $post->name,
  326. "email" => $post->email,
  327. "com" => (in_array($this->req_type, array("catalog", "threads")) ? (strlen($post->body_nomarkup) > 100 ? substr($post->body_nomarkup, 0, 100)."..." : $post->body_nomarkup) : $post->body_nomarkup),
  328. "time" => (int)$post->time,
  329. "resto" => (int)$post->thread,
  330. "capcode" => $post->capcode
  331. ), $this->getFileInfo($post));
  332. }
  333.  
  334. private function getFileInfo($post)
  335. {
  336. if (!isset($post->filename) || !strlen($post->filename))
  337. return array();
  338.  
  339. return array(
  340. "filename" => $post->filename,
  341. "file" => $post->file,
  342. "thumb" => $post->thumb,
  343. "ext" => substr($post->file, strrpos($post->file, ".")),
  344. "w" => (int)$post->filewidth,
  345. "h" => (int)$post->fileheight,
  346. "tn_w" => (int)$post->thumbwidth,
  347. "tn_h" => (int)$post->thumbheight,
  348. "md5" => $post->filehash,
  349. "fsize" => (int)$post->filesize,
  350. );
  351. }
  352.  
  353. private function success($data)
  354. {
  355. header("Content-Type: application/json");
  356. $encoded = json_encode(
  357. array_merge(array(
  358. "status" => "success"),
  359. $data)
  360. );
  361. header("Content-Lengtj: ".strlen($encoded));
  362. die(encoded);
  363. }
  364.  
  365. private function err($error)
  366. {
  367. header("Content-Type: application/json");
  368. die(json_encode(array(
  369. "status" => "error",
  370. "messages" => (is_array($error) ? $error : array($error))
  371. )));
  372. }
  373. }
  374.  
  375. $request = new apireq();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement