diff --git a/.env b/.env index 7e40b56..7ee0421 100644 --- a/.env +++ b/.env @@ -12,6 +12,13 @@ TRANCO_USERNAME='' TRANCO_API_KEY='' CLOUDMERSIVE_API_KEY='' +GOOGLE_CLOUD_API_KEY='AIzaSyB4bvds3nkHhw29X5_xX549LULaRYm_2iU' +TORRENT_IP_API_KEY='385915166ab8461fbec188995e256dcf' +REACT_APP_SHODAN_API_KEY='WB6B7tRAskjlmpVUrYfnU1CVGCIpUs1t' +REACT_APP_WHO_API_KEY='0d49be5b3417cd42bd60712b139c730d' +SECURITY_TRAILS_API_KEY='cakw8TzsKJisdQX1QBd1ejpHm04SQa3F' +BUILT_WITH_API_KEY='6f6e1906-0c2a-4406-9d10-d7b5f2b21f25' + # API Keys for external services (frontend) REACT_APP_SHODAN_API_KEY='' REACT_APP_WHO_API_KEY='' @@ -24,3 +31,4 @@ REACT_APP_WHO_API_KEY='' # API_CORS_ORIGIN='*' # Enable CORS, by setting your allowed hostname(s) here # API_ENABLE_RATE_LIMIT='true' # Enable rate limiting for the API # REACT_APP_API_ENDPOINT='/api' # The endpoint for the API (can be local or remote) +# ENABLE_ANALYTICS='false' # Enable Plausible hit counter for the frontend diff --git a/astro.config.mjs b/astro.config.mjs index 4097853..e33b157 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,7 +1,7 @@ import { defineConfig } from 'astro/config'; // Integrations -// import svelte from '@astrojs/svelte'; +import svelte from '@astrojs/svelte'; import react from "@astrojs/react"; import partytown from '@astrojs/partytown'; import sitemap from '@astrojs/sitemap'; @@ -35,7 +35,7 @@ const base = unwrapEnvVar('BASE_URL', '/'); const isBossServer = unwrapEnvVar('BOSS_SERVER', false); // Initialize Astro integrations -const integrations = [react(), partytown(), sitemap()]; +const integrations = [svelte(), react(), partytown(), sitemap()]; // Set the appropriate adapter, based on the deploy target function getAdapter(target) { diff --git a/package.json b/package.json index 1dbe809..f6edcda 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "dotenv": "^16.4.5", "express": "^4.19.2", "express-rate-limit": "^7.2.0", + "framer-motion": "^11.2.6", "got": "^14.2.1", "pm2": "^5.3.1", "psl": "^1.9.0", @@ -42,6 +43,7 @@ "react-simple-maps": "^3.0.0", "react-toastify": "^10.0.5", "recharts": "^2.12.6", + "svelte": "^4.2.17", "traceroute": "^1.0.0", "typescript": "^5.4.5", "unzipper": "^0.11.5", diff --git a/src/components/HomeBackground.tsx b/src/components/HomeBackground.tsx new file mode 100644 index 0000000..d1a2b8a --- /dev/null +++ b/src/components/HomeBackground.tsx @@ -0,0 +1,119 @@ +import React, { useState, useEffect } from 'react'; +import { motion } from 'framer-motion'; +import styled from '@emotion/styled'; + +const dotSpacing = 32; + +const Meteor = styled(motion.div)` + position: absolute; + width: 4px; + height: 4px; + border-radius: 50%; + background-color: #9fef00; + box-shadow: 0 0 15px 3px #9fef00; + + &::before { + content: ''; + position: absolute; + top: -100px; + left: 0; + width: 2px; + height: 100px; + background: linear-gradient(to bottom, #9fef00, transparent); + } +`; + +const StyledSvg = styled.svg` + pointer-events: none; + position: absolute; + inset: 0; + height: 100%; + width: 100%; + fill: rgba(100, 100, 100, 0.5); +`; + +const StyledRect = styled.rect` + width: 100%; + height: 100%; + stroke-width: 0; +`; + +const generateMeteor = (id: number, gridSizeX: number, gridSizeY: number) => { + const column = Math.floor(Math.random() * gridSizeX); + const startRow = Math.floor(Math.random() * (gridSizeY - 12)); + const travelDistance = 5 + Math.floor(Math.random() * 10); // Between 5 and 15 spaces + const duration = 1.5 + Math.random(); // 1.5 to 2.5 seconds duration + + return { + id, + column, + startRow, + endRow: startRow + travelDistance, + duration, + key: Math.random() + Math.random(), + }; +}; + +const DotPattern = ({ className }: { className?: string }) => { + const countOfMeteors = 6; + const [gridSizeX, setGridSizeX] = useState(Math.floor(window.innerWidth / dotSpacing)); + const [gridSizeY, setGridSizeY] = useState(Math.floor(window.innerHeight / dotSpacing)); + const [meteors, setMeteors] = useState(() => Array.from({ length: countOfMeteors }, (_, index) => generateMeteor(index, gridSizeX, gridSizeY))); + + const handleAnimationComplete = (id: number) => { + setMeteors(current => + current.map(meteor => { + if (meteor.id === id) { + return generateMeteor(id, gridSizeX, gridSizeY); + } + return meteor; + }) + ); + }; + + useEffect(() => { + const handleResize = () => { + setGridSizeX(Math.floor(window.innerWidth / dotSpacing)); + setGridSizeY(Math.floor(window.innerHeight / dotSpacing)); + }; + + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + + return ( + <> + + + + + + + + + + {meteors.map(({ id, column, startRow, endRow, duration, key }) => ( + handleAnimationComplete(id)} + /> + ))} + + ); +}; + +export default DotPattern; diff --git a/src/pages/account/index.astro b/src/pages/account/index.astro new file mode 100644 index 0000000..65ec0c6 --- /dev/null +++ b/src/pages/account/index.astro @@ -0,0 +1,44 @@ +--- +import BaseLayout from '@layouts/Base.astro'; +import Nav from '@components/Nav.astro'; + +--- + + +
+
+
+ + diff --git a/src/pages/index.astro b/src/pages/index.astro index 9a6beb4..6e75e02 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,9 +1,9 @@ --- import BaseLayout from '@layouts/Base.astro'; import Nav from '@components/Nav.astro'; +import HomeBackground from '@/components/HomeBackground'; const isBossServer = import.meta.env.BOSS_SERVER === true; -console.log('IS BOSS?', isBossServer) const searchUrl = new URLSearchParams(new URL(Astro.request.url).search).get('url'); @@ -18,6 +18,7 @@ if (!isBossServer && searchUrl) { {!isBossServer && ()}
+