myetv-player 1.0.0 → 1.0.8

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.
Files changed (38) hide show
  1. package/.github/workflows/codeql.yml +100 -0
  2. package/README.md +49 -58
  3. package/SECURITY.md +50 -0
  4. package/css/myetv-player.css +424 -219
  5. package/css/myetv-player.min.css +1 -1
  6. package/dist/myetv-player.js +1759 -1502
  7. package/dist/myetv-player.min.js +1705 -1469
  8. package/package.json +7 -1
  9. package/plugins/README.md +1016 -0
  10. package/plugins/cloudflare/README.md +1068 -0
  11. package/plugins/cloudflare/myetv-player-cloudflare-stream-plugin.js +556 -0
  12. package/plugins/facebook/README.md +1024 -0
  13. package/plugins/facebook/myetv-player-facebook-plugin.js +437 -0
  14. package/plugins/gamepad-remote-controller/README.md +816 -0
  15. package/plugins/gamepad-remote-controller/myetv-player-gamepad-remote-plugin.js +678 -0
  16. package/plugins/google-adsense-ads/README.md +1 -0
  17. package/plugins/google-adsense-ads/g-adsense-ads-plugin.js +158 -0
  18. package/plugins/google-ima-ads/README.md +1 -0
  19. package/plugins/google-ima-ads/g-ima-ads-plugin.js +355 -0
  20. package/plugins/twitch/README.md +1185 -0
  21. package/plugins/twitch/myetv-player-twitch-plugin.js +569 -0
  22. package/plugins/vast-vpaid-ads/README.md +1 -0
  23. package/plugins/vast-vpaid-ads/vast-vpaid-ads-plugin.js +346 -0
  24. package/plugins/vimeo/README.md +1416 -0
  25. package/plugins/vimeo/myetv-player-vimeo.js +640 -0
  26. package/plugins/youtube/README.md +851 -0
  27. package/plugins/youtube/myetv-player-youtube-plugin.js +1714 -210
  28. package/scss/README.md +160 -0
  29. package/scss/_controls.scss +184 -30
  30. package/scss/_menus.scss +840 -672
  31. package/scss/_responsive.scss +67 -105
  32. package/scss/_volume.scss +67 -105
  33. package/src/README.md +559 -0
  34. package/src/controls.js +17 -5
  35. package/src/core.js +1237 -1060
  36. package/src/i18n.js +27 -1
  37. package/src/quality.js +478 -436
  38. 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
+ })();