yandex.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. <?php
  2. class yandex{
  3. /*
  4. curl functions
  5. */
  6. public function __construct(){
  7. include "lib/fuckhtml.php";
  8. $this->fuckhtml = new fuckhtml();
  9. include "lib/nextpage.php";
  10. $this->nextpage = new nextpage("yandex");
  11. }
  12. private function get($url, $get = [], $nsfw){
  13. $curlproc = curl_init();
  14. $search = $get["text"];
  15. if($get !== []){
  16. $get = http_build_query($get);
  17. $url .= "?" . $get;
  18. }
  19. curl_setopt($curlproc, CURLOPT_URL, $url);
  20. switch($nsfw){
  21. case "yes": $nsfw = "0"; break;
  22. case "maybe": $nsfw = "1"; break;
  23. case "no": $nsfw = "2"; break;
  24. }
  25. $headers =
  26. ["User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0",
  27. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
  28. "Accept-Encoding: gzip",
  29. "Accept-Language: en-US,en;q=0.5",
  30. "DNT: 1",
  31. "Cookie: yp=1716337604.sp.family%3A{$nsfw}#1685406411.szm.1:1920x1080:1920x999",
  32. "Referer: https://yandex.com/images/search?text={$search}",
  33. "Connection: keep-alive",
  34. "Upgrade-Insecure-Requests: 1",
  35. "Sec-Fetch-Dest: document",
  36. "Sec-Fetch-Mode: navigate",
  37. "Sec-Fetch-Site: cross-site",
  38. "Upgrade-Insecure-Requests: 1"];
  39. curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
  40. curl_setopt($curlproc, CURLOPT_HTTPHEADER, $headers);
  41. curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
  42. curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
  43. curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
  44. curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
  45. curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
  46. $data = curl_exec($curlproc);
  47. if(curl_errno($curlproc)){
  48. throw new Exception(curl_error($curlproc));
  49. }
  50. curl_close($curlproc);
  51. return $data;
  52. }
  53. public function getfilters($pagetype){
  54. switch($pagetype){
  55. case "images":
  56. return
  57. [
  58. "nsfw" => [
  59. "display" => "NSFW",
  60. "option" => [
  61. "yes" => "Yes",
  62. "maybe" => "Maybe",
  63. "no" => "No"
  64. ]
  65. ],
  66. "time" => [
  67. "display" => "Time posted",
  68. "option" => [
  69. "any" => "Any time",
  70. "week" => "Last week"
  71. ]
  72. ],
  73. "size" => [
  74. "display" => "Size",
  75. "option" => [
  76. "any" => "Any size",
  77. "small" => "Small",
  78. "medium" => "Medium",
  79. "large" => "Large",
  80. "wallpaper" => "Wallpaper"
  81. ]
  82. ],
  83. "color" => [
  84. "display" => "Colors",
  85. "option" => [
  86. "any" => "All colors",
  87. "color" => "Color images only",
  88. "gray" => "Black and white",
  89. "red" => "Red",
  90. "orange" => "Orange",
  91. "yellow" => "Yellow",
  92. "cyan" => "Cyan",
  93. "green" => "Green",
  94. "blue" => "Blue",
  95. "violet" => "Purple",
  96. "white" => "White",
  97. "black" => "Black"
  98. ]
  99. ],
  100. "type" => [
  101. "display" => "Type",
  102. "option" => [
  103. "any" => "All types",
  104. "photo" => "Photos",
  105. "clipart" => "White background",
  106. "lineart" => "Drawings and sketches",
  107. "face" => "People",
  108. "demotivator" => "Demotivators"
  109. ]
  110. ],
  111. "layout" => [
  112. "display" => "Layout",
  113. "option" => [
  114. "any" => "All layouts",
  115. "horizontal" => "Horizontal",
  116. "vertical" => "Vertical",
  117. "square" => "Square"
  118. ]
  119. ],
  120. "format" => [
  121. "display" => "Format",
  122. "option" => [
  123. "any" => "Any format",
  124. "jpeg" => "JPEG",
  125. "png" => "PNG",
  126. "gif" => "GIF"
  127. ]
  128. ]
  129. ];
  130. break;
  131. default:
  132. return [];
  133. break;
  134. }
  135. }
  136. public function image($get){
  137. if($get["npt"]){
  138. $request =
  139. json_decode(
  140. $this->nextpage->get(
  141. $get["npt"],
  142. "images"
  143. ),
  144. true
  145. );
  146. $nsfw = $request["nsfw"];
  147. unset($request["nsfw"]);
  148. }else{
  149. $search = $get["s"];
  150. if(strlen($search) === 0){
  151. throw new Exception("Search term is empty!");
  152. }
  153. $nsfw = $get["nsfw"];
  154. $time = $get["time"];
  155. $size = $get["size"];
  156. $color = $get["color"];
  157. $type = $get["type"];
  158. $layout = $get["layout"];
  159. $format = $get["format"];
  160. /*
  161. $handle = fopen("scraper/yandex.json", "r");
  162. $json = fread($handle, filesize("scraper/yandex.json"));
  163. fclose($handle);*/
  164. // SIZE
  165. // large
  166. // 227.0=1;203.0=1;76fe94.0=1;41d251.0=1;75.0=1;371.0=1;291.0=1;307.0=1;f797ee.0=1;1cf7c2.0=1;deca32.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&isize=large&suggest_reqid=486139416166165501540886508227485&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  167. // medium
  168. // 227.0=1;203.0=1;76fe94.0=1;41d251.0=1;75.0=1;371.0=1;291.0=1;307.0=1;f797ee.0=1;1cf7c2.0=1;deca32.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&isize=medium&suggest_reqid=486139416166165501540886508227485&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  169. // small
  170. // 227.0=1;203.0=1;76fe94.0=1;41d251.0=1;75.0=1;371.0=1;291.0=1;307.0=1;f797ee.0=1;1cf7c2.0=1;deca32.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&isize=small&suggest_reqid=486139416166165501540886508227485&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  171. // ORIENTATION
  172. // Horizontal
  173. // 227.0=1;203.0=1;76fe94.0=1;41d251.0=1;75.0=1;371.0=1;291.0=1;307.0=1;f797ee.0=1;1cf7c2.0=1;deca32.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&iorient=horizontal&suggest_reqid=486139416166165501540886508227485&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  174. // Vertical
  175. // 227.0=1;203.0=1;76fe94.0=1;41d251.0=1;75.0=1;371.0=1;291.0=1;307.0=1;f797ee.0=1;1cf7c2.0=1;deca32.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&iorient=vertical&suggest_reqid=486139416166165501540886508227485&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  176. // Square
  177. // 227.0=1;203.0=1;76fe94.0=1;41d251.0=1;75.0=1;371.0=1;291.0=1;307.0=1;f797ee.0=1;1cf7c2.0=1;deca32.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&iorient=square&suggest_reqid=486139416166165501540886508227485&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  178. // TYPE
  179. // Photos
  180. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&text=minecraft&type=photo&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  181. // White background
  182. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&text=minecraft&type=clipart&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  183. // Drawings and sketches
  184. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&text=minecraft&type=lineart&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  185. // People
  186. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&text=minecraft&type=face&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  187. // Demotivators
  188. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&text=minecraft&type=demotivator&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  189. // COLOR
  190. // Color images only
  191. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=color&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  192. // Black and white
  193. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=gray&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  194. // Red
  195. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=red&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  196. // Orange
  197. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=orange&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  198. // Yellow
  199. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=yellow&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  200. // Cyan
  201. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=cyan&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  202. // Green
  203. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=green&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  204. // Blue
  205. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=blue&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  206. // Purple
  207. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=violet&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  208. // White
  209. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=white&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  210. // Black
  211. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&icolor=black&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  212. // FORMAT
  213. // jpeg
  214. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&itype=jpg&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  215. // png
  216. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&itype=png&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  217. // gif
  218. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&itype=gifan&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  219. // RECENT
  220. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&recent=7D&text=minecraft&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  221. // WALLPAPER
  222. // 307.0=1;371.0=1;291.0=1;203.0=1;deca32.0=1;f797ee.0=1;1cf7c2.0=1;41d251.0=1;267.0=1;bde197.0=1"},"extraContent":{"names":["i-react-ajax-adapter"]}}}&yu=4861394161661655015&isize=wallpaper&text=minecraft&wp=wh16x9_1920x1080&uinfo=sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080
  223. $request = [
  224. "format" => "json",
  225. "request" => [
  226. "blocks" => [
  227. [
  228. "block" => "extra-content",
  229. "params" => (object)[],
  230. "version" => 2
  231. ],
  232. [
  233. "block" => "i-global__params:ajax",
  234. "params" => (object)[],
  235. "version" => 2
  236. ],
  237. [
  238. "block" => "search2:ajax",
  239. "params" => (object)[],
  240. "version" => 2
  241. ],
  242. [
  243. "block" => "preview__isWallpaper",
  244. "params" => (object)[],
  245. "version" => 2
  246. ],
  247. [
  248. "block" => "content_type_search",
  249. "params" => (object)[],
  250. "version" => 2
  251. ],
  252. [
  253. "block" => "serp-controller",
  254. "params" => (object)[],
  255. "version" => 2
  256. ],
  257. [
  258. "block" => "cookies_ajax",
  259. "params" => (object)[],
  260. "version" => 2
  261. ],
  262. [
  263. "block" => "advanced-search-block",
  264. "params" => (object)[],
  265. "version" => 2
  266. ]
  267. ],
  268. "metadata" => [
  269. "bundles" => [
  270. "lb" => "AS?(E<X120"
  271. ],
  272. "assets" => [
  273. // las base
  274. "las" => "justifier-height=1;justifier-setheight=1;fitimages-height=1;justifier-fitincuts=1;react-with-dom=1;"
  275. // las default
  276. //"las" => "justifier-height=1;justifier-setheight=1;fitimages-height=1;justifier-fitincuts=1;react-with-dom=1;227.0=1;203.0=1;76fe94.0=1;215f96.0=1;75.0=1"
  277. ],
  278. "extraContent" => [
  279. "names" => [
  280. "i-react-ajax-adapter"
  281. ]
  282. ]
  283. ]
  284. ]
  285. ];
  286. /*
  287. Apply filters
  288. */
  289. if($time == "week"){
  290. $request["recent"] = "7D";
  291. }
  292. if($size != "any"){
  293. $request["isize"] = $size;
  294. }
  295. if($type != "any"){
  296. $request["type"] = $type;
  297. }
  298. if($color != "any"){
  299. $request["icolor"] = $color;
  300. }
  301. if($layout != "any"){
  302. $request["iorient"] = $layout;
  303. }
  304. if($format != "any"){
  305. $request["itype"] = $format;
  306. }
  307. $request["text"] = $search;
  308. $request["uinfo"] = "sw-1920-sh-1080-ww-1125-wh-999-pd-1-wp-16x9_1920x1080";
  309. $request["request"] = json_encode($request["request"]);
  310. }
  311. try{
  312. $json = $this->get(
  313. "https://yandex.com/images/search",
  314. $request,
  315. $nsfw
  316. );
  317. }catch(Exception $err){
  318. throw new Exception("Failed to get JSON");
  319. }
  320. /*
  321. $handle = fopen("scraper/yandex.json", "r");
  322. $json = fread($handle, filesize("scraper/yandex.json"));
  323. fclose($handle);*/
  324. $json = json_decode($json, true);
  325. if(
  326. isset($json["type"]) &&
  327. $json["type"] == "captcha"
  328. ){
  329. throw new Exception("Yandex blocked this 4get instance. Yandex blocks don't last very long, but the block timer gets reset everytime you make another unsuccessful request. Please try again in ~7 minutes.");
  330. }
  331. if($json === null){
  332. throw new Exception("Failed to decode JSON");
  333. }
  334. // get html
  335. $html = "";
  336. foreach($json["blocks"] as $block){
  337. $html .= $block["html"];
  338. }
  339. $this->fuckhtml->load($html);
  340. $div = $this->fuckhtml->getElementsByTagName("div");
  341. $out = [
  342. "status" => "ok",
  343. "npt" => null,
  344. "image" => []
  345. ];
  346. // check for next page
  347. if(
  348. count(
  349. $this->fuckhtml
  350. ->getElementsByClassName(
  351. "more more_direction_next",
  352. $div
  353. )
  354. ) !== 0
  355. ){
  356. $request["nsfw"] = $nsfw;
  357. if(isset($request["p"])){
  358. $request["p"]++;
  359. }else{
  360. $request["p"] = 1;
  361. }
  362. $out["npt"] = $this->nextpage->store(json_encode($request), "images");
  363. }
  364. // get search results
  365. foreach(
  366. $this->fuckhtml
  367. ->getElementsByClassName(
  368. "serp-item serp-item_type_search",
  369. $div
  370. )
  371. as $image
  372. ){
  373. $image =
  374. json_decode(
  375. $image
  376. ["attributes"]
  377. ["data-bem"],
  378. true
  379. )["serp-item"];
  380. $title = [html_entity_decode($image["snippet"]["title"], ENT_QUOTES | ENT_HTML5)];
  381. if(isset($image["snippet"]["text"])){
  382. $title[] = html_entity_decode($image["snippet"]["text"], ENT_QUOTES | ENT_HTML5);
  383. }
  384. $tmp = [
  385. "title" =>
  386. $this->fuckhtml
  387. ->getTextContent(
  388. $this->titledots(
  389. implode(": ", $title)
  390. )
  391. ),
  392. "source" => [],
  393. "url" => htmlspecialchars_decode($image["snippet"]["url"])
  394. ];
  395. foreach($image["dups"] as $dup){
  396. $tmp["source"][] = [
  397. "url" => htmlspecialchars_decode($dup["url"]),
  398. "width" => (int)$dup["w"],
  399. "height" => (int)$dup["h"],
  400. ];
  401. }
  402. $tmp["source"][] = [
  403. "url" =>
  404. preg_replace(
  405. '/^\/\//',
  406. "https://",
  407. htmlspecialchars_decode($image["thumb"]["url"])
  408. ),
  409. "width" => (int)$image["thumb"]["size"]["width"],
  410. "height" => (int)$image["thumb"]["size"]["height"]
  411. ];
  412. $out["image"][] = $tmp;
  413. }
  414. return $out;
  415. }
  416. private function titledots($title){
  417. $substr = substr($title, -3);
  418. if(
  419. $substr == "..." ||
  420. $substr == "…"
  421. ){
  422. return trim(substr($title, 0, -3));
  423. }
  424. return trim($title);
  425. }
  426. }