api-ix commited on
Commit
0ed58c6
·
verified ·
1 Parent(s): 0382f55

Upload script.js

Browse files
Files changed (1) hide show
  1. script.js +130 -964
script.js CHANGED
@@ -1,974 +1,140 @@
1
- // API Endpoints Data (from your original script.js)
2
  const endpoints = [
3
- {
4
- name: "Anime Downloader",
5
- path: "/api/animedl?name=solo%20leveling&episode=1",
6
- method: "GET",
7
- params: ["name", "episode"],
8
- description: "Download any anime series with ease",
9
- category: "Downloaders",
10
- },
11
- {
12
- name: "All-in-one",
13
- path: "/api/all-in-one?url=https://www.facebook.com/DeadWithDerrSter/videos/951658963655313/",
14
- method: "GET",
15
- params: ["url"],
16
- description: "Download any social media video",
17
- category: "Downloaders",
18
- },
19
- {
20
- name: "Anime Quote",
21
- path: "/api/aniquote",
22
- method: "GET",
23
- params: [],
24
- description: "Get a Random quote from popular anime series",
25
- category: "Fun",
26
- },
27
- {
28
- name: "APK Downloader",
29
- path: "/api/apkdl?q=Facebook%20lite",
30
- method: "GET",
31
- params: ["q"],
32
- description: "Endpoint for app downloader",
33
- category: "Downloaders",
34
- },
35
- {
36
- name: "Calculator",
37
- path: "/api/cal?num1=10&num2=5&operation=add",
38
- method: "GET",
39
- params: ["num1", "num2", "operation"],
40
- description: "Perform basic arithmetic operations",
41
- category: "Tools",
42
- },
43
- {
44
- name: "Country",
45
- path: "/api/country?q=Nigeria",
46
- method: "GET",
47
- params: ["q"],
48
- description: "Search for countries info",
49
- category: "Tools",
50
- },
51
- {
52
- name: "Currency Converter",
53
- path: "/api/convert?from=USD&to=EUR&amount=100",
54
- method: "GET",
55
- params: ["from", "to", "amount"],
56
- description: "Convert currencies with real-time exchange rates",
57
- category: "Tools",
58
- },
59
- {
60
- name: "Dare",
61
- path: "/api/dare",
62
- method: "GET",
63
- params: [],
64
- description: "Get a Random dare challenge",
65
- category: "Fun",
66
- },
67
- {
68
- name: "Encode",
69
- path: "/api/encode?text=Hello-world",
70
- method: "GET",
71
- params: ["text"],
72
- description: "Encode text to binary",
73
- category: "Tools",
74
- },
75
- {
76
- name: "Decode",
77
- path: "/api/decode?binary=01001000 01101001",
78
- method: "GET",
79
- params: ["binary"],
80
- description: "Decode binary to text",
81
- category: "Tools",
82
- },
83
- {
84
- name: "Font",
85
- path: "/api/font?text=Blue%20demon",
86
- method: "GET",
87
- params: ["text"],
88
- description: "Generate different fonts ",
89
- category: "Tools",
90
- },
91
- {
92
- name: "Facebook",
93
- path: "/api/fbdl?url=https://www.facebook.com/share/v/12En5xB3SQk/",
94
- method: "GET",
95
- params: ["url"],
96
- description: "Facebook video downloader",
97
- category: "Downloaders",
98
- },
99
- {
100
- name: "Gpt3.5",
101
- path: "/api/gpt3.5?prompt=hi",
102
- method: "GET",
103
- params: ["prompt"],
104
- description: "advance chatbot artificial intelligence",
105
- category: "Ai",
106
- },
107
- {
108
- name: "Waifu",
109
- path: "/api/waifu?q=",
110
- method: "GET",
111
- params: ["q"],
112
- description: "Get a Random waifu image (NSFW)",
113
- category: "Search",
114
- },
115
- {
116
- name: "Hentai",
117
- path: "/api/hentai",
118
- method: "GET",
119
- params: [],
120
- description: "Get a Random hentai videos (NSFW)",
121
- category: "Random",
122
- },
123
- {
124
- name: "Mediafire",
125
- path: "/api/mediafire?url=https://www.mediafire.com/file/2s3pdn53o12ug5a/%25E2%2588%2582%25C9%259B%25C6%25A8%25D1%2582%25D1%258F%25CA%258Bc%25D1%2582%25CE%25B9%25CF%2583%25D0%25B8%25CF%2587-2.zip/file",
126
- method: "GET",
127
- params: ["url"],
128
- description: "automated mediafire downloader",
129
- category: "Downloaders",
130
- },
131
- {
132
- name: "Pinterest",
133
- path: "/api/pinterest?q=fat%20ass",
134
- method: "GET",
135
- params: ["q"],
136
- description: "Get Pinterest image via search query",
137
- category: "Search",
138
- },
139
- {
140
- name: "Text2image",
141
- path: "/api/text2img?prompt=a%20big%20dog%20and%20a%20tiny%20cat",
142
- method: "GET",
143
- params: ["prompt"],
144
- description: "Generate an HD image via text prompt",
145
- category: "Ai",
146
- },
147
- {
148
- name: "Translator",
149
- path: "/api/translate?text=hello%20how%20are%20you&from=en&to=id",
150
- method: "GET",
151
- params: ["text"],
152
- description: "Translate from any language to another",
153
- category: "Tools",
154
- },
155
- {
156
- name: "Twitter / X",
157
- path: "/api/twitterdl?url=https://x.com/dammiedammie35/status/1897584097083400456?t=zU0X4PZDLQswYHbDCxi6Ng&s=09",
158
- method: "GET",
159
- params: ["url"],
160
- description: "Twitter video downloader",
161
- category: "Downloaders",
162
- },
163
- {
164
- name: "Instagram",
165
- path: "/api/instadl?url=https://www.instagram.com/reel/DBlb0Q8vxjD/?utm_source=ig_web_copy_link",
166
- method: "GET",
167
- params: ["url"],
168
- description: "Instagram video downloader",
169
- category: "Downloaders",
170
- },
171
- {
172
- name: "Joke",
173
- path: "/api/joke",
174
- method: "GET",
175
- params: [],
176
- description: "Get a Random joke to make you laugh",
177
- category: "Fun",
178
- },
179
- {
180
- name: "NpmCheck",
181
- path: "/api/npmcheck?package=express",
182
- method: "GET",
183
- params: ["package"],
184
- description: "Check any npmpackage details",
185
- category: "Search",
186
- },
187
- {
188
- name: "Movie downloader",
189
- path: "/api/moviedl?moviename=moana&episode=",
190
- method: "GET",
191
- params: ["moviename", "episode"],
192
- description: "search and download different movies",
193
- category: "Downloaders",
194
- },
195
- {
196
- name: "lyrics",
197
- path: "/api/lyrics?q=not%20like%20us",
198
- method: "GET",
199
- params: ["q"],
200
- description: "automated lyrics search",
201
- category: "Search",
202
- },
203
- {
204
- name: "Obfuscate",
205
- path: "/api/obf?code=console.log('hello');",
206
- method: "GET",
207
- params: ["code"],
208
- description: "Obfuscate your JavaScript code",
209
- category: "Tools",
210
- },
211
- {
212
- name: "Quote",
213
- path: "/api/quote",
214
- method: "GET",
215
- params: [],
216
- description: "Get an inspirational quote to brighten your day",
217
- category: "Fun",
218
- },
219
- {
220
- name: "Rizz",
221
- path: "/api/rizz",
222
- method: "GET",
223
- params: [],
224
- description: "Get a Random pickup line to impress your crush",
225
- category: "Fun",
226
- },
227
- {
228
- name: "wallpaper",
229
- path: "/api/wallpaper?q=naruto",
230
- method: "GET",
231
- params: ["q"],
232
- description: "generates cool wallpapers",
233
- category: "Random",
234
- },
235
- {
236
- name: "Web Screenshot",
237
- path: "/api/screenshot?url=https://api-xx-xi.hf.space/",
238
- method: "GET",
239
- params: ["url"],
240
- description: "Take a screenshot of any website via url",
241
- category: "Tools",
242
- },
243
- {
244
- name: "Spotify",
245
- path: "/api/spotifydl?url=https://open.spotify.com/track/1r3yPRzWPxM4O0S1T8X6vx?si=1NSDkaZxRjW-dDMcn14V7g",
246
- method: "GET",
247
- params: ["url"],
248
- description: "Download Spotify music via link",
249
- category: "Downloaders",
250
- },
251
- {
252
- name: "short movie clips",
253
- path: "/api/shortclip?q=moana",
254
- method: "GET",
255
- params: ["q"],
256
- description: "Get clips of any movie available",
257
- category: "Search",
258
- },
259
- {
260
- name: "Thread Downloader",
261
- path: "/api/threaddl?url=https://www.threads.net/@ekene_umenwa/post/DHL9gkgsZct?xmt=AQGzXGz-1ax86LccgoJoIaOR5xDXKhGxZwMB1HAkIr3yRw",
262
- method: "GET",
263
- params: ["url"],
264
- description: "Download Thread video/images without watermark",
265
- category: "Downloaders",
266
- },
267
- {
268
- name: "TikTok Downloader",
269
- path: "/api/tkdl?url=https://vm.tiktok.com/ZMknsbayE/",
270
- method: "GET",
271
- params: ["url"],
272
- description: "Download TikTok videos without watermark",
273
- category: "Downloaders",
274
- },
275
- {
276
- name: "TikTok Downloader V2",
277
- path: "/api/tkdl2?url=https://vm.tiktok.com/ZMknsbayE/",
278
- method: "GET",
279
- params: ["url"],
280
- description: "Download TikTok videos without watermark",
281
- category: "Downloaders",
282
- },
283
- {
284
- name: "Xxx Downloader",
285
- path: "/api/xvideos?url=https://www.xvideos.com/video.udvpliv122f/the_best_videos_of_hot_stepmom_alexa_payne",
286
- method: "GET",
287
- params: ["url"],
288
- description: "Download xvidos without premium access",
289
- category: "Downloaders",
290
- },
291
- {
292
- name: "Xxx Search",
293
- path: "/api/xxxsearch?q=big%20fat%20ass",
294
- method: "GET",
295
- params: ["q"],
296
- description: "Search xvideos with ease",
297
- category: "Search",
298
- },
299
- {
300
- name: "Xnxx Search",
301
- path: "/api/xnxxsearch?q=big%20fat%20ass",
302
- method: "GET",
303
- params: ["q"],
304
- description: "Search xnxx videos with ease",
305
- category: "Search",
306
- },
307
- {
308
- name: "TinyURL",
309
- path: "/api/tinyurl?url=https://api-x-demon-dev.hf.space",
310
- method: "GET",
311
- params: ["url"],
312
- description: "Shorten long URLs for easy sharing",
313
- category: "Tools",
314
- },
315
- {
316
- name: "Truth",
317
- path: "/api/truth",
318
- method: "GET",
319
- params: [],
320
- description: "Get a Random truth question for your game night",
321
- category: "Fun",
322
- },
323
- {
324
- name: "Flirt",
325
- path: "/api/flirt",
326
- method: "GET",
327
- params: [],
328
- description: "Get a Random flirting words for your crush😉",
329
- category: "Fun",
330
- },
331
- {
332
- name: "Wachannel info",
333
- path: "/api/wachannel?url=https://whatsapp.com/channel/0029Vah3fKtCnA7oMPTPJm1h",
334
- method: "GET",
335
- params: ["url"],
336
- description: "check WhatsApp channel info via link",
337
- category: "Tools",
338
- },
339
- {
340
- name: "YouTube MP3",
341
- path: "/api/ytmp3?url=https://youtu.be/wf_s7OIfHyw?si=yJSInCsXUVgHrH4t&qua=256",
342
- method: "GET",
343
- params: ["url"],
344
- description: "Convert YouTube videos to MP3 audio",
345
- category: "Downloaders",
346
- },
347
- {
348
- name: "YouTube MP4",
349
- path: "/api/ytmp4?url=https://youtu.be/wf_s7OIfHyw?si=yJSInCsXUVgHrH4t",
350
- method: "GET",
351
- params: ["url"],
352
- description: "Download YouTube videos in MP4 format",
353
- category: "Downloaders",
354
- },
355
- {
356
- name: "YouTube Search",
357
- path: "/api/yts?q=demon-slayers",
358
- method: "GET",
359
- params: ["q"],
360
- description: "Search for YouTube videos and get detailed information",
361
- category: "Search",
362
- },
363
- {
364
- name: "cecan-china",
365
- path: "/api/cecan-china",
366
- method: "GET",
367
- params: [],
368
- description: "Get a Random Chinese women image",
369
- category: "Random",
370
- },
371
- {
372
- name: "cecan-indo",
373
- path: "/api/cecan-indo",
374
- method: "GET",
375
- params: [],
376
- description: "Get a Random Indonesian women image",
377
- category: "Random",
378
- },
379
- {
380
- name: "cecan-japan",
381
- path: "/api/cecan-japan",
382
- method: "GET",
383
- params: [],
384
- description: "Get a Random Japanese women image",
385
- category: "Random",
386
- },
387
- {
388
- name: "cecan-korea",
389
- path: "/api/cecan-korea",
390
- method: "GET",
391
- params: [],
392
- description: "Get a Random Korean women image",
393
- category: "Random",
394
- },
395
- {
396
- name: "cecan-thailand",
397
- path: "/api/cecan-thailand",
398
- method: "GET",
399
- params: [],
400
- description: "Get a Random Thai women image",
401
- category: "Random",
402
- },
403
- {
404
- name: "cecan-vietnam",
405
- path: "/api/cecan-vietnam",
406
- method: "GET",
407
- params: [],
408
- description: "Get a Random Vietnamese women image",
409
- category: "Random",
410
- },
411
  ];
412
 
413
- // Global State
414
- let currentFilter = 'All';
415
- let displayedEndpoints = 12;
416
- let filteredEndpoints = [...endpoints];
417
- let isLoading = false;
418
-
419
- // DOM Elements
420
- const elements = {
421
- navToggle: document.getElementById('navToggle'),
422
- navMenu: document.getElementById('navMenu'),
423
- searchInput: document.getElementById('searchInput'),
424
- searchClear: document.getElementById('searchClear'),
425
- categoryFilters: document.getElementById('categoryFilters'),
426
- endpointsGrid: document.getElementById('endpointsGrid'),
427
- loadMoreBtn: document.getElementById('loadMoreBtn'),
428
- totalRequests: document.getElementById('totalRequests'),
429
- heroRequests: document.getElementById('heroRequests'),
430
- demoCode: document.getElementById('demoCode'),
431
- fab: document.getElementById('fab'),
432
- fabMain: document.getElementById('fabMain'),
433
- modal: document.getElementById('endpointModal'),
434
- modalTitle: document.getElementById('modalTitle'),
435
- modalBody: document.getElementById('modalBody'),
436
- modalClose: document.getElementById('modalClose'),
437
- modalBackdrop: document.getElementById('modalBackdrop'),
438
- toastContainer: document.getElementById('toastContainer')
439
- };
440
-
441
- // Utility Functions
442
- const debounce = (func, wait) => {
443
- let timeout;
444
- return function executedFunction(...args) {
445
- const later = () => {
446
- clearTimeout(timeout);
447
- func(...args);
448
- };
449
- clearTimeout(timeout);
450
- timeout = setTimeout(later, wait);
451
- };
452
- };
453
-
454
- const animateNumber = (element, start, end, duration = 2000) => {
455
- const startTime = performance.now();
456
- const animate = (currentTime) => {
457
- const elapsed = currentTime - startTime;
458
- const progress = Math.min(elapsed / duration, 1);
459
- const current = Math.floor(start + (end - start) * progress);
460
- element.textContent = current.toLocaleString();
461
- if (progress < 1) {
462
- requestAnimationFrame(animate);
463
- }
464
- };
465
- requestAnimationFrame(animate);
466
- };
467
-
468
- const showToast = (message, type = 'success') => {
469
- const toast = document.createElement('div');
470
- toast.className = `toast ${type}`;
471
- toast.innerHTML = `
472
- <i class="fas ${type === 'success' ? 'fa-check' : 'fa-exclamation-triangle'}"></i>
473
- <span>${message}</span>
474
- `;
475
-
476
- elements.toastContainer.appendChild(toast);
477
-
478
- // Show toast
479
- setTimeout(() => toast.classList.add('show'), 100);
480
-
481
- // Remove toast
482
- setTimeout(() => {
483
- toast.classList.remove('show');
484
- setTimeout(() => {
485
- if (toast.parentNode) {
486
- toast.parentNode.removeChild(toast);
487
- }
488
- }, 300);
489
- }, 3000);
490
- };
491
-
492
- // Initialize Particles
493
- const initParticles = () => {
494
- const particlesContainer = document.getElementById('particles');
495
- const particleCount = 50;
496
-
497
- for (let i = 0; i < particleCount; i++) {
498
- const particle = document.createElement('div');
499
- particle.className = 'particle';
500
- particle.style.left = Math.random() * 100 + '%';
501
- particle.style.top = Math.random() * 100 + '%';
502
- particle.style.animationDelay = Math.random() * 6 + 's';
503
- particle.style.animationDuration = (Math.random() * 3 + 3) + 's';
504
- particlesContainer.appendChild(particle);
505
- }
506
- };
507
-
508
- // Navigation
509
- const initNavigation = () => {
510
- // Mobile menu toggle
511
- elements.navToggle.addEventListener('click', () => {
512
- elements.navMenu.classList.toggle('active');
513
- elements.navToggle.classList.toggle('active');
514
- });
515
-
516
- // Navigation links
517
- document.querySelectorAll('.nav-link').forEach(link => {
518
- link.addEventListener('click', (e) => {
519
- e.preventDefault();
520
- const targetId = link.getAttribute('data-section');
521
- const targetElement = document.getElementById(targetId);
522
-
523
- if (targetElement) {
524
- const offsetTop = targetElement.offsetTop - 60;
525
- window.scrollTo({
526
- top: offsetTop,
527
- behavior: 'smooth'
528
- });
529
-
530
- // Update active nav link
531
- document.querySelectorAll('.nav-link').forEach(l => l.classList.remove('active'));
532
- link.classList.add('active');
533
-
534
- // Close mobile menu
535
- elements.navMenu.classList.remove('active');
536
- elements.navToggle.classList.remove('active');
537
- }
538
- });
539
- });
540
-
541
- // Update active nav on scroll
542
- window.addEventListener('scroll', () => {
543
- const sections = ['home', 'stats', 'endpoints', 'docs'];
544
- let currentSection = 'home';
545
-
546
- sections.forEach(sectionId => {
547
- const section = document.getElementById(sectionId);
548
- if (section) {
549
- const rect = section.getBoundingClientRect();
550
- if (rect.top <= 100 && rect.bottom >= 100) {
551
- currentSection = sectionId;
552
- }
553
- }
554
- });
555
-
556
- document.querySelectorAll('.nav-link').forEach(link => {
557
- link.classList.remove('active');
558
- if (link.getAttribute('data-section') === currentSection) {
559
- link.classList.add('active');
560
- }
561
- });
562
- });
563
- };
564
-
565
- // Typewriter Effect
566
- const initTypewriter = () => {
567
- const code = `// Make API Request
568
- fetch('/api/quote')
569
- .then(response => response.json())
570
- .then(data => {
571
- console.log(data);
572
- })
573
- .catch(error => {
574
- console.error('Error:', error);
575
- });`;
576
-
577
- let i = 0;
578
- const speed = 50;
579
-
580
- const typeWriter = () => {
581
- if (i < code.length) {
582
- elements.demoCode.textContent += code.charAt(i);
583
- i++;
584
- setTimeout(typeWriter, speed);
585
- }
586
- };
587
-
588
- setTimeout(typeWriter, 1000);
589
- };
590
-
591
- // Fetch Request Count
592
- const fetchRequestCount = async () => {
593
- try {
594
- const response = await fetch(`${window.location.origin}/api/requests`);
595
- const data = await response.json();
596
-
597
- if (data.success) {
598
- // Animate numbers
599
- animateNumber(elements.totalRequests, 0, data.request_count, 2000);
600
- animateNumber(elements.heroRequests, 0, data.request_count, 2000);
601
- } else {
602
- elements.totalRequests.textContent = 'Error';
603
- elements.heroRequests.textContent = 'Error';
604
- }
605
- } catch (error) {
606
- console.error('Error fetching request count:', error);
607
- elements.totalRequests.textContent = 'Error';
608
- elements.heroRequests.textContent = 'Error';
609
- }
610
- };
611
-
612
- // Create Category Filters
613
- const createCategoryFilters = () => {
614
- const categories = ['All', ...new Set(endpoints.map(endpoint => endpoint.category))];
615
-
616
- elements.categoryFilters.innerHTML = '';
617
-
618
- categories.forEach(category => {
619
- const filter = document.createElement('button');
620
- filter.className = `category-filter ${category === currentFilter ? 'active' : ''}`;
621
- filter.textContent = category;
622
- filter.addEventListener('click', () => filterEndpoints(category));
623
- elements.categoryFilters.appendChild(filter);
624
- });
625
- };
626
-
627
- // Filter Endpoints
628
- const filterEndpoints = (category) => {
629
- currentFilter = category;
630
- displayedEndpoints = 12;
631
-
632
- // Update active filter
633
- document.querySelectorAll('.category-filter').forEach(filter => {
634
- filter.classList.toggle('active', filter.textContent === category);
635
- });
636
-
637
- // Filter endpoints
638
- if (category === 'All') {
639
- filteredEndpoints = [...endpoints];
640
- } else {
641
- filteredEndpoints = endpoints.filter(endpoint => endpoint.category === category);
642
- }
643
-
644
- // Apply search filter if active
645
- const searchTerm = elements.searchInput.value.toLowerCase().trim();
646
- if (searchTerm) {
647
- filteredEndpoints = filteredEndpoints.filter(endpoint =>
648
- endpoint.name.toLowerCase().includes(searchTerm) ||
649
- endpoint.description.toLowerCase().includes(searchTerm) ||
650
- endpoint.category.toLowerCase().includes(searchTerm)
651
- );
652
- }
653
-
654
- renderEndpoints();
655
- };
656
-
657
- // Search Functionality
658
- const initSearch = () => {
659
- const handleSearch = debounce(() => {
660
- const searchTerm = elements.searchInput.value.toLowerCase().trim();
661
-
662
- // Show/hide clear button
663
- elements.searchClear.classList.toggle('visible', searchTerm.length > 0);
664
-
665
- // Filter endpoints
666
- if (searchTerm) {
667
- filteredEndpoints = endpoints.filter(endpoint =>
668
- endpoint.name.toLowerCase().includes(searchTerm) ||
669
- endpoint.description.toLowerCase().includes(searchTerm) ||
670
- endpoint.category.toLowerCase().includes(searchTerm)
671
- );
672
- } else {
673
- // Reset to current category filter
674
- if (currentFilter === 'All') {
675
- filteredEndpoints = [...endpoints];
676
- } else {
677
- filteredEndpoints = endpoints.filter(endpoint => endpoint.category === currentFilter);
678
- }
679
- }
680
-
681
- displayedEndpoints = 12;
682
- renderEndpoints();
683
- }, 300);
684
-
685
- elements.searchInput.addEventListener('input', handleSearch);
686
-
687
- // Clear search
688
- elements.searchClear.addEventListener('click', () => {
689
- elements.searchInput.value = '';
690
- elements.searchClear.classList.remove('visible');
691
- filterEndpoints(currentFilter);
692
- });
693
- };
694
-
695
- // Render Endpoints
696
- const renderEndpoints = () => {
697
- const endpointsToShow = filteredEndpoints.slice(0, displayedEndpoints);
698
-
699
- elements.endpointsGrid.innerHTML = '';
700
-
701
- if (endpointsToShow.length === 0) {
702
- elements.endpointsGrid.innerHTML = `
703
- <div style="grid-column: 1 / -1; text-align: center; padding: 3rem; color: var(--text-secondary);">
704
- <i class="fas fa-search" style="font-size: 3rem; margin-bottom: 1rem; opacity: 0.5;"></i>
705
- <h3>No endpoints found</h3>
706
- <p>Try adjusting your search or filter criteria</p>
707
- </div>
708
- `;
709
- elements.loadMoreBtn.style.display = 'none';
710
- return;
711
- }
712
-
713
- endpointsToShow.forEach((endpoint, index) => {
714
- const card = createEndpointCard(endpoint, index);
715
- elements.endpointsGrid.appendChild(card);
716
- });
717
-
718
- // Show/hide load more button
719
- elements.loadMoreBtn.style.display =
720
- filteredEndpoints.length > displayedEndpoints ? 'block' : 'none';
721
- };
722
-
723
- // Create Endpoint Card
724
- const createEndpointCard = (endpoint, index) => {
725
- const card = document.createElement('div');
726
- card.className = 'endpoint-card';
727
- card.style.animationDelay = `${index * 0.1}s`;
728
-
729
- card.innerHTML = `
730
- <div class="endpoint-header">
731
- <div>
732
- <h3 class="endpoint-title">${endpoint.name}</h3>
733
- <span class="endpoint-category">${endpoint.category}</span>
734
- </div>
735
- </div>
736
- <p class="endpoint-description">${endpoint.description}</p>
737
- <div class="endpoint-meta">
738
- <span class="method-tag">${endpoint.method}</span>
739
- ${endpoint.params.length > 0 ?
740
- endpoint.params.map(param => `<span class="param-tag">${param}</span>`).join('') :
741
- '<span class="param-tag">No params</span>'
742
- }
743
- </div>
744
- <div class="endpoint-actions">
745
- <button class="action-btn action-btn-primary copy-btn" data-path="${endpoint.path}">
746
- <i class="fas fa-copy"></i>
747
- <span>Copy</span>
748
- </button>
749
- <button class="action-btn action-btn-secondary test-btn" data-path="${endpoint.path}">
750
- <i class="fas fa-external-link-alt"></i>
751
- <span>Test</span>
752
- </button>
753
- </div>
754
- `;
755
-
756
- // Add event listeners
757
- const copyBtn = card.querySelector('.copy-btn');
758
- const testBtn = card.querySelector('.test-btn');
759
-
760
- copyBtn.addEventListener('click', (e) => {
761
- e.stopPropagation();
762
- const url = `${window.location.origin}${endpoint.path}`;
763
- navigator.clipboard.writeText(url).then(() => {
764
- showToast('URL copied to clipboard!');
765
- });
766
- });
767
-
768
- testBtn.addEventListener('click', (e) => {
769
- e.stopPropagation();
770
- const url = `${window.location.origin}${endpoint.path}`;
771
- window.open(url, '_blank');
772
- });
773
-
774
- // Card click to show modal
775
- card.addEventListener('click', () => {
776
- showEndpointModal(endpoint);
777
- });
778
-
779
- return card;
780
- };
781
-
782
- // Load More Endpoints
783
- const initLoadMore = () => {
784
- elements.loadMoreBtn.addEventListener('click', () => {
785
- if (isLoading) return;
786
-
787
- isLoading = true;
788
- elements.loadMoreBtn.innerHTML = `
789
- <i class="fas fa-spinner fa-spin"></i>
790
- <span>Loading...</span>
791
  `;
792
-
793
- setTimeout(() => {
794
- displayedEndpoints += 12;
795
- renderEndpoints();
796
- isLoading = false;
797
- elements.loadMoreBtn.innerHTML = `
798
- <i class="fas fa-plus"></i>
799
- <span>Load More</span>
800
- `;
801
- }, 500);
802
- });
803
- };
804
-
805
- // Modal Functions
806
- const showEndpointModal = (endpoint) => {
807
- elements.modalTitle.textContent = endpoint.name;
808
- elements.modalBody.innerHTML = `
809
- <div style="margin-bottom: 1.5rem;">
810
- <h4 style="color: var(--text-primary); margin-bottom: 0.5rem;">Description</h4>
811
- <p style="color: var(--text-secondary);">${endpoint.description}</p>
812
- </div>
813
-
814
- <div style="margin-bottom: 1.5rem;">
815
- <h4 style="color: var(--text-primary); margin-bottom: 0.5rem;">Endpoint URL</h4>
816
- <div class="code-block">
817
- <code>${window.location.origin}${endpoint.path}</code>
818
- </div>
819
- </div>
820
-
821
- <div style="margin-bottom: 1.5rem;">
822
- <h4 style="color: var(--text-primary); margin-bottom: 0.5rem;">Method</h4>
823
- <span class="method-tag">${endpoint.method}</span>
824
- </div>
825
-
826
- <div style="margin-bottom: 1.5rem;">
827
- <h4 style="color: var(--text-primary); margin-bottom: 0.5rem;">Parameters</h4>
828
- <div style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
829
- ${endpoint.params.length > 0 ?
830
- endpoint.params.map(param => `<span class="param-tag">${param}</span>`).join('') :
831
- '<span style="color: var(--text-secondary);">No parameters required</span>'
832
- }
833
- </div>
834
- </div>
835
-
836
- <div style="margin-bottom: 1.5rem;">
837
- <h4 style="color: var(--text-primary); margin-bottom: 0.5rem;">Example Request</h4>
838
- <div class="code-block">
839
- <code>curl -X ${endpoint.method} "${window.location.origin}${endpoint.path}"</code>
840
- </div>
841
- </div>
842
-
843
- <div style="display: flex; gap: 1rem; margin-top: 2rem;">
844
- <button class="btn btn-primary" onclick="copyEndpointURL('${endpoint.path}')">
845
- <i class="fas fa-copy"></i>
846
- <span>Copy URL</span>
847
- </button>
848
- <button class="btn btn-secondary" onclick="testEndpoint('${endpoint.path}')">
849
- <i class="fas fa-external-link-alt"></i>
850
- <span>Test Endpoint</span>
851
- </button>
852
  </div>
853
  `;
854
-
855
- elements.modal.classList.add('active');
856
- document.body.style.overflow = 'hidden';
857
- };
858
-
859
- const hideEndpointModal = () => {
860
- elements.modal.classList.remove('active');
861
- document.body.style.overflow = '';
862
- };
863
-
864
- // Global functions for modal buttons
865
- window.copyEndpointURL = (path) => {
866
- const url = `${window.location.origin}${path}`;
867
- navigator.clipboard.writeText(url).then(() => {
868
- showToast('URL copied to clipboard!');
869
- });
870
- };
871
-
872
- window.testEndpoint = (path) => {
873
- const url = `${window.location.origin}${path}`;
874
- window.open(url, '_blank');
875
- };
876
-
877
- // Modal event listeners
878
- const initModal = () => {
879
- elements.modalClose.addEventListener('click', hideEndpointModal);
880
- elements.modalBackdrop.addEventListener('click', hideEndpointModal);
881
-
882
- document.addEventListener('keydown', (e) => {
883
- if (e.key === 'Escape' && elements.modal.classList.contains('active')) {
884
- hideEndpointModal();
885
- }
886
- });
887
- };
888
 
