Initialize rails app

This commit is contained in:
Roscoe 2025-09-20 03:31:27 +01:00
commit 64fb080e96
Signed by: RoscoeDaWah
SSH key fingerprint: SHA256:Hqn452XQ1ETzUt/FthJu6+OFkS4NBxCv5VQSEvuk7CE
234 changed files with 1398 additions and 14539 deletions

View file

@ -1,27 +0,0 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*/
protected function schedule(Schedule $schedule): void
{
// $schedule->command('inspire')->hourly();
}
/**
* Register the commands for the application.
*/
protected function commands(): void
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}

View file

@ -1,32 +0,0 @@
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* The list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*/
public function register(): void
{
$this->reportable(function (Throwable $e) {
if (app()->bound('sentry')) {
app('sentry')->captureException($e);
}
});
}
}

View file

@ -1,15 +0,0 @@
<?php
if (!function_exists('isLegacy')) {
/**
* Checks if the current hostname should return the legacy site
* @return bool
*/
function isLegacy(): bool {
return (
request()->getHost() === "legacy.wah.moe" || // Accessed via legacy.wah.moe domain
str_starts_with(request()->getHost(), "192.168") || // Accessed via local IP address
!request()->hasHeader("Host") // Browser does not send Host header (e.g. NCSA MOSAIC)
);
}
}

View file

@ -1,15 +0,0 @@
<?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

@ -1,12 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, ValidatesRequests;
}

View file

@ -1,33 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\GuestbookEntry;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Contracts\View\View;
use Illuminate\Validation\ValidationException;
use UAParser\Parser;
class GuestbookController extends Controller {
public function show(): View {
$entries = GuestbookEntry::selectEntries();
$parser = Parser::create();
return view('guestbook')
->with('entries', $entries)
->with('parser', $parser);
}
/**
* Creates a new guestbook entry
*
* @param Request $request
* @return RedirectResponse
* @throws ValidationException
*/
public function addEntry(Request $request): RedirectResponse {
GuestbookEntry::insertGuestbookEntry($request);
return back()->with('success', 'Entry submitted successfully!');
}
}

View file

@ -1,33 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
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

@ -1,76 +0,0 @@
<?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();
$track_data = $data["recenttracks"]["track"][0];
// $image = array_column($track_data["image"], null, 'size')['large'] ?? false;
$image = end($track_data["image"]) ?? false;
$now_playing = false;
if (array_key_exists("@attr", $track_data)) {
$now_playing = $track_data["@attr"]["nowplaying"] == "true" ?? ["url"=>null];
}
$current_track = [
'title' => $track_data["name"],
'artist' => $track_data["artist"]["#text"],
'url' => $track_data["url"],
'image' => $image["#text"],
'header' => $now_playing ? "Now Playing" : "Last Track",
];
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

@ -1,52 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\File;
use Illuminate\View\View;
class RoscoLekoController extends Controller {
public function getImages(): array {
$images = [];
$path = 'images/pandamonium';
if (isLegacy()) {
$path = 'images/pandamonium-legacy';
}
foreach (File::glob(public_path($path).'/*') as $path) {
$image_data = [];
try {
$exif = exif_read_data($path);
} catch (Exception $ex) {
}
$image_data["path"] = str_replace(public_path(), '', $path);
if (isset($exif)) {
if (isset($exif["ImageDescription"])) {
$image_data["description"] = $exif["ImageDescription"];
}
if (isset($exif["DateTime"])) {
$image_data["date"] = strtotime($exif["DateTime"]);
}
}
array_push($images, $image_data);
}
usort($images, function ($a, $b) {
$dateA = $a['date'] ?? PHP_INT_MIN;
$dateB = $b['date'] ?? PHP_INT_MIN;
return $dateB <=> $dateA;
});
return $images;
}
/**
* Shows the page
* @return View
*/
public function show(): View {
return view('pandamonium', [
'images' => $this->getImages(),
]);
}
}

View file

