Merge MVC rewrite into master (#21)

* Just commit it all

* Require auth

* crap

* Update homepage

* Block AI scrapers

* Update cache update script

* Add dummy file

* Remove unnecessary lastfm config var

* Use withQueryParameters for LastFM API

* Fix embeds

* Update example env

* Smard
This commit is contained in:
floppydiskette 2024-06-11 18:02:01 +01:00 committed by GitHub
parent a64bcc2c46
commit 0f52d80ca6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
88 changed files with 1982 additions and 1661 deletions

View file

@ -26,5 +26,3 @@ MEMCACHED_HOST=127.0.0.1
LASTFM_KEY= LASTFM_KEY=
LASTFM_USER= LASTFM_USER=
LASTFM_TOP_TRACKS=10
API_ROOT=http://127.0.0.1:3000

View file

@ -0,0 +1,15 @@
<?php
namespace App\Http\Controllers;
use App\Models\BookmarkCategory;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
class AdminBookmarksController extends Controller
{
public function show() : View {
$categories = BookmarkCategory::with('sites')->get();
return view('admin.bookmarks', compact('categories'));
}
}

View file

@ -0,0 +1,34 @@
<?php
namespace App\Http\Controllers;
use App\Models\GuestbookEntry;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
use UAParser\Parser;
class AdminGuestbookController extends Controller
{
function getGuestbookUniqueAddr(): int {
$uniqueIpsCount = DB::table('guestbook__entries')->distinct()->count('ip');
return $uniqueIpsCount;
}
function getGuestbookEntriesCount(): int {
$entryCount = DB::table('guestbook__entries')->count();
return $entryCount;
}
public function show() : View {
$guestbook_unique_addr = $this->getGuestbookUniqueAddr();
$guestbook_entry_count = $this->getGuestbookEntriesCount();
$entries = GuestbookEntry::selectEntries();
$parser = Parser::create();
return view('admin.guestbook', [
'guestbook_unique_addr' => $guestbook_unique_addr,
'guestbook_entry_count' => $guestbook_entry_count,
'entries' => $entries,
'parser' => $parser,
]);
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace App\Http\Controllers;
use App\Models\BookmarkCategory;
use App\Models\BookmarkSite;
use App\Models\GuestbookEntry;
use Exception;
use Illuminate\Http\Request;
use Illuminate\View\View;
class AdminImportController extends Controller
{
public function show() : View {
return view('admin.import');
}
public function submit(Request $request)
{
$request->validate([
'data_file' => 'required|mimes:json',
]);
$file = $request->file('data_file');
$jsonContent = file_get_contents($file->getRealPath());
$data = json_decode($jsonContent, true);
$tables = [];
foreach($data as $item) {
if ($item['type'] !== "table") continue;
$tables[$item['name']] = [
'data' => $item['data'],
'count' => count($item['data'])
];
if ($item['name'] === "guestbook__entries") {
GuestbookEntry::importGuestbookEntry($item['data']);
}
$this->import($item['data'], $item['name']);
}
return view('admin.import-success', ['tables' => $tables]);
}
/**
* Imports the given data to the specified table
*
* @param array $data The data to import
* @param string $table_name The name of the table to import to
* @return void
* @throws Exception Invalid table specified, to be replaced with custom exception
*/
public function import(array $data, string $table_name): void {
switch ($table_name) {
case 'guestbook__entries':
GuestbookEntry::importGuestbookEntry($data);
break;
case 'bookmark__categories' :
BookmarkCategory::importBookmarkCategory($data);
break;
case 'bookmark__sites':
BookmarkSite::importBookmark($data);
break;
case 'guestbook__bans':
break;
default:
// TODO: Replace with custom exception
throw new Exception("Invalid table specified ($table_name)");
}
}
}

View file

@ -0,0 +1,15 @@
<?php
namespace App\Http\Controllers;
use App\Models\BookmarkSite;
use App\Models\BookmarkCategory;
use Illuminate\View\View;
class BookmarksController extends Controller
{
public function show() : View {
$categories = BookmarkCategory::with('sites')->get();
return view('bookmarks', compact('categories'));
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\View\View;
class CalculatorsController extends Controller
{
public function show() : View {
return view('calculators');
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\View\View;
class ComputersController extends Controller
{
public function show() : View {
return view('computers');
}
}

View file

@ -2,37 +2,46 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\GuestbookEntry;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use DB; use Illuminate\Http\RedirectResponse;
use Illuminate\Contracts\View\View;
use Illuminate\Validation\ValidationException;
use UAParser\Parser;
class GuestbookController extends Controller { class GuestbookController extends Controller {
public function guestbook() { public function show(): View {
return view('pages.guestbook'); $entries = GuestbookEntry::selectEntries();
$parser = Parser::create();
return view('guestbook')
->with('entries', $entries)
->with('parser', $parser);
} }
public function guestbookPost(Request $request) { /**
* Creates a new guestbook entry
*
* @param Request $request
* @return RedirectResponse
* @throws ValidationException
*/
public function addEntry(Request $request): RedirectResponse {
$this->validate($request, [ $this->validate($request, [
'name' => 'required', 'name' => 'required',
'message' => 'required' 'message' => 'required'
]); ]);
$matching_bans = DB::select('SELECT reason FROM guestbook__bans WHERE ip_address = ?', array($request->ip()));
if (!empty($matching_bans)) {
return view('errors.guestbook-ipban')->with('reason', $matching_bans[0]->reason);
}
DB::insert(
'INSERT INTO guestbook__entries (name, timestamp, ip_address, agent, message) values (?, ?, ?, ?, ?)',
[
htmlspecialchars($request->get('name')),
time(),
$request->ip(),
$request->userAgent(),
htmlspecialchars($request->get('message'))
]
);
GuestbookEntry::insertGuestbookEntry($request);
return back()->with('success', 'Entry submitted successfully!'); return back()->with('success', 'Entry submitted successfully!');
} }
public function banIP(string $addr) {
// TODO: Add banning system
// $matching_bans = DB::select('SELECT reason FROM guestbook__bans WHERE ip_address = ?', array($request->ip()));
// if (!empty($matching_bans)) {
// return view('errors.guestbook-ipban')->with('reason', $matching_bans[0]->reason);
// }
}
} }

View file

@ -0,0 +1,32 @@
<?php
namespace App\Http\Controllers;
use Illuminate\View\View;
use DateTime;
class HomeController extends Controller
{
/**
* Returns age based on birthday date and current date (GMT)
* @return int
*/
function returnAge(): int
{
date_default_timezone_set('Europe/London');
$birthday = new DateTime("2005-06-07");
$currentDate = DateTime::createFromFormat("Y-m-d", date("Y-m-d"));
$age = $birthday->diff($currentDate);
return $age->y;
}
/**
* Shows home page
* @return View
*/
public function show() : View {
return view('home', [
'age' => $this->returnAge()
]);
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Illuminate\View\View;
class MusicController extends Controller
{
public function getCurrentTrack() {
// If it's already cached just return that
if (Cache::has('current_track')) {
return Cache::get('current_track');
}
$response = Http::withQueryParameters([
'method' => 'user.getrecenttracks',
'user' => Config::get('services.lastfm.user'),
'format' => 'json',
'nowplaying' => 'true',
'api_key' => Config::get('services.lastfm.key')
])->get('https://ws.audioscrobbler.com/2.0/');
$data = $response->json();
error_log($response->body());
$track_data = $data["recenttracks"]["track"][0];
$current_track = [
'title' => $track_data["name"],
'artist' => $track_data["artist"]["#text"],
'url' => $track_data["url"],
];
Cache::put('current_track', $current_track, now()->addSeconds(15));
return $current_track;
}
public function getTopTracks() {
// If it's already cached just return that
if (Cache::has('top_tracks')) {
return Cache::get('top_tracks');
}
$response = Http::withQueryParameters([
'method' => 'user.gettoptracks',
'user' => Config::get('services.lastfm.user'),
'format' => 'json',
'period' => '1month',
'limit' => 10,
'api_key' => Config::get('services.lastfm.key')
])->get('https://ws.audioscrobbler.com/2.0/');
$data = $response->json();
$topTracks = [];
foreach ($data["toptracks"]["track"] as $track) {
$topTracks[] = [
'title' => $track["name"],
'artist' => $track["artist"]["name"],
'url' => $track["url"],
'plays' => $track["playcount"],
];
}
Cache::put('top_tracks', $topTracks, now()->addSeconds(15));
return $topTracks;
}
public function show() : View {
return view('music')
->with('current_track', $this->getCurrentTrack())
->with('top_tracks', $this->getTopTracks());
}
}

View file

@ -16,6 +16,9 @@ class RateLimiter
*/ */
public function handle(Request $request, Closure $next): Response public function handle(Request $request, Closure $next): Response
{ {
if (auth()->check()) {
return $next($request);
}
$ipAddress = $request->ip(); $ipAddress = $request->ip();
$cacheKey = 'rate_limit_'.$ipAddress; $cacheKey = 'rate_limit_'.$ipAddress;

View file

@ -0,0 +1,36 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BookmarkCategory extends Model
{
use HasFactory;
protected $table = "bookmark__categories";
protected $fillable = ['name'];
public function sites() {
return $this->hasMany(BookmarkSite::class, 'category');
}
public static function insertBookmarkCategory(string $name) {
$newBookmarkCategory = new BookmarkCategory;
$newBookmarkCategory->name = $name;
$newBookmarkCategory->save();
}
public static function selectBookmarks(int $id) {
$bookmarks = BookmarkSite::where('category', '=', $id)->firstOrFail();
return $bookmarks;
}
public static function importBookmarkCategory(array $data) {
foreach ($data as $category) {
$newBookmarkCategory = new BookmarkCategory;
$newBookmarkCategory->name = $category['name'];
$newBookmarkCategory->priority = intval($category['priority']);
$newBookmarkCategory->save();
}
}
}

View file

@ -0,0 +1,35 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BookmarkSite extends Model {
use HasFactory;
protected $table = "bookmark__sites";
protected $fillable = ['name', 'description', 'url', 'category'];
public function category() {
return $this->belongsTo(BookmarkCategory::class, 'category');
}
public static function insertBookmark(string $name, string $url, int $category) {
$category = BookmarkCategory::where('id', $category)->firstOrFail();
$newBookmark = new BookmarkSite;
$newBookmark->name = $name;
$newBookmark->url = $url;
$newBookmark->category = $category->id;
$newBookmark->save();
}
public static function importBookmark(array $data) {
foreach ($data as $site) {
$newBookmark = new BookmarkSite;
$newBookmark->name = $site['name'];
$newBookmark->description = $site['description'];
$newBookmark->url = $site['url'];
$newBookmark->category = $site['category_id'];
$newBookmark->save();
}
}
}

View file

@ -0,0 +1,50 @@
<?php
namespace App\Models;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class GuestbookEntry extends Model
{
use HasFactory;
protected $table = "guestbook__entries";
protected $fillable = ['name', 'message'];
/**
* Creates a new guestbook entry.
*
* @param Request $request The HTTP POST request
* @return void
*/
public static function insertGuestbookEntry(Request $request) {
$newEntry = new GuestbookEntry;
$newEntry->name = htmlspecialchars($request->get('name'));
$newEntry->message = htmlspecialchars($request->get('message'));
$newEntry->ip = $request->ip();
$newEntry->agent = $request->userAgent();
$newEntry->admin = auth()->check();
$newEntry->save();
}
public static function selectEntries() {
$entries = GuestbookEntry::orderBy('created_at', 'desc')->get();
return $entries;
}
public static function importGuestbookEntry(array $data) {
foreach ($data as $entry) {
$dt = new \DateTime('@' . $entry['timestamp']);
$newEntry = new GuestbookEntry;
$newEntry->name = $entry['name'];
$newEntry->ip = $entry['ip_address'];
$newEntry->agent = $entry['agent'];
$newEntry->admin = $entry['site_owner'];
$newEntry->message = $entry['message'];
$newEntry->created_at = $dt;
$newEntry->updated_at = $dt;
$newEntry->save();
}
}
}

View file

@ -1,45 +0,0 @@
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}

View file

@ -0,0 +1,27 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class CurrentTrack extends Component
{
public $track;
/**
* Create a new component instance.
*/
public function __construct($track)
{
$this->track = $track;
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.current-track');
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class Layout extends Component
{
/**
* Create a new component instance.
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.layout');
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class Navbar extends Component
{
public $title;
/**
* Create a new component instance.
*/
public function __construct($title)
{
$this->title = $title;
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.navbar');
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class TopTracks extends Component
{
public $tracks;
/**
* Create a new component instance.
*/
public function __construct($tracks)
{
$this->tracks = $tracks;
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.top-tracks');
}
}

View file

@ -0,0 +1,29 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class Track extends Component
{
public $track;
public $count;
/**
* Create a new component instance.
*/
public function __construct($track, $count)
{
$this->track = $track;
$this->count = $count;
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.track');
}
}

BIN
auth0 Executable file

Binary file not shown.

View file

@ -13,6 +13,7 @@
"scrivo/highlight.php": "v9.18.1.10", "scrivo/highlight.php": "v9.18.1.10",
"sentry/sentry-laravel": "^4.1", "sentry/sentry-laravel": "^4.1",
"spatie/laravel-honeypot": "^4.3", "spatie/laravel-honeypot": "^4.3",
"spatie/laravel-html": "^3.4",
"ua-parser/uap-php": "^3.9.14" "ua-parser/uap-php": "^3.9.14"
}, },
"require-dev": { "require-dev": {

757
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -37,6 +37,8 @@
Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_KEY => Configuration::get(Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_KEY), Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_KEY => Configuration::get(Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_KEY),
Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_ALGORITHM => Configuration::get(Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_ALGORITHM), Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_ALGORITHM => Configuration::get(Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_ALGORITHM),
Configuration::CONFIG_PUSHED_AUTHORIZATION_REQUEST => Configuration::get(Configuration::CONFIG_PUSHED_AUTHORIZATION_REQUEST), Configuration::CONFIG_PUSHED_AUTHORIZATION_REQUEST => Configuration::get(Configuration::CONFIG_PUSHED_AUTHORIZATION_REQUEST),
Configuration::CONFIG_BACKCHANNEL_LOGOUT_CACHE => Configuration::get(Configuration::CONFIG_BACKCHANNEL_LOGOUT_CACHE),
Configuration::CONFIG_BACKCHANNEL_LOGOUT_EXPIRES => Configuration::get(Configuration::CONFIG_BACKCHANNEL_LOGOUT_EXPIRES),
], ],
'api' => [ 'api' => [
@ -53,4 +55,13 @@
Configuration::CONFIG_TRANSIENT_STORAGE_ID => Configuration::get(Configuration::CONFIG_TRANSIENT_STORAGE_ID), Configuration::CONFIG_TRANSIENT_STORAGE_ID => Configuration::get(Configuration::CONFIG_TRANSIENT_STORAGE_ID),
], ],
], ],
'routes' => [
Configuration::CONFIG_ROUTE_INDEX => Configuration::get(Configuration::CONFIG_ROUTE_INDEX, '/'),
Configuration::CONFIG_ROUTE_CALLBACK => Configuration::get(Configuration::CONFIG_ROUTE_CALLBACK, '/callback'),
Configuration::CONFIG_ROUTE_LOGIN => Configuration::get(Configuration::CONFIG_ROUTE_LOGIN, '/login'),
Configuration::CONFIG_ROUTE_AFTER_LOGIN => Configuration::get(Configuration::CONFIG_ROUTE_AFTER_LOGIN, '/'),
Configuration::CONFIG_ROUTE_LOGOUT => Configuration::get(Configuration::CONFIG_ROUTE_LOGOUT, '/logout'),
Configuration::CONFIG_ROUTE_AFTER_LOGOUT => Configuration::get(Configuration::CONFIG_ROUTE_AFTER_LOGOUT, '/'),
],
]; ];

View file

@ -17,6 +17,5 @@
'lastfm' => [ 'lastfm' => [
'key' => env('LASTFM_KEY'), 'key' => env('LASTFM_KEY'),
'user' => env('LASTFM_USER'), 'user' => env('LASTFM_USER'),
'toptracks' => env('LASTFM_TOP_TRACKS')
] ]
]; ];

View file

@ -0,0 +1,23 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\BookmarkCategory>
*/
class BookmarkCategoryFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->word,
];
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\BookmarkCategory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\BookmarkSite>
*/
class BookmarkSiteFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->name,
'description' => $this->faker->sentence,
'url' => $this->faker->url,
'category' => BookmarkCategory::factory(),
];
}
}

View file

@ -1,29 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('guestbook__bans', function (Blueprint $table) {
$table->increments('id');
$table->string('ip_address', 40);
$table->string('reason', 50);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('guestbook__bans');
}
};

View file

@ -1,34 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// Check if table exists and is empty
if (Schema::hasTable('bookmark__categories') && DB::table('bookmark__categories')->count() == 0) {
// Insert placeholder categories
DB::table('bookmark__categories')->insert([
['name' => 'Friends\' Websites', 'priority' => 1],
['name' => 'Cool Projects', 'priority' => 2],
['name' => 'Other Cool Sites', 'priority' => 3],
['name' => 'Miscellaneous Resources', 'priority' => 4]
]);
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};

View file

@ -12,9 +12,9 @@
public function up(): void public function up(): void
{ {
Schema::create('bookmark__categories', function (Blueprint $table) { Schema::create('bookmark__categories', function (Blueprint $table) {
$table->increments('id'); $table->id();
$table->string('name'); $table->string('name');
$table->float('priority'); $table->unsignedBigInteger('priority')->nullable();
$table->timestamps(); $table->timestamps();
}); });
} }

View file

@ -12,13 +12,15 @@
public function up(): void public function up(): void
{ {
Schema::create('bookmark__sites', function (Blueprint $table) { Schema::create('bookmark__sites', function (Blueprint $table) {
$table->increments('id'); $table->id();
$table->string('name', 50); $table->string('name');
$table->string('description', 150); $table->text('description')->nullable();
$table->string('url', 100); $table->string('url');
$table->float('priority'); $table->unsignedBigInteger('category');
$table->integer('category_id')->unsigned(); $table->foreign('category')
$table->foreign('category_id')->references('id')->on('bookmark__categories'); ->references('id')
->on('bookmark__categories')
->onDelete('cascade');
$table->timestamps(); $table->timestamps();
}); });
} }
@ -28,6 +30,6 @@ public function up(): void
*/ */
public function down(): void public function down(): void
{ {
Schema::dropIfExists('bookmark__sites'); Schema::dropIfExists('bookmarks');
} }
}; };

View file

@ -12,13 +12,12 @@
public function up(): void public function up(): void
{ {
Schema::create('guestbook__entries', function (Blueprint $table) { Schema::create('guestbook__entries', function (Blueprint $table) {
$table->increments('id'); $table->id();
$table->string('name', 255); $table->string('name');
$table->bigInteger('timestamp'); $table->string('ip');
$table->string('ip_address', 40); $table->string('agent');
$table->string('agent', 2048)->default('Agent unavailable'); $table->longText('message');
$table->boolean('site_owner')->default(0); $table->boolean('admin');
$table->string('message', 512);
$table->timestamps(); $table->timestamps();
}); });
} }

View file

@ -0,0 +1,30 @@
<?php
namespace Database\Seeders;
use App\Models\BookmarkCategory;
use App\Models\BookmarkSite;
use Illuminate\Database\Seeder;
class BookmarkCategoriesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void {
// BookmarkCategory::factory()->count(5)->create()->each(function ($category) {
// $category->sites()->saveMany(BookmarkSite::factory()->count(3)->make());
// });
$category = new BookmarkCategory([
'name' => 'cool people',
]);
$category->save();
$site = new BookmarkSite([
'name' => 'campos',
'description' => 'Cool brazilian dude, does programming and stuff',
'url' => 'https://campos02.me/',
'category' => 1,
]);
$site->save();
}
}

View file

@ -1,22 +0,0 @@
<?php
namespace Database\Seeders;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
// \App\Models\User::factory(10)->create();
// \App\Models\User::factory()->create([
// 'name' => 'Test User',
// 'email' => 'test@example.com',
// ]);
}
}

View file

