28 |
29 |
30 | <% recentReleases.results.forEach(card => { %>
31 |
32 |
33 | <%- card.title %>
34 | Episode: <%- card.episodeNumber %>
35 |
36 | <% }) %>
37 | <% recentReleases2.results.forEach(card => { %>
38 |
39 |
40 | <%- card.title %>
41 | Episode: <%- card.episodeNumber %>
42 |
43 | <% }) %>
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/public/js/af/random.js:
--------------------------------------------------------------------------------
1 | let randomData;
2 | async function randomAnime() {
3 | let randomIcn = document.getElementById('random-btn').className = "fa-regular fa-spinner-third"
4 | document.getElementById('random-btn').classList.add("spinning")
5 | let randomOutput = await fetch('https://cors.fl-anime.com/https://api.fl-anime.com/meta/anilist/random-anime');
6 | randomData = await randomOutput.json()
7 | window.location.href = '/watch/' + randomData.title.romaji.replace(/ /g, '-').replace('.', '').replace(',', '').replace('/', '').replace('?', '').replace(/:/g, '').replace(/!/g, '').replace('∞', '').replace(/☆/g, '-').replace(/;/g, '').replace(/~/g, '').replace(/ä/g, 'a') + '-episode-1'
8 | }
--------------------------------------------------------------------------------
/public/js/af/search_list.js:
--------------------------------------------------------------------------------
1 | // Generic Debouncing function :D
2 | function debounce(func, wait, immediate) {
3 | var timeout;
4 | return function() {
5 | var context = this,
6 | args = arguments;
7 | var callNow = immediate && !timeout;
8 | clearTimeout(timeout);
9 | timeout = setTimeout(function() {
10 | timeout = null;
11 | if (!immediate) {
12 | func.apply(context, args);
13 | }
14 | }, wait);
15 | if (callNow) func.apply(context, args);
16 | }
17 | }
18 |
19 | document.getElementById('livesearch').addEventListener('keyup', (e) => {
20 | if (e.keyCode == 27) return
21 | debouncedPost()
22 | })
23 |
24 | function showResult() {
25 | var x = document.getElementById("livesearch");
26 | $.post("https://cors.haikei.xyz/https://animefox.to/livesearch", { value: x.value }).done(function (data) {
27 | let list = DOMPurify.sanitize(document.getElementById("search-suggest").innerHTML = data)
28 | });
29 | }
30 |
31 | // Define the debounced function
32 | var debouncedPost = debounce(showResult, 300);
--------------------------------------------------------------------------------
/public/js/app.js:
--------------------------------------------------------------------------------
1 | // Universal Functions for Every HaiKei page
2 |
3 | function defaultConfig() {
4 | localStorage.setItem("_noads", false)
5 | localStorage.setItem("_firstload", false)
6 | localStorage.setItem("videoSource", "gogoanime")
7 | }
8 | if (localStorage.getItem("_firstload") == undefined) {
9 | defaultConfig()
10 | }
--------------------------------------------------------------------------------
/public/js/donate.js:
--------------------------------------------------------------------------------
1 | let loadedFlag = false;
2 | function copyAddr(addr) {
3 | navigator.clipboard.writeText(addr)
4 | // dynamically load css only the first time
5 | if (loadedFlag == false) {
6 | const link = document.createElement("link");
7 | link.rel = "stylesheet";
8 | link.href = "https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css";
9 | document.head.appendChild(link);
10 | loadedFlag = true;
11 | }
12 |
13 | Toastify({
14 | text: "Copied to clipboard!",
15 | duration: 3000,
16 | style: {
17 | background: "var(--dark-accent)",
18 | boxShadow: "none"
19 | },
20 | close: true,
21 | }).showToast();
22 |
23 | }
--------------------------------------------------------------------------------
/public/js/genres.js:
--------------------------------------------------------------------------------
1 | function toggle() {
2 | window.location.href = `/genre/${genre}`
3 | }
--------------------------------------------------------------------------------
/public/js/index.js:
--------------------------------------------------------------------------------
1 | const swiper = new Swiper(".swiper", {
2 | // Optional parameters
3 | direction: "horizontal",
4 | loop: true,
5 | allowTouchMove: true,
6 | pagination: {
7 | el: ".swiper-pagination",
8 | },
9 | autoplay: {
10 | delay: 6000,
11 |
12 | },
13 | keyboard: {
14 | enabled: true,
15 | onlyInViewport: false,
16 | },
17 | });
--------------------------------------------------------------------------------
/public/js/jquery_debounce.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery throttle / debounce - v1.1 - 3/7/2010
3 | * http://benalman.com/projects/jquery-throttle-debounce-plugin/
4 | *
5 | * Copyright (c) 2010 "Cowboy" Ben Alman
6 | * Dual licensed under the MIT and GPL licenses.
7 | * http://benalman.com/about/license/
8 | */
9 | (function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this);
--------------------------------------------------------------------------------
/public/js/kaomoji.js:
--------------------------------------------------------------------------------
1 | let joy = [
2 | '(* ^ ω ^)', '(´ ∀ ` *)', '٩(◕‿◕。)۶', '☆*:.。.o(≧▽≦)o.。.:*☆',
3 | '(o^▽^o)', '(⌒▽⌒)☆', '<( ̄︶ ̄)>', "。.:☆*:・'(*⌒―⌒*)))",
4 | 'ヽ(・∀・)ノ', '(´。• ω •。`)', '( ̄ω ̄)', '`;:゛;`;・(°ε° )',
5 | '(o・ω・o)', '(@^◡^)', 'ヽ(*・ω・)ノ', '(o_ _)ノ彡☆',
6 | '(^人^)', '(o´▽`o)', '(*´▽`*)', '。゚( ゚^∀^゚)゚。',
7 | '( ´ ω ` )', '(((o(*°▽°*)o)))', '(≧◡≦)', '(o´∀`o)',
8 | '(´• ω •`)', '(^▽^)', '(⌒ω⌒)', '∑d(°∀°d)',
9 | '╰(▔∀▔)╯', '(─‿‿─)', '(*^‿^*)', 'ヽ(o^ ^o)ノ',
10 | '(✯◡✯)', '(◕‿◕)', '(*≧ω≦*)', '(☆▽☆)',
11 | '(⌒‿⌒)', '\(≧▽≦)/', 'ヽ(o^▽^o)ノ', "☆ ~('▽^人)",
12 | '(*°▽°*)', '٩(。•́‿•̀。)۶', '(✧ω✧)', 'ヽ(*⌒▽⌒*)ノ',
13 | '(´。• ᵕ •。`)', '( ´ ▽ ` )', '( ̄▽ ̄)', '╰(*´︶`*)╯',
14 | 'ヽ(>∀<☆)ノ', 'o(≧▽≦)o', '(☆ω☆)', '(っ˘ω˘ς )',
15 | '\( ̄▽ ̄)/', '(*¯︶¯*)', '\(^▽^)/', '٩(◕‿◕)۶',
16 | "('o˘◡˘o)", '\(★ω★)/', '\(^ヮ^)/', '(〃^▽^〃)',
17 | '(╯✧▽✧)╯', 'o(>ω<)o', 'o( ❛ᴗ❛ )o', '。゚(TヮT)゚。',
18 | '( ‾́ ◡ ‾́ )', '(ノ´ヮ`)ノ*: ・゚', '(b ᵔ▽ᵔ)b', '(๑˃ᴗ˂)ﻭ',
19 | '(๑˘︶˘๑)', '( ˙꒳˙ )', '(*꒦ິ꒳꒦ີ)', '°˖✧◝(⁰▿⁰)◜✧˖°',
20 | '(´・ᴗ・ ` )', '(ノ◕ヮ◕)ノ*:・゚✧', '(„• ֊ •„)', '(.❛ ᴗ ❛.)',
21 | '(⁀ᗢ⁀)', '(¬‿¬ )', '(¬‿¬ )', '(* ̄▽ ̄)b',
22 | '( ˙▿˙ )', '(¯▿¯)', '( ◕▿◕ )', '\(٥⁀▽⁀ )/',
23 | '(„• ᴗ •„)', '(ᵔ◡ᵔ)', '( ´ ▿ ` )]'
24 | ]
25 |
26 | let sadness = [
27 | '(ノ_<。)', '(-_-)', '(´-ω-`)', '.・゚゚・(/ω\)・゚゚・.',
28 | '(μ_μ)', '(ノД`)', '(-ω-、)', '。゜゜(´O`) ゜゜。',
29 | 'o(TヘTo)', '( ; ω ; )', '(。╯︵╰。)', '。・゚゚*(>д<)*゚゚・。',
30 | '( ゚,_ゝ`)', '(个_个)', '(╯︵╰,)', '。・゚(゚>_<゚)゚・。',
31 | '( ╥ω╥ )', '(╯_╰)', '(╥_╥)', '.。・゚゚・(>_<)・゚゚・。.',
32 | '(/ˍ・、)', '(ノ_<、)', '(╥﹏╥)', '。゚(。ノωヽ。)゚。',
33 | '(つω`。)', '(。T ω T。)', '(ノω・、)', '・゚・(。>ω<。)・゚・',
34 | '(T_T)', '(>_<)', '(っ˘̩╭╮˘̩)っ', '。゚・ (>﹏<) ・゚。',
35 | 'o(〒﹏〒)o', '(。•́︿•̀。)', '(ಥ﹏ಥ)', '(ಡ‸ಡ)',
36 | ]
37 |
38 | class kaomoji {
39 |
40 | joy() {
41 | return joy[Math.floor(Math.random()*joy.length)];
42 | }
43 |
44 | sadness() {
45 | return sadness[Math.floor(Math.random()*sadness.length)];
46 | }
47 |
48 | }
--------------------------------------------------------------------------------
/public/js/login.js:
--------------------------------------------------------------------------------
1 | var code = document.getElementById("new-password");
2 | document.getElementById('complete_login').classList.add("enabled")
3 |
4 | const togglePassword = document.querySelector('#togglePassword');
5 | const password = document.querySelector('#new-password');
6 |
7 | togglePassword.addEventListener('click', function (e) {
8 | // toggle the type attribute
9 | const type = password.getAttribute('type') === 'password' ? 'text' : 'password';
10 | password.setAttribute('type', type);
11 | // toggle the eye slash icon
12 | this.classList.toggle('fa-eye-slash');
13 | this.classList.toggle('fa-eye')
14 | });
--------------------------------------------------------------------------------
/public/js/main.js:
--------------------------------------------------------------------------------
1 | // e.keyCode added for legacy support, if no one uses a legacy browser I will remove this in a later release
2 | // let searchBox = document.getElementById("searchanime")
3 | // searchBox.addEventListener('keyup', function(e) {
4 | // if (e.key == "Enter" || e.keyCode == 13) {
5 | // window.location.href = `/search?query=${searchBox.value}`
6 | // }
7 | // })
--------------------------------------------------------------------------------
/public/js/modals.js:
--------------------------------------------------------------------------------
1 | $("#login").iziModal();
2 | $("#userInfo").iziModal();
3 | $("#register").iziModal();
4 |
5 |
6 | setTimeout(() => {
7 | const iziModalCSS = document.createElement("link");
8 | iziModalCSS.rel = "stylesheet";
9 | iziModalCSS.href = "https://cdnjs.cloudflare.com/ajax/libs/izimodal/1.6.1/css/iziModal.css";
10 | document.head.appendChild(iziModalCSS);
11 |
12 | const fontAwesomeCSS = document.createElement("link");
13 | fontAwesomeCSS.rel = "stylesheet";
14 | fontAwesomeCSS.href = "https://site-assets.fontawesome.com/releases/v6.2.1/css/all.css";
15 | document.head.appendChild(fontAwesomeCSS);
16 | }, 0);
17 | let navFlag = 0; // false
18 |
19 | window.addEventListener('keydown', function(e) {
20 | if (e.key === 'Escape' && navFlag === 1) {
21 | sidebarClose();
22 | }
23 | });
24 |
25 | function sidebarOpen() {
26 | if (window.innerWidth <= 585) {
27 | document.getElementById("sidebar-nav").style.width = "100%";
28 | navFlag = 1; // true
29 | } else {
30 | document.getElementById("sidebar-nav").style.width = "360px";
31 | document.getElementById("sidebar-nav").style.filter = "brightness(1.5)"
32 | document.getElementById('full-doc').style.filter = "brightness(0.5)"
33 | navFlag = 1;
34 | }
35 |
36 | }
37 |
38 | function sidebarClose() {
39 | document.getElementById("sidebar-nav").style.width = "0";
40 | document.getElementById("sidebar-nav").style.filter = "brightness(0)"
41 | document.getElementById('full-doc').style.filter = "brightness(1)"
42 | navFlag = 0;
43 | }
--------------------------------------------------------------------------------
/public/js/recentReleases.js:
--------------------------------------------------------------------------------
1 | const consumetURL = "http://localhost:8081/http://localhost:8080/"
2 | let recentReleases;
3 | let recentReleases2;
4 | async function loadRecentReleases() {
5 | fetch(`${consumetURL}anime/gogoanime/recent-episodes`)
6 | .then((response) => response.json())
7 | .then((data) => recentReleases = data)
8 | .then(() =>
9 | recentReleases.results.forEach((ep) => {
10 |
11 | }));
12 | fetch(`${consumetURL}anime/gogoanime/recent-episodes?page=2`)
13 | .then((response) => response.json())
14 | .then((data) => recentReleases2 = data);
15 | }
16 | loadRecentReleases()
17 |
--------------------------------------------------------------------------------
/public/js/signup.js:
--------------------------------------------------------------------------------
1 | var code = document.getElementById("new-password");
2 |
3 | var strengthbar = document.getElementById("pw_strength");
4 | document.getElementById('complete_signup').classList.add("disabled")
5 | code.addEventListener("keyup", function() {
6 | checkPassword(code.value);
7 | });
8 |
9 | function checkPassword(password) {
10 | var strength = 0;
11 | if (password.match(/[a-z]+/)) {
12 | strength++;
13 | }
14 | if (password.match(/[A-Z]+/)) {
15 | strength++;
16 | }
17 | if (password.match(/[0-9]+/)) {
18 | strength++;
19 | }
20 | if (password.match(/[$@#&!]+/)) {
21 | strength++;
22 | if (password.length >= 8 ) {
23 | strength++
24 | }
25 | console.log(strength)
26 | }
27 |
28 | // if (password.length < 6) {
29 | // display.innerHTML = "minimum number of characters is 6";
30 | // }
31 |
32 | // if (password.length > 12) {
33 | // display.innerHTML = "maximum number of characters is 12";
34 | // }
35 |
36 | switch (strength) {
37 | case 0:
38 | strengthbar.style.width = '3%';
39 | document.getElementById('complete_signup').classList.add("disabled")
40 | document.getElementById('complete_signup').classList.remove("enabled");
41 | break;
42 |
43 | case 1:
44 | strengthbar.style.width = '20%';
45 | document.getElementById('complete_signup').classList.add("disabled")
46 | document.getElementById('complete_signup').classList.remove("enabled");
47 | break;
48 |
49 | case 2:
50 | strengthbar.style.width = '40%';
51 | document.getElementById('complete_signup').classList.add("disabled")
52 | document.getElementById('complete_signup').classList.remove("enabled");
53 | break;
54 |
55 | case 3:
56 | strengthbar.style.width = '60%';
57 | document.getElementById('complete_signup').classList.add("disabled")
58 | document.getElementById('complete_signup').classList.remove("enabled");
59 | break;
60 |
61 | case 4:
62 | strengthbar.style.width = '80%';
63 | document.getElementById('complete_signup').disabled = false;
64 | document.getElementById('complete_signup').classList.add("enabled");
65 | document.getElementById('complete_signup').classList.remove("disabled");
66 | break;
67 | case 5:
68 | strengthbar.style.width = '100%';
69 | document.getElementById('complete_signup').disabled = false;
70 | document.getElementById('complete_signup').classList.add("enabled");
71 | document.getElementById('complete_signup').classList.remove("disabled");
72 | break;
73 | }
74 | }
75 |
76 | const togglePassword = document.querySelector('#togglePassword');
77 | const password = document.querySelector('#new-password');
78 |
79 | togglePassword.addEventListener('click', function (e) {
80 | // toggle the type attribute
81 | const type = password.getAttribute('type') === 'password' ? 'text' : 'password';
82 | password.setAttribute('type', type);
83 | // toggle the eye slash icon
84 | this.classList.toggle('fa-eye-slash');
85 | this.classList.toggle('fa-eye')
86 | });
--------------------------------------------------------------------------------
/public/js/splide__fn.js:
--------------------------------------------------------------------------------
1 | let perPage = 6
2 |
3 | function carouselInit() {
4 | carousel = new Splide('.splide', {
5 | type: "loop",
6 | perPage: perPage,
7 | gap: "10px",
8 | breakpoints: {
9 | 1800: {
10 | perPage: 8
11 | },
12 | 1500: {
13 | perPage: 4,
14 | },
15 | 730: {
16 | perPage: 3,
17 | },
18 | 525: {
19 | perPage: 2,
20 | },
21 | 350: {
22 | perPage: 1,
23 | }
24 | },
25 | paginationKeyboard: true,
26 | height: '480px',
27 | }) // loads splide.js
28 | console.log("carousel.js loaded!")
29 | }
--------------------------------------------------------------------------------
/public/js/trending.js:
--------------------------------------------------------------------------------
1 | let trending;
2 | async function getTrending() {
3 |
4 |
5 | const res = await fetch(window.location.protocol + "//" + window.location.hostname + ":8080" + "/consumet/anime/gogoanime/top-airing", {
6 |
7 | })
8 |
9 | trending = await res.json();
10 |
11 | const slideContainer = document.getElementById("splide__list")
12 | slideContainer.style = "display: flex; align-items: center; justify-content: center"
13 |
14 | for (let c in trending.results) {
15 | // create slides
16 | const card = document.createElement("li")
17 | card.className = "splide__slide"
18 | card.setAttribute("onclick","window.location.href=" + `"${window.location.origin}/watch/${trending['results'][c].id}-episode-1"`);
19 | slideContainer.appendChild(card)
20 |
21 | // add image to slide
22 | const slideImg = document.createElement("img")
23 | slideImg.style = "width: 164px; height: 231px; align-self: center"
24 | slideImg.src = trending['results'][c].image
25 | card.appendChild(slideImg)
26 |
27 | // add title to slide
28 | const animeTxt = document.createElement("p")
29 | animeTxt.textContent = trending['results'][c].title
30 | animeTxt.className = "splide__animeTitle"
31 | card.appendChild(animeTxt)
32 |
33 | // add episode number to slide
34 | const releaseTxt = document.createElement("p")
35 | releaseTxt.textContent = "Genres: " + trending.results[c].genres[0] + ', ' + trending.results[c].genres[1]
36 | releaseTxt.className = "splide__episodeNum"
37 | card.appendChild(releaseTxt)
38 |
39 |
40 | }
41 |
42 |
43 |
44 | carousel.mount();
45 |
46 | }
47 | carouselInit()
48 | getTrending()
--------------------------------------------------------------------------------
/public/login.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
HaiKei | Login
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | HaiKei
15 | Sign in
16 | <% if (message) { %>
17 |
20 | <% } %>
21 |
32 |
33 | Don't have an account? Sign up
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Allow: /
3 | Crawl-delay: 2
4 | Sitemap: https://haikei.xyz/sitemap.xml
--------------------------------------------------------------------------------
/public/search.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
Search Results for <%= query %>
8 |
9 |
10 |
11 |
12 |
13 |
14 | <%- include("./templates/sidenav.ejs") %>
15 | <%- include("./templates/navbar.ejs") %>
16 |
17 |
18 |