Adityadn commited on
Commit
1bdc4ba
·
verified ·
1 Parent(s): b094f43

Update script.js

Browse files
Files changed (1) hide show
  1. script.js +1167 -1167
script.js CHANGED
@@ -1,1167 +1,1167 @@
1
- function getQueryParam(param) {
2
- const urlParams = new URLSearchParams(window.location.search);
3
- return urlParams.get(param);
4
- }
5
-
6
- const fN = "Aditya Dwi Nugraha";
7
- const whatsappNumber = "6289668041554";
8
-
9
- var fromName = fN;
10
- let urlsdatasDB = {};
11
- let urlsdataDB = {};
12
- let urlDB = "";
13
- let ucapanGabungan = "";
14
- let renderedUcapanGabungan = "";
15
-
16
- var inputConfigs = [
17
- {
18
- label: "Nama Anda:",
19
- type: "text",
20
- placeholder: "Masukkan nama anda",
21
- id: "targetName",
22
- value: "",
23
- },
24
- ];
25
-
26
- var selectConfigs = [
27
- {
28
- label: `Pilih relasi (hubungan) antara Anda dan ${fromName}:`,
29
- options: [
30
- { value: "0", label: "Anak anda" },
31
- { value: "1", label: "Keponakan anda" },
32
- { value: "2", label: "Murid anda" },
33
- { value: "3", label: "Saudaramu" },
34
- { value: "4", label: "Sepupumu" },
35
- { value: "5", label: "Sahabatmu" },
36
- { value: "6", label: "Temanmu" },
37
- { value: "7", label: "Orang lain" },
38
- ],
39
- default: "6",
40
- id: "relationshipOption",
41
- },
42
- ];
43
-
44
- const innerHTMLOnTopMessage = `<h2 class="mb-3">Masukkan Nama Penerima & Pilih Relasi</h2>`;
45
-
46
- try {
47
- const GEMINI_API_KEY = atob(
48
- "QUl6YVN5QzUyNGNQREdEcWRZSnZkYmNtaUZ2N1Q2QzRnbE9JQXNR"
49
- );
50
- const MODEL_ID = "gemini-1.5-flash";
51
- const GENERATE_CONTENT_API = "streamGenerateContent";
52
-
53
- var noUcapan = "Ucapan tidak tersedia. Silakan coba lagi nanti.";
54
-
55
- const tryErrorMessage = document.querySelectorAll(".tryErrorMessage");
56
- const tryOtherMessage = document.querySelectorAll(".tryOtherMessage");
57
-
58
- const relationshipMapping = {
59
- 0: "Ayah/Ibu",
60
- 1: "Pakde/Bude",
61
- 2: "Guru",
62
- 3: "Saudara",
63
- 4: "Sepupu",
64
- 5: "Sahabat",
65
- 6: "Teman",
66
- 7: "Tidak dikenal alias orang lain",
67
- };
68
-
69
- async function generateUcapan(
70
- name,
71
- option,
72
- regenerate = false,
73
- isChange = false
74
- ) {
75
- const targetName = name;
76
- const relationship =
77
- relationshipMapping[option.toString()] || relationshipMapping["6"];
78
- // const language = [0, 1, 2].includes(parseInt(option))
79
- // ? "Sopan"
80
- // : `Gaul tapi tetap Sopan dan tidak berlebihan, karena INGAT! SAYA LAKI LAKI GENTLEMAN DAN PUNYA WIBAWA!. jangan pakai "lo" tapi "kamu"`;
81
-
82
- const payload = {
83
- contents: [
84
- {
85
- role: "user",
86
- parts: [{ text: `Nama targetnya: ${targetName}` }],
87
- },
88
- ],
89
- systemInstruction: {
90
- parts: [
91
- { text: "Sekarang tahun 1446H." },
92
- {
93
- text: 'Langsung mulai dengan "Assalamu\'alaikum Wr. Wb." alias salam lalu "Taqabbalallah wa minna ...." dan "Untuk ..." tanpa basa-basi.',
94
- },
95
- {
96
- text: `Buat kartu ucapan Idul Fitri yang personal untuk ${targetName} berdasarkan jenis kelamin dan hubungan sebagai ${relationship}. Jika hubungan adalah "teman", jangan gunakan kata-kata romantis seperti "sayang", "ku cinta", atau istilah sejenis yang terkesan intim secara romantis.`,
97
- },
98
- {
99
- text: `Sertakan kalimat "Kami sekeluarga ${fromName} mengucapkan..." jika hubungan bukan termasuk keluarga saya (Ayah/Ibu/Saudara). Jika termasuk keluarga saya maka beda lagi kalimatnya! Misal kalau untuk ibu: "Untuk ibuku yang tercinta..." atau kalau saudara: "Untuk ${targetName} yang ku cinta...".`,
100
- },
101
- {
102
- text: "Setelah itu, lanjutkan ucapan dengan salam pembuka, doa, permohonan maaf, dan harapan yang hangat namun tidak berlebihan karena saya laki-laki yang gentleman punya wibawa.",
103
- },
104
- {
105
- text: `Berikan emoji di setiap kalimat sebanyak-banyaknya untuk kesan asik dan santai.`,
106
- },
107
- {
108
- text: "Jadikan bahasa manusia agak kaku agar tidak dikira robot.",
109
- },
110
- {
111
- text: 'Ingat! Langsung mulai dengan "Assalamu\'alaikum Wr. Wb." alias salam lalu "Untuk ..." tanpa basa-basi.',
112
- },
113
- {
114
- text: `INGAT KALAU KELUARGA SENDIRI TIDAK PAKAI KALIMAT "kami sekeluarga ${fromName}"!!!!!`,
115
- },
116
- ],
117
- },
118
- generationConfig: {
119
- responseMimeType: "text/plain",
120
- },
121
- };
122
-
123
- ucapanGabungan = "";
124
- let isFDB = false;
125
- let isCU = false;
126
-
127
- urlsdatasDB = (await getURLSDATAs())[0];
128
-
129
- localStorage.setItem("data", JSON.stringify(urlsdatasDB));
130
-
131
- for (const [key, data] of Object.entries(urlsdatasDB)) {
132
- if (
133
- data.from === fromName &&
134
- data.target === name &&
135
- data.option === option &&
136
- data.message &&
137
- data.message !== noUcapan
138
- ) {
139
- ucapanGabungan = data.message;
140
- urlDB = `${window.location.origin}?i=` + key;
141
- isFDB = true;
142
-
143
- localStorage.setItem("url", key);
144
- break;
145
- }
146
- }
147
-
148
- const logic =
149
- (!isFDB && !regenerate && !isChange) ||
150
- (isFDB && regenerate && !isChange) ||
151
- (!isFDB && regenerate && isChange);
152
-
153
- console.log([regenerate, isFDB, isChange], logic);
154
-
155
- try {
156
- if (logic) {
157
- const response = await fetch(
158
- `https://generativelanguage.googleapis.com/v1beta/models/${MODEL_ID}:${GENERATE_CONTENT_API}?key=${GEMINI_API_KEY}`,
159
- {
160
- method: "POST",
161
- headers: { "Content-Type": "application/json" },
162
- body: JSON.stringify(payload),
163
- }
164
- );
165
-
166
- const data = await response.json();
167
-
168
- ucapanGabungan = "";
169
- isCU = true;
170
-
171
- if (Array.isArray(data)) {
172
- data.forEach((item) => {
173
- if (
174
- item &&
175
- item.candidates &&
176
- item.candidates[0] &&
177
- item.candidates[0].content &&
178
- item.candidates[0].content.parts &&
179
- item.candidates[0].content.parts[0] &&
180
- item.candidates[0].content.parts[0].text
181
- ) {
182
- ucapanGabungan +=
183
- item.candidates[0].content.parts[0].text;
184
- }
185
- });
186
- ucapanGabungan = ucapanGabungan.trim();
187
- } else {
188
- ucapanGabungan = noUcapan;
189
- }
190
- }
191
-
192
- console.log("Ucapan:", ucapanGabungan);
193
- } catch (error) {
194
- ucapanGabungan = noUcapan;
195
-
196
- console.error("Error:", error);
197
- }
198
-
199
- if (!ucapanGabungan.trim() || ucapanGabungan === noUcapan) {
200
- tryErrorMessage.forEach((elm) => {
201
- do {
202
- elm.classList.remove("d-none");
203
- } while (elm.classList.contains("d-none"));
204
- });
205
- } else {
206
- tryOtherMessage.forEach((elm) => {
207
- do {
208
- elm.classList.remove("d-none");
209
- } while (elm.classList.contains("d-none"));
210
- });
211
-
212
- const data = {
213
- from: fromName,
214
- target: name,
215
- option: parseInt(option),
216
- message: ucapanGabungan,
217
- };
218
-
219
- if (isCU) {
220
- [urlDB, urlsdataDB] = await generateUrl(Object.values(data));
221
-
222
- urlsdatasDB[urlDB] = urlsdataDB;
223
-
224
- localStorage.setItem(
225
- "url",
226
- urlDB
227
- .replace(window.location.origin, "")
228
- .replace(urlDB.origin, "")
229
- .replace("?i=", "")
230
- );
231
- function isCircular(obj, seen = new WeakSet()) {
232
- if (typeof obj !== "object" || obj === null) return false;
233
- if (seen.has(obj)) return true;
234
- seen.add(obj);
235
- return Object.values(obj).some((value) =>
236
- isCircular(value, seen)
237
- );
238
- }
239
-
240
- if (isCircular(urlsdataDB)) {
241
- console.error("Data mengandung referensi circular!");
242
- } else {
243
- localStorage.setItem(urlDB, JSON.stringify(urlsdataDB));
244
- }
245
- }
246
- }
247
-
248
- return [ucapanGabungan, urlDB];
249
- }
250
-
251
- async function tampilkanKartu(
252
- name,
253
- option,
254
- regenerate = false,
255
- isChange = false
256
- ) {
257
- // document.getElementById("cardTitle").innerText = `Untuk ${name}`;
258
- // document.getElementById("cardSection").style.display = "block";
259
-
260
- console.log(name, option, regenerate);
261
-
262
- [ucapanGabungan, urlDB] = await generateUcapan(
263
- name,
264
- option,
265
- regenerate,
266
- isChange
267
- );
268
-
269
- document.getElementById("cardMessage").innerHTML =
270
- marked.parse(ucapanGabungan);
271
-
272
- alert(`Akses halaman ini di: ${urlDB}`, false);
273
-
274
- if (window.location.href.replace("/?", "?") !== urlDB) {
275
- await alert(`Kamu akan diarahkan ke halaman ${urlDB}`);
276
- await new Promise((res) => setTimeout(res, 1000));
277
- window.location.href = urlDB;
278
- }
279
- }
280
-
281
- async function getUser() {
282
- let url = localStorage.getItem("url");
283
- let data = localStorage.getItem("data");
284
-
285
- if (data) {
286
- try {
287
- data = JSON.parse(data);
288
- } catch (e) {
289
- data = await getURLSDATAs();
290
- }
291
- } else {
292
- data = await getURLSDATAs();
293
- }
294
-
295
- console.log(url, data);
296
-
297
- return url && data ? data[url] || null : null;
298
- }
299
-
300
- async function setConfigs() {
301
- urlsdataDB = await getUser();
302
-
303
- console.log(urlsdataDB);
304
-
305
- if (urlsdataDB) {
306
- inputConfigs[0].value = urlsdataDB.target;
307
- selectConfigs[0].label = `Pilih relasi (hubungan) antara Anda dan ${urlsdataDB.from}:`;
308
- selectConfigs[0].default = urlsdataDB.option;
309
- }
310
- }
311
-
312
- async function handleTryClick(target) {
313
- target.classList.add("d-none");
314
-
315
- await setConfigs();
316
-
317
- const res = await multiPrompt(
318
- inputConfigs,
319
- selectConfigs,
320
- innerHTMLOnTopMessage
321
- );
322
-
323
- if (!res.isCancel) {
324
- userName = res["inputValues"]["targetName"];
325
- userOption = res["selectValues"]["relationshipOption"];
326
-
327
- let isC = false;
328
-
329
- urlsdataDB = await getUser();
330
-
331
- if (urlsdataDB) {
332
- if (
333
- (urlsdataDB.target === userName &&
334
- urlsdataDB.option !== userOption) ||
335
- (urlsdataDB.target !== userName &&
336
- urlsdataDB.option === userOption)
337
- ) {
338
- isC = true;
339
- }
340
- } else {
341
- isC = true;
342
- }
343
-
344
- await tampilkanKartu(userName, userOption, true, isC);
345
- }
346
-
347
- target.classList.remove("d-none");
348
- }
349
-
350
- document.addEventListener("click", async function (event) {
351
- // Jika tombol yang diklik adalah .tryErrorMessage
352
- if (event.target.classList.contains("tryErrorMessage")) {
353
- await handleTryClick(event.target);
354
- }
355
-
356
- // Jika tombol yang diklik adalah .tryOtherMessage
357
- if (event.target.classList.contains("tryOtherMessage")) {
358
- await handleTryClick(event.target);
359
- }
360
-
361
- if (event.target.classList.contains("waButton")) {
362
- window.open(`https://wa.me/${whatsappNumber}`, "_blank");
363
- }
364
-
365
- if (event.target.classList.contains("manageURL")) {
366
- window.open(`manage.html`, "_blank");
367
- }
368
-
369
- if (event.target.classList.contains("urlButton")) {
370
- navigator.clipboard.writeText(window.location.href).then(
371
- () => alert("URL berhasil disalin", false),
372
- () => alert("Gagal menyalin URL", false)
373
- );
374
- }
375
- });
376
-
377
- if (!window.location.href.includes("manage")) {
378
- document.addEventListener("DOMContentLoaded", async () => {
379
- const queryId = getQueryParam("i");
380
- let isId = false;
381
- let data = {};
382
-
383
- if (queryId) {
384
- data = await getURLSDATA(queryId);
385
- console.log(data);
386
-
387
- if (data) {
388
- isId = true;
389
- } else {
390
- await alert("Id Kartu Tidak Ditemukan.");
391
- }
392
- }
393
-
394
- urlsdataDB = await getUser();
395
-
396
- const queryFromName = isId
397
- ? data.from
398
- : getQueryParam("f") ||
399
- (urlsdataDB && urlsdataDB.from
400
- ? urlsdataDB.from
401
- : fromName || fN);
402
- let queryTargetName = isId
403
- ? data.target
404
- : getQueryParam("t") ||
405
- (urlsdataDB && urlsdataDB.target ? urlsdataDB.target : "");
406
- let queryOption = isId
407
- ? data.option
408
- : getQueryParam("o") ||
409
- (urlsdataDB && urlsdataDB.option ? urlsdataDB.option : "");
410
-
411
- fromName = queryFromName;
412
-
413
- console.log(queryFromName, queryTargetName, queryOption);
414
-
415
- if (
416
- queryFromName.trim() &&
417
- queryTargetName.trim() &&
418
- queryOption.trim()
419
- ) {
420
- [urlDB, urlsdatasDB] = await generateUrl([
421
- queryFromName.trim(),
422
- queryTargetName.trim(),
423
- queryOption.trim(),
424
- ]);
425
-
426
- urlsdatasDB[urlDB] = urlsdataDB;
427
-
428
- localStorage.setItem(
429
- "url",
430
- urlDB
431
- .replace(window.location.origin, "")
432
- .replace(urlDB.origin, "")
433
- .replace("?i=", "")
434
- );
435
- localStorage.setItem(urlDB, JSON.stringify(urlsdataDB));
436
- localStorage.setItem("data", JSON.stringify(urlsdatasDB));
437
- }
438
-
439
- await setConfigs();
440
-
441
- let res3 = false;
442
-
443
- do {
444
- let res2 = false;
445
-
446
- do {
447
- let res1 = false;
448
-
449
- if (!res3 === !res2 || (!res3 && res2)) {
450
- do {
451
- let res0 = false;
452
-
453
- if (!res2 === !res1 || (!res2 && res1)) {
454
- do {
455
- // MultiPrompt 1: Konfirmasi awal
456
- if (!res1 === !res0 || (!res1 && res0)) {
457
- let res = await multiPrompt(
458
- inputConfigs,
459
- selectConfigs,
460
- `<div class="child-container text-center">
461
- <img class="img-fluid rounded-circle" src="https://media.stickerswiki.app/stickerly_o1nn49_by_stickerly_official_bot/1825567.512.webp">
462
- <h2 class="mb-3">Apakah benar ini Anda?</h2></div>`,
463
- false,
464
- false,
465
- isId
466
- );
467
-
468
- let isC = false;
469
-
470
- if (!isId && !res.isCancel) {
471
- queryTargetName =
472
- res["inputValues"][
473
- "targetName"
474
- ];
475
- queryOption =
476
- res["selectValues"][
477
- "relationshipOption"
478
- ];
479
-
480
- let isC = false;
481
-
482
- urlsdataDB = await getUser();
483
-
484
- if (urlsdataDB) {
485
- if (
486
- (urlsdataDB.target ===
487
- userName &&
488
- urlsdataDB.option !==
489
- userOption) ||
490
- (urlsdataDB.target !==
491
- userName &&
492
- urlsdataDB.option ===
493
- userOption)
494
- ) {
495
- isC = true;
496
- }
497
- } else {
498
- isC = true;
499
- }
500
-
501
- // [urlDB, urlsdatasDB] =
502
- // await generateUrl([
503
- // queryFromName.trim(),
504
- // queryTargetName.trim(),
505
- // queryOption.trim(),
506
- // ]);
507
-
508
- // urlsdatasDB[urlDB] = urlsdataDB;
509
-
510
- localStorage.setItem(
511
- "url",
512
- urlDB
513
- .replace(
514
- window.location.origin,
515
- ""
516
- )
517
- .replace(urlDB.origin, "")
518
- .replace("?i=", "")
519
- );
520
- localStorage.setItem(
521
- urlDB,
522
- JSON.stringify(urlsdataDB)
523
- );
524
- localStorage.setItem(
525
- "data",
526
- JSON.stringify(urlsdatasDB)
527
- );
528
- }
529
-
530
- alert("Tunggu sebentar...", false);
531
-
532
- await tampilkanKartu(
533
- queryTargetName,
534
- queryOption,
535
- isC,
536
- isC
537
- );
538
-
539
- alert("Lanjut...", false);
540
- }
541
-
542
- // MultiPrompt 2: Konfirmasi lanjutan
543
- res0 = (
544
- await multiPrompt(
545
- [],
546
- [],
547
- `<div class="child-container text-center">
548
- <img class="img-fluid rounded-circle" src="https://i.pinimg.com/236x/db/75/9f/db759f85996381cfc69fc4878f6fa3c6.jpg">
549
- <h2 class="mb-3">
550
- "${queryTargetName}", apakah benar ini kamu?<br>
551
- Kalau iya, yuk lanjut ada yang spesial buat kamu! 🎉✨
552
- </h2>
553
- </div>`.trim(),
554
- true,
555
- false,
556
- true,
557
- "Kembali"
558
- )
559
- ).isCancel;
560
- } while (res0);
561
- }
562
-
563
- // MultiPrompt 3: Menampilkan nama penerima
564
- res1 = (
565
- await multiPrompt(
566
- [],
567
- [],
568
- `<div class="child-container text-center">
569
- <img class="img-fluid rounded-circle" src="https://media.stickerswiki.app/pandagemoi4byofcsaraya/215937.512.webp">
570
- <h2 class="mb-3">
571
- Klik Lanjut
572
- </h2>
573
- </div>`.trim(),
574
- true,
575
- false,
576
- true,
577
- "Kembali"
578
- )
579
- ).isCancel;
580
- } while (res1);
581
- }
582
-
583
- // MultiPrompt 4: Pesan tambahan
584
- res2 = (
585
- await multiPrompt(
586
- [],
587
- [],
588
- `<div class="child-container text-center">
589
- <img class="img-fluid rounded-circle" src="https://i.pinimg.com/474x/7d/08/e5/7d08e5de7c11a7356c7ee187f39cbc34.jpg">
590
- <div class="text-center">${
591
- document.getElementById("cardSection").innerHTML
592
- }</div></div>`,
593
- true,
594
- false,
595
- true,
596
- "Kembali",
597
- true,
598
- true,
599
- document.getElementById("cardMessage").innerHTML ||
600
- ucapanGabungan
601
- )
602
- ).isCancel;
603
- } while (res2);
604
-
605
- res3 = (
606
- await multiPrompt(
607
- [],
608
- [],
609
- `<div class="child-container text-center">
610
- <img class="img-fluid rounded-circle" src="https://i.pinimg.com/736x/c1/78/ea/c178eae8b11823b36f4d76fc5f8a2a29.jpg">
611
- <div class="text-center">${
612
- document.querySelector(".areaFooter").innerHTML
613
- }</div></div>`,
614
- true,
615
- false,
616
- true,
617
- "Kembali",
618
- false
619
- )
620
- ).isCancel;
621
- } while (res3);
622
- });
623
- }
624
- } catch (e) {
625
- console.error(e);
626
- }
627
-
628
- let counterAlert = 0;
629
-
630
- async function alert(
631
- message = "",
632
- isPopUp = true,
633
- isTime = false,
634
- timeOut = 5,
635
- messagesAfterTimeOut = [],
636
- awaitResolve = 0
637
- ) {
638
- counterAlert++;
639
-
640
- return new Promise((resolve) => {
641
- try {
642
- let modal;
643
- let messageElem;
644
- let timeOutElm;
645
- let okBtn;
646
- let intervalId;
647
-
648
- if (isPopUp) {
649
- modal = document.createElement("div");
650
- modal.className = "modal";
651
- modal.style.position = "fixed";
652
- modal.style.top = "0";
653
- modal.style.left = "0";
654
- modal.style.width = "100%";
655
- modal.style.height = "100%";
656
- modal.style.backgroundColor = "rgba(0,0,0,0.5)";
657
- modal.style.display = "flex";
658
- modal.style.alignItems = "center";
659
- modal.style.justifyContent = "center";
660
- } else {
661
- modal = document.createElement("div");
662
- modal.className = "notification";
663
- modal.style.position = "fixed";
664
- modal.style.top = "5%";
665
- modal.style.right = "2.5%";
666
- modal.style.padding = "10px 20px";
667
- modal.style.borderRadius = "5px";
668
- modal.style.zIndex = "1000000000";
669
- modal.setAttribute("data-aos", "fade-left");
670
- }
671
-
672
- const modalContent = document.createElement("div");
673
- modalContent.className = `modal-content d-flex align-items-center ${
674
- isPopUp
675
- ? "bg-light"
676
- : counterAlert % 2 === 0
677
- ? "bg-success"
678
- : "bg-primary"
679
- } p-3 ${isPopUp ? "" : "text-white"}`;
680
- modalContent.style.width = isPopUp ? "75%" : "100%";
681
- modalContent.style.height = isPopUp ? "" : "100%";
682
- modalContent.style.borderRadius = "5px";
683
- modalContent.style.boxShadow = isPopUp
684
- ? "0 2px 10px rgba(0,0,0,0.1)"
685
- : "";
686
-
687
- messageElem = document.createElement("p");
688
- messageElem.innerHTML =
689
- (!isPopUp ? `<i class="bi bi-bell-fill m-2"></i>` : ``) +
690
- message;
691
-
692
- timeOutElm = document.createElement("p");
693
-
694
- okBtn = document.createElement("button");
695
- okBtn.className = `btn ${
696
- counterAlert % 2 === 0 ? "btn-primary" : "btn-warning"
697
- } btn-lg`;
698
- okBtn.textContent = "OK";
699
- okBtn.style.minWidth = "80px";
700
- okBtn.style.display = isTime ? "none" : "block";
701
- okBtn.style.marginTop = "10px";
702
-
703
- modalContent.appendChild(messageElem);
704
-
705
- if (isTime) {
706
- modalContent.appendChild(timeOutElm);
707
- }
708
-
709
- if (isPopUp) {
710
- const btnContainer = document.createElement("div");
711
- btnContainer.style.marginTop = "20px";
712
- btnContainer.appendChild(okBtn);
713
- modalContent.appendChild(btnContainer);
714
- }
715
-
716
- modal.appendChild(modalContent);
717
- document.body.appendChild(modal);
718
-
719
- okBtn.addEventListener("click", function () {
720
- if (intervalId) clearInterval(intervalId);
721
- if (document.body.contains(modal)) {
722
- document.body.removeChild(modal);
723
- }
724
- resolve();
725
- });
726
-
727
- if (!isPopUp) {
728
- intervalId = setInterval(async () => {
729
- timeOut--;
730
- console.log(timeOut);
731
- if (messagesAfterTimeOut.length === 0)
732
- timeOutElm.textContent = timeOut;
733
- if (messagesAfterTimeOut.length > 0) {
734
- messagesAfterTimeOut.forEach((mes) => {
735
- if (mes.timeOut >= timeOut) {
736
- modalContent.className =
737
- "modal-content d-flex align-items-center bg-warning p-3";
738
- messageElem.textContent = mes.message;
739
- timeOutElm.textContent = timeOut;
740
- }
741
- });
742
- }
743
-
744
- if (timeOut <= 0) {
745
- await new Promise((res) =>
746
- setTimeout(res, awaitResolve)
747
- );
748
- if (document.body.contains(modal)) {
749
- document.body.removeChild(modal);
750
- }
751
- clearInterval(intervalId);
752
- resolve();
753
- }
754
- }, 1000);
755
-
756
- setTimeout(() => {
757
- if (document.body.contains(modal)) {
758
- document.body.removeChild(modal);
759
- }
760
- resolve();
761
- }, timeOut * 1000);
762
- }
763
- } catch (e) {
764
- console.error(e);
765
- }
766
- });
767
- }
768
-
769
- async function multiPrompt(
770
- inputConfigs = [
771
- {
772
- label: "Nama:",
773
- type: "text",
774
- placeholder: "Masukkan nama Anda",
775
- id: "name",
776
- value: "",
777
- },
778
- ],
779
- selectConfigs = [
780
- {
781
- label: "Pilih Gender:",
782
- options: [
783
- { value: "L", label: "Laki-laki" },
784
- { value: "P", label: "Perempuan" },
785
- ],
786
- default: "L",
787
- id: "gender",
788
- },
789
- ],
790
- innerHTMLOnTopMessage = "",
791
- withCancelButton = true,
792
- isDOM = false,
793
- isDisabledAll = false,
794
- cancelText = "",
795
- withNextButton = true,
796
- runFunc = false,
797
- originalText = ""
798
- ) {
799
- console.log(ucapanGabungan, originalText, "AAAA");
800
- return new Promise((resolve) => {
801
- const modal = document.createElement("div");
802
- modal.className = "modal";
803
- Object.assign(modal.style, {
804
- position: "fixed",
805
- top: "0",
806
- left: "0",
807
- width: "100%",
808
- height: "100%",
809
- backgroundColor: "rgba(0,0,0,0.5)",
810
- display: "flex",
811
- alignItems: "center",
812
- justifyContent: "center",
813
- });
814
-
815
- const modalContent = document.createElement("div");
816
- modalContent.className = "modal-content";
817
- Object.assign(modalContent.style, {
818
- width: "75%",
819
- background: "#fff",
820
- padding: "20px",
821
- borderRadius: "5px",
822
- boxShadow: "0 2px 10px rgba(0,0,0,0.1)",
823
- });
824
-
825
- const okBtn = document.createElement("button");
826
- const okBtnClassName = "btn btn-success btn-lg";
827
- const okBtnTextContent = "Cari";
828
-
829
- okBtn.className = isDOM
830
- ? okBtnClassName.replace("success", "warning")
831
- : okBtnClassName;
832
- okBtn.textContent = isDisabledAll
833
- ? "Lanjut"
834
- : isDOM
835
- ? okBtnTextContent
836
- : "Ganti pesan";
837
- okBtn.style.marginRight = "10px";
838
- okBtn.style.display = withNextButton ? "" : "none";
839
-
840
- const cancelBtn = document.createElement("button");
841
- cancelBtn.className =
842
- "btn btn-danger btn-lg" + (withCancelButton ? "" : " d-none");
843
- cancelBtn.textContent = cancelText || "Batal";
844
-
845
- const innerHTMLOnTopMessageContent = document.createElement("div");
846
- innerHTMLOnTopMessageContent.innerHTML = innerHTMLOnTopMessage;
847
-
848
- const form = document.createElement("form");
849
-
850
- const inputElements = {};
851
- const selectElements = {};
852
-
853
- function changeOKBTN(isChange) {
854
- okBtn.textContent = isDisabledAll
855
- ? "Lanjut"
856
- : isDOM
857
- ? okBtnTextContent
858
- : isChange === false
859
- ? "Ganti pesan"
860
- : "Ganti data";
861
- okBtn.className = isDOM
862
- ? okBtnClassName.replace("success", "warning")
863
- : isChange === false
864
- ? okBtnClassName
865
- : okBtnClassName.replace("success", "primary");
866
- }
867
-
868
- inputConfigs.forEach((config) => {
869
- const labelElem = document.createElement("label");
870
- labelElem.textContent = config.label;
871
- Object.assign(labelElem.style, {
872
- display: "block",
873
- marginTop: "10px",
874
- });
875
- form.appendChild(labelElem);
876
-
877
- const input = document.createElement("input");
878
- Object.assign(input, {
879
- type: config.type || "text",
880
- placeholder: config.placeholder || "",
881
- required: true,
882
- id: config.id,
883
- });
884
- Object.assign(input.style, {
885
- width: "100%",
886
- marginTop: "5px",
887
- });
888
- input.className = "form-control form-control-lg";
889
- input.value = config.value;
890
- inputElements[config.id] = input;
891
- form.appendChild(input);
892
-
893
- if (isDisabledAll) input.disabled = true;
894
-
895
- input.addEventListener("change", () => {
896
- changeOKBTN(inputElements[config.id].value !== config.value);
897
- });
898
- });
899
-
900
- selectConfigs.forEach((config) => {
901
- const labelElem = document.createElement("label");
902
- labelElem.textContent = config.label;
903
- Object.assign(labelElem.style, {
904
- display: "block",
905
- marginTop: "10px",
906
- });
907
- form.appendChild(labelElem);
908
-
909
- const selectElem = document.createElement("select");
910
- Object.assign(selectElem, {
911
- required: true,
912
- id: config.id,
913
- });
914
- Object.assign(selectElem.style, {
915
- width: "100%",
916
- marginTop: "5px",
917
- });
918
- selectElem.className = "form-select form-select-lg";
919
-
920
- config.options.forEach((opt) => {
921
- const optionElem = document.createElement("option");
922
- optionElem.value = opt.value;
923
- optionElem.textContent = opt.label;
924
- if (config.default === opt.value) optionElem.selected = true;
925
- selectElem.appendChild(optionElem);
926
- });
927
-
928
- selectElements[config.id] = selectElem;
929
- form.appendChild(selectElem);
930
-
931
- if (isDisabledAll) selectElem.disabled = true;
932
-
933
- selectElem.addEventListener("change", () => {
934
- changeOKBTN(selectElements[config.id].value !== config.default);
935
- });
936
- });
937
-
938
- const btnContainer = document.createElement("div");
939
- Object.assign(btnContainer.style, {
940
- marginTop: "20px",
941
- textAlign: "right",
942
- });
943
-
944
- btnContainer.appendChild(okBtn);
945
- btnContainer.appendChild(cancelBtn);
946
- form.appendChild(btnContainer);
947
-
948
- modalContent.appendChild(innerHTMLOnTopMessageContent);
949
- modalContent.appendChild(form);
950
- modal.appendChild(modalContent);
951
- document.body.appendChild(modal);
952
-
953
- console.log(runFunc);
954
-
955
- function initTypewriter() {
956
- async function typeWriterHTML(element, html, speed = 50) {
957
- let currentLength = renderedUcapanGabungan.length;
958
- for (let i = currentLength; i < html.length; i++) {
959
- renderedUcapanGabungan += html.charAt(i);
960
- element.innerHTML = renderedUcapanGabungan;
961
- await new Promise((resolve) => setTimeout(resolve, speed));
962
-
963
- okBtn.disabled = true;
964
- cancelBtn.disabled = true;
965
- }
966
-
967
- okBtn.disabled = false;
968
- cancelBtn.disabled = false;
969
- }
970
-
971
- const cardMessagess = document.querySelectorAll(".card-body");
972
- cardMessagess.forEach((cardMessages, index) => {
973
- if (index !== 0) {
974
- typeWriterHTML(
975
- cardMessages,
976
- marked.parse(originalText),
977
- 25
978
- );
979
- }
980
- });
981
- }
982
-
983
- if (document.readyState === "loading") {
984
- document.addEventListener("DOMContentLoaded", initTypewriter);
985
- } else {
986
- initTypewriter();
987
- }
988
-
989
- form.addEventListener("submit", function (e) {
990
- e.preventDefault();
991
-
992
- let isValid = true;
993
- const inputValues = {};
994
- const selectValues = {};
995
-
996
- Object.entries(inputElements).forEach(([id, elem]) => {
997
- const value = elem.value.trim();
998
- inputValues[id] = value;
999
- if (value.length === 0) {
1000
- elem.style.border = "1px solid red";
1001
- isValid = false;
1002
- } else {
1003
- elem.style.border = "";
1004
- }
1005
- });
1006
-
1007
- Object.entries(selectElements).forEach(([id, elem]) => {
1008
- const value = elem.value;
1009
- selectValues[id] = value;
1010
- if (!value) {
1011
- elem.style.border = "1px solid red";
1012
- isValid = false;
1013
- } else {
1014
- elem.style.border = "";
1015
- }
1016
- });
1017
-
1018
- if (isValid) {
1019
- document.body.removeChild(modal);
1020
- console.log(inputValues, selectValues);
1021
- resolve({ inputValues, selectValues, isCancel: false });
1022
- }
1023
- });
1024
-
1025
- okBtn.addEventListener("click", () => {
1026
- form.dispatchEvent(new Event("submit", { cancelable: true }));
1027
- });
1028
-
1029
- cancelBtn.addEventListener("click", () => {
1030
- document.body.removeChild(modal);
1031
- resolve({
1032
- inputValues: null,
1033
- selectValues: null,
1034
- isCancel: true,
1035
- });
1036
- });
1037
- });
1038
- }
1039
-
1040
- let isCustomMessage = false;
1041
-
1042
- try {
1043
- document
1044
- .getElementById("btnGU")
1045
- .addEventListener("click", async function () {
1046
- const fromName = document.getElementById("fromName").value.trim();
1047
- const targetName = document
1048
- .getElementById("targetName")
1049
- .value.trim();
1050
- const option = parseInt(
1051
- document.getElementById("relationshipOption").value.trim()
1052
- );
1053
- const message = document.getElementById("message").value.trim();
1054
-
1055
- const generatedUrl = (
1056
- await generateUrl([
1057
- fromName,
1058
- targetName,
1059
- option,
1060
- isCustomMessage ? message : "",
1061
- ])
1062
- )[0];
1063
-
1064
- document.getElementById(
1065
- "generatedUrl"
1066
- ).innerHTML = `<div class='alert alert-success'>
1067
- <strong>URL Generated:</strong> <a href="${generatedUrl}" target="_blank">${generatedUrl}</a>
1068
- </div>`;
1069
- });
1070
-
1071
- document
1072
- .getElementById("isCustomMessage")
1073
- .addEventListener("change", function () {
1074
- const inputMessage = document.getElementById("inputMessage");
1075
- if (this.checked) {
1076
- inputMessage.setAttribute("class", "mt-3");
1077
- isCustomMessage = true;
1078
- } else {
1079
- inputMessage.setAttribute("class", "mt-3 d-none");
1080
- isCustomMessage = false;
1081
- }
1082
- });
1083
- } catch (error) {}
1084
-
1085
- async function generateUrl([fromName, targetName, option, message = ""]) {
1086
- let i = 0;
1087
- let generatedUrl = "";
1088
-
1089
- while (true) {
1090
- let queryUrl = "";
1091
-
1092
- if (!fromName || !targetName) {
1093
- alert("Mohon isi semua field sebelum generate URL", false);
1094
- return;
1095
- }
1096
-
1097
- const fts = [fromName, targetName];
1098
-
1099
- fts.forEach((ft, indexs) => {
1100
- let finalFN = "";
1101
-
1102
- let fNS = ft.split(" ");
1103
- let fNSJ = fNS.join("");
1104
-
1105
- fNS.forEach((word, index) => {
1106
- let wl = Math.round(word.length / (i + 2));
1107
- finalFN +=
1108
- (indexs === 0 && index === 0) ||
1109
- (indexs === 1 && index === fNS.length - 1)
1110
- ? (word[i] || "x") +
1111
- (fNSJ[wl] || "y") +
1112
- (word[word.length - (i + 1)] || "z")
1113
- : "";
1114
- });
1115
-
1116
- queryUrl += finalFN + (indexs === 0 ? "X" : "Y");
1117
- });
1118
-
1119
- const char = "abcdefghijklmnopqrstuvwxyz";
1120
-
1121
- queryUrl += char[option + i] || "Z";
1122
-
1123
- let data = await getURLSDATA(queryUrl);
1124
-
1125
- if (!data) {
1126
- data = {
1127
- from: fromName,
1128
- target: targetName,
1129
- option: option.toString(),
1130
- message: message,
1131
- };
1132
- }
1133
-
1134
- console.log(queryUrl, data);
1135
-
1136
- let isSuccess = false;
1137
-
1138
- [isSuccess, urlsdatasDB] = await setURLSDATAData(queryUrl, data);
1139
-
1140
- i++;
1141
-
1142
- if (isSuccess) {
1143
- generatedUrl = `${window.location.origin}?i=` + queryUrl;
1144
- break;
1145
- }
1146
- }
1147
-
1148
- return [generatedUrl, urlsdatasDB];
1149
- }
1150
-
1151
- try {
1152
- function addStars(count) {
1153
- for (let i = 0; i < count; i++) {
1154
- const star = document.createElement("div");
1155
- star.className = "star";
1156
- // Atur posisi acak
1157
- star.style.top = Math.random() * 100 + "%";
1158
- star.style.left = Math.random() * 100 + "%";
1159
- // Atur durasi animasi antara 2s hingga 5s
1160
- star.style.animationDuration = 2 + Math.random() * 3 + "s";
1161
- // Atur delay animasi antara 0s hingga 3s
1162
- star.style.animationDelay = Math.random() * 3 + "s";
1163
- document.body.appendChild(star);
1164
- }
1165
- }
1166
- addStars(100);
1167
- } catch {}
 
