From f193f1e86c2c98e14d827c4d38d0e51617bcaf3e Mon Sep 17 00:00:00 2001
From: zyqunix <117040076+zyqunix@users.noreply.github.com>
Date: Thu, 3 Jul 2025 22:22:16 +0200
Subject: [PATCH 1/2] badge api
---
assets/css/style.css | 16 ++++++++++++++++
assets/js/badgesapi.js | 29 +++++++++++++++++++++++++++++
assets/js/index.js | 6 ++++--
index.html | 3 ++-
4 files changed, 51 insertions(+), 3 deletions(-)
create mode 100644 assets/js/badgesapi.js
diff --git a/assets/css/style.css b/assets/css/style.css
index 140ced9..0eb12cf 100644
--- a/assets/css/style.css
+++ b/assets/css/style.css
@@ -770,3 +770,19 @@ br {
#review-person:hover {
text-decoration: underline;
}
+
+#badges {
+ display: flex;
+ padding: 3px;
+ background-color: var(--surface0);
+ border: 2px solid var(--surface1);
+ align-items: center;
+ justify-content: center;
+ gap: 3px;
+ border-radius: 8px;
+ margin-bottom: 10px;
+}
+
+#badges > img {
+ border-radius: 50%;
+}
diff --git a/assets/js/badgesapi.js b/assets/js/badgesapi.js
new file mode 100644
index 0000000..36a6f9f
--- /dev/null
+++ b/assets/js/badgesapi.js
@@ -0,0 +1,29 @@
+import { user } from "./index.js";
+const apiUrl = "https://badges.atums.world";
+
+
+export async function getBadges(user) {
+ const response = await fetch(`${apiUrl}/${user}`);
+ if (!response.ok) throw new Error(`Error fetching reviews: ${response.status} ${response.statusText}`);
+ const data = await response.json();
+ return data;
+}
+
+export async function populateBadges(element) {
+ const target = document.querySelector(element);
+ const data = await getBadges(user);
+
+ target.innerHTML = "";
+
+ data.badges.forEach(badge => {
+ const badgeEl = document.createElement("div");
+ const badgeImg = document.createElement("img");
+ badgeImg.src = badge.badge;
+ badgeEl.classList.add("tooltip");
+ badgeEl.setAttribute("data-tooltip", badge.tooltip);
+ badgeImg.style.width = "32px";
+
+ badgeEl.appendChild(badgeImg);
+ target.appendChild(badgeEl);
+ })
+}
diff --git a/assets/js/index.js b/assets/js/index.js
index af43ccc..707d791 100644
--- a/assets/js/index.js
+++ b/assets/js/index.js
@@ -1,10 +1,12 @@
import * as wakatime from "./wakatime.js";
import * as github from "./github.js";
import * as reviewdb from "./reviewdb.js";
+import * as badgeapi from "./badgesapi.js";
+
const timeElem = document.getElementById('time');
const timezone = 'Europe/Berlin';
-timeElem.setAttribute('data-tooltip', timezone);
+export const user = "1201415921802170388";
function getTime(timezone) {
const now = new Date();
@@ -85,7 +87,6 @@ setInterval(() => {
ageElem.setAttribute("data-tooltip", updateAge(null, 10, "years old"));
}, 10);
-const user = "1201415921802170388";
function lan() {
lanyard({userId: user}).then(data => {
@@ -289,6 +290,7 @@ function fetchWeather(location) {
wakatime.fetchWakatime("#wakapi");
github.writeGithubStats("#github-full");
reviewdb.writeReviews("#reviews");
+badgeapi.populateBadges("#badges");
const messages = [
"Coding",
diff --git a/index.html b/index.html
index 89ae213..e4a1e63 100644
--- a/index.html
+++ b/index.html
@@ -14,7 +14,8 @@
-
+
Badges
+
Coding, Listening to Music, Reverse Engineering, Playing Counter-Strike
From a6111e4a55445d849c08ac8a2da887d5c1940b63 Mon Sep 17 00:00:00 2001
From: zyqunix <117040076+zyqunix@users.noreply.github.com>
Date: Thu, 3 Jul 2025 22:50:46 +0200
Subject: [PATCH 2/2] various weather decoration
---
assets/js/index.js | 26 ++++++++++---
assets/js/rain.js | 88 ++++++++++++++++++++++++++++++++++++++++++
assets/js/snow.js | 95 ++++++++++++++++++++++++++++++++++++++++++++++
assets/js/stars.js | 63 ++++++++++++++++++++++++++++++
4 files changed, 267 insertions(+), 5 deletions(-)
create mode 100644 assets/js/rain.js
create mode 100644 assets/js/snow.js
create mode 100644 assets/js/stars.js
diff --git a/assets/js/index.js b/assets/js/index.js
index 707d791..f056c0b 100644
--- a/assets/js/index.js
+++ b/assets/js/index.js
@@ -277,14 +277,19 @@ function fetchSong() {
});
}
-function fetchWeather(location) {
+async function fetchWeather(location) {
const target = document.getElementById('weather');
const query = location ? location : "Munich";
- fetch(`https://wttr.in/${query}?format=%t | %C`).then(response => response.text()).then(data => {
+
+ try {
+ const response = await fetch(`https://wttr.in/${query}?format=%t | %C`);
+ const data = await response.text();
target.innerText = data;
- }).catch(() => {
+ return data;
+ } catch {
target.innerText = "Weather unavailable";
- });
+ return null;
+ }
}
wakatime.fetchWakatime("#wakapi");
@@ -347,9 +352,20 @@ setInterval(() => {
}, 50);
typeWriter();
-fetchWeather();
fetchSong();
+const weather = await fetchWeather();
+
+if (weather && weather.includes("rain")) {
+ const deco = document.createElement("script");
+ deco.src = "/assets/js/rain.js";
+ document.body.appendChild(deco);
+} else if (weather.includes("snow")) {
+ const deco = document.createElement("script");
+ deco.src = "/assets/js/snow.js";
+ document.body.appendChild(deco);
+}
+
let countdown = 60;
setInterval(() => {
diff --git a/assets/js/rain.js b/assets/js/rain.js
new file mode 100644
index 0000000..1e51d6e
--- /dev/null
+++ b/assets/js/rain.js
@@ -0,0 +1,88 @@
+const rainContainer = document.createElement("div");
+rainContainer.style.position = "fixed";
+rainContainer.style.top = "0";
+rainContainer.style.left = "0";
+rainContainer.style.width = "100vw";
+rainContainer.style.height = "100vh";
+rainContainer.style.pointerEvents = "none";
+document.body.appendChild(rainContainer);
+
+const maxRaindrops = 100;
+const raindrops = [];
+const mouse = { x: -100, y: -100 };
+
+document.addEventListener("mousemove", (e) => {
+ mouse.x = e.clientX;
+ mouse.y = e.clientY;
+});
+
+const getRaindropColor = () => {
+ const htmlTag = document.documentElement;
+ return htmlTag.getAttribute("data-theme") === "dark"
+ ? "rgba(173, 216, 230, 0.8)"
+ : "rgba(70, 130, 180, 0.8)";
+};
+
+const createRaindrop = () => {
+ if (raindrops.length >= maxRaindrops) {
+ const oldest = raindrops.shift();
+ rainContainer.removeChild(oldest);
+ }
+
+ const raindrop = document.createElement("div");
+ raindrop.classList.add("raindrop");
+ raindrop.style.position = "absolute";
+ const height = Math.random() * 10 + 10;
+ raindrop.style.width = "2px";
+ raindrop.style.height = `${height}px`;
+ raindrop.style.background = getRaindropColor();
+ raindrop.style.borderRadius = "1px";
+ raindrop.style.opacity = Math.random() * 0.5 + 0.3;
+
+ raindrop.x = Math.random() * window.innerWidth;
+ raindrop.y = -height;
+ raindrop.speed = Math.random() * 6 + 4;
+ raindrop.directionX = (Math.random() - 0.5) * 0.2;
+ raindrop.directionY = Math.random() * 0.5 + 0.8;
+
+ raindrop.style.left = `${raindrop.x}px`;
+ raindrop.style.top = `${raindrop.y}px`;
+
+ raindrops.push(raindrop);
+ rainContainer.appendChild(raindrop);
+};
+
+setInterval(createRaindrop, 50);
+
+function updateRaindrops() {
+ raindrops.forEach((raindrop, index) => {
+ const height = Number.parseFloat(raindrop.style.height);
+
+ raindrop.x += raindrop.directionX * raindrop.speed;
+ raindrop.y += raindrop.directionY * raindrop.speed;
+
+ raindrop.style.left = `${raindrop.x}px`;
+ raindrop.style.top = `${raindrop.y}px`;
+
+ if (raindrop.y > window.innerHeight) {
+ rainContainer.removeChild(raindrop);
+ raindrops.splice(index, 1);
+ return;
+ }
+
+ if (
+ raindrop.x > window.innerWidth ||
+ raindrop.y > window.innerHeight ||
+ raindrop.x < 0
+ ) {
+ raindrop.x = Math.random() * window.innerWidth;
+ raindrop.y = -height;
+ raindrop.style.left = `${raindrop.x}px`;
+ raindrop.style.top = `${raindrop.y}px`;
+ }
+ });
+
+ requestAnimationFrame(updateRaindrops);
+}
+
+updateRaindrops();
diff --git a/assets/js/snow.js b/assets/js/snow.js
new file mode 100644
index 0000000..4d3e755
--- /dev/null
+++ b/assets/js/snow.js
@@ -0,0 +1,95 @@
+const snowContainer = document.createElement("div");
+snowContainer.style.position = "fixed";
+snowContainer.style.top = "0";
+snowContainer.style.left = "0";
+snowContainer.style.width = "100vw";
+snowContainer.style.height = "100vh";
+snowContainer.style.pointerEvents = "none";
+document.body.appendChild(snowContainer);
+
+const maxSnowflakes = 60;
+const snowflakes = [];
+const mouse = { x: -100, y: -100 };
+
+document.addEventListener("mousemove", (e) => {
+ mouse.x = e.clientX;
+ mouse.y = e.clientY;
+});
+
+const createSnowflake = () => {
+ if (snowflakes.length >= maxSnowflakes) {
+ const oldestSnowflake = snowflakes.shift();
+ snowContainer.removeChild(oldestSnowflake);
+ }
+
+ const snowflake = document.createElement("div");
+ snowflake.classList.add("snowflake");
+ snowflake.style.position = "absolute";
+ const size = Math.random() * 3 + 2;
+ snowflake.style.width = `${size}px`;
+ snowflake.style.height = `${size}px`;
+ snowflake.style.background = "white";
+ snowflake.style.borderRadius = "50%";
+ snowflake.style.opacity = Math.random();
+
+ snowflake.x = Math.random() * window.innerWidth;
+ snowflake.y = -size;
+ snowflake.speed = Math.random() * 3 + 2;
+ snowflake.directionX = (Math.random() - 0.5) * 0.5;
+ snowflake.directionY = Math.random() * 0.5 + 0.5;
+
+ snowflake.style.left = `${snowflake.x}px`;
+ snowflake.style.top = `${snowflake.y}px`;
+
+ snowflakes.push(snowflake);
+ snowContainer.appendChild(snowflake);
+};
+
+setInterval(createSnowflake, 80);
+
+function updateSnowflakes() {
+ snowflakes.forEach((snowflake, index) => {
+ const size = Number.parseFloat(snowflake.style.width);
+ const centerX = snowflake.x + size / 2;
+ const centerY = snowflake.y + size / 2;
+
+ const dx = centerX - mouse.x;
+ const dy = centerY - mouse.y;
+ const distance = Math.sqrt(dx * dx + dy * dy);
+
+ if (distance < 30) {
+ snowflake.directionX += (dx / distance) * 0.02;
+ snowflake.directionY += (dy / distance) * 0.02;
+ } else {
+ snowflake.directionX += (Math.random() - 0.5) * 0.01;
+ snowflake.directionY += (Math.random() - 0.5) * 0.01;
+ }
+
+ snowflake.x += snowflake.directionX * snowflake.speed;
+ snowflake.y += snowflake.directionY * snowflake.speed;
+
+ snowflake.style.left = `${snowflake.x}px`;
+ snowflake.style.top = `${snowflake.y}px`;
+
+ if (snowflake.y > window.innerHeight) {
+ snowContainer.removeChild(snowflake);
+ snowflakes.splice(index, 1);
+ return;
+ }
+
+ if (
+ snowflake.x > window.innerWidth ||
+ snowflake.y > window.innerHeight ||
+ snowflake.x < 0
+ ) {
+ snowflake.x = Math.random() * window.innerWidth;
+ snowflake.y = -size;
+ snowflake.style.left = `${snowflake.x}px`;
+ snowflake.style.top = `${snowflake.y}px`;
+ }
+ });
+
+ requestAnimationFrame(updateSnowflakes);
+}
+
+updateSnowflakes();
diff --git a/assets/js/stars.js b/assets/js/stars.js
new file mode 100644
index 0000000..6fff4eb
--- /dev/null
+++ b/assets/js/stars.js
@@ -0,0 +1,63 @@
+const container = document.createElement("div");
+container.style.position = "fixed";
+container.style.top = "0";
+container.style.left = "0";
+container.style.width = "100vw";
+container.style.height = "100vh";
+container.style.pointerEvents = "none";
+container.style.overflow = "hidden";
+container.style.zIndex = "9999";
+document.body.appendChild(container);
+
+for (let i = 0; i < 60; i++) {
+ const star = document.createElement("div");
+ star.className = "star";
+ const size = Math.random() * 2 + 1;
+ star.style.width = `${size}px`;
+ star.style.height = `${size}px`;
+ star.style.opacity = Math.random();
+ star.style.top = `${Math.random() * 100}vh`;
+ star.style.left = `${Math.random() * 100}vw`;
+ star.style.animationDuration = `${Math.random() * 3 + 2}s`;
+ container.appendChild(star);
+}
+
+function createShootingStar() {
+ const star = document.createElement("div");
+ star.className = "shooting-star";
+
+ star.x = Math.random() * window.innerWidth * 0.8;
+ star.y = Math.random() * window.innerHeight * 0.3;
+ const angle = (Math.random() * Math.PI) / 6 + Math.PI / 8;
+ const speed = 10;
+ const totalFrames = 60;
+ let frame = 0;
+
+ const deg = angle * (180 / Math.PI);
+ star.style.left = `${star.x}px`;
+ star.style.top = `${star.y}px`;
+ star.style.transform = `rotate(${deg}deg)`;
+
+ container.appendChild(star);
+
+ function animate() {
+ star.x += Math.cos(angle) * speed;
+ star.y += Math.sin(angle) * speed;
+ star.style.left = `${star.x}px`;
+ star.style.top = `${star.y}px`;
+ star.style.opacity = `${1 - frame / totalFrames}`;
+
+ frame++;
+ if (frame < totalFrames) {
+ requestAnimationFrame(animate);
+ } else if (star.parentNode === container) {
+ container.removeChild(star);
+ }
+ }
+
+ animate();
+}
+
+setInterval(() => {
+ if (Math.random() < 0.3) createShootingStar();
+}, 1000);