快捷弹幕

B站直播间发送快捷弹幕

目前為 2022-01-28 提交的版本,檢視 最新版本

// ==UserScript==
// @name         快捷弹幕
// @namespace    http://tampermonkey.net/
// @version      0.2.1
// @description  B站直播间发送快捷弹幕
// @author       mianju
// @include      /https?:\/\/live\.bilibili\.com\/(blanc\/)?\d+\??.*/
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js
// @grant        none
// ==/UserScript==

(function () {
  function main() {
    initLib()
    initCss()
    waitForLoaded(() => {
      initUi()
    })
  }

  function initLib() {
    let scriptElement = document.createElement('script')
    scriptElement.src = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js'
    document.head.appendChild(scriptElement)

    let linkElement = document.createElement('link')
    linkElement.rel = 'stylesheet'
    linkElement.href = 'https://unpkg.com/element-ui/lib/theme-chalk/index.css'
    document.head.appendChild(linkElement)

    scriptElement = document.createElement('script')
    scriptElement.src = 'https://unpkg.com/element-ui/lib/index.js'
    document.head.appendChild(scriptElement)
  }

  function initCss() {
    let css = `
      .el-select .el-input {
          width: 80px;
        }
        .input-with-select .el-input-group__prepend {
          background-color: #fff;
        }
    `
    let styleElement = document.createElement('style')
    styleElement.innerText = css
    document.head.appendChild(styleElement)
  }

  function waitForLoaded(callback, timeout = 10 * 1000) {
    let startTime = new Date()
    function poll() {
      if (isLoaded()) {
        callback()
        return
      }

      if (new Date() - startTime > timeout) {
        return
      }
      setTimeout(poll, 1000)
    }
    poll()
  }

  function isLoaded() {
    if (window.ELEMENT === undefined) {
      return false
    }
    if (document.querySelector('#control-panel-ctnr-box') === null) {
      return false
    }
    return true
  }
  function initUi() {
      var father = document.getElementsByClassName('icon-left-part')[0];
      let quickDanmukuElement = document.createElement('div');
      father.appendChild(quickDanmukuElement);

      new Vue({
          el: quickDanmukuElement,
          template: `
          <span>
        <template style="width: 200px" >
            <el-select v-model="value" placeholder="选择" @change="sendDanmuku" style="width: 80px;height: 24px" size="mini">
                <el-option-group
                    v-for="group in options"
                    :key="group.label"
                    :label="group.label">
                    <el-option
                    v-for="danmuku in group.danmukus"
                    :key="danmuku.label"
                    :label="danmuku.label"
                    :value="danmuku.label">
                    </el-option>
                </el-option-group>
            </el-select>
            <el-button icon="el-icon-message" size="mini" circle @click="sendDanmuku(value)"></el-button>
            <el-popover
                placement="bottom"
                title="快捷弹幕设置"
                width="300px"
                trigger="click"
                >
                <span class="demonstration">添加</span><br>
                <el-input placeholder="请输入内容" v-model="danmuku4add" class="input-with-select" maxlength="20">
                    <el-select v-model="select" slot="prepend" placeholder="请选择">
                        <el-option label="当前" value="cur"></el-option>
                        <el-option label="所有" value="all"></el-option>
                    </el-select>
                    <el-button slot="append" icon="el-icon-check" @click="addDanmuku"></el-button>
                </el-input>
                <div class="block">
                    <span class="demonstration">删除</span><br>
                    <el-cascader
                      v-model="danmukus4del"
                      :options="options"
                      :props="{ expandTrigger: 'hover','children': 'danmukus','multiple': 'true','emitPath':'false' }"
                      ></el-cascader>
                      <el-button type="danger" icon="el-icon-delete" @click="delDanmukus"></el-button>
                </div>
                <el-button slot="reference" icon="el-icon-setting" size="mini" circle></el-button>
            </el-popover>
        </template>
    </span>
          `,
          data: {
                options: [
                    {
                        label: '所有直播间',
                        value: 'all',
                        danmukus: []
                    },
                    {
                        label: '当前直播间',
                        value: 'cur',
                        danmukus: []
                    }
                ],
                value: '',
                danmuku4add: '',
                select: 'cur',
                danmukus4del: [],
                roomId: 0,
                allRoomDanmukus: [],
                curRoomDanmukus: [],
                key4all: 'allRoomDanmukus',
                key4cur: ''
            },
            methods: {
                "delDanmukus": function () {
                    function del(val,danmukus) {
                        let index = danmukus.indexOf(val);
                        danmukus.splice(index,1);
                    };
                    for (let i=0;i<this.danmukus4del.length;i++){
                        let danmuku = this.danmukus4del[i];
                        if (danmuku[0] == "cur") {
                            del(danmuku[1],this.curRoomDanmukus);
                        } else {
                            del(danmuku[1],this.allRoomDanmukus);
                        }
                    }
                    localStorage.setItem(this.key4cur,JSON.stringify(this.curRoomDanmukus));
                    localStorage.setItem(this.key4all,JSON.stringify(this.allRoomDanmukus));
                    this.danmukus4del = [];
                    this.$message.success("删除成功");
                    this.handleDanmukus();
                },
                "getRoomId": function () {
                    if (window.__NEPTUNE_IS_MY_WAIFU__) {
                        this.roomId = window.__NEPTUNE_IS_MY_WAIFU__.roomInfoRes.data.room_info.room_id;
                    } else {
                        let url = document.URL;
                        var re = /\/\d+/.exec(url);
                        this.roomId = re[0].substr(1);
                    }
                },
                "getDanmukus": function (key) {
                    if (localStorage.getItem(key)){
                        return JSON.parse(localStorage.getItem(key));
                    }
                    return [];
                },
                "handleDanmukus": function () {
                    function handle(danmukus4opt,danmukus4room){
                        danmukus4opt.splice(0);
                        for (let i=0;i<danmukus4room.length;i++) {
                            danmukus4opt.push({label:danmukus4room[i],value:danmukus4room[i]});
                        }
                    }
                    handle(this.options[0].danmukus,this.allRoomDanmukus);
                    handle(this.options[1].danmukus,this.curRoomDanmukus);
                },
                "addDanmuku": function () {
                    function add(key,danmukus,danmuku){
                        danmukus.push(danmuku);
                        localStorage.setItem(key,JSON.stringify(danmukus));
                    };
                    if (this.select == "cur") {
                        add(this.key4cur,this.curRoomDanmukus,this.danmuku4add);
                    } else {
                        add(this.key4all,this.allRoomDanmukus,this.danmuku4add);
                    }
                    this.danmuku4add = '';
                    this.$message.success("添加成功");
                    this.handleDanmukus();
                },
                "sendDanmuku": function (danmuku4send) {
                    var jct = getCookie('bili_jct');
                    var date = new Date();
                    var data = new FormData();
                    data.append('bubble',0);
                    data.append('color',16777215);
                    data.append('fontsize',25);
                    data.append('mode',1);
                    data.append('msg',danmuku4send);
                    data.append('rnd',parseInt(date.getTime()/1000));
                    data.append('roomid',this.roomId);
                    data.append('csrf',jct);
                    data.append('csrf_token',jct);
                    let apiClient = axios.create({
                        baseURL: 'https://api.live.bilibili.com',
                        withCredentials: true
                    });
                    apiClient.post('/msg/send',data).then((res)=>{
                        if (res.data.msg == 'f'){
                            this.$message.error('发送失败 - 弹幕被屏蔽: ' + danmuku4send);
                        }
                        else if (res.data.code ==0) {
                            this.$message.success('发送成功 - ' + danmuku4send);
                        } else {
                            this.$message.error('发送失败 - ' + res.data.message);
                        }
                    }).catch(()=>{
                        this.$message.error('发送失败 - ' + danmuku4send);
                    });
                }
            } ,
            created: function () {
                this.getRoomId();
                this.key4cur = this.roomId + '-danmukus';
                this.curRoomDanmukus = this.getDanmukus(this.key4cur);
                this.allRoomDanmukus = this.getDanmukus(this.key4all);
                this.handleDanmukus();
            }
      });
  }
  function getCookie(cname){
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
        var c = ca[i].trim();
        if (c.indexOf(name)==0) { return c.substring(name.length,c.length); }
    }
    return "";
  }
  main()
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址