aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorFrankie B <git@diskfloppy.me>2024-06-11 18:02:01 +0100
committerGitHub <noreply@github.com>2024-06-11 18:02:01 +0100
commit0f52d80ca67a49258b235f5831163dd72fbd54cf (patch)
tree9c5cd36b6e0a233e09ac88a4409fb68c63e4781a /app
parenta64bcc2c4639d5804b6dada23151bfcb8b198121 (diff)
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
Diffstat (limited to 'app')
-rw-r--r--app/Http/Controllers/AdminBookmarksController.php15
-rw-r--r--app/Http/Controllers/AdminGuestbookController.php34
-rw-r--r--app/Http/Controllers/AdminImportController.php69
-rw-r--r--app/Http/Controllers/BookmarksController.php15
-rw-r--r--app/Http/Controllers/CalculatorsController.php13
-rw-r--r--app/Http/Controllers/ComputersController.php13
-rw-r--r--app/Http/Controllers/GuestbookController.php49
-rw-r--r--app/Http/Controllers/HomeController.php32
-rw-r--r--app/Http/Controllers/MusicController.php69
-rw-r--r--app/Http/Middleware/RateLimiter.php3
-rw-r--r--app/Models/BookmarkCategory.php36
-rw-r--r--app/Models/BookmarkSite.php35
-rw-r--r--app/Models/GuestbookEntry.php50
-rw-r--r--app/Models/User.php45
-rw-r--r--app/View/Components/CurrentTrack.php27
-rw-r--r--app/View/Components/Layout.php26
-rw-r--r--app/View/Components/Navbar.php27
-rw-r--r--app/View/Components/TopTracks.php27
-rw-r--r--app/View/Components/Track.php29
19 files changed, 549 insertions, 65 deletions
diff --git a/app/Http/Controllers/AdminBookmarksController.php b/app/Http/Controllers/AdminBookmarksController.php
new file mode 100644
index 0000000..c7d8afd
--- /dev/null
+++ b/app/Http/Controllers/AdminBookmarksController.php
@@ -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'));
+ }
+}
diff --git a/app/Http/Controllers/AdminGuestbookController.php b/app/Http/Controllers/AdminGuestbookController.php
new file mode 100644
index 0000000..5ebf451
--- /dev/null
+++ b/app/Http/Controllers/AdminGuestbookController.php
@@ -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,
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/AdminImportController.php b/app/Http/Controllers/AdminImportController.php
new file mode 100644
index 0000000..dc32cec
--- /dev/null
+++ b/app/Http/Controllers/AdminImportController.php
@@ -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)");
+ }
+ }
+}
diff --git a/app/Http/Controllers/BookmarksController.php b/app/Http/Controllers/BookmarksController.php
new file mode 100644
index 0000000..56aacc7
--- /dev/null
+++ b/app/Http/Controllers/BookmarksController.php
@@ -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'));
+ }
+}
diff --git a/app/Http/Controllers/CalculatorsController.php b/app/Http/Controllers/CalculatorsController.php
new file mode 100644
index 0000000..38a7a41
--- /dev/null
+++ b/app/Http/Controllers/CalculatorsController.php
@@ -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');
+ }
+}
diff --git a/app/Http/Controllers/ComputersController.php b/app/Http/Controllers/ComputersController.php
new file mode 100644
index 0000000..e16e70d
--- /dev/null
+++ b/app/Http/Controllers/ComputersController.php
@@ -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');
+ }
+}
diff --git a/app/Http/Controllers/GuestbookController.php b/app/Http/Controllers/GuestbookController.php
index 70707d7..df726ef 100644
--- a/app/Http/Controllers/GuestbookController.php
+++ b/app/Http/Controllers/GuestbookController.php
@@ -2,37 +2,46 @@
namespace App\Http\Controllers;
+use App\Models\GuestbookEntry;
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 {
- public function guestbook() {
- return view('pages.guestbook');
+ public function show(): View {
+ $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, [
'name' => '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!');
}
+
+ 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);
+ // }
+ }
}
diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php
new file mode 100644
index 0000000..3fad094
--- /dev/null
+++ b/app/Http/Controllers/HomeController.php
@@ -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()
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/MusicController.php b/app/Http/Controllers/MusicController.php
new file mode 100644
index 0000000..5e31d86
--- /dev/null
+++ b/app/Http/Controllers/MusicController.php
@@ -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());
+ }
+}
diff --git a/app/Http/Middleware/RateLimiter.php b/app/Http/Middleware/RateLimiter.php
index 09eb0a9..821868f 100644
--- a/app/Http/Middleware/RateLimiter.php
+++ b/app/Http/Middleware/RateLimiter.php
@@ -16,6 +16,9 @@ class RateLimiter
*/
public function handle(Request $request, Closure $next): Response
{
+ if (auth()->check()) {
+ return $next($request);
+ }
$ipAddress = $request->ip();
$cacheKey = 'rate_limit_'.$ipAddress;
diff --git a/app/Models/BookmarkCategory.php b/app/Models/BookmarkCategory.php
new file mode 100644
index 0000000..a8bc8d2
--- /dev/null
+++ b/app/Models/BookmarkCategory.php
@@ -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();
+ }
+ }
+}
diff --git a/app/Models/BookmarkSite.php b/app/Models/BookmarkSite.php
new file mode 100644
index 0000000..3c9cc5d
--- /dev/null
+++ b/app/Models/BookmarkSite.php
@@ -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();
+ }
+ }
+}
diff --git a/app/Models/GuestbookEntry.php b/app/Models/GuestbookEntry.php
new file mode 100644
index 0000000..f5e2de2
--- /dev/null
+++ b/app/Models/GuestbookEntry.php
@@ -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();
+ }
+ }
+}
diff --git a/app/Models/User.php b/app/Models/User.php
deleted file mode 100644
index 4d7f70f..0000000
--- a/app/Models/User.php
+++ /dev/null
@@ -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',
- ];
-}
diff --git a/app/View/Components/CurrentTrack.php b/app/View/Components/CurrentTrack.php
new file mode 100644
index 0000000..337809a
--- /dev/null
+++ b/app/View/Components/CurrentTrack.php
@@ -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');
+ }
+}
diff --git a/app/View/Components/Layout.php b/app/View/Components/Layout.php
new file mode 100644
index 0000000..576d1a0
--- /dev/null
+++ b/app/View/Components/Layout.php
@@ -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');
+ }
+}
diff --git a/app/View/Components/Navbar.php b/app/View/Components/Navbar.php
new file mode 100644
index 0000000..a19db3b
--- /dev/null
+++ b/app/View/Components/Navbar.php
@@ -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');
+ }
+}
diff --git a/app/View/Components/TopTracks.php b/app/View/Components/TopTracks.php
new file mode 100644
index 0000000..768ce33
--- /dev/null
+++ b/app/View/Components/TopTracks.php
@@ -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');
+ }
+}
diff --git a/app/View/Components/Track.php b/app/View/Components/Track.php
new file mode 100644
index 0000000..b9f628f
--- /dev/null
+++ b/app/View/Components/Track.php
@@ -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');
+ }
+}