Compare commits
No commits in common. "91119c877454dde1c30e33f5b19477d62f76f350" and "69e9d63be792f54d2ae72b3c8c4a6251e6f0e974" have entirely different histories.
91119c8774
...
69e9d63be7
16 changed files with 200 additions and 5160 deletions
46
.gitignore
vendored
46
.gitignore
vendored
|
|
@ -1,4 +1,42 @@
|
|||
/.astro
|
||||
/.direnv
|
||||
dist/
|
||||
result*
|
||||
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
||||
#
|
||||
# If you find yourself ignoring temporary files generated by your text editor
|
||||
# or operating system, you probably want to add a global ignore instead:
|
||||
# git config --global core.excludesfile '~/.gitignore_global'
|
||||
|
||||
# Ignore bundler config.
|
||||
/.bundle
|
||||
|
||||
# Ignore all environment files (except templates).
|
||||
/.env*
|
||||
!/.env*.erb
|
||||
|
||||
# Ignore all logfiles and tempfiles.
|
||||
/log/*
|
||||
/tmp/*
|
||||
!/log/.keep
|
||||
!/tmp/.keep
|
||||
|
||||
# Ignore pidfiles, but keep the directory.
|
||||
/tmp/pids/*
|
||||
!/tmp/pids/
|
||||
!/tmp/pids/.keep
|
||||
|
||||
# Ignore storage (uploaded files in development and any SQLite databases).
|
||||
/storage/*
|
||||
!/storage/.keep
|
||||
/tmp/storage/*
|
||||
!/tmp/storage/
|
||||
!/tmp/storage/.keep
|
||||
|
||||
/public/assets
|
||||
|
||||
# Ignore master key for decrypting credentials and more.
|
||||
/config/master.key
|
||||
|
||||
# JetBrains can you not
|
||||
.idea/*
|
||||
/tmp
|
||||
|
||||
# VScode can you not
|
||||
.vscode/*
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Build output
|
||||
dist/
|
||||
|
||||
# Generated types
|
||||
.astro/
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Debugging
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Things handled by other linters
|
||||
*.md
|
||||
*.yaml
|
||||
*.yml
|
||||
*.json
|
||||
!.prettierrc
|
||||
!.package.json
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 100,
|
||||
"plugins": []
|
||||
}
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
@font-face {
|
||||
font-family: "FiraCode";
|
||||
src: url("/assets/FiraCode-Regular.woff2") format("woff2");
|
||||
}
|
||||
|
||||
:root {
|
||||
--background: #11111b;
|
||||
--foreground: #cdd6f4;
|
||||
--links: #89b4fa;
|
||||
--font-fira-code: 'Fira Code', monospace;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
html, body {
|
||||
height: 98%;
|
||||
}
|
||||
|
||||
|
|
@ -22,7 +25,7 @@ body {
|
|||
|
||||
body,
|
||||
pre {
|
||||
font-family: var(--font-fira-code);
|
||||
font-family: "FiraCode", monospace;
|
||||
}
|
||||
|
||||
a {
|
||||
|
|
@ -46,7 +49,7 @@ li {
|
|||
}
|
||||
|
||||
li:before {
|
||||
content: '-';
|
||||
content: "-";
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +70,7 @@ pre {
|
|||
grid-template-rows: 1fr;
|
||||
grid-column-gap: 0px;
|
||||
grid-row-gap: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.section {
|
||||
min-width: 20em;
|
||||
|
|
@ -87,35 +90,11 @@ ul.members li:before {
|
|||
}
|
||||
|
||||
ul.members li.error {
|
||||
color: lightcoral;
|
||||
}
|
||||
|
||||
ul.members li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
ul.members li a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.member-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.member-icon.owner {
|
||||
color: #f9e2af;
|
||||
}
|
||||
|
||||
.member-icon.admin {
|
||||
color: #a6e3a1;
|
||||
color: lightcoral
|
||||
}
|
||||
|
||||
ul.sidebar-links li:before {
|
||||
content: '>';
|
||||
content: ">";
|
||||
}
|
||||
|
||||
body > div {
|
||||
|
|
@ -143,7 +122,7 @@ table.services tr td:first-child {
|
|||
}
|
||||
|
||||
table.services tr td:nth-child(2)::before {
|
||||
content: '- ';
|
||||
content: "- ";
|
||||
}
|
||||
|
||||
table.services tr td:last-child {
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
import { defineConfig, fontProviders } from 'astro/config';
|
||||
import node from '@astrojs/node';
|
||||
import icon from 'astro-icon';
|
||||
|
||||
export default defineConfig({
|
||||
output: 'server',
|
||||
adapter: node({
|
||||
mode: 'standalone',
|
||||
}),
|
||||
|
||||
server: {
|
||||
host: true,
|
||||
},
|
||||
|
||||
integrations: [icon()],
|
||||
|
||||
fonts: [
|
||||
{
|
||||
name: 'Fira Code',
|
||||
cssVariable: '--font-fira-code',
|
||||
provider: fontProviders.local(),
|
||||
options: {
|
||||
variants: [
|
||||
{
|
||||
src: ['./src/assets/fonts/FiraCode-Regular.woff2'],
|
||||
weight: 'normal',
|
||||
style: 'normal',
|
||||
},
|
||||
],
|
||||
fallbacks: ['monospace'],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
146
index.php
Normal file
146
index.php
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
<?php
|
||||
|
||||
function getUsers()
|
||||
{
|
||||
$usernames = array();
|
||||
|
||||
// Get all users in /home directory
|
||||
$users = glob("/home/*");
|
||||
|
||||
foreach ($users as $user) {
|
||||
if (is_dir($user)) {
|
||||
if (file_exists("$user/public_html")) {
|
||||
$username = basename($user);
|
||||
$usernames[] = $username;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $usernames;
|
||||
}
|
||||
|
||||
// Execute the function and display results
|
||||
$usernames = getUsers();
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>frzn.dev</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||
<link rel="stylesheet" href="/assets/master.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page-container">
|
||||
<div class="header">
|
||||
<pre>
|
||||
_______ _____
|
||||
| ___|.----.-----.-----.-----.-----.| \.-----.--.--.
|
||||
| ___|​| _| _ |-- __| -__| |​| -- | -__| | |
|
||||
|___| |__| |_____|_____|_____|__|__|​|_____/|_____|\___/</pre>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div>
|
||||
<div class="section tor-notice">
|
||||
<pre>
|
||||
+----------------------------------------------------------------+
|
||||
| This site is accessible via Tor! |
|
||||
| <a href="http://frzndev32nhnla77oozhxhz5yzo4abldr6zbc4qkdh5hcyanizlxs2ad.onion/">frzndev32nhnla77oozhxhz5yzo4abldr6zbc4qkdh5hcyanizlxs2ad.onion</a> |
|
||||
+----------------------------------------------------------------+
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<p>Members</p>
|
||||
<ul class="members">
|
||||
<?php if (count($usernames) > 0) { ?>
|
||||
<?php foreach ($usernames as $username) { ?>
|
||||
<li><a href="/~<?= $username ?>">~<?= $username ?></a><?= $username == "amr" ? "*" : "" ?></li>
|
||||
<?php } ?>
|
||||
<?php } else { ?>
|
||||
<li class="error">Error fetching members!</li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
<small>
|
||||
* owner & admin
|
||||
</small>
|
||||
</div>
|
||||
<div class="section">
|
||||
<p>Services</p>
|
||||
<table class="services">
|
||||
<tr>
|
||||
<td><a href="https://git.frzn.dev">git.frzn.dev</a></td>
|
||||
<td>Forgejo<sup>1</sup></td>
|
||||
<td>A lightweight git server (which is better than Gogs)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://p.frzn.dev">p.frzn.dev</a></td>
|
||||
<td>fiche</td>
|
||||
<td>A command line pastebin (similar to termbin)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://pb.frzn.dev">pb.frzn.dev</a></td>
|
||||
<td>PrivateBin</td>
|
||||
<td>A minimalist, open source online pastebin</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://bitwarden.frzn.dev/">bitwarden.frzn.dev</a></td>
|
||||
<td>Vaultwarden<sup>1</sup></td>
|
||||
<td>A Bitwarden-compatible server written in Rust</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://snowflake.torproject.org/">Snowflake</a></td>
|
||||
<td></td>
|
||||
<td>A web proxy server</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://crypt.frzn.dev">crypt.frzn.dev</a></td>
|
||||
<td>CryptPad</td>
|
||||
<td>An open-source web-based encrypted suite of realtime collaborative editors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>frzn.dev:64738</td>
|
||||
<td>Mumble<sup>1,2</sup></td>
|
||||
<td>A VoIP server</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://irc.frozenelectronics.ca:8088/">frzn.dev:6697/6667</a></td>
|
||||
<td>ZNC<sup>1</sup></td>
|
||||
<td>An IRC bouncer</td>
|
||||
</tr>
|
||||
</table>
|
||||
<small>
|
||||
<sup>1</sup> Only available for existing members<br>
|
||||
<sup>2</sup> Not running 24/7
|
||||
</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<div class="section">
|
||||
<p>System Info</p>
|
||||
<table class="system-info">
|
||||
<tr>
|
||||
<td>time:</td>
|
||||
<td><?= gmdate("l, j F Y g:i:s A (e)") ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>os:</td>
|
||||
<td>Ubuntu GNU/Linux 24.04 (LTS)</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<hr>
|
||||
(c) frzn.dev 2018 - <?= date('Y') ?> / design and "backend" by <a href="/~roscoe">~roscoe</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
23
package.json
23
package.json
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"name": "frzn.dev",
|
||||
"type": "module",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"fmt": "prettier --write .",
|
||||
"fmt:check": "prettier --check ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^10.0.4",
|
||||
"@iconify-json/fa": "^1.2.2",
|
||||
"@iconify-json/fa-solid": "^1.2.2",
|
||||
"astro": "^6.1.5",
|
||||
"astro-icon": "^1.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.8.1"
|
||||
}
|
||||
}
|
||||
4785
pnpm-lock.yaml
generated
4785
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon/components';
|
||||
|
||||
interface Props {
|
||||
members: string[];
|
||||
}
|
||||
|
||||
const { members } = Astro.props;
|
||||
|
||||
const owner = "amr";
|
||||
const admins = ["raf", "rocoe"];
|
||||
---
|
||||
|
||||
<div class="section">
|
||||
<p>Members</p>
|
||||
<ul class="members">
|
||||
{members.length > 0 ? (
|
||||
members.map(username => (
|
||||
<li>
|
||||
<a href={`/~${username}`}>~{username}</a>
|
||||
{username === owner && (
|
||||
<Icon name="fa-solid:crown" class="member-icon owner" title="Owner" />
|
||||
)}
|
||||
{admins.includes(username) && username !== owner && (
|
||||
<Icon name="fa-solid:shield-halved" class="member-icon admin" title="Admin" />
|
||||
)}
|
||||
</li>
|
||||
))
|
||||
) : (
|
||||
<li class="error">Error fetching members!</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
interface Service {
|
||||
url: string;
|
||||
name: string;
|
||||
desc: string;
|
||||
requiresMember: boolean;
|
||||
special?: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
services: Service[];
|
||||
}
|
||||
|
||||
const { services } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="section">
|
||||
<p>Services</p>
|
||||
<table class="services">
|
||||
{services.map(service => (
|
||||
<tr>
|
||||
<td>{service.url ? <a href={service.url}>{service.special || service.url}</a> : service.special}</td>
|
||||
<td>{service.name}</td>
|
||||
<td>{service.desc}</td>
|
||||
</tr>
|
||||
))}
|
||||
</table>
|
||||
<small>
|
||||
<sup>1</sup> Only available for existing members<br>
|
||||
<sup>2</sup> Not running 24/7
|
||||
</small>
|
||||
</div>
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
---
|
||||
interface Props {
|
||||
currentDate: string;
|
||||
}
|
||||
|
||||
const { currentDate } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="section">
|
||||
<p>System Info</p>
|
||||
<table class="system-info">
|
||||
<tr>
|
||||
<td>time:</td>
|
||||
<td>{currentDate}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>os:</td>
|
||||
<td>Ubuntu GNU/Linux 24.04 (LTS)</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
|
||||
---
|
||||
|
||||
<div class="section tor-notice">
|
||||
<pre>
|
||||
+----------------------------------------------------------------+
|
||||
| This site is accessible via Tor! |
|
||||
| <a href="http://frzndev32nhnla77oozhxhz5yzo4abldr6zbc4qkdh5hcyanizlxs2ad.onion/">frzndev32nhnla77oozhxhz5yzo4abldr6zbc4qkdh5hcyanizlxs2ad.onion</a> |
|
||||
+----------------------------------------------------------------+
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
---
|
||||
import { Font } from "astro:assets";
|
||||
import "@/styles/global.css";
|
||||
|
||||
interface Props {
|
||||
title?: string;
|
||||
currentYear?: number;
|
||||
}
|
||||
|
||||
const {
|
||||
title = "frzn.dev",
|
||||
currentYear = new Date().getFullYear()
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>{title}</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||
<Font cssVariable="--font-fira-code" preload />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page-container">
|
||||
<div class="header">
|
||||
<pre>
|
||||
_______ _____
|
||||
| ___|.----.-----.-----.-----.-----.| \.-----.--.--.
|
||||
| ___|| _| _ |-- __| -__| || -- | -__| | |
|
||||
|___| |__| |_____|_____|_____|__|__||_____/|_____|\___/</pre>
|
||||
</div>
|
||||
<div class="content">
|
||||
<slot />
|
||||
</div>
|
||||
<div class="footer">
|
||||
<hr>
|
||||
(c) frzn.dev 2018 - {currentYear} / design and "backend" by <a href="/~roscoe">~roscoe</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import TorNotice from '../components/TorNotice.astro';
|
||||
import MemberList from '../components/MemberList.astro';
|
||||
import ServicesTable from '../components/ServicesTable.astro';
|
||||
import SystemInfo from '../components/SystemInfo.astro';
|
||||
import { readdirSync, statSync } from "node:fs";
|
||||
|
||||
function getUsers(): string[] {
|
||||
const usernames: string[] = [];
|
||||
|
||||
let users;
|
||||
try {
|
||||
users = readdirSync("/home", { withFileTypes: true });
|
||||
} catch {
|
||||
return usernames;
|
||||
}
|
||||
|
||||
for (const user of users) {
|
||||
if (user.isDirectory()) {
|
||||
try {
|
||||
statSync(`/home/${user.name}/public_html`);
|
||||
usernames.push(user.name);
|
||||
} catch {
|
||||
// public_html doesn't exist
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return usernames;
|
||||
}
|
||||
|
||||
const users = getUsers();
|
||||
|
||||
// Services data
|
||||
const services = [
|
||||
{ url: "https://git.frzn.dev", name: "Forgejo", desc: "A lightweight git server (which is better than Gogs)", requiresMember: true },
|
||||
{ url: "https://p.frzn.dev", name: "fiche", desc: "A command line pastebin (similar to termbin)", requiresMember: false },
|
||||
{ url: "https://pb.frzn.dev", name: "PrivateBin", desc: "A minimalist, open source online pastebin", requiresMember: false },
|
||||
{ url: "https://bitwarden.frzn.dev/", name: "Vaultwarden", desc: "A Bitwarden-compatible server written in Rust", requiresMember: true },
|
||||
{ url: "https://snowflake.torproject.org/", name: "", desc: "A web proxy server", requiresMember: false },
|
||||
{ url: "https://crypt.frzn.dev", name: "CryptPad", desc: "An open-source web-based encrypted suite of realtime collaborative editors", requiresMember: false },
|
||||
{ url: "", name: "Mumble", desc: "A VoIP server", requiresMember: true, special: "frzn.dev:64738 (Not running 24/7)" },
|
||||
{ url: "https://irc.frozenelectronics.ca:8088/", name: "ZNC", desc: "An IRC bouncer", requiresMember: true, special: "frzn.dev:6697/6667" },
|
||||
];
|
||||
|
||||
function formatDate(date: Date): string {
|
||||
const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
||||
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
const dayName = days[date.getUTCDay()];
|
||||
const day = date.getUTCDate();
|
||||
const monthName = months[date.getUTCMonth()];
|
||||
const year = date.getUTCFullYear();
|
||||
|
||||
let hours = date.getUTCHours();
|
||||
const ampm = hours >= 12 ? "PM" : "AM";
|
||||
hours = hours % 12 || 12;
|
||||
|
||||
const minutes = date.getUTCMinutes().toString().padStart(2, "0");
|
||||
const seconds = date.getUTCSeconds().toString().padStart(2, "0");
|
||||
|
||||
return `${dayName}, ${day} ${monthName} ${year} ${hours}:${minutes}:${seconds} ${ampm} (UTC)`;
|
||||
}
|
||||
|
||||
const currentDate = formatDate(new Date());
|
||||
const currentYear = new Date().getFullYear();
|
||||
---
|
||||
|
||||
<Layout title="frzn.dev" currentYear={currentYear}>
|
||||
<div>
|
||||
<TorNotice />
|
||||
<MemberList members={users} />
|
||||
<ServicesTable services={services} />
|
||||
</div>
|
||||
<div>
|
||||
<SystemInfo currentDate={currentDate} />
|
||||
</div>
|
||||
</Layout>
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"outDir": "dist/",
|
||||
"declaration": true,
|
||||
"composite": true,
|
||||
"noEmit": false,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react",
|
||||
"verbatimModuleSyntax": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "@astrojs/ts-plugin"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"include": [".astro/types.d.ts", "src/**/*.d.ts"],
|
||||
"exclude": ["dist", "result", "node_modules"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue