BilibiliFavList.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <?php
  2. namespace Sakura\API;
  3. class BilibiliFavList
  4. {
  5. private $uid;
  6. private $headers;
  7. public function __construct()
  8. {
  9. $this->uid = iro_opt('bilibili_id');
  10. $this->headers = array(
  11. 'Host' => 'api.bilibili.com',
  12. 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97',
  13. "Cookie" => iro_opt('bilibili_cookie')
  14. );
  15. }
  16. function fetch_folder_api()
  17. {
  18. $uid = $this->uid;
  19. $url = "https://api.bilibili.com/x/v3/fav/folder/created/list-all?up_mid=$uid&jsonp=jsonp";
  20. $args = array(
  21. 'headers' => $this->headers
  22. );
  23. $response = wp_remote_get($url, $args);
  24. if (is_array($response)) {
  25. $result = json_decode($response["body"], true);
  26. if ($result) {
  27. return $result;
  28. }
  29. }
  30. error_log("BilibiliFavList: fetch_folder_api failed, response dump:" . var_export($response, true));
  31. return false;
  32. }
  33. function fetch_folder_item_api(int $folder_id, int $page)
  34. {
  35. $url = "https://api.bilibili.com/x/v3/fav/resource/list?media_id=$folder_id&pn=$page&ps=9&platform=web&jsonp=jsonp";
  36. $args = array(
  37. 'headers' => $this->headers
  38. );
  39. $response = wp_remote_get($url, $args);
  40. if (is_array($response)) {
  41. $result = json_decode($response["body"], true);
  42. if ($result) {
  43. return $result;
  44. }
  45. }
  46. return false;
  47. }
  48. public function get_folders()
  49. {
  50. $resp = $this->fetch_folder_api();
  51. if ($resp === false) {
  52. return "<div>" . __('Backend error', 'sakurairo') . "</div>";
  53. }
  54. $folders_data = $resp['data'];
  55. if ($folders_data === null) {
  56. error_log("BilibiliFavList: no data fetched. Try apply cookie.");
  57. return "<div>" . __('Backend error', 'sakurairo') . "</div>";
  58. }
  59. $folders = $folders_data['list'];
  60. $html = '';
  61. foreach ((array)$folders as $folder) {
  62. $render_result = $this->folder_display($folder['id']);
  63. if ($render_result) {
  64. $html .= $render_result;
  65. } else {
  66. error_log("BilibiliFavList: folder_display failed, folder_id: " . $folder['id']);
  67. $html .= '<div class="folder"><div class="folder-top">'
  68. . '<div class="folder-detail"><h3>' . $folder['title'] . '</h3>'
  69. . __('Backend error', 'sakurairo') . "</div></div></div>";
  70. }
  71. }
  72. return $html;
  73. }
  74. public function folder_display(int $folder_id)
  75. {
  76. $folder_resp = $this->fetch_folder_item_api($folder_id, 1);
  77. if (!$folder_resp) {
  78. return false;
  79. }
  80. $folder_content_info = $folder_resp['data']['info'];
  81. $html = '<div class="folder"><div class="folder-top">' .
  82. lazyload_img(str_replace('http://', 'https://', $folder_content_info['cover']), 'folder-img', array('alt' => $folder_content_info['title'])) .
  83. '<div class="folder-detail"><h3>' . $folder_content_info['title'] . '</h3>' .
  84. '<p>' . __('Item count: ', 'sakurairo') . $folder_content_info['media_count'] . '</p>' .
  85. '<button class="expand-button">' . __('Expand', 'sakurairo') . '</button></div></div>' .
  86. '<hr><div class="folder-content">';
  87. $load = BilibiliFavList::load_more(rest_url('sakura/v1/favlist/bilibili') . '?page=1' . '&folder_id=' . $folder_id);
  88. return $html . $load . '</div></div></br>';
  89. }
  90. public function load_folder_items(int $folder_id, $page = 1)
  91. {
  92. $folder_resp = $this->fetch_folder_item_api($folder_id, $page);
  93. $folder_content = $folder_resp['data']['medias'];
  94. $html = '';
  95. foreach ((array)$folder_content as $item) {
  96. $html .= BilibiliFavList::folder_item_display($item);
  97. }
  98. if ($folder_resp['data']['has_more']) {
  99. $load = BilibiliFavList::load_more(rest_url('sakura/v1/favlist/bilibili') . '?page=' . ++$page . '&folder_id=' . $folder_id);
  100. } else {
  101. $load = '<a class="load-more"><i class="fa-solid fa-ban"></i>' . __('All item has been loaded.', 'sakurairo') . '</a>';
  102. }
  103. return $html . $load;
  104. }
  105. private static function folder_item_display(array $item)
  106. {
  107. if ($item['type'] == 24) {
  108. $link = $item['link'];
  109. } else {
  110. $link = "https://www.bilibili.com/video/" . $item['bvid'];
  111. }
  112. // TODO: add lazyload to item-image with typescript
  113. return '<div class="column"><a class="folder-item" href="' . $link . '" target="_blank" rel="nofollow">' .
  114. '<img class="item-image" src="' . $item['cover'] . '">' .
  115. '<div class="item-info"><h3 class="item-title" title="' . $item['title'] . '">' . $item['title'] . '</h3>' .
  116. '<div class="item-intro" title="' . $item['intro'] . '">' . $item['intro'] . '</div>' .
  117. '</div></a></div>';
  118. }
  119. private static function load_more($href)
  120. {
  121. return '<a class="load-more" data-href="' . $href . '"><i class="fa-solid fa-bolt-lightning"></i>' . __('Load More', 'sakurairo') . '</a>';
  122. }
  123. }