BilibiliAPI

BilibiliAPI,PC端抓包研究所得

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/38140/736466/BilibiliAPI.js

  1. // ==UserScript==
  2. // @name BilibiliAPI
  3. // @namespace SeaLoong
  4. // @version 1.4.6
  5. // @description BilibiliAPI,PC端抓包研究所得
  6. // @author SeaLoong
  7. // @require http://code.jquery.com/jquery-3.3.1.min.js
  8. // @grant none
  9. // @license MIT License
  10. // ==/UserScript==
  11.  
  12. let csrf_token, visit_id;
  13.  
  14. var BilibiliAPI = {
  15. setCommonArgs: (csrfToken = '', visitId = '') => {
  16. csrf_token = csrfToken;
  17. visit_id = visitId;
  18. },
  19. // 整合常用API
  20. TreasureBox: {
  21. getAward: (time_start, end_time, captcha) => BilibiliAPI.lottery.SilverBox.getAward(time_start, end_time, captcha),
  22. getCaptcha: (ts) => BilibiliAPI.lottery.SilverBox.getCaptcha(ts),
  23. getCurrentTask: () => BilibiliAPI.lottery.SilverBox.getCurrentTask()
  24. },
  25. Exchange: {
  26. coin2silver: (num, platform) => BilibiliAPI.pay.coin2silver(num, platform),
  27. silver2coin: (platform) => BilibiliAPI.pay.silver2coin(platform),
  28. old: {
  29. coin2silver: (coin) => BilibiliAPI.exchange.coin2silver(coin),
  30. silver2coin: () => BilibiliAPI.exchange.silver2coin()
  31. }
  32. },
  33. Lottery: {
  34. Gift: {
  35. check: (roomid) => BilibiliAPI.xlive.smalltv.check(roomid),
  36. join: (roomid, raffleId, type) => BilibiliAPI.xlive.smalltv.join(roomid, raffleId, type),
  37. notice: (raffleId, type) => BilibiliAPI.xlive.smalltv.notice(raffleId, type)
  38. },
  39. Raffle: {
  40. check: (roomid) => BilibiliAPI.activity.check(roomid),
  41. join: (roomid, raffleId) => BilibiliAPI.activity.join(roomid, raffleId),
  42. notice: (roomid, raffleId) => BilibiliAPI.activity.notice(roomid, raffleId)
  43. },
  44. MaterialObject: {
  45. getRoomActivityByRoomid: (roomid) => BilibiliAPI.lottery.box.getRoomActivityByRoomid(roomid),
  46. getStatus: (aid, times) => BilibiliAPI.lottery.box.getStatus(aid, times),
  47. draw: (aid, number) => BilibiliAPI.lottery.box.draw(aid, number),
  48. getWinnerGroupInfo: (aid, number) => BilibiliAPI.lottery.box.getWinnerGroupInfo(aid, number)
  49. },
  50. Guard: {
  51. check: (roomid) => BilibiliAPI.lottery.lottery.check_guard(roomid),
  52. join: (roomid, id, type) => BilibiliAPI.xlive.guard.join(roomid, id, type)
  53. },
  54. Pk: {
  55. check: (roomid) => BilibiliAPI.xlive.pk.check(roomid),
  56. join: (roomid, id) => BilibiliAPI.xlive.pk.join(roomid, id)
  57. }
  58. },
  59. Group: {
  60. my_groups: () => BilibiliAPI.link_group.my_groups(),
  61. sign_in: (group_id, owner_id) => BilibiliAPI.link_group.sign_in(group_id, owner_id)
  62. },
  63. Storm: {
  64. check: (roomid) => BilibiliAPI.lottery.Storm.check(roomid),
  65. join: (id, captcha_token, captcha_phrase, roomid, color) => BilibiliAPI.lottery.Storm.join(id, captcha_token, captcha_phrase, roomid, color)
  66. },
  67. HeartBeat: {
  68. web: () => BilibiliAPI.user.userOnlineHeart(),
  69. mobile: () => BilibiliAPI.mobile.userOnlineHeart()
  70. },
  71. DailyReward: {
  72. task: () => BilibiliAPI.home.reward(), // CORS
  73. exp: () => BilibiliAPI.exp(),
  74. login: () => BilibiliAPI.x.now(),
  75. watch: (aid, cid, mid, start_ts, played_time, realtime, type, play_type, dt) => BilibiliAPI.x.heartbeat(aid, cid, mid, start_ts, played_time, realtime, type, play_type, dt),
  76. coin: (aid, multiply) => BilibiliAPI.x.coin_add(aid, multiply),
  77. share: (aid) => BilibiliAPI.x.share_add(aid)
  78. },
  79. // ajax调用B站API
  80. runUntilSucceed: (callback, delay = 0, period = 50) => {
  81. setTimeout(() => {
  82. if (!callback()) BilibiliAPI.runUntilSucceed(callback, period, period);
  83. }, delay);
  84. },
  85. processing: 0,
  86. ajax: (settings) => {
  87. if (settings.xhrFields === undefined) settings.xhrFields = {};
  88. settings.xhrFields.withCredentials = true;
  89. jQuery.extend(settings, {
  90. url: (settings.url.substr(0, 2) === '//' ? '' : '//api.live.bilibili.com/') + settings.url,
  91. method: settings.method || 'GET',
  92. crossDomain: true,
  93. dataType: settings.dataType || 'json'
  94. });
  95. const p = jQuery.Deferred();
  96. BilibiliAPI.runUntilSucceed(() => {
  97. if (BilibiliAPI.processing > 8) return false;
  98. ++BilibiliAPI.processing;
  99. return jQuery.ajax(settings).then((arg1, arg2, arg3) => {
  100. --BilibiliAPI.processing;
  101. p.resolve(arg1, arg2, arg3);
  102. return true;
  103. }, (arg1, arg2, arg3) => {
  104. --BilibiliAPI.processing;
  105. p.reject(arg1, arg2, arg3);
  106. return true;
  107. });
  108. });
  109. return p;
  110. },
  111. ajaxWithCommonArgs: (settings) => {
  112. if (!settings.data) settings.data = {};
  113. settings.data.csrf = csrf_token;
  114. settings.data.csrf_token = csrf_token;
  115. settings.data.visit_id = visit_id;
  116. return BilibiliAPI.ajax(settings);
  117. },
  118. // 以下按照URL分类
  119. ajaxGetCaptchaKey: () => {
  120. return BilibiliAPI.ajax({
  121. url: '//www.bilibili.com/plus/widget/ajaxGetCaptchaKey.php?js'
  122. });
  123. },
  124. exp: () => {
  125. // 获取今日已获得的投币经验?
  126. return BilibiliAPI.ajax({
  127. url: '//www.bilibili.com/plus/account/exp.php'
  128. });
  129. },
  130. msg: (roomid) => {
  131. return BilibiliAPI.ajaxWithCommonArgs({
  132. method: 'POST',
  133. url: 'ajax/msg',
  134. data: {
  135. roomid: roomid
  136. }
  137. });
  138. },
  139. ajaxCapsule: () => {
  140. return BilibiliAPI.ajax({
  141. url: 'api/ajaxCapsule'
  142. });
  143. },
  144. player: (id, ts, platform = 'pc', player_type = 'web') => {
  145. return BilibiliAPI.ajax({
  146. url: 'api/player',
  147. data: {
  148. id: typeof id === 'string' && id.substr(0, 4) === 'cid:' ? id : 'cid:' + id, // cid:{room_id}
  149. ts: typeof ts === 'string' ? ts : ts.toString(16), // HEX
  150. platform: platform,
  151. player_type: player_type
  152. },
  153. dataType: 'text'
  154. });
  155. },
  156. create: (width, height) => {
  157. // 生成一个验证码(用于节奏风暴)
  158. return BilibiliAPI.ajax({
  159. url: 'captcha/v1/Captcha/create',
  160. data: {
  161. width: width || '112',
  162. height: height || '32'
  163. },
  164. cache: false
  165. });
  166. },
  167. topList: (roomid, page, ruid) => {
  168. return BilibiliAPI.ajax({
  169. url: 'guard/topList',
  170. data: {
  171. roomid: roomid,
  172. page: page,
  173. ruid: ruid
  174. }
  175. });
  176. },
  177. getSuser: () => {
  178. return BilibiliAPI.ajax({
  179. url: 'msg/getSuser'
  180. });
  181. },
  182. refresh: (area = 'all') => {
  183. return BilibiliAPI.ajax({
  184. url: 'index/refresh?area=' + area
  185. });
  186. },
  187. get_ip_addr: () => {
  188. return BilibiliAPI.ajax({
  189. url: 'ip_service/v1/ip_service/get_ip_addr'
  190. });
  191. },
  192. getuserinfo: () => {
  193. return BilibiliAPI.ajax({
  194. url: 'user/getuserinfo'
  195. });
  196. },
  197. activity: {
  198. mobileActivity: () => {
  199. return BilibiliAPI.ajax({
  200. url: 'activity/v1/Common/mobileActivity'
  201. });
  202. },
  203. mobileRoomInfo: (roomid) => {
  204. return BilibiliAPI.ajax({
  205. url: 'activity/v1/Common/mobileRoomInfo',
  206. data: {
  207. roomid: roomid
  208. }
  209. });
  210. },
  211. roomInfo: (roomid, ruid, area_v2_id, area_v2_parent_id) => {
  212. return BilibiliAPI.ajax({
  213. url: 'activity/v1/Common/roomInfo',
  214. data: {
  215. roomid: roomid,
  216. ruid: ruid,
  217. area_v2_id: area_v2_id,
  218. area_v2_parent_id: area_v2_parent_id
  219. }
  220. });
  221. },
  222. welcomeInfo: (roomid, ruid) => {
  223. return BilibiliAPI.ajax({
  224. url: 'activity/v1/Common/welcomeInfo',
  225. data: {
  226. roomid: roomid,
  227. ruid: ruid
  228. }
  229. });
  230. },
  231. check: (roomid) => {
  232. // 检查是否有活动抽奖
  233. return BilibiliAPI.ajax({
  234. url: 'activity/v1/Raffle/check?roomid=' + roomid
  235. });
  236. },
  237. join: (roomid, raffleId) => {
  238. // 参加活动抽奖
  239. return BilibiliAPI.ajax({
  240. url: 'activity/v1/Raffle/join',
  241. data: {
  242. roomid: roomid,
  243. raffleId: raffleId
  244. }
  245. });
  246. },
  247. notice: (roomid, raffleId) => {
  248. // 领取活动抽奖奖励
  249. return BilibiliAPI.ajax({
  250. url: 'activity/v1/Raffle/notice',
  251. data: {
  252. roomid: roomid,
  253. raffleId: raffleId
  254. }
  255. });
  256. },
  257. receive_award: (task_id) => {
  258. // 领取任务奖励
  259. return BilibiliAPI.ajaxWithCommonArgs({
  260. method: 'POST',
  261. url: 'activity/v1/task/receive_award',
  262. data: {
  263. task_id: task_id
  264. }
  265. });
  266. }
  267. },
  268. av: {
  269. getTimestamp: (platform = 'pc') => {
  270. return BilibiliAPI.ajaxWithCommonArgs({
  271. method: 'POST',
  272. url: 'av/v1/Time/getTimestamp',
  273. data: {
  274. platform: platform
  275. }
  276. });
  277. }
  278. },
  279. dynamic_svr: {
  280. dynamic_new: (uid, type = 8) => {
  281. // 获取动态
  282. return BilibiliAPI.ajax({
  283. url: 'dynamic_svr/v1/dynamic_svr/dynamic_new',
  284. data: {
  285. uid: uid,
  286. type: type // 8: 投稿视频; 268435455: 全部
  287. }
  288. });
  289. }
  290. },
  291. exchange: {
  292. coin2silver: (coin) => {
  293. // 硬币兑换银瓜子(旧API),1硬币=900银瓜子
  294. return BilibiliAPI.ajax({
  295. method: 'POST',
  296. url: 'exchange/coin2silver',
  297. data: {
  298. coin: coin
  299. }
  300. });
  301. },
  302. silver2coin: () => {
  303. // 银瓜子兑换硬币(旧API),1400银瓜子=1硬币
  304. return BilibiliAPI.ajax({
  305. type: 'GET',
  306. url: 'exchange/silver2coin'
  307. });
  308. }
  309. },
  310. fans_medal: {
  311. get_fans_medal_info: (uid, target_id, source = 1) => {
  312. return BilibiliAPI.ajaxWithCommonArgs({
  313. method: 'POST',
  314. url: 'fans_medal/v1/fans_medal/get_fans_medal_info',
  315. data: {
  316. source: source,
  317. uid: uid,
  318. target_id: target_id
  319. }
  320. });
  321. }
  322. },
  323. feed_svr: {
  324. notice: () => {
  325. return BilibiliAPI.ajaxWithCommonArgs({
  326. method: 'POST',
  327. url: 'feed_svr/v1/feed_svr/notice',
  328. data: {}
  329. });
  330. },
  331. my: (page_size, live_status = 0, type = 0, offset = 0) => {
  332. return BilibiliAPI.ajaxWithCommonArgs({
  333. method: 'POST',
  334. url: 'feed_svr/v1/feed_svr/my',
  335. data: {
  336. live_status: live_status,
  337. type: type,
  338. page_size: page_size,
  339. offset: offset
  340. }
  341. });
  342. }
  343. },
  344. gift: {
  345. bag_list: () => {
  346. // 获取包裹礼物列表
  347. return BilibiliAPI.ajax({
  348. url: 'gift/v2/gift/bag_list'
  349. });
  350. },
  351. send: (uid, gift_id, ruid, gift_num, biz_id, rnd, coin_type = 'silver', platform = 'pc', biz_code = 'live', storm_beat_id = 0, price = 0) => {
  352. // 消耗瓜子送礼
  353. return BilibiliAPI.ajaxWithCommonArgs({
  354. method: 'POST',
  355. url: 'gift/v2/gift/send',
  356. data: {
  357. uid: uid,
  358. gift_id: gift_id,
  359. ruid: ruid,
  360. gift_num: gift_num,
  361. coin_type: coin_type,
  362. bag_id: 0,
  363. platform: platform,
  364. biz_code: biz_code,
  365. biz_id: biz_id, // roomid
  366. rnd: rnd,
  367. storm_beat_id: storm_beat_id,
  368. metadata: '',
  369. price: price
  370. }
  371. });
  372. },
  373. bag_send: (uid, gift_id, ruid, gift_num, bag_id, biz_id, rnd, platform = 'pc', biz_code = 'live', storm_beat_id = 0, price = 0) => {
  374. // 送出包裹中的礼物
  375. return BilibiliAPI.ajaxWithCommonArgs({
  376. method: 'POST',
  377. url: 'gift/v2/live/bag_send',
  378. data: {
  379. uid: uid,
  380. gift_id: gift_id,
  381. ruid: ruid,
  382. gift_num: gift_num,
  383. bag_id: bag_id,
  384. platform: platform,
  385. biz_code: biz_code,
  386. biz_id: biz_id, // roomid
  387. rnd: rnd,
  388. storm_beat_id: storm_beat_id,
  389. metadata: '',
  390. price: price
  391. }
  392. });
  393. },
  394. gift_config: () => {
  395. return BilibiliAPI.ajax({
  396. url: 'gift/v3/live/gift_config'
  397. });
  398. },
  399. heart_gift_receive: (roomid, area_v2_id) => {
  400. return BilibiliAPI.ajax({
  401. url: 'gift/v2/live/heart_gift_receive',
  402. data: {
  403. roomid: roomid,
  404. area_v2_id: area_v2_id
  405. }
  406. });
  407. },
  408. heart_gift_status: (roomid, area_v2_id) => {
  409. return BilibiliAPI.ajax({
  410. url: 'gift/v2/live/heart_gift_status',
  411. data: {
  412. roomid: roomid,
  413. area_v2_id: area_v2_id
  414. }
  415. });
  416. },
  417. receive_daily_bag: () => {
  418. // 领取每日礼物
  419. return BilibiliAPI.ajax({
  420. url: 'gift/v2/live/receive_daily_bag'
  421. });
  422. },
  423. room_gift_list: (roomid, area_v2_id) => {
  424. return BilibiliAPI.ajax({
  425. url: 'gift/v2/live/room_gift_list',
  426. data: {
  427. roomid: roomid,
  428. area_v2_id: area_v2_id
  429. }
  430. });
  431. },
  432. smalltv: {
  433. // 礼物抽奖
  434. check: (roomid) => {
  435. return BilibiliAPI.ajax({
  436. url: 'gift/v3/smalltv/check',
  437. data: {
  438. roomid: roomid
  439. }
  440. });
  441. },
  442. join: (roomid, raffleId, type = 'Gift') => {
  443. return BilibiliAPI.ajaxWithCommonArgs({
  444. method: 'POST',
  445. url: 'gift/v3/smalltv/join',
  446. data: {
  447. roomid: roomid,
  448. raffleId: raffleId,
  449. type: type
  450. }
  451. });
  452. },
  453. notice: (raffleId, type = 'small_tv') => {
  454. return BilibiliAPI.ajax({
  455. url: 'gift/v3/smalltv/notice',
  456. data: {
  457. type: type,
  458. raffleId: raffleId
  459. }
  460. });
  461. }
  462. }
  463. },
  464. giftBag: {
  465. getSendGift: () => {
  466. return BilibiliAPI.ajax({
  467. url: 'giftBag/getSendGift'
  468. });
  469. },
  470. sendDaily: () => {
  471. return BilibiliAPI.ajax({
  472. url: 'giftBag/sendDaily'
  473. });
  474. }
  475. },
  476. home: {
  477. reward: () => {
  478. // 获取每日奖励情况
  479. return BilibiliAPI.ajax({
  480. url: '//account.bilibili.com/home/reward'
  481. });
  482. }
  483. },
  484. i: {
  485. ajaxCancelWear: () => {
  486. // 取消佩戴勋章
  487. return BilibiliAPI.ajax({
  488. url: 'i/ajaxCancelWear'
  489. });
  490. },
  491. ajaxGetAchieve: (keywords, page, pageSize = 6, type = 'normal', status = 0, category = 'all') => {
  492. return BilibiliAPI.ajax({
  493. url: 'i/api/ajaxGetAchieve',
  494. data: {
  495. type: type, // 'legend'
  496. status: status,
  497. category: category,
  498. keywords: keywords,
  499. page: page,
  500. pageSize: pageSize
  501. }
  502. });
  503. },
  504. ajaxGetMyMedalList: () => {
  505. // 勋章列表
  506. return BilibiliAPI.ajax({
  507. url: 'i/ajaxGetMyMedalList'
  508. });
  509. },
  510. ajaxWearFansMedal: (medal_id) => {
  511. // 佩戴勋章/更换当前佩戴的勋章
  512. return BilibiliAPI.ajax({
  513. url: 'i/ajaxWearFansMedal?medal_id=' + medal_id
  514. });
  515. },
  516. following: (page = 1, pageSize = 9) => {
  517. return BilibiliAPI.ajax({
  518. url: 'i/api/following',
  519. data: {
  520. page: page,
  521. pageSize: pageSize
  522. }
  523. });
  524. },
  525. guard: (page, pageSize = 10) => {
  526. return BilibiliAPI.ajax({
  527. url: 'i/api/guard',
  528. data: {
  529. page: page,
  530. pageSize: pageSize
  531. }
  532. });
  533. },
  534. liveinfo: () => {
  535. return BilibiliAPI.ajax({
  536. url: 'i/api/liveinfo'
  537. });
  538. },
  539. medal: (page = 1, pageSize = 10) => {
  540. // 获取勋章列表信息
  541. return BilibiliAPI.ajax({
  542. url: 'i/api/medal',
  543. data: {
  544. page: page,
  545. pageSize: pageSize
  546. }
  547. });
  548. },
  549. operation: (page = 1) => {
  550. return BilibiliAPI.ajax({
  551. url: 'i/api/operation?page=' + page
  552. });
  553. },
  554. taskInfo: () => {
  555. return BilibiliAPI.ajax({
  556. url: 'i/api/taskInfo'
  557. });
  558. }
  559. },
  560. link_group: {
  561. my_groups: () => {
  562. // 应援团列表
  563. return BilibiliAPI.ajax({
  564. url: 'link_group/v1/member/my_groups'
  565. });
  566. },
  567. sign_in: (group_id, owner_id) => {
  568. // 应援团签到
  569. return BilibiliAPI.ajax({
  570. url: 'link_setting/v1/link_setting/sign_in',
  571. data: {
  572. group_id: group_id,
  573. owner_id: owner_id
  574. }
  575. });
  576. }
  577. },
  578. live: {
  579. getRoomKanBanModel: (roomid) => {
  580. return BilibiliAPI.ajax({
  581. url: 'live/getRoomKanBanModel?roomid' + roomid
  582. });
  583. },
  584. rankTab: (roomid) => {
  585. return BilibiliAPI.ajax({
  586. url: 'live/rankTab?roomid=' + roomid
  587. });
  588. },
  589. roomAdList: () => {
  590. return BilibiliAPI.ajax({
  591. url: 'live/roomAdList'
  592. });
  593. }
  594. },
  595. live_user: {
  596. get_anchor_in_room: (roomid) => {
  597. return BilibiliAPI.ajax({
  598. url: 'live_user/v1/UserInfo/get_anchor_in_room?roomid=' + roomid
  599. });
  600. },
  601. get_info_in_room: (roomid) => {
  602. return BilibiliAPI.ajax({
  603. url: 'live_user/v1/UserInfo/get_info_in_room?roomid=' + roomid
  604. });
  605. },
  606. get_weared_medal: (uid, target_id, source = 1) => {
  607. return BilibiliAPI.ajaxWithCommonArgs({
  608. method: 'POST',
  609. url: 'live_user/v1/UserInfo/get_weared_medal',
  610. data: {
  611. source: source,
  612. uid: uid,
  613. target_id: target_id // ruid
  614. }
  615. });
  616. },
  617. governorShow: (target_id) => {
  618. return BilibiliAPI.ajax({
  619. url: 'live_user/v1/Master/governorShow?target_id=' + target_id
  620. });
  621. }
  622. },
  623. lottery: {
  624. box: {
  625. getRoomActivityByRoomid: (roomid) => {
  626. // 获取房间特有的活动 (实物抽奖)
  627. return BilibiliAPI.ajax({
  628. url: 'lottery/v1/box/getRoomActivityByRoomid?roomid=' + roomid
  629. });
  630. },
  631. getStatus: (aid, times = '') => {
  632. // 获取活动信息/状态
  633. return BilibiliAPI.ajax({
  634. url: 'lottery/v1/box/getStatus',
  635. data: {
  636. aid: aid,
  637. times: times
  638. }
  639. });
  640. },
  641. draw: (aid, number = 1) => {
  642. // 参加实物抽奖
  643. return BilibiliAPI.ajax({
  644. url: 'lottery/v1/box/draw',
  645. data: {
  646. aid: aid,
  647. number: number
  648. }
  649. });
  650. },
  651. getWinnerGroupInfo: (aid, number = 1) => {
  652. // 获取中奖名单
  653. return BilibiliAPI.ajax({
  654. url: 'lottery/v1/box/getWinnerGroupInfo',
  655. data: {
  656. aid: aid,
  657. number: number
  658. }
  659. });
  660. }
  661. },
  662. SilverBox: {
  663. getAward: (time_start, end_time, captcha) => {
  664. // 领取银瓜子
  665. return BilibiliAPI.ajax({
  666. url: 'lottery/v1/SilverBox/getAward',
  667. data: {
  668. time_start: time_start,
  669. end_time: end_time,
  670. captcha: captcha
  671. }
  672. });
  673. },
  674. getCaptcha: (ts) => {
  675. // 获取银瓜子验证码图片
  676. return BilibiliAPI.ajax({
  677. url: 'lottery/v1/SilverBox/getCaptcha?ts=' + ts
  678. });
  679. },
  680. getCurrentTask: () => {
  681. // 获取领取银瓜子的任务
  682. return BilibiliAPI.ajax({
  683. url: 'lottery/v1/SilverBox/getCurrentTask'
  684. });
  685. }
  686. },
  687. Storm: {
  688. check: (roomid) => {
  689. // 检查是否有节奏风暴
  690. return BilibiliAPI.ajax({
  691. url: 'lottery/v1/Storm/check?roomid=' + roomid
  692. });
  693. },
  694. join: (id, captcha_token, captcha_phrase, roomid, color = 16777215) => {
  695. // 参加节奏风暴
  696. return BilibiliAPI.ajaxWithCommonArgs({
  697. method: 'POST',
  698. url: 'lottery/v1/Storm/join',
  699. data: {
  700. id: id,
  701. color: color,
  702. captcha_token: captcha_token,
  703. captcha_phrase: captcha_phrase,
  704. roomid: roomid
  705. }
  706. });
  707. }
  708. },
  709. lottery: {
  710. check_guard: (roomid) => {
  711. // 检查是否有舰队领奖
  712. return BilibiliAPI.ajax({
  713. url: 'lottery/v1/Lottery/check_guard?roomid=' + roomid
  714. });
  715. },
  716. join: (roomid, id, type = 'guard') => {
  717. // 参加总督领奖
  718. return BilibiliAPI.ajaxWithCommonArgs({
  719. method: 'POST',
  720. url: 'lottery/v2/Lottery/join',
  721. data: {
  722. roomid: roomid,
  723. id: id,
  724. type: type
  725. }
  726. });
  727. }
  728. }
  729. },
  730. mobile: {
  731. userOnlineHeart: () => {
  732. return BilibiliAPI.ajaxWithCommonArgs({
  733. method: 'POST',
  734. url: 'mobile/userOnlineHeart',
  735. data: {}
  736. });
  737. }
  738. },
  739. pay: {
  740. coin2silver: (num, platform = 'pc') => {
  741. // 硬币兑换银瓜子(新API),1硬币=450银瓜子
  742. return BilibiliAPI.ajaxWithCommonArgs({
  743. method: 'POST',
  744. url: 'pay/v1/Exchange/coin2silver',
  745. data: {
  746. num: num,
  747. platform: platform
  748. }
  749. });
  750. },
  751. getRule: (platform = 'pc') => {
  752. return BilibiliAPI.ajax({
  753. url: 'pay/v1/Exchange/getRule?platform=' + platform
  754. });
  755. },
  756. getStatus: (platform = 'pc') => {
  757. return BilibiliAPI.ajax({
  758. url: 'pay/v1/Exchange/getStatus?platform=' + platform
  759. });
  760. },
  761. silver2coin: (platform = 'pc') => {
  762. // 银瓜子兑换硬币,700银瓜子=1硬币
  763. return BilibiliAPI.ajaxWithCommonArgs({
  764. method: 'POST',
  765. url: 'pay/v1/Exchange/silver2coin',
  766. data: {
  767. platform: platform
  768. }
  769. });
  770. }
  771. },
  772. rankdb: {
  773. roomInfo: (ruid, roomid, areaId) => {
  774. return BilibiliAPI.ajax({
  775. url: 'rankdb/v1/Common/roomInfo',
  776. data: {
  777. ruid: ruid,
  778. roomid: roomid,
  779. areaId: areaId
  780. }
  781. });
  782. }
  783. },
  784. relation: {
  785. getList: (page, page_size) => {
  786. return BilibiliAPI.ajax({
  787. url: 'relation/v1/feed/getList',
  788. data: {
  789. page: page,
  790. page_size: page_size
  791. },
  792. cache: false
  793. });
  794. },
  795. heartBeat: () => {
  796. return BilibiliAPI.ajax({
  797. url: 'relation/v1/feed/heartBeat',
  798. cache: false
  799. });
  800. },
  801. GetUserFc: (follow) => { // follow: 主播uid===ruid
  802. return BilibiliAPI.ajax({
  803. url: 'relation/v1/Feed/GetUserFc?follow=' + follow
  804. });
  805. },
  806. IsUserFollow: (follow) => { // follow: 主播uid===ruid
  807. return BilibiliAPI.ajax({
  808. url: 'relation/v1/Feed/IsUserFollow?follow=' + follow
  809. });
  810. }
  811. },
  812. room: {
  813. get_info: (room_id, from = 'room') => {
  814. return BilibiliAPI.ajax({
  815. url: 'room/v1/Room/get_info',
  816. data: {
  817. room_id: room_id,
  818. from: from
  819. }
  820. });
  821. },
  822. get_recommend_by_room: (room_id, count, rnd) => {
  823. return BilibiliAPI.ajax({
  824. url: 'room/v1/room/get_recommend_by_room',
  825. data: {
  826. room_id: room_id,
  827. count: count,
  828. rnd: rnd || Math.floor(Date.now() / 1000)
  829. }
  830. });
  831. },
  832. playUrl: (cid, quality = '0', platform = 'web') => {
  833. return BilibiliAPI.ajax({
  834. url: 'room/v1/Room/playUrl',
  835. data: {
  836. cid: cid, // roomid
  837. quality: quality,
  838. platform: platform
  839. }
  840. });
  841. },
  842. room_entry_action: (room_id, platform = 'pc') => {
  843. return BilibiliAPI.ajaxWithCommonArgs({
  844. method: 'POST',
  845. url: 'room/v1/Room/room_entry_action',
  846. data: {
  847. room_id: room_id,
  848. platform: platform
  849. }
  850. });
  851. },
  852. room_init: (id) => {
  853. return BilibiliAPI.ajax({
  854. url: 'room/v1/Room/room_init?id=' + id
  855. });
  856. },
  857. getConf: (room_id, platform = 'pc', player = 'web') => {
  858. return BilibiliAPI.ajax({
  859. url: 'room/v1/Danmu/getConf',
  860. data: {
  861. room_id: room_id,
  862. platform: platform,
  863. player: player
  864. }
  865. });
  866. },
  867. getList: () => {
  868. return BilibiliAPI.ajax({
  869. url: 'room/v1/Area/getList'
  870. });
  871. },
  872. getRoomList: (parent_area_id = 1, cate_id = 0, area_id = 0, page = 1, page_size = 30, sort_type = 'online', platform = 'web') => {
  873. return BilibiliAPI.ajax({
  874. url: 'room/v1/area/getRoomList',
  875. data: {
  876. platform: platform,
  877. parent_area_id: parent_area_id,
  878. cate_id: cate_id,
  879. area_id: area_id,
  880. sort_type: sort_type,
  881. page: page,
  882. page_size: page_size
  883. }
  884. });
  885. }
  886. },
  887. sign: {
  888. doSign: () => {
  889. // 签到
  890. return BilibiliAPI.ajax({
  891. url: 'sign/doSign'
  892. });
  893. },
  894. GetSignInfo: () => {
  895. // 获取签到信息
  896. return BilibiliAPI.ajax({
  897. url: 'sign/GetSignInfo'
  898. });
  899. },
  900. getLastMonthSignDays: () => {
  901. return BilibiliAPI.ajax({
  902. url: 'sign/getLastMonthSignDays'
  903. });
  904. }
  905. },
  906. user: {
  907. getWear: (uid) => {
  908. return BilibiliAPI.ajax({
  909. url: 'user/v1/user_title/getWear?uid=' + uid
  910. });
  911. },
  912. isBiliVip: (uid) => {
  913. return BilibiliAPI.ajax({
  914. url: 'user/v1/user/isBiliVip?uid=' + uid
  915. });
  916. },
  917. userOnlineHeart: () => {
  918. return BilibiliAPI.ajaxWithCommonArgs({
  919. method: 'POST',
  920. url: 'User/userOnlineHeart',
  921. data: {}
  922. });
  923. },
  924. getUserInfo: (ts) => { // ms
  925. return BilibiliAPI.ajax({
  926. url: 'User/getUserInfo?ts=' + ts
  927. });
  928. }
  929. },
  930. x: {
  931. coin_add: (aid, multiply = 1) => {
  932. // 投币
  933. return BilibiliAPI.ajaxWithCommonArgs({
  934. method: 'POST',
  935. url: '//api.bilibili.com/x/web-interface/coin/add',
  936. data: {
  937. aid: aid,
  938. multiply: multiply,
  939. cross_domain: true
  940. }
  941. });
  942. },
  943. share_add: (aid) => {
  944. // 分享
  945. return BilibiliAPI.ajaxWithCommonArgs({
  946. method: 'POST',
  947. url: '//api.bilibili.com/x/web-interface/share/add',
  948. data: {
  949. aid: aid,
  950. jsonp: 'jsonp'
  951. }
  952. });
  953. },
  954. heartbeat: (aid, cid, mid, start_ts, played_time = 0, realtime = 0, type = 3, play_type = 1, dt = 2) => {
  955. // B站视频心跳
  956. return BilibiliAPI.ajaxWithCommonArgs({
  957. method: 'POST',
  958. url: '//api.bilibili.com/x/report/web/heartbeat',
  959. data: {
  960. aid: aid,
  961. cid: cid,
  962. mid: mid, // uid
  963. start_ts: start_ts || (Date.now() / 1000),
  964. played_time: played_time,
  965. realtime: realtime,
  966. type: type,
  967. play_type: play_type, // 1:播放开始,2:播放中
  968. dt: dt
  969. }
  970. });
  971. },
  972. now: () => {
  973. // 点击播放视频时出现的事件,可能与登录/观看视频判定有关
  974. return BilibiliAPI.ajax({
  975. url: '//api.bilibili.com/x/report/click/now',
  976. data: {
  977. jsonp: 'jsonp'
  978. }
  979. });
  980. }
  981. },
  982. xlive: {
  983. guard: {
  984. join: (roomid, id, type = 'guard') => {
  985. return BilibiliAPI.ajaxWithCommonArgs({
  986. method: 'POST',
  987. url: 'xlive/lottery-interface/v3/guard/join',
  988. data: {
  989. roomid: roomid,
  990. id: id,
  991. type: type
  992. }
  993. });
  994. }
  995. },
  996. lottery: {
  997. check: (roomid) => {
  998. return BilibiliAPI.ajax({
  999. url: 'xlive/lottery-interface/v1/lottery/Check',
  1000. data: {
  1001. roomid: roomid
  1002. }
  1003. });
  1004. }
  1005. },
  1006. smalltv: {
  1007. check: (roomid) => {
  1008. return BilibiliAPI.ajax({
  1009. url: 'xlive/lottery-interface/v3/smalltv/Check',
  1010. data: {
  1011. roomid: roomid
  1012. }
  1013. });
  1014. },
  1015. join: (roomid, id, type = 'small_tv') => {
  1016. return BilibiliAPI.ajaxWithCommonArgs({
  1017. method: 'POST',
  1018. url: 'xlive/lottery-interface/v5/smalltv/join',
  1019. data: {
  1020. roomid: roomid,
  1021. id: id,
  1022. type: type
  1023. }
  1024. });
  1025. },
  1026. notice: (raffleId, type = 'small_tv') => {
  1027. return BilibiliAPI.ajax({
  1028. url: 'xlive/lottery-interface/v3/smalltv/Notice',
  1029. data: {
  1030. type: type,
  1031. raffleId: raffleId
  1032. }
  1033. });
  1034. }
  1035. },
  1036. pk: {
  1037. check: (roomid) => {
  1038. return BilibiliAPI.ajax({
  1039. url: 'xlive/lottery-interface/v1/pk/check',
  1040. data: {
  1041. roomid: roomid
  1042. }
  1043. });
  1044. },
  1045. join: (roomid, id) => {
  1046. return BilibiliAPI.ajaxWithCommonArgs({
  1047. method: 'POST',
  1048. url: 'xlive/lottery-interface/v1/pk/join',
  1049. data: {
  1050. roomid: roomid,
  1051. id: id
  1052. }
  1053. });
  1054. }
  1055. }
  1056. },
  1057. YearWelfare: {
  1058. checkFirstCharge: () => {
  1059. return BilibiliAPI.ajax({
  1060. url: 'YearWelfare/checkFirstCharge'
  1061. });
  1062. },
  1063. inviteUserList: () => {
  1064. return BilibiliAPI.ajax({
  1065. url: 'YearWelfare/inviteUserList/1'
  1066. });
  1067. }
  1068. },
  1069. DanmuWebSocket: class extends WebSocket {
  1070. static stringToUint(string) {
  1071. const charList = string.split('');
  1072. const uintArray = [];
  1073. for (var i = 0; i < charList.length; ++i) {
  1074. uintArray.push(charList[i].charCodeAt(0));
  1075. }
  1076. return new Uint8Array(uintArray);
  1077. }
  1078. static uintToString(uintArray) {
  1079. return decodeURIComponent(escape(String.fromCharCode.apply(null, uintArray)));
  1080. }
  1081. constructor(uid, roomid, host_server_list, token) {
  1082. // 总字节长度 int(4bytes) + 头字节长度(16=4+2+2+4+4) short(2bytes) + protover(1,2) short(2bytes) + operation int(4bytes) + sequence(1,0) int(4bytes) + Data
  1083. let address = 'wss://broadcastlv.chat.bilibili.com/sub';
  1084. if (Array.isArray(host_server_list) && host_server_list.length > 0) {
  1085. let flag = false;
  1086. do {
  1087. const chosen = host_server_list.shift();
  1088. if (chosen.wss_port) address = `wss://${chosen.host}:${chosen.wss_port}/sub`;
  1089. else flag = true;
  1090. } while (flag && host_server_list.length > 0);
  1091. } else if (typeof host_server_list === 'string' && host_server_list.length > 0) {
  1092. address = host_server_list;
  1093. }
  1094. super(address);
  1095. this.binaryType = 'arraybuffer';
  1096. this.handlers = {
  1097. reconnect: [],
  1098. login: [],
  1099. heartbeat: [],
  1100. cmd: [],
  1101. receive: []
  1102. };
  1103. this.host_server_list = host_server_list;
  1104. this.token = token;
  1105. this.closed = false;
  1106. this.addEventListener('open', () => {
  1107. this.sendLoginPacket(uid, roomid).sendHeartBeatPacket();
  1108. this.heartBeatHandler = setInterval(() => {
  1109. this.sendHeartBeatPacket();
  1110. }, 30e3);
  1111. });
  1112. this.addEventListener('close', () => {
  1113. if (this.heartBeatHandler) clearInterval(this.heartBeatHandler);
  1114. if (this.closed) return;
  1115. // 自动重连
  1116. setTimeout(() => {
  1117. const ws = new BilibiliAPI.DanmuWebSocket(uid, roomid, this.host_server_list, this.token);
  1118. ws.handlers = this.handlers;
  1119. ws.unzip = this.unzip;
  1120. for (const key in this.handlers) {
  1121. if (this.handlers.hasOwnProperty(key)) {
  1122. this.handlers[key].forEach(handler => {
  1123. switch (key) {
  1124. case 'reconnect':
  1125. ws.addEventListener('reconnect', (event) => {
  1126. handler.call(ws, event.detail.ws);
  1127. });
  1128. break;
  1129. case 'login':
  1130. ws.addEventListener('login', () => {
  1131. handler.call(ws);
  1132. });
  1133. break;
  1134. case 'heartbeat':
  1135. ws.addEventListener('heartbeat', (event) => {
  1136. handler.call(ws, event.detail.num);
  1137. });
  1138. break;
  1139. case 'cmd':
  1140. ws.addEventListener('cmd', (event) => {
  1141. handler.call(ws, event.detail.obj, event.detail.str);
  1142. });
  1143. break;
  1144. case 'receive':
  1145. ws.addEventListener('receive', (event) => {
  1146. handler.call(ws, event.detail.len, event.detail.headerLen, event.detail.protover, event.detail.operation, event.detail.sequence, event.detail.data);
  1147. });
  1148. break;
  1149. }
  1150. });
  1151. }
  1152. }
  1153. this.dispatchEvent(new CustomEvent('reconnect', {
  1154. detail: {
  1155. ws: ws
  1156. }
  1157. }));
  1158. }, 10e3);
  1159. });
  1160. this.addEventListener('message', (event) => {
  1161. const dv = new DataView(event.data);
  1162. let len = 0;
  1163. for (let position = 0; position < event.data.byteLength; position += len) {
  1164. /*
  1165. 登录 总字节长度 int(4bytes) + 头字节长度 short(2bytes) + 00 01 + 00 00 00 08 + 00 00 00 01
  1166. 心跳 总字节长度 int(4bytes) + 头字节长度 short(2bytes) + 00 01 + 00 00 00 03 + 00 00 00 01 + 直播间人气 int(4bytes)
  1167. 弹幕消息/系统消息/送礼 总字节长度 int(4bytes) + 头字节长度 short(2bytes) + 00 00 + 00 00 00 05 + 00 00 00 00 + Data
  1168. */
  1169. len = dv.getUint32(position);
  1170. const headerLen = dv.getUint16(position + 4);
  1171. const protover = dv.getUint16(position + 6);
  1172. const operation = dv.getUint32(position + 8);
  1173. const sequence = dv.getUint32(position + 12);
  1174. let data = event.data.slice(position + headerLen, position + len);
  1175. if (protover === 2 && this.unzip) data = this.unzip(data);
  1176. this.dispatchEvent(new CustomEvent('receive', {
  1177. detail: {
  1178. len: len,
  1179. headerLen: headerLen,
  1180. protover: protover,
  1181. operation: operation,
  1182. sequence: sequence,
  1183. data: data
  1184. }
  1185. }));
  1186. if (protover === 2 && !this.unzip) continue;
  1187. const dataV = new DataView(data);
  1188. switch (operation) {
  1189. case 3:
  1190. {
  1191. const num = dataV.getUint32(0); // 在线人数
  1192. this.dispatchEvent(new CustomEvent('heartbeat', {
  1193. detail: {
  1194. num: num
  1195. }
  1196. }));
  1197. break;
  1198. }
  1199. case 5:
  1200. {
  1201. const str = BilibiliAPI.DanmuWebSocket.uintToString(new Uint8Array(data));
  1202. const obj = JSON.parse(str);
  1203. this.dispatchEvent(new CustomEvent('cmd', {
  1204. detail: {
  1205. obj: obj,
  1206. str: str
  1207. }
  1208. }));
  1209. break;
  1210. }
  1211. case 8:
  1212. this.dispatchEvent(new CustomEvent('login'));
  1213. break;
  1214. }
  1215. }
  1216. });
  1217. }
  1218. close(code, reason) {
  1219. this.closed = true;
  1220. super.close(code, reason);
  1221. }
  1222. setUnzip(fn) {
  1223. this.unzip = fn;
  1224. }
  1225. bind(onreconnect = undefined, onlogin = undefined, onheartbeat = undefined, oncmd = undefined, onreceive = undefined) {
  1226. /*
  1227. 参数说明
  1228. onreconnect(DanmuWebSocket) // 必要,DanmuWebSocket为新的
  1229. onlogin()
  1230. onheartbeat(number)
  1231. oncmd(object, string)
  1232. onreceive(number, number, number, number, number, arraybuffer)
  1233. */
  1234. if (typeof onreconnect === 'function') {
  1235. this.addEventListener('reconnect', (event) => {
  1236. onreconnect.call(this, event.detail.ws);
  1237. });
  1238. this.handlers.reconnect.push(onreconnect);
  1239. }
  1240. if (typeof onlogin === 'function') {
  1241. this.addEventListener('login', () => {
  1242. onlogin.call(this);
  1243. });
  1244. this.handlers.login.push(onlogin);
  1245. }
  1246. if (typeof onheartbeat === 'function') {
  1247. this.addEventListener('heartbeat', (event) => {
  1248. onheartbeat.call(this, event.detail.num);
  1249. });
  1250. this.handlers.heartbeat.push(onheartbeat);
  1251. }
  1252. if (typeof oncmd === 'function') {
  1253. this.addEventListener('cmd', (event) => {
  1254. oncmd.call(this, event.detail.obj, event.detail.str);
  1255. });
  1256. this.handlers.cmd.push(oncmd);
  1257. }
  1258. if (typeof onreceive === 'function') {
  1259. this.addEventListener('receive', (event) => {
  1260. onreceive.call(this, event.detail.len, event.detail.headerLen, event.detail.protover, event.detail.operation, event.detail.sequence, event.detail.data);
  1261. });
  1262. this.handlers.receive.push(onreceive);
  1263. }
  1264. }
  1265. sendData(data, protover, operation, sequence) {
  1266. if (this.readyState !== WebSocket.OPEN) throw new Error('DanmuWebSocket未连接');
  1267. switch (Object.prototype.toString.call(data)) {
  1268. case '[object Object]':
  1269. return this.sendData(JSON.stringify(data), protover, operation, sequence);
  1270. case '[object String]':
  1271. {
  1272. let dataUint8Array = BilibiliAPI.DanmuWebSocket.stringToUint(data);
  1273. let buffer = new ArrayBuffer(BilibiliAPI.DanmuWebSocket.headerLength + dataUint8Array.byteLength);
  1274. let dv = new DataView(buffer);
  1275. dv.setUint32(0, BilibiliAPI.DanmuWebSocket.headerLength + dataUint8Array.byteLength);
  1276. dv.setUint16(4, BilibiliAPI.DanmuWebSocket.headerLength);
  1277. dv.setUint16(6, parseInt(protover, 10));
  1278. dv.setUint32(8, parseInt(operation, 10));
  1279. dv.setUint32(12, parseInt(sequence, 10));
  1280. for (let i = 0; i < dataUint8Array.byteLength; ++i) {
  1281. dv.setUint8(BilibiliAPI.DanmuWebSocket.headerLength + i, dataUint8Array[i]);
  1282. }
  1283. this.send(buffer);
  1284. }
  1285. return this;
  1286. default:
  1287. this.send(data);
  1288. }
  1289. return this;
  1290. }
  1291. sendLoginPacket(uid, roomid) {
  1292. // 总字节长度 int(4bytes) + 头字节长度 short(2bytes) + 00 01 + 00 00 00 07 + 00 00 00 01 + Data 登录数据包
  1293. const data = {
  1294. 'uid': parseInt(uid, 10),
  1295. 'roomid': parseInt(roomid, 10),
  1296. 'protover': 2,
  1297. 'platform': 'web',
  1298. 'clientver': '1.8.5',
  1299. 'type': 2,
  1300. 'key': this.token
  1301. };
  1302. return this.sendData(data, 1, 7, 1);
  1303. }
  1304. sendHeartBeatPacket() {
  1305. // 总字节长度 int(4bytes) + 头字节长度 short(2bytes) + 00 01 + 00 00 00 02 + 00 00 00 01 + Data 心跳数据包
  1306. return this.sendData('[object Object]', 1, 2, 1);
  1307. }
  1308. }
  1309. };
  1310. BilibiliAPI.DanmuWebSocket.headerLength = 16;