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.
Files changed (37) hide show
  1. package/.github/workflows/codeql.yml +100 -0
  2. package/README.md +36 -58
  3. package/SECURITY.md +50 -0
  4. package/css/myetv-player.css +301 -218
  5. package/css/myetv-player.min.css +1 -1
  6. package/dist/myetv-player.js +1713 -1503
  7. package/dist/myetv-player.min.js +1670 -1471
  8. package/package.json +6 -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/_menus.scss +840 -672
  30. package/scss/_responsive.scss +67 -105
  31. package/scss/_volume.scss +67 -105
  32. package/src/README.md +559 -0
  33. package/src/controls.js +16 -4
  34. package/src/core.js +1192 -1062
  35. package/src/i18n.js +27 -1
  36. package/src/quality.js +478 -436
  37. package/src/subtitles.js +2 -2
@@ -0,0 +1,158 @@
1
+ /* Google AdSense Plugin for MYETV Video Player
2
+ * Integrates Google AdSense for Video
3
+ * Created by https://www.myetv.tv https://oskarcosimo.com
4
+ */
5
+
6
+ /* GLOBAL_START */
7
+ (function () {
8
+ 'use strict';
9
+
10
+ /**
11
+ * Google AdSense Video Plugin
12
+ */
13
+ class AdSenseVideoPlugin {
14
+ constructor(player, options = {}) {
15
+ this.player = player;
16
+ this.options = {
17
+ publisherId: options.publisherId || '',
18
+ adSlot: options.adSlot || '',
19
+ adFormat: options.adFormat || 'auto',
20
+ fullWidth: options.fullWidth !== false,
21
+ debug: options.debug || false,
22
+ ...options
23
+ };
24
+
25
+ this.adContainer = null;
26
+ this.isAdLoaded = false;
27
+ }
28
+
29
+ /**
30
+ * Setup plugin
31
+ */
32
+ setup() {
33
+ if (!this.options.publisherId) {
34
+ console.error('🎬 AdSense Publisher ID is required');
35
+ return;
36
+ }
37
+
38
+ this.createAdContainer();
39
+ this.loadAdSenseScript();
40
+
41
+ if (this.options.debug) {
42
+ console.log('🎬 AdSense Video Plugin initialized');
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Create ad container
48
+ */
49
+ createAdContainer() {
50
+ this.adContainer = document.createElement('div');
51
+ this.adContainer.className = 'adsense-video-container';
52
+ this.adContainer.style.cssText = `
53
+ position: absolute;
54
+ top: 0;
55
+ left: 0;
56
+ width: 100%;
57
+ height: 100%;
58
+ z-index: 999;
59
+ display: none;
60
+ `;
61
+
62
+ // Create AdSense ins element
63
+ const ins = document.createElement('ins');
64
+ ins.className = 'adsbygoogle';
65
+ ins.style.cssText = 'display:block;';
66
+ ins.setAttribute('data-ad-client', this.options.publisherId);
67
+
68
+ if (this.options.adSlot) {
69
+ ins.setAttribute('data-ad-slot', this.options.adSlot);
70
+ }
71
+
72
+ ins.setAttribute('data-ad-format', this.options.adFormat);
73
+
74
+ if (this.options.fullWidth) {
75
+ ins.setAttribute('data-full-width-responsive', 'true');
76
+ }
77
+
78
+ this.adContainer.appendChild(ins);
79
+ this.player.container.appendChild(this.adContainer);
80
+ }
81
+
82
+ /**
83
+ * Load AdSense script
84
+ */
85
+ loadAdSenseScript() {
86
+ if (document.querySelector('script[src*="adsbygoogle.js"]')) {
87
+ this.initializeAd();
88
+ return;
89
+ }
90
+
91
+ const script = document.createElement('script');
92
+ script.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
93
+ script.async = true;
94
+ script.crossOrigin = 'anonymous';
95
+ script.onload = () => this.initializeAd();
96
+ script.onerror = () => {
97
+ console.error('🎬 Failed to load AdSense script');
98
+ };
99
+ document.head.appendChild(script);
100
+ }
101
+
102
+ /**
103
+ * Initialize ad
104
+ */
105
+ initializeAd() {
106
+ try {
107
+ (window.adsbygoogle = window.adsbygoogle || []).push({});
108
+ this.isAdLoaded = true;
109
+
110
+ if (this.options.debug) {
111
+ console.log('🎬 AdSense ad initialized');
112
+ }
113
+ } catch (error) {
114
+ console.error('🎬 AdSense initialization error:', error);
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Show ad
120
+ */
121
+ showAd() {
122
+ if (this.isAdLoaded) {
123
+ this.adContainer.style.display = 'block';
124
+ this.player.video.pause();
125
+ this.player.triggerEvent('adstarted');
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Hide ad
131
+ */
132
+ hideAd() {
133
+ this.adContainer.style.display = 'none';
134
+ this.player.video.play();
135
+ this.player.triggerEvent('adcomplete');
136
+ }
137
+
138
+ /**
139
+ * Dispose plugin
140
+ */
141
+ dispose() {
142
+ if (this.adContainer) {
143
+ this.adContainer.remove();
144
+ }
145
+
146
+ if (this.options.debug) {
147
+ console.log('🎬 AdSense Video Plugin disposed');
148
+ }
149
+ }
150
+ }
151
+
152
+ // Register plugin globally
153
+ if (typeof window.registerMYETVPlugin === 'function') {
154
+ window.registerMYETVPlugin('adsense', AdSenseVideoPlugin);
155
+ }
156
+
157
+ })();
158
+ /* GLOBAL_END */
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,355 @@
1
+ /* Google IMA Plugin for MYETV Video Player
2
+ * Integrates Google Interactive Media Ads SDK
3
+ * Supports VAST, VMAP, VPAID
4
+ * Created by https://www.myetv.tv https://oskarcosimo.com
5
+ */
6
+
7
+ // ===================================================================
8
+ // GLOBAL CODE - Will be placed OUTSIDE the class by build script
9
+ // ===================================================================
10
+
11
+ /* GLOBAL_START */
12
+ (function () {
13
+ 'use strict';
14
+
15
+ /**
16
+ * Google IMA Ads Plugin
17
+ * Manages video advertising through Google IMA SDK
18
+ */
19
+ class GoogleIMAPlugin {
20
+ constructor(player, options = {}) {
21
+ this.player = player;
22
+ this.options = {
23
+ adTagUrl: options.adTagUrl || '',
24
+ adsResponse: options.adsResponse || null,
25
+ locale: options.locale || 'it',
26
+ showCountdown: options.showCountdown !== false,
27
+ showControls: options.showControls !== false,
28
+ autoPlayAdBreaks: options.autoPlayAdBreaks !== false,
29
+ disableCustomPlaybackForIOS10Plus: options.disableCustomPlaybackForIOS10Plus || false,
30
+ vastLoadTimeout: options.vastLoadTimeout || 5000,
31
+ debug: options.debug || false,
32
+ vpaidMode: options.vpaidMode || 'ENABLED', // ENABLED, INSECURE, DISABLED
33
+ adLabel: options.adLabel || 'Pubblicità',
34
+ adLabelNofN: options.adLabelNofN || 'di',
35
+ nonLinearWidth: options.nonLinearWidth || null,
36
+ nonLinearHeight: options.nonLinearHeight || null,
37
+ numRedirects: options.numRedirects || 4,
38
+ adsRenderingSettings: options.adsRenderingSettings || {},
39
+ ...options
40
+ };
41
+
42
+ this.adDisplayContainer = null;
43
+ this.adsLoader = null;
44
+ this.adsManager = null;
45
+ this.adContainer = null;
46
+ this.contentComplete = false;
47
+ this.isAdPlaying = false;
48
+
49
+ // Check if IMA SDK is loaded
50
+ if (typeof google === 'undefined' || typeof google.ima === 'undefined') {
51
+ console.error('🎬 Google IMA SDK not loaded. Please include: //imasdk.googleapis.com/js/sdkloader/ima3.js');
52
+ return;
53
+ }
54
+
55
+ this.ima = google.ima;
56
+ }
57
+
58
+ /**
59
+ * Setup plugin
60
+ */
61
+ setup() {
62
+ this.createAdContainer();
63
+ this.initializeIMA();
64
+ this.attachPlayerEvents();
65
+
66
+ if (this.options.debug) {
67
+ console.log('🎬 Google IMA Plugin initialized');
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Create ad container element
73
+ */
74
+ createAdContainer() {
75
+ this.adContainer = document.createElement('div');
76
+ this.adContainer.id = `ima-ad-container-${Date.now()}`;
77
+ this.adContainer.className = 'ima-ad-container';
78
+ this.adContainer.style.cssText = `
79
+ position: absolute;
80
+ top: 0;
81
+ left: 0;
82
+ width: 100%;
83
+ height: 100%;
84
+ z-index: 1000;
85
+ display: none;
86
+ `;
87
+ this.player.container.appendChild(this.adContainer);
88
+ }
89
+
90
+ /**
91
+ * Initialize IMA SDK
92
+ */
93
+ initializeIMA() {
94
+ // Set locale
95
+ this.ima.settings.setLocale(this.options.locale);
96
+
97
+ // Set VPAID mode
98
+ if (this.options.vpaidMode === 'DISABLED') {
99
+ this.ima.settings.setVpaidMode(this.ima.ImaSdkSettings.VpaidMode.DISABLED);
100
+ } else if (this.options.vpaidMode === 'INSECURE') {
101
+ this.ima.settings.setVpaidMode(this.ima.ImaSdkSettings.VpaidMode.INSECURE);
102
+ } else {
103
+ this.ima.settings.setVpaidMode(this.ima.ImaSdkSettings.VpaidMode.ENABLED);
104
+ }
105
+
106
+ // Create ad display container
107
+ this.adDisplayContainer = new this.ima.AdDisplayContainer(
108
+ this.adContainer,
109
+ this.player.video
110
+ );
111
+
112
+ // Create ads loader
113
+ this.adsLoader = new this.ima.AdsLoader(this.adDisplayContainer);
114
+
115
+ // Add event listeners
116
+ this.adsLoader.addEventListener(
117
+ this.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
118
+ this.onAdsManagerLoaded.bind(this),
119
+ false
120
+ );
121
+
122
+ this.adsLoader.addEventListener(
123
+ this.ima.AdErrorEvent.Type.AD_ERROR,
124
+ this.onAdError.bind(this),
125
+ false
126
+ );
127
+ }
128
+
129
+ /**
130
+ * Request ads
131
+ */
132
+ requestAds() {
133
+ if (!this.options.adTagUrl && !this.options.adsResponse) {
134
+ console.warn('🎬 No ad tag URL or ads response provided');
135
+ return;
136
+ }
137
+
138
+ // Initialize ad display container on user interaction
139
+ if (!this.adDisplayContainer.initialized) {
140
+ this.adDisplayContainer.initialize();
141
+ }
142
+
143
+ // Create ads request
144
+ const adsRequest = new this.ima.AdsRequest();
145
+
146
+ if (this.options.adsResponse) {
147
+ adsRequest.adsResponse = this.options.adsResponse;
148
+ } else {
149
+ adsRequest.adTagUrl = this.options.adTagUrl;
150
+ }
151
+
152
+ adsRequest.linearAdSlotWidth = this.player.video.clientWidth;
153
+ adsRequest.linearAdSlotHeight = this.player.video.clientHeight;
154
+ adsRequest.nonLinearAdSlotWidth = this.options.nonLinearWidth || this.player.video.clientWidth;
155
+ adsRequest.nonLinearAdSlotHeight = this.options.nonLinearHeight || Math.floor(this.player.video.clientHeight / 3);
156
+ adsRequest.vastLoadTimeout = this.options.vastLoadTimeout;
157
+
158
+ if (this.options.numRedirects) {
159
+ adsRequest.numRedirects = this.options.numRedirects;
160
+ }
161
+
162
+ // Request ads
163
+ this.adsLoader.requestAds(adsRequest);
164
+
165
+ if (this.options.debug) {
166
+ console.log('🎬 Ads requested');
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Ads manager loaded event handler
172
+ */
173
+ onAdsManagerLoaded(adsManagerLoadedEvent) {
174
+ // Get ads manager
175
+ const adsRenderingSettings = new this.ima.AdsRenderingSettings();
176
+ adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
177
+
178
+ // Apply custom rendering settings
179
+ Object.assign(adsRenderingSettings, this.options.adsRenderingSettings);
180
+
181
+ this.adsManager = adsManagerLoadedEvent.getAdsManager(
182
+ this.player.video,
183
+ adsRenderingSettings
184
+ );
185
+
186
+ // Attach ads manager event listeners
187
+ this.attachAdsManagerEvents();
188
+
189
+ try {
190
+ // Initialize ads manager
191
+ this.adsManager.init(
192
+ this.player.video.clientWidth,
193
+ this.player.video.clientHeight,
194
+ this.ima.ViewMode.NORMAL
195
+ );
196
+
197
+ // Start ads
198
+ this.adsManager.start();
199
+
200
+ if (this.options.debug) {
201
+ console.log('🎬 Ads manager loaded and started');
202
+ }
203
+ } catch (adError) {
204
+ console.error('🎬 Ads manager error:', adError);
205
+ this.player.video.play();
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Attach ads manager event listeners
211
+ */
212
+ attachAdsManagerEvents() {
213
+ // Ad started
214
+ this.adsManager.addEventListener(
215
+ this.ima.AdEvent.Type.STARTED,
216
+ () => {
217
+ this.isAdPlaying = true;
218
+ this.adContainer.style.display = 'block';
219
+ this.player.triggerEvent('adstarted');
220
+ if (this.options.debug) console.log('🎬 Ad started');
221
+ }
222
+ );
223
+
224
+ // Ad complete
225
+ this.adsManager.addEventListener(
226
+ this.ima.AdEvent.Type.COMPLETE,
227
+ () => {
228
+ this.player.triggerEvent('adcomplete');
229
+ if (this.options.debug) console.log('🎬 Ad complete');
230
+ }
231
+ );
232
+
233
+ // All ads completed
234
+ this.adsManager.addEventListener(
235
+ this.ima.AdEvent.Type.ALL_ADS_COMPLETED,
236
+ () => {
237
+ this.isAdPlaying = false;
238
+ this.adContainer.style.display = 'none';
239
+ this.player.triggerEvent('allAdscomplete');
240
+ if (this.options.debug) console.log('🎬 All ads completed');
241
+ }
242
+ );
243
+
244
+ // Ad paused
245
+ this.adsManager.addEventListener(
246
+ this.ima.AdEvent.Type.PAUSED,
247
+ () => {
248
+ this.player.triggerEvent('adpaused');
249
+ }
250
+ );
251
+
252
+ // Ad resumed
253
+ this.adsManager.addEventListener(
254
+ this.ima.AdEvent.Type.RESUMED,
255
+ () => {
256
+ this.player.triggerEvent('adresumed');
257
+ }
258
+ );
259
+
260
+ // Ad skipped
261
+ this.adsManager.addEventListener(
262
+ this.ima.AdEvent.Type.SKIPPED,
263
+ () => {
264
+ this.player.triggerEvent('adskipped');
265
+ if (this.options.debug) console.log('🎬 Ad skipped');
266
+ }
267
+ );
268
+
269
+ // Ad error
270
+ this.adsManager.addEventListener(
271
+ this.ima.AdErrorEvent.Type.AD_ERROR,
272
+ this.onAdError.bind(this)
273
+ );
274
+ }
275
+
276
+ /**
277
+ * Ad error event handler
278
+ */
279
+ onAdError(adErrorEvent) {
280
+ console.error('🎬 Ad error:', adErrorEvent.getError());
281
+
282
+ if (this.adsManager) {
283
+ this.adsManager.destroy();
284
+ }
285
+
286
+ this.isAdPlaying = false;
287
+ this.adContainer.style.display = 'none';
288
+
289
+ // Resume content playback
290
+ this.player.video.play();
291
+
292
+ this.player.triggerEvent('aderror', { error: adErrorEvent.getError() });
293
+ }
294
+
295
+ /**
296
+ * Attach player event listeners
297
+ */
298
+ attachPlayerEvents() {
299
+ // Play event - request ads if not already done
300
+ this.player.video.addEventListener('play', () => {
301
+ if (!this.contentComplete && !this.isAdPlaying && this.options.adTagUrl) {
302
+ // Request ads on first play
303
+ this.requestAds();
304
+ }
305
+ });
306
+
307
+ // Content ended
308
+ this.player.video.addEventListener('ended', () => {
309
+ this.contentComplete = true;
310
+ if (this.adsLoader) {
311
+ this.adsLoader.contentComplete();
312
+ }
313
+ });
314
+
315
+ // Window resize
316
+ window.addEventListener('resize', () => {
317
+ if (this.adsManager && this.isAdPlaying) {
318
+ this.adsManager.resize(
319
+ this.player.video.clientWidth,
320
+ this.player.video.clientHeight,
321
+ this.ima.ViewMode.NORMAL
322
+ );
323
+ }
324
+ });
325
+ }
326
+
327
+ /**
328
+ * Dispose plugin
329
+ */
330
+ dispose() {
331
+ if (this.adsManager) {
332
+ this.adsManager.destroy();
333
+ }
334
+
335
+ if (this.adsLoader) {
336
+ this.adsLoader.destroy();
337
+ }
338
+
339
+ if (this.adContainer) {
340
+ this.adContainer.remove();
341
+ }
342
+
343
+ if (this.options.debug) {
344
+ console.log('🎬 Google IMA Plugin disposed');
345
+ }
346
+ }
347
+ }
348
+
349
+ // Register plugin globally
350
+ if (typeof window.registerMYETVPlugin === 'function') {
351
+ window.registerMYETVPlugin('googleIMA', GoogleIMAPlugin);
352
+ }
353
+
354
+ })();
355
+ /* GLOBAL_END */