889
- // Floating Action Button
890
- const initFAB = () => {
891
- elements.fabMain.addEventListener('click', () => {
892
- elements.fab.classList.toggle('active');
893
- });
894
-
895
- // FAB actions
896
- document.querySelectorAll('.fab-action').forEach(action => {
897
- action.addEventListener('click', () => {
898
- const actionType = action.getAttribute('data-action');
899
-
900
- switch (actionType) {
901
- case 'top':
902
- window.scrollTo({ top: 0, behavior: 'smooth' });
903
- break;
904
- case 'share':
905
- if (navigator.share) {
906
- navigator.share({
907
- title: 'BLUE DEMON API',
908
- text: 'Check out this awesome API platform!',
909
- url: window.location.href
910
- });
911
- } else {
912
- navigator.clipboard.writeText(window.location.href);
913
- showToast('URL copied to clipboard!');
914
- }
915
- break;
916
- case 'theme':
917
- showToast('Theme toggle coming soon!');
918
- break;
919
- }
920
-
921
- elements.fab.classList.remove('active');
922
- });
923
- });
924
-
925
- // Close FAB when clicking outside
926
- document.addEventListener('click', (e) => {
927
- if (!elements.fab.contains(e.target)) {
928
- elements.fab.classList.remove('active');
929
- }
930
- });
931
- };
932
-
933
- // Scroll to section function
934
- window.scrollToSection = (sectionId) => {
935
- const section = document.getElementById(sectionId);
936
- if (section) {
937
- const offsetTop = section.offsetTop - 60;
938
- window.scrollTo({
939
- top: offsetTop,
940
- behavior: 'smooth'
941
- });
942
  }
943
- };
944
 
