File size: 3,652 Bytes
11452ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { PostsService } from 'app/posts.services';
import CryptoJS from 'crypto-js';

@Component({
  selector: 'app-skip-ad-button',
  templateUrl: './skip-ad-button.component.html',
  styleUrls: ['./skip-ad-button.component.scss']
})
export class SkipAdButtonComponent implements OnInit {

  @Input() current_video = null;
  @Input() playback_timestamp = null;
  
  @Output() setPlaybackTimestamp = new EventEmitter<any>();

  sponsor_block_cache = {};
  show_skip_ad_button = false;

  skip_ad_button_check_interval = null;

  constructor(private postsService: PostsService) { }

  ngOnInit(): void {
    this.skip_ad_button_check_interval = setInterval(() => this.skipAdButtonCheck(), 500);
  }

  ngOnDestroy(): void {
    clearInterval(this.skip_ad_button_check_interval);
  }

  checkSponsorBlock(video_to_check) {
    if (!video_to_check) return;

    // check cache, null means it has been checked and confirmed not to exist (limits API calls)
    if (this.sponsor_block_cache[video_to_check.url] || this.sponsor_block_cache[video_to_check.url] === null) return;

    // sponsor block needs first 4 chars from video ID hash
    const video_id = this.getVideoIDFromURL(video_to_check.url);
    const id_hash = this.getVideoIDHashFromURL(video_id);
    if (!id_hash || id_hash.length < 4) return;
    const truncated_id_hash = id_hash.substring(0, 4);

    // we couldn't get the data from the cache, let's get it from sponsor block directly

    this.postsService.getSponsorBlockDataForVideo(truncated_id_hash).subscribe(res => {
      if (res && res['length'] && res['length'] === 0) {
        return;
      }

      const found_data = res['find'](data => data['videoID'] === video_id);
      if (found_data) {
        this.sponsor_block_cache[video_to_check.url] = found_data;
      } else {
        this.sponsor_block_cache[video_to_check.url] = null;
      }
    }, err => {
      // likely doesn't exist
      this.sponsor_block_cache[video_to_check.url] = null;
    });
  }

  getVideoIDHashFromURL(video_id) {
    if (!video_id) return null;
    return CryptoJS.SHA256(video_id).toString(CryptoJS.enc.Hex);
  }

  getVideoIDFromURL(url) {
    const regex_exp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
    const match = url.match(regex_exp);
    return (match && match[7].length==11) ? match[7] : null;
  }

  skipAdButtonCheck() {
    const sponsor_block_data = this.sponsor_block_cache[this.current_video.url];
    if (!sponsor_block_data && sponsor_block_data !== null) {
      // we haven't yet tried to get the sponsor block data for the video
      this.checkSponsorBlock(this.current_video);
    } else if (!sponsor_block_data) {
      this.show_skip_ad_button = false;
      return;
    }

    if (this.getTimeToSkipTo()) {
      this.show_skip_ad_button = true;
    } else {
      this.show_skip_ad_button = false;
    }
  }

  getTimeToSkipTo() {
    const sponsor_block_data = this.sponsor_block_cache[this.current_video.url];

    if (!sponsor_block_data) return;

    // check if we're in between an ad segment
    const found_segment = sponsor_block_data['segments'].find(segment_data => this.playback_timestamp > segment_data.segment[0] && this.playback_timestamp < segment_data.segment[1] - 0.5);

    if (found_segment) {
      return found_segment['segment'][1];
    }

    return null;
  }

  skipAdButtonClicked() {
    const time_to_skip_to = this.getTimeToSkipTo();
    if (!time_to_skip_to) return;

    this.setPlaybackTimestamp.emit(time_to_skip_to);

    this.show_skip_ad_button = false;
  }

}