@ -1,73 +0,0 @@
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array<int, class-string|string>
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
protected $routeMiddleware = [
'rate_limit' => \App\Http\Middleware\RateLimiter::class,
'validator' => \App\Http\Middleware\GuestbookValidate::class,
];
/**
* The application's middleware aliases.
*
* Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
}

View file

@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*/
protected function redirectTo(Request $request): ?string
{
return $request->expectsJson() ? null : route('login');
}
}

View file

@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array<int, string>
*/
protected $except = [
"colorscheme"
];
}

View file

@ -1,37 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class GuestbookValidate
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if (
!$request->validate([
'name' => 'required',
'message' => 'required'
]) ||
$this->containsUrl($request->get('message')) ||
$this->containsUrl($request->get('name'))
) {
return response()->view('errors.guestbook-invalid', [], 400);
}
return $next($request);
}
public function containsUrl($str) {
$matches = [];
$pattern = '/\b(?:https?|ftp|www)(:\/\/)*[-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i';
preg_match_all($pattern, $str, $matches);
return count($matches[0]);
}
}

View file

@ -1,15 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array<int, string>
*/
protected $except = [];
}

View file

@ -1,35 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\Response;
class RateLimiter
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if (auth()->check()) {
return $next($request);
}
$ipAddress = $request->ip();
$cacheKey = 'rate_limit_'.$ipAddress;
if (Cache::has($cacheKey)) {
// If the cache key exists, the IP has submitted an entry within the last hour.
return response()->view('errors.guestbook-ratelimit', [], 429);
}
// Add the IP address to the cache and set the expiration time to one hour.
Cache::put($cacheKey, true, 3600);
return $next($request);
}
}

View file

@ -1,30 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next, string ...$guards): Response
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
} // End handle().
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array<int, string>
*/
protected $except = [
'current_password',
'password',
'password_confirmation',
];
}

View file

@ -1,20 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustHosts as Middleware;
class TrustHosts extends Middleware
{
/**
* Get the host patterns that should be trusted.
*
* @return array<int, string|null>
*/
public function hosts(): array
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}

View file

@ -1,29 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array<int, string>|string|null
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers =(
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB
);
}

View file

@ -1,22 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
class ValidateSignature extends Middleware
{
/**
* The names of the query string parameters that should be ignored.
*
* @var array<int, string>
*/
protected $except = [
// 'fbclid',
// 'utm_campaign',
// 'utm_content',
// 'utm_medium',
// 'utm_source',
// 'utm_term',
];
}

View file

@ -1,15 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array<int, string>
*/
protected $except = [];
}

View file

@ -1,36 +0,0 @@
<?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

@ -1,35 +0,0 @@
<?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

@ -1,50 +0,0 @@
<?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 = $request->get('name');
$newEntry->message = $request->get('message');
$newEntry->ip = $request->ip();
$newEntry->agent = $request->userAgent();
$newEntry->legacy_flagged = isLegacy();
$newEntry->save();
}
public static function selectEntries() {
$entries = GuestbookEntry::where("legacy_flagged", false)->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,21 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\ServiceProvider;
use PostHog\PostHog;
class AppServiceProvider extends ServiceProvider {
/**
* Register any application services.
*/
public function register(): void {
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void {}
}

View file

@ -1,25 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The model to policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [
//
];
/**
* Register any authentication / authorization services.
*/
public function boot(): void
{
//
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Broadcast::routes();
require base_path('routes/channels.php');
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event to listener mappings for the application.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*/
public function boot(): void
{
//
}
/**
* Determine if events and listeners should be automatically discovered.
*/
public function shouldDiscoverEvents(): bool
{
return false;
}
}

View file

@ -1,40 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* The path to your application's "home" route.
*
* Typically, users are redirected here after authentication.
*
* @var string
*/
public const HOME = '/home';
/**
* Define your route model bindings, pattern filters, and other route configuration.
*/
public function boot(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));
});
}
}

View file

@ -1,24 +0,0 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class LastFMCurrent 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.lastfm-current');
}
}

View file

@ -1,24 +0,0 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class LastFMTop 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.lastfm-top');
}
}

View file

@ -1,26 +0,0 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class LastFMTrack 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.lastfm-track');
}
}

View file

@ -1,40 +0,0 @@
<?php
namespace App\View\Components;
use Closure;
use DateTime;
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 {
if (isLegacy()) {
return view('components.layout-legacy', [
'isChristmas' => $this->isItChristmas()
]);
} else {
return view('components.layout', [
'isChristmas' => $this->isItChristmas()
]);
}
}
public function isItChristmas() : bool {
$currentDate = new DateTime();
$currentYear = intval($currentDate->format('Y'));
$startDate = new DateTime("$currentYear-11-10");
$endDate = new DateTime(($currentYear + 1) . "-01-01");
return $currentDate >= $startDate && $currentDate < $endDate;
}
}

View file

@ -1,24 +0,0 @@
<?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.navigation');
}
}

View file

@ -1,50 +0,0 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Illuminate\View\Component;
class Wah extends Component {
/**
* Create a new component instance.
*/
public function __construct() {}
public function getWah(): string {
if (isLegacy()) {
try {
$response = Http::get('https://api.tinyfox.dev/img.json?animal=wah');
$data = $response->json();
if ($data == null) return "";
$path = parse_url("https://api.tinyfox.dev" . $data["loc"], PHP_URL_PATH);
return "//".request()->getHttpHost()."/proxy/wah/".basename($path);
} catch (Exception $ex) {
return "";
}
}
try {
$response = Http::get('https://api.tinyfox.dev/img.json?animal=wah');
$data = $response->json();
if ($data == null) return "";
return "https://api.tinyfox.dev" . $data["loc"];
} catch (Exception $ex) {
return "";
}
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string {
return view('components.wah', [
'wah' => $this->getWah(),
]);
}
}

0
app/assets/images/.keep Normal file
View file

View file

@ -0,0 +1,10 @@
/*
* This is a manifest file that'll be compiled into application.css.
*
* With Propshaft, assets are served efficiently without preprocessing steps. You can still include
* application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
* cascading order, meaning styles declared later in the document or manifest will override earlier ones,
* depending on specificity.
*
* Consider organizing styles into separate files for maintainability.
*/

View file

@ -0,0 +1,4 @@
class ApplicationController < ActionController::Base
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
allow_browser versions: :modern
end

View file

View file

@ -0,0 +1,2 @@
module ApplicationHelper
end

View file

@ -0,0 +1,3 @@
class ApplicationRecord < ActiveRecord::Base
primary_abstract_class
end

View file

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<title><%= content_for(:title) || "Wah Moe" %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= yield :head %>
<%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
<%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
<link rel="icon" href="/icon.png" type="image/png">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/icon.png">
<%# Includes all stylesheet files in app/assets/stylesheets %>
<%= stylesheet_link_tag :app %>
</head>
<body>
<%= yield %>
</body>
</html>

View file

@ -0,0 +1,22 @@
{
"name": "WahMoe",
"icons": [
{
"src": "/icon.png",
"type": "image/png",
"sizes": "512x512"
},
{
"src": "/icon.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "maskable"
}
],
"start_url": "/",
"display": "standalone",
"scope": "/",
"description": "WahMoe.",
"theme_color": "red",
"background_color": "red"
}

View file

@ -0,0 +1,26 @@
// Add a service worker for processing Web Push notifications:
//
// self.addEventListener("push", async (event) => {
// const { title, options } = await event.data.json()
// event.waitUntil(self.registration.showNotification(title, options))
// })
//
// self.addEventListener("notificationclick", function(event) {
// event.notification.close()
// event.waitUntil(
// clients.matchAll({ type: "window" }).then((clientList) => {
// for (let i = 0; i < clientList.length; i++) {
// let client = clientList[i]
// let clientPath = (new URL(client.url)).pathname
//
// if (clientPath == event.notification.data.path && "focus" in client) {
// return client.focus()
// }
// }
//
// if (clients.openWindow) {
// return clients.openWindow(event.notification.data.path)
// }
// })
// )
// })