unoffical wafrn mirror
wafrn.net
atproto
social-network
activitypub
1import { Component, Injector, OnInit, DOCUMENT, HostBinding, ElementRef, effect, inject } from '@angular/core'
2import { SwUpdate } from '@angular/service-worker'
3import { LoginService } from './services/login.service'
4import { EnvironmentService } from './services/environment.service'
5import { TranslateService } from '@ngx-translate/core'
6import { SwPush } from '@angular/service-worker'
7import { Title } from '@angular/platform-browser'
8import { GlobalData } from './services/global-data.service'
9import { WebsocketService } from './services/websocket.service'
10import { NavigationError, Router } from '@angular/router'
11import { filter, map } from 'rxjs'
12import { MessageService } from './services/message.service'
13import { supportedLanguages } from './lists/languages'
14import { ThemeService } from './services/theme.service'
15import { PostsService } from './services/posts.service'
16
17@Component({
18 selector: 'app-root',
19 templateUrl: './app.component.html',
20 styleUrls: ['./app.component.scss'],
21 standalone: false
22})
23export class AppComponent implements OnInit {
24 private swUpdate = inject(SwUpdate);
25 private swPush = inject(SwPush);
26 private injector = inject(Injector);
27 private loginService = inject(LoginService);
28 private environmentService = inject(EnvironmentService);
29 private document = inject<Document>(DOCUMENT);
30 private translateService = inject(TranslateService);
31 private websocketService = inject(WebsocketService);
32 private router = inject(Router);
33 private messages = inject(MessageService);
34 private titleService = inject(Title);
35 private postService = inject(PostsService)
36
37
38 title = 'wafrn'
39
40 @HostBinding('attr.data-additional-style-modes') dataAdditionalStyleModes: string | null = null
41
42 constructor() {
43 const swUpdate = this.swUpdate;
44 const translateService = this.translateService;
45 const router = this.router;
46 const themeService = inject(ThemeService);
47
48 this.title = this.titleService.getTitle()
49 GlobalData.appDefaultTitle = this.title
50
51 this.translateService.addLangs([...supportedLanguages])
52 this.translateService.setDefaultLang('en')
53
54 // User specified language
55 const userLanguage = localStorage?.getItem('appLanguage')
56 if (userLanguage !== null && translateService.langs.includes(userLanguage)) {
57 // Given the above call to add languages is correct to what we have, this should always succeed
58 translateService.use(userLanguage)
59 }
60
61 // Keep the 'lang' property up to date
62 const currentLang = this.translateService.currentLang || this.translateService.getDefaultLang() || 'en'
63 this.document.documentElement.lang = currentLang
64 this.translateService.onLangChange.subscribe((event) => {
65 this.document.documentElement.lang = event.lang
66 })
67
68 router.events
69 .pipe(
70 filter((evt) => evt instanceof NavigationError),
71 map((evt) => evt as NavigationError)
72 )
73 .subscribe((evt) => {
74 if (evt.error instanceof Error && evt.error.name == 'ChunkLoadError') {
75 window.location.assign(evt.url)
76 }
77 })
78 swUpdate.unrecoverable.subscribe((event) => {
79 navigator.serviceWorker.getRegistrations().then(function (registrations) {
80 for (const registration of registrations) {
81 registration.unregister()
82 }
83 window.location.reload()
84 })
85 })
86
87 // Sync data value of additional style modes to root
88 effect(() => {
89 const attributeValue = Object.entries(themeService.additionalStyleModes)
90 .filter(([_, value]) => value())
91 .map(([mode, _]) => mode)
92 .join(' ')
93 this.dataAdditionalStyleModes = attributeValue || null
94 })
95 }
96
97 ngOnInit() {
98
99 // lets check for evil websites. fuck them.
100 const referer = document.referrer;
101 if(referer) {
102 console.log(referer)
103 try {
104 let evilUrls = [
105 '4chan.org',
106 'p.4chan.org',
107 '8chan.org',
108 '8kun.top',
109 'kiwifarms.st',
110 'truthsocial.com',
111 'poast.org',
112 '13bells.com',
113 '1611.social',
114 '4aem.com',
115 '5dollah.click',
116 'adachi.party',
117 'adtension.com',
118 'annihilation.social',
119 'anon-kenkai.com',
120 'asbestos.cafe',
121 'bae.st',
122 'banepo.st',
123 'bassam.social',
124 'battlepenguin.video',
125 'beefyboys.win',
126 'boymoder.biz',
127 'brainsoap.net',
128 'breastmilk.club',
129 'brighteon.social',
130 'cachapa.cc',
131 'cachapa.xyz',
132 'caekis.love',
133 'cawfee.club',
134 'childlove.su',
135 'clew.lol',
136 'clubcyberia.co',
137 'contrapointsfan.club',
138 'cottoncandy.cafe',
139 'crlf.ninja',
140 'crucible.world',
141 'cum.camp',
142 'cum.salon',
143 'cunnyborea.space',
144 'decayable.ink',
145 'dembased.xyz',
146 'detroitriotcity.com',
147 'djsumdog.com',
148 'drinkanddrive.africa',
149 'eientei.org',
150 'eveningzoo.club',
151 'fluf.club',
152 'foxgirl.lol',
153 'freak.university',
154 'freeatlantis.com',
155 'freespeechextremist.com',
156 'froth.zone',
157 'fsebugoutzone.org',
158 'gameliberty.club',
159 'gearlandia.haus',
160 'genderheretics.xyz',
161 'geofront.rocks',
162 'gleasonator.com',
163 'glee.li',
164 'glindr.org',
165 'goyim.social',
166 'h5q.net',
167 'haeder.net',
168 'handholding.io',
169 'harpy.faith',
170 'hitchhiker.social',
171 'iddqd.social',
172 'kitsunemimi.club',
173 'kiwifarms.cc',
174 'kurosawa.moe',
175 'kyaruc.moe',
176 'leafposter.club',
177 'liberdon.com',
178 'ligma.pro',
179 'loli.church',
180 'lolicon.rocks',
181 'lolison.network',
182 'lolison.top',
183 'lovingexpressions.net',
184 'makemysarcophagus.com',
185 'mastinator.com',
186 'merovingian.club',
187 'midwaytrades.com',
188 'mirr0r.city',
189 'morale.ch',
190 'mouse.services',
191 'mugicha.club',
192 'narrativerry.xyz',
193 'nationalist.social',
194 'needs.vodka',
195 'neenster.org',
196 'nicecrew.digital',
197 'nightshift.social',
198 'nnia.space',
199 'noagendasocial.com',
200 'noagendatube.com',
201 'noauthority.social',
202 'nobodyhasthe.biz',
203 'norwoodzero.net',
204 'nyanide.com',
205 'onionfarms.org',
206 'parcero.casa',
207 'pawlicker.com',
208 'pawoo.net',
209 'pedo.school',
210 'peertube.se',
211 'peervideo.club',
212 'piazza.today',
213 'pibvt.net',
214 'pieville.net',
215 'pisskey.io',
216 'plagu.ee',
217 'poa.st',
218 'poast.org',
219 'poast.tv',
220 'poster.place',
221 'prospeech.space',
222 'quodverum.com',
223 'r18.social',
224 'rakket.app',
225 'rapemeat.express',
226 'rapemeat.solutions',
227 'rayci.st',
228 'rebelbase.site',
229 'ryona.agency',
230 'sad.cab',
231 'schwartzwelt.xyz',
232 'seal.cafe',
233 'shaw.app',
234 'shigusegubu.club',
235 'shitpost.cloud',
236 'shortstacksran.ch',
237 'silliness.observer',
238 'skinheads.eu',
239 'skinheads.io',
240 'skinheads.social',
241 'skinheads.uk',
242 'skippers-bin.com',
243 'skyshanty.xyz',
244 'slash.cl',
245 'sleepy.cafe',
246 'smuglo.li',
247 'sneed.social',
248 'sonichu.com',
249 'spinster.xyz',
250 'springbo.cc',
251 'strelizia.net',
252 'subs4social.xyz',
253 'taihou.website',
254 'tastingtraffic.net',
255 'teci.world',
256 'theblab.org',
257 'thechimp.zone',
258 'thenobody.club',
259 'thepostearthdestination.com',
260 'tkammer.de',
261 'trumpislovetrumpis.life',
262 'truthsocial.co.in',
263 'tsundere.love',
264 'usualsuspects.lol',
265 'vampiremaid.cafe',
266 'varishangout.net',
267 'volk.love',
268 'volk.network',
269 'wolfgirl.bar',
270 'xn--p1abe3d.xn--80asehdb',
271 'yggdrasil.social',
272 'youjo.love',
273 'zhub.link',
274 // spanish 4chan
275 'forocoches.com',
276 // finish kiwifarms
277 'ylilauta.org',
278 'hommaforum.org'
279 ]
280 const refererUrl = new URL(referer)
281 if(evilUrls.includes(refererUrl.host)) {
282 while(true) {
283 let i = 0;
284 i ++;
285 }
286 }
287 } catch (error) {
288 // we dont care too much
289 }
290 }
291
292 // unregister serviceworkers
293 /*navigator.serviceWorker.getRegistrations().then(function (registrations) {
294 for (const registration of registrations) {
295 registration.unregister();
296 }
297 });*/
298 const wafrnUpdated = localStorage.getItem('wafrnUpdated')
299 if (wafrnUpdated == 'true') {
300 localStorage.removeItem('wafrnUpdated')
301 this.messages.add({ severity: 'success', summary: 'Wafrn has been updated!' })
302 }
303 if (this.swUpdate.isEnabled) {
304 console.log('SOFTWARE UPDATES ACTIVE - This is a PWA')
305 this.swUpdate.checkForUpdate().then((updateAvaiable) => {
306 if (EnvironmentService.environment.disablePWA) {
307 if ('caches' in window) {
308 caches.keys().then(function (keyList) {
309 return Promise.all(
310 keyList.map(function (key) {
311 return caches.delete(key)
312 })
313 )
314 })
315 }
316 if (window.navigator && navigator.serviceWorker) {
317 navigator.serviceWorker.getRegistrations().then(function (registrations) {
318 for (const registration of registrations) {
319 registration.unregister()
320 }
321 })
322 }
323 }
324 // we are no longer asking nicely
325 if (updateAvaiable) {
326 localStorage.setItem('wafrnUpdated',
327 'true')
328 if (window.location.toString().toLowerCase().endsWith('/editor')) {
329 if (confirm('There is an update available, would you like to update?')) {
330 window.location.reload()
331 } else {
332 alert('Please reload manualy after writing the post!')
333 }
334 } else {
335 window.location.reload()
336 }
337 }
338 })
339 }
340
341 if (EnvironmentService.environment.disablePWA) {
342 if ('caches' in window) {
343 caches.keys().then(function (keyList) {
344 return Promise.all(
345 keyList.map(function (key) {
346 return caches.delete(key)
347 })
348 )
349 })
350 }
351 if (window.navigator && navigator.serviceWorker) {
352 navigator.serviceWorker.getRegistrations().then(function (registrations) {
353 for (const registration of registrations) {
354 registration.unregister()
355 }
356 })
357 }
358 }
359 // TODO lets keep with this later
360 /*
361 if (this.swPush.isEnabled && EnvironmentService.environment.webpushPublicKey) {
362 this.swPush
363 .requestSubscription({
364 serverPublicKey: EnvironmentService.environment.webpushPublicKey
365 })
366 .then((notificationSubscription) => {
367 console.log(notificationSubscription)
368 })
369 }
370 */
371
372
373 this.postService.loadFollowers().then(() => {
374 })
375
376 }
377}