MangareaderBridge.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. <?php
  2. define('MANGAREADER_LIMIT', 10); // The default limit
  3. class MangareaderBridge extends BridgeAbstract{
  4. public function loadMetadatas() {
  5. $this->maintainer = "logmanoriginal";
  6. $this->name = "Mangareader Bridge";
  7. $this->uri = "http://www.mangareader.net";
  8. $this->description = "Returns the latest updates, popular mangas or manga updates (new chapters)";
  9. $this->update = "2016-01-22";
  10. $this->parameters["Get latest updates"] = '[]';
  11. $this->parameters["Get popular mangas"] =
  12. '[
  13. {
  14. "name" : "Category",
  15. "identifier" : "category",
  16. "type" : "list",
  17. "required" : "true",
  18. "values" : [
  19. {
  20. "name" : "All",
  21. "value" : "all"
  22. },
  23. {
  24. "name" : "Action",
  25. "value" : "action"
  26. },
  27. {
  28. "name" : "Adventure",
  29. "value" : "adventure"
  30. },
  31. {
  32. "name" : "Comedy",
  33. "value" : "comedy"
  34. },
  35. {
  36. "name" : "Demons",
  37. "value" : "demons"
  38. },
  39. {
  40. "name" : "Drama",
  41. "value" : "drama"
  42. },
  43. {
  44. "name" : "Ecchi",
  45. "value" : "ecchi"
  46. },
  47. {
  48. "name" : "Fantasy",
  49. "value" : "fantasy"
  50. },
  51. {
  52. "name" : "Gender Bender",
  53. "value" : "gender-bender"
  54. },
  55. {
  56. "name" : "Harem",
  57. "value" : "harem"
  58. },
  59. {
  60. "name" : "Historical",
  61. "value" : "historical"
  62. },
  63. {
  64. "name" : "Horror",
  65. "value" : "horror"
  66. },
  67. {
  68. "name" : "Josei",
  69. "value" : "josei"
  70. },
  71. {
  72. "name" : "Magic",
  73. "value" : "magic"
  74. },
  75. {
  76. "name" : "Martial Arts",
  77. "value" : "martial-arts"
  78. },
  79. {
  80. "name" : "Mature",
  81. "value" : "mature"
  82. },
  83. {
  84. "name" : "Mecha",
  85. "value" : "mecha"
  86. },
  87. {
  88. "name" : "Military",
  89. "value" : "military"
  90. },
  91. {
  92. "name" : "Mystery",
  93. "value" : "mystery"
  94. },
  95. {
  96. "name" : "One Shot",
  97. "value" : "one-shot"
  98. },
  99. {
  100. "name" : "Psychological",
  101. "value" : "psychological"
  102. },
  103. {
  104. "name" : "Romance",
  105. "value" : "romance"
  106. },
  107. {
  108. "name" : "School Life",
  109. "value" : "school-life"
  110. },
  111. {
  112. "name" : "Sci-Fi",
  113. "value" : "sci-fi"
  114. },
  115. {
  116. "name" : "Seinen",
  117. "value" : "seinen"
  118. },
  119. {
  120. "name" : "Shoujo",
  121. "value" : "shoujo"
  122. },
  123. {
  124. "name" : "Shoujoai",
  125. "value" : "shoujoai"
  126. },
  127. {
  128. "name" : "Shounen",
  129. "value" : "shounen"
  130. },
  131. {
  132. "name" : "Shounenai",
  133. "value" : "shounenai"
  134. },
  135. {
  136. "name" : "Slice of Life",
  137. "value" : "slice-of-life"
  138. },
  139. {
  140. "name" : "Smut",
  141. "value" : "smut"
  142. },
  143. {
  144. "name" : "Sports",
  145. "value" : "sports"
  146. },
  147. {
  148. "name" : "Super Power",
  149. "value" : "super-power"
  150. },
  151. {
  152. "name" : "Supernatural",
  153. "value" : "supernatural"
  154. },
  155. {
  156. "name" : "Tragedy",
  157. "value" : "tragedy"
  158. },
  159. {
  160. "name" : "Vampire",
  161. "value" : "vampire"
  162. },
  163. {
  164. "name" : "Yaoi",
  165. "value" : "yaoi"
  166. },
  167. {
  168. "name" : "Yuri",
  169. "value" : "yuri"
  170. }
  171. ],
  172. "exampleValue" : "All",
  173. "title" : "Select your category"
  174. }
  175. ]';
  176. $this->parameters["Get manga updates"] =
  177. '[
  178. {
  179. "name" : "Path",
  180. "identifier" : "path",
  181. "type" : "text",
  182. "required" : "true",
  183. "pattern" : "[a-zA-Z0-9-_]*",
  184. "exampleValue" : "bleach, umi-no-kishidan",
  185. "title" : "URL part of desired manga"
  186. },
  187. {
  188. "name" : "Limit",
  189. "identifier" : "limit",
  190. "type" : "number",
  191. "exampleValue" : "10",
  192. "title" : "Number of items to return.\n-1 returns all"
  193. }
  194. ]';
  195. }
  196. public function collectData(array $param){
  197. $this->request = '';
  198. $type = "latest"; // can be "latest", "popular" or "path". Default is "latest"!
  199. $path = "latest";
  200. $limit = MANGAREADER_LIMIT;
  201. if(isset($param['category'])){ // Get popular updates
  202. $type = "popular";
  203. $path = "popular";
  204. if($param['category'] !== "all"){
  205. $path .= "/" . $param['category'];
  206. }
  207. }
  208. if(isset($param['path'])){ // Get manga updates
  209. $type = "path";
  210. $path = $param['path'];
  211. }
  212. if(isset($param['limit']) && $param['limit'] !== ""){ // Get manga updates (optional parameter)
  213. $limit = $param['limit'];
  214. }
  215. // We'll use the DOM parser for this as it makes navigation easier
  216. $html = file_get_contents("http://www.mangareader.net/" . $path);
  217. if(!$html){
  218. $this->returnError('Could not receive data for ' . $path . '!', 400);
  219. }
  220. $doc = new DomDocument;
  221. @$doc->loadHTML($html);
  222. // Navigate via XPath
  223. $xpath = new DomXPath($doc);
  224. // Build feed based on the context (site updates or manga updates)
  225. if($type === "latest"){
  226. $this->request = 'Latest updates';
  227. // Query each item (consists of Manga + chapters)
  228. $nodes = $xpath->query("//*[@id='latestchapters']/table//td");
  229. foreach ($nodes as $node){
  230. // Query the manga
  231. $manga = $xpath->query("a[@class='chapter']", $node)->item(0);
  232. // Collect the chapters for each Manga
  233. $chapters = $xpath->query("a[@class='chaptersrec']", $node);
  234. if (isset($manga) && $chapters->length >= 1){
  235. $item = new \Item();
  236. $item->uri = 'http://www.mangareader.net' . htmlspecialchars($manga->getAttribute('href'));
  237. $item->title = htmlspecialchars($manga->nodeValue);
  238. // Add each chapter to the feed
  239. $item->content = "";
  240. foreach ($chapters as $chapter){
  241. if($item->content <> ""){
  242. $item->content .= "<br>";
  243. }
  244. $item->content .= "<a href='http://www.mangareader.net" . htmlspecialchars($chapter->getAttribute('href')) . "'>" . htmlspecialchars($chapter->nodeValue) . "</a>";
  245. }
  246. $this->items[] = $item;
  247. }
  248. }
  249. }
  250. if($type === "popular"){
  251. $pagetitle = $xpath->query(".//*[@id='bodyalt']/h1")->item(0)->nodeValue;
  252. $this->request = substr($pagetitle, 0, strrpos($pagetitle, " -")); // "Popular mangas for ..."
  253. // Query all mangas
  254. $mangas = $xpath->query("//*[@id='mangaresults']/*[@class='mangaresultitem']");
  255. foreach ($mangas as $manga){
  256. // The thumbnail is encrypted in a css-style...
  257. // format: "background-image:url('<the part which is actually interesting>')"
  258. $mangaimgelement = $xpath->query(".//*[@class='imgsearchresults']", $manga)->item(0)->getAttribute('style');
  259. $item = new \Item();
  260. $item->title = htmlspecialchars($xpath->query(".//*[@class='manga_name']//a", $manga)->item(0)->nodeValue);
  261. $item->uri = 'http://www.mangareader.net' . $xpath->query(".//*[@class='manga_name']//a", $manga)->item(0)->getAttribute('href');
  262. $item->author = htmlspecialchars($xpath->query("//*[@class='author_name']", $manga)->item(0)->nodeValue);
  263. $item->chaptercount = $xpath->query(".//*[@class='chapter_count']", $manga)->item(0)->nodeValue;
  264. $item->genre = htmlspecialchars($xpath->query(".//*[@class='manga_genre']", $manga)->item(0)->nodeValue);
  265. $item->thumbnailUri = substr($mangaimgelement, 22, strlen($mangaimgelement) - 24);
  266. $item->content = '<a href="' . $item->uri . '"><img src="' . $item->thumbnailUri . '" alt="' . $item->title . '" /></a><p>' . $item->genre . '</p><p>' . $item->chaptercount . '</p>';
  267. $this->items[] = $item;
  268. }
  269. }
  270. if($type === "path") {
  271. $this->request = $xpath->query(".//*[@id='mangaproperties']//*[@class='aname']")->item(0)->nodeValue;
  272. $query = "(.//*[@id='listing']//tr)[position() > 1]";
  273. if($limit !== -1){
  274. $query = "(.//*[@id='listing']//tr)[position() > 1][position() > last() - " . $limit . "]";
  275. }
  276. $chapters = $xpath->query($query);
  277. foreach ($chapters as $chapter){
  278. $item = new \Item();
  279. $item->title = htmlspecialchars($xpath->query("td[1]", $chapter)->item(0)->nodeValue);
  280. $item->uri = 'http://www.mangareader.net' . $xpath->query("td[1]/a", $chapter)->item(0)->getAttribute('href');
  281. $item->timestamp = strtotime($xpath->query("td[2]", $chapter)->item(0)->nodeValue);
  282. array_unshift($this->items, $item);
  283. }
  284. }
  285. // Return some dummy-data if no content available
  286. if(count($this->items) == 0){
  287. $item = new \Item();
  288. $item->content = "<p>No updates available</p>";
  289. $this->items[] = $item;
  290. }
  291. }
  292. public function getName(){
  293. return (!empty($this->request) ? $this->request . ' - ' : '') . 'Mangareader Bridge';
  294. }
  295. public function getURI(){
  296. return 'http://www.mangareader.net';
  297. }
  298. public function getCacheDuration(){
  299. return 10800; // 3 hours
  300. }
  301. }
  302. ?>