1
+ function getQueryParam(param) {
2
+ const urlParams = new URLSearchParams(window.location.search);
3
+ return urlParams.get(param);
4
+ }
5
+
6
+ const fN = "Aditya Dwi Nugraha";
7
+ const whatsappNumber = "6289668041554";
8
+
9
+ var fromName = fN;
10
+ let urlsdatasDB = {};
11
+ let urlsdataDB = {};
12
+ let urlDB = "";
13
+ let ucapanGabungan = "";
14
+ let renderedUcapanGabungan = "";
15
+
16
+ var inputConfigs = [
17
+ {
18
+ label: "Nama Anda:",
19
+ type: "text",
20
+ placeholder: "Masukkan nama anda",
21
+ id: "targetName",
22
+ value: "",
23
+ },
24
+ ];
25
+
26
+ var selectConfigs = [
27
+ {
28
+ label: `Pilih relasi (hubungan) antara Anda dan ${fromName}:`,
29
+ options: [
30
+ { value: "0", label: "Anak anda" },
31
+ { value: "1", label: "Keponakan anda" },
32
+ { value: "2", label: "Murid anda" },
33
+ { value: "3", label: "Saudaramu" },
34
+ { value: "4", label: "Sepupumu" },
35
+ { value: "5", label: "Sahabatmu" },
36
+ { value: "6", label: "Temanmu" },
37
+ { value: "7", label: "Orang lain" },
38
+ ],
39
+ default: "6",
40
+ id: "relationshipOption",
41
+ },
42
+ ];
43
+
44
+ const innerHTMLOnTopMessage = `<h2 class="mb-3">Masukkan Nama Penerima & Pilih Relasi</h2>`;
45
+
46
+ try {
47
+ const GEMINI_API_KEY = atob(
48
+ "QUl6YVN5QzUyNGNQREdEcWRZSnZkYmNtaUZ2N1Q2QzRnbE9JQXNR"
49
+ );
50
+ const MODEL_ID = "gemini-1.5-flash";
51
+ const GENERATE_CONTENT_API = "streamGenerateContent";
52
+
53
+ var noUcapan = "Ucapan tidak tersedia. Silakan coba lagi nanti.";
54
+
55
+ const tryErrorMessage = document.querySelectorAll(".tryErrorMessage");
56
+ const tryOtherMessage = document.querySelectorAll(".tryOtherMessage");
57
+
58
+ const relationshipMapping = {
59
+ 0: "Ayah/Ibu",
60
+ 1: "Pakde/Bude",
61
+ 2: "Guru",
62
+ 3: "Saudara",
63
+ 4: "Sepupu",
64
+ 5: "Sahabat",
65
+ 6: "Teman",
66
+ 7: "Tidak dikenal alias orang lain",
67
+ };
68
+
69
+ async function generateUcapan(
70
+ name,
71
+ option,
72
+ regenerate = false,
73
+ isChange = false
74
+ ) {
75
+ const targetName = name;
76
+ const relationship =
77
+ relationshipMapping[option.toString()] || relationshipMapping["6"];
78
+ // const language = [0, 1, 2].includes(parseInt(option))
79
+ // ? "Sopan"
80
+ // : `Gaul tapi tetap Sopan dan tidak berlebihan, karena INGAT! SAYA LAKI LAKI GENTLEMAN DAN PUNYA WIBAWA!. jangan pakai "lo" tapi "kamu"`;
81
+
82
+ const payload = {
83
+ contents: [
84
+ {
85
+ role: "user",
86
+ parts: [{ text: `Nama targetnya: ${targetName}` }],
87
+ },
88
+ ],
89
+ systemInstruction: {
90
+ parts: [
91
+ { text: "Sekarang tahun 1446H." },
92
+ {
93
+ text: 'Langsung mulai dengan "Assalamu\'alaikum Wr. Wb." alias salam lalu "Taqabbalallah wa minna ...." dan "Untuk ..." tanpa basa-basi.',
94
+ },
95
+ {
96
+ text: `Buat kartu ucapan Idul Fitri yang personal untuk ${targetName} berdasarkan jenis kelamin dan hubungan sebagai ${relationship}. Jika hubungan adalah "teman", jangan gunakan kata-kata romantis seperti "sayang", "ku cinta", atau istilah sejenis yang terkesan intim secara romantis.`,
97
+ },
98
+ {
99
+ text: `Sertakan kalimat "Kami sekeluarga ${fromName} mengucapkan..." jika hubungan bukan termasuk keluarga saya (Ayah/Ibu/Saudara). Jika termasuk keluarga saya maka beda lagi kalimatnya! Misal kalau untuk ibu: "Untuk ibuku yang tercinta..." atau kalau saudara: "Untuk ${targetName} yang ku cinta...".`,
100
+ },
101
+ {
102
+ text: "Setelah itu, lanjutkan ucapan dengan salam pembuka, doa, permohonan maaf, dan harapan yang hangat namun tidak berlebihan karena saya laki-laki yang gentleman punya wibawa.",
103
+ },
104
+ {
105
+ text: `Berikan emoji di setiap kalimat sebanyak-banyaknya untuk kesan asik dan santai.`,
106
+ },
107
+ {
108
+ text: "Jadikan bahasa manusia agak kaku agar tidak dikira robot.",
109
+ },
110
+ {
111
+ text: 'Ingat! Langsung mulai dengan "Assalamu\'alaikum Wr. Wb." alias salam lalu "Untuk ..." tanpa basa-basi.',
112
+ },
113
+ {
114
+ text: `INGAT KALAU KELUARGA SENDIRI TIDAK PAKAI KALIMAT "kami sekeluarga ${fromName}"!!!!!`,
115
+ },
116
+ ],
117
+ },
118
+ generationConfig: {
119
+ responseMimeType: "text/plain",
120
+ },
121
+ };
122
+
123
+ ucapanGabungan = "";
124
+ let isFDB = false;
125
+ let isCU = false;
126
+
127
+ urlsdatasDB = (await getURLSDATAs())[0];
128
+
129
+ localStorage.setItem("data", JSON.stringify(urlsdatasDB));
130
+
131
+ for (const [key, data] of Object.entries(urlsdatasDB)) {
132
+ if (
133
+ data.from === fromName &&
134
+ data.target === name &&
135
+ data.option === option &&
136
+ data.message &&
137
+ data.message !== noUcapan
138
+ ) {
139
+ ucapanGabungan = data.message;
140
+ urlDB = `${window.location.origin}?i=` + key;
141
+ isFDB = true;
142
+
143
+ localStorage.setItem("url", key);
144
+ break;
145
+ }
146
+ }
147
+
148
+ const logic =
149
+ (!isFDB && !regenerate && !isChange) ||
150
+ (isFDB && regenerate && !isChange) ||
151
+ (!isFDB && regenerate && isChange);
152
+
153
+ console.log([regenerate, isFDB, isChange], logic);
154
+
155
+ try {
156
+ if (logic) {
157
+ const response = await fetch(
158
+ `https://generativelanguage.googleapis.com/v1beta/models/${MODEL_ID}:${GENERATE_CONTENT_API}?key=${GEMINI_API_KEY}`,
159
+ {
160
+ method: "POST",
161
+ headers: { "Content-Type": "application/json" },
162
+ body: JSON.stringify(payload),
163
+ }
164
+ );
165
+
166
+ const data = await response.json();
167
+
168
+ ucapanGabungan = "";
169
+ isCU = true;
170
+
171
+ if (Array.isArray(data)) {
172
+ data.forEach((item) => {
173
+ if (
174
+ item &&
175
+ item.candidates &&
176
+ item.candidates[0] &&
177
+ item.candidates[0].content &&
178
+ item.candidates[0].content.parts &&
179
+ item.candidates[0].content.parts[0] &&
180
+ item.candidates[0].content.parts[0].text
181
+ ) {
182
+ ucapanGabungan +=
183
+ item.candidates[0].content.parts[0].text;
184
+ }
185
+ });
186
+ ucapanGabungan = ucapanGabungan.trim();
187
+ } else {
188
+ ucapanGabungan = noUcapan;
189
+ }
190
+ }
191
+
192
+ console.log("Ucapan:", ucapanGabungan);
193
+ } catch (error) {
194
+ ucapanGabungan = noUcapan;
195
+
196
+ console.error("Error:", error);
197
+ }
198
+
199
+ if (!ucapanGabungan.trim() || ucapanGabungan === noUcapan) {
200
+ tryErrorMessage.forEach((elm) => {
201
+ do {
202
+ elm.classList.remove("d-none");
203
+ } while (elm.classList.contains("d-none"));
204
+ });
205
+ } else {
206
+ tryOtherMessage.forEach((elm) => {
207
+ do {
208
+ elm.classList.remove("d-none");
209
+ } while (elm.classList.contains("d-none"));
210
+ });
211
+
212
+ const data = {
213
+ from: fromName,
214
+ target: name,
215
+ option: parseInt(option),
216
+ message: ucapanGabungan,
217
+ };
218
+
219
+ if (isCU) {
220
+ [urlDB, urlsdataDB] = await generateUrl(Object.values(data));
221
+
222
+ urlsdatasDB[urlDB] = urlsdataDB;
223
+
224
+ localStorage.setItem(
225
+ "url",
226
+ urlDB
227
+ .replace(window.location.origin, "")
228
+ .replace(urlDB.origin, "")
229
+ .replace("?i=", "")
230
+ );
231
+ function isCircular(obj, seen = new WeakSet()) {
232
+ if (typeof obj !== "object" || obj === null) return false;
233
+ if (seen.has(obj)) return true;
234
+ seen.add(obj);
235
+ return Object.values(obj).some((value) =>
236
+ isCircular(value, seen)
237
+ );
238
+ }
239
+
240
+ if (isCircular(urlsdataDB)) {
241
+ console.error("Data mengandung referensi circular!");
242
+ } else {
243
+ localStorage.setItem(urlDB, JSON.stringify(urlsdataDB));
244
+ }
245
+ }
246
+ }
247
+
248
+ return [ucapanGabungan, urlDB];
249
+ }
250
+
251
+ async function tampilkanKartu(
252
+ name,
253
+ option,
254
+ regenerate = false,
255
+ isChange = false
256
+ ) {
257
+ // document.getElementById("cardTitle").innerText = `Untuk ${name}`;
258
+ // document.getElementById("cardSection").style.display = "block";
259
+
260
+ console.log(name, option, regenerate);
261
+
262
+ [ucapanGabungan, urlDB] = await generateUcapan(
263
+ name,
264
+ option,
265
+ regenerate,
266
+ isChange
267
+ );
268
+
269
+ document.getElementById("cardMessage").innerHTML =
270
+ marked.parse(ucapanGabungan);
271
+
272
+ alert(`Akses halaman ini di: ${urlDB}`, false);
273
+
274
+ if (window.location.href.replace("/?", "?") !== urlDB.replace("index.html", "")) {
275
+ await alert(`Kamu akan diarahkan ke halaman ${urlDB}`);
276
+ await new Promise((res) => setTimeout(res, 1000));
277
+ window.location.href = urlDB;
278
+ }
279
+ }
280
+
281
+ async function getUser() {
282
+ let url = localStorage.getItem("url");
283
+ let data = localStorage.getItem("data");
284
+
285
+ if (data) {
286
+ try {
287
+ data = JSON.parse(data);
288
+ } catch (e) {
289
+ data = await getURLSDATAs();
290
+ }
291
+ } else {
292
+ data = await getURLSDATAs();
293
+ }
294
+
295
+ console.log(url, data);
296
+
297
+ return url && data ? data[url] || null : null;
298
+ }
299
+
300
+ async function setConfigs() {
301
+ urlsdataDB = await getUser();
302
+
303
+ console.log(urlsdataDB);
304
+
305
+ if (urlsdataDB) {
306
+ inputConfigs[0].value = urlsdataDB.target;
307
+ selectConfigs[0].label = `Pilih relasi (hubungan) antara Anda dan ${urlsdataDB.from}:`;
308
+ selectConfigs[0].default = urlsdataDB.option;
309
+ }
310
+ }
311
+
312
+ async function handleTryClick(target) {
313
+ target.classList.add("d-none");
314
+
315
+ await setConfigs();
316
+
317
+ const res = await multiPrompt(
318
+ inputConfigs,
319
+ selectConfigs,
320
+ innerHTMLOnTopMessage
321
+ );
322
+
323
+ if (!res.isCancel) {
324
+ userName = res["inputValues"]["targetName"];
325
+ userOption = res["selectValues"]["relationshipOption"];
326
+
327
+ let isC = false;
328
+
329
+ urlsdataDB = await getUser();
330
+
331
+ if (urlsdataDB) {
332
+ if (
333
+ (urlsdataDB.target === userName &&
334
+ urlsdataDB.option !== userOption) ||
335
+ (urlsdataDB.target !== userName &&
336
+ urlsdataDB.option === userOption)
337
+ ) {
338
+ isC = true;
339
+ }
340
+ } else {
341
+ isC = true;
342
+ }
343
+
344
+ await tampilkanKartu(userName, userOption, true, isC);
345
+ }
346
+
347
+ target.classList.remove("d-none");
348
+ }
349
+
350
+ document.addEventListener("click", async function (event) {
351
+ // Jika tombol yang diklik adalah .tryErrorMessage
352
+ if (event.target.classList.contains("tryErrorMessage")) {
353
+ await handleTryClick(event.target);
354
+ }
355
+
356
+ // Jika tombol yang diklik adalah .tryOtherMessage
357
+ if (event.target.classList.contains("tryOtherMessage")) {
358
+ await handleTryClick(event.target);
359
+ }
360
+
361
+ if (event.target.classList.contains("waButton")) {
362
+ window.open(`https://wa.me/${whatsappNumber}`, "_blank");
363
+ }
364
+
365
+ if (event.target.classList.contains("manageURL")) {
366
+ window.open(`manage.html`, "_blank");
367
+ }
368
+
369
+ if (event.target.classList.contains("urlButton")) {
370
+ navigator.clipboard.writeText(window.location.href).then(
371
+ () => alert("URL berhasil disalin", false),
372
+ () => alert("Gagal menyalin URL", false)
373
+ );
374
+ }
375
+ });
376
+
377
+ if (!window.location.href.includes("manage")) {
378
+ document.addEventListener("DOMContentLoaded", async () => {
379
+ const queryId = getQueryParam("i");
380
+ let isId = false;
381
+ let data = {};
382
+
383
+ if (queryId) {
384
+ data = await getURLSDATA(queryId);
385
+ console.log(data);
386
+
387
+ if (data) {
388
+ isId = true;
389
+ } else {
390
+ await alert("Id Kartu Tidak Ditemukan.");
391
+ }
392
+ }
393
+
394
+ urlsdataDB = await getUser();
395
+
396
+ const queryFromName = isId
397
+ ? data.from
398
+ : getQueryParam("f") ||
399
+ (urlsdataDB && urlsdataDB.from
400
+ ? urlsdataDB.from
401
+ : fromName || fN);
402
+ let queryTargetName = isId
403
+ ? data.target
404
+ : getQueryParam("t") ||
405
+ (urlsdataDB && urlsdataDB.target ? urlsdataDB.target : "");
406
+ let queryOption = isId
407
+ ? data.option
408
+ : getQueryParam("o") ||
409
+ (urlsdataDB && urlsdataDB.option ? urlsdataDB.option : "");
410
+
411
+ fromName = queryFromName;
412
+
413
+ console.log(queryFromName, queryTargetName, queryOption);
414
+
415
+ if (
416
+ queryFromName.trim() &&
417
+ queryTargetName.trim() &&
418
+ queryOption.trim()
419
+ ) {
420
+ [urlDB, urlsdatasDB] = await generateUrl([
421
+ queryFromName.trim(),
422
+ queryTargetName.trim(),
423
+ queryOption.trim(),
424
+ ]);
425
+
426
+ urlsdatasDB[urlDB] = urlsdataDB;
427
+
428
+ localStorage.setItem(
429
+ "url",
430
+ urlDB
431
+ .replace(window.location.origin, "")
432
+ .replace(urlDB.origin, "")
433
+ .replace("?i=", "")
434
+ );
435
+ localStorage.setItem(urlDB, JSON.stringify(urlsdataDB));
436
+ localStorage.setItem("data", JSON.stringify(urlsdatasDB));
437
+ }
438
+
439
+ await setConfigs();
440
+
441
+ let res3 = false;
442
+
443
+ do {
444
+ let res2 = false;
445
+
446
+ do {
447
+ let res1 = false;
448
+
449
+ if (!res3 === !res2 || (!res3 && res2)) {
450
+ do {
451
+ let res0 = false;
452
+
453
+ if (!res2 === !res1 || (!res2 && res1)) {
454
+ do {
455
+ // MultiPrompt 1: Konfirmasi awal
456
+ if (!res1 === !res0 || (!res1 && res0)) {
457
+ let res = await multiPrompt(
458
+ inputConfigs,
459
+ selectConfigs,
460
+ `<div class="child-container text-center">
461
+ <img class="img-fluid rounded-circle" src="https://media.stickerswiki.app/stickerly_o1nn49_by_stickerly_official_bot/1825567.512.webp">
462
+ <h2 class="mb-3">Apakah benar ini Anda?</h2></div>`,
463
+ false,
464
+ false,
465
+ isId
466
+ );
467
+
468
+ let isC = false;
469
+
470
+ if (!isId && !res.isCancel) {
471
+ queryTargetName =
472
+ res["inputValues"][
473
+ "targetName"
474
+ ];
475
+ queryOption =
476
+ res["selectValues"][
477
+ "relationshipOption"
478
+ ];
479
+
480
+ let isC = false;
481
+
482
+ urlsdataDB = await getUser();
483
+
484
+ if (urlsdataDB) {
485
+ if (
486
+ (urlsdataDB.target ===
487
+ userName &&
488
+ urlsdataDB.option !==
489
+ userOption) ||
490
+ (urlsdataDB.target !==
491
+ userName &&
492
+ urlsdataDB.option ===
493
+ userOption)
494
+ ) {
495
+ isC = true;
496
+ }
497
+ } else {
498
+ isC = true;
499
+ }
500
+
501
+ // [urlDB, urlsdatasDB] =
502
+ // await generateUrl([
503
+ // queryFromName.trim(),
504
+ // queryTargetName.trim(),
505
+ // queryOption.trim(),
506
+ // ]);
507
+
508
+ // urlsdatasDB[urlDB] = urlsdataDB;
509
+
510
+ localStorage.setItem(
511
+ "url",
512
+ urlDB
513
+ .replace(
514
+ window.location.origin,
515
+ ""
516
+ )
517
+ .replace(urlDB.origin, "")
518
+ .replace("?i=", "")
519
+ );
520
+ localStorage.setItem(
521
+ urlDB,
522
+ JSON.stringify(urlsdataDB)
523
+ );
524
+ localStorage.setItem(
525
+ "data",
526
+ JSON.stringify(urlsdatasDB)
527
+ );
528
+ }
529
+
530
+ alert("Tunggu sebentar...", false);
531
+
532
+ await tampilkanKartu(
533
+ queryTargetName,
534
+ queryOption,
535
+ isC,
536
+ isC
537
+ );
538
+
539
+ alert("Lanjut...", false);
540
+ }
541
+
542
+ // MultiPrompt 2: Konfirmasi lanjutan
543
+ res0 = (
544
+ await multiPrompt(
545
+ [],
546
+ [],
547
+ `<div class="child-container text-center">
548
+ <img class="img-fluid rounded-circle" src="https://i.pinimg.com/236x/db/75/9f/db759f85996381cfc69fc4878f6fa3c6.jpg">
549
+ <h2 class="mb-3">
550
+ "${queryTargetName}", apakah benar ini kamu?<br>
551
+ Kalau iya, yuk lanjut ada yang spesial buat kamu! 🎉✨
552
+ </h2>
553
+ </div>`.trim(),
554
+ true,
555
+ false,
556
+ true,
557
+ "Kembali"
558
+ )
559
+ ).isCancel;
560
+ } while (res0);
561
+ }
562
+
563
+ // MultiPrompt 3: Menampilkan nama penerima
564
+ res1 = (
565
+ await multiPrompt(
566
+ [],
567
+ [],
568
+ `<div class="child-container text-center">
569
+ <img class="img-fluid rounded-circle" src="https://media.stickerswiki.app/pandagemoi4byofcsaraya/215937.512.webp">
570
+ <h2 class="mb-3">
571
+ Klik Lanjut
572
+ </h2>
573
+ </div>`.trim(),
574
+ true,
575
+ false,
576
+ true,
577
+ "Kembali"
578
+ )
579
+ ).isCancel;
580
+ } while (res1);
581
+ }
582
+
583
+ // MultiPrompt 4: Pesan tambahan
584
+ res2 = (
585
+ await multiPrompt(
586
+ [],
587
+ [],
588
+ `<div class="child-container text-center">
589
+ <img class="img-fluid rounded-circle" src="https://i.pinimg.com/474x/7d/08/e5/7d08e5de7c11a7356c7ee187f39cbc34.jpg">
590
+ <div class="text-center">${
591
+ document.getElementById("cardSection").innerHTML
592
+ }</div></div>`,
593
+ true,
594
+ false,
595
+ true,
596
+ "Kembali",
597
+ true,
598
+ true,
599
+ document.getElementById("cardMessage").innerHTML ||
600
+ ucapanGabungan
601
+ )
602
+ ).isCancel;
603
+ } while (res2);
604
+
605
+ res3 = (
606
+ await multiPrompt(
607
+ [],
608
+ [],
609
+ `<div class="child-container text-center">
610
+ <img class="img-fluid rounded-circle" src="https://i.pinimg.com/736x/c1/78/ea/c178eae8b11823b36f4d76fc5f8a2a29.jpg">
611
+ <div class="text-center">${
612
+ document.querySelector(".areaFooter").innerHTML
613
+ }</div></div>`,
614
+ true,
615
+ false,
616
+ true,
617
+ "Kembali",
618
+ false
619
+ )
620
+ ).isCancel;
621
+ } while (res3);
622
+ });
623
+ }
624
+ } catch (e) {
625
+ console.error(e);
626
+ }
627
+
628
+ let counterAlert = 0;
629
+
630
+ async function alert(
631
+ message = "",
632
+ isPopUp = true,
633
+ isTime = false,
634
+ timeOut = 5,
635
+ messagesAfterTimeOut = [],
636
+ awaitResolve = 0
637
+ ) {
638
+ counterAlert++;
639
+
640
+ return new Promise((resolve) => {
641
+ try {
642
+ let modal;
643
+ let messageElem;
644
+ let timeOutElm;
645
+ let okBtn;
646
+ let intervalId;
647
+
648
+ if (isPopUp) {
649
+ modal = document.createElement("div");
650
+ modal.className = "modal";
651
+ modal.style.position = "fixed";
652
+ modal.style.top = "0";
653
+ modal.style.left = "0";
654
+ modal.style.width = "100%";
655
+ modal.style.height = "100%";
656
+ modal.style.backgroundColor = "rgba(0,0,0,0.5)";
657
+ modal.style.display = "flex";
658
+ modal.style.alignItems = "center";
659
+ modal.style.justifyContent = "center";
660
+ } else {
661
+ modal = document.createElement("div");
662
+ modal.className = "notification";
663
+ modal.style.position = "fixed";
664
+ modal.style.top = "5%";
665
+ modal.style.right = "2.5%";
666
+ modal.style.padding = "10px 20px";
667
+ modal.style.borderRadius = "5px";
668
+ modal.style.zIndex = "1000000000";
669
+ modal.setAttribute("data-aos", "fade-left");
670
+ }
671
+
672
+ const modalContent = document.createElement("div");
673
+ modalContent.className = `modal-content d-flex align-items-center ${
674
+ isPopUp
675
+ ? "bg-light"
676
+ : counterAlert % 2 === 0
677
+ ? "bg-success"
678
+ : "bg-primary"
679
+ } p-3 ${isPopUp ? "" : "text-white"}`;
680
+ modalContent.style.width = isPopUp ? "75%" : "100%";
681
+ modalContent.style.height = isPopUp ? "" : "100%";
682
+ modalContent.style.borderRadius = "5px";
683
+ modalContent.style.boxShadow = isPopUp
684
+ ? "0 2px 10px rgba(0,0,0,0.1)"
685
+ : "";
686
+
687
+ messageElem = document.createElement("p");
688
+ messageElem.innerHTML =
689
+ (!isPopUp ? `<i class="bi bi-bell-fill m-2"></i>` : ``) +
690
+ message;
691
+
692
+ timeOutElm = document.createElement("p");
693
+
694
+ okBtn = document.createElement("button");
695
+ okBtn.className = `btn ${
696
+ counterAlert % 2 === 0 ? "btn-primary" : "btn-warning"
697
+ } btn-lg`;
698
+ okBtn.textContent = "OK";
699
+ okBtn.style.minWidth = "80px";
700
+ okBtn.style.display = isTime ? "none" : "block";
701
+ okBtn.style.marginTop = "10px";
702
+
703
+ modalContent.appendChild(messageElem);
704
+
705
+ if (isTime) {
706
+ modalContent.appendChild(timeOutElm);
707
+ }
708
+
709
+ if (isPopUp) {
710
+ const btnContainer = document.createElement("div");
711
+ btnContainer.style.marginTop = "20px";
712
+ btnContainer.appendChild(okBtn);
713
+ modalContent.appendChild(btnContainer);
714
+ }
715
+
716
+ modal.appendChild(modalContent);
717
+ document.body.appendChild(modal);
718
+
719
+ okBtn.addEventListener("click", function () {
720
+ if (intervalId) clearInterval(intervalId);
721
+ if (document.body.contains(modal)) {
722
+ document.body.removeChild(modal);
723
+ }
724
+ resolve();
725
+ });
726
+
727
+ if (!isPopUp) {
728
+ intervalId = setInterval(async () => {
729
+ timeOut--;
730
+ console.log(timeOut);
731
+ if (messagesAfterTimeOut.length === 0)
732
+ timeOutElm.textContent = timeOut;
733
+ if (messagesAfterTimeOut.length > 0) {
734
+ messagesAfterTimeOut.forEach((mes) => {
735
+ if (mes.timeOut >= timeOut) {
736
+ modalContent.className =
737
+ "modal-content d-flex align-items-center bg-warning p-3";
738
+ messageElem.textContent = mes.message;
739
+ timeOutElm.textContent = timeOut;
740
+ }
741
+ });
742
+ }
743
+
744
+ if (timeOut <= 0) {
745
+ await new Promise((res) =>
746
+ setTimeout(res, awaitResolve)
747
+ );
748
+ if (document.body.contains(modal)) {
749
+ document.body.removeChild(modal);
750
+ }
751
+ clearInterval(intervalId);
752
+ resolve();
753
+ }
754
+ }, 1000);
755
+
756
+ setTimeout(() => {
757
+ if (document.body.contains(modal)) {
758
+ document.body.removeChild(modal);
759
+ }
760
+ resolve();
761
+ }, timeOut * 1000);
762
+ }
763
+ } catch (e) {
764
+ console.error(e);
765
+ }
766
+ });
767
+ }
768
+
769
+ async function multiPrompt(
770
+ inputConfigs = [
771
+ {
772
+ label: "Nama:",
773
+ type: "text",
774
+ placeholder: "Masukkan nama Anda",
775
+ id: "name",
776
+ value: "",
777
+ },
778
+ ],
779
+ selectConfigs = [
780
+ {
781
+ label: "Pilih Gender:",
782
+ options: [
783
+ { value: "L", label: "Laki-laki" },
784
+ { value: "P", label: "Perempuan" },
785
+ ],
786
+ default: "L",
787
+ id: "gender",
788
+ },
789
+ ],
790
+ innerHTMLOnTopMessage = "",
791
+ withCancelButton = true,
792
+ isDOM = false,
793
+ isDisabledAll = false,
794
+ cancelText = "",
795
+ withNextButton = true,
796
+ runFunc = false,
797
+ originalText = ""
798
+ ) {
799
+ console.log(ucapanGabungan, originalText, "AAAA");
800
+ return new Promise((resolve) => {
801
+ const modal = document.createElement("div");
802
+ modal.className = "modal";
803
+ Object.assign(modal.style, {
804
+ position: "fixed",
805
+ top: "0",
806
+ left: "0",
807
+ width: "100%",
808
+ height: "100%",
809
+ backgroundColor: "rgba(0,0,0,0.5)",
810
+ display: "flex",
811
+ alignItems: "center",
812
+ justifyContent: "center",
813
+ });
814
+
815
+ const modalContent = document.createElement("div");
816
+ modalContent.className = "modal-content";
817
+ Object.assign(modalContent.style, {
818
+ width: "75%",
819
+ background: "#fff",
820
+ padding: "20px",
821
+ borderRadius: "5px",
822
+ boxShadow: "0 2px 10px rgba(0,0,0,0.1)",
823
+ });
824
+
825
+ const okBtn = document.createElement("button");
826
+ const okBtnClassName = "btn btn-success btn-lg";
827
+ const okBtnTextContent = "Cari";
828
+
829
+ okBtn.className = isDOM
830
+ ? okBtnClassName.replace("success", "warning")
831
+ : okBtnClassName;
832
+ okBtn.textContent = isDisabledAll
833
+ ? "Lanjut"
834
+ : isDOM
835
+ ? okBtnTextContent
836
+ : "Ganti pesan";
837
+ okBtn.style.marginRight = "10px";
838
+ okBtn.style.display = withNextButton ? "" : "none";
839
+
840
+ const cancelBtn = document.createElement("button");
841
+ cancelBtn.className =
842
+ "btn btn-danger btn-lg" + (withCancelButton ? "" : " d-none");
843
+ cancelBtn.textContent = cancelText || "Batal";
844
+
845
+ const innerHTMLOnTopMessageContent = document.createElement("div");
846
+ innerHTMLOnTopMessageContent.innerHTML = innerHTMLOnTopMessage;
847
+
848
+ const form = document.createElement("form");
849
+
850
+ const inputElements = {};
851
+ const selectElements = {};
852
+
853
+ function changeOKBTN(isChange) {
854
+ okBtn.textContent = isDisabledAll
855
+ ? "Lanjut"
856
+ : isDOM
857
+ ? okBtnTextContent
858
+ : isChange === false
859
+ ? "Ganti pesan"
860
+ : "Ganti data";
861
+ okBtn.className = isDOM
862
+ ? okBtnClassName.replace("success", "warning")
863
+ : isChange === false
864
+ ? okBtnClassName
865
+ : okBtnClassName.replace("success", "primary");
866
+ }
867
+
868
+ inputConfigs.forEach((config) => {
869
+ const labelElem = document.createElement("label");
870
+ labelElem.textContent = config.label;
871
+ Object.assign(labelElem.style, {
872
+ display: "block",
873
+ marginTop: "10px",
874
+ });
875
+ form.appendChild(labelElem);
876
+
877
+ const input = document.createElement("input");
878
+ Object.assign(input, {
879
+ type: config.type || "text",
880
+ placeholder: config.placeholder || "",
881
+ required: true,
882
+ id: config.id,
883
+ });
884
+ Object.assign(input.style, {
885
+ width: "100%",
886
+ marginTop: "5px",
887
+ });
888
+ input.className = "form-control form-control-lg";
889
+ input.value = config.value;
890
+ inputElements[config.id] = input;
891
+ form.appendChild(input);
892
+
893
+ if (isDisabledAll) input.disabled = true;
894
+
895
+ input.addEventListener("change", () => {
896
+ changeOKBTN(inputElements[config.id].value !== config.value);
897
+ });
898
+ });
899
+
900
+ selectConfigs.forEach((config) => {
901
+ const labelElem = document.createElement("label");
902
+ labelElem.textContent = config.label;
903
+ Object.assign(labelElem.style, {
904
+ display: "block",
905
+ marginTop: "10px",
906
+ });
907
+ form.appendChild(labelElem);
908
+
909
+ const selectElem = document.createElement("select");
910
+ Object.assign(selectElem, {
911
+ required: true,
912
+ id: config.id,
913
+ });
914
+ Object.assign(selectElem.style, {
915
+ width: "100%",
916
+ marginTop: "5px",
917
+ });
918
+ selectElem.className = "form-select form-select-lg";
919
+
920
+ config.options.forEach((opt) => {
921
+ const optionElem = document.createElement("option");
922
+ optionElem.value = opt.value;
923
+ optionElem.textContent = opt.label;
924
+ if (config.default === opt.value) optionElem.selected = true;
925
+ selectElem.appendChild(optionElem);
926
+ });
927
+
928
+ selectElements[config.id] = selectElem;
929
+ form.appendChild(selectElem);
930
+
931
+ if (isDisabledAll) selectElem.disabled = true;
932
+
933
+ selectElem.addEventListener("change", () => {
934
+ changeOKBTN(selectElements[config.id].value !== config.default);
935
+ });
936
+ });
937
+
938
+ const btnContainer = document.createElement("div");
939
+ Object.assign(btnContainer.style, {
940
+ marginTop: "20px",
941
+ textAlign: "right",
942
+ });
943
+
944
+ btnContainer.appendChild(okBtn);
945
+ btnContainer.appendChild(cancelBtn);
946
+ form.appendChild(btnContainer);
947
+
948
+ modalContent.appendChild(innerHTMLOnTopMessageContent);
949
+ modalContent.appendChild(form);
950
+ modal.appendChild(modalContent);
951
+ document.body.appendChild(modal);
952
+
953
+ console.log(runFunc);
954
+
955
+ function initTypewriter() {
956
+ async function typeWriterHTML(element, html, speed = 50) {
957
+ let currentLength = renderedUcapanGabungan.length;
958
+ for (let i = currentLength; i < html.length; i++) {
959
+ renderedUcapanGabungan += html.charAt(i);
960
+ element.innerHTML = renderedUcapanGabungan;
961
+ await new Promise((resolve) => setTimeout(resolve, speed));
962
+
963
+ okBtn.disabled = true;
964
+ cancelBtn.disabled = true;
965
+ }
966
+
967
+ okBtn.disabled = false;
968
+ cancelBtn.disabled = false;
969
+ }
970
+
971
+ const cardMessagess = document.querySelectorAll(".card-body");
972
+ cardMessagess.forEach((cardMessages, index) => {
973
+ if (index !== 0) {
974
+ typeWriterHTML(
975
+ cardMessages,
976
+ marked.parse(originalText),
977
+ 25
978
+ );
979
+ }
980
+ });
981
+ }
982
+
983
+ if (document.readyState === "loading") {
984
+ document.addEventListener("DOMContentLoaded", initTypewriter);
985
+ } else {
986
+ initTypewriter();
987
+ }
988
+
989
+ form.addEventListener("submit", function (e) {
990
+ e.preventDefault();
991
+
992
+ let isValid = true;
993
+ const inputValues = {};
994
+ const selectValues = {};
995
+
996
+ Object.entries(inputElements).forEach(([id, elem]) => {
997
+ const value = elem.value.trim();
998
+ inputValues[id] = value;
999
+ if (value.length === 0) {
1000
+ elem.style.border = "1px solid red";
1001
+ isValid = false;
1002
+ } else {
1003
+ elem.style.border = "";
1004
+ }
1005
+ });
1006
+
1007
+ Object.entries(selectElements).forEach(([id, elem]) => {
1008
+ const value = elem.value;
1009
+ selectValues[id] = value;
1010
+ if (!value) {
1011
+ elem.style.border = "1px solid red";
1012
+ isValid = false;
1013
+ } else {
1014
+ elem.style.border = "";
1015
+ }
1016
+ });
1017
+
1018
+ if (isValid) {
1019
+ document.body.removeChild(modal);
1020
+ console.log(inputValues, selectValues);
1021
+ resolve({ inputValues, selectValues, isCancel: false });
1022
+ }
1023
+ });
1024
+
1025
+ okBtn.addEventListener("click", () => {
1026
+ form.dispatchEvent(new Event("submit", { cancelable: true }));
1027
+ });
1028
+
1029
+ cancelBtn.addEventListener("click", () => {
1030
+ document.body.removeChild(modal);
1031
+ resolve({
1032
+ inputValues: null,
1033
+ selectValues: null,
1034
+ isCancel: true,
1035
+ });
1036
+ });
1037
+ });
1038
+ }
1039
+
1040
+ let isCustomMessage = false;
1041
+
1042
+ try {
1043
+ document
1044
+ .getElementById("btnGU")
1045
+ .addEventListener("click", async function () {
1046
+ const fromName = document.getElementById("fromName").value.trim();
1047
+ const targetName = document
1048
+ .getElementById("targetName")
1049
+ .value.trim();
1050
+ const option = parseInt(
1051
+ document.getElementById("relationshipOption").value.trim()
1052
+ );
1053
+ const message = document.getElementById("message").value.trim();
1054
+
1055
+ const generatedUrl = (
1056
+ await generateUrl([
1057
+ fromName,
1058
+ targetName,
1059
+ option,
1060
+ isCustomMessage ? message : "",
1061
+ ])
1062
+ )[0];
1063
+
1064
+ document.getElementById(
1065
+ "generatedUrl"
1066
+ ).innerHTML = `<div class='alert alert-success'>
1067
+ <strong>URL Generated:</strong> <a href="${generatedUrl}" target="_blank">${generatedUrl}</a>
1068
+ </div>`;
1069
+ });
1070
+
1071
+ document
1072
+ .getElementById("isCustomMessage")
1073
+ .addEventListener("change", function () {
1074
+ const inputMessage = document.getElementById("inputMessage");
1075
+ if (this.checked) {
1076
+ inputMessage.setAttribute("class", "mt-3");
1077
+ isCustomMessage = true;
1078
+ } else {
1079
+ inputMessage.setAttribute("class", "mt-3 d-none");
1080
+ isCustomMessage = false;
1081
+ }
1082
+ });
1083
+ } catch (error) {}
1084
+
1085
+ async function generateUrl([fromName, targetName, option, message = ""]) {
1086
+ let i = 0;
1087
+ let generatedUrl = "";
1088
+
1089
+ while (true) {
1090
+ let queryUrl = "";
1091
+
1092
+ if (!fromName || !targetName) {
1093
+ alert("Mohon isi semua field sebelum generate URL", false);
1094
+ return;
1095
+ }
1096
+
1097
+ const fts = [fromName, targetName];
1098
+
1099
+ fts.forEach((ft, indexs) => {
1100
+ let finalFN = "";
1101
+
1102
+ let fNS = ft.split(" ");
1103
+ let fNSJ = fNS.join("");
1104
+
1105
+ fNS.forEach((word, index) => {
1106
+ let wl = Math.round(word.length / (i + 2));
1107
+ finalFN +=
1108
+ (indexs === 0 && index === 0) ||
1109
+ (indexs === 1 && index === fNS.length - 1)
1110
+ ? (word[i] || "x") +
1111
+ (fNSJ[wl] || "y") +
1112
+ (word[word.length - (i + 1)] || "z")
1113
+ : "";
1114
+ });
1115
+
1116
+ queryUrl += finalFN + (indexs === 0 ? "X" : "Y");
1117
+ });
1118
+
1119
+ const char = "abcdefghijklmnopqrstuvwxyz";
1120
+
1121
+ queryUrl += char[option + i] || "Z";
1122
+
1123
+ let data = await getURLSDATA(queryUrl);
1124
+
1125
+ if (!data) {
1126
+ data = {
1127
+ from: fromName,
1128
+ target: targetName,
1129
+ option: option.toString(),
1130
+ message: message,
1131
+ };
1132
+ }
1133
+
1134
+ console.log(queryUrl, data);
1135
+
1136
+ let isSuccess = false;
1137
+
1138
+ [isSuccess, urlsdatasDB] = await setURLSDATAData(queryUrl, data);
1139
+
1140
+ i++;
1141
+
1142
+ if (isSuccess) {
1143
+ generatedUrl = `${window.location.origin}?i=` + queryUrl;
1144
+ break;
1145
+ }
1146
+ }
1147
+
1148
+ return [generatedUrl, urlsdatasDB];
1149
+ }
1150
+
1151
+ try {
1152
+ function addStars(count) {
1153
+ for (let i = 0; i < count; i++) {
1154
+ const star = document.createElement("div");
1155
+ star.className = "star";
1156
+ // Atur posisi acak
1157
+ star.style.top = Math.random() * 100 + "%";
1158
+ star.style.left = Math.random() * 100 + "%";
1159
+ // Atur durasi animasi antara 2s hingga 5s
1160
+ star.style.animationDuration = 2 + Math.random() * 3 + "s";
1161
+ // Atur delay animasi antara 0s hingga 3s
1162
+ star.style.animationDelay = Math.random() * 3 + "s";
1163
+ document.body.appendChild(star);
1164
+ }
1165
+ }
1166
+ addStars(100);
1167
+ } catch {}