myetv-player 1.0.0 → 1.0.6
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.
- package/.github/workflows/codeql.yml +100 -0
- package/README.md +36 -58
- package/SECURITY.md +50 -0
- package/css/myetv-player.css +301 -218
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +1713 -1503
- package/dist/myetv-player.min.js +1670 -1471
- package/package.json +6 -1
- package/plugins/README.md +1016 -0
- package/plugins/cloudflare/README.md +1068 -0
- package/plugins/cloudflare/myetv-player-cloudflare-stream-plugin.js +556 -0
- package/plugins/facebook/README.md +1024 -0
- package/plugins/facebook/myetv-player-facebook-plugin.js +437 -0
- package/plugins/gamepad-remote-controller/README.md +816 -0
- package/plugins/gamepad-remote-controller/myetv-player-gamepad-remote-plugin.js +678 -0
- package/plugins/google-adsense-ads/README.md +1 -0
- package/plugins/google-adsense-ads/g-adsense-ads-plugin.js +158 -0
- package/plugins/google-ima-ads/README.md +1 -0
- package/plugins/google-ima-ads/g-ima-ads-plugin.js +355 -0
- package/plugins/twitch/README.md +1185 -0
- package/plugins/twitch/myetv-player-twitch-plugin.js +569 -0
- package/plugins/vast-vpaid-ads/README.md +1 -0
- package/plugins/vast-vpaid-ads/vast-vpaid-ads-plugin.js +346 -0
- package/plugins/vimeo/README.md +1416 -0
- package/plugins/vimeo/myetv-player-vimeo.js +640 -0
- package/plugins/youtube/README.md +851 -0
- package/plugins/youtube/myetv-player-youtube-plugin.js +1714 -210
- package/scss/README.md +160 -0
- package/scss/_menus.scss +840 -672
- package/scss/_responsive.scss +67 -105
- package/scss/_volume.scss +67 -105
- package/src/README.md +559 -0
- package/src/controls.js +16 -4
- package/src/core.js +1192 -1062
- package/src/i18n.js +27 -1
- package/src/quality.js +478 -436
- package/src/subtitles.js +2 -2
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MYETV Player - Facebook Plugin
|
|
3
|
+
* File: myetv-player-facebook-plugin.js
|
|
4
|
+
* Integrates Facebook videos with full API control
|
|
5
|
+
* Created by https://www.myetv.tv https://oskarcosimo.com
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
(function () {
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
class FacebookPlugin {
|
|
12
|
+
constructor(player, options = {}) {
|
|
13
|
+
this.player = player;
|
|
14
|
+
this.options = {
|
|
15
|
+
// Facebook App ID (required for API features)
|
|
16
|
+
appId: options.appId || null,
|
|
17
|
+
|
|
18
|
+
// Video source (Facebook video URL or ID)
|
|
19
|
+
videoUrl: options.videoUrl || null,
|
|
20
|
+
videoId: options.videoId || null,
|
|
21
|
+
|
|
22
|
+
// Embed options
|
|
23
|
+
width: options.width || 500,
|
|
24
|
+
autoplay: options.autoplay || false,
|
|
25
|
+
allowFullscreen: options.allowFullscreen !== false,
|
|
26
|
+
showText: options.showText !== false,
|
|
27
|
+
showCaptions: options.showCaptions !== false,
|
|
28
|
+
|
|
29
|
+
// Plugin options
|
|
30
|
+
debug: options.debug || false,
|
|
31
|
+
replaceNativePlayer: options.replaceNativePlayer !== false,
|
|
32
|
+
autoLoadFromData: options.autoLoadFromData !== false,
|
|
33
|
+
|
|
34
|
+
...options
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
this.fbPlayer = null;
|
|
38
|
+
this.fbContainer = null;
|
|
39
|
+
this.isFBSDKLoaded = false;
|
|
40
|
+
this.isPlayerReady = false;
|
|
41
|
+
|
|
42
|
+
// Get plugin API
|
|
43
|
+
this.api = player.getPluginAPI ? player.getPluginAPI() : {
|
|
44
|
+
player: player,
|
|
45
|
+
video: player.video,
|
|
46
|
+
container: player.container,
|
|
47
|
+
controls: player.controls,
|
|
48
|
+
debug: (msg) => {
|
|
49
|
+
if (this.options.debug) console.log('📘 Facebook Plugin:', msg);
|
|
50
|
+
},
|
|
51
|
+
triggerEvent: (event, data) => player.triggerEvent(event, data)
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (!this.options.appId) {
|
|
55
|
+
console.warn('📘 Facebook Plugin: appId is recommended for full API features');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Setup plugin
|
|
61
|
+
*/
|
|
62
|
+
setup() {
|
|
63
|
+
this.api.debug('Setup started');
|
|
64
|
+
|
|
65
|
+
// Auto-detect video URL from data attributes
|
|
66
|
+
if (this.options.autoLoadFromData) {
|
|
67
|
+
this.autoDetectVideoUrl();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Load Facebook SDK
|
|
71
|
+
this.loadFacebookSDK().then(() => {
|
|
72
|
+
if (this.options.videoUrl || this.options.videoId) {
|
|
73
|
+
this.createFacebookPlayer();
|
|
74
|
+
}
|
|
75
|
+
}).catch(error => {
|
|
76
|
+
console.error('📘 Facebook Plugin: Failed to load SDK', error);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
this.api.debug('Setup completed');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Auto-detect video URL from various sources
|
|
84
|
+
*/
|
|
85
|
+
autoDetectVideoUrl() {
|
|
86
|
+
// Priority 1: Check data attributes
|
|
87
|
+
const dataVideoUrl = this.api.video.getAttribute('data-video-url');
|
|
88
|
+
const dataVideoType = this.api.video.getAttribute('data-video-type');
|
|
89
|
+
|
|
90
|
+
if (dataVideoUrl && dataVideoType === 'facebook') {
|
|
91
|
+
this.options.videoUrl = dataVideoUrl;
|
|
92
|
+
this.api.debug('Video URL detected from data attribute: ' + dataVideoUrl);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Priority 2: Check video src
|
|
97
|
+
const src = this.api.video.src || this.api.video.currentSrc;
|
|
98
|
+
if (src && this.isFacebookUrl(src)) {
|
|
99
|
+
this.options.videoUrl = src;
|
|
100
|
+
this.api.debug('Video URL detected from src: ' + src);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Priority 3: Check source elements
|
|
105
|
+
const sources = this.api.video.querySelectorAll('source');
|
|
106
|
+
for (const source of sources) {
|
|
107
|
+
const sourceSrc = source.getAttribute('src');
|
|
108
|
+
const sourceType = source.getAttribute('type');
|
|
109
|
+
|
|
110
|
+
if ((sourceType === 'video/facebook' || this.isFacebookUrl(sourceSrc)) && sourceSrc) {
|
|
111
|
+
this.options.videoUrl = sourceSrc;
|
|
112
|
+
this.api.debug('Video URL detected from source: ' + sourceSrc);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Check if URL is a Facebook video URL
|
|
120
|
+
*/
|
|
121
|
+
isFacebookUrl(url) {
|
|
122
|
+
if (!url) return false;
|
|
123
|
+
return /facebook\.com\/(.*\/)?videos?\//.test(url);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Load Facebook SDK
|
|
128
|
+
*/
|
|
129
|
+
loadFacebookSDK() {
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
// Check if already loaded
|
|
132
|
+
if (window.FB && window.FB.init) {
|
|
133
|
+
this.isFBSDKLoaded = true;
|
|
134
|
+
this.initializeFBSDK();
|
|
135
|
+
resolve();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Load SDK
|
|
140
|
+
window.fbAsyncInit = () => {
|
|
141
|
+
this.initializeFBSDK();
|
|
142
|
+
this.isFBSDKLoaded = true;
|
|
143
|
+
this.api.debug('Facebook SDK loaded');
|
|
144
|
+
resolve();
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Inject script
|
|
148
|
+
const script = document.createElement('script');
|
|
149
|
+
script.src = 'https://connect.facebook.net/en_US/sdk.js';
|
|
150
|
+
script.async = true;
|
|
151
|
+
script.defer = true;
|
|
152
|
+
script.onerror = () => reject(new Error('Failed to load Facebook SDK'));
|
|
153
|
+
|
|
154
|
+
if (!document.getElementById('fb-root')) {
|
|
155
|
+
const fbRoot = document.createElement('div');
|
|
156
|
+
fbRoot.id = 'fb-root';
|
|
157
|
+
document.body.insertBefore(fbRoot, document.body.firstChild);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
document.head.appendChild(script);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Initialize Facebook SDK
|
|
166
|
+
*/
|
|
167
|
+
initializeFBSDK() {
|
|
168
|
+
const config = {
|
|
169
|
+
xfbml: true,
|
|
170
|
+
version: 'v18.0'
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
if (this.options.appId) {
|
|
174
|
+
config.appId = this.options.appId;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
FB.init(config);
|
|
178
|
+
|
|
179
|
+
// Listen for video player ready
|
|
180
|
+
FB.Event.subscribe('xfbml.ready', (msg) => {
|
|
181
|
+
if (msg.type === 'video') {
|
|
182
|
+
this.fbPlayer = msg.instance;
|
|
183
|
+
this.isPlayerReady = true;
|
|
184
|
+
this.setupEventListeners();
|
|
185
|
+
this.api.debug('Facebook player ready');
|
|
186
|
+
this.api.triggerEvent('facebookplugin:playerready', {});
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Create Facebook player
|
|
193
|
+
*/
|
|
194
|
+
createFacebookPlayer() {
|
|
195
|
+
if (!this.options.videoUrl && !this.options.videoId) {
|
|
196
|
+
this.api.debug('No video URL or ID provided');
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Hide native player
|
|
201
|
+
if (this.options.replaceNativePlayer) {
|
|
202
|
+
this.api.video.style.display = 'none';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Create container
|
|
206
|
+
this.fbContainer = document.createElement('div');
|
|
207
|
+
this.fbContainer.className = 'fb-video-container';
|
|
208
|
+
this.fbContainer.style.cssText = `
|
|
209
|
+
position: absolute;
|
|
210
|
+
top: 0;
|
|
211
|
+
left: 0;
|
|
212
|
+
width: 100%;
|
|
213
|
+
height: 100%;
|
|
214
|
+
z-index: 100;
|
|
215
|
+
`;
|
|
216
|
+
|
|
217
|
+
// Create Facebook video element
|
|
218
|
+
const fbVideo = document.createElement('div');
|
|
219
|
+
fbVideo.className = 'fb-video';
|
|
220
|
+
|
|
221
|
+
const videoUrl = this.options.videoUrl || `https://www.facebook.com/video.php?v=${this.options.videoId}`;
|
|
222
|
+
fbVideo.setAttribute('data-href', videoUrl);
|
|
223
|
+
fbVideo.setAttribute('data-width', this.options.width);
|
|
224
|
+
fbVideo.setAttribute('data-allowfullscreen', this.options.allowFullscreen);
|
|
225
|
+
fbVideo.setAttribute('data-autoplay', this.options.autoplay);
|
|
226
|
+
fbVideo.setAttribute('data-show-text', this.options.showText);
|
|
227
|
+
fbVideo.setAttribute('data-show-captions', this.options.showCaptions);
|
|
228
|
+
|
|
229
|
+
this.fbContainer.appendChild(fbVideo);
|
|
230
|
+
this.api.container.appendChild(this.fbContainer);
|
|
231
|
+
|
|
232
|
+
// Parse XFBML
|
|
233
|
+
if (window.FB && window.FB.XFBML) {
|
|
234
|
+
FB.XFBML.parse(this.fbContainer);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
this.api.debug('Facebook player created');
|
|
238
|
+
this.api.triggerEvent('facebookplugin:videoloaded', { videoUrl });
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Setup event listeners
|
|
243
|
+
*/
|
|
244
|
+
setupEventListeners() {
|
|
245
|
+
if (!this.fbPlayer) return;
|
|
246
|
+
|
|
247
|
+
// Started playing
|
|
248
|
+
this.fbPlayer.subscribe('startedPlaying', () => {
|
|
249
|
+
this.api.debug('Video started playing');
|
|
250
|
+
this.api.triggerEvent('play', {});
|
|
251
|
+
this.api.triggerEvent('playing', {});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Paused
|
|
255
|
+
this.fbPlayer.subscribe('paused', () => {
|
|
256
|
+
this.api.debug('Video paused');
|
|
257
|
+
this.api.triggerEvent('pause', {});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Finished playing
|
|
261
|
+
this.fbPlayer.subscribe('finishedPlaying', () => {
|
|
262
|
+
this.api.debug('Video finished');
|
|
263
|
+
this.api.triggerEvent('ended', {});
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// Started buffering
|
|
267
|
+
this.fbPlayer.subscribe('startedBuffering', () => {
|
|
268
|
+
this.api.debug('Buffering started');
|
|
269
|
+
this.api.triggerEvent('waiting', {});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// Finished buffering
|
|
273
|
+
this.fbPlayer.subscribe('finishedBuffering', () => {
|
|
274
|
+
this.api.debug('Buffering finished');
|
|
275
|
+
this.api.triggerEvent('canplay', {});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Error
|
|
279
|
+
this.fbPlayer.subscribe('error', (error) => {
|
|
280
|
+
console.error('📘 Facebook player error:', error);
|
|
281
|
+
this.api.triggerEvent('error', error);
|
|
282
|
+
this.api.triggerEvent('facebookplugin:error', error);
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Play video
|
|
288
|
+
*/
|
|
289
|
+
play() {
|
|
290
|
+
if (!this.fbPlayer) {
|
|
291
|
+
return Promise.reject('Player not initialized');
|
|
292
|
+
}
|
|
293
|
+
this.fbPlayer.play();
|
|
294
|
+
return Promise.resolve();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Pause video
|
|
299
|
+
*/
|
|
300
|
+
pause() {
|
|
301
|
+
if (!this.fbPlayer) {
|
|
302
|
+
return Promise.reject('Player not initialized');
|
|
303
|
+
}
|
|
304
|
+
this.fbPlayer.pause();
|
|
305
|
+
return Promise.resolve();
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Seek to position
|
|
310
|
+
*/
|
|
311
|
+
seek(seconds) {
|
|
312
|
+
if (!this.fbPlayer) {
|
|
313
|
+
return Promise.reject('Player not initialized');
|
|
314
|
+
}
|
|
315
|
+
this.fbPlayer.seek(seconds);
|
|
316
|
+
return Promise.resolve(seconds);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Get current time
|
|
321
|
+
*/
|
|
322
|
+
getCurrentTime() {
|
|
323
|
+
if (!this.fbPlayer) {
|
|
324
|
+
return Promise.reject('Player not initialized');
|
|
325
|
+
}
|
|
326
|
+
return Promise.resolve(this.fbPlayer.getCurrentPosition());
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Get duration
|
|
331
|
+
*/
|
|
332
|
+
getDuration() {
|
|
333
|
+
if (!this.fbPlayer) {
|
|
334
|
+
return Promise.reject('Player not initialized');
|
|
335
|
+
}
|
|
336
|
+
return Promise.resolve(this.fbPlayer.getDuration());
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Mute video
|
|
341
|
+
*/
|
|
342
|
+
mute() {
|
|
343
|
+
if (!this.fbPlayer) {
|
|
344
|
+
return Promise.reject('Player not initialized');
|
|
345
|
+
}
|
|
346
|
+
this.fbPlayer.mute();
|
|
347
|
+
return Promise.resolve();
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Unmute video
|
|
352
|
+
*/
|
|
353
|
+
unmute() {
|
|
354
|
+
if (!this.fbPlayer) {
|
|
355
|
+
return Promise.reject('Player not initialized');
|
|
356
|
+
}
|
|
357
|
+
this.fbPlayer.unmute();
|
|
358
|
+
return Promise.resolve();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Check if muted
|
|
363
|
+
*/
|
|
364
|
+
isMuted() {
|
|
365
|
+
if (!this.fbPlayer) {
|
|
366
|
+
return Promise.reject('Player not initialized');
|
|
367
|
+
}
|
|
368
|
+
return Promise.resolve(this.fbPlayer.isMuted());
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Set volume
|
|
373
|
+
*/
|
|
374
|
+
setVolume(volume) {
|
|
375
|
+
if (!this.fbPlayer) {
|
|
376
|
+
return Promise.reject('Player not initialized');
|
|
377
|
+
}
|
|
378
|
+
this.fbPlayer.setVolume(volume);
|
|
379
|
+
return Promise.resolve(volume);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Get volume
|
|
384
|
+
*/
|
|
385
|
+
getVolume() {
|
|
386
|
+
if (!this.fbPlayer) {
|
|
387
|
+
return Promise.reject('Player not initialized');
|
|
388
|
+
}
|
|
389
|
+
return Promise.resolve(this.fbPlayer.getVolume());
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Load new video
|
|
394
|
+
*/
|
|
395
|
+
loadVideo(videoUrl) {
|
|
396
|
+
this.options.videoUrl = videoUrl;
|
|
397
|
+
|
|
398
|
+
// Remove existing player
|
|
399
|
+
if (this.fbContainer) {
|
|
400
|
+
this.fbContainer.remove();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Create new player
|
|
404
|
+
this.createFacebookPlayer();
|
|
405
|
+
return Promise.resolve();
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Dispose plugin
|
|
410
|
+
*/
|
|
411
|
+
dispose() {
|
|
412
|
+
this.api.debug('Disposing plugin');
|
|
413
|
+
|
|
414
|
+
if (this.fbContainer) {
|
|
415
|
+
this.fbContainer.remove();
|
|
416
|
+
this.fbContainer = null;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
this.fbPlayer = null;
|
|
420
|
+
|
|
421
|
+
// Restore native player
|
|
422
|
+
if (this.api.video && this.options.replaceNativePlayer) {
|
|
423
|
+
this.api.video.style.display = '';
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
this.api.debug('Plugin disposed');
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Register plugin globally
|
|
431
|
+
if (typeof window.registerMYETVPlugin === 'function') {
|
|
432
|
+
window.registerMYETVPlugin('facebook', FacebookPlugin);
|
|
433
|
+
} else {
|
|
434
|
+
console.error('📘 MYETV Player plugin system not found');
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
})();
|