// ==UserScript==
// @name b站 - 同步看视频 - 暂时关闭,需要此功能进群@
// @namespace https://github.com/your_username
// @license All Rights Reserved
// @version 1.0.0
// @description bilibili视频页面,进入同一个房间,视频进度条和房间内的人互相同步
// @author 会飞的蛋蛋面
// @match *://www.bilibili.com/video/*
// @grant GM_xmlhttpRequest
// @license All Rights Reserved
// @require https://code.jquery.com/jquery-3.6.4.slim.min.js
// @require https://cdn.bootcdn.net/ajax/libs/vue/2.7.14/vue.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/vuex/2.5.0/vuex.min.js
// @require https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/index.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/fingerprintjs2/2.1.0/fingerprint2.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js
// @run-at document-start
// ==/UserScript==
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ 376:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function (resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = this && this.__generator || function (thisArg, body) {
var _ = {
label: 0,
sent: function sent() {
if (t[0] & 1) throw t[1];
return t[1];
},
trys: [],
ops: []
},
f,
y,
t,
g;
return g = {
next: verb(0),
"throw": verb(1),
"return": verb(2)
}, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
return this;
}), g;
function verb(n) {
return function (v) {
return step([n, v]);
};
}
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return {
value: op[1],
done: false
};
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2]) _.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
} catch (e) {
op = [6, e];
y = 0;
} finally {
f = t = 0;
}
if (op[0] & 5) throw op[1];
return {
value: op[0] ? op[1] : void 0,
done: true
};
}
};
var __values = this && this.__values || function (o) {
var s = typeof Symbol === "function" && Symbol.iterator,
m = s && o[s],
i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function next() {
if (o && i >= o.length) o = void 0;
return {
value: o && o[i++],
done: !o
};
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __read = this && this.__read || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o),
r,
ar = [],
e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
} catch (error) {
e = {
error: error
};
} finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
} finally {
if (e) throw e.error;
}
}
return ar;
};
var __importDefault = this && this.__importDefault || function (mod) {
return mod && mod.__esModule ? mod : {
"default": mod
};
};
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.Client = void 0;
var EventReplyDispatcher_1 = __webpack_require__(508);
var store_1 = __importDefault(__webpack_require__(527));
var Client = /** @class */function () {
function Client() {
var _this = this;
this.listenerMap = new Map();
// 监听连接消息
var messageListener = function messageListener(event) {
var eventReplyMessage = JSON.parse(event.data);
console.log(eventReplyMessage);
EventReplyDispatcher_1.EventReplyDispatcher.getInstance().handleEvent(eventReplyMessage); // 分发message
};
// 监听连接关闭事件
var closeListener = function closeListener(event) {
console.log("WebSocket closed, code: " + event.code + ", reason: " + event.reason);
_this.reconnect(); // 连接关闭后尝试重连
};
this.listenerMap.set("message", messageListener);
this.listenerMap.set("close", closeListener);
Client.instance = this;
}
Client.getInstance = function () {
return Client.instance || new Client();
};
/**
* 发送数据
* @param message 要发送的数据
*/
Client.prototype.send = function (message) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
// 没起名字,先不建立连接
if (!store_1["default"].state.createNickname) {
return [2 /*return*/];
}
return [4 /*yield*/, this.connect()];
case 1:
_a.sent();
message.memberId = localStorage.getItem('memberId') + "";
this.socket.send(JSON.stringify(message));
return [2 /*return*/];
}
});
});
};
/**
* 关闭连接
*/
Client.prototype.close = function () {
var e_1, _a;
try {
for (var _b = __values(this.listenerMap), _c = _b.next(); !_c.done; _c = _b.next()) {
var _d = __read(_c.value, 2),
key = _d[0],
value = _d[1];
this.socket.removeEventListener(key, value); // 移除监听事件
}
} catch (e_1_1) {
e_1 = {
error: e_1_1
};
} finally {
try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
} finally {
if (e_1) throw e_1.error;
}
}
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
this.socket.close();
}
};
/**
* 建立连接
*/
Client.prototype.connect = function () {
return __awaiter(this, void 0, void 0, function () {
var _a, _b, _c, key, value;
var e_2, _d;
var _this = this;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// 已经存在连接
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
return [2 /*return*/];
}
this.socket = new WebSocket("wss://150.158.150.183:9090/enjoy");
// this.socket = new WebSocket("wss://127.0.0.1:9090/enjoy");
return [4 /*yield*/, new Promise(function (resolve) {
_this.socket.addEventListener("open", function () {
console.log("WebSocket connection established!");
resolve();
});
})];
case 1:
// this.socket = new WebSocket("wss://127.0.0.1:9090/enjoy");
_e.sent();
try {
for (_a = __values(this.listenerMap), _b = _a.next(); !_b.done; _b = _a.next()) {
_c = __read(_b.value, 2), key = _c[0], value = _c[1];
this.socket.addEventListener(key, value); // 添加监听事件
}
} catch (e_2_1) {
e_2 = {
error: e_2_1
};
} finally {
try {
if (_b && !_b.done && (_d = _a["return"])) _d.call(_a);
} finally {
if (e_2) throw e_2.error;
}
}
return [2 /*return*/];
}
});
});
};
/**
* 心跳包检测
*/
Client.prototype.startHeartbeatCheck = function () {
var _this = this;
var heartbeatInterval = 30000; // 心跳包发送间隔,单位:毫秒
var sendHeartbeat = function sendHeartbeat() {
if (_this.socket && _this.socket.readyState === WebSocket.OPEN) {
var heartbeatData = {
eventType: "heartbeat"
};
_this.send(heartbeatData);
}
};
var heartbeatTimer = setInterval(sendHeartbeat, heartbeatInterval);
// 监听连接关闭事件,清除心跳定时器
this.socket.addEventListener("close", function () {
clearInterval(heartbeatTimer);
});
};
/**
* 断线重连
*/
Client.prototype.reconnect = function () {
var _this = this;
var reconnectInterval = 5000; // 重连间隔,单位:毫秒
var reconnect = function reconnect() {
if (_this.socket && _this.socket.readyState === WebSocket.CLOSED) {
console.log("Reconnecting...");
_this.connect().then(function () {
console.log("Reconnect Success");
var reconnect = {
eventType: "reconnect"
};
_this.send(reconnect);
});
}
};
setTimeout(reconnect, reconnectInterval);
};
return Client;
}();
exports.Client = Client;
/***/ }),
/***/ 508:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.EventReplyDispatcher = void 0;
var EventReplyDispatcher = /** @class */function () {
function EventReplyDispatcher() {
this.eventHandlers = new Map();
EventReplyDispatcher.instance = this;
}
EventReplyDispatcher.getInstance = function () {
return EventReplyDispatcher.instance || new EventReplyDispatcher();
};
EventReplyDispatcher.prototype.registerEventHandler = function (eventType, eventHandler) {
this.eventHandlers.set(eventType, eventHandler);
};
/**
* 处理事件
* @param reply 事件对象
*/
EventReplyDispatcher.prototype.handleEvent = function (reply) {
var eventHandler = this.eventHandlers.get(reply.eventType);
if (eventHandler) {
if (reply.code === 200) {
eventHandler(reply);
} else {
alert(reply.msg);
}
} else {
console.log("\u672A\u6CE8\u518C\u4E8B\u4EF6\u7C7B\u578B\u7684\u4E8B\u4EF6\u5904\u7406\u5668\uFF1A".concat(reply.eventType));
}
};
return EventReplyDispatcher;
}();
exports.EventReplyDispatcher = EventReplyDispatcher;
/***/ }),
/***/ 434:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
var __webpack_unused_export__;
__webpack_unused_export__ = ({
value: true
});
exports.L = void 0;
var client_1 = __webpack_require__(376);
var EventReplyDispatcher_1 = __webpack_require__(508);
var element_ui_1 = __webpack_require__(959);
var VideoController = /** @class */function () {
function VideoController() {
this.isCallBackTriggered = false; // 标识是否回调触发,是否是房间其他人触发
this.videoTimeupdateFlag = false; // 拖动会触发播放事件,不能和播放用同一个flag
this.video = $(".bpx-player-video-wrap video"); // 寻找 class 为 bpx-player-video-wrap 的元素下的 bwp-video 子元素
// edge浏览器有shadow保护
// if (this.video == null) {
// // @ts-ignore
// this.video = document.querySelector(".bpx-player-video-wrap bwp-video").shadowRoot.querySelector("video");
// }
this.registerEventReply();
this.bindEventListeners();
VideoController.instance = this;
}
VideoController.getInstance = function () {
return VideoController.instance || new VideoController();
};
// 注册响应触发事件
VideoController.prototype.registerEventReply = function () {
var _this = this;
var replyEventDispatcher = EventReplyDispatcher_1.EventReplyDispatcher.getInstance();
replyEventDispatcher.registerEventHandler("videoPlay", function (reply) {
_this.isCallBackTriggered = true;
_this.video[0].play();
(0, element_ui_1.Notification)({
title: '播放',
message: reply.msg + "",
duration: 2000
});
});
replyEventDispatcher.registerEventHandler("videoPause", function (reply) {
_this.isCallBackTriggered = true;
_this.video[0].pause();
(0, element_ui_1.Notification)({
title: '暂停',
message: reply.msg + "",
duration: 2000
});
});
replyEventDispatcher.registerEventHandler("videoTimeupdate", function (reply) {
_this.videoTimeupdateFlag = true;
_this.video.prop("currentTime", reply.data.currentTime);
(0, element_ui_1.Notification)({
title: '视频拖动',
message: reply.msg + "",
duration: 2000
});
});
};
// 绑定事件监听器
VideoController.prototype.bindEventListeners = function () {
var _this = this;
var client = client_1.Client.getInstance();
// 视频播放
$(this.video).on("play", function () {
if (_this.isCallBackTriggered) {
// 如果是脚本触发,忽略该事件
_this.isCallBackTriggered = false; // 重置标识为 false
return;
}
var send = {
eventType: "videoPlay"
};
client.send(send).then();
});
// 视频暂停
$(this.video).on("pause", function () {
if (_this.isCallBackTriggered) {
_this.isCallBackTriggered = false; // 重置标识为 false
return;
}
var send = {
eventType: "videoPause"
};
client.send(send).then();
});
// 视频进度条改变
$(this.video).on("seeked", function () {
if (_this.videoTimeupdateFlag) {
_this.videoTimeupdateFlag = false; // 重置标识为 false
return;
}
var send = {
eventType: "videoTimeupdate",
message: {
currentTime: _this.video.prop("currentTime")
}
};
client.send(send).then();
});
// 换视频
$(this.video).on("loadedmetadata", function () {
var url = new URL(window.location.href);
var pathname = url.pathname;
var bv = pathname.substring(pathname.lastIndexOf("/") + 1).split("?")[0]; // 从pathname中提取BV号
var p = url.searchParams.get("p"); // 获取P参数
var bvAndP = !p || p === "1" ? bv : "".concat(bv, "?p=").concat(p); // 拼接BV号和P参数
var send = {
eventType: "videoReload",
message: {
"bv": bvAndP
}
};
client.send(send);
});
};
// 生成UUID,用于标识每一个事件
VideoController.prototype.generateUUID = function () {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0,
v = c === "x" ? r : r & 0x3 | 0x8;
return v.toString(16);
});
};
return VideoController;
}();
exports.L = VideoController;
/***/ }),
/***/ 527:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __importDefault = this && this.__importDefault || function (mod) {
return mod && mod.__esModule ? mod : {
"default": mod
};
};
Object.defineProperty(exports, "__esModule", ({
value: true
}));
var vue_1 = __importDefault(__webpack_require__(311));
var vuex_1 = __importDefault(__webpack_require__(294));
// @ts-ignore
vue_1["default"].use(vuex_1["default"]);
var store = {
state: {
createNickname: false
},
mutations: {
createNickname: function createNickname(state, value) {
state.createNickname = value;
}
}
};
exports["default"] = new vuex_1["default"].Store(store);
/***/ }),
/***/ 959:
/***/ ((module) => {
"use strict";
module.exports = ELEMENT;
/***/ }),
/***/ 311:
/***/ ((module) => {
"use strict";
module.exports = Vue;
/***/ }),
/***/ 294:
/***/ ((module) => {
"use strict";
module.exports = Vuex;
/***/ }),
/***/ 61:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
var _typeof = (__webpack_require__(698)["default"]);
function _regeneratorRuntime() {
"use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
module.exports = _regeneratorRuntime = function _regeneratorRuntime() {
return exports;
}, module.exports.__esModule = true, module.exports["default"] = module.exports;
var exports = {},
Op = Object.prototype,
hasOwn = Op.hasOwnProperty,
defineProperty = Object.defineProperty || function (obj, key, desc) {
obj[key] = desc.value;
},
$Symbol = "function" == typeof Symbol ? Symbol : {},
iteratorSymbol = $Symbol.iterator || "@@iterator",
asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
function define(obj, key, value) {
return Object.defineProperty(obj, key, {
value: value,
enumerable: !0,
configurable: !0,
writable: !0
}), obj[key];
}
try {
define({}, "");
} catch (err) {
define = function define(obj, key, value) {
return obj[key] = value;
};
}
function wrap(innerFn, outerFn, self, tryLocsList) {
var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
generator = Object.create(protoGenerator.prototype),
context = new Context(tryLocsList || []);
return defineProperty(generator, "_invoke", {
value: makeInvokeMethod(innerFn, self, context)
}), generator;
}
function tryCatch(fn, obj, arg) {
try {
return {
type: "normal",
arg: fn.call(obj, arg)
};
} catch (err) {
return {
type: "throw",
arg: err
};
}
}
exports.wrap = wrap;
var ContinueSentinel = {};
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {}
var IteratorPrototype = {};
define(IteratorPrototype, iteratorSymbol, function () {
return this;
});
var getProto = Object.getPrototypeOf,
NativeIteratorPrototype = getProto && getProto(getProto(values([])));
NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
function defineIteratorMethods(prototype) {
["next", "throw", "return"].forEach(function (method) {
define(prototype, method, function (arg) {
return this._invoke(method, arg);
});
});
}
function AsyncIterator(generator, PromiseImpl) {
function invoke(method, arg, resolve, reject) {
var record = tryCatch(generator[method], generator, arg);
if ("throw" !== record.type) {
var result = record.arg,
value = result.value;
return value && "object" == _typeof(value) && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
invoke("next", value, resolve, reject);
}, function (err) {
invoke("throw", err, resolve, reject);
}) : PromiseImpl.resolve(value).then(function (unwrapped) {
result.value = unwrapped, resolve(result);
}, function (error) {
return invoke("throw", error, resolve, reject);
});
}
reject(record.arg);
}
var previousPromise;
defineProperty(this, "_invoke", {
value: function value(method, arg) {
function callInvokeWithMethodAndArg() {
return new PromiseImpl(function (resolve, reject) {
invoke(method, arg, resolve, reject);
});
}
return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
}
});
}
function makeInvokeMethod(innerFn, self, context) {
var state = "suspendedStart";
return function (method, arg) {
if ("executing" === state) throw new Error("Generator is already running");
if ("completed" === state) {
if ("throw" === method) throw arg;
return doneResult();
}
for (context.method = method, context.arg = arg;;) {
var delegate = context.delegate;
if (delegate) {
var delegateResult = maybeInvokeDelegate(delegate, context);
if (delegateResult) {
if (delegateResult === ContinueSentinel) continue;
return delegateResult;
}
}
if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
if ("suspendedStart" === state) throw state = "completed", context.arg;
context.dispatchException(context.arg);
} else "return" === context.method && context.abrupt("return", context.arg);
state = "executing";
var record = tryCatch(innerFn, self, context);
if ("normal" === record.type) {
if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
return {
value: record.arg,
done: context.done
};
}
"throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
}
};
}
function maybeInvokeDelegate(delegate, context) {
var methodName = context.method,
method = delegate.iterator[methodName];
if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator["return"] && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel;
var record = tryCatch(method, delegate.iterator, context.arg);
if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
var info = record.arg;
return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel);
}
function pushTryEntry(locs) {
var entry = {
tryLoc: locs[0]
};
1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
}
function resetTryEntry(entry) {
var record = entry.completion || {};
record.type = "normal", delete record.arg, entry.completion = record;
}
function Context(tryLocsList) {
this.tryEntries = [{
tryLoc: "root"
}], tryLocsList.forEach(pushTryEntry, this), this.reset(!0);
}
function values(iterable) {
if (iterable) {
var iteratorMethod = iterable[iteratorSymbol];
if (iteratorMethod) return iteratorMethod.call(iterable);
if ("function" == typeof iterable.next) return iterable;
if (!isNaN(iterable.length)) {
var i = -1,
next = function next() {
for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;
return next.value = undefined, next.done = !0, next;
};
return next.next = next;
}
}
return {
next: doneResult
};
}
function doneResult() {
return {
value: undefined,
done: !0
};
}
return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", {
value: GeneratorFunctionPrototype,
configurable: !0
}), defineProperty(GeneratorFunctionPrototype, "constructor", {
value: GeneratorFunction,
configurable: !0
}), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
var ctor = "function" == typeof genFun && genFun.constructor;
return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
}, exports.mark = function (genFun) {
return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun;
}, exports.awrap = function (arg) {
return {
__await: arg
};
}, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
return this;
}), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
void 0 === PromiseImpl && (PromiseImpl = Promise);
var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
return result.done ? result.value : iter.next();
});
}, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
return this;
}), define(Gp, "toString", function () {
return "[object Generator]";
}), exports.keys = function (val) {
var object = Object(val),
keys = [];
for (var key in object) keys.push(key);
return keys.reverse(), function next() {
for (; keys.length;) {
var key = keys.pop();
if (key in object) return next.value = key, next.done = !1, next;
}
return next.done = !0, next;
};
}, exports.values = values, Context.prototype = {
constructor: Context,
reset: function reset(skipTempReset) {
if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined);
},
stop: function stop() {
this.done = !0;
var rootRecord = this.tryEntries[0].completion;
if ("throw" === rootRecord.type) throw rootRecord.arg;
return this.rval;
},
dispatchException: function dispatchException(exception) {
if (this.done) throw exception;
var context = this;
function handle(loc, caught) {
return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
}
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i],
record = entry.completion;
if ("root" === entry.tryLoc) return handle("end");
if (entry.tryLoc <= this.prev) {
var hasCatch = hasOwn.call(entry, "catchLoc"),
hasFinally = hasOwn.call(entry, "finallyLoc");
if (hasCatch && hasFinally) {
if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
} else if (hasCatch) {
if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
} else {
if (!hasFinally) throw new Error("try statement without catch or finally");
if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
}
}
}
},
abrupt: function abrupt(type, arg) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
var finallyEntry = entry;
break;
}
}
finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
var record = finallyEntry ? finallyEntry.completion : {};
return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
},
complete: function complete(record, afterLoc) {
if ("throw" === record.type) throw record.arg;
return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel;
},
finish: function finish(finallyLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
}
},
"catch": function _catch(tryLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc === tryLoc) {
var record = entry.completion;
if ("throw" === record.type) {
var thrown = record.arg;
resetTryEntry(entry);
}
return thrown;
}
}
throw new Error("illegal catch attempt");
},
delegateYield: function delegateYield(iterable, resultName, nextLoc) {
return this.delegate = {
iterator: values(iterable),
resultName: resultName,
nextLoc: nextLoc
}, "next" === this.method && (this.arg = undefined), ContinueSentinel;
}
}, exports;
}
module.exports = _regeneratorRuntime, module.exports.__esModule = true, module.exports["default"] = module.exports;
/***/ }),
/***/ 698:
/***/ ((module) => {
function _typeof(obj) {
"@babel/helpers - typeof";
return (module.exports = _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
}, module.exports.__esModule = true, module.exports["default"] = module.exports), _typeof(obj);
}
module.exports = _typeof, module.exports.__esModule = true, module.exports["default"] = module.exports;
/***/ }),
/***/ 687:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
// TODO(Babel 8): Remove this file.
var runtime = __webpack_require__(61)();
module.exports = runtime;
// Copied from https://github.com/facebook/regenerator/blob/main/packages/runtime/runtime.js#L736=
try {
regeneratorRuntime = runtime;
} catch (accidentalStrictMode) {
if (typeof globalThis === "object") {
globalThis.regeneratorRuntime = runtime;
} else {
Function("r", "regeneratorRuntime = r")(runtime);
}
}
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
(() => {
"use strict";
;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
// EXTERNAL MODULE: ./node_modules/@babel/runtime/regenerator/index.js
var regenerator = __webpack_require__(687);
var regenerator_default = /*#__PURE__*/__webpack_require__.n(regenerator);
// EXTERNAL MODULE: ./src/logic/VideoController.ts
var VideoController = __webpack_require__(434);
// EXTERNAL MODULE: external "Vue"
var external_Vue_ = __webpack_require__(311);
var external_Vue_default = /*#__PURE__*/__webpack_require__.n(external_Vue_);
// EXTERNAL MODULE: external "ELEMENT"
var external_ELEMENT_ = __webpack_require__(959);
var external_ELEMENT_default = /*#__PURE__*/__webpack_require__.n(external_ELEMENT_);
;// CONCATENATED MODULE: ./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/App.vue?vue&type=template&id=814da472&
var render = function render() {
var _vm = this,
_c = _vm._self._c;
return _c("div", [_c("div", {
directives: [{
name: "show",
rawName: "v-show",
value: _vm.nicknameShow,
expression: "nicknameShow"
}]
}, [_c("el-input", {
staticStyle: {
width: "128px"
},
attrs: {
size: "mini",
placeholder: "起个名字吧"
},
model: {
value: _vm.nickname,
callback: function callback($$v) {
_vm.nickname = $$v;
},
expression: "nickname"
}
}), _vm._v(" "), _c("el-button", {
attrs: {
size: "mini"
},
on: {
click: function click($event) {
return _vm.nicknameSubmit();
}
}
}, [_vm._v("OK")])], 1), _vm._v(" "), _c("el-popover", {
attrs: {
placement: "top",
width: "160",
height: "60"
},
scopedSlots: _vm._u([{
key: "reference",
fn: function fn() {
return [_c("el-button", {
directives: [{
name: "show",
rawName: "v-show",
value: _vm.joinRoomShow,
expression: "joinRoomShow"
}],
attrs: {
size: "mini"
},
on: {
click: function click() {
_vm.joinRoomShow = true;
}
}
}, [_vm._v("加入房间")])];
},
proxy: true
}]),
model: {
value: _vm.visible,
callback: function callback($$v) {
_vm.visible = $$v;
},
expression: "visible"
}
}, [_c("el-input", {
staticStyle: {
width: "auto"
},
attrs: {
size: "mini",
placeholder: "房间号(纯数字)"
},
on: {
input: _vm.validateRoomId
},
model: {
value: _vm.roomId,
callback: function callback($$v) {
_vm.roomId = $$v;
},
expression: "roomId"
}
}), _vm._v(" "), _c("div", {
staticStyle: {
"text-align": "right",
"margin-top": "8px"
}
}, [_c("el-button", {
attrs: {
size: "mini"
},
on: {
click: function click($event) {
return _vm.joinRoomSend();
}
}
}, [_vm._v("确定")]), _vm._v(" "), _c("el-button", {
attrs: {
size: "mini"
},
on: {
click: function click($event) {
_vm.visible = false;
}
}
}, [_vm._v("取消")])], 1)], 1), _vm._v(" "), _c("div", {
directives: [{
name: "show",
rawName: "v-show",
value: _vm.createRoomShow,
expression: "createRoomShow"
}],
staticStyle: {
display: "inline"
}
}, [_c("el-button", {
attrs: {
size: "mini"
},
on: {
click: _vm.createRoomSend
}
}, [_vm._v("创建房间")])], 1), _vm._v(" "), _c("div", {
directives: [{
name: "show",
rawName: "v-show",
value: _vm.exitRoomShow,
expression: "exitRoomShow"
}]
}, [_c("el-tag", {
attrs: {
size: "mini",
effect: "plain"
}
}, [_vm._v("房间号:" + _vm._s(_vm.roomId))]), _vm._v(" "), _c("el-button", {
attrs: {
size: "mini"
},
on: {
click: _vm.exitRoom
}
}, [_vm._v("退出房间")])], 1)], 1);
};
var staticRenderFns = [];
render._withStripped = true;
;// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=814da472&
// EXTERNAL MODULE: ./src/event/EventReplyDispatcher.ts
var EventReplyDispatcher = __webpack_require__(508);
// EXTERNAL MODULE: ./src/client/index.ts
var client = __webpack_require__(376);
// EXTERNAL MODULE: ./src/store/index.ts
var store = __webpack_require__(527);
var store_default = /*#__PURE__*/__webpack_require__.n(store);
;// CONCATENATED MODULE: ./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/App.vue?vue&type=script&lang=js&
/* harmony default export */ const Appvue_type_script_lang_js_ = ({
name: "App",
data: function data() {
return {
visible: true,
nicknameShow: true,
joinRoomShow: false,
createRoomShow: false,
exitRoomShow: false,
nickname: '',
roomId: '',
webSocketClient: null
};
},
created: function created() {
var _this = this;
this.webSocketClient = client.Client.getInstance();
var eventDispatcher = EventReplyDispatcher.EventReplyDispatcher.getInstance();
eventDispatcher.registerEventHandler("createNickname", function () {
_this.nicknameShow = false;
_this.joinRoomShow = true;
_this.createRoomShow = true;
});
eventDispatcher.registerEventHandler("createRoom", function (reply) {
_this.createRoomShow = false;
_this.joinRoomShow = false;
_this.exitRoomShow = true;
_this.roomId = reply.data.roomId;
});
eventDispatcher.registerEventHandler("joinRoom", function (reply) {
_this.visible = false;
_this.joinRoomShow = false;
_this.createRoomShow = false;
_this.exitRoomShow = true;
if (reply.code !== 200) {
_this.$message.warning(reply.msg);
}
});
eventDispatcher.registerEventHandler("exitRoom", function (reply) {
_this.webSocketClient.close();
if (reply.code !== 200) {
_this.$message.warning(reply.msg);
}
});
eventDispatcher.registerEventHandler("offLine", function (reply) {
_this.webSocketClient.close();
_this.nicknameShow = true;
_this.joinRoomShow = false;
_this.createRoomShow = false;
_this.exitRoomShow = false;
_this.nickname = '';
_this.roomId = '';
if (reply.code !== 200) {
_this.$message.warning(reply.msg);
}
});
// 浏览器退出监听
window.addEventListener('beforeunload', function () {
return _this.exitRoom();
});
},
methods: {
nicknameSubmit: function nicknameSubmit() {
var _this2 = this;
return _asyncToGenerator( /*#__PURE__*/regenerator_default().mark(function _callee() {
var url, bv, p, bvAndP, send;
return regenerator_default().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
if (!(!_this2.nickname && _this2.nickname.trim().length === 0)) {
_context.next = 3;
break;
}
alert('请输入昵称');
return _context.abrupt("return");
case 3:
// 获取bv号
url = new URL(window.location.href);
bv = url.pathname.split('/')[2]; // 从pathname中提取BV号
p = url.searchParams.get("p"); // 获取P参数
bvAndP = !p || p === "1" ? bv : "".concat(bv, "?p=").concat(p); // 拼接BV号和P参数
send = {
eventType: "createNickname",
message: {
"nickname": _this2.nickname,
"bv": bvAndP
}
};
store_default().commit('createNickname', true);
_this2.webSocketClient.send(send);
case 10:
case "end":
return _context.stop();
}
}, _callee);
}))();
},
// 房间号校验
validateRoomId: function validateRoomId() {
// 使用正则表达式校验输入是否为数字
if (!/^\d*$/.test(this.roomId)) {
this.roomId = this.roomId.replace(/\D/g, ''); // 移除非数字字符
}
},
joinRoomSend: function joinRoomSend() {
if (!this.roomId || !/^\d+$/.test(this.roomId)) {
alert('请输入正确的房间号');
return;
}
var event = {
eventType: 'joinRoom',
message: {
roomId: this.roomId
}
};
this.webSocketClient.send(event);
},
exitRoom: function exitRoom() {
var event = {
eventType: 'exitRoom',
message: {
roomId: this.roomId
}
};
this.webSocketClient.send(event);
this.joinRoomShow = true;
this.createRoomShow = true;
this.exitRoomShow = false;
this.roomId = '';
},
createRoomSend: function createRoomSend() {
var event = {
eventType: 'createRoom'
};
this.webSocketClient.send(event);
},
generateUUID: function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0,
v = c === 'x' ? r : r & 0x3 | 0x8;
return v.toString(16);
});
}
}
});
;// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
/* harmony default export */ const src_Appvue_type_script_lang_js_ = (Appvue_type_script_lang_js_);
;// CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js
/* globals __VUE_SSR_CONTEXT__ */
// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).
// This module is a runtime utility for cleaner component module output and will
// be included in the final webpack user bundle.
function normalizeComponent(
scriptExports,
render,
staticRenderFns,
functionalTemplate,
injectStyles,
scopeId,
moduleIdentifier /* server only */,
shadowMode /* vue-cli only */
) {
// Vue.extend constructor export interop
var options =
typeof scriptExports === 'function' ? scriptExports.options : scriptExports
// render functions
if (render) {
options.render = render
options.staticRenderFns = staticRenderFns
options._compiled = true
}
// functional template
if (functionalTemplate) {
options.functional = true
}
// scopedId
if (scopeId) {
options._scopeId = 'data-v-' + scopeId
}
var hook
if (moduleIdentifier) {
// server build
hook = function (context) {
// 2.3 injection
context =
context || // cached call
(this.$vnode && this.$vnode.ssrContext) || // stateful
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
// 2.2 with runInNewContext: true
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
context = __VUE_SSR_CONTEXT__
}
// inject component styles
if (injectStyles) {
injectStyles.call(this, context)
}
// register component module identifier for async chunk inferrence
if (context && context._registeredComponents) {
context._registeredComponents.add(moduleIdentifier)
}
}
// used by ssr in case component is cached and beforeCreate
// never gets called
options._ssrRegister = hook
} else if (injectStyles) {
hook = shadowMode
? function () {
injectStyles.call(
this,
(options.functional ? this.parent : this).$root.$options.shadowRoot
)
}
: injectStyles
}
if (hook) {
if (options.functional) {
// for template-only hot-reload because in that case the render fn doesn't
// go through the normalizer
options._injectStyles = hook
// register for functional component in vue file
var originalRender = options.render
options.render = function renderWithStyleInjection(h, context) {
hook.call(context)
return originalRender(h, context)
}
} else {
// inject component registration as beforeCreate hook
var existing = options.beforeCreate
options.beforeCreate = existing ? [].concat(existing, hook) : [hook]
}
}
return {
exports: scriptExports,
options: options
}
}
;// CONCATENATED MODULE: ./src/App.vue
/* normalize component */
;
var component = normalizeComponent(
src_Appvue_type_script_lang_js_,
render,
staticRenderFns,
false,
null,
null,
null
)
/* harmony default export */ const App = (component.exports);
;// CONCATENATED MODULE: ./src/main.js
// ==UserScript==
// @name b站视频进度条和别人一起同步观看
// @namespace https://github.com/your_username
// @license All Rights Reserved
// @version 0.3.5
// @description 必须先访问 https://150.158.150.183:9090/sslCheck 同意证书,不然按钮点不动
// @author 会飞的蛋蛋面,495033653@qq.com
// @match *://www.bilibili.com/video/*
// @grant GM_xmlhttpRequest
// @license All Rights Reserved
// @require https://code.jquery.com/jquery-3.6.4.slim.min.js
// @require https://cdn.bootcdn.net/ajax/libs/vue/2.7.14/vue.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/vuex/2.5.0/vuex.min.js
// @require https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/index.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/fingerprintjs2/2.1.0/fingerprint2.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js
// @require file:E:\Project\Tampermonkey\bili-together\dist\main.js
// @run-at document-start
// ==/UserScript==
_asyncToGenerator( /*#__PURE__*/regenerator_default().mark(function _callee() {
'use strict';
var loadElement, memberId, app;
return regenerator_default().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
loadElement = function _loadElement() {
$('<link>').attr({
rel: 'stylesheet',
type: 'text/css',
href: 'https://cdn.jsdelivr.net/npm/element-ui@2.15.13/lib/theme-chalk/index.min.css'
}).appendTo(document.documentElement);
};
Element.prototype._attachShadow = Element.prototype.attachShadow;
Element.prototype.attachShadow = function () {
return this._attachShadow({
mode: 'open'
});
};
// 加载element-ui
loadElement();
// 延迟2秒执行
_context.next = 6;
return new Promise(function (resolve) {
return setTimeout(resolve, 5000);
});
case 6:
$(".video-info-detail").css("height", "28px");
// 全局唯一id
_context.next = 9;
return new Promise(function (resolve) {
return Fingerprint2.get(function (components) {
return resolve(Fingerprint2.x64hash128(components.map(function (pair) {
return pair.value;
}).join(), 31));
});
});
case 9:
memberId = _context.sent;
localStorage.setItem("memberId", memberId);
// 初始化框架
external_Vue_default().use((external_ELEMENT_default()));
app = new (external_Vue_default())({
render: function render(h) {
return h(App);
}
}).$mount();
$(".video-info-detail-list").append(app.$el);
VideoController/* VideoController.getInstance */.L.getInstance();
case 15:
case "end":
return _context.stop();
}
}, _callee);
}))();
})();
/******/ })()
;
//# sourceMappingURL=main.js.map