Browse Source

fix a severe danamku tunnel bug; Bilibili 弹幕支持!

DIYgod 8 years ago
parent
commit
5b720441e9
8 changed files with 123 additions and 12 deletions
  1. 12 0
      README.md
  2. 0 0
      dist/DPlayer.min.js
  3. 0 0
      dist/DPlayer.min.js.map
  4. 1 0
      nodejs/index.js
  5. 3 1
      nodejs/package.json
  6. 65 0
      nodejs/routes/bilibili.js
  7. 1 1
      package.json
  8. 41 10
      src/DPlayer.js

+ 12 - 0
README.md

@@ -60,6 +60,7 @@ var option = {
         api: 'https://dplayer.daoapp.io/',                             // Required, danmaku api
         token: 'tokendemo',                                            // Optional, danmaku token for api
         maximum: 1000                                                  // Optional, maximum quantity of danmaku
+        addition: ['https://dplayer.daoapp.io/bilibili?aid=4157142']   // Optional, additional danmaku, see: `Bilibili 弹幕支持`
     }
 }
 ```
@@ -91,6 +92,17 @@ var option = {
 + `ended`: Triggered when DPlayer ended
 + `error`: Triggered when an error occurs
 
+**Bilibili 弹幕支持**
+
+```JS
+var option = {
+    danmaku: {
+        // ...
+        addition: ['https://dplayer.daoapp.io/bilibili?aid=【bilibili视频AV号】']
+    }
+}
+```
+
 **Live Video (HTTP Live Streaming, M3U8 format)**
 
 It requires the library [hls.js](https://github.com/dailymotion/hls.js) and it should be loaded before DPlayer.min.js.

File diff suppressed because it is too large
+ 0 - 0
dist/DPlayer.min.js


File diff suppressed because it is too large
+ 0 - 0
dist/DPlayer.min.js.map


+ 1 - 0
nodejs/index.js

@@ -9,4 +9,5 @@ app.all('*', require('./routes/all'));
 app.get('/', require('./routes/get'));
 app.post('/', require('./routes/post'));
 app.get('/list', require('./routes/list'));
+app.get('/bilibili', require('./routes/bilibili'));
 app.listen(1207);

+ 3 - 1
nodejs/package.json

@@ -9,6 +9,8 @@
   "dependencies": {
     "express": "^4.13.4",
     "log4js": "^0.6.36",
-    "mongoose": "^4.1.9"
+    "mongoose": "^4.1.9",
+    "node-fetch": "^1.6.3",
+    "xml2js": "^0.4.17"
   }
 }

+ 65 - 0
nodejs/routes/bilibili.js

@@ -0,0 +1,65 @@
+var url = require('url');
+var logger = require('../tools/logger');
+var fetch = require('node-fetch');
+var parseString = require('xml2js').parseString;
+
+module.exports = function (req, res) {
+    var ip = req.headers['x-forwarded-for'] ||
+        req.connection.remoteAddress ||
+        req.socket.remoteAddress ||
+        req.connection.socket.remoteAddress;
+    logger.info(`bilibili form IP: ${ip}`);
+
+    var query = url.parse(req.url,true).query;
+    var aid = query.aid;
+    var dan = {
+        code: 1,
+        danmaku: []
+    };
+
+    function addZero(str, length){
+        return new Array(length - str.length + 1).join("0") + str;
+    }
+
+    fetch(`http://www.bilibili.com/widget/getPageList?aid=${aid}`).then(
+        response => response.json()
+    ).then((data) => {
+        fetch(`http://comment.bilibili.com/${data[0].cid}.xml`).then(
+            response => response.text()
+        ).then((data) => {
+                parseString(data, function (err, result) {
+                    var danOriginal = result.i.d;
+                    for (var i = 0; i < danOriginal.length; i++) {
+                        console.log(danOriginal[i].$.p);
+                        var info = danOriginal[i].$.p.split(',');
+                        console.log(info);
+                        var type = '';
+                        if (info[1] === '4') {
+                            type = 'bottom';
+                        }
+                        else if (info[1] === '5') {
+                            type = 'top';
+                        }
+                        else {
+                            type = 'right';
+                        }
+                        var danOne = {
+                            author: 'bilibili' + info[6],
+                            time: info[0],
+                            text: danOriginal[i]._,
+                            color: '#' + addZero(parseInt(info[3]).toString(16), 6),
+                            type: type
+                        };
+                        dan.danmaku.push(danOne);
+                    }
+                    res.send(JSON.stringify(dan));
+                });
+            }
+        ).catch(
+            e => console.log("获取弹幕失败", e)
+        );
+    }
+    ).catch(
+        e => console.log("获取cid失败", e)
+    );
+};

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "dplayer",
-  "version": "1.0.11",
+  "version": "1.1.0",
   "description": "Wow, such a lovely HTML5 danmaku video player",
   "main": "dist/DPlayer.min.js",
   "scripts": {

+ 41 - 10
src/DPlayer.js

@@ -1,4 +1,4 @@
-console.log("\n %c DPlayer 1.0.11 %c http://dplayer.js.org \n\n","color: #fadfa3; background: #030307; padding:5px 0;","background: #fadfa3; padding:5px 0;");
+console.log("\n %c DPlayer 1.1.0 %c http://dplayer.js.org \n\n","color: #fadfa3; background: #030307; padding:5px 0;","background: #fadfa3; padding:5px 0;");
 
 require('./DPlayer.scss');
 
@@ -860,7 +860,7 @@ class DPlayer {
                 if (item && item.length) {
                     for (let j = 0; j < item.length; j++) {
                         const danRight = danItemRight(item[j]) - 10;
-                        if (danRight <= danWidth - (tmp * danSpeed(item[j])) || danRight <= 0) {
+                        if (danRight <= danWidth - (tmp * danSpeed(item[j].offsetWidth)) || danRight <= 0) {
                             break;
                         }
                         if (j === item.length - 1) {
@@ -940,15 +940,46 @@ class DPlayer {
                             alert(response.msg);
                         }
                         else {
-                            this.dan = response.danmaku.sort((a, b) => a.time - b.time);
-                            this.element.getElementsByClassName('dplayer-danloading')[0].style.display = 'none';
-
-                            // autoplay
-                            if (this.option.autoplay && !isMobile) {
-                                this.play();
+                            if (this.option.danmaku.addition) {
+                                xhr.onreadystatechange = () => {
+                                    if (xhr.readyState === 4) {
+                                        if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
+                                            const response2 = JSON.parse(xhr.responseText);
+                                            if (response2.code !== 1) {
+                                                alert(response2.msg);
+                                            }
+                                            else {
+                                                this.dan = response.danmaku.concat(response2.danmaku).sort((a, b) => a.time - b.time);
+                                                this.element.getElementsByClassName('dplayer-danloading')[0].style.display = 'none';
+
+                                                // autoplay
+                                                if (this.option.autoplay && !isMobile) {
+                                                    this.play();
+                                                }
+                                                else if (isMobile) {
+                                                    this.pause();
+                                                }
+                                            }
+                                        }
+                                        else {
+                                            console.log('Request was unsuccessful: ' + xhr.status);
+                                        }
+                                    }
+                                };
+                                xhr.open('get', this.option.danmaku.addition[0], true);
+                                xhr.send(null);
                             }
-                            else if (isMobile) {
-                                this.pause();
+                            else {
+                                this.dan = response.danmaku.sort((a, b) => a.time - b.time);
+                                this.element.getElementsByClassName('dplayer-danloading')[0].style.display = 'none';
+
+                                // autoplay
+                                if (this.option.autoplay && !isMobile) {
+                                    this.play();
+                                }
+                                else if (isMobile) {
+                                    this.pause();
+                                }
                             }
                         }
                     }

Some files were not shown because too many files changed in this diff