945
- // Initialize everything
946
- const init = () => {
947
- // Initialize components
948
- initParticles();
949
- initNavigation();
950
- initTypewriter();
951
- initSearch();
952
- initLoadMore();
953
- initModal();
954
- initFAB();
955
-
956
- // Create content
957
- createCategoryFilters();
958
-
959
- // Initial render
960
- filterEndpoints('All');
961
-
962
- // Fetch data
963
- fetchRequestCount();
964
-
965
- // Update request count periodically
966
- setInterval(fetchRequestCount, 30000);
967
- };
968
 
969
- // Start when DOM is loaded
970
- if (document.readyState === 'loading') {
971
- document.addEventListener('DOMContentLoaded', init);
972
- } else {
973
- init();
974
- }
 
1
+ /* ====== DATA ====== */
2
  const endpoints = [
3
+ { name: "Anime Downloader", path: "/api/animedl?name=solo%20leveling&episode=1", method: "GET", params: ["name","episode"], desc: "Download any anime series with ease", cat: "Downloaders"},
4
+ { name: "All-in-one", path: "/api/all-in-one?url=https://fb.com/video", method: "GET", params: ["url"], desc: "Download any social-media video", cat: "Downloaders"},
5
+ { name: "Anime Quote", path: "/api/aniquote", method: "GET", params: [], desc: "Random quote from popular anime", cat: "Fun"},
6
+ { name: "APK Downloader", path: "/api/apkdl?q=Facebook%20lite", method: "GET", params: ["q"], desc: "Download APKs directly", cat: "Downloaders"},
7
+ { name: "Calculator", path: "/api/cal?num1=10&num2=5&operation=add", method: "GET", params: ["num1","num2","operation"], desc: "Basic arithmetic", cat: "Tools"},
8
+ { name: "Country Info", path: "/api/country?q=Nigeria", method: "GET", params: ["q"], desc: "Country profiles", cat: "Tools"},
9
+ { name: "Currency Converter", path: "/api/convert?from=USD&to=EUR&amount=100", method: "GET", params: ["from","to","amount"], desc: "Live exchange rates", cat: "Tools"},
10
+ { name: "Dare", path: "/api/dare", method: "GET", params: [], desc: "Random dare challenge", cat: "Fun"},
11
+ { name: "Encode", path: "/api/encode?text=Hello-world", method: "GET", params: ["text"], desc: "Text → binary", cat: "Tools"},
12
+ { name: "Decode", path: "/api/decode?binary=01001000", method: "GET", params: ["binary"], desc: "Binary → text", cat: "Tools"},
13
+ { name: "Facebook DL", path: "/api/fbdl?url=URL", method: "GET", params: ["url"], desc: "Facebook video downloader", cat: "Downloaders"},
14
+ { name: "Gpt3.5", path: "/api/gpt3.5?prompt=hi", method: "GET", params: ["prompt"], desc: "ChatGPT-3.5 turbo", cat: "AI"},
15
+ { name: "TikTok DL", path: "/api/tkdl?url=URL", method: "GET", params: ["url"], desc: "No-watermark TikTok", cat: "Downloaders"},
16
+ { name: "Instagram DL", path: "/api/instadl?url=URL", method: "GET", params: ["url"], desc: "Instagram media downloader", cat: "Downloaders"},
17
+ { name: "YouTube MP4", path: "/api/ytmp4?url=URL", method: "GET", params: ["url"], desc: "YouTube video", cat: "Downloaders"},
18
+ { name: "YouTube MP3", path: "/api/ytmp3?url=URL", method: "GET", params: ["url"], desc: "YouTube audio", cat: "Downloaders"},
19
+ { name: "Text-to-Image", path: "/api/text2img?prompt=hello", method: "GET", params: ["prompt"], desc: "AI image generation", cat: "AI"},
20
+ { name: "Translator", path: "/api/translate?text=hello&from=en&to=id", method: "GET", params: ["text","from","to"], desc: "Auto-detect translate", cat: "Tools"},
21
+ { name: "Joke", path: "/api/joke", method: "GET", params: [], desc: "Random joke", cat: "Fun"},
22
+ { name: "Quote", path: "/api/quote", method: "GET", params: [], desc: "Inspirational quote", cat: "Fun"},
23
+ { name: "Screenshot", path: "/api/screenshot?url=WEBSITE", method: "GET", params: ["url"], desc: "Website screenshot", cat: "Tools"},
24
+ { name: "TinyURL", path: "/api/tinyurl?url=LONG", method: "GET", params: ["url"], desc: "URL shortener", cat: "Tools"},
25
+ { name: "Spotify DL", path: "/api/spotifydl?url=TRACK_URL", method: "GET", params: ["url"], desc: "Spotify downloader", cat: "Downloaders"},
26
+ { name: "Twitter DL", path: "/api/twitterdl?url=TWEET_URL", method: "GET", params: ["url"], desc: "Twitter video downloader", cat: "Downloaders"},
27
+ { name: "Pinterest Search", path: "/api/pinterest?q=cats", method: "GET", params: ["q"], desc: "Pinterest images", cat: "Search"},
28
+ { name: "Wallpaper", path: "/api/wallpaper?q=nature", method: "GET", params: ["q"], desc: "HD wallpapers", cat: "Random"},
29
+ { name: "Waifu (NSFW)", path: "/api/waifu?q=", method: "GET", params: ["q"], desc: "Random waifu pics", cat: "Random"},
30
+ { name: "Hentai (NSFW)", path: "/api/hentai", method: "GET", params: [], desc: "Hentai videos", cat: "Random"},
31
+ { name: "XXX Search", path: "/api/xxxsearch?q=keyword", method: "GET", params: ["q"], desc: "Search adult videos", cat: "Search"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  ];
33
 
34
+ const baseURL = window.location.origin;
35
+
36
+ /* ====== STATE ====== */
37
+ let filtered = [...endpoints];
38
+ let page = 0;
39
+ const perPage = 12;
40
+
41
+ /* ====== DOM ====== */
42
+ const grid = document.getElementById('grid');
43
+ const search = document.getElementById('search');
44
+ const pills = document.getElementById('pills');
45
+ const loadBtn = document.getElementById('loadMore');
46
+ const modal = document.getElementById('modal');
47
+ const mTitle = document.getElementById('mTitle');
48
+ const mBody = document.getElementById('mBody');
49
+
50
+ /* ====== INIT ====== */
51
+ function init() {
52
+ createPills();
53
+ render();
54
+ bindEvents();
55
+ fetchCount();
56
+ }
57
+
58
+ /* ====== CATEGORIES ====== */
59
+ function createPills() {
60
+ const cats = ['All', ...new Set(endpoints.map(e => e.cat))];
61
+ pills.innerHTML = cats.map(c => `<button class="pill" data-cat="${c}">${c}</button>`).join('');
62
+ pills.firstElementChild.classList.add('active');
63
+ }
64
+
65
+ /* ====== RENDER ====== */
66
+ function render(reset = true) {
67
+ if (reset) { grid.innerHTML = ''; page = 0; }
68
+ const slice = filtered.slice(0, (page + 1) * perPage);
69
+ slice.forEach(e => {
70
+ const card = document.createElement('div');
71
+ card.className = 'card';
72
+ card.innerHTML = `
73
+ <span class="cat">${e.cat}</span>
74
+ <h4>${e.name}</h4>
75
+ <p>${e.desc}</p>
76
+ <span class="method">${e.method}</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  `;
78
+ card.onclick = () => openModal(e);
79
+ grid.appendChild(card);
80
+ });
81
+ loadBtn.style.display = slice.length < filtered.length ? 'block' : 'none';
82
+ }
83
+
84
+ /* ====== SEARCH / FILTER ====== */
85
+ function bindEvents() {
86
+ search.addEventListener('input', filter);
87
+ pills.addEventListener('click', e => {
88
+ if (!e.target.classList.contains('pill')) return;
89
+ pills.querySelector('.active')?.classList.remove('active');
90
+ e.target.classList.add('active');
91
+ filter();
92
+ });
93
+ loadBtn.addEventListener('click', () => { page++; render(false); });
94
+ modal.querySelector('.modal-close').onclick = closeModal;
95
+ modal.querySelector('.modal-backdrop').onclick = closeModal;
96
+ }
97
+
98
+ function filter() {
99
+ const term = search.value.toLowerCase();
100
+ const cat = pills.querySelector('.active').dataset.cat;
101
+ filtered = endpoints.filter(e =>
102
+ (cat === 'All' || e.cat === cat) &&
103
+ (e.name.toLowerCase().includes(term) || e.desc.toLowerCase().includes(term))
104
+ );
105
+ render();
106
+ }
107
+
108
+ /* ====== MODAL ====== */
109
+ function openModal(e) {
110
+ mTitle.textContent = e.name;
111
+ const url = `${baseURL}${e.path}`;
112
+ mBody.innerHTML = `
113
+ <p>${e.desc}</p>
114
+ <p><strong>Method:</strong> ${e.method}</p>
115
+ ${e.params.length ? `<p><strong>Params:</strong> ${e.params.join(', ')}</p>` : ''}
116
+ <div class="code-snippet">curl -X ${e.method} "${url}"</div>
117
+ <div style="margin-top:1rem">
118
+ <button class="btn-copy" onclick="navigator.clipboard.writeText('${url}')">Copy URL</button>
119
+ <a href="${url}" target="_blank" style="margin-left:.5rem" class="btn-copy">Test</a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  </div>
121
  `;
122
+ modal.classList.add('active');
123
+ }
124
+ function closeModal() { modal.classList.remove('active'); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
+ /* ====== LIVE REQUEST COUNT ====== */
127
+ async function fetchCount() {
128
+ try {
129
+ const res = await fetch(`${baseURL}/api/requests`);
130
+ const data = await res.json();
131
+ document.getElementById('req-count').textContent = data.request_count.toLocaleString();
132
+ } catch {
133
+ document.getElementById('req-count').textContent = '0';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  }
135
+ }
136
 
137
+ /* ====== UTILS ====== */
138
+ window.scrollToSection = id => document.getElementById(id).scrollIntoView({ behavior: 'smooth' });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
+ init();