@ -111,6 +111,10 @@ .nav-wrapper {
grid-row-gap: 0; grid-row-gap: 0;
} }
.nav-wrapper div:nth-child(2) {
text-align: right;
}
.theme-selector label { .theme-selector label {
font-weight: bold; font-weight: bold;
} }
@ -226,7 +230,7 @@ table.computers td ul {
padding-left: 20px; padding-left: 20px;
} }
table.computers section-title { table.computers .section-title {
text-decoration: underline; text-decoration: underline;
font-style: italic; font-style: italic;
font-weight: bold; font-weight: bold;
@ -272,34 +276,46 @@ a {
text-decoration: underline dotted; text-decoration: underline dotted;
} }
table.gb-entry-form tr td { table.form tr td {
border: none; border: none;
} }
table.gb-entry-form tr td label { table.form tr td label {
padding-right: 5px; padding-right: 5px;
} }
table.gb-entry-form tr td span.text-danger { table.form tr td span.text-danger {
padding-left: 5px; padding-left: 5px;
color: var(--warning); color: var(--warning);
} }
table.gb-entry-form tr td textarea, input.file {
table.gb-entry-form tr td input, border: 0 !important;
table.gb-entry-form tr td button{ }
margin-bottom: 5px;
margin-left: 10px; table.form tr td textarea,
table.form tr td input,
table.form tr td button,
form.import input::file-selector-button,
form.import button {
background-color: var(--background); background-color: var(--background);
border: var(--foreground) solid 1px; border: var(--foreground) solid 1px;
} }
table.gb-entry-form tr td button { table.form label {
margin: 5px 0;
}
form.import button,
form.import input::file-selector-button,
table.form tr td button {
color: var(--foreground); color: var(--foreground);
background-color: var(--background-secondary); background-color: var(--background-secondary);
} }
table.gb-entry-form tr td button:hover { form.import button:hover,
form.import input::file-selector-button:hover,
table.form tr td button:hover {
color: var(--background); color: var(--background);
background-color: var(--foreground); background-color: var(--foreground);
} }
@ -318,7 +334,7 @@ table.gb-entry-form-container tr td ul {
margin: 0; margin: 0;
} }
table.gb-entry-form tbody tr td textarea { table.form tbody tr td textarea {
width: 210px; width: 210px;
} }
@ -490,20 +506,151 @@ #scheme-selector {
} }
.music-top10 td { .music-top10 td,
.music-top10 th {
border: none; border: none;
border-left: 1px dotted var(--foreground); border-left: 1px dotted var(--foreground);
padding: 2px 5px padding: 2px 5px
} }
.music-top10 tr:nth-child(2) td { .music-top10 tr:nth-child(1) th {
border-bottom: 1px dotted var(--foreground); border-bottom: 1px dotted var(--foreground);
} }
.music-top10 tr:nth-child(3) td { .music-top10 tr:nth-child(2) td {
padding-top: 5px; padding-top: 5px;
} }
.music-top10 td:first-child { .music-top10 td:first-child,
.music-top10 th:first-child {
border: none; border: none;
} }
.music-top10 tr th:first-child {
text-align: right;
}
.music-top10 td {
white-space: nowrap; text-overflow:ellipsis; overflow: hidden;
}
.music-top10 tr td:first-child {
text-align: right;
}
.music-top10 tr td:nth-child(2),
.music-top10 tr td:nth-child(3) {
width: 50%;
}
.current-track {
width: 100%;
}
.current-track h2 {
margin: 0;
}
.info-section ul {
list-style-position: inside;
list-style-type: none;
padding-left: 0;
margin: 0;
}
.info-section ul li:before {
content: "◆ ";
}
.info-section h2 {
margin: 0;
}
.info-section p {
margin-top: 10px;
}
.contact-section {
display: grid;
grid-template-rows: 1fr 1fr;
}
.banner {
padding: 5px;
margin-top: 10px;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: 1fr;
grid-column-gap: 0;
grid-row-gap: 0;
}
.banner div:nth-child(1) {
text-align: left;
}
.banner div:nth-child(2) {
text-align: right;
}
.red-banner {
border: 3px solid var(--foreground);
background-color: var(--background-secondary);
}
.info-admin td,
.info-admin th {
border: 1px solid var(--foreground);
padding: 5px;
}
.info-admin th {
background-color: var(--background-secondary);
}
.info-admin th.blank {
border: none;
background-color: var(--background);
}
.info-admin button {
border: 1px solid var(--foreground);
background-color: var(--background);
color: var(--foreground);
}
.info-admin button:hover {
background-color: var(--foreground);
color: var(--background);
}
.info-admin button:active {
background-color: var(--background-secondary);
color: var(--foreground);
}
.info-admin-section h2 {
margin-bottom: 5px;
}
.fullwidth {
width: 100%;
}
.fullwidth td:last-child {
width: 0;
}
.guestbook-message {
text-wrap: wrap;
width: 100%;
}
td.diagonal-line {
background: linear-gradient(to right bottom, var(--background) 0%,var(--background) 49.9%,var(--foreground) 50%,var(--foreground) 51%,var(--background) 51.1%,var(--background) 100%);
}
form.import h2 {
margin: 10px 0 5px 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,31 +1,31 @@
// Define an array of strings // Define an array of strings
const neverSaid = [ const neverSaid = [
"<td style=\"width: 105px\"><strong>ASM:</strong></td> <td>The Director liked all the props we got today.</td>", "<strong>ASM:</strong> The Director liked all the props we got today.",
"<td style=\"width: 105px\"><strong>PM:</strong></td> <td>Ah ha, a revolve. Terrific.</td>", "<strong>PM:</strong> Ah ha, a revolve. Terrific.",
"<td style=\"width: 105px\"><strong>Chippie:</strong></td> <td>I don't know, let's look at the ground plan.</td>", "<strong>Chippie:</strong> I don't know, let's look at the ground plan.",
"<td style=\"width: 105px\"><strong>Set Designer:</strong></td> <td>Well, let's just have whatever is cheaper.</td>", "<strong>Set Designer:</strong> Well, let's just have whatever is cheaper.",
"<td style=\"width: 105px\"><strong>Sound:</strong></td> <td>Better turn that down a bit. We don't want to deafen them.</td>", "<strong>Sound:</strong> Better turn that down a bit. We don't want to deafen them.",
"<td style=\"width: 105px\"><strong>Director:</strong></td> <td>Sorry, my mistake.</td>", "<strong>Director:</strong> Sorry, my mistake.",
"<td style=\"width: 105px\"><strong>Electrics:</strong></td> <td>This equipment is more complicated than we need.</td>", "<strong>Electrics:</strong> This equipment is more complicated than we need.",
"<td style=\"width: 105px\"><strong>Performer:</strong></td> <td>I really think my big scene should be cut.</td>", "<strong>Performer:</strong> I really think my big scene should be cut.",
"<td style=\"width: 105px\"><strong>SM:</strong></td> <td>Can we doo that scene change again please?", "<strong>SM:</strong> Can we do that scene change again please?",
"<td style=\"width: 105px\"><strong>LX designer:</strong></td> <td>Bit more light from those big chaps at the side. Yes that's right, the ones on stalks whatever they are called.</td>", "<strong>LX designer:</strong> Bit more light from those big chaps at the side. Yes that's right, the ones on stalks whatever they are called.",
"<td style=\"width: 105px\"><strong>Electrics:</strong></td> <td>All the equipment works perfectly.</td>", "<strong>Electrics:</strong> All the equipment works perfectly.",
"<td style=\"width: 105px\"><strong>Musicians:</strong></td> <td>So what if that's the end of a call. Let's just finish this bit off.</td>", "<strong>Musicians:</strong> So what if that's the end of a call. Let's just finish this bit off.",
"<td style=\"width: 105px\"><strong>Wardrobe:</strong></td> <td>Now, when exactly is the first dress rehearsal?", "<strong>Wardrobe:</strong> Now, when exactly is the first dress rehearsal?",
"<td style=\"width: 105px\"><strong>Workshop:</strong></td> <td>I don't want anyone to know, but if you insist then yes, I admit it, I have just done an all-nighter.</td>", "<strong>Workshop:</strong> I don't want anyone to know, but if you insist then yes, I admit it, I have just done an all-nighter.",
"<td style=\"width: 105px\"><strong>Performer:</strong></td> <td>This costume is so comfortable.</td>", "<strong>Performer:</strong> This costume is so comfortable.",
"<td style=\"width: 105px\"><strong>Admin:</strong></td> <td>The level of overtime payments here are simply unacceptable. Our backstage staff deserve better.</td>", "<strong>Admin:</strong> The level of overtime payments here are simply unacceptable. Our backstage staff deserve better.",
"<td style=\"width: 105px\"><strong>Box Office:</strong></td> <td>Comps? No problem.</td>", "<strong>Box Office:</strong> Comps? No problem.",
"<td style=\"width: 105px\"><strong>Set Designer:</strong></td> <td>You're right, it looks dreadful.</td>", "<strong>Set Designer:</strong> You're right, it looks dreadful.",
"<td style=\"width: 105px\"><strong>Flyman:</strong></td> <td>No, my lips are sealed. What I may or may not have seen remains a secret.</td>", "<strong>Flyman:</strong> No, my lips are sealed. What I may or may not have seen remains a secret.",
"<td style=\"width: 105px\"><strong>Electrics:</strong></td> <td>That had nothing to do with the computer, it was my fault.</td>", "<strong>Electrics:</strong> That had nothing to do with the computer, it was my fault.",
"<td style=\"width: 105px\"><strong>Crew:</strong></td> <td>No, no, I'm sure that's our job.</td>", "<strong>Crew:</strong> No, no, I'm sure that's our job.",
"<td style=\"width: 105px\"><strong>SMgt:</strong></td> <td>Thanks, but I don't drink", "<strong>SMgt:</strong> Thanks, but I don't drink",
"<td style=\"width: 105px\"><strong>Performer:</strong></td> <td>Let me stand down here with my back to the audience.</td>", "<strong>Performer:</strong> Let me stand down here with my back to the audience.",
"<td style=\"width: 105px\"><strong>Chippie:</strong></td> <td>I can't really manage those big fast power tools myself.</td>", "<strong>Chippie:</strong> I can't really manage those big fast power tools myself.",
"<td style=\"width: 105px\"><strong>Chippie:</strong></td> <td>I prefer to use these little hand drills.</td>", "<strong>Chippie:</strong> I prefer to use these little hand drills.",
"<td style=\"width: 105px\"><strong>All:</strong></td> <td>Let's go and ask the Production Manager. He'll know.</td>" "<strong>All:</strong> Let's go and ask the Production Manager. He'll know."
] ]
// Generate a random index into the array // Generate a random index into the array

View file

@ -3,3 +3,19 @@ Disallow: /admin
Disallow: /login Disallow: /login
Disallow: /js Disallow: /js
Disallow: /css Disallow: /css
User-Agent: GPTBot
Disallow: /
User-Agent: ChatGPT-User
Disallow: /
User-Agent: Google-Extended
Disallow: /
User-Agent: CCBot
Disallow: /
User-Agent: PerplexityBot
Disallow: /

35
resources/js/neverSaid.js Normal file
View file

@ -0,0 +1,35 @@
// Define an array of strings
const neverSaid = [
"<td style=\"width: 105px\"><strong>ASM:</strong></td> <td>The Director liked all the props we got today.</td>",
"<td style=\"width: 105px\"><strong>PM:</strong></td> <td>Ah ha, a revolve. Terrific.</td>",
"<td style=\"width: 105px\"><strong>Chippie:</strong></td> <td>I don't know, let's look at the ground plan.</td>",
"<td style=\"width: 105px\"><strong>Set Designer:</strong></td> <td>Well, let's just have whatever is cheaper.</td>",
"<td style=\"width: 105px\"><strong>Sound:</strong></td> <td>Better turn that down a bit. We don't want to deafen them.</td>",
"<td style=\"width: 105px\"><strong>Director:</strong></td> <td>Sorry, my mistake.</td>",
"<td style=\"width: 105px\"><strong>Electrics:</strong></td> <td>This equipment is more complicated than we need.</td>",
"<td style=\"width: 105px\"><strong>Performer:</strong></td> <td>I really think my big scene should be cut.</td>",
"<td style=\"width: 105px\"><strong>SM:</strong></td> <td>Can we doo that scene change again please?",
"<td style=\"width: 105px\"><strong>LX designer:</strong></td> <td>Bit more light from those big chaps at the side. Yes that's right, the ones on stalks whatever they are called.</td>",
"<td style=\"width: 105px\"><strong>Electrics:</strong></td> <td>All the equipment works perfectly.</td>",
"<td style=\"width: 105px\"><strong>Musicians:</strong></td> <td>So what if that's the end of a call. Let's just finish this bit off.</td>",
"<td style=\"width: 105px\"><strong>Wardrobe:</strong></td> <td>Now, when exactly is the first dress rehearsal?",
"<td style=\"width: 105px\"><strong>Workshop:</strong></td> <td>I don't want anyone to know, but if you insist then yes, I admit it, I have just done an all-nighter.</td>",
"<td style=\"width: 105px\"><strong>Performer:</strong></td> <td>This costume is so comfortable.</td>",
"<td style=\"width: 105px\"><strong>Admin:</strong></td> <td>The level of overtime payments here are simply unacceptable. Our backstage staff deserve better.</td>",
"<td style=\"width: 105px\"><strong>Box Office:</strong></td> <td>Comps? No problem.</td>",
"<td style=\"width: 105px\"><strong>Set Designer:</strong></td> <td>You're right, it looks dreadful.</td>",
"<td style=\"width: 105px\"><strong>Flyman:</strong></td> <td>No, my lips are sealed. What I may or may not have seen remains a secret.</td>",
"<td style=\"width: 105px\"><strong>Electrics:</strong></td> <td>That had nothing to do with the computer, it was my fault.</td>",
"<td style=\"width: 105px\"><strong>Crew:</strong></td> <td>No, no, I'm sure that's our job.</td>",
"<td style=\"width: 105px\"><strong>SMgt:</strong></td> <td>Thanks, but I don't drink",
"<td style=\"width: 105px\"><strong>Performer:</strong></td> <td>Let me stand down here with my back to the audience.</td>",
"<td style=\"width: 105px\"><strong>Chippie:</strong></td> <td>I can't really manage those big fast power tools myself.</td>",
"<td style=\"width: 105px\"><strong>Chippie:</strong></td> <td>I prefer to use these little hand drills.</td>",
"<td style=\"width: 105px\"><strong>All:</strong></td> <td>Let's go and ask the Production Manager. He'll know.</td>"
]
// Generate a random index into the array
const randomIndex = Math.floor(Math.random() * neverSaid.length);
// Use document.write to output the random string
document.write(neverSaid[randomIndex]);

View file

@ -0,0 +1,70 @@
/**
* Retrieves a cookies value
* @param {string} cname Cookie name
* @returns {string} Cookie value
*/
function getCookie(cname) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for(let i = 0; i <ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1);
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
/**
* Sets/creates a cookie
* @param {string} cname Cookie name
* @param {string} cvalue Cookie value
* @param {number} exdays Cookie lifespan (days)
*/
function setCookie(cname, cvalue, exdays) {
const d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
let expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/;SameSite=Strict;Domain=.diskfloppy.me";
}
/**
* Checks if a cookie exists
* @param {string} cname Cookie name
* @returns {boolean} If cookie exists or not
*/
function cookieExists(cname) {
const cvalue = getCookie(cname);
return cvalue !== "";
}
/**
* Swaps the colorscheme
* @param {string} scheme Color scheme ID
*/
function swapScheme(scheme) {
setCookie("colorscheme", scheme, 90);
document.getElementById("css-colorscheme").href = `/css/colorschemes/${scheme}.css`;
console.log(`Set colorscheme to ${getCookie("colorscheme")}`)
}
function setSchemeSelector() {
if (!cookieExists("colorscheme")) {
setCookie("colorscheme", "catppuccin-macchiato", 90);
} else {
const scheme = getCookie("colorscheme");
const scheme_selector = document.getElementById("scheme-selector");
if (scheme && scheme_selector) {
for (let option of scheme_selector.options) {
if (option.value === scheme) {
option.selected = true;
break;
}
}
}
}
}

View file

@ -0,0 +1,28 @@
<x-layout>
<x-slot:title>Admin | Bookmarks</x-slot:title>
@foreach($categories as $category)
<div class="info-section info-admin-section">
<h2>{{ $category->name }}</h2>
<table class="info-admin">
<tr>
<th>ID</th>
<th>Name</th>
<th>Description</th>
<th>URL</th>
<th>Priority</th>
<th class="blank"></th>
</tr>
@foreach($category->sites as $site)
<tr>
<td>{{ $site->id }}</td>
<td>{{ $site->name }}</td>
<td>{{ $site->description }}</td>
<td>{{ $site->url }}</td>
<td>{{ $site->priority }}</td>
<td><a href="?action=delete&id={{ $site->id }}"><button>Delete</button></a></td>
</tr>
@endforeach
</table>
</div>
@endforeach
</x-layout>

View file

@ -0,0 +1,32 @@
<x-layout>
<x-slot:title>Admin | Guestbook</x-slot:title>
<div class="info-section">
<h2>Statistics</h2>
<hr>
<strong>Unique IP addresses:</strong> {{ $guestbook_unique_addr }}<br>
<strong>Entries:</strong> {{ $guestbook_entry_count }}
</div>
<br>
<div class="info-section">
<h2>Entries</h2>
<hr>
<table class="info-admin fullwidth">
<tr>
<th>ID</th>
<th>Name</th>
<th>IP Address</th>
<th>Message</th>
<th class="blank"></th>
</tr>
@foreach ($entries as $entry)
<tr>
<td>{{ $entry->id }}</td>
<td>{{ $entry->name }}</td>
<td>{{ $entry->ip }}</td>
<td>{{ $entry->message }}</td>
<td><a href="?action=delete&id={{ $entry->id }}"><button>Delete</button></a></td>
</tr>
@endforeach
</table>
</div>
</x-layout>

View file

@ -0,0 +1,12 @@
<x-layout>
<x-slot:title>Admin | Import</x-slot:title>
<div class="info-section">
<h2>Imported data</h2>
<hr>
<ul>
@foreach($tables as $name => $data)
<li><strong>{{ ucwords(str_replace('__', ' ', $name)) }}:</strong> {{ $data['count'] }} record(s)</li>
@endforeach
</ul>
</div>
</x-layout>

View file

@ -0,0 +1,18 @@
<x-layout>
<x-slot:title>Admin | Import</x-slot:title>
<form class="import" action="{{ route('admin.import.submit') }}" method="post" enctype="multipart/form-data">
@csrf
<label for="data_file"><strong>File:</strong></label>
<input class="file" type="file" name="data_file" accept=".json"><br>
<h2>What to import:</h2>
<input type="checkbox" name="guestbook__entries" checked>
<label for="guestbook__entries">Guestbook Entries</label><br>
<input type="checkbox" name="guestbook__bans" checked>
<label for="guestbook__bans">Guestbook Bans</label><br>
<input type="checkbox" name="guestbook__entries" checked>
<label for="bookmark__categories">Bookmark Categories</label><br>
<input type="checkbox" name="guestbook__entries" checked>
<label for="bookmark_sites">Bookmark Sites</label><br>
<button type="submit">Import</button>
</form>
</x-layout>

View file

@ -0,0 +1,18 @@
<x-layout>
<x-slot:title>Bookmarks</x-slot:title>
@foreach($categories as $category)
<table class="info-table" role="presentation">
<caption>
<h2>{{ $category->name }}</h2>
<hr>
</caption>
<tbody>
@foreach($category->sites as $site)
<tr>
<td><a href="{{ $site->url }}">{{ $site->name }}</a> - {{ $site->description }}</td>
</tr>
@endforeach
</tbody>
</table>
@endforeach
</x-layout>

View file

@ -0,0 +1,4 @@
<div class="info-table current-track">
<h2>Last/Current Track:</h2>
<a href="{{ $track["url"] }}">{{ $track["title"] }} {{ $track["artist"] }}</a><br>
</div>

View file

@ -0,0 +1,113 @@
@php // Get colorscheme from cookie and apply immediately
$colorscheme = request()->cookie('colorscheme', 'catppuccin-macchiato');
@endphp
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Global -->
<meta charset="utf-8">
<meta property="og:type" content="website">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#333333">
<link rel="stylesheet" href="{{ asset("/css/colorschemes/$colorscheme.css") }}" id="css-colorscheme"/>
<link rel="stylesheet" href="{{ asset('/css/master.css') }}"/>
<link rel="icon" type="image/png" href="{{ asset('/favicon-32x32.png') }}" sizes="32x32"/>
<link rel="icon" type="image/png" href="{{ asset('/favicon-16x16.png') }}" sizes="16x16"/>
<script src="{{ asset('/js/schemeSwap.js') }}"></script>
{!! (intval(date('n')) == 12) ? '<script src="/js/christmas/snow.js"></script>' : '' !!}
<!-- Page-specific -->
<title>{{ $title ?? 'Unknown' }} - diskfloppy.me</title>
<meta property="og:title" content="diskfloppy.me | {{ $title }}">
<meta property="og:image" content="/favicon-128x128.png">
</head>
<body onload="setSchemeSelector()">
<div class="page">
<div id="header" class="header">
@if (auth()->check())
<div class="banner red-banner">
<div>
<a href="/admin/guestbook">Guestbook</a>&nbsp;|
<a href="/admin/bookmarks">Bookmarks</a> |
<a href="/admin/import">Import</a>
</div>
<div><strong>Logged in as:</strong> {{ auth()->user()->name }} (<a href="/logout">logout</a>)</div>
</div>
@endif
<x-navbar title="{{ $title }}"/>
<hr>
</div> <!-- header -->
<div id="content" class="content" role="main">
{{ $slot }}
</div> <!-- content -->
<div id="footer" class="footer">
<hr>
<div class="footer" role="contentinfo">
<a href="https://dimden.dev/" class="button">
<img src="https://dimden.dev/services/images/88x31.gif" width="88" height="31"
class="pixel" alt="dimden.dev">
</a>&nbsp;
<a href="https://www.linux.org/" class="button">
<img src="{{ URL::asset('images/buttons/linuxnow.gif') }}" width="88"
class="pixel" height="31" alt="Linux NOW!">
</a>&nbsp;
<a href="https://www.vim.org/" class="button">
<img src="{{ URL::asset('images/buttons/vim.gif') }}" width="88" height="31"
class="pixel" alt="vim">
</a>&nbsp;
<a href="https://wave.webaim.org/" class="button">
<img src="{{ URL::asset('images/buttons/evaluatedWAVE.png') }}" width="88" height="31"
class="pixel" alt="Evaluated to be accessible!">
</a>&nbsp;
<a href="https://jigsaw.w3.org/css-validator/check/referer" class="button">
<img src="{{ URL::asset('images/buttons/vcss-blue.gif') }}" width="88" height="31"
class="pixel" alt="Valid CSS!">
</a>&nbsp;
<a href="https://wiby.me/" class="button">
<img src="{{ URL::asset('images/buttons/wiby.gif') }}" width="88" height="31"
class="pixel" alt="Wiby - Search Engine for the Classic Web">
</a><br>
This site is best viewed at 1024x768 with 16-bit color or better<br>
&copy; floppydisk 2021-{{ date('Y') }}, v{{ config('app.version') }} <a
href="https://github.com/floppydisk05/diskfloppy.me">Source</a>,
Served by {{ gethostname() }}<br>
<label for="scheme-selector">Color Scheme:</label>
<select onchange="swapScheme(this.value)" id="scheme-selector">
<optgroup label="Misc">
<option value="c64">C64</option>
</optgroup>
<optgroup label="Light">
<option value="catppuccin-latte">Catppuccin Latte</option>
<option value="gruvbox">Gruvbox</option>
<option value="man-page">Man Page</option>
<option value="papercolor-light">Papercolor Light</option>
<option value="rose-pine-dawn">Rosé Pine Dawn</option>
<option value="solarized-light">Solarized Light</option>
<option value="terminal-basic">Terminal Basic</option>
</optgroup>
<optgroup label="Dark">
<option value="catppuccin-frappe">Catppuccin Frappé</option>
<option value="catppuccin-macchiato" selected="selected">Catppuccin Macchiato</option>
<option value="catppuccin-mocha">Catppuccin Mocha</option>
<option value="gruvbox-dark">Gruvbox Dark</option>
<option value="gruvbox-material">Gruvbox Material</option>
<option value="maia">Maia</option>
<option value="mono-amber">Mono Amber</option>
<option value="mono-cyan">Mono Cyan</option>
<option value="mono-green">Mono Green</option>
<option value="mono-red">Mono Red</option>
<option value="mono-white">Mono White</option>
<option value="mono-yellow">Mono Yellow</option>
<option value="papercolor-dark">Papercolor Dark</option>
<option value="rose-pine">Rosé Pine</option>
<option value="rose-pine-moon">Rose Pine Moon</option>
<option value="shel">Shel</option>
<option value="slate">Slate</option>
<option value="solarized-dark">Solarized Dark</option>
</optgroup>
</select><br>
</div>
</div> <!-- footer -->
</div> <!-- page -->
</body>
</html>

View file

@ -0,0 +1,28 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<title>{{ $title ?? '' }}</title>
<link rel="stylesheet" href="{{ URL::asset ('css/minimal.css') }}"/>
</head>
<body>
<h1>Error {{ $code }} | <strong>{{ $message }}</strong></h1>
<hr align="left">
<p>Here, have a cat...</p>
<img src="https://http.cat/{{ $code }}" width="500"><br><br>
<p>If you believe this is a server error, contact the <a href="mailto:webmaster@diskfloppy.me">webmaster</a></p>
<br>
<h4>Diagnostic Info</h4>
<table><tr><td>
<code>
Server: &nbsp;{{ gethostname() }}<br>
Your IP: {{ Request::ip() }}<br>
Root: &nbsp;&nbsp;&nbsp;{!! url('') !!}<br>
Path: &nbsp;&nbsp;&nbsp;@if(Request::path() == "/")/@else/{{ Request::path() }}/@endif<br>
Epoch: &nbsp;&nbsp;{{ now()->timestamp }}<br>
Agent: &nbsp;&nbsp;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0 </code>
</td></tr></table>
<hr align="left">
<p>&copy; floppydisk 2021-2024</p>
</body>
</html>

View file

@ -0,0 +1,18 @@
<nav>
<h1>diskfloppy.me | <strong>{{ $title }}</strong></h1>
<div class="nav-wrapper">
<div>
<a href="/" title="Home"><img class="pixel" src="/images/icons/nav/home2.png" alt="Home" width="32" height="32"></a>
<a href="//git.diskfloppy.me/" title="cgit"><img class="pixel" src="/images/icons/nav/repo.png" alt="cgit" width="32" height="32"></a>
<a href="/pub/" title="Public Files"><img class="pixel" src="/images/icons/nav/pubfiles.png" alt="Public Files" width="32" height="32"></a>
<a href="/computers/" title="Computers"><img class="pixel" src="/images/icons/nav/computers.png" alt="Computers" width="32" height="32"></a>
<a href="/bookmarks/" title="Bookmarks"><img class="pixel" src="/images/icons/nav/bookmarks.png" alt="Bookmarks" width="32" height="32"></a>
<a href="/guestbook/" title="Guestbook"><img class="pixel" src="/images/icons/nav/guestbook.png" alt="Guestbook" width="32" height="32"></a>
<a href="//weather.diskfloppy.me/" title="Weather"><img class="pixel" src="/images/icons/nav/weather.png" alt="Weather" width="32" height="32"></a>
<a href="/music/" title="Music"><img class="pixel" src="/images/icons/nav/music.png" alt="Music" width="32" height="32"></a>&nbsp;&nbsp;
</div>
<div>
<a href="/login/" title="Admin Login"><img class="pixel" src="/images/icons/nav/admin.png" alt="Admin Login" width="32" height="32"></a>&nbsp;&nbsp;
</div>
</div>
</nav>

View file

@ -0,0 +1,16 @@
<table class="music-top10">
<caption>
<h2 style="margin-bottom: 5px">Top 10 Tracks (Last 30 days):</h2>
</caption>
<tr>
<th><b>#</b></th>
<th><b>Track</b></th>
<th><b>Artist</b></th>
<th><b>Plays</b></th>
</tr>
@php($count = 0)
@foreach ($tracks as $track)
@php($count++)
<x-track :track="$track" :count="$count"/>
@endforeach
</table>

View file

@ -0,0 +1,6 @@
<tr>
<td>{{ $count }}</td>
<td><a href="{{ $track["url"] }}">{{ $track["title"] }}</a></td>
<td>{{ $track["artist"] }}</td>
<td>{{ $track["plays"] }}</td>
</tr>

View file

@ -0,0 +1,187 @@
@extends('layouts.default')
@section('title', 'Computers')
@section('description', 'Computers I own or have owned.')
@php
// TODO: AMD whitebox, 745, D531, 1525, server, vaio, qosmio, packard bell
@endphp
@section('content')
<table class="computers">
<tr>
<th>PICTURES</th>
<th>SPECS &amp; DESCRIPTION</th>
</tr>
<tr>
<td>Random Whitebox</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>486DX2 (50MHz)</li>
<li>16MB RAM</li>
<li>280MB HDD</li>
<li>Windows NT 3.51</li>
</ul>
<p class="description">
Had been monitoring the ventilation system in a school since the late 1990s,
only stopped because the power supply internally exploded. Replaced the PSU with
a standard ATX PSU and an ATX to AT adaptor and it sprung back to life.
Motherboard is a Gigabyte GA486IM with 4 PCI slots, 4 ISA slots and 2 VLB slots.
Has two identical ISA serial/parallel/game-port cards with one acting as the
HDD/FDD controller. Also has a Realtek NIC with both RJ45 and BNC. GPU is a
Cirrus Logic card and is astoundingly shit.
</p>
</td>
</tr>
<tr>
<td>2023 MacBook Pro 14"</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>Apple M3 Pro</li>
<li>18GB RAM</li>
<li>500GB SSD</li>
<li>macOS Sonoma</li>
</ul>
</td>
</tr>
<tr>
<td>2018 MacBook Pro 13"</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>Intel i5-8259U @ 2.3GHz</li>
<li>Intel Iris Plus Graphics 655</li>
<li>8GB RAM</li>
<li>250GB SSD</li>
<li>macOS Sonoma</li>
</ul>
<p class="description">
Old main computer. Really like the touch bar, absolutely hate the butterfly
keyboard.
</p>
</td>
</tr>
<tr>
<td>2012 Lenovo ThinkPad T430</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>Intel Core i7</li>
<li>16GB RAM</li>
<li>Windows 7 Professional / NixOS</li>
</ul>
<p class="description">
One of my main computers. Has been modified to use a classic keyboard instead of
the stock Lenovo keyboard.
</p>
</td>
</tr>
<tr>
<td>2005 IBM ThinkPad X41T</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>Intel Pentium M @ 1.6GHz</li>
<li>Mobile Intel Express Chipset Family (128MB)</li>
<li>1.5GB RAM</li>
<li>40GB HDD</li>
<li>Windows XP Tablet PC Edition</li>
</ul>
</td>
</tr>
<tr>
<td>1999 Dell OptiPlex GX1</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>Intel Pentium II (Deschutes) @ 400MHz</li>
<li>ATI 3D Rage Pro (4MB)</li>
<li>639MB</li>
<li>40GB HDD</li>
<li>MS-DOS 6.22 &amp; WFW 3.10</li>
</ul>
<p class="description">
Cool computer that uses Slot 1 CPUs. After a lot of trial and error I managed to
max out the memory. Has a riser that sports 2 PCI and 2 ISA slots (one PCI and
ISA share the same slot).
</p>
</td>
</tr>
<tr>
<td>2003 IBM ThinkPad T40</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>Intel Pentium M @ 1.3GHz</li>
<li>ATI Mobility Radeon 7500 (32MB)</li>
<li>1GB RAM</li>
<li>30GB HDD</li>
<li>Windows 2000 Professional</li>
</ul>
<p class="description">
Useful laptop thanks to its parallel port. Has the ubiquitous GPU solder issues
which I &quot;&quot;&quot;&quot;fixed&quot;&quot;&quot;&quot; by jamming a CF card
between the GPU chip and the keyboard.
</p>
</td>
</tr>
<tr>
<td>2010 HP Compaq Elite 8100</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>Intel Core i7</li>
<li>16GB RAM</li>
<li>some SSD and an HDD</li>
<li>Windows Vista Ultimate (64-bit)</li>
</ul>
</td>
</tr>
<tr>
<td>2014 Mac mini</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>Intel Core i5-4278U @ 2.6GHz</li>
<li>Intel Iris Graphics</li>
<li>8GB RAM</li>
<li>1TB HDD</li>
<li>VMware ESXi 6.7.0u3</li>
</ul>
<p class="description">
Was used as my VM host for a few years. Has now been superseded by an
actual 1U rack-mount server.
</p>
</td>
</tr>
<tr>
<td>1996 Fujitsu Milan</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>Intel Pentium</li>
<li>32MB RAM</li>
<li>1215MB HDD</li>
<li>Windows 98 SE</li>
</ul>
<p class="description">
Was originally a family members' laptop. Unfortunately the HDD side of the
HDD/FDD cable ripped while I was removing the drive to clean the computer.
Still scouring eBay for a replacement cable (or more likely, an entire
parts machine).
</p>
</td>
</tr>
<tr>
<td>1999 Compaq Armada M300</td>
<td>
<span class="section-title">Quick Specs</span>
<ul>
<li>Intel Pentium III</li>
</ul>
<p class="description">
Nice little laptop. Mysteriously dead.
</p>
</td>
</tr>
</table>
@stop

View file

@ -1,5 +1,4 @@
@extends('errors::minimal') <x-minimal-error>
<x-slot:code>401</x-slot:code>
@section('title', __('Unauthorized')) <x-slot:message>Unauthorized</x-slot:message>
@section('code', '401') </x-minimal-error>
@section('message', __('Unauthorized'))

View file

@ -1,5 +1,4 @@
@extends('errors::minimal') <x-minimal-error>
<x-slot:code>402</x-slot:code>
@section('title', __('Payment Required')) <x-slot:message>Payment Required</x-slot:message>
@section('code', '402') </x-minimal-error>
@section('message', __('Payment Required'))

View file

@ -1,5 +1,4 @@
@extends('errors::minimal') <x-minimal-error>
<x-slot:code>403</x-slot:code>
@section('title', __('Forbidden')) <x-slot:message>{{__($exception->getMessage() ?: 'Forbidden')}}</x-slot:message>
@section('code', '403') </x-minimal-error>
@section('message', __($exception->getMessage() ?: 'Forbidden'))

View file

@ -1,27 +1,4 @@
@extends('errors::minimal') <x-minimal-error>
@section('content') <x-slot:code>404</x-slot:code>
<x-slot:message>Page not found!</x-slot:message>
<h1>Error 404 | <strong>Page not found!</strong></h1> </x-minimal-error>
<hr align="left">
<h2>The page <code class="addr">/{{ Request::path() }}/</code> doesn't exist! Did you mean...</h2>
<ul>
<li><a href="//www.diskfloppy.me/">diskfloppy.me</a></li>
<li><a href="//git.diskfloppy.me/">git.diskfloppy.me</a></li>
<li><a href="//weather.diskfloppy.me">weather.diskfloppy.me</a></li>
<li><a href="//dl.diskfloppy.me/">dl.diskfloppy.me</a></li>
<li><a href="https://status.diskfloppy.me">status.diskfloppy.me</a> (HTTPS Only)</li>
<li><a href="gopher://diskfloppy.me">gopher://diskfloppy.me</a></li>
</ul>
<p>Still haven't found what you were looking for or believe this is a server error? Contact the <a href="mailto:webmaster@diskfloppy.me">webmaster</a>!</p>
<br>
<h4>Diagnostic Info</h4>
<table><tr><td>
<code>
Server: &nbsp;{{ gethostname() }}<br>
Your IP: {{ Request::ip() }}<br>
Epoch: &nbsp;&nbsp;{{ now()->timestamp }}<br>
Agent: &nbsp;&nbsp;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0 </code>
</td></tr></table>
<hr align="left">
<p>&copy; floppydisk 2021-2024</p>
@endsection

View file

@ -1,5 +1,4 @@
@extends('errors::minimal') <x-minimal-error>
<x-slot:code>418</x-slot:code>
@section('title', __('I\'m a teapot')) <x-slot:message>I'm a teapot</x-slot:message>
@section('code', '418') </x-minimal-error>
@section('message', __('I\'m a teapot'))

View file

@ -1,5 +1,4 @@
@extends('errors::minimal') <x-minimal-error>
<x-slot:code>419</x-slot:code>
@section('title', __('Page Expired')) <x-slot:message>Page Expired</x-slot:message>
@section('code', '419') </x-minimal-error>
@section('message', __('Page Expired'))

View file

@ -1,5 +1,4 @@
@extends('errors::minimal') <x-minimal-error>
<x-slot:code>429</x-slot:code>
@section('title', __('Too Many Requests')) <x-slot:message>Too Many Requests</x-slot:message>
@section('code', '429') </x-minimal-error>
@section('message', __('Too Many Requests'))

View file

@ -1,5 +1,4 @@
@extends('errors::minimal') <x-minimal-error>
<x-slot:code>500</x-slot:code>
@section('title', __('Server Error')) <x-slot:message>Server Error</x-slot:message>
@section('code', '500') </x-minimal-error>
@section('message', __('Server Error'))

View file

@ -1,5 +1,4 @@
@extends('errors::minimal') <x-minimal-error>
<x-slot:code>503</x-slot:code>
@section('title', __('Service Unavailable')) <x-slot:message>Service Unavailable</x-slot:message>
@section('code', '503') </x-minimal-error>
@section('message', __('Service Unavailable'))

View file

@ -1,9 +1,8 @@
@extends('layouts.minimal') <x-minimal>
@section('title', 'Error 401: Unauthorized User!') <x-slot:title>Error 401: Unauthorized User!</x-slot:title>
@section('content')
<h1>{{ $error }}</h1> <h1>{{ $error }}</h1>
<hr> <hr>
@if(isset($description)) @if(isset($description))
<p>{{ $description }}</p> <p>{{ $description }}</p>
@endif @endif
@stop </x-minimal>

View file

@ -1,6 +1,5 @@
@extends('layouts.minimal') <x-minimal>
@section('title', 'Error 403: IP Blocked!') <x-slot:title>Error 403: IP Blocked!</x-slot:title>
@section('content')
<h1>Error 403: IP Blocked!</h1> <h1>Error 403: IP Blocked!</h1>
<hr> <hr>
<p>Your IP has been banned from submitting to the guestbook.</p> <p>Your IP has been banned from submitting to the guestbook.</p>
@ -9,4 +8,4 @@
@endif @endif
<br> <br>
Click <a href="/guestbook">here</a> to go back to the guestbook. Click <a href="/guestbook">here</a> to go back to the guestbook.
@stop </x-minimal>

View file

@ -1,10 +1,9 @@
@extends('layouts.minimal') <x-minimal>
@section('title', 'Error 429: Overclocking Detected!') <x-slot:title>Error 429: Overclocking Detected!</x-slot:title>
@section('content')
<h1>Error 429: Overclocking Detected!</h1> <h1>Error 429: Overclocking Detected!</h1>
<hr> <hr>
<p>Whoa there! Your submissions are going at warp speed.</p> <p>Whoa there! Your submissions are going at warp speed.</p>
<p>Remember you can only submit an entry <u>once every hour</u>!</p> <p>Remember you can only submit an entry <u>once every hour</u>!</p>
<br> <br>
Click <a href="/guestbook">here</a> to go back to the guestbook. Click <a href="/guestbook">here</a> to go back to the guestbook.
@stop </x-minimal>

View file

@ -1,53 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title')</title>
<!-- Styles -->
<style>
html, body {
background-color: #fff;
color: #636b6f;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-weight: 100;
height: 100vh;
margin: 0;
}
.full-height {
height: 100vh;
}
.flex-center {
align-items: center;
display: flex;
justify-content: center;
}
.position-ref {
position: relative;
}
.content {
text-align: center;
}
.title {
font-size: 36px;
padding: 20px;
}
</style>
</head>
<body>
<div class="flex-center position-ref full-height">
<div class="content">
<div class="title">
@yield('message')
</div>
</div>
</div>
</body>
</html>

View file

@ -1,21 +1,3 @@
@extends('layouts.minimal') <x-minimal>
@section('content')
<h1>Error @yield('code') | <strong>@yield('message')</strong></h1> </x-minimal>
<hr align="left">
<p>Here, have a cat...</p>
<img src="https://http.cat/@yield('code')" width="500"><br><br>
<p>If you believe this is a server error, contact the <a href="mailto:webmaster@diskfloppy.me">webmaster</a></p>
<br>
<h4>Diagnostic Info</h4>
<table><tr><td>
<code>
Server: &nbsp;{{ gethostname() }}<br>
Your IP: {{ Request::ip() }}<br>
Root: &nbsp;&nbsp;&nbsp;{!! url('') !!}<br>
Path: &nbsp;&nbsp;&nbsp;/{{ Request::path() }}/<br>
Epoch: &nbsp;&nbsp;{{ now()->timestamp }}<br>
Agent: &nbsp;&nbsp;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0 </code>
</td></tr></table>
<hr align="left">
<p>&copy; floppydisk 2021-2024</p>
@endsection

View file

@ -1,27 +1,12 @@
@extends('layouts.default') <x-layout>
@section('title', 'Guestbook') <x-slot:title>Guestbook</x-slot:title>
@section('content')
@php
use UAParser\Parser;
$parser = Parser::create();
$db_alive = true;
try {
DB::connection()->getPdo();
} catch (Exception $e) {
$db_alive = false;
}
@endphp
@if (!$db_alive)
@include('components.errors.db-error')
@else
<br>
<table class="gb-entry-form-container" role="presentation"> <table class="gb-entry-form-container" role="presentation">
<tr> <tr>
<td> <td>
<form method="POST" action="/guestbook"> <form method="POST" action="/guestbook">
@csrf @csrf
<x-honeypot/> <x-honeypot/>
<table class="gb-entry-form" role="presentation"> <table class="form" role="presentation">
<tr> <tr>
<td> <td>
<label for="name"><strong>Name:</strong></label> <label for="name"><strong>Name:</strong></label>
@ -66,13 +51,6 @@
<hr> <hr>
@php
$entries = DB::select('
SELECT name, timestamp, message, agent
FROM guestbook__entries
ORDER BY id DESC
');
@endphp
<h2>Entries <small>({{ count($entries) }} total)</small></h2> <h2>Entries <small>({{ count($entries) }} total)</small></h2>
@foreach ($entries as $entry) @foreach ($entries as $entry)
@php @php
@ -82,10 +60,10 @@
<tr> <tr>
<td> <td>
Submitted by <strong>{{ $entry->name }}</strong> Submitted by <strong>{{ $entry->name }}</strong>
on <strong>{{ gmdate('Y-m-d', $entry->timestamp) }}</strong> on <strong>{{ $entry->created_at->format('Y-m-d') }}</strong>
at <strong>{{ gmdate('h:i:s A (e)', $entry->timestamp) }}</strong> at <strong>{{ $entry->created_at->format('h:i:s A (e)') }}</strong>
<hr> <hr>
{{ $entry->message }} <span class="guestbook-message">{{ $entry->message }}</span>
<hr> <hr>
@if($entry->agent === "Agent Unavailable") @if($entry->agent === "Agent Unavailable")
<address>Agent unavailable</address> <address>Agent unavailable</address>
@ -98,5 +76,4 @@
</table> </table>
<br> <br>
@endforeach @endforeach
@endif </x-layout>
@stop

View file

@ -0,0 +1,45 @@
<x-layout>
<x-slot:title>Home</x-slot:title>
<p>Hi! This is my personal homepage on the <strong>W</strong>orld <strong>W</strong>ide <strong>W</strong>eb.</p>
<div class="info-section">
<h2>QuickFacts&trade;</h2>
<hr>
<ul>
<li>18 y/o, he/him, British</li>
<li>Theatre Technician, &quot;Web Developer&quot; and NixOS User</li>
<li>Loves ETC desks, prefers Generics to LEDs for some reason</li>
<li>Has a crippling Soundcraft addiction</li>
<li>Spends way too much time on his computer</li>
<li>Favorite games: <a href="https://steamcommunity.com/id/floppydisk05/recommended/420530/">OneShot</a>, Minecraft, Stardew Valley, N++ and Starbound</li>
<li><a href="http://wxqa.com/">CWOP</a> member</li>
</ul>
</div>
<div class="info-section">
<h2>Interests</h2>
<hr>
<ul>
<li><strong>Tech Theatre</strong> - Lighting, Stage Management, etc. (<a href="https://www.controlbooth.com/members/floppydisk.28673/">ControlBooth</a>)</li>
<li><strong>Programming</strong> - HTML, CSS, JavaScript, C#, Java, PHP, Ruby, Python (<a href="https://github.com/floppydisk05">GitHub</a>)</li>
<li><strong>Photography</strong> - <a href="https://www.flickr.com/photos/floppydisk/">Flickr</a></li>
<li><strong>Gaming</strong> - <a href="https://steamcommunity.com/id/floppydisk05/">Steam Profile</a></li>
</ul>
</div>
<div class="info-section">
<h2>Things they never said</h2>
<hr>
<p>
<script type="text/javascript" src="{{ asset("/js/neverSaid.js") }}"></script>
<noscript>Oops! You need JavaScript enabled to view this content.</noscript>
</p>
</div>
<div class="info-section">
<h2>Contact &amp; social</h2>
<hr>
<p>
<strong>E-mail:</strong> <a href="mailto:contact@diskfloppy.me">contact@diskfloppy.me</a><br>
<strong>Mastodon:</strong> <a rel="me" href="https://c.im/@floppydisk">@floppydisk@c.im</a><br>
<strong>Matrix:</strong> <a href="https://matrix.to/#/@floppydisk:arcticfoxes.net">@floppydisk:arcticfoxes.net</a>
</p>
</div>
</x-layout>

View file

@ -1,12 +0,0 @@
<nav>
<div>
<a href="/">public home</a> |
<a href="/admin">admin home</a> |
<a href="/admin/guestbook">guestbook</a>
@if (auth()->check())
| ({{ auth()->user()->name }}) <a href="/logout">logout</a>
@else
| <a href="/login">login</a>
@endif
</div>
</nav>

View file

@ -25,7 +25,7 @@ class="pixel" alt="Valid CSS!">
class="pixel" alt="Wiby - Search Engine for the Classic Web"> class="pixel" alt="Wiby - Search Engine for the Classic Web">
</a><br> </a><br>
This site is best viewed at 1024x768 with 16-bit color or better<br> This site is best viewed at 1024x768 with 16-bit color or better<br>
&copy; floppydisk 2021-{{ date('Y') }}, v{{ config('app.version') }}, <a &copy; floppydisk 2021-{{ date('Y') }}, v{{ config('app.version') }}@if(env('DEVEL'))-dev, @else, @endif<a
href="https://github.com/floppydisk05/diskfloppy.me">Source</a>, href="https://github.com/floppydisk05/diskfloppy.me">Source</a>,
Served by {{ gethostname() }}<br> Served by {{ gethostname() }}<br>
<label for="scheme-selector">Color Scheme:</label> <label for="scheme-selector">Color Scheme:</label>

View file

@ -0,0 +1,6 @@
<x-layout>
<x-slot:title>Music</x-slot:title>
<x-current-track :track="$current_track"/>
<hr>
<x-top-tracks :tracks="$top_tracks"/>
</x-layout>

View file

@ -1,33 +0,0 @@
@extends('layouts.minimal')
@section('title', 'Delete confirm')
@section('content')
<h1>Delete Confirmation</h1>
<hr>
<p>Are you sure you want to delete this entry?</p>
<h3>Entry Details:</h3>
<table class="gb-entry-details">
<tr>
<td><b>ID:</b></td>
<td>{{ $entry->id }}</td>
</tr>
<tr>
<td><b>Name:</b></td>
<td>{{ $entry->name }}</td>
</tr>
<tr>
<td><b>Date:</b></td>
<td>{{ gmdate("H:i:s - Y-m-d", $entry->timestamp) }}</td>
</tr>
<tr>
<td><b>Message:</b></td>
<td>{{ $entry->message }}</td>
</tr>
</table>
<form action="/admin/guestbook/delete" method="POST">
@csrf
<input type="hidden" name="id" value="{{ $entry->id }}">
<button type="submit">Confirm Delete</button>
</form>
@stop

View file

@ -1,32 +0,0 @@
@extends('layouts.default-admin')
@section('title', 'Guestbook')
@section('content')
@php
$entries = DB::select('
SELECT id, name, timestamp, message, ip_address
FROM guestbook__entries
ORDER BY id DESC
');
@endphp
<h1>Entries <small>({{ count($entries) }} total)</small></h1>
@foreach ($entries as $entry)
<table class="gb-admin">
<tr>
<td>
Name:&nbsp;{{ $entry->name }}<br>
IP:&nbsp;&nbsp;&nbsp;{{ $entry->ip_address }}<br>
Date:&nbsp;{{ gmdate("H:i:s - Y-m-d", $entry->timestamp) }}
</td>
<td class="gb-del">
<a href="/admin/guestbook/delete?id={{ $entry->id }}">del</a>
</td>
</tr>
<tr>
<td class="gb-message">
<br>
{{ htmlspecialchars($entry->message) }}
</td>
</tr></table>
@endforeach
@stop

View file

@ -1,9 +0,0 @@
@extends('layouts.default-admin')
@section('title', 'Page Title')
@section('description', 'Page description goes here')
@php
$user = auth()->user();
@endphp
@section('content')
<p>You are logged in as {{ $user->name }} ({{ $user->email }})</p>
@stop

View file

@ -1,52 +0,0 @@
@extends('layouts.default')
@section('title', 'Bookmarks')
@section('description', 'This is the personal homepage of floppydisk.')
@section('content')
@php
$db_alive = true;
try {
DB::connection()->getPdo();
} catch (Exception $e) {
$db_alive = false;
}
@endphp
@if (!$db_alive)
@include('components.errors.db-error')
@else
@php
$categories = DB::select('
SELECT id, name
FROM bookmark__categories
ORDER BY priority ASC
');
@endphp
@foreach ($categories as $category)
<table class="info-table" role="presentation">
<caption>
<h2>{{ $category->name }}</h2>
<hr>
</caption>
@php
$sites = DB::select(
'
SELECT name, url, description
FROM bookmark__sites
WHERE category_id = ? ORDER BY priority ASC
',
[$category->id],
);
@endphp
@foreach ($sites as $site)
<tr>
<td><a href="{{ $site->url }}">{{ $site->name }}</a>
- {{ $site->description }}</td>
</tr>
@endforeach
</table>
<br>
@endforeach
@endif
@stop

View file

@ -1,7 +0,0 @@
@extends('layouts.default')
@section('title', 'Discord Bot')
@section('description', '')
@section('content')
<p>The diskfloppy.me Discord bot blah blah blah blah blah</p>
<p>Maybe I'll finish this page later idk</p>
@stop

View file

@ -1,442 +0,0 @@
@extends('layouts.default')
@section('title', 'Computers')
@section('description', 'Computers I own or have owned.')
@section('content')
<table class="computers">
<tr>
<th>PICTURES</th>
<th>SPECS &amp; DESCRIPTION</th>
</tr>
<tr>
<td>2023 MacBook Pro 14"</td>
<td>
<section-title>Quick Specs</section-title>
<ul>
<li>Apple M3 Pro</li>
<li>18GB RAM</li>
<li>500GB SSD</li>
<li>macOS Sonoma</li>
</ul>
<p class="description">WHAT</p>
</td>
</tr>
<tr>
<td>2018 MacBook Pro 13"</td>
<td>
<section-title>Quick Specs</section-title>
<ul>
<li>Intel i5-8259U @ 2.3GHz</li>
<li>Intel Iris Plus Graphics 655</li>
<li>8GB RAM</li>
<li>250GB SSD</li>
<li>macOS Sonoma</li>
</ul>
</td>
</tr>
<tr>
<td>2012 Lenovo ThinkPad T430</td>
<td>
<section-title>Quick Specs</section-title>
<ul>
<li>Intel Core i7</li>
<li>16GB RAM</li>
<li>Windows 7 Professional</li>
</ul>
</td>
</tr>
<tr>
<td>2005 IBM ThinkPad X41T</td>
<td>
<section-title>Quick Specs</section-title>
<ul>
<li>Intel Pentium M @ 1.6GHz</li>
<li>Mobile Intel Express Chipset Family (128MB)</li>
<li>1.5GB RAM</li>
<li>40GB HDD</li>
<li>Windows XP Tablet PC Edition</li>
</ul>
</td>
</tr>
<tr>
<td>1999 Dell OptiPlex GX1</td>
<td>
<section-title>Quick Specs</section-title>
<ul>
<li>Intel Pentium II (Deschutes) @ 400MHz</li>
<li>ATI 3D Rage Pro (4MB)</li>
<li>639MB</li>
<li>40GB HDD</li>
<li>MS-DOS 6.22 &amp; WFW 3.10</li>
</ul>
</td>
</tr>
<tr>
<td>2003 IBM ThinkPad T40</td>
<td>
<section-title>Quick Specs</section-title>
<ul>
<li>Intel Pentium M @ 1.3GHz</li>
<li>ATI Mobility Radeon 7500 (32MB)</li>
<li>1GB RAM</li>
<li>30GB HDD</li>
<li>Windows 2000 Professional</li>
</ul>
</td>
</tr>
<tr>
<td>2010 HP Compaq Elite 8100</td>
<td>
<section-title>Quick Specs</section-title>
<ul>
<li>Intel Core i7</li>
<li>16GB RAM</li>
<li>some SSD and an HDD</li>
<li>Windows Vista Ultimate (64-bit)</li>
</ul>
</td>
</tr>
<tr>
<td>2014 Mac mini</td>
<td>
<section-title>Quick Specs</section-title>
<ul>
<li>Intel Core i5-4278U @ 2.6GHz</li>
<li>Intel Iris Graphics</li>
<li>8GB RAM</li>
<li>1TB HDD</li>
<li>VMware ESXi 6.7.0u3</li>
</ul>
</td>
</tr>
<tr>
<td>1996 Fujitsu Milan</td>
<td>
<section-title>Quick Specs</section-title>
<ul>
<li>Intel Pentium</li>
<li>32MB RAM</li>
<li>1215MB HDD</li>
<li>Windows 98 SE</li>
</ul>
</td>
</tr>
<tr>
<td>1999 Compaq Armada M300</td>
<td>
<section-title>Quick Specs</section-title>
<ul>
<li>Intel Pentium III</li>
</ul>
</td>
</tr>
</table>
<!--<table class="computer" role="presentation">
<tr>
<td colspan="2"><h2>Custom Build</h2><hr></td>
</tr>
<tr>
<td>
<table class="computer-specs">
<tr>
<td class="spec-title">OS:</td>
<td class="spec">NixOS 22.11 / Windows 10 Pro</td>
</tr>
<tr>
<td class="spec-title">CPU:</td>
<td class="spec">Intel i7-6700K (8-core) @ 4.0GHz</td>
</tr>
<tr>
<td class="spec-title">GPU:</td>
<td class="spec">NVidia GTX 1060 (3GB)</td>
</tr>
<tr>
<td class="spec-title">Memory:</td>
<td class="spec">64GB</td>
</tr>
<tr>
<td class="spec-title">DISK0:</td>
<td class="spec">SanDisk SSD Plus (120GB, Win10)</td>
</tr>
<tr>
<td class="spec-title">DISK1:</td>
<td class="spec">Crucial CT500MX500SSD1 (500GB, NixOS)</td>
</tr>
<tr>
<td class="spec-title">DISK2:</td>
<td class="spec">WDC WD20EZEAZ-00GGJB0 (2TB, Data)</td>
</tr>
</table>
</td>
</tr>
</table>
<table class="computer" role="presentation">
<tr>
<td colspan="2"><h2>MacBook Pro (2018)</h2><hr></td>
</tr>
<tr>
<td>
<table class="computer-specs">
<tr>
<td class="spec-title">OS:</td>
<td class="spec">macOS 12.5.1</td>
</tr>
<tr>
<td class="spec-title">Display:</td>
<td class="spec">2560x1600 (Retina)</td>
</tr>
<tr>
<td class="spec-title">CPU:</td>
<td class="spec">Intel i5-8259U (8-core) @ 2.3GHz</td>
</tr>
<tr>
<td class="spec-title">GPU:</td>
<td class="spec">Intel Iris Plus Graphics 655</td>
</tr>
<tr>
<td class="spec-title">Memory:</td>
<td class="spec">8GB</td>
</tr>
<tr>
<td class="spec-title">DISK:</td>
<td class="spec">Apple SSD AP0256M (250GB)</td>
</tr>
</table>
</td>
</tr>
</table>
<table class="computer" role="presentation">
<tr>
<td colspan="2"><h2>Lenovo ThinkPad T430 (2012)</h2><hr></td>
</tr>
<tr>
<td>
<table class="computer-specs">
<tr>
<td class="spec-title">OS:</td>
<td class="spec">NixOS 22.11 / Windows 7 Ultimate</td>
</tr>
<tr>
<td class="spec-title">CPU:</td>
<td class="spec">Intel i7-3520M (4-core) @ 3.6GHz</td>
</tr>
<tr>
<td class="spec-title">GPU:</td>
<td class="spec">Intel 3rd Gen Core processor Graphics Controllertd>
</tr>
<tr>
<td class="spec-title">Memory:</td>
<td class="spec">16GB</td>
</tr>
<tr>
<td class="spec-title">DISK0:</td>
<td class="spec">Crucial CT500MX500SSD1 (500GB, NixOS)</td>
</tr>
<tr>
<td class="spec-title">DISK1:</td>
<td class="spec">Crucial CT250MX500SSD1 (250GB, Win7)</td>
</tr>
</table>
</td>
</tr>
</table>
<table class="computer" role="presentation">
<tr>
<td colspan="2"><h2>IBM ThinkPad X41 (2005)</h2><hr></td>
</tr>
<tr>
<td>
<table class="computer-specs">
<tr>
<td class="spec-title">OS:</td>
<td class="spec">Windows XP Tablet PC Edition (2005, SP3)</td>
</tr>
<tr>
<td class="spec-title">CPU:</td>
<td class="spec">Intel Pentium M (single-core) @ 1.6GHz</td>
</tr>
<tr>
<td class="spec-title">GPU:</td>
<td class="spec">Mobile Intel 915GM/GMS 910GML Express Chipset Family (128MB)</td>
</tr>
<tr>
<td class="spec-title">Memory:</td>
<td class="spec">1.5GB</td>
</tr>
<tr>
<td class="spec-title">DISK:</td>
<td class="spec">Hitachi HTC426040G9AT00 (40GB)</td>
</tr>
</table>
</td>
</tr>
</table>
<table class="computer" role="presentation">
<tr>
<td colspan="2"><h2>Dell OptiPlex GX1 (400L+, 1999)</h2><hr></td>
</tr>
<tr>
<td>
<table class="computer-specs">
<tr>
<td class="spec-title">OS:</td>
<td class="spec">Windows 3.10 for Workgroups (DOS 6.22)</td>
</tr>
<tr>
<td class="spec-title">CPU:</td>
<td class="spec">Intel Pentium II (Deschutes) @ 400MHz</td>
</tr>
<tr>
<td class="spec-title">GPU:</td>
<td class="spec">ATI 3D Rage Pro (4MB)</td>
</tr>
<tr>
<td class="spec-title">Memory:</td>
<td class="spec">639MB</td>
</tr>
<tr>
<td class="spec-title">DISK:</td>
<td class="spec">Unknown</td>
</tr>
</table>
</td>
</tr>
</table>
<table class="computer" role="presentation">
<tr>
<td colspan="2"><h2>IBM ThinkPad T40 (2003)</h2><hr></td>
</tr>
<tr>
<td>
<table class="computer-specs">
<tr>
<td class="spec-title">OS:</td>
<td class="spec">Windows XP Pro</td>
</tr>
<tr>
<td class="spec-title">CPU:</td>
<td class="spec">Intel Pentium M (single-core) @ 1.3GHz</td>
</tr>
<tr>
<td class="spec-title">GPU:</td>
<td class="spec">ATI Mobility Radeon 7500 (32MB)</td>
</tr>
<tr>
<td class="spec-title">Memory:</td>
<td class="spec">1GB</td>
</tr>
<tr>
<td class="spec-title">DISK:</td>
<td class="spec">Fujitsu MHS2030AT (30GB)</td>
</tr>
</table>
</td>
</tr>
</table>
<table class="computer" role="presentation">
<tr>
<td colspan="2"><h2>HP Compaq Elite 8100 CMT</h2><hr></td>
</tr>
<tr>
<td>
<table class="computer-specs">
<tr>
<td class="spec-title">OS:</td>
<td class="spec">Windows Vista 64-bit</td>
</tr>
<tr>
<td class="spec-title">CPU:</td>
<td class="spec">Intel Core i7</td>
</tr>
<tr>
<td class="spec-title">GPU:</td>
<td class="spec"></td>
</tr>
<tr>
<td class="spec-title">Memory:</td>
<td class="spec">16GB</td>
</tr>
<tr>
<td class="spec-title">DISK0:</td>
<td class="spec">SanDisk SSD Plus (120GB, Win10)</td>
</tr>
<tr>
<td class="spec-title">DISK1:</td>
<td class="spec">Crucial CT500MX500SSD1 (500GB, NixOS)</td>
</tr>
</table>
</td>
</tr>
</table>
<table class="computer" role="presentation">
<tr>
<td colspan="2"><h2>Mac mini (2014)</h2><hr></td>
</tr>
<tr>
<td>
<table class="computer-specs">
<tr>
<td class="spec-title">OS:</td>
<td class="spec">VMware ESXi 6.7.0u3</td>
</tr>
<tr>
<td class="spec-title">CPU:</td>
<td class="spec">Intel i5-4278U (4-core) @ 2.6GHz</td>
</tr>
<tr>
<td class="spec-title">GPU:</td>
<td class="spec">Intel Iris Graphics</td>
</tr>
<tr>
<td class="spec-title">Memory:</td>
<td class="spec">8GB</td>
</tr>
<tr>
<td class="spec-title">DISK:</td>
<td class="spec">Apple HDD HTS541 (1TB)</td>
</tr>
</table>
</td>
</tr>
</table>
<table class="computer" role="presentation">
<tr>
<td colspan="2"><h2>Fujitsu Milan (1996)</h2><hr></td>
</tr>
<tr>
<td>
<table class="computer-specs">
<tr>
<td class="spec-title">OS:</td>
<td class="spec">Windows 98 SE</td>
</tr>
<tr>
<td class="spec-title">CPU:</td>
<td class="spec">Intel Pentium</td>
</tr>
<tr>
<td class="spec-title">Memory:</td>
<td class="spec">32MB</td>
</tr>
<tr>
<td class="spec-title">DISK:</td>
<td class="spec">IBM DPRA-21215 (1215MB)</td>
</tr>
</table>
</td>
</tr>
</table>-->
<!--<table class="computer" role="presentation">
<tr>
<td colspan="2"><h2>Compaq Armada M300</h2><hr></td>
</tr>
<tr>
<td>
<table class="computer-specs">
<tr>
<td class="spec">TBD</td>
</tr>
</table>
</td>
</tr>
</table>-->
@stop

View file

@ -1,88 +0,0 @@
@extends('layouts.default')
@section('title', 'Home')
@section('description', 'This is the personal homepage of floppydisk.')
@section('content')
<p>Hi! This is my personal homepage on the <strong>W</strong>orld <strong>W</strong>ide <strong>W</strong>eb.</p>
<table class="info-table" role="presentation">
<caption>
<h2>QuickFacts&trade;</h2>
<hr>
</caption>
<tr>
<td>&#9670; 18 y/o, he/him, British</td>
</tr>
<tr>
<td>&#9670; Theatre Technician, &quot;Web Developer&quot; and NixOS User</td>
</tr>
<tr>
<td>&#9670; Loves ETC desks, prefers Generics to LEDs for some reason</td>
</tr>
<tr>
<td>&#9670; Spends way too much time on his computer</td>
</tr>
<tr>
<td>&#9670; Favorite games: <a href="https://steamcommunity.com/id/floppydisk05/recommended/420530/">OneShot</a>, Minecraft, Stardew Valley, N++ and Starbound</td>
</tr>
<tr>
<td>&#9670; <a href="http://wxqa.com/">CWOP</a> member</td>
</tr>
</table>
<br>
<table class="info-table" role="presentation">
<caption>
<h2>Interests</h2>
<hr>
</caption>
<tr>
<td>&#9670; <b>Tech Theatre</b></td>
<td>- Lighting, Stage Management, etc. (<a href="https://www.controlbooth.com/members/floppydisk.28673/">ControlBooth</a>)</td>
</tr>
<tr>
<td>&#9670; <b>Programming</b></td>
<td>- HTML, CSS, JavaScript, C#, Java, PHP, Ruby, Python (<a href="https://github.com/floppydisk05">GitHub</a>)</td>
</tr>
<tr>
<td>&#9670; <b>Photography</b></td>
<td>- <a href="https://www.flickr.com/photos/floppydisk/">Flickr</a></td>
</tr>
<tr>
<td>&#9670; <b>Gaming</b></td>
<td>- <a href="https://steamcommunity.com/id/floppydisk05/">Steam Profile</a></td>
</tr>
</table>
<br>
<table class="info-table never-said" role="presentation">
<caption>
<h2>Things they never said</h2>
<hr>
</caption>
<tr>
<script type="text/javascript" src="/js/neverSaid.js"></script>
<noscript><td>Oops! You need JavaScript enabled to view this content.</td></noscript>
</tr>
</table>
<br>
<table class="info-table" role="presentation">
<caption>
<h2>Contact &amp; social</h2>
<hr>
</caption>
<tr>
<td><strong>E-mail:</strong></td>
<td><a href="mailto:contact@diskfloppy.me">contact@diskfloppy.me</a></td>
</tr>
<tr>
<td><strong>Mastodon:</strong></td>
<td><a rel="me" href="https://c.im/@floppydisk">@floppydisk@c.im</a></td>
</tr>
<tr>
<td><strong>Matrix:</strong></td>
<td><a href="https://matrix.to/#/@floppydisk:arcticfoxes.net">@floppydisk:arcticfoxes.net</a></td>
</tr>
</table>
@stop

View file

@ -1,66 +0,0 @@
@extends('layouts.default')
@section('title', 'Music')
@section('description', '')
@section('content')
@php
$cfg = app('config')->get('services')['lastfm'];
$api_root = app('config')->get('app')['api_root'];
$api_alive = true;
try {
$data = file_get_contents($api_root.'/lastfm/current');
} catch (Exception $e) {
$api_alive = false;
}
@endphp
@if (!$api_alive)
@include('components.errors.api-error')
@else
@php
$current_track = json_decode(file_get_contents($api_root . '/lastfm/current'));
$top_tracks = json_decode(file_get_contents($api_root . '/lastfm/top'));
$count = 0;
@endphp
<table class="info-table" role="presentation" width="100%">
<tr>
<td colspan="4">
<h2>Last/Current Track:</h2>
</td>
</tr>
<tr>
<td colspan="4">
<a href="{{ $current_track->url }}">{{ $current_track->title }} {{ $current_track->artist }}</a><br>
</td>
</tr>
</table>
<hr>
<table class="music-top10">
<tr>
<td colspan="4">
<h2 style="margin-bottom: 5px">Top {{ $cfg['toptracks'] }} Tracks (Last 7 days)</h2>
</td>
</tr>
<tr>
<td style="text-align: right"><b>#</b></td>
<td><b>Track</b></td>
<td><b>Artist</b></td>
<td><b>Plays</b></td>
</tr>
@foreach ($top_tracks as $track)
@php $count++ @endphp
@if ($count >= $cfg['toptracks']+1)
@break
@endif
<tr>
<td style="text-align: right">{{ $count }}</td>
<td style="white-space: nowrap; text-overflow:ellipsis; overflow: hidden; max-width:1px;" width="50%"><a href="{{ $track->url }}">{{ $track->title }}</a></td>
<td style="white-space: nowrap; text-overflow:ellipsis; overflow: hidden; max-width:1px;" width="50%">{{ $track->artist }}</td>
<td>{{ $track->playcount }}</td>
</tr>
@endforeach
</table>
@endif
@stop

View file

@ -1,16 +0,0 @@
<?php $categories = app('config')->get('projects'); ?>
@extends('layouts.default')
@section('title', 'Projects')
@section('description', 'My projects')
@section('content')
@foreach ($categories as $category)
<h2>{{ $category['name']}}</h2>
@foreach ($category['projects'] as $project)
<div>
<a href="{{ $project['url'] }}">{{ $project['name'] }}</a> - {{ $project['description'] }}<br>
<b>Languages:</b> {{ implode(", ", $project['languages']) }}
</div>
<br>
@endforeach
@endforeach
@stop

View file

@ -1,6 +0,0 @@
@extends('layouts.default')
@section('title', 'Page Title')
@section('description', 'Page description goes here')
@section('content')
<p>page content</p>
@stop

View file

@ -1,61 +0,0 @@
@extends('layouts.default')
@section('title', 'Weather')
@section('description', 'Data from my weather station')
@section('content')
@php
$api_root = app('config')->get('app')['api_root'];
function degreesToCompassDirection($degrees) {
$cardinalDirections = [
'N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE',
'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N'
];
return $cardinalDirections[round($degrees*16/360)];
}
$api_alive = true;
try {
$data = file_get_contents($api_root.'/weather');
} catch (Exception $e) {
$api_alive = false;
}
@endphp
@if (!$api_alive)
@include('components.errors.api-error')
@else
@php
$data = json_decode(file_get_contents($api_root.'/weather'));
$updated = gmdate('H:i Y-m-d', $data->updated);
$data = $data->current;
@endphp
<table class="info-table" role="presentation">
<caption>
<h2>Local Weather</h2>
<hr>
</caption>
<tr>
<td><b>Wind Speed:</b></td>
<td>{{ $data->wind->speed }} mph</td>
</tr>
<tr>
<td><b>Wind Direction:</b></td>
<td>{{ $data->wind->direction->degrees }}°, {{ $data->wind->direction->cardinal }}</td>
</tr>
<tr>
<td><b>Temperature:</b></td>
<td>{{ $data->temperature }}°C</td>
</tr>
<tr>
<td><b>Rain Rate:</b></td>
<td>{{ $data->rain_rate }} mm/hr</td>
</tr>
<tr>
<td><b>Humidity:</b></td>
<td>{{ $data->humidity }}%</td>
</tr>
</table>
<br>
<small><i>(Last Update: {{ $updated }})</i></small>
@endif
@stop

View file

@ -1,8 +1,15 @@
<?php <?php
use Illuminate\Support\Facades\DB; use App\Http\Controllers\AdminBookmarksController;
use App\Http\Controllers\AdminGuestbookController;
use App\Http\Controllers\AdminImportController;
use App\Http\Controllers\BookmarksController;
use App\Http\Controllers\CalculatorsController;
use App\Http\Controllers\ComputersController;
use App\Http\Controllers\GuestbookController;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\MusicController;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\View;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -15,87 +22,23 @@
| |
*/ */
Route::get('/', function () { Route::get('/', [HomeController::class, 'show']);
return View::make('pages.home'); Route::get('/bookmarks', [BookmarksController::class, 'show']);
}); Route::get('/guestbook', [GuestbookController::class, 'show']);
Route::post('/guestbook', [GuestbookController::class, 'addEntry'])
Route::get('/bookmarks', function () {
return View::make('pages.bookmarks');
});
Route::get('/projects', function () {
return View::make('pages.projects');
});
Route::get('/calculators', function () {
return View::make('pages.calculators');
});
Route::get('/computers', function () {
return View::make('pages.computers');
});
Route::get('/guestbook', 'App\Http\Controllers\GuestbookController@guestbook')
->name('guestbook');
Route::post('/guestbook', 'App\Http\Controllers\GuestbookController@guestbookpost')
->name('guestbookPost')
->middleware('rate_limit'); ->middleware('rate_limit');
Route::get('/calculators', [CalculatorsController::class, 'show']);
Route::get('/computers', [ComputersController::class, 'show']);
Route::get('/music', [MusicController::class, 'show']);
Route::get('/weather', function () { // Admin pages
return View::make('pages.weather'); Route::get('/admin/guestbook', [AdminGuestbookController::class, 'show'])
}); ->middleware('auth');
Route::get('/admin/bookmarks', [AdminBookmarksController::class, 'show'])
Route::get('/music', function () { ->middleware('auth');
return View::make('pages.music'); Route::get('/admin/import', [AdminImportController::class, 'show'])
}); ->middleware('auth');
Route::post('/admin/import', [AdminImportController::class, 'submit'])
Route::get('/bot', function () { ->name('admin.import.submit')
return View::make('pages.bot'); ->middleware('auth');
});
/* ------------------------------ Admin Routes ------------------------------ */
//Route::get('/admin', function () {
// if (!auth()->check()) {
// return View::make('errors.no-auth');
// }
// return View::make('pages.admin.index');
//});
//
//Route::get('/admin/guestbook', function () {
// if (!auth()->check()) {
// return View::make('errors.no-auth');
// }
// return View::make('pages.admin.guestbook');
//});
//
//Route::get('/admin/guestbook/delete', function () {
// if (!auth()->check()) {
// return View::make('errors.no-auth');
// }
//
// $id = request()->input('id');
// $entry = DB::table('guestbook__entries')->find($id);
//
// if ($entry) {
// // Render a confirmation view
// return View::make('pages.admin.guestbook-del-confirm', compact('entry'));
// } else {
// return View::make('errors.generic-error')
// ->with('error', "Entry not found")
// ->with('description', "The specified entry does not exist!");
// }
//});
//
//Route::post('/admin/guestbook/delete', function () {
// if (!auth()->check()) {
// return View::make('errors.no-auth');
// }
//
// $id = request()->input('id');
// DB::table('guestbook__entries')->where('id', $id)->delete();
//
// return back()->with('success', 'Entry deleted successfully!');
//});

View file

@ -2,3 +2,4 @@ php artisan config:cache
php artisan route:cache php artisan route:cache
php artisan view:cache php artisan view:cache
php artisan event:cache php artisan event:cache
php artisan cache:clear