1
+ ( function ( ) {
2
+
3
+ window . addEventListener ( 'unhandledrejection' , ( event ) => {
4
+ console . error ( 'Unhandled promise rejection:' , event . reason ) ;
5
+ } ) ;
6
+
7
+ function toDataURL ( url , callback ) {
8
+ var xhr = new XMLHttpRequest ( ) ;
9
+ xhr . onload = function ( ) {
10
+
11
+ var blob = xhr . response ;
12
+
13
+ if ( blob . size > ( 25 * 1024 ) ) {
14
+ callback ( url ) ; // Image size is larger than 25kb.
15
+ return ;
16
+ }
17
+
18
+ var reader = new FileReader ( ) ;
19
+
20
+
21
+ reader . onloadend = function ( ) {
22
+ callback ( reader . result ) ;
23
+ }
24
+ reader . readAsDataURL ( xhr . response ) ;
25
+ } ;
26
+ xhr . open ( 'GET' , url ) ;
27
+ xhr . responseType = 'blob' ;
28
+ xhr . send ( ) ;
29
+ }
30
+
31
+ function escapeHtml ( unsafe ) { // success is when goofs be trying to hack me
32
+ return unsafe
33
+ . replace ( / & / g, "&" )
34
+ . replace ( / < / g, "<" )
35
+ . replace ( / > / g, ">" )
36
+ . replace ( / " / g, """ )
37
+ . replace ( / ' / g, "'" ) || "" ;
38
+ }
39
+ function getAllContentNodes ( element ) {
40
+ var resp = "" ;
41
+
42
+ if ( ! element . childNodes || ! element . childNodes . length ) {
43
+ if ( element . nodeType === 3 ) {
44
+ return escapeHtml ( element . textContent ) || "" ;
45
+ }
46
+ }
47
+
48
+ element . childNodes . forEach ( node => {
49
+ if ( node . childNodes . length ) {
50
+ resp += getAllContentNodes ( node )
51
+ } else if ( ( node . nodeType === 3 ) && node . textContent && ( node . textContent . trim ( ) . length > 0 ) ) {
52
+ resp += escapeHtml ( node . textContent ) ;
53
+ } else if ( node . nodeType === 1 ) {
54
+ if ( ! settings . textonlymode ) {
55
+ if ( ( node . nodeName == "IMG" ) && node . src ) {
56
+ node . src = node . src + "" ;
57
+ }
58
+ resp += node . outerHTML ;
59
+ }
60
+ }
61
+ } ) ;
62
+ return resp ;
63
+ }
64
+
65
+
66
+ function processMessage ( ele ) {
67
+
68
+ var chatimg = "" ;
69
+ try {
70
+ chatimg = ele . querySelector ( "[data-sentry-component='UserAvatar'] img[src]" ) . src ;
71
+ } catch ( e ) {
72
+ }
73
+
74
+ var name = "" ;
75
+ try {
76
+ name = ele . querySelector ( "[data-sentry-component='UserInlineWithBadges'] span" ) . textContent . trim ( ) ;
77
+ name = escapeHtml ( name ) ;
78
+ } catch ( e ) {
79
+ }
80
+
81
+ var chatbadges = [ ] ;
82
+ try {
83
+ ele . querySelector ( "[data-sentry-component='UserInlineWithBadges'] svg, [data-sentry-component='UserInlineWithBadges'] img" ) . forEach ( badge => {
84
+ if ( badge . srcset ) {
85
+ let bb = badge . srcset . split ( "https://" ) . pop ( ) ;
86
+ if ( bb ) {
87
+ bb = "https://" + bb . split ( " " ) [ 0 ] ;
88
+ if ( ! chatbadges . includes ( bb ) ) {
89
+ chatbadges . push ( bb ) ;
90
+ }
91
+ }
92
+ } else if ( badge && badge . nodeName == "IMG" ) {
93
+ var tmp = { } ;
94
+ tmp . src = badge . src + "" ;
95
+ tmp . type = "img" ;
96
+ chatbadges . push ( tmp ) ;
97
+ } else if ( badge && badge . nodeName . toLowerCase ( ) == "svg" ) {
98
+ var tmp = { } ;
99
+ tmp . html = badge . outerHTML ;
100
+ tmp . type = "svg" ;
101
+ chatbadges . push ( tmp ) ;
102
+ }
103
+ } ) ;
104
+ } catch ( e ) { }
105
+
106
+ var msg = "" ;
107
+ try {
108
+ ele . querySelectorAll ( "span.inline.text" ) . forEach ( xx => {
109
+ msg += getAllContentNodes ( xx ) ;
110
+ } ) ;
111
+ } catch ( e ) {
112
+ }
113
+
114
+
115
+ var data = { } ;
116
+ data . chatname = name ;
117
+ data . chatbadges = chatbadges ;
118
+ data . backgroundColor = "" ;
119
+ data . textColor = "" ;
120
+ data . chatmessage = msg ;
121
+ data . chatimg = chatimg ;
122
+ data . hasDonation = "" ;
123
+ data . membership = "" ; ;
124
+ data . contentimg = "" ;
125
+ data . textonly = settings . textonlymode || false ;
126
+ data . type = "favorited" ;
127
+
128
+ console . log ( data ) ;
129
+
130
+ pushMessage ( data ) ;
131
+ }
132
+
133
+ function pushMessage ( data ) {
134
+ try {
135
+ chrome . runtime . sendMessage ( chrome . runtime . id , { "message" : data } , function ( e ) { } ) ;
136
+ } catch ( e ) {
137
+ }
138
+ }
139
+
140
+ var settings = { } ;
141
+ // settings.textonlymode
142
+ // settings.captureevents
143
+
144
+
145
+ chrome . runtime . sendMessage ( chrome . runtime . id , { "getSettings" : true } , function ( response ) { // {"state":isExtensionOn,"streamID":channel, "settings":settings}
146
+ if ( "settings" in response ) {
147
+ settings = response . settings ;
148
+ }
149
+ } ) ;
150
+
151
+ chrome . runtime . onMessage . addListener (
152
+ function ( request , sender , sendResponse ) {
153
+ try {
154
+ if ( "focusChat" == request ) {
155
+ document . querySelector ( 'input[placeholder]' ) . focus ( ) ;
156
+ sendResponse ( true ) ;
157
+ return ;
158
+ }
159
+ if ( typeof request === "object" ) {
160
+ if ( "settings" in request ) {
161
+ settings = request . settings ;
162
+ sendResponse ( true ) ;
163
+ return ;
164
+ }
165
+ }
166
+ } catch ( e ) { }
167
+ sendResponse ( false ) ;
168
+ }
169
+ ) ;
170
+
171
+ var lastURL = "" ;
172
+ var observer = null ;
173
+
174
+
175
+ function onElementInserted ( target ) {
176
+
177
+ var onMutationsObserved = function ( mutations ) {
178
+ mutations . forEach ( function ( mutation ) {
179
+ if ( mutation . addedNodes . length ) {
180
+
181
+ for ( var i = 0 , len = mutation . addedNodes . length ; i < len ; i ++ ) {
182
+ try {
183
+ if ( mutation . addedNodes [ i ] . skip ) { continue ; }
184
+ mutation . addedNodes [ i ] . skip = true ;
185
+ if ( mutation . addedNodes [ i ] . dataset . sentryComponent ) {
186
+ setTimeout ( function ( ele ) {
187
+ processMessage ( ele ) ;
188
+ } , 400 , mutation . addedNodes [ i ] ) ;
189
+ }
190
+ } catch ( e ) { }
191
+ }
192
+ }
193
+ } ) ;
194
+ } ;
195
+
196
+ var config = { childList : true , subtree : true } ;
197
+ var MutationObserver = window . MutationObserver || window . WebKitMutationObserver ;
198
+
199
+ observer = new MutationObserver ( onMutationsObserved ) ;
200
+ observer . observe ( target , config ) ;
201
+ }
202
+
203
+ console . log ( "social stream injected" ) ;
204
+
205
+ setInterval ( function ( ) {
206
+ try {
207
+ if ( ! document . querySelector ( '[data-sentry-element="ScrollableCardContent"]' ) . marked ) {
208
+ document . querySelector ( '[data-sentry-element="ScrollableCardContent"]' ) . marked = true ;
209
+ console . log ( "CONNECTED chat detected" ) ;
210
+ setTimeout ( function ( ) {
211
+ document . querySelectorAll ( '[data-sentry-component="ChatMessageUser"' ) . forEach ( ele => {
212
+ ele . skip = true ;
213
+ } ) ;
214
+ onElementInserted ( document . querySelector ( '[data-sentry-element="ScrollableCardContent"]' ) ) ;
215
+ } , 1000 ) ;
216
+ }
217
+ } catch ( e ) { }
218
+ } , 2000 ) ;
219
+
220
+ } ) ( ) ;
0 commit comments