花心拯救者

白嫖没有错,花心也没有猜错,错的是这个破站直播!

  1. // ==UserScript==
  2. // @name 花心拯救者
  3. // @namespace Cutemon
  4. // @version 1.60
  5. // @description 白嫖没有错,花心也没有猜错,错的是这个破站直播!
  6. // @author Cutemon
  7. // @include /https?:\/\/live\.bilibili\.com\/\d+\??.*/
  8. // @require https://static.hdslb.com/live-static/libs/jquery/jquery-1.11.3.min.js
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. let room_id = window.location.pathname.slice(1),
  17. medal_id = '';
  18. let xx, yy;
  19. let left, top;
  20.  
  21. // 获取用户cookie
  22. let getCookie = Name => {
  23. let search = Name + '='; //查询检索的值
  24. let returnvalue = ''; //返回值
  25. if (document.cookie.length > 0) {
  26. let sd = document.cookie.indexOf(search);
  27. if (sd != -1) {
  28. sd += search.length;
  29. let end = document.cookie.indexOf(';', sd);
  30. if (end == -1) end = document.cookie.length;
  31. //unescape() 函数可对通过 escape() 编码的字符串进行解码。
  32. returnvalue = unescape(document.cookie.substring(sd, end));
  33. }
  34. }
  35. return returnvalue;
  36. };
  37.  
  38. function bindInput() {
  39. let bindTimer = setInterval(() => {
  40. console.log(`弹幕输入框事件绑定中……`);
  41.  
  42. if ($('.chat-input').length) {
  43. // 一般情况下获取dom
  44. $('.chat-input').focus(checkMedal);
  45. left = $('#control-panel-ctnr-box').offset().left + 8 + 'px';
  46. top = $('#control-panel-ctnr-box').offset().top - 50 + 'px';
  47. console.log(`勋章自动切换功能已启动`);
  48. toast('勋章自动切换功能已启动', 'success');
  49. clearInterval(bindTimer);
  50. } else {
  51. // iframe情况下获取dom
  52. try {
  53. let ifr = document
  54. .getElementById('player-ctnr')
  55. .getElementsByTagName('iframe');
  56. if (ifr.length) {
  57. $('head').append(`<style type="text/css">/*
  58. * Link Toast Style By LancerComet at 17:31, 2015.12.16.
  59. * # Carry Your World #
  60. * ---
  61. * 直播站 Toast 组件样式文件.
  62. */
  63. .link-toast {
  64. position: absolute;
  65. padding: 12px 24px;
  66. font-size: 14px;
  67. border-radius: 8px;
  68. white-space: nowrap;
  69. color: #fff;
  70. -webkit-animation: link-msg-move-in-top cubic-bezier(0.22, 0.58, 0.12, 0.98) 0.4s;
  71. animation: link-msg-move-in-top cubic-bezier(0.22, 0.58, 0.12, 0.98) 0.4s;
  72. z-index: 10000;
  73. }
  74. .link-toast.fixed {
  75. position: fixed;
  76. }
  77. .link-toast.success {
  78. background-color: #47d279;
  79. -webkit-box-shadow: 0 0.2em 0.1em 0.1em rgba(71,210,121,0.2);
  80. box-shadow: 0 0.2em 0.1em 0.1em rgba(71,210,121,0.2);
  81. }
  82. .link-toast.caution {
  83. background-color: #ffb243;
  84. -webkit-box-shadow: 0 0.2em 0.1em 0.1em rgba(255,190,68,0.2);
  85. box-shadow: 0 0.2em 0.1em 0.1em rgba(255,190,68,0.2);
  86. }
  87. .link-toast.error {
  88. background-color: #ff6464;
  89. -webkit-box-shadow: 0 0.2em 1em 0.1em rgba(255,100,100,0.2);
  90. box-shadow: 0 0.2em 1em 0.1em rgba(255,100,100,0.2);
  91. }
  92. .link-toast.info {
  93. background-color: #48bbf8;
  94. -webkit-box-shadow: 0 0.2em 0.1em 0.1em rgba(72,187,248,0.2);
  95. box-shadow: 0 0.2em 0.1em 0.1em rgba(72,187,248,0.2);
  96. }
  97. .link-toast.out {
  98. -webkit-animation: link-msg-fade-out cubic-bezier(0.22, 0.58, 0.12, 0.98) 0.4s;
  99. animation: link-msg-fade-out cubic-bezier(0.22, 0.58, 0.12, 0.98) 0.4s;
  100. }
  101. @-webkit-keyframes link-msg-move-in-top {
  102. from {
  103. opacity: 0;
  104. -webkit-transform: translate(0, 5em);
  105. transform: translate(0, 5em);
  106. }
  107. to {
  108. opacity: 1;
  109. -webkit-transform: translate(0, 0);
  110. transform: translate(0, 0);
  111. }
  112. }
  113. @keyframes link-msg-move-in-top {
  114. from {
  115. opacity: 0;
  116. -webkit-transform: translate(0, 5em);
  117. transform: translate(0, 5em);
  118. }
  119. to {
  120. opacity: 1;
  121. -webkit-transform: translate(0, 0);
  122. transform: translate(0, 0);
  123. }
  124. }
  125. @-webkit-keyframes link-msg-fade-out {
  126. from {
  127. opacity: 1;
  128. }
  129. to {
  130. opacity: 0;
  131. }
  132. }
  133. @keyframes link-msg-fade-out {
  134. from {
  135. opacity: 1;
  136. }
  137. to {
  138. opacity: 0;
  139. }
  140. }
  141. </style>`);
  142.  
  143. let domChat = ifr[0].contentWindow.document.getElementsByClassName(
  144. 'chat-input'
  145. )[0];
  146. $(domChat).focus(checkMedal);
  147. let domPanel = ifr[0].contentWindow.document.getElementById(
  148. 'control-panel-ctnr-box'
  149. );
  150. left = $(domPanel).offset().left + 8 + 'px';
  151. top = $(domPanel).offset().top - 50 + 'px';
  152. console.log(`勋章自动切换功能已启动`);
  153. toast('勋章自动切换功能已启动', 'success');
  154. clearInterval(bindTimer);
  155. }
  156. } catch (err) {
  157. let ifr = document
  158. .getElementById('player-ctnr')
  159. .getElementsByTagName('iframe');
  160. console.log(
  161. `chatinput: ${$('.chat-input')
  162. .length}\niframe: ${ifr.length}`
  163. );
  164. }
  165. }
  166. }, 1e3);
  167.  
  168. $('body').mousemove(e => {
  169. xx = e.originalEvent.x || e.originalEvent.layerX || 0;
  170. yy = e.originalEvent.y || e.originalEvent.layerY || 0;
  171. //let d = document.getElementById("div");获取某div在当前窗口的位置
  172. //let dx = xx - p.getBoundingClientRect().left;
  173. //let dy = yy - p.getBoundingClientRect().top;
  174. //$(this).text(dx + '---' + dy);鼠标在该div内位置
  175. });
  176. }
  177.  
  178. function getMedal() {
  179. $.ajax({
  180. type: 'GET',
  181. url:
  182. '//api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom',
  183. data: {
  184. room_id
  185. },
  186. success: res => {
  187. if (res.code == 0) {
  188. console.log('勋章id获取成功');
  189. medal_id = res.data.anchor_info.medal_info.medal_id;
  190. bindInput();
  191. }
  192. }
  193. });
  194. }
  195.  
  196. function checkMedal() {
  197. // let left = '85%',
  198. // top = '70%';
  199. $.ajax({
  200. type: 'GET',
  201. // url: '//api.live.bilibili.com/i/ajaxWearFansMedal',
  202. url:
  203. '//api.live.bilibili.com/live_user/v1/UserInfo/get_weared_medal',
  204. success: res => {
  205. if (medal_id == res.data.medal_id) {
  206. toast('已经佩戴本房间勋章,无需重复佩戴', 'caution');
  207. } else {
  208. wearMedal(medal_id);
  209. }
  210. }
  211. });
  212. }
  213.  
  214. function wearMedal(medal_id) {
  215. // let left = xx - 100 + 'px',
  216. // top = yy - 100 + 'px';
  217. // let left = '85%',
  218. // top = '70%';
  219. $.ajax({
  220. type: 'POST',
  221. // url: '//api.live.bilibili.com/i/ajaxWearFansMedal',
  222. url: '//api.live.bilibili.com/xlive/web-room/v1/fansMedal/wear',
  223. data: {
  224. medal_id
  225. },
  226. success: res => {
  227. if (res.code == 0) {
  228. toast(res.message || res.msg, 'success');
  229. console.log(left, top, res.message || res.msg);
  230. } else {
  231. toast(res.message || res.msg, 'caution');
  232. // $('.chat-input').unbind();
  233. }
  234. }
  235. });
  236. }
  237.  
  238. function toast(text, level) {
  239. text = text || '这是一个提示';
  240. level = level || 'success'; // success,caution,info,error
  241. // left = left || '75%';
  242. // top = top || '80%';
  243. if (level != 'success') {
  244. console.log(text);
  245. }
  246. let id = new Date().valueOf();
  247.  
  248. $('body').append(
  249. '<div class="link-toast ' +
  250. level +
  251. '"data-id="' +
  252. id +
  253. '" style="position: fixed; left: ' +
  254. left +
  255. '; top: ' +
  256. top +
  257. ';"><span class="toast-text">' +
  258. text +
  259. '</span></div>'
  260. );
  261. $(
  262. "div.link-toast[data-id='" + id + "']"
  263. ).slideDown('normal', function() {
  264. setTimeout(function() {
  265. $(
  266. "div.link-toast[data-id='" + id + "']"
  267. ).fadeOut('normal', function() {
  268. $("div.link-toast[data-id='" + id + "']").remove();
  269. });
  270. }, 1500);
  271. });
  272. }
  273.  
  274. window.onload = function() {
  275. let token = getCookie('bili_jct');
  276. $.ajaxSetup({
  277. crossDomain: true,
  278. xhrFields: {
  279. withCredentials: true
  280. },
  281. data: {
  282. csrf: token,
  283. csrf_token: token
  284. }
  285. });
  286. console.log(`花心拯救者脚本已开始工作!`);
  287. getMedal();
  288. };
  289. })();