multi_embed_player 3.0.1 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,451 +1,1035 @@
1
- import { PlayerState } from '../types';
1
+ "use strict";
2
+ // Notice! This file JSDOC is generated by gitHub copilot.
3
+ // So some of this JSDOC is not correct.
4
+ // Please refer to documents https://multi-embed-player.pages.dev/docs/reference/iframe_class/#mep_bilibili-class
5
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
6
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
7
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
8
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
9
+ };
10
+ var _mep_bilibili_instances, _mep_bilibili_image_player, _mep_bilibili_set_pause_transparent, _mep_bilibili_add_loading_animation, _mep_bilibili_remove_loading_animation, _mep_bilibili_add_error_description, _mep_bilibili_add_player_css_style, _mep_bilibili_add_local_storage_error_description, _mep_bilibili_element_constructor, _mep_bilibili_checkLocalstorage, _mep_bilibili_observe_load_time, _mep_bilibili_observe_end_time, _mep_bilibili_video_loader, _mep_bilibili_getVideodataApi, _mep_bilibili_messageListener;
2
11
  /**
3
12
  * Class representing a Bilibili player.
13
+ * @class
14
+ * @classdesc This class provides methods to control a Bilibili player and handle errors.
15
+ * @property {boolean} localStorageCheck - A flag indicating whether the local storage is accessible.
16
+ * @property {boolean} mep_extension_bilibili - A flag indicating whether the extension is installed.
17
+ * @property {string} api_endpoint - The API endpoint for the player.
18
+ * @property {string} no_extention_error - The error message to display when the extension is not installed.
19
+ * @property {string} player_base_url - The base URL for the player.
20
+ * @property {Object} bilibili_api_cache - The cache for the Bilibili API.
21
+ * @property {string} cors_proxy - The CORS proxy for the player.
22
+ * @constructor
23
+ * @param {HTMLElement|String} replacing_element - The element to replace with the player or the ID of the element to replace with the player.
24
+ * @param {Object} content - The content to display in the player.
25
+ * @param {Function} player_set_event_function - The function to set the player event.
4
26
  */
5
- export class mep_bilibili {
27
+ class mep_bilibili {
6
28
  constructor(replacing_element, content, player_set_event_function) {
7
- this.autoplay = 0;
29
+ _mep_bilibili_instances.add(this);
30
+ this.player = document.createElement("iframe");
31
+ this.play_control_wrap = false;
32
+ this.loading = false;
33
+ this.before_mute_volume = 100;
34
+ this.content_width = 0;
35
+ this.content_height = 0;
36
+ this.videoid = "";
37
+ this.original_replacing_element = document.createElement("div");
38
+ this.seek_time = 0;
39
+ this.seek_time_used = false;
40
+ this.noextention_count_stop = 0;
41
+ this.state = { getPlayerState: "0" };
42
+ this.apicache = {};
43
+ this.no_extention_pause = false;
8
44
  this.startSeconds = 0;
45
+ this.innerStartSeconds = 0;
46
+ this.autoplay_flag = false;
47
+ this.displayCommentMode = false;
48
+ this.fastload = false;
49
+ this.no_extention_estimate_stop = false;
50
+ this.play_start_time = 0;
9
51
  this.endSeconds = -1;
10
- this.displayComment = 1;
11
- this.fastLoad = 0;
12
- this.play_control_wrap = 1;
13
- this.playerState = PlayerState.UNSTARTED;
14
- this.currentTime = 0;
15
- this.duration = 0;
16
- this.volume = 100;
17
- this.muted = false;
18
- this.initialize_player_base_url();
19
- this.element_constructor(replacing_element, content, player_set_event_function);
20
- }
21
- /**
22
- * Initialize player base URL based on browser.
23
- */
24
- initialize_player_base_url() {
25
- if (mep_bilibili.player_base_url === "") {
52
+ this.start_event_count = 0;
53
+ this.end_event_count = 0;
54
+ if (mep_bilibili.player_base_url == "") {
26
55
  const ua = navigator.userAgent;
27
- if (ua.indexOf("Firefox") !== -1 || ua.indexOf("Edg") !== -1) {
28
- mep_bilibili.player_base_url = "https://www.bilibili.com/blackboard/webplayer/embed-old.html?";
56
+ if (ua.indexOf("Firefox") != -1 || ua.indexOf("Edg") != -1) {
57
+ mep_bilibili.player_base_url = "https://www.bilibili.com/blackboard/webplayer/embed-old.html?"; //fast
29
58
  }
30
59
  else {
31
- mep_bilibili.player_base_url = "https://player.bilibili.com/player.html?";
60
+ mep_bilibili.player_base_url = "https://player.bilibili.com/player.html?"; //load often lazy in japan but this can mute auto play
32
61
  }
33
62
  }
63
+ (async () => {
64
+ await __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_element_constructor).call(this, replacing_element, content, player_set_event_function);
65
+ })();
34
66
  }
35
67
  /**
36
- * Constructor for element setup.
68
+ * Loads the video player with the specified content in cue mode.
69
+ * @param {Object} content - The content to display in the player.
37
70
  */
38
- async element_constructor(replacing_element, content, player_set_event_function) {
39
- try {
40
- this.player = document.createElement("iframe");
41
- if (typeof player_set_event_function === "function") {
42
- player_set_event_function();
43
- }
44
- let iframe_replace_node;
45
- if (typeof replacing_element === "string") {
46
- const element = document.getElementById(replacing_element);
47
- if (!element) {
48
- throw new Error(`Element with id "${replacing_element}" not found`);
49
- }
50
- iframe_replace_node = element;
71
+ cueVideoById(content) {
72
+ if (content["overwrite"] == undefined) {
73
+ content["overwrite"] = true;
74
+ }
75
+ if (content["startSeconds"] != undefined && content["overwrite"] == true) {
76
+ this.startSeconds = content["startSeconds"];
77
+ }
78
+ if (typeof content.startSeconds !== "undefined") {
79
+ this.innerStartSeconds = parseInt(content.startSeconds.toString());
80
+ }
81
+ else {
82
+ this.innerStartSeconds = 0;
83
+ }
84
+ if (content["endSeconds"] != undefined && content["overwrite"] == true) {
85
+ this.endSeconds = content["endSeconds"];
86
+ }
87
+ this.autoplay_flag = false;
88
+ this.no_extention_pause = true;
89
+ if (content["overwrite"] == true) {
90
+ this.videoid = content["videoId"] || "";
91
+ }
92
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_image_player).call(this);
93
+ }
94
+ /**
95
+ * Loads the video player with the specified content in play mode.
96
+ * @param {Object} content - The content to display in the player.
97
+ */
98
+ loadVideoById(content) {
99
+ if (content["overwrite"] == undefined) {
100
+ content["overwrite"] = true;
101
+ }
102
+ if (content["startSeconds"] != undefined && content["overwrite"] == true) {
103
+ this.startSeconds = content["startSeconds"];
104
+ }
105
+ if (typeof content.startSeconds !== "undefined") {
106
+ this.innerStartSeconds = parseInt(content.startSeconds.toString());
107
+ }
108
+ else {
109
+ this.innerStartSeconds = 0;
110
+ }
111
+ if (content["endSeconds"] != undefined && content["overwrite"] == true) {
112
+ this.endSeconds = content["endSeconds"];
113
+ }
114
+ this.autoplay_flag = true;
115
+ this.no_extention_pause = false;
116
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_video_loader).call(this, content);
117
+ }
118
+ /**
119
+ * Returns the current time of the video.
120
+ * @returns {Promise<number>} - The current time of the video.
121
+ */
122
+ getCurrentTime() {
123
+ if (!window.mep_bilibili.mep_extension_bilibili) {
124
+ if (this.loading) {
125
+ return this.startSeconds;
126
+ }
127
+ else if (!this.seek_time_used) {
128
+ return this.seek_time;
129
+ }
130
+ else if (this.estimate_time != undefined) {
131
+ return this.estimate_time;
51
132
  }
52
133
  else {
53
- iframe_replace_node = replacing_element;
54
- }
55
- this.videoid = content.videoId;
56
- const playerVars = content.playerVars || {};
57
- // Set player variables
58
- this.autoplay = playerVars.autoplay || 0;
59
- this.startSeconds = playerVars.startSeconds || 0;
60
- this.endSeconds = playerVars.endSeconds || -1;
61
- this.displayComment = playerVars.displayComment !== undefined ? playerVars.displayComment : 1;
62
- this.fastLoad = playerVars.fastLoad || 0;
63
- this.play_control_wrap = playerVars.play_control_wrap !== undefined ? playerVars.play_control_wrap : 1;
64
- // Check local storage access
65
- if (mep_bilibili.localStorageCheck === null) {
66
- try {
67
- localStorage.setItem("mep_bilibili_test", "test");
68
- localStorage.removeItem("mep_bilibili_test");
69
- mep_bilibili.localStorageCheck = true;
70
- }
71
- catch {
72
- mep_bilibili.localStorageCheck = false;
73
- this.front_error_code = 2;
74
- this.add_error_description();
75
- return;
76
- }
134
+ return this.startSeconds;
77
135
  }
78
- // Check extension
79
- mep_bilibili.mep_extension_bilibili = localStorage.getItem("mep_extension_bilibili") === "true";
80
- this.add_player_css_style();
81
- this.player.classList.add("mep_bilibili_player");
82
- // Set iframe attributes
83
- this.player.width = String(content.width || 560);
84
- this.player.height = String(content.height || 315);
85
- this.player.allow = "autoplay; fullscreen";
86
- this.player.allowFullscreen = true;
87
- this.player.referrerPolicy = "no-referrer";
88
- // Replace element
89
- iframe_replace_node.replaceWith(this.player);
90
- // Load video
91
- await this.image_player(true);
92
- }
93
- catch (error) {
94
- console.error("Error in element_constructor:", error);
95
- this.front_error_code = 0;
96
- this.add_error_description();
136
+ }
137
+ else {
138
+ return this.state.currentTime || 0;
97
139
  }
98
140
  }
99
141
  /**
100
- * Display image player when paused.
142
+ * Plays the video. If the Bilibili extension is not installed, loads the video with the specified parameters.
143
+ * If the extension is installed, sends a message to the extension to play the video.
101
144
  */
102
- async image_player(first_load = false) {
103
- try {
104
- let exist_img_children = false;
105
- const parent_element = this.player.parentElement;
106
- if (!parent_element)
107
- return;
108
- parent_element.childNodes.forEach((node) => {
109
- if (node.nodeName === "IMG") {
110
- exist_img_children = true;
111
- }
112
- if (node.nodeName === "DIV" && node.classList.contains("mep_bilibili_transparent")) {
113
- node.remove();
114
- }
115
- });
116
- if (!exist_img_children && this.play_control_wrap) {
117
- const img_element = document.createElement("img");
118
- const video_data = await this.getVideodataApi();
119
- img_element.src = video_data.image_base64 || "";
120
- img_element.width = parseInt(this.player.width);
121
- img_element.height = parseInt(this.player.height);
122
- img_element.style.width = "100%";
123
- img_element.style.height = "100%";
124
- img_element.style.objectFit = "cover";
125
- img_element.style.cursor = "pointer";
126
- img_element.addEventListener("click", () => {
127
- this.playVideo();
128
- });
129
- parent_element.prepend(img_element);
130
- }
131
- this.player.hidden = true;
132
- this.player.src = "";
133
- if (first_load) {
134
- this.player.dispatchEvent(new Event("onReady"));
145
+ playVideo() {
146
+ if (!window.mep_bilibili.mep_extension_bilibili) {
147
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_set_pause_transparent).call(this);
148
+ this.no_extention_pause = false;
149
+ this.noextention_count_stop = 0;
150
+ let generate_sorce = { "videoId": this.videoid, "overwrite": false };
151
+ if (this.endSeconds != -1) {
152
+ generate_sorce.endSeconds = this.endSeconds;
153
+ }
154
+ if (this.seek_time != -1 && !this.seek_time_used) {
155
+ this.seek_time_used = true;
156
+ generate_sorce.startSeconds = this.seek_time;
157
+ }
158
+ else if (this.estimate_time != 0) {
159
+ generate_sorce.startSeconds = this.estimate_time;
160
+ }
161
+ else if (this.startSeconds != 0) {
162
+ generate_sorce.startSeconds = this.startSeconds;
135
163
  }
164
+ this.loadVideoById(generate_sorce);
136
165
  }
137
- catch (error) {
138
- console.error("Error in image_player:", error);
166
+ else {
167
+ this.player.contentWindow?.postMessage({ eventName: "play" }, "*");
139
168
  }
140
169
  }
141
170
  /**
142
- * Set pause transparent overlay.
171
+ * Pauses the video playback. If the Bilibili extension is not detected, it replaces the player with an image and stops the play start count interval.
172
+ * @function
143
173
  */
144
- set_pause_transparent() {
145
- let exist_div_children = false;
146
- const parent_element = this.player.parentElement;
147
- if (!parent_element)
148
- return;
149
- parent_element.childNodes.forEach((node) => {
150
- if (node.nodeName === "DIV" && node.classList.contains("mep_bilibili_transparent")) {
151
- exist_div_children = true;
152
- }
153
- });
154
- if (!exist_div_children && this.play_control_wrap) {
155
- const div_element = document.createElement("div");
156
- div_element.classList.add("mep_bilibili_transparent");
157
- div_element.style.width = "100%";
158
- div_element.style.height = "100%";
159
- div_element.style.zIndex = "1";
160
- div_element.style.position = "absolute";
161
- div_element.style.cursor = "pointer";
162
- div_element.addEventListener("click", () => {
163
- this.pauseVideo();
164
- });
165
- parent_element.prepend(div_element);
174
+ pauseVideo() {
175
+ if (!window.mep_bilibili.mep_extension_bilibili) {
176
+ clearInterval(this.play_start_count_interval);
177
+ this.no_extention_pause = true;
178
+ this.noextention_count_stop = 1;
179
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_image_player).call(this);
180
+ this.seek_time = this.estimate_time || 0;
181
+ try {
182
+ this.player.parentElement.deleteEvent();
183
+ }
184
+ catch { }
185
+ }
186
+ else {
187
+ this.player.contentWindow?.postMessage({ eventName: "pause" }, "*");
166
188
  }
167
189
  }
168
190
  /**
169
- * Add loading animation.
191
+ * Seeks to the specified time in the video.
192
+ * @async
193
+ * @param {number} seektime - The time to seek to, in seconds.
170
194
  */
171
- add_loading_animation() {
172
- let exist_mep_load_animation = false;
173
- Array.from(document.head.getElementsByClassName("mep_load_animation")).forEach((element) => {
174
- if (element.nodeName === "STYLE") {
175
- exist_mep_load_animation = true;
176
- }
177
- });
178
- if (!exist_mep_load_animation) {
179
- const style_element = document.createElement("style");
180
- style_element.classList.add("mep_load_animation");
181
- style_element.innerHTML = `
182
- .mep_loading_animation{
183
- border: 12px solid #fafafa;
184
- border-radius: 50%;
185
- border-top: 12px solid #3498db;
186
- width: 100px;
187
- height: 100px;
188
- animation: spin 1s linear infinite;
189
- }
190
- @keyframes spin{
191
- 0%{
192
- transform: rotate(0deg);
193
- }
194
- 100%{
195
- transform: rotate(360deg);
196
- }
197
- }`;
198
- document.head.appendChild(style_element);
199
- }
200
- let exist_animation_div = false;
201
- const parent_element = this.player.parentElement;
202
- if (!parent_element)
203
- return;
204
- parent_element.childNodes.forEach((node) => {
205
- if (node.nodeName === "DIV" && node.classList.contains("mep_loading_animation")) {
206
- exist_animation_div = true;
207
- }
208
- });
209
- if (!exist_animation_div) {
210
- const div_element = document.createElement("div");
211
- div_element.classList.add("mep_loading_animation");
212
- div_element.style.zIndex = "2";
213
- div_element.style.top = "calc(50% - 50px)";
214
- div_element.style.left = "calc(50% - 50px)";
215
- div_element.style.position = "absolute";
216
- parent_element.prepend(div_element);
195
+ async seekTo(seektime) {
196
+ if (!window.mep_bilibili.mep_extension_bilibili) {
197
+ let generate_sorce = { "videoId": this.videoid, "overwrite": false };
198
+ if (this.endSeconds != -1) {
199
+ generate_sorce.endSeconds = this.endSeconds;
200
+ }
201
+ generate_sorce.startSeconds = seektime;
202
+ this.seek_time = seektime;
203
+ this.seek_time_used = false;
204
+ let player_state = await this.getPlayerState();
205
+ if (player_state == 2) {
206
+ this.seek_time_used = true;
207
+ this.loadVideoById(generate_sorce);
208
+ }
209
+ else {
210
+ this.estimate_time = seektime;
211
+ this.cueVideoById(generate_sorce);
212
+ }
213
+ }
214
+ else {
215
+ this.player.contentWindow?.postMessage({ eventName: "seek", seekTime: Number(seektime) }, "*");
217
216
  }
218
217
  }
219
218
  /**
220
- * Remove loading animation.
219
+ * Calculates the real duration of the video based on the start and end seconds.
220
+ * @async
221
+ * @function
222
+ * @returns {Promise<number>} The real duration of the video.
221
223
  */
222
- remove_loading_animation() {
223
- const parent_element = this.player.parentElement;
224
- if (!parent_element)
225
- return;
226
- parent_element.childNodes.forEach((node) => {
227
- if (node.nodeName === "DIV" && node.classList.contains("mep_loading_animation")) {
228
- node.remove();
229
- }
230
- });
224
+ async getRealDulation() {
225
+ if (this.endSeconds == -1) {
226
+ return await this.getDuration() - this.startSeconds;
227
+ }
228
+ else {
229
+ return this.endSeconds - this.startSeconds;
230
+ }
231
231
  }
232
232
  /**
233
- * Add error description.
233
+ * Get the duration of the video.
234
+ * @async
235
+ * @returns {Promise<number>} The duration of the video in seconds.
234
236
  */
235
- add_error_description() {
236
- const error_description_document = document.createElement("div");
237
- error_description_document.style.width = "100%";
238
- error_description_document.style.height = "100%";
239
- let error_message = "unknown error occurred";
240
- if (this.front_error_code !== undefined && mep_bilibili.error_description[this.front_error_code] !== undefined) {
241
- error_message = mep_bilibili.error_description[this.front_error_code] + "\n front end error code:" + String(this.front_error_code);
242
- }
243
- error_description_document.innerText = error_message;
244
- this.player.replaceWith(error_description_document);
245
- this.player = error_description_document;
246
- try {
247
- const parent_element = this.player.parentElement;
248
- if (parent_element) {
249
- parent_element.style.backgroundImage = "";
250
- }
237
+ async getDuration() {
238
+ if (!window.mep_bilibili.mep_extension_bilibili) {
239
+ let videodata_api = await __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_getVideodataApi).call(this);
240
+ return videodata_api["data"]?.["duration"] || 0;
241
+ }
242
+ else {
243
+ return this.state.dulation || 0;
251
244
  }
252
- catch { }
253
245
  }
254
246
  /**
255
- * Add player CSS style.
247
+ * Gets the title of the video.
248
+ * @returns {Promise<string>} The title of the video.
256
249
  */
257
- add_player_css_style() {
258
- let exist_mep_bilibili_player_css = false;
259
- Array.from(document.head.getElementsByClassName("mep_bilibili_player_css")).forEach((element) => {
260
- if (element.nodeName === "STYLE") {
261
- exist_mep_bilibili_player_css = true;
262
- }
263
- });
264
- if (!exist_mep_bilibili_player_css) {
265
- const style_element = document.createElement("style");
266
- style_element.classList.add("mep_bilibili_player_css");
267
- style_element.innerHTML = `
268
- .mep_bilibili_player{
269
- border: none;
270
- width: 100%;
271
- height: 100%;
272
- }`;
273
- document.head.appendChild(style_element);
250
+ async getTitle() {
251
+ if (!window.mep_bilibili.mep_extension_bilibili) {
252
+ let videodata_api = await __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_getVideodataApi).call(this);
253
+ return videodata_api["data"]?.["title"] || "";
254
+ }
255
+ else {
256
+ return this.state.getTitle || "";
274
257
  }
275
258
  }
276
259
  /**
277
- * Get video data from API.
260
+ * Returns the current state of the player.
261
+ * @async
262
+ * @returns {number} The state of the player. Possible values are:
263
+ * 0 - Player is not ready or cache is not available.
264
+ * 1 - Player is ready and not playing.
265
+ * 2 - Player is playing.
266
+ * 3 - Player is paused.
267
+ * 4 - Player was ended.
278
268
  */
279
- async getVideodataApi() {
280
- return new Promise(async (resolve, reject) => {
281
- if (!(this.videoid in mep_bilibili.bilibili_api_cache)) {
282
- if (mep_bilibili.bilibili_api_promise[this.videoid] === undefined) {
283
- mep_bilibili.bilibili_api_promise[this.videoid] = { res: [], rej: [] };
284
- try {
285
- if (mep_bilibili.cors_proxy === "") {
286
- mep_bilibili.bilibili_api_cache[this.videoid] = await (await fetch(`${mep_bilibili.api_endpoint}?route=bilibili&videoid=${this.videoid}&image_base64=1`)).json();
287
- }
288
- else {
289
- const json_response_bilibili = await (await fetch(mep_bilibili.cors_proxy + `https://api.bilibili.com/x/web-interface/view?bvid=${this.videoid}`)).json();
290
- if (json_response_bilibili?.data?.pic === undefined) {
291
- json_response_bilibili["image_base64"] = null;
292
- }
293
- else {
294
- json_response_bilibili["image_base64"] = mep_bilibili.cors_proxy + json_response_bilibili.data.pic;
295
- }
296
- mep_bilibili.bilibili_api_cache[this.videoid] = json_response_bilibili;
297
- }
269
+ async getPlayerState() {
270
+ if (!window.mep_bilibili.mep_extension_bilibili) {
271
+ const realDulationCache = await this.getRealDulation();
272
+ const currentTimeCahce = await this.getCurrentTime();
273
+ if (this.loading || currentTimeCahce == undefined || realDulationCache == undefined || Number.isNaN(realDulationCache)) {
274
+ return 0; //1のほうが適切かもしれない
275
+ }
276
+ else if (this.innerStartSeconds == currentTimeCahce) {
277
+ return 1;
278
+ }
279
+ else if (((currentTimeCahce - this.startSeconds) / realDulationCache) > 0.99) {
280
+ return 4;
281
+ }
282
+ else if (this.no_extention_pause) {
283
+ return 3;
284
+ }
285
+ else if (((currentTimeCahce - this.startSeconds) / realDulationCache) < 0.99) { //再生中の可能性大
286
+ return 2;
287
+ }
288
+ else {
289
+ return -2;
290
+ }
291
+ }
292
+ else {
293
+ if (this.state.getPlayerState != undefined) {
294
+ if (this.state.getPlayerState == "READY") {
295
+ return 1;
296
+ }
297
+ else if (this.state.getPlayerState == "PLAYING") {
298
+ return 2;
299
+ }
300
+ else if (this.state.getPlayerState == "PAUSED") {
301
+ let current_duration = ((this.getCurrentTime()) / ((await this.getDuration()) - this.endSeconds)) * 100; //%で出す
302
+ if (current_duration > 99) {
303
+ return 4;
298
304
  }
299
- catch {
300
- console.error("error occurred when get bilibili api. Are you sure you overwrite iframe_api endpoint? or cors proxy is not working?");
301
- this.front_error_code = 1;
302
- this.player.dispatchEvent(new CustomEvent("onError", { detail: { code: 1100 } }));
305
+ else {
306
+ return 3;
303
307
  }
304
- mep_bilibili.bilibili_api_promise[this.videoid].res.forEach((resolveFunc) => { resolveFunc(); });
305
- resolve(mep_bilibili.bilibili_api_cache[this.videoid]);
306
- }
307
- else {
308
- mep_bilibili.bilibili_api_promise[this.videoid].res.push(() => resolve(mep_bilibili.bilibili_api_cache[this.videoid]));
309
- mep_bilibili.bilibili_api_promise[this.videoid].rej.push(() => reject());
310
- return;
311
308
  }
312
309
  }
313
- else {
314
- resolve(mep_bilibili.bilibili_api_cache[this.videoid]);
315
- }
316
- });
310
+ return 0; // Default return value
311
+ }
317
312
  }
318
- // IPlayer interface implementation
319
- playVideo() {
320
- if (!mep_bilibili.mep_extension_bilibili) {
321
- this.set_pause_transparent();
322
- // Implementation for non-extension mode
313
+ /**
314
+ * Sets the volume of the Bilibili player.
315
+ * When not install extention, this function will not work.
316
+ * @param {number} volume - The volume level to set, between 0 and 100.
317
+ */
318
+ setVolume(volume) {
319
+ if (!window.mep_bilibili.mep_extension_bilibili) {
320
+ console.warn(window.mep_bilibili.no_extention_error);
323
321
  }
324
322
  else {
325
- this.player.contentWindow.postMessage({ eventName: "play" }, "*");
323
+ this.player.contentWindow?.postMessage({ eventName: "setVolume", volume: Number(volume / 100) }, "*"); //100で割って差をなくす
326
324
  }
327
325
  }
328
- pauseVideo() {
329
- if (!mep_bilibili.mep_extension_bilibili) {
330
- this.image_player();
326
+ /**
327
+ * Gets the current volume of the Bilibili player.
328
+ * When not install extention, this function will not work.
329
+ * @returns {number} The current volume value.
330
+ */
331
+ getVolume() {
332
+ if (!window.mep_bilibili.mep_extension_bilibili) {
333
+ console.warn(window.mep_bilibili.no_extention_error);
334
+ return undefined;
331
335
  }
332
336
  else {
333
- this.player.contentWindow.postMessage({ eventName: "pause" }, "*");
337
+ return this.state.volumeValue;
334
338
  }
335
339
  }
336
- getCurrentTime() {
337
- return Promise.resolve(this.currentTime);
340
+ /**
341
+ * Checks if the player is currently muted.
342
+ * When not install extention, this function will not work.
343
+ * @returns {boolean} True if the player is muted, false otherwise.
344
+ */
345
+ isMuted() {
346
+ if (!window.mep_bilibili.mep_extension_bilibili) {
347
+ console.warn(window.mep_bilibili.no_extention_error);
348
+ return undefined;
349
+ }
350
+ else {
351
+ if (this.getVolume() != 0) {
352
+ return false;
353
+ }
354
+ else {
355
+ return true;
356
+ }
357
+ }
338
358
  }
339
- getDuration() {
340
- return Promise.resolve(this.duration);
359
+ /**
360
+ * Mutes the player by setting the volume to 0.
361
+ * When not install extention, this function will not work.
362
+ * @function
363
+ * @returns {void}
364
+ */
365
+ mute() {
366
+ if (!window.mep_bilibili.mep_extension_bilibili) {
367
+ console.warn(window.mep_bilibili.no_extention_error);
368
+ }
369
+ else {
370
+ this.before_mute_volume = this.getVolume() || 0;
371
+ this.setVolume(0);
372
+ }
341
373
  }
342
- async seekTo(time) {
343
- const num_time = Number(time);
344
- if (isNaN(num_time) || num_time < 0) {
345
- console.error("Invalid time value");
346
- return;
374
+ /**
375
+ * Unmutes the player by setting the volume to the previous volume.
376
+ * When not install extention, this function will not work.
377
+ * @function
378
+ * @returns {void}
379
+ */
380
+ unMute() {
381
+ if (!window.mep_bilibili.mep_extension_bilibili) {
382
+ console.warn(window.mep_bilibili.no_extention_error);
347
383
  }
348
- if (!mep_bilibili.mep_extension_bilibili) {
349
- // Implementation for non-extension mode
384
+ else {
385
+ this.setVolume(this.before_mute_volume);
386
+ }
387
+ }
388
+ /**
389
+ * Sends a message to the player's content window to display or hide comments.
390
+ * When not install extention, this function will not work.
391
+ * @param {string} mode - The visibility mode of the comments. Possible values are "visible" or "hidden".
392
+ * @returns {void}
393
+ */
394
+ displayComment(mode) {
395
+ if (!window.mep_bilibili.mep_extension_bilibili) {
396
+ console.warn(window.mep_bilibili.no_extention_error);
350
397
  }
351
398
  else {
352
- this.player.contentWindow.postMessage({ eventName: "seek", seekTime: num_time }, "*");
399
+ this.player.contentWindow?.postMessage({ eventName: "displayComment", commentVisibility: mode }, "*");
353
400
  }
354
401
  }
355
- setVolume(volume) {
356
- const num_volume = Number(volume);
357
- if (isNaN(num_volume) || num_volume < 0 || num_volume > 100) {
358
- console.error("Invalid volume value");
359
- return;
402
+ }
403
+ _mep_bilibili_instances = new WeakSet(), _mep_bilibili_image_player =
404
+ /**
405
+ * @private
406
+ * This function is used for display when player is paused.
407
+ * When this img clicked the player will be played.
408
+ */
409
+ async function _mep_bilibili_image_player(first_load = false) {
410
+ try {
411
+ let exist_img_children = false;
412
+ this.player.parentElement?.childNodes.forEach((node) => { if (node.nodeName === "IMG") {
413
+ exist_img_children = true;
414
+ } if (node.nodeName === "DIV" && node.classList.contains("mep_bilibili_transparent")) {
415
+ node.remove();
416
+ } });
417
+ if (!exist_img_children && this.play_control_wrap) {
418
+ const img_element = document.createElement("img");
419
+ img_element.src = (await __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_getVideodataApi).call(this))["image_base64"] || "";
420
+ img_element.width = Number(this.player.width);
421
+ img_element.height = Number(this.player.height);
422
+ img_element.style.width = "100%";
423
+ img_element.style.height = "100%";
424
+ img_element.style.objectFit = "cover";
425
+ img_element.style.cursor = "pointer";
426
+ img_element.addEventListener("click", () => { this.playVideo(); });
427
+ this.player.parentElement?.prepend(img_element);
428
+ }
429
+ this.player.hidden = true;
430
+ this.player.src = "";
431
+ if (first_load) {
432
+ this.player.dispatchEvent(new Event("onReady"));
433
+ }
434
+ }
435
+ catch (e) {
436
+ console.error(e);
437
+ }
438
+ }, _mep_bilibili_set_pause_transparent = function _mep_bilibili_set_pause_transparent() {
439
+ let exist_div_children = false;
440
+ this.player.parentElement?.childNodes.forEach((node) => { if (node.nodeName === "DIV" && node.classList.contains("mep_bilibili_transparent")) {
441
+ exist_div_children = true;
442
+ } });
443
+ if (!exist_div_children && this.play_control_wrap) {
444
+ const div_element = document.createElement("div");
445
+ div_element.classList.add("mep_bilibili_transparent");
446
+ div_element.style.width = "100%";
447
+ div_element.style.height = "100%";
448
+ div_element.style.zIndex = "1";
449
+ div_element.style.position = "absolute";
450
+ div_element.style.cursor = "pointer";
451
+ div_element.addEventListener("click", () => { this.pauseVideo(); });
452
+ this.player.parentElement?.prepend(div_element);
453
+ }
454
+ }, _mep_bilibili_add_loading_animation = function _mep_bilibili_add_loading_animation() {
455
+ //https://qiita.com/yoshio-the-end/items/8cec41bad0e817928893
456
+ let exist_mep_load_animation = false;
457
+ Array.from(document.head.getElementsByClassName("mep_load_animation")).forEach((element) => { if (element.nodeName === "STYLE") {
458
+ exist_mep_load_animation = true;
459
+ } });
460
+ if (!exist_mep_load_animation) {
461
+ const style_element = document.createElement("style");
462
+ style_element.classList.add("mep_load_animation");
463
+ style_element.innerHTML = `
464
+ .mep_loading_animation{
465
+ border: 12px solid #fafafa;
466
+ border-radius: 50%;
467
+ border-top: 12px solid #3498db;
468
+ width: 100px;
469
+ height: 100px;
470
+ animation: spin 1s linear infinite;
471
+ }
472
+ @keyframes spin{
473
+ 0%{
474
+ transform: rotate(0deg);
475
+ }
476
+ 100%{
477
+ transform: rotate(360deg);
478
+ }
479
+ }`;
480
+ document.head.appendChild(style_element);
481
+ }
482
+ let exist_animation_div = false;
483
+ this.player.parentElement?.childNodes.forEach((node) => { if (node.nodeName === "DIV" && node.classList.contains("mep_loading_animation")) {
484
+ exist_animation_div = true;
485
+ } });
486
+ if (!exist_animation_div) {
487
+ const div_element = document.createElement("div");
488
+ div_element.classList.add("mep_loading_animation");
489
+ div_element.style.zIndex = "2";
490
+ div_element.style.top = "calc(50% - 50px)";
491
+ div_element.style.left = "calc(50% - 50px)";
492
+ div_element.style.position = "absolute";
493
+ this.player.parentElement?.prepend(div_element);
494
+ }
495
+ }, _mep_bilibili_remove_loading_animation = function _mep_bilibili_remove_loading_animation() {
496
+ this.player.parentElement?.childNodes.forEach((node) => { if (node.nodeName === "DIV" && node.classList.contains("mep_loading_animation")) {
497
+ node.remove();
498
+ } });
499
+ }, _mep_bilibili_add_error_description = function _mep_bilibili_add_error_description() {
500
+ const error_description_document = document.createElement("div");
501
+ error_description_document.style.width = "100%";
502
+ error_description_document.style.height = "100%";
503
+ let error_message = "unknown error occurred";
504
+ if (this.front_error_code != undefined && window.mep_bilibili.error_description[this.front_error_code] != undefined) {
505
+ error_message = window.mep_bilibili.error_description[this.front_error_code] + "\n front end error code:" + String(this.front_error_code);
506
+ }
507
+ error_description_document.innerText = error_message;
508
+ this.player.replaceWith(error_description_document);
509
+ this.player = error_description_document;
510
+ try {
511
+ this.player.parentElement.style.backgroundImage = "";
512
+ }
513
+ catch { }
514
+ }, _mep_bilibili_add_player_css_style = function _mep_bilibili_add_player_css_style() {
515
+ let exist_mep_bilibili_player_css = false;
516
+ Array.from(document.head.getElementsByClassName("mep_bilibili_player_css")).forEach((element) => { if (element.nodeName === "STYLE") {
517
+ exist_mep_bilibili_player_css = true;
518
+ } });
519
+ if (!exist_mep_bilibili_player_css) {
520
+ const style_element = document.createElement("style");
521
+ style_element.classList.add("mep_bilibili_player_css");
522
+ style_element.innerHTML = `
523
+ .mep_bilibili_player{
524
+ border: none;
525
+ width: 100%;
526
+ height: 100%;
527
+ }`;
528
+ document.head.appendChild(style_element);
529
+ }
530
+ }, _mep_bilibili_add_local_storage_error_description = function _mep_bilibili_add_local_storage_error_description() {
531
+ const error_description_document = document.createElement("div");
532
+ error_description_document.style.width = "100%";
533
+ error_description_document.style.height = "100%";
534
+ error_description_document.innerText = "Due to not to access localstorage,can't play bilibili video\nyou should turn on third party cookie for this site and then reload this page";
535
+ this.player.replaceWith(error_description_document);
536
+ this.player = error_description_document;
537
+ try {
538
+ this.player.parentElement.style.backgroundImage = "";
539
+ }
540
+ catch { }
541
+ }, _mep_bilibili_element_constructor =
542
+ /**
543
+ * Constructor function for the Bilibili player.
544
+ * @param {string|HTMLElement} replacing_element - The element to replace with the Bilibili player.
545
+ * @param {Object} content - The content object containing the video ID and player variables.
546
+ * @param {Function} player_set_event_function - The function to set event listeners on the player.
547
+ */
548
+ async function _mep_bilibili_element_constructor(replacing_element, content, player_set_event_function) {
549
+ this.loading = true;
550
+ this.before_mute_volume = 100;
551
+ this.content_width = content.width;
552
+ this.content_height = content.height;
553
+ if (content?.play_control_wrap == 0) {
554
+ this.play_control_wrap = false;
555
+ }
556
+ else {
557
+ this.play_control_wrap = true;
558
+ }
559
+ this.videoid = content["videoId"];
560
+ if (typeof replacing_element === "string") {
561
+ const element = document.getElementById(replacing_element);
562
+ if (!element)
563
+ throw new Error(`Element with id '${replacing_element}' not found`);
564
+ replacing_element = element;
565
+ }
566
+ this.original_replacing_element = replacing_element;
567
+ let bilibili_doc = document.createElement("iframe");
568
+ replacing_element.replaceWith(bilibili_doc);
569
+ this.player = bilibili_doc;
570
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_add_loading_animation).call(this);
571
+ this.player.addEventListener("onReady", () => { __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_remove_loading_animation).call(this); this.loading = false; }, { once: true });
572
+ this.player.addEventListener("onError", () => { __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_remove_loading_animation).call(this); __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_add_error_description).call(this); }, { once: true });
573
+ if (typeof player_set_event_function == "function") {
574
+ player_set_event_function(this.player);
575
+ this.player_set_event = player_set_event_function;
576
+ }
577
+ const api_response = await __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_getVideodataApi).call(this);
578
+ if (api_response?.code !== 0) { //video can play or not if code not 0 such as 69002 the video maybe delete.
579
+ console.error("error occured when get bilibili api. Are you sure you overwrite iframe_api endpoint? or cors proxy is not working? or videoid is invalid?");
580
+ this.front_error_code = 1;
581
+ this.player.dispatchEvent(new CustomEvent("onError", { detail: { code: 1100 } }));
582
+ return;
583
+ }
584
+ this.seek_time = -1;
585
+ this.seek_time_used = true;
586
+ this.noextention_count_stop = 0;
587
+ if (typeof content?.videoId !== "string") {
588
+ console.log("videoId = undefined is not valid");
589
+ }
590
+ this.state = {
591
+ getPlayerState: "PAUSE"
592
+ };
593
+ this.apicache = {};
594
+ if (window.mep_bilibili.localStorageCheck != true) {
595
+ await __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_checkLocalstorage).call(this);
596
+ }
597
+ if (window.mep_bilibili.localStorageCheck === false) {
598
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_add_local_storage_error_description).call(this);
599
+ return;
600
+ }
601
+ this.no_extention_pause = false;
602
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_messageListener).call(this);
603
+ this.startSeconds = 0;
604
+ this.innerStartSeconds = 0;
605
+ if (content?.playerVars?.startSeconds != undefined) {
606
+ this.startSeconds = content?.playerVars?.startSeconds;
607
+ this.innerStartSeconds = parseInt(content?.playerVars?.startSeconds.toString());
608
+ }
609
+ this.autoplay_flag = false;
610
+ if (content?.playerVars?.autoplay == 1) { //終わり次第再生
611
+ this.autoplay_flag = true;
612
+ }
613
+ if (content?.playerVars?.displayComment != undefined) {
614
+ if (content?.playerVars?.displayComment == 0) {
615
+ this.displayCommentMode = false;
360
616
  }
361
- if (!mep_bilibili.mep_extension_bilibili) {
362
- console.warn(mep_bilibili.no_extention_error);
617
+ else if (content?.playerVars?.displayComment == 1) {
618
+ this.displayCommentMode = true;
363
619
  }
364
620
  else {
365
- this.player.contentWindow.postMessage({ eventName: "setVolume", volume: num_volume / 100 }, "*");
621
+ this.displayCommentMode = false;
366
622
  }
367
623
  }
368
- getVolume() {
369
- if (!mep_bilibili.mep_extension_bilibili) {
370
- console.warn(mep_bilibili.no_extention_error);
371
- return Promise.resolve(this.volume);
624
+ let bilibili_query = {
625
+ bvid: "",
626
+ autoplay: 0,
627
+ danmaku: 0
628
+ };
629
+ if (content["videoId"] == undefined) {
630
+ console.log("invalid videoid:" + content["videoId"] + "so stop loading");
631
+ return;
632
+ }
633
+ bilibili_query.bvid = content["videoId"];
634
+ if (this.startSeconds > 0) {
635
+ bilibili_query.t = this.startSeconds;
636
+ }
637
+ if (this.autoplay_flag) {
638
+ bilibili_query.autoplay = 1;
639
+ }
640
+ else {
641
+ bilibili_query.autoplay = 0;
642
+ }
643
+ if (!this.autoplay_flag && !window.mep_bilibili.mep_extension_bilibili) {
644
+ this.no_extention_pause = true;
645
+ }
646
+ if (this.displayCommentMode) {
647
+ bilibili_query.danmaku = 1;
648
+ }
649
+ else {
650
+ bilibili_query.danmaku = 0;
651
+ }
652
+ this.fastload = false;
653
+ if (content?.playerVars?.fastLoad != undefined) {
654
+ if (!window.mep_bilibili.mep_extension_bilibili) {
655
+ console.log("fast load ignored because of mep extention not installed in your browser");
372
656
  }
373
657
  else {
374
- return Promise.resolve(this.volume);
658
+ if (content?.playerVars?.fastLoad == 1) {
659
+ this.fastload = true;
660
+ }
375
661
  }
376
662
  }
377
- mute() {
378
- if (!mep_bilibili.mep_extension_bilibili) {
379
- console.warn(mep_bilibili.no_extention_error);
663
+ let query_string = "";
664
+ let bilibili_query_keys = Object.keys(bilibili_query);
665
+ for (let x = 0; x < bilibili_query_keys.length; x++) {
666
+ const key = bilibili_query_keys[x];
667
+ if (key !== undefined) {
668
+ const value = bilibili_query[key];
669
+ if (value !== undefined) {
670
+ query_string += key + "=" + String(value) + "&";
671
+ }
672
+ }
673
+ }
674
+ query_string = query_string.slice(0, -1);
675
+ if (this.autoplay_flag) {
676
+ if (!window.mep_bilibili.mep_extension_bilibili) { //時間カウント用プログラムの追加
677
+ this.no_extention_estimate_stop = true;
678
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_set_pause_transparent).call(this);
679
+ this.player.addEventListener("load", () => { this.play_start_time = new Date().getTime(); this.no_extention_estimate_stop = false; this.play_start_count_interval = setInterval(__classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_observe_load_time).bind(this), 500); this.player.dispatchEvent(new Event("onReady")); }, { once: true });
380
680
  }
381
681
  else {
382
- this.volume = this.volume; // Store current volume
383
- this.player.contentWindow.postMessage({ eventName: "setVolume", volume: 0 }, "*");
682
+ this.player.addEventListener("onReady", () => { if (this.fastload && this.startSeconds != 0) {
683
+ this.seekTo(this.startSeconds);
684
+ } ; if (this.fastload && this.autoplay_flag) {
685
+ this.playVideo();
686
+ } });
384
687
  }
385
688
  }
386
- unMute() {
387
- if (!mep_bilibili.mep_extension_bilibili) {
388
- console.warn(mep_bilibili.no_extention_error);
689
+ if (this.autoplay_flag || window.mep_bilibili.mep_extension_bilibili === true) {
690
+ bilibili_doc.src = window.mep_bilibili.player_base_url + query_string;
691
+ }
692
+ else {
693
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_image_player).call(this, true);
694
+ }
695
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_add_player_css_style).call(this);
696
+ bilibili_doc.classList.add("mep_bilibili_player");
697
+ bilibili_doc.width = String(content.width);
698
+ bilibili_doc.height = String(content.height);
699
+ bilibili_doc.allow = "autoplay"; //fix bug not autoplay on chrome
700
+ bilibili_doc.allowFullscreen = true; //fix bug can't watch on full screen(all browser)
701
+ bilibili_doc.style.border = "none"; //fix bug display border on outer frame
702
+ try {
703
+ bilibili_doc.parentElement.setEvent();
704
+ }
705
+ catch { }
706
+ //bilibili_doc.sandbox = "allow-scripts";
707
+ this.endSeconds = -1;
708
+ if (content?.playerVars?.endSeconds != undefined) {
709
+ this.endSeconds = content?.playerVars?.endSeconds;
710
+ }
711
+ if (this.endSeconds != -1) {
712
+ this.end_point_observe = setInterval(__classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_observe_end_time).bind(this), 500);
713
+ }
714
+ }, _mep_bilibili_checkLocalstorage =
715
+ /**
716
+ * Checks whether cross domain iframe can use local storage.
717
+ * If it can't, it will not load bilibili embed.
718
+ * @returns {Promise<void>}
719
+ */
720
+ async function _mep_bilibili_checkLocalstorage() {
721
+ //check whether cross domain iframe can use local storage
722
+ //if can't ,it will not load bilibili embed
723
+ if (window.mep_bilibili.localStorageCheck == null) {
724
+ let selected_localStorageCheck_url = "";
725
+ if (!location.origin.includes("pages.dev")) {
726
+ selected_localStorageCheck_url = "https://multi-embed-player.pages.dev/localStorageCheck";
389
727
  }
390
728
  else {
391
- this.player.contentWindow.postMessage({ eventName: "setVolume", volume: this.volume / 100 }, "*");
729
+ selected_localStorageCheck_url = "https://multi-embed-player.netlify.app/localstoragecheck";
730
+ }
731
+ const cdls = document.createElement("iframe");
732
+ cdls.width = "0";
733
+ cdls.height = "0";
734
+ cdls.src = selected_localStorageCheck_url; //if you don't prefer you can change this file.But you must change origin.If you this embed example.com,you must not this otherdomain.example.com
735
+ //and if extention exists,it will redirect to send information about exist browser extention
736
+ cdls.style.cssText = "border:none;";
737
+ const origin = new URL(selected_localStorageCheck_url).origin;
738
+ document.body.appendChild(cdls);
739
+ const return_localstorage_status = await new Promise(function (resolve, reject) {
740
+ window.addEventListener("message", function (ms) {
741
+ if (ms.origin == origin) {
742
+ try {
743
+ if (ms.data.extention) {
744
+ window.mep_bilibili.mep_extension_bilibili = true;
745
+ }
746
+ }
747
+ catch { }
748
+ resolve(ms.data.localStorageUsable);
749
+ }
750
+ });
751
+ }.bind(origin));
752
+ cdls.remove();
753
+ if (!return_localstorage_status) {
754
+ window.mep_bilibili.localStorageCheck = false;
755
+ this.front_error_code = 2;
756
+ this.player.dispatchEvent(new CustomEvent("onError", { detail: { code: 1200 } })); //can't play bilibili video
757
+ }
758
+ else {
759
+ window.mep_bilibili.localStorageCheck = true;
392
760
  }
393
761
  }
394
- isMuted() {
395
- return Promise.resolve(this.muted);
762
+ else if (window.mep_bilibili.localStorageCheck == false) {
763
+ this.front_error_code = 2;
764
+ this.player.dispatchEvent(new CustomEvent("onError", { detail: { code: 1200 } })); //can't play bilibili video
765
+ console.log("error");
766
+ }
767
+ }, _mep_bilibili_observe_load_time =
768
+ /**
769
+ * Observes the load time of the video player and estimates the current time of the video.
770
+ * @private
771
+ */
772
+ async function _mep_bilibili_observe_load_time() {
773
+ if (this.noextention_count_stop == 0 || this.noextention_count_stop == 1) {
774
+ let now_time = new Date().getTime();
775
+ if (!this.no_extention_estimate_stop) {
776
+ if (this.innerStartSeconds != undefined && this.innerStartSeconds != 0) {
777
+ this.estimate_time = (now_time - this.play_start_time) / 1000 + this.innerStartSeconds - window.mep_bilibili.currentTime_delay;
778
+ }
779
+ else if (this.seek_time != undefined && this.seek_time != 0) {
780
+ this.estimate_time = (now_time - this.play_start_time) / 1000 + this.seek_time - window.mep_bilibili.currentTime_delay;
781
+ }
782
+ else {
783
+ this.estimate_time = (now_time - this.play_start_time) / 1000 + this.startSeconds - window.mep_bilibili.currentTime_delay;
784
+ }
785
+ }
786
+ if (this.endSeconds != -1 && this.estimate_time !== undefined && this.estimate_time > this.endSeconds) {
787
+ this.custom_state = 4;
788
+ this.player.dispatchEvent(new Event("onEndVideo")); //再生を終了したことにする
789
+ clearInterval(this.play_start_count_interval); //確認を消去
790
+ this.pauseVideo();
791
+ }
792
+ if (this.endSeconds === -1 && this.estimate_time !== undefined && this.estimate_time >= (await this.getDuration())) {
793
+ this.player.dispatchEvent(new Event("onEndVideo")); //再生を終了したことにする
794
+ clearInterval(this.play_start_count_interval); //確認を消去
795
+ this.pauseVideo();
796
+ }
797
+ if (this.noextention_count_stop == 1) {
798
+ this.noextention_count_stop = 2;
799
+ }
396
800
  }
397
- getPlayerState() {
398
- return Promise.resolve(this.playerState);
801
+ }, _mep_bilibili_observe_end_time = function _mep_bilibili_observe_end_time() {
802
+ let current_time = this.getCurrentTime();
803
+ if (this.endSeconds != -1 && this.endSeconds <= current_time) { //時間が来た
804
+ this.custom_state = 4;
805
+ clearInterval(this.end_point_observe);
806
+ this.pauseVideo();
807
+ this.player.dispatchEvent(new Event("onEndVideo"));
399
808
  }
400
- /**
401
- * Get real duration between start and end times.
402
- */
403
- async getRealDulation() {
404
- const duration = await this.getDuration();
405
- if (this.endSeconds === -1) {
406
- return duration - this.startSeconds;
809
+ else if (this.endSeconds == -1) {
810
+ clearInterval(this.end_point_observe);
811
+ }
812
+ }, _mep_bilibili_video_loader =
813
+ /**
814
+ * Asynchronously loads a Bilibili video player with the given content.
815
+ * @param {Object} content - The content of the video player to be loaded.
816
+ * @returns {Promise<void>} - A Promise that resolves when the video player is loaded.
817
+ * @private
818
+ */
819
+ async function _mep_bilibili_video_loader(content) {
820
+ if (this.player === undefined) {
821
+ this.player = this.original_replacing_element;
822
+ }
823
+ this.loading = true;
824
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_add_loading_animation).call(this);
825
+ if (window.mep_bilibili.localStorageCheck === false) {
826
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_add_local_storage_error_description).call(this);
827
+ return;
828
+ }
829
+ this.player.parentElement?.childNodes.forEach((node) => { if (node.tagName === "IMG") {
830
+ node.remove();
831
+ } });
832
+ let bilibili_query = {
833
+ bvid: "",
834
+ autoplay: 0,
835
+ danmaku: 0
836
+ };
837
+ if (this.videoid != content?.videoId) { //when load other video
838
+ this.seek_time = -1;
839
+ this.seek_time_used = true;
840
+ this.estimate_time = undefined;
841
+ this.noextention_count_stop = 0;
842
+ }
843
+ this.videoid = content?.videoId || "";
844
+ if ((await __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_getVideodataApi).call(this))?.code != 0) { //video can play or not if code not 0 such as 69002 the video maybe delete.
845
+ this.front_error_code = 3;
846
+ this.player.dispatchEvent(new CustomEvent("onError", { detail: { code: 404 } }));
847
+ return;
848
+ }
849
+ bilibili_query.bvid = content?.videoId || "";
850
+ if (content?.startSeconds && content.startSeconds > 0) {
851
+ bilibili_query.t = content.startSeconds;
852
+ }
853
+ if (this.autoplay_flag) {
854
+ bilibili_query.autoplay = 1;
855
+ }
856
+ else {
857
+ bilibili_query.autoplay = 0;
858
+ }
859
+ if (content?.displayComment != undefined) {
860
+ if (content?.displayComment == 0) {
861
+ this.displayCommentMode = false;
862
+ }
863
+ else if (content?.displayComment == 1) {
864
+ this.displayCommentMode = true;
407
865
  }
408
866
  else {
409
- return this.endSeconds - this.startSeconds;
867
+ this.displayCommentMode = false;
410
868
  }
411
869
  }
412
- /**
413
- * Load video by ID.
414
- */
415
- loadVideoById(content) {
416
- this.videoid = content.videoId;
417
- const playerVars = content.playerVars || {};
418
- this.autoplay = playerVars.autoplay || 0;
419
- this.startSeconds = playerVars.startSeconds || 0;
420
- this.endSeconds = playerVars.endSeconds || -1;
421
- // Implementation for loading video
870
+ if (this.displayCommentMode) {
871
+ bilibili_query.danmaku = 1;
422
872
  }
423
- /**
424
- * Cue video by ID.
425
- */
426
- cueVideoById(content) {
427
- this.videoid = content.videoId;
428
- const playerVars = content.playerVars || {};
429
- this.autoplay = 0; // Don't autoplay when cueing
430
- this.startSeconds = playerVars.startSeconds || 0;
431
- this.endSeconds = playerVars.endSeconds || -1;
432
- // Implementation for cueing video
873
+ else {
874
+ bilibili_query.danmaku = 0;
433
875
  }
434
- }
435
- mep_bilibili.error_description = {
436
- 0: "unknown error occurred",
437
- 1: "data api endpoint invalid or throw error",
438
- 2: "can't access local storage",
439
- 3: "data api throw error",
440
- 4: "player throw error direct"
876
+ let query_string = "";
877
+ let bilibili_query_keys = Object.keys(bilibili_query);
878
+ for (let x = 0; x < bilibili_query_keys.length; x++) {
879
+ const key = bilibili_query_keys[x];
880
+ if (key !== undefined) {
881
+ const value = bilibili_query[key];
882
+ if (value !== undefined) {
883
+ query_string += key + "=" + String(value) + "&";
884
+ }
885
+ }
886
+ }
887
+ query_string = query_string.slice(0, -1);
888
+ const new_player = document.createElement("iframe");
889
+ this.player.replaceWith(new_player);
890
+ this.player = new_player;
891
+ if (typeof this.player_set_event == "function") {
892
+ this.player_set_event(this.player);
893
+ }
894
+ else {
895
+ try {
896
+ this.player.parentElement.setEvent();
897
+ }
898
+ catch { }
899
+ }
900
+ this.player.addEventListener("onReady", () => { __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_remove_loading_animation).call(this); this.loading = false; }, { once: true });
901
+ this.player.addEventListener("onError", () => { __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_remove_loading_animation).call(this); __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_add_error_description).call(this); }, { once: true });
902
+ if (!window.mep_bilibili.mep_extension_bilibili) { //時間カウント用プログラムの追加
903
+ this.no_extention_estimate_stop = true;
904
+ if (this.autoplay_flag) {
905
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_set_pause_transparent).call(this);
906
+ }
907
+ else {
908
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_image_player).call(this, true);
909
+ }
910
+ new_player.addEventListener("load", () => { this.play_start_time = new Date().getTime(); this.no_extention_estimate_stop = false; this.play_start_count_interval = setInterval(__classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_observe_load_time).bind(this), 500); this.player.dispatchEvent(new Event("onReady")); }, { once: true });
911
+ }
912
+ this.player.src = window.mep_bilibili.player_base_url + query_string;
913
+ this.player.allow = "autoplay"; //fix bug not autoplay on chrome
914
+ this.player.allowFullscreen = true; //fix bug can't watch on full screen(all browser)
915
+ this.player.style.border = "none"; //fix bug display border on outer frame
916
+ this.player.width = String(this.content_width);
917
+ this.player.height = String(this.content_height);
918
+ __classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_add_player_css_style).call(this);
919
+ this.player.classList.add("mep_bilibili_player");
920
+ this.player.hidden = false;
921
+ //this.player.sandbox = "allow-scripts";
922
+ if (this.endSeconds != -1) {
923
+ this.end_point_observe = setInterval(__classPrivateFieldGet(this, _mep_bilibili_instances, "m", _mep_bilibili_observe_end_time).bind(this), 500);
924
+ }
925
+ }, _mep_bilibili_getVideodataApi =
926
+ /**
927
+ * Asynchronously retrieves video data API for Bilibili.
928
+ * @returns {Promise<Object>} Promise object representing the video data API for Bilibili.
929
+ */
930
+ async function _mep_bilibili_getVideodataApi() {
931
+ return new Promise(async (resolve, reject) => {
932
+ let multi_embed_player_class_usable = false;
933
+ try {
934
+ if (typeof multi_embed_player !== 'undefined' && multi_embed_player.cors_proxy) { }
935
+ ;
936
+ multi_embed_player_class_usable = true;
937
+ }
938
+ catch {
939
+ multi_embed_player_class_usable = false;
940
+ }
941
+ let url = "";
942
+ if (multi_embed_player_class_usable) {
943
+ url = (typeof multi_embed_player !== 'undefined') ? multi_embed_player.cors_proxy : '';
944
+ }
945
+ else {
946
+ url = window.mep_bilibili.cors_proxy;
947
+ }
948
+ if (multi_embed_player_class_usable) {
949
+ if (typeof multi_embed_player !== 'undefined' && !(this.videoid in multi_embed_player.api_cache.bilibili)) {
950
+ if (typeof multi_embed_player_fetch_iframe_api !== 'undefined') {
951
+ await multi_embed_player_fetch_iframe_api("bilibili", this.videoid, multi_embed_player.cors_proxy !== "", true, false, true, this.player);
952
+ }
953
+ }
954
+ if (typeof multi_embed_player !== 'undefined') {
955
+ resolve(multi_embed_player.api_cache.bilibili[this.videoid]);
956
+ }
957
+ else {
958
+ reject('multi_embed_player not available');
959
+ }
960
+ }
961
+ else {
962
+ if (!(this.videoid in window.mep_bilibili.bilibili_api_cache)) {
963
+ if (window.mep_bilibili.bilibili_api_promise[this.videoid] == undefined) {
964
+ window.mep_bilibili.bilibili_api_promise[this.videoid] = { res: [], rej: [] };
965
+ try {
966
+ if (window.mep_bilibili.cors_proxy === "") {
967
+ window.mep_bilibili.bilibili_api_cache[this.videoid] = await (await fetch(`${window.mep_bilibili.api_endpoint}?route=bilibili&videoid=${this.videoid}&image_base64=1`)).json();
968
+ }
969
+ else {
970
+ let json_response_bilibili = await (await fetch(url + `https://api.bilibili.com/x/web-interface/view?bvid=${this.videoid}`)).json();
971
+ if (json_response_bilibili?.data?.pic === undefined) {
972
+ json_response_bilibili["image_base64"] = null;
973
+ }
974
+ else {
975
+ json_response_bilibili["image_base64"] = url + json_response_bilibili.data.pic;
976
+ }
977
+ window.mep_bilibili.bilibili_api_cache[this.videoid] = json_response_bilibili;
978
+ }
979
+ }
980
+ catch {
981
+ console.error("error occured when get bilibili api. Are you sure you overwrite iframe_api endpoint? or cors proxy is not working?");
982
+ this.front_error_code = 1;
983
+ this.player.dispatchEvent(new CustomEvent("onError", { detail: { code: 1100 } }));
984
+ }
985
+ window.mep_bilibili.bilibili_api_promise[this.videoid].res.forEach((resolve) => { resolve(window.mep_bilibili.bilibili_api_cache[this.videoid]); });
986
+ resolve(window.mep_bilibili.bilibili_api_cache[this.videoid]);
987
+ }
988
+ else {
989
+ window.mep_bilibili.bilibili_api_promise[this.videoid].res.push(resolve);
990
+ window.mep_bilibili.bilibili_api_promise[this.videoid].rej.push(reject);
991
+ return;
992
+ }
993
+ }
994
+ else {
995
+ resolve(window.mep_bilibili.bilibili_api_cache[this.videoid]);
996
+ }
997
+ }
998
+ });
999
+ }, _mep_bilibili_messageListener = function _mep_bilibili_messageListener() {
1000
+ this.start_event_count = 0;
1001
+ this.end_event_count = 0;
1002
+ window.addEventListener("message", (data) => {
1003
+ if (data.data.type == "data_change") {
1004
+ this.state = Object.assign(this.state, data.data);
1005
+ if (this.start_event_count == 0 && data.data.dulation > 0) {
1006
+ this.start_event_count = 1;
1007
+ this.player.dispatchEvent(new Event("onReady"));
1008
+ }
1009
+ if (this.end_event_count == 0 && data.data.dulation > data.data.currentTime - 1 && data.data.getPlayerState == "PAUSED") {
1010
+ this.player.dispatchEvent(new Event("onEndVideo"));
1011
+ this.end_event_count = 1;
1012
+ }
1013
+ }
1014
+ else if (data.data.type == "error") {
1015
+ this.front_error_code = 4;
1016
+ this.player.dispatchEvent(new CustomEvent("onError", { detail: { code: 500 } }));
1017
+ }
1018
+ });
441
1019
  };
442
- mep_bilibili.localStorageCheck = null;
443
- mep_bilibili.mep_extension_bilibili = false;
444
- mep_bilibili.api_endpoint = "https://iframe_api.ryokuryu.workers.dev";
445
- mep_bilibili.no_extention_error = "you seems not to install mep_extension yet.if it not installed in your browser,you can't exact some function(mute unMute setVolume etc) and some function(getDuration,getPlayerState etc) will return incorrect data which is not reflect real data";
446
- mep_bilibili.player_base_url = "";
1020
+ mep_bilibili.error_description = { 0: "unknown error occurred", 1: "data api endpoint invalid or throw error", 2: "can't access local storage", 3: "data api throw error", 4: "player throw error direct" };
1021
+ mep_bilibili.localStorageCheck = null; //ニコニコと同じくlocalstorageにアクセスできないと死ぬため
1022
+ mep_bilibili.mep_extension_bilibili = false; //拡張機能ないとまともに動かん
1023
+ mep_bilibili.api_endpoint = "https://iframe_api.ryokuryu.workers.dev"; //please change this if you use
1024
+ mep_bilibili.no_extention_error = "you seems not to install mep_extention yet.if it not installed in your browser,you can't exac some function(mute unMute setVolume etc) and some function(getDulation,getPlayerState etc) will return incorrect data which is not reflect real data";
1025
+ mep_bilibili.player_base_url = ""; //"https://www.bilibili.com/blackboard/webplayer/embed-old.html?"
447
1026
  mep_bilibili.bilibili_api_cache = {};
448
1027
  mep_bilibili.cors_proxy = "";
449
1028
  mep_bilibili.currentTime_delay = 2;
450
1029
  mep_bilibili.bilibili_api_promise = {};
1030
+ // after loading a class, call the function to set the variable before use this class.
1031
+ if (typeof multi_embed_player_set_variable !== 'undefined' && typeof multi_embed_player_set_variable === "function") {
1032
+ multi_embed_player_set_variable(mep_bilibili);
1033
+ }
1034
+ window.mep_bilibili = mep_bilibili;
451
1035
  //# sourceMappingURL=bilibili.js.map