Compare commits
2 Commits
ea044f0875
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| a9231446a8 | |||
| cf6d8fc2c2 |
17
.gitignore
vendored
17
.gitignore
vendored
@ -1 +1,16 @@
|
|||||||
deploy_dangrubb.net.sh
|
# Deployment Script
|
||||||
|
deploy_dangrubb.net.sh
|
||||||
|
# Data files (contain current state)
|
||||||
|
server_state.txt
|
||||||
|
php/server_state.log
|
||||||
|
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*.tmp
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Local configuration
|
||||||
|
config.local.php
|
||||||
254
blog/index.html
254
blog/index.html
@ -1,254 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
|
|
||||||
<html lang="en" >
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>dangrubb.net</title>
|
|
||||||
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon">
|
|
||||||
<link rel="stylesheet" href="./style.css">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<!-- partial:index.partial.html -->
|
|
||||||
<div class="bard">
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -2em;
|
|
||||||
--glitch-hue-1: -16deg;
|
|
||||||
--glitch-x-2: 2em;
|
|
||||||
--glitch-hue-2: 13deg;
|
|
||||||
|
|
||||||
background-position: 0 -0em;
|
|
||||||
height: 5em;
|
|
||||||
animation-name: glitch-9;
|
|
||||||
animation-duration: 9000ms;
|
|
||||||
animation-delay: 2s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -1em;
|
|
||||||
--glitch-hue-1: -42deg;
|
|
||||||
--glitch-x-2: -6em;
|
|
||||||
--glitch-hue-2: -23deg;
|
|
||||||
|
|
||||||
background-position: 0 -5em;
|
|
||||||
height: 3em;
|
|
||||||
animation-name: glitch-5;
|
|
||||||
animation-duration: 5000ms;
|
|
||||||
animation-delay: 1s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -10em;
|
|
||||||
--glitch-hue-1: -42deg;
|
|
||||||
--glitch-x-2: -9em;
|
|
||||||
--glitch-hue-2: 45deg;
|
|
||||||
|
|
||||||
background-position: 0 -8em;
|
|
||||||
height: 3em;
|
|
||||||
animation-name: glitch-7;
|
|
||||||
animation-duration: 7000ms;
|
|
||||||
animation-delay: 0s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -6em;
|
|
||||||
--glitch-hue-1: -11deg;
|
|
||||||
--glitch-x-2: 2em;
|
|
||||||
--glitch-hue-2: 29deg;
|
|
||||||
|
|
||||||
background-position: 0 -11em;
|
|
||||||
height: 5em;
|
|
||||||
animation-name: glitch-8;
|
|
||||||
animation-duration: 8000ms;
|
|
||||||
animation-delay: 1s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: 0em;
|
|
||||||
--glitch-hue-1: 42deg;
|
|
||||||
--glitch-x-2: 2em;
|
|
||||||
--glitch-hue-2: -28deg;
|
|
||||||
|
|
||||||
background-position: 0 -16em;
|
|
||||||
height: 5em;
|
|
||||||
animation-name: glitch-6;
|
|
||||||
animation-duration: 6000ms;
|
|
||||||
animation-delay: 0s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -3em;
|
|
||||||
--glitch-hue-1: -45deg;
|
|
||||||
--glitch-x-2: -5em;
|
|
||||||
--glitch-hue-2: -15deg;
|
|
||||||
|
|
||||||
background-position: 0 -21em;
|
|
||||||
height: 2em;
|
|
||||||
animation-name: glitch-7;
|
|
||||||
animation-duration: 7000ms;
|
|
||||||
animation-delay: 0s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -5em;
|
|
||||||
--glitch-hue-1: 35deg;
|
|
||||||
--glitch-x-2: 9em;
|
|
||||||
--glitch-hue-2: 35deg;
|
|
||||||
|
|
||||||
background-position: 0 -23em;
|
|
||||||
height: 2em;
|
|
||||||
animation-name: glitch-6;
|
|
||||||
animation-duration: 6000ms;
|
|
||||||
animation-delay: 0s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: 10em;
|
|
||||||
--glitch-hue-1: 39deg;
|
|
||||||
--glitch-x-2: -8em;
|
|
||||||
--glitch-hue-2: 24deg;
|
|
||||||
|
|
||||||
background-position: 0 -25em;
|
|
||||||
height: 6em;
|
|
||||||
animation-name: glitch-7;
|
|
||||||
animation-duration: 7000ms;
|
|
||||||
animation-delay: 1s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -6em;
|
|
||||||
--glitch-hue-1: -46deg;
|
|
||||||
--glitch-x-2: -3em;
|
|
||||||
--glitch-hue-2: 18deg;
|
|
||||||
|
|
||||||
background-position: 0 -31em;
|
|
||||||
height: 6em;
|
|
||||||
animation-name: glitch-10;
|
|
||||||
animation-duration: 10000ms;
|
|
||||||
animation-delay: 1s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -8em;
|
|
||||||
--glitch-hue-1: -37deg;
|
|
||||||
--glitch-x-2: -6em;
|
|
||||||
--glitch-hue-2: 15deg;
|
|
||||||
|
|
||||||
background-position: 0 -37em;
|
|
||||||
height: 1em;
|
|
||||||
animation-name: glitch-9;
|
|
||||||
animation-duration: 9000ms;
|
|
||||||
animation-delay: 1s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -1em;
|
|
||||||
--glitch-hue-1: 16deg;
|
|
||||||
--glitch-x-2: 2em;
|
|
||||||
--glitch-hue-2: 25deg;
|
|
||||||
|
|
||||||
background-position: 0 -38em;
|
|
||||||
height: 2em;
|
|
||||||
animation-name: glitch-5;
|
|
||||||
animation-duration: 5000ms;
|
|
||||||
animation-delay: 1s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: 5em;
|
|
||||||
--glitch-hue-1: 32deg;
|
|
||||||
--glitch-x-2: 10em;
|
|
||||||
--glitch-hue-2: -3deg;
|
|
||||||
|
|
||||||
background-position: 0 -40em;
|
|
||||||
height: 2em;
|
|
||||||
animation-name: glitch-9;
|
|
||||||
animation-duration: 9000ms;
|
|
||||||
animation-delay: 1s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: 10em;
|
|
||||||
--glitch-hue-1: -26deg;
|
|
||||||
--glitch-x-2: 6em;
|
|
||||||
--glitch-hue-2: -45deg;
|
|
||||||
|
|
||||||
background-position: 0 -42em;
|
|
||||||
height: 4em;
|
|
||||||
animation-name: glitch-6;
|
|
||||||
animation-duration: 6000ms;
|
|
||||||
animation-delay: 1s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -7em;
|
|
||||||
--glitch-hue-1: -45deg;
|
|
||||||
--glitch-x-2: -8em;
|
|
||||||
--glitch-hue-2: 45deg;
|
|
||||||
|
|
||||||
background-position: 0 -46em;
|
|
||||||
height: 3em;
|
|
||||||
animation-name: glitch-5;
|
|
||||||
animation-duration: 5000ms;
|
|
||||||
animation-delay: 2s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: 4em;
|
|
||||||
--glitch-hue-1: 40deg;
|
|
||||||
--glitch-x-2: -8em;
|
|
||||||
--glitch-hue-2: 29deg;
|
|
||||||
|
|
||||||
background-position: 0 -49em;
|
|
||||||
height: 3em;
|
|
||||||
animation-name: glitch-6;
|
|
||||||
animation-duration: 6000ms;
|
|
||||||
animation-delay: 1s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: -4em;
|
|
||||||
--glitch-hue-1: 26deg;
|
|
||||||
--glitch-x-2: -6em;
|
|
||||||
--glitch-hue-2: -3deg;
|
|
||||||
|
|
||||||
background-position: 0 -52em;
|
|
||||||
height: 6em;
|
|
||||||
animation-name: glitch-10;
|
|
||||||
animation-duration: 10000ms;
|
|
||||||
animation-delay: 0s;
|
|
||||||
"></div>
|
|
||||||
|
|
||||||
<div class="strip" style="
|
|
||||||
--glitch-x-1: 6em;
|
|
||||||
--glitch-hue-1: 43deg;
|
|
||||||
--glitch-x-2: -1em;
|
|
||||||
--glitch-hue-2: -1deg;
|
|
||||||
|
|
||||||
background-position: 0 -58em;
|
|
||||||
height: 4em;
|
|
||||||
animation-name: glitch-8;
|
|
||||||
animation-duration: 8000ms;
|
|
||||||
animation-delay: 0s;
|
|
||||||
"></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
dangrubb.net/blog
|
|
||||||
</p>
|
|
||||||
<div></div>
|
|
||||||
<h1 style="color:white;text-align:center;">Status</h1>
|
|
||||||
<p>
|
|
||||||
dangrubb.net is fully functional and operating at 18% of potential. When Blog updates are posted, this score will increase to 19%.
|
|
||||||
</p>
|
|
||||||
<div><p></p></div>
|
|
||||||
<div class="img-container">
|
|
||||||
<img src="./src/img/CannotConnect.JPEG" alt="Cannot Connect" class="viewport-image">
|
|
||||||
</div>
|
|
||||||
<!-- partial -->
|
|
||||||
<script src="./script.js"></script>
|
|
||||||
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.0 MiB |
222
blog/style.css
222
blog/style.css
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -201,36 +201,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="resume__right">
|
<div class="resume__right">
|
||||||
|
|
||||||
<!--========== EXPERIENCE ==========-->
|
<!--========== EXPERIENCE ==========-->
|
||||||
<section class="experience section" id="experience">
|
<section class="experience section" id="experience">
|
||||||
<h2 class="section-title">Experience</h2>
|
<h2 class="section-title">Experience</h2>
|
||||||
|
|
||||||
<div class="experience__container bd-grid">
|
<div class="experience__container bd-grid">
|
||||||
<div class="experience__content">
|
<div class="experience__content">
|
||||||
<div class="experience__time">
|
|
||||||
<span class="experience__rounder"></span>
|
|
||||||
<span class="experience__line"></span>
|
|
||||||
</div>
|
|
||||||
<div class="experience__data bd-grid">
|
|
||||||
<h3 class="experience__title">IT Consultant and Support Technician</h3>
|
|
||||||
<span class="experience__company"
|
|
||||||
>2025 to Present | Blue Tech Innovation</span>
|
|
||||||
<p class="experience__description">
|
|
||||||
<ul class="experience__description">
|
|
||||||
<li>• Provide administration and internal support for company systems, including PCs, Macs, phones, printers, servers, and other related equipment.</li>
|
|
||||||
<li>• Offer end-user support for both office-based and remote employees.</li>
|
|
||||||
<li>• Ensure the health, stability, and best practices configuration of client infrastructures.</li>
|
|
||||||
<li>• Troubleshoot and resolve issues with the following technologies:</li>
|
|
||||||
<li>• Windows Server, VPN Clients, Group Policy, Folder Permissions</li>
|
|
||||||
<li>• Firewalls, Printer Servers, Office 365</li>
|
|
||||||
<li>• Mac systems, workstation and network connectivity issues</li>
|
|
||||||
<li>• Exchange Server, Microsoft Office Applications, and the latest Microsoft Office suite versions</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="experience__content">
|
|
||||||
<div class="experience__time">
|
<div class="experience__time">
|
||||||
<span class="experience__rounder"></span>
|
<span class="experience__rounder"></span>
|
||||||
<span class="experience__line"></span>
|
<span class="experience__line"></span>
|
||||||
@ -238,7 +216,8 @@
|
|||||||
<div class="experience__data bd-grid">
|
<div class="experience__data bd-grid">
|
||||||
<h3 class="experience__title">Technical Account Manager</h3>
|
<h3 class="experience__title">Technical Account Manager</h3>
|
||||||
<span class="experience__company"
|
<span class="experience__company"
|
||||||
>2023 to 2025 | ITG</span>
|
>2023 to Present | ITG</span
|
||||||
|
>
|
||||||
<p class="experience__description">
|
<p class="experience__description">
|
||||||
<ul class="experience__description">
|
<ul class="experience__description">
|
||||||
<li>• Ensure customer success with technical consulting and implementation of adaptive software and hardware.</li>
|
<li>• Ensure customer success with technical consulting and implementation of adaptive software and hardware.</li>
|
||||||
@ -253,26 +232,49 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="experience__content">
|
<div class="experience__content">
|
||||||
<div class="experience__time">
|
<div class="experience__time">
|
||||||
<span class="experience__rounder"></span>
|
<span class="experience__rounder"></span>
|
||||||
<span class="experience__line__last"></span>
|
<span class="experience__line"></span>
|
||||||
</div>
|
|
||||||
<div class="experience__data bd-grid">
|
|
||||||
<h3 class="experience__title">Field Technician</h3>
|
|
||||||
<span class="experience__company">2023 | Dell</span>
|
|
||||||
<p class="experience__description">
|
|
||||||
<ul class="experience__description">
|
|
||||||
<li>• Managed a workload of repairs in a ticketing system.</li>
|
|
||||||
<li>• Scheduled, routed, and completed all tickets in a timely manner.</li>
|
|
||||||
<li>• Found solutions to complex hardware/firmware issues and ensured systems were up and running efficiently.</li>
|
|
||||||
<li>• Maintained positive professional relations with Dell’s corporate, government, and consumer clients.</li>
|
|
||||||
<li>• Exceeded ticket completion standards handling all tickets in the Falls Church - Arlington area.</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="experience__data bd-grid">
|
||||||
|
<h3 class="experience__title">Field Technician</h3>
|
||||||
|
<span class="experience__company"
|
||||||
|
>2023 | Dell</span
|
||||||
|
>
|
||||||
|
<p class="experience__description">
|
||||||
|
<ul class="experience__description">
|
||||||
|
<li>• Managed a workload of repairs in a ticketing system.</li>
|
||||||
|
<li>• Scheduled, routed, and completed all tickets in a timely manner.</li>
|
||||||
|
<li>• Found solutions to complex hardware/firmware issues and ensured systems were up and running efficiently.</li>
|
||||||
|
<li>• Maintained positive professional relations with Dell’s corporate, government, and consumer clients.</li>
|
||||||
|
<li>• Exceeded ticket completion standards handling all tickets in the Falls Church - Arlington area.</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="experience__content">
|
||||||
|
<div class="experience__time">
|
||||||
|
<span class="experience__rounder"></span>
|
||||||
|
<!-- <span class="experience__line"></span> -->
|
||||||
|
</div>
|
||||||
|
<div class="experience__data bd-grid">
|
||||||
|
<h3 class="experience__title">
|
||||||
|
Lead Repair Technician
|
||||||
|
</h3>
|
||||||
|
<span class="experience__company"
|
||||||
|
>2021 to 2022 | T-Mobile</span
|
||||||
|
>
|
||||||
|
<p class="experience__description">
|
||||||
|
<ul class="experience__description">
|
||||||
|
<li>• Diagnosed and repaired cellphones, tablets, laptops, and other mobile devices.</li>
|
||||||
|
<li>• Efficiently diagnosed issues with customers' devices and performed all necessary repairs.</li>
|
||||||
|
<li>• Handled inventory and parts returns while ensuring systems were up to date.</li>
|
||||||
|
<li>• Exceeded SLA expectations completing 90% of repairs in under 90 minutes.</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<a href="moreInformation.html" class="more__information">
|
<a href="moreInformation.html" class="more__information">
|
||||||
<i class="bx bx-info-circle information__icon"></i>
|
<i class="bx bx-info-circle information__icon"></i>
|
||||||
More Information
|
More Information
|
||||||
@ -282,7 +284,7 @@
|
|||||||
|
|
||||||
<!--========== CERTIFICATES ==========-->
|
<!--========== CERTIFICATES ==========-->
|
||||||
<section class="certificate section" id="certificates">
|
<section class="certificate section" id="certificates">
|
||||||
<h2 class="section-title">Certifications</h2>
|
<h2 class="section-title">Certificates</h2>
|
||||||
|
|
||||||
<div class="certificate__container bd-grid">
|
<div class="certificate__container bd-grid">
|
||||||
<div class="certificate__content">
|
<div class="certificate__content">
|
||||||
|
|||||||
@ -214,37 +214,11 @@
|
|||||||
<h2 class="section-title">Experience</h2>
|
<h2 class="section-title">Experience</h2>
|
||||||
|
|
||||||
<div class="experience__container bd-grid">
|
<div class="experience__container bd-grid">
|
||||||
|
|
||||||
<div class="experience__content">
|
<div class="experience__content">
|
||||||
<div class="experience__time">
|
<div class="experience__time">
|
||||||
<span class="experience__rounder"></span>
|
<span class="experience__rounder"></span>
|
||||||
<span class="experience__line"></span>
|
<span class="experience__line"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="experience__data bd-grid">
|
|
||||||
<h3 class="experience__title">IT Consultant and Support Technician</h3>
|
|
||||||
<span class="experience__company"
|
|
||||||
>2025 to Present | Blue Tech Innovation</span>
|
|
||||||
<p class="experience__description">
|
|
||||||
<ul class="experience__description">
|
|
||||||
<li>• Provide administration and internal support for company systems, including PCs, Macs, phones, printers, servers, and other related equipment.</li>
|
|
||||||
<li>• Offer end-user support for both office-based and remote employees.</li>
|
|
||||||
<li>• Ensure the health, stability, and best practices configuration of client infrastructures.</li>
|
|
||||||
<li>• Troubleshoot and resolve issues with the following technologies:</li>
|
|
||||||
<li>• Windows Server, VPN Clients, Group Policy, Folder Permissions</li>
|
|
||||||
<li>• Firewalls, Printer Servers, Office 365</li>
|
|
||||||
<li>• Mac systems, workstation and network connectivity issues</li>
|
|
||||||
<li>• Exchange Server, Microsoft Office Applications, and the latest Microsoft Office suite versions</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="experience__content">
|
|
||||||
<div class="experience__time">
|
|
||||||
<span class="experience__rounder"></span>
|
|
||||||
<span class="experience__line"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="experience__data bd-grid">
|
<div class="experience__data bd-grid">
|
||||||
<h3 class="experience__title">Technical Account Manager</h3>
|
<h3 class="experience__title">Technical Account Manager</h3>
|
||||||
<span class="experience__company"
|
<span class="experience__company"
|
||||||
|
|||||||
@ -139,11 +139,6 @@ body.scale-cv {
|
|||||||
height: 110%;
|
height: 110%;
|
||||||
transform: translate(5px, 0);
|
transform: translate(5px, 0);
|
||||||
}
|
}
|
||||||
.scale-cv .experience__line__last {
|
|
||||||
width: 1px;
|
|
||||||
height: 100%;
|
|
||||||
transform: translate(5px, 0);
|
|
||||||
}
|
|
||||||
.scale-cv .education__data,
|
.scale-cv .education__data,
|
||||||
.scale-cv .experience__data {
|
.scale-cv .experience__data {
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
@ -415,14 +410,7 @@ img {
|
|||||||
.experience__line {
|
.experience__line {
|
||||||
display: block;
|
display: block;
|
||||||
width: 2px;
|
width: 2px;
|
||||||
height: 109%;
|
height: 110%;
|
||||||
background-color: var(--text-color-light);
|
|
||||||
transform: translate(7px, 0);
|
|
||||||
}
|
|
||||||
.experience__line__last {
|
|
||||||
display: block;
|
|
||||||
width: 2px;
|
|
||||||
height: 100%;
|
|
||||||
background-color: var(--text-color-light);
|
background-color: var(--text-color-light);
|
||||||
transform: translate(7px, 0);
|
transform: translate(7px, 0);
|
||||||
}
|
}
|
||||||
@ -442,7 +430,6 @@ img {
|
|||||||
.education__year {
|
.education__year {
|
||||||
font-size: var(--smaller-font-size);
|
font-size: var(--smaller-font-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*========== SKILLS AND LANGUAGES ==========*/
|
/*========== SKILLS AND LANGUAGES ==========*/
|
||||||
.skills__content,
|
.skills__content,
|
||||||
.languages__content {
|
.languages__content {
|
||||||
|
|||||||
122
index.html
122
index.html
@ -11,6 +11,109 @@
|
|||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!-- Add this anywhere in your HTML -->
|
||||||
|
<div id="server-control">
|
||||||
|
<span id="ascii-switch">[||==] OFF</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Position the control in top right */
|
||||||
|
#server-control {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
z-index: 1000;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ascii-switch {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Color states */
|
||||||
|
.state-off {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-on {
|
||||||
|
color: #4CAF50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-unavailable {
|
||||||
|
color: #ff6b6b;
|
||||||
|
cursor: not-allowed;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const asciiSwitch = document.getElementById('ascii-switch');
|
||||||
|
let currentState = false; // false = off, true = on
|
||||||
|
|
||||||
|
// Load current state
|
||||||
|
fetch('/php/get_state.php')
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(data => {
|
||||||
|
const state = data.trim();
|
||||||
|
currentState = (state === '1');
|
||||||
|
updateDisplay(currentState);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// If file doesn't exist or can't be reached, set to unavailable
|
||||||
|
updateDisplay('unavailable');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle clicks
|
||||||
|
asciiSwitch.addEventListener('click', function() {
|
||||||
|
if (currentState === 'unavailable') return; // Don't allow clicking if unavailable
|
||||||
|
|
||||||
|
const newState = !currentState;
|
||||||
|
const stateValue = newState ? '1' : '0';
|
||||||
|
|
||||||
|
// Optimistically update display
|
||||||
|
updateDisplay(newState);
|
||||||
|
currentState = newState;
|
||||||
|
|
||||||
|
// Send state to server
|
||||||
|
fetch('/php/update_state.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
body: 'state=' + stateValue
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(data => {
|
||||||
|
console.log('State updated:', stateValue);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error updating state:', error);
|
||||||
|
// Revert on error
|
||||||
|
currentState = !newState;
|
||||||
|
updateDisplay(currentState);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateDisplay(state) {
|
||||||
|
asciiSwitch.className = ''; // Clear existing classes
|
||||||
|
|
||||||
|
if (state === 'unavailable') {
|
||||||
|
asciiSwitch.textContent = '[????] UNAVAILABLE';
|
||||||
|
asciiSwitch.classList.add('state-unavailable');
|
||||||
|
} else if (state === true || state === '1') {
|
||||||
|
asciiSwitch.textContent = '[==||]⠀ ON';
|
||||||
|
asciiSwitch.classList.add('state-on');
|
||||||
|
} else {
|
||||||
|
asciiSwitch.textContent = '[||==] OFF';
|
||||||
|
asciiSwitch.classList.add('state-off');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<!-- partial:index.partial.html -->
|
<!-- partial:index.partial.html -->
|
||||||
<div class="bard">
|
<div class="bard">
|
||||||
<div class="strip" style="
|
<div class="strip" style="
|
||||||
@ -238,25 +341,18 @@
|
|||||||
<p>
|
<p>
|
||||||
dangrubb.net
|
dangrubb.net
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
<p class="announcement">
|
|
||||||
<a href="https://dangrubb.net/music">EXCLUSIVE: Leaked mixtape from Darnea's vault</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="debug">
|
|
||||||
<div class="code"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="links-bottom">
|
|
||||||
<a target="_parent" href="https://ai.dangrubb.net">ai</a>
|
<a target="_parent" href="https://ai.dangrubb.net">ai</a>
|
||||||
<a target="_parent" href="https://dangrubb.net/blog">blog</a>
|
<a target="_parent" href="https://ghost.dangrubb.net">blog</a>
|
||||||
<a target="_parent" href="https://pi.dangrubb.net/jellyfin">media</a>
|
<a target="_parent" href="https://pi.dangrubb.net/jellyfin">media</a>
|
||||||
<a target="_parent" href="https://pi.dangrubb.net/nextcloud">storage</a>
|
<a target="_parent" href="https://pi.dangrubb.net/nextcloud">storage</a>
|
||||||
<a target="_parent" href="https://dangrubb.net/cv">cv</a>
|
<a target="_parent" href="https://dangrubb.net/cv">cv</a>
|
||||||
<a target="_parent" href="https://pi.dangrubb.net/dangit">git</a>
|
<a target="_parent" href="https://pi.dangrubb.net/dangit">git</a></p>
|
||||||
|
<div class="debug">
|
||||||
|
<div class="code"></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- partial -->
|
<!-- partial -->
|
||||||
<script src="./script.js"></script>
|
<script src="./script.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -1,49 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>DGDN - Darnea | dangrubb.net</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon">
|
|
||||||
<link rel="stylesheet" href="../../../style.css">
|
|
||||||
<link rel="stylesheet" href="../../music.css">
|
|
||||||
<link rel="stylesheet" href="./player.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="music-container">
|
|
||||||
<div class="music-header">
|
|
||||||
<h1><a href="/music">Music</a> / <a href="/music/Darnea">Darnea</a> / DGDN</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="album-player">
|
|
||||||
<div class="album-header">
|
|
||||||
<div class="album-artwork">🔥</div>
|
|
||||||
<div class="album-info">
|
|
||||||
<h2>DGDN</h2>
|
|
||||||
<p class="artist-name">Darnea</p>
|
|
||||||
<p class="album-desc">Leaked from the vault</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="player-section">
|
|
||||||
<div id="now-playing" class="now-playing">
|
|
||||||
<p>Select a track to play</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<audio id="audio-player" controls></audio>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="tracklist">
|
|
||||||
<h3>Tracklist</h3>
|
|
||||||
<ol id="tracks-list"></ol>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="music-footer">
|
|
||||||
<p><a href="/music/Darnea">← back to artist</a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="./player.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,139 +0,0 @@
|
|||||||
/* Album Player */
|
|
||||||
|
|
||||||
.album-player {
|
|
||||||
margin: 40px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.album-header {
|
|
||||||
display: flex;
|
|
||||||
gap: 30px;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
padding: 30px;
|
|
||||||
background: rgba(107, 225, 233, 0.05);
|
|
||||||
border-radius: 8px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.album-artwork {
|
|
||||||
font-size: 5rem;
|
|
||||||
min-width: 150px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.album-info h2 {
|
|
||||||
margin: 0 0 5px 0;
|
|
||||||
font-size: 2rem;
|
|
||||||
color: #9d9aa4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.album-info .artist-name {
|
|
||||||
margin: 0 0 5px 0;
|
|
||||||
color: #6be1e9;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.album-info .album-desc {
|
|
||||||
margin: 0;
|
|
||||||
color: #6be1e9;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now Playing */
|
|
||||||
.now-playing {
|
|
||||||
text-align: center;
|
|
||||||
padding: 20px;
|
|
||||||
background: rgba(107, 225, 233, 0.1);
|
|
||||||
border: 1px solid rgba(107, 225, 233, 0.3);
|
|
||||||
border-radius: 6px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
min-height: 60px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.now-playing p {
|
|
||||||
margin: 0;
|
|
||||||
color: #9d9aa4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.now-playing.playing p {
|
|
||||||
color: #6be1e9;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Audio Player */
|
|
||||||
#audio-player {
|
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
accent-color: #6be1e9;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tracklist */
|
|
||||||
.tracklist {
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tracklist h3 {
|
|
||||||
margin: 0 0 20px 0;
|
|
||||||
font-size: 1.3rem;
|
|
||||||
color: #9d9aa4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tracklist ol {
|
|
||||||
list-style-position: inside;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tracklist li {
|
|
||||||
padding: 12px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
background: rgba(157, 154, 164, 0.05);
|
|
||||||
border: 1px solid rgba(107, 225, 233, 0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
color: #9d9aa4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tracklist li:hover {
|
|
||||||
background: rgba(107, 225, 233, 0.1);
|
|
||||||
border-color: rgba(107, 225, 233, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tracklist li.active {
|
|
||||||
background: rgba(107, 225, 233, 0.2);
|
|
||||||
border-color: #6be1e9;
|
|
||||||
color: #6be1e9;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-duration {
|
|
||||||
float: right;
|
|
||||||
color: #6be1e9;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.album-header {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 15px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.album-artwork {
|
|
||||||
font-size: 3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.album-info h2 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tracklist li {
|
|
||||||
padding: 10px;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
// Album player for DGDN
|
|
||||||
|
|
||||||
const tracks = [
|
|
||||||
{ title: "Dan Beat (bonus)", filename: "Dan Beat (bonus).flac" },
|
|
||||||
{ title: "Neigh V3", filename: "Neigh V3.flac" },
|
|
||||||
{ title: "On Ice", filename: "On Ice.flac" },
|
|
||||||
{ title: "Otish", filename: "Otish.flac" },
|
|
||||||
{ title: "Scan V2", filename: "Scan V2.flac" },
|
|
||||||
{ title: "balance v2", filename: "balance v2.flac" },
|
|
||||||
{ title: "eh ee uhn V2", filename: "eh ee uhn V2.flac" },
|
|
||||||
{ title: "held v3", filename: "held v3.flac" }
|
|
||||||
];
|
|
||||||
|
|
||||||
const audioPlayer = document.getElementById('audio-player');
|
|
||||||
const tracksList = document.getElementById('tracks-list');
|
|
||||||
const nowPlaying = document.getElementById('now-playing');
|
|
||||||
|
|
||||||
let currentTrackIndex = 0;
|
|
||||||
|
|
||||||
// Build tracklist
|
|
||||||
function initTracklist() {
|
|
||||||
tracks.forEach((track, index) => {
|
|
||||||
const li = document.createElement('li');
|
|
||||||
li.textContent = track.title;
|
|
||||||
li.dataset.index = index;
|
|
||||||
li.addEventListener('click', () => playTrack(index));
|
|
||||||
tracksList.appendChild(li);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Play track
|
|
||||||
function playTrack(index) {
|
|
||||||
currentTrackIndex = index;
|
|
||||||
const track = tracks[index];
|
|
||||||
|
|
||||||
// Update audio source
|
|
||||||
audioPlayer.src = `/src/audio/DGDN/${track.filename}`;
|
|
||||||
audioPlayer.play();
|
|
||||||
|
|
||||||
// Update UI
|
|
||||||
updateNowPlaying(track.title);
|
|
||||||
updateActiveTrack();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update now playing display
|
|
||||||
function updateNowPlaying(title) {
|
|
||||||
nowPlaying.classList.add('playing');
|
|
||||||
nowPlaying.innerHTML = `<p>▶ Now playing: ${title}</p>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update active track in list
|
|
||||||
function updateActiveTrack() {
|
|
||||||
document.querySelectorAll('.tracklist li').forEach((li, i) => {
|
|
||||||
li.classList.toggle('active', i === currentTrackIndex);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auto-play next track when current ends
|
|
||||||
audioPlayer.addEventListener('ended', () => {
|
|
||||||
if (currentTrackIndex < tracks.length - 1) {
|
|
||||||
playTrack(currentTrackIndex + 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update active track when manually seeking/playing
|
|
||||||
audioPlayer.addEventListener('play', () => {
|
|
||||||
updateActiveTrack();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize
|
|
||||||
initTracklist();
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Darnea - dangrubb.net</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon">
|
|
||||||
<link rel="stylesheet" href="../../style.css">
|
|
||||||
<link rel="stylesheet" href="../music.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="music-container">
|
|
||||||
<div class="music-header">
|
|
||||||
<h1><a href="/music">Music</a> / Darnea</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="artist-detail">
|
|
||||||
<div class="artist-banner">🎤</div>
|
|
||||||
<h2>Darnea</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="albums-grid">
|
|
||||||
<div class="album-card">
|
|
||||||
<div class="album-cover">🔥</div>
|
|
||||||
<h3><a href="/music/Darnea/DGDN">DGDN</a></h3>
|
|
||||||
<p class="album-meta">8 tracks</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="music-footer">
|
|
||||||
<p><a href="/music">← back to music</a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>dangrubb.net Music</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon">
|
|
||||||
<link rel="stylesheet" href="../style.css">
|
|
||||||
<link rel="stylesheet" href="./music.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="music-container">
|
|
||||||
<div class="music-header">
|
|
||||||
<h1><a href="/">dangrubb</a>.net/music</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="artists-grid">
|
|
||||||
<div class="artist-card">
|
|
||||||
<div class="artist-cover">🎤</div>
|
|
||||||
<h2><a href="/music/Darnea">Darnea</a></h2>
|
|
||||||
<p class="artist-meta">1 album</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="music-footer">
|
|
||||||
<p><a href="/">← back home</a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
152
music/music.css
152
music/music.css
@ -1,152 +0,0 @@
|
|||||||
/* Music Platform Styling */
|
|
||||||
|
|
||||||
.music-container {
|
|
||||||
max-width: 900px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 40px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-header {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 50px;
|
|
||||||
border-bottom: 2px solid rgba(107, 225, 233, 0.3);
|
|
||||||
padding-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-header h1 {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 2rem;
|
|
||||||
color: #9d9aa4;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-header h1 a {
|
|
||||||
color: #6be1e9;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-header h1 a:hover {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Artists Grid */
|
|
||||||
.artists-grid,
|
|
||||||
.albums-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
||||||
gap: 30px;
|
|
||||||
margin: 40px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-card,
|
|
||||||
.album-card {
|
|
||||||
text-align: center;
|
|
||||||
padding: 20px;
|
|
||||||
background: rgba(157, 154, 164, 0.05);
|
|
||||||
border: 1px solid rgba(107, 225, 233, 0.2);
|
|
||||||
border-radius: 8px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-card:hover,
|
|
||||||
.album-card:hover {
|
|
||||||
background: rgba(107, 225, 233, 0.1);
|
|
||||||
border-color: rgba(107, 225, 233, 0.5);
|
|
||||||
transform: translateY(-4px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-cover,
|
|
||||||
.album-cover {
|
|
||||||
font-size: 4rem;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-card h2,
|
|
||||||
.album-card h3 {
|
|
||||||
margin: 10px 0;
|
|
||||||
font-size: 1.3rem;
|
|
||||||
color: #9d9aa4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-card h2 a,
|
|
||||||
.album-card h3 a {
|
|
||||||
color: #6be1e9;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-card h2 a:hover,
|
|
||||||
.album-card h3 a:hover {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-meta,
|
|
||||||
.album-meta {
|
|
||||||
color: #6be1e9;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Artist Detail */
|
|
||||||
.artist-detail {
|
|
||||||
text-align: center;
|
|
||||||
margin: 40px 0;
|
|
||||||
padding: 40px 20px;
|
|
||||||
background: rgba(107, 225, 233, 0.05);
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-banner {
|
|
||||||
font-size: 5rem;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-detail h2 {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 2.5rem;
|
|
||||||
color: #9d9aa4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Footer */
|
|
||||||
.music-footer {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 60px;
|
|
||||||
padding-top: 20px;
|
|
||||||
border-top: 2px solid rgba(107, 225, 233, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-footer p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-footer a {
|
|
||||||
color: #6be1e9;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-footer a:hover {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.music-container {
|
|
||||||
padding: 20px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-header h1 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artists-grid,
|
|
||||||
.albums-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-banner {
|
|
||||||
font-size: 3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artist-detail h2 {
|
|
||||||
font-size: 1.8rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
45
php/get_state.php
Normal file
45
php/get_state.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: text/plain');
|
||||||
|
|
||||||
|
// Only allow GET requests
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
||||||
|
http_response_code(405);
|
||||||
|
die('Method not allowed');
|
||||||
|
}
|
||||||
|
|
||||||
|
$file_path = '../server_state.txt';
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($file_path)) {
|
||||||
|
// Return default state if file doesn't exist
|
||||||
|
echo '0';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if file is readable
|
||||||
|
if (!is_readable($file_path)) {
|
||||||
|
http_response_code(500);
|
||||||
|
die('Cannot read state file');
|
||||||
|
}
|
||||||
|
|
||||||
|
$state = file_get_contents($file_path);
|
||||||
|
|
||||||
|
// Validate the stored state
|
||||||
|
if ($state === false) {
|
||||||
|
http_response_code(500);
|
||||||
|
die('Failed to read state');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean the state (remove any whitespace)
|
||||||
|
$state = trim($state);
|
||||||
|
|
||||||
|
// Validate what we read from the file
|
||||||
|
if (!in_array($state, ['0', '1'], true)) {
|
||||||
|
// File was corrupted somehow, reset to default
|
||||||
|
file_put_contents($file_path, '0', LOCK_EX);
|
||||||
|
echo '0';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $state;
|
||||||
|
?>
|
||||||
66
php/update_state.php
Normal file
66
php/update_state.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
// Set proper headers
|
||||||
|
header('Content-Type: text/plain');
|
||||||
|
|
||||||
|
// Only allow POST requests
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
http_response_code(405);
|
||||||
|
die('Method not allowed');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strict input validation
|
||||||
|
if (!isset($_POST['state'])) {
|
||||||
|
http_response_code(400);
|
||||||
|
die('Missing state parameter');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only allow exact string matches
|
||||||
|
if (!in_array($_POST['state'], ['0', '1'], true)) {
|
||||||
|
http_response_code(400);
|
||||||
|
die('Invalid state - must be 0 or 1');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional validation - check if it's exactly one character
|
||||||
|
if (strlen($_POST['state']) !== 1) {
|
||||||
|
http_response_code(400);
|
||||||
|
die('Invalid state length');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate it's actually a digit
|
||||||
|
if (!ctype_digit($_POST['state'])) {
|
||||||
|
http_response_code(400);
|
||||||
|
die('State must be numeric');
|
||||||
|
}
|
||||||
|
|
||||||
|
$state = $_POST['state'];
|
||||||
|
|
||||||
|
// Use a safe file path outside web root
|
||||||
|
$file_path = '../server_state.txt';
|
||||||
|
|
||||||
|
// Ensure directory exists and is writable
|
||||||
|
if (!is_writable(dirname($file_path))) {
|
||||||
|
http_response_code(500);
|
||||||
|
die('Server configuration error');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write with file locking to prevent race conditions
|
||||||
|
$result = file_put_contents($file_path, $state, LOCK_EX);
|
||||||
|
|
||||||
|
if ($result === false) {
|
||||||
|
http_response_code(500);
|
||||||
|
die('Failed to write state');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the write was successful
|
||||||
|
$written_state = file_get_contents($file_path);
|
||||||
|
if ($written_state !== $state) {
|
||||||
|
http_response_code(500);
|
||||||
|
die('State verification failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional: Log the change (helpful for debugging)
|
||||||
|
$log_entry = date('Y-m-d H:i:s') . " - State changed to: {$state} - IP: {$_SERVER['REMOTE_ADDR']}\n";
|
||||||
|
error_log($log_entry, 3, '../tmp/server_state.log');
|
||||||
|
|
||||||
|
echo 'success';
|
||||||
|
?>
|
||||||
BIN
src/audio/._DGDN
BIN
src/audio/._DGDN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
61
style.css
61
style.css
@ -1,23 +1,18 @@
|
|||||||
body {
|
body {
|
||||||
background: #0d0a14;
|
background: #0d0a14;
|
||||||
padding: 20px 20px 100px 20px;
|
padding: 40px 20px;
|
||||||
font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, "DejaVu Sans Mono", monospace;
|
font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, "DejaVu Sans Mono", monospace;
|
||||||
color: #9d9aa4;
|
color: #9d9aa4;
|
||||||
position: relative;
|
|
||||||
height: 100vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bard {
|
.bard {
|
||||||
margin: 0 auto 30px;
|
margin: 0 auto 40px;
|
||||||
/* Remove fixed width in pixels */
|
/* Remove fixed width in pixels */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 65em; /* Keep the same max size for desktop */
|
max-width: 65em; /* Keep the same max size for desktop */
|
||||||
height: auto;
|
height: auto;
|
||||||
aspect-ratio: 1 / 0.95; /* Maintains the proportion of the artwork */
|
aspect-ratio: 1 / 0.95; /* Maintains the proportion of the artwork */
|
||||||
font-size: 2px;
|
font-size: 2px;
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust media queries for better scaling */
|
/* Adjust media queries for better scaling */
|
||||||
@ -153,7 +148,7 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
margin: 10px auto 0;
|
margin: 20px auto 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -161,56 +156,6 @@ p {
|
|||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.announcement {
|
|
||||||
margin: 10px auto 0;
|
|
||||||
position: relative;
|
|
||||||
max-width: 400px;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 1.3;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.announcement a {
|
|
||||||
color: #ffeb3b;
|
|
||||||
font-weight: bold;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.announcement a:hover,
|
|
||||||
.announcement a:focus {
|
|
||||||
text-decoration: underline;
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
|
||||||
|
|
||||||
.debug {
|
|
||||||
margin: 40px auto 0;
|
|
||||||
position: relative;
|
|
||||||
max-width: 800px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.links-bottom {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
padding: 20px;
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 20px;
|
|
||||||
justify-content: center;
|
|
||||||
background: linear-gradient(to top, rgba(13, 10, 20, 0.95), rgba(13, 10, 20, 0.8));
|
|
||||||
backdrop-filter: blur(4px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.links-bottom a {
|
|
||||||
color: #6be1e9;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #6be1e9;
|
color: #6be1e9;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user