🆙 Final fix delete storage link to fix news_images and logs 🆙

This commit is contained in:
Remco
2026-01-07 20:29:24 +01:00
parent 65ea6c167f
commit acf2d7e661
447 changed files with 208 additions and 66965 deletions
@@ -1,29 +0,0 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\OnlineUserCountResource;
use App\Http\Resources\OnlineUsersResource;
use App\Http\Resources\UserResource;
use App\Services\User\UserApiService;
class HotelApiController extends Controller
{
public function __construct(private readonly UserApiService $userApiService) {}
public function fetchUser(string $username, array $columns = ['username', 'motto', 'look']): UserResource
{
return new UserResource($this->userApiService->fetchUser($username, $columns));
}
public function onlineUsers($columns = ['username', 'motto', 'look'], bool $randomOrder = true): OnlineUsersResource
{
return new OnlineUsersResource($this->userApiService->onlineUsers($columns, $randomOrder));
}
public function onlineUserCount(): OnlineUserCountResource
{
return new OnlineUserCountResource($this->userApiService->onlineUserCount());
}
}
@@ -1,46 +0,0 @@
<?php
namespace App\Http\Controllers\Articles;
use App\Http\Controllers\Controller;
use App\Models\Articles\WebsiteArticle;
use App\Services\Articles\ArticleService;
use App\Services\Articles\ReactionService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class ArticleController extends Controller
{
public function __construct(
private readonly ArticleService $articlesService,
private readonly ReactionService $reactionService,
) {}
public function index(): View
{
$articles = $this->articlesService->getArticles(true);
return view('community.articles', [
'articles' => $articles,
]);
}
public function show(WebsiteArticle $article): View
{
return view('community.article', [
'article' => $article,
'otherArticles' => WebsiteArticle::whereNot('slug', $article->slug)->latest('id')->take(15)->get(),
'myReactions' => Auth::check() ? $article->reactions->where('user_id', Auth::id())->pluck('reaction') : [],
'articleReactions' => collect($article->reactions)->groupBy('reaction', true),
]);
}
public function toggleReaction(WebsiteArticle $article, Request $request): JsonResponse
{
$response = $this->reactionService->toggleReaction($article, Auth::user(), $request);
return response()->json($response);
}
}
@@ -1,29 +0,0 @@
<?php
namespace App\Http\Controllers\Articles;
use App\Http\Controllers\Controller;
use App\Http\Requests\ArticleCommentFormRequest;
use App\Models\Articles\WebsiteArticle;
use App\Models\Articles\WebsiteArticleComment;
use App\Services\Articles\CommentService;
use Illuminate\Http\RedirectResponse;
class WebsiteArticleCommentsController extends Controller
{
public function __construct(public readonly CommentService $commentService) {}
public function store(WebsiteArticle $article, ArticleCommentFormRequest $request): RedirectResponse
{
$this->commentService->store($request->get('comment'), $article);
return back()->with('success', __('You comment has been posted!'));
}
public function destroy(WebsiteArticleComment $comment): RedirectResponse
{
$this->commentService->destroy($comment);
return back()->with('success', __('You comment has been deleted!'));
}
}
@@ -1,124 +0,0 @@
<?php
namespace App\Http\Controllers\Badge;
use App\Actions\SendCurrency;
use App\Enums\CurrencyTypes;
use App\Http\Controllers\Controller;
use App\Models\WebsiteDrawBadge;
use App\Services\SettingsService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class BadgeController extends Controller
{
private const int BADGE_WIDTH = 40;
private const int BADGE_HEIGHT = 40;
private const int MAX_BADGE_SIZE_BYTES = 40960;
public function show(SettingsService $settingsService)
{
$cost = (int) $settingsService->getOrDefault('drawbadge_currency_value', 150);
$currencyType = $settingsService->getOrDefault('drawbadge_currency_type', 'credits');
$badgesPath = $settingsService->getOrDefault('badge_path_filesystem');
$folderError = false;
$errorMessage = '';
if ($badgesPath === '' || $badgesPath === '0') {
$folderError = true;
$errorMessage = 'Badges path not configured.';
} elseif (! file_exists($badgesPath)) {
$folderError = true;
$errorMessage = 'Badges path not configured.';
} elseif (! is_writable($badgesPath)) {
$folderError = true;
$errorMessage = 'Badges folder does not have write access.';
}
return view('draw-badge', ['cost' => $cost, 'currencyType' => $currencyType, 'folderError' => $folderError, 'errorMessage' => $errorMessage]);
}
public function buy(Request $request, SendCurrency $sendCurrency, SettingsService $settingsService)
{
$user = Auth::user();
$cost = (int) $settingsService->getOrDefault('drawbadge_currency_value', 150);
$currencyType = $settingsService->getOrDefault('drawbadge_currency_type', 'credits');
$currentAmount = match ($currencyType) {
'credits' => $user->credits ?? 0,
'duckets' => $user->currencies()->where('type', CurrencyTypes::Duckets)->value('amount') ?? 0,
'diamonds' => $user->currencies()->where('type', CurrencyTypes::Diamonds)->value('amount') ?? 0,
'points' => $user->currencies()->where('type', CurrencyTypes::Points)->value('amount') ?? 0,
default => 0,
};
if ($currentAmount < $cost) {
return response()->json(['success' => false, 'message' => 'Insufficient ' . $currencyType . '.'], 400);
}
$result = $sendCurrency->execute($user, $currencyType, -$cost);
if ($result === false) {
return response()->json(['success' => false, 'message' => 'Failed to deduct ' . $currencyType . '.'], 500);
}
$badgeData = $request->input('badge_data');
if (! $badgeData) {
return response()->json(['success' => false, 'message' => 'No badge data provided.'], 400);
}
$badgeData = preg_replace('#^data:image/\w+;base64,#i', '', (string) $badgeData);
$decoded = base64_decode((string) $badgeData, true);
if ($decoded === false) {
return response()->json(['success' => false, 'message' => 'Invalid base64 data.'], 400);
}
$info = @getimagesizefromstring($decoded);
if (
$info === false ||
$info['mime'] !== 'image/gif' ||
$info[0] !== self::BADGE_WIDTH ||
$info[1] !== self::BADGE_HEIGHT
) {
return response()->json(['success' => false, 'message' => 'Invalid GIF image or incorrect dimensions.'], 400);
}
if (strlen($decoded) > self::MAX_BADGE_SIZE_BYTES) {
return response()->json(['success' => false, 'message' => 'Image file too large.'], 400);
}
$image = @imagecreatefromstring($decoded);
if ($image === false) {
return response()->json(['success' => false, 'message' => 'Failed to process image.'], 400);
}
$badgesPath = $settingsService->getOrDefault('badge_path_filesystem');
if ($badgesPath === '' || $badgesPath === '0') {
return response()->json(['success' => false, 'message' => 'Badges path not configured.'], 500);
}
$filename = $user->id . '_' . time() . '.gif';
$fullPath = rtrim($badgesPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $filename;
if (! imagegif($image, $fullPath)) {
return response()->json(['success' => false, 'message' => 'Failed to save badge file.'], 500);
}
$baseUrl = $settingsService->getOrDefault('badges_path', '/badges/');
$badgeUrl = rtrim($baseUrl, '/') . '/' . $filename;
WebsiteDrawBadge::create([
'user_id' => $user->id,
'badge_path' => $fullPath,
'badge_url' => $badgeUrl,
'badge_name' => $request->input('badge_name'),
'badge_desc' => $request->input('badge_description'),
]);
return response()->json(['success' => true, 'badge_path_filesystem' => $fullPath]);
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\Client;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class FlashController extends Controller
{
public function __invoke(): View
{
Auth::user()->update([
'ip_current' => request()->ip(),
]);
return view('client.flash', [
'sso' => Auth::user()->ssoTicket(),
]);
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\Client;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class NitroController extends Controller
{
public function __invoke(): View
{
Auth::user()->update([
'ip_current' => request()->ip(),
]);
return view('client.nitro', [
'sso' => Auth::user()->ssoTicket(),
]);
}
}
@@ -1,56 +0,0 @@
<?php
namespace App\Http\Controllers\Community;
use App\Http\Controllers\Controller;
use App\Models\Game\Player\UserCurrency;
use App\Models\Game\Player\UserSetting;
use App\Models\User;
use App\Services\Community\StaffService;
use Illuminate\View\View;
class LeaderboardController extends Controller
{
protected array $staffIds = [];
public function __construct(private readonly StaffService $staffService)
{
$this->staffIds = $this->staffService->fetchEmployeeIds();
}
public function __invoke(): View
{
$topCredits = User::query()
->whereNotIn('id', $this->staffIds)
->orderByDesc('credits')
->take(9)
->get();
$getUserCurrency = fn ($type) => UserCurrency::query()
->whereNotIn('user_id', $this->staffIds)
->where('type', $type)
->orderByDesc('amount')
->take(9)
->with('user:id,username,look')
->get();
return view('leaderboard', [
'credits' => $topCredits,
'duckets' => $getUserCurrency(0),
'diamonds' => $getUserCurrency(5),
'mostOnline' => $this->retrieveSettings('online_time'),
'respectsReceived' => $this->retrieveSettings('respects_received'),
'achievementScores' => $this->retrieveSettings('achievement_score'),
]);
}
private function retrieveSettings($column)
{
return UserSetting::select('user_id', $column)
->whereNotIn('user_id', $this->staffIds)
->orderByDesc($column)
->take(9)
->with('user:id,username,look')
->get();
}
}
@@ -1,19 +0,0 @@
<?php
namespace App\Http\Controllers\Community;
use App\Http\Controllers\Controller;
use App\Services\Community\CameraService;
use Illuminate\View\View;
class PhotosController extends Controller
{
public function __construct(private readonly CameraService $cameraService) {}
public function __invoke(): View
{
return view('community.photos', [
'photos' => $this->cameraService->fetchPhotos(true),
]);
}
}
@@ -1,17 +0,0 @@
<?php
namespace App\Http\Controllers\Community;
use App\Http\Controllers\Controller;
use App\Models\Game\Room;
use Illuminate\View\View;
class RoomController extends Controller
{
public function __invoke(Room $room): View
{
return view('room.index', [
'room' => $room->load('owner:id,username,look'),
]);
}
}
@@ -1,47 +0,0 @@
<?php
namespace App\Http\Controllers\Community\Staff;
use App\Http\Controllers\Controller;
use App\Http\Requests\StaffApplicationFormRequest;
use App\Models\Community\Staff\WebsiteOpenPosition;
use App\Services\Community\StaffApplicationService;
use Illuminate\Http\RedirectResponse;
class StaffApplicationsController extends Controller
{
public function __construct(private readonly StaffApplicationService $staffApplicationService) {}
public function index()
{
return view('community.staff-applications', [
'positions' => $this->staffApplicationService->fetchOpenPositions(),
]);
}
public function show(WebsiteOpenPosition $position)
{
return view('community.staff-applications-apply', [
'position' => $position->load('permission'),
]);
}
public function store(WebsiteOpenPosition $position, StaffApplicationFormRequest $request): RedirectResponse
{
if ($this->staffApplicationService->hasUserAppliedForPosition($request->user(), $position->permission->id)) {
return back()->withErrors([
'message' => __('You have already applied for this position.'),
]);
}
if (! $this->staffApplicationService->isPositionOpenForApplication($position)) {
return back()->withErrors([
'message' => __('You cannot apply for this position.'),
]);
}
$this->staffApplicationService->storeApplication($request->user(), $position->permission->id, $request->input('content'));
return to_route('staff-applications.index')->with('success', __('Your application has been submitted!'));
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\Community\Staff;
use App\Http\Controllers\Controller;
use App\Services\Community\StaffService;
use Illuminate\View\View;
class StaffController extends Controller
{
public function __construct(private readonly StaffService $staffService) {}
public function __invoke(): View
{
$employees = $this->staffService->fetchStaffPositions();
return view('community.staff', [
'employees' => $employees,
]);
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\Community\Staff;
use App\Http\Controllers\Controller;
use App\Services\Community\TeamService;
use Illuminate\View\View;
class WebsiteTeamsController extends Controller
{
public function __construct(private readonly TeamService $teamService) {}
public function __invoke(): View
{
$employees = $this->teamService->fetchTeams();
return view('community.teams', [
'employees' => $employees,
]);
}
}
@@ -1,81 +0,0 @@
<?php
namespace App\Http\Controllers\Community;
use App\Http\Controllers\Controller;
use App\Http\Requests\RareSearchFormRequest;
use App\Models\Community\RareValue\WebsiteRareValue;
use App\Models\Community\RareValue\WebsiteRareValueCategory;
use App\Models\Game\Furniture\Item;
use App\Services\Community\RareValues\RareValueCategoriesService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;
class WebsiteRareValuesController extends Controller
{
public function __construct(private readonly RareValueCategoriesService $valueCategoriesService) {}
public function index(): View
{
return view('rare-values', [
'categories' => $this->valueCategoriesService->fetchCategoriesByPriority(),
'categoriesNav' => $this->valueCategoriesService->fetchAllCategories(),
]);
}
public function category(int $id): View|RedirectResponse
{
$category = $this->valueCategoriesService->fetchCategoryById($id);
if (! $category instanceof \App\Models\Community\RareValue\WebsiteRareValueCategory) {
return back()->withErrors([
'message' => __('The entered category does not exist'),
]);
}
return view('rare-values', [
'categories' => $category,
'categoriesNav' => $this->valueCategoriesService->fetchAllCategories(),
]);
}
public function search(RareSearchFormRequest $request): View|RedirectResponse
{
$searchTerm = $request->input('search');
$categories = $this->valueCategoriesService->searchCategories($searchTerm);
if ($categories->isEmpty()) {
return back()->withErrors([
'message' => __('It seems like there were no rares matching your search input'),
]);
}
return view('rare-values', [
'categories' => $categories,
'categoriesNav' => WebsiteRareValueCategory::has('furniture')->get(),
]);
}
public function value(WebsiteRareValue $value): View
{
$items = Item::with(['user:id,username,look'])
->where('item_id', $value->item_id)
->get();
$itemsPerUser = $items->groupBy('user_id')->map(fn ($group) => [
'user' => $group->first()->user,
'item_count' => $group->count(),
]);
if ((bool) setting('enable_caching')) {
Cache::remember('allItems_' . $value->id, setting('cache_timer'), fn () => $items);
}
return view('value', [
'value' => $value,
'items' => $itemsPerUser,
]);
}
}
@@ -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;
}
@@ -1,16 +0,0 @@
<?php
namespace App\Http\Controllers\Help;
use App\Http\Controllers\Controller;
use App\Models\Help\WebsiteHelpCenterCategory;
class HelpCenterController extends Controller
{
public function __invoke()
{
return view('help-center.index', [
'categories' => WebsiteHelpCenterCategory::orderBy('position')->get(),
]);
}
}
@@ -1,120 +0,0 @@
<?php
namespace App\Http\Controllers\Help;
use App\Http\Controllers\Controller;
use App\Http\Requests\WebsiteTicketFormRequest;
use App\Models\Help\WebsiteHelpCenterCategory;
use App\Models\Help\WebsiteHelpCenterTicket;
use Illuminate\Support\Facades\Auth;
class TicketController extends Controller
{
public function index()
{
if (hasPermission('manage_website_tickets') === '' || hasPermission('manage_website_tickets') === '0') {
return back()->with([
'message' => __('You cannot access this page'),
]);
}
return view('help-center.tickets.index', [
'tickets' => WebsiteHelpCenterTicket::orderBy('open')->with('user:id,username')->paginate(15),
]);
}
public function create()
{
return view('help-center.tickets.create', [
'categories' => WebsiteHelpCenterCategory::get(),
'openTickets' => WebsiteHelpCenterTicket::where('open', true)->where('user_id', Auth::id())->get(),
]);
}
public function store(WebsiteTicketFormRequest $request)
{
Auth::user()->tickets()->create($request->validated());
return back()->with('success', __('Ticket submitted!'));
}
public function edit(WebsiteHelpCenterTicket $ticket)
{
if (! $ticket->canManageTicket()) {
return back()->with([
'message' => __('You cannot manage others tickets.'),
]);
}
$ticket->load([
'user:id,username,look',
'category',
'replies.user:id,username,look',
]);
return view('help-center.tickets.edit', [
'ticket' => $ticket,
'categories' => WebsiteHelpCenterCategory::get(),
'openTickets' => WebsiteHelpCenterTicket::where('open', true)->where('id', '!=', $ticket->id)->where('user_id', Auth::id())->get(),
]);
}
public function update(WebsiteHelpCenterTicket $ticket, WebsiteTicketFormRequest $request)
{
if (! $ticket->canManageTicket()) {
return back()->with([
'message' => __('You cannot manage others tickets.'),
]);
}
$ticket->update($request->validated());
return to_route('help-center.ticket.show', $ticket)->with('success', __('Ticket updated!'));
}
public function show(WebsiteHelpCenterTicket $ticket)
{
if (! $ticket->canManageTicket()) {
return back()->with([
'message' => __('You cannot view others tickets.'),
]);
}
$ticket->load([
'user:id,username,look',
'category',
'replies.user:id,username,look',
]);
return view('help-center.tickets.show', [
'ticket' => $ticket,
'openTickets' => WebsiteHelpCenterTicket::where('open', true)->where('id', '!=', $ticket->id)->where('user_id', Auth::id())->get(),
]);
}
public function destroy(WebsiteHelpCenterTicket $ticket)
{
if (! $ticket->canDeleteTicket()) {
return back()->with([
'message' => __('You cannot delete others tickets.'),
]);
}
$ticket->delete();
return to_route('me.show')->with('success', __('The ticket has been deleted!'));
}
public function toggleTicketStatus(WebsiteHelpCenterTicket $ticket)
{
if (! $ticket->canManageTicket()) {
return back()->with([
'message' => __('You manage others tickets.'),
]);
}
$ticket->open ? $ticket->update(['open' => false]) : $ticket->update(['open' => true]);
return back()->with('success', __('The ticket status has been changed!'));
}
}
@@ -1,47 +0,0 @@
<?php
namespace App\Http\Controllers\Help;
use App\Http\Controllers\Controller;
use App\Http\Requests\WebsiteTicketReplyFormRequest;
use App\Models\Help\WebsiteHelpCenterTicket;
use App\Models\Help\WebsiteHelpCenterTicketReply;
class TicketReplyController extends Controller
{
public function store(WebsiteHelpCenterTicket $ticket, WebsiteTicketReplyFormRequest $request)
{
if (! $ticket->isOpen()) {
return back()->with([
'message' => __('You cannot reply to the ticket as it has been closed.'),
]);
}
if (! $ticket->canManageTicket()) {
return back()->with([
'message' => __('You cannot reply to others tickets.'),
]);
}
$data = $request->validated();
$ticket->replies()->create([
'user_id' => $request->user()->id,
'content' => $data['content'],
]);
return back()->with('success', __('The reply has been submitted!'));
}
public function destroy(WebsiteHelpCenterTicketReply $reply)
{
if (! $reply->canDeleteReply()) {
return back()->with([
'message' => __('You do not have permission to delete this reply.'),
]);
}
$reply->delete();
return back()->with('success', __('The reply has been deleted!'));
}
}
@@ -1,17 +0,0 @@
<?php
namespace App\Http\Controllers\Help;
use App\Http\Controllers\Controller;
use App\Models\Help\WebsiteRuleCategory;
use Illuminate\View\View;
class WebsiteRulesController extends Controller
{
public function __invoke(): View
{
return view('rules', [
'categories' => WebsiteRuleCategory::with('rules')->get(),
]);
}
}
@@ -1,27 +0,0 @@
<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Articles\WebsiteArticle;
use App\Models\Miscellaneous\CameraWeb;
use Illuminate\View\View;
class HomeController extends Controller
{
public function __invoke(): View
{
return view('index', [
'articles' => WebsiteArticle::latest('id')
->take(4)
->has('user')
->with('user:id,username,look')
->get(),
'photos' => CameraWeb::latest('id')
->take(4)
->where('visible', true)
->with('user:id,username,look')
->get(),
]);
}
}
@@ -1,119 +0,0 @@
<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Miscellaneous\WebsiteInstallation;
use App\Models\Miscellaneous\WebsiteSetting;
use App\Rules\ValidateInstallationKeyRule;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class InstallationController extends Controller
{
public function index()
{
return view('installation.index');
}
public function storeInstallationKey(Request $request)
{
$request->validate([
'installation_key' => ['required', 'string', 'max:255', new ValidateInstallationKeyRule],
]);
WebsiteInstallation::first()->update([
'step' => 1,
'user_ip' => $request->ip(),
]);
return to_route('installation.show-step', 1);
}
public function showStep($currentStep)
{
$settings = $this->getSettingsForStep((int) $currentStep);
return view('installation.step-' . $currentStep, [
'settings' => $settings,
]);
}
public function saveStepSettings(Request $request)
{
$this->updateSettings($request);
WebsiteInstallation::increment('step');
return to_route('installation.show-step', WebsiteInstallation::first()->step);
}
public function previousStep()
{
WebsiteInstallation::decrement('step');
return to_route('installation.show-step', WebsiteInstallation::first()->step);
}
public function restartInstallation()
{
WebsiteInstallation::first()->update([
'step' => 0,
'installation_key' => Str::uuid(),
'user_ip' => null,
]);
WebsiteSetting::where('key', 'theme')->update([
'value' => 'atom',
]);
return to_route('installation.index');
}
public function completeInstallation()
{
WebsiteInstallation::latest()->first()->update([
'completed' => true,
]);
if (Cache::has('website_permissions')) {
Cache::forget('website_permissions');
}
if (Cache::has('website_settings')) {
Cache::forget('website_settings');
}
return to_route('welcome');
}
private function updateSettings(Request $request)
{
foreach ($request->except('_token') as $key => $value) {
WebsiteSetting::where('key', '=', $key)->update([
'value' => $value ?? '',
]);
}
}
private function getSettingsForStep(int $step)
{
$settingsData = array_chunk(WebsiteSetting::all()->pluck('key')->toArray(), ceil(WebsiteSetting::count() / 4));
$settings = match ($step) {
1 => $settingsData[0] ?? [],
2 => $settingsData[1] ?? [],
3 => $settingsData[2] ?? [],
4 => $settingsData[3] ?? [],
5 => [], // Completion step has no settings
default => throw new Exception('Step does not exist'),
};
return WebsiteSetting::query()
->whereIn('key', $settings)
->select(['key', 'value', 'comment'])
->get();
}
}
@@ -1,24 +0,0 @@
<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Miscellaneous\WebsiteLanguage;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Session;
class LocaleController extends Controller
{
public function __invoke(string $locale): RedirectResponse
{
if (! WebsiteLanguage::where('country_code', $locale)->exists()) {
return back()->withErrors(['message' => __('The language selected is not supported')]);
}
App::setLocale($locale);
Session::put('locale', $locale);
return back();
}
}
@@ -1,40 +0,0 @@
<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Miscellaneous\WebsiteSetting;
use Illuminate\Http\Request;
class LogoGeneratorController extends Controller
{
public function index()
{
if (hasPermission('generate_logo') === '' || hasPermission('generate_logo') === '0') {
return to_route('me.show')->with([
'message' => __('You do not have permission to do this.'),
]);
}
return view('logo-generator');
}
public function store(Request $request)
{
$request->validate(['logo' => ['required', 'image']]);
$file = $request->file('logo');
$filename = $file->getClientOriginalName();
$path = '/assets/images/generated-logos';
$file->move(public_path($path), $filename);
$setting = WebsiteSetting::where('key', 'cms_logo')->first();
$setting->update([
'value' => sprintf('%s/%s', $path, $filename),
]);
return response()->json(['success' => true, 'message' => 'Logo updated!']);
}
}
@@ -1,17 +0,0 @@
<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Miscellaneous\WebsiteMaintenanceTask;
use Illuminate\View\View;
class MaintenanceController extends Controller
{
public function __invoke(): View
{
return view('maintenance', [
'tasks' => WebsiteMaintenanceTask::with('user:id,username,look')->simplePaginate(5),
]);
}
}
@@ -1,145 +0,0 @@
<?php
namespace App\Http\Controllers\Shop;
use App\Http\Controllers\Controller;
use App\Http\Requests\AccountTopupFormRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Srmklive\PayPal\Services\PayPal as PayPalClient;
use Symfony\Component\HttpFoundation\Response;
class PaypalController extends Controller
{
private const string STATUS_CANCELLED = 'CANCELLED';
private const string STATUS_COMPLETED = 'COMPLETED';
public function __construct(private PayPalClient $provider)
{
$this->provider = new PayPalClient;
$this->provider->setApiCredentials(config('habbo.paypal'));
$this->provider->getAccessToken();
}
public function process(AccountTopupFormRequest $request): Response|RedirectResponse
{
$amount = $request->integer('amount');
$orderData = [
'intent' => 'CAPTURE',
'application_context' => [
'return_url' => route('paypal.successful-transaction'),
'cancel_url' => route('paypal.cancelled-transaction'),
'brand_name' => setting('hotel_name'),
'landing_page' => 'BILLING',
'shipping_preference' => 'NO_SHIPPING',
'user_action' => 'CONTINUE',
],
'purchase_units' => [
0 => [
'amount' => [
'currency_code' => config('habbo.paypal.currency'),
'value' => (string) $amount,
],
],
],
];
$response = $this->provider->createOrder($orderData);
if (isset($response['id']) === false) {
Log::error('Error creating order', ['response' => $response]);
return to_route('shop.index')->withErrors(
['message' => $response['message'] ?? __('Something went wrong')],
);
}
foreach ($response['links'] as $links) {
if ($links['rel'] === 'approve') {
$request->user()->transactions()->create([
'transaction_id' => $response['id'],
'amount' => 0,
]);
return redirect()->away($links['href']);
}
}
return to_route('shop.index')->withErrors(
['message' => $response['message'] ?? __('Something went wrong')],
);
}
public function successful(Request $request): Response
{
$request->validate([
'token' => ['required'],
]);
$user = $request->user();
$transaction = $user->transactions()->where('transaction_id', $request['token'])->first();
if ($transaction === null) {
return to_route('shop.index')->withErrors(['message' => __('Something went wrong, please try again later')]);
}
$response = $this->provider->capturePaymentOrder($request['token']);
$paymentDetails = $response['purchase_units'][0]['payments']['captures'][0];
if (! isset($response['status'], $paymentDetails)) {
Log::error('Invalid response from PayPal', ['response' => $response]);
return to_route('shop.index')->withErrors(['message' => __('Something went wrong, please try again later')]);
}
if (($response['status'] ?? null) === null) {
$details = $response['error']['details'][0];
$transaction->update([
'status' => $response['name'],
'description' => sprintf('%s - %s', $details['issue'], $details['description']),
'amount' => 0,
]);
return to_route('shop.index')->withErrors(['message' => __('Something went wrong, please check your paypal account to make sure nothing was deducted and try again')]);
}
$paymentDetails = $response['purchase_units'][0]['payments']['captures'][0];
$transaction->update([
'status' => $paymentDetails['status'],
'amount' => $paymentDetails['amount']['value'],
'currency' => $paymentDetails['amount']['currency_code'],
]);
if ($response['status'] !== self::STATUS_COMPLETED) {
return to_route('shop.index')->withErrors(
['message' => $response['message'] ?? __('Something went wrong')],
);
}
$user->increment('website_balance', $paymentDetails['amount']['value']);
return to_route('shop.index')->with('success', __('Transaction successful'));
}
public function cancelled(Request $request): Response
{
$request->validate([
'token' => ['required'],
]);
$transaction = $request->user()->transactions()->where('transaction_id', $request['token'])->first();
if ($transaction !== null) {
$transaction->update([
'status' => self::STATUS_CANCELLED,
'description' => 'The user cancelled the transaction',
]);
}
return to_route('shop.index')->withErrors(
['message' => __('You have canceled the transaction')],
);
}
}
@@ -1,142 +0,0 @@
<?php
namespace App\Http\Controllers\Shop;
use App\Actions\SendCurrency;
use App\Actions\SendFurniture;
use App\Http\Controllers\Controller;
use App\Models\Shop\WebsiteShopArticle;
use App\Models\Shop\WebsiteShopCategory;
use App\Models\User;
use App\Services\RconService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class ShopController extends Controller
{
public function __construct(private readonly RconService $rconService) {}
public function __invoke(?WebsiteShopCategory $category)
{
$packages = WebsiteShopArticle::orderBy('position');
if ($category && $category->exists) {
$packages = $category->articles()->orderBy('position');
}
return view('shop.shop', [
'articles' => $packages->with(['rank:id,rank_name', 'features'])->get(),
'categories' => WebsiteShopCategory::whereHas('articles')->get(),
]);
}
private function giveBadges(User $user, string $badges)
{
$badgeList = explode(';', $badges);
$ownedBadges = $user->badges()->pluck('badge_code')->toArray();
foreach ($badgeList as $badge) {
if (in_array($badge, $ownedBadges)) {
continue;
}
if ($this->rconService->isConnected) {
$this->rconService->giveBadge($user, $badge);
continue;
}
$user->badges()->updateOrCreate([
'user_id' => $user->id,
'badge_code' => $badge,
]);
}
}
public function purchase(WebsiteShopArticle $package, Request $request, SendCurrency $sendCurrency): Response
{
$user = Auth::user();
if ($request->has('receiver')) {
if (! $package->is_giftable) {
return to_route('shop.index')->withErrors(
['message' => __('This package is not giftable')],
);
}
$user = User::where('username', $request->input('receiver'))->first();
if (! $user) {
return to_route('shop.index')->withErrors(
['message' => __('Recipient not found')],
);
}
}
if ($package->give_rank && $user->rank >= $package->give_rank) {
$message = __('You are already this or a higher rank');
if ($user->username !== Auth::user()->username) {
$message = __('The recipient is already this or a higher rank');
}
return to_route('shop.index')->withErrors(
['message' => $message],
);
}
if (! $this->rconService->isConnected && $user->online === '1') {
return to_route('shop.index')->withErrors(
['message' => __('Please logout before purchasing a package')],
);
}
if (Auth::user()->website_balance < $package->price()) {
return to_route('shop.index')->withErrors(
['message' => __('You need to top-up your account with another $:amount to purchase this package', ['amount' => ($package->price() - Auth::user()->website_balance)])],
);
}
Auth::user()?->decrement('website_balance', $package->price());
$sendCurrency->execute($user, 'credits', $package->credits);
$sendCurrency->execute($user, 'duckets', $package->duckets);
$sendCurrency->execute($user, 'diamonds', $package->diamonds);
if ($package->give_rank) {
if ($this->rconService->isConnected) {
$this->rconService->setRank($user, $package->give_rank);
$this->rconService->disconnectUser($user);
} else {
$user->update([
'rank' => $package->give_rank,
]);
}
}
if ($package->badges) {
$this->giveBadges($user, $package->badges);
}
if ($package->furniture) {
$this->handleFurniture(json_decode($package->furniture, true));
}
$message = __('You have successfully purchased the package :name', ['name' => $package->name]);
if ($user->username !== Auth::user()->username) {
$message = __('You have successfully purchased the package :name for :username', ['name' => $package->name, 'username' => $user->username]);
}
return to_route('shop.index')->with('success', $message);
}
public function handleFurniture(array $furniture)
{
$sendFurniture = app(SendFurniture::class);
$sendFurniture->execute(Auth::user(), $furniture);
}
}
@@ -1,44 +0,0 @@
<?php
namespace App\Http\Controllers\Shop;
use App\Http\Controllers\Controller;
use App\Http\Requests\ShopVoucherFormRequest;
use App\Models\Shop\WebsiteShopVoucher;
class ShopVoucherController extends Controller
{
public function __invoke(ShopVoucherFormRequest $request)
{
$user = $request->user();
$voucher = WebsiteShopVoucher::where('code', $request->string('code'))->first();
if (is_null($voucher) || ($voucher->expires_at && $voucher->expires_at->lte(now()))) {
return back()->withErrors([
'message' => __('No active voucher with the given code was found'),
]);
}
if ($user->usedShopVouchers()->where('voucher_id', $voucher->id)->exists()) {
return back()->withErrors([
'message' => __('You can only use each shop voucher once'),
]);
}
$user->usedShopVouchers()->create([
'voucher_id' => $voucher->id,
]);
$user->increment('website_balance', $voucher->amount);
$voucher->increment('use_count');
if ($voucher->max_uses && $voucher->use_count >= $voucher->max_uses) {
$voucher->update([
'expires_at' => now(),
]);
}
return back()->with('success', __('Your balance has been increased by $:amount', ['amount' => $voucher->amount]));
}
}
@@ -1,69 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\AccountSettingsFormRequest;
use App\Services\RconService;
use App\Services\User\SessionService;
use App\Services\User\UserService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class AccountSettingsController extends Controller
{
public function __construct(private readonly SessionService $sessionService, private readonly UserService $userService, private readonly RconService $rconService) {}
public function edit(): View
{
return view('user.settings.account', [
'user' => Auth::user()->load('settings:allow_name_change'),
]);
}
public function sessionLogs(Request $request): View
{
$sessions = $this->sessionService->fetchSessionLogs($request);
return view('user.settings.session-logs', [
'logs' => $sessions,
]);
}
public function update(AccountSettingsFormRequest $request): RedirectResponse
{
$user = Auth::user();
if ($user === null) {
return back()->withErrors('User not found');
}
// $allowedNameChange = $user->settings?->allow_name_change && $user->username !== $request->input('username');
if (! $this->rconService->isConnected() && Auth::user()->online === '1') {
return back()->withErrors('You must be offline to change your account settings');
}
/** if ($allowedNameChange) {
$this->rconService->disconnectUser($user);
$this->userService->updateField($user, 'username', $request->input('username'));
} **/
if ($user->mail !== $request->input('mail')) {
$this->userService->updateField($user, 'mail', $request->input('mail'));
}
if ($user->motto !== $request->input('motto')) {
$this->rconService->setMotto($user, $request->input('motto'));
$this->userService->updateField($user, 'motto', $request->input('motto'));
}
return to_route('settings.account.show')->with('success', __('Your account settings has been updated'));
}
public function twoFactor(): View
{
return view('user.settings.two-factor');
}
}
@@ -1,23 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\User\Ban;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class BannedController extends Controller
{
public function __invoke(): View
{
$ipBan = Ban::where('ip', '=', request()->ip())
->where('ban_expire', '>', time())
->orderByDesc('id')
->first();
return view('banned', [
'ban' => $ipBan ?? Auth::user()->ban,
]);
}
}
@@ -1,78 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\PasswordResetToken;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Mail;
class ForgotPasswordController extends Controller
{
public function __invoke()
{
return view('auth.passwords.forget');
}
public function submitForgetPassword(Request $request)
{
$request->validate([
'mail' => ['required', 'email'],
]);
// Do not tell the user that this email does not exist to prevent possible attacks
if (User::where('mail', $request->mail)->exists()) {
$token = Str::uuid();
PasswordResetToken::create([
'email' => $request->mail,
'token' => $token,
]);
Mail::send('email.forgetPassword', ['token' => $token], function ($message) use ($request): void {
$message->to($request->mail);
$message->subject('Reset Password');
});
}
return back()->with('success', __('We have e-mailed your password reset link!'));
}
public function showResetPassword(Request $request, string $token)
{
$prt = PasswordResetToken::select('token', 'created_at')->where('token', $token)->first();
if ($prt === null) {
return to_route('forgot.password.get')->withErrors('message', __('This token has expired!'));
}
$tokenExpiration = \Illuminate\Support\Facades\Date::now()->subMinutes(config('habbo.password_reset_token_time'));
if ($prt->created_at->gte($tokenExpiration)) { // gte = greater than or equals
$prt->delete();
return to_route('forgot.password.get')->withErrors('message', __('This token has expired!'));
}
return view('auth.passwords.reset', [
'token' => $token,
]);
}
public function submitResetPassword(Request $request, string $token)
{
$request->validate([
'password' => ['required', 'min:8', 'confirmed'],
'password_confirmation' => ['required'],
]);
$prt = PasswordResetToken::select('email', 'token')->where('token', $token)->first();
if ($prt === null) {
return to_route('forgot.password.get')->withErrors('message', __('This token has expired!'));
}
$prt->user->changePassword($request->password);
$prt->delete();
return to_route('login')->with('success', __('Your password has been successfully reset!'));
}
}
@@ -1,54 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\GuestbookFormRequest;
use App\Models\User;
use App\Models\User\WebsiteUserGuestbook;
use Illuminate\Support\Facades\Auth;
class GuestbookController extends Controller
{
public function store(User $user, GuestbookFormRequest $request)
{
$this->validateGuestbookPost($user, $request);
$user->profileGuestbook()->create([
'user_id' => Auth::id(),
'message' => $request->input('message'),
]);
return back()->with('success', __('Your message has been posted.'));
}
public function destroy(User $user, WebsiteUserGuestbook $guestbook)
{
if ($guestbook->user_id !== Auth::id() && $guestbook->profile_id !== $user->id && Auth::user()->rank < (int) setting('min_staff_rank')) {
return back()->withErrors([
'message' => __('Do do not have permission to delete this message'),
]);
}
$guestbook->delete();
return back()->with('success', __('Your message has been deleted.'));
}
private function validateGuestbookPost(User $user, GuestbookFormRequest $request)
{
if ($user->id === $request->user()->id) {
return $this->redirectWithError(__('You cannot post a message on your own profile.'));
}
$maxAllowedPostCount = in_array(setting('max_guestbook_posts_per_profile'), ['', '0'], true) ? 3 : (int) setting('max_guestbook_posts_per_profile');
if ($user->profileGuestbook()->where('user_id', $request->user()->id)->count() >= $maxAllowedPostCount) {
return $this->redirectWithError(__('You have already posted :count messages on this profile.', ['count' => $maxAllowedPostCount]));
}
}
private function redirectWithError($message)
{
return back()->withErrors(['message' => $message]);
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\Articles\WebsiteArticle;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class MeController extends Controller
{
public function __invoke(): View
{
return view('user.me', [
'onlineFriends' => Auth::user()?->getOnlineFriends(),
'user' => Auth::user()?->load('permission:id,rank_name'),
'articles' => WebsiteArticle::whereHas('user')->with('user:id,username,look')->latest()->take(5)->get(),
]);
}
}
@@ -1,27 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\PasswordSettingsFormRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\View\View;
class PasswordSettingsController extends Controller
{
public function edit(): View
{
return view('user.settings.password');
}
public function update(PasswordSettingsFormRequest $request): RedirectResponse
{
Auth::user()->update([
'password' => Hash::make($request->input('password')),
]);
return to_route('settings.password.show')->with('success', __('Your password has been changed!'));
}
}
@@ -1,65 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\Game\Guild\GuildMember;
use App\Models\Game\Player\MessengerFriendship;
use App\Models\User;
class ProfileController extends Controller
{
public function __invoke(User $user)
{
$user = $this->loadUserRelations($user);
$friends = $this->getUserFriends($user->id);
$groups = $this->getUserGroups($user->id);
return view('user.profile', [
'user' => $user,
'friends' => $friends,
'groups' => $groups,
'guestbook' => $user->profileGuestbook()->with('user')->latest()->limit(5)->get(),
'photos' => $user->photos()->limit(3)->get(),
]);
}
private function loadUserRelations(User $user): User
{
return $user->load([
'badges' => function ($badges): void {
$badges->where('slot_id', '>', '0')
->orderBy('slot_id')
->take(5);
},
'rooms' => function ($rooms): void {
$rooms->select('id', 'owner_id', 'name', 'users')
->orderByDesc('users')
->orderBy('id');
},
]);
}
private function getUserFriends(int $userId)
{
return MessengerFriendship::select('user_two_id')
->where('user_one_id', '=', $userId)
->whereHas('user')
->with('user:id,username,look')
->inRandomOrder()
->take(12)
->get();
}
private function getUserGroups(int $userId)
{
return GuildMember::query()
->select(['guilds_members.id', 'guilds_members.guild_id', 'guilds_members.user_id', 'guilds.name', 'guilds.badge'])
->where('guilds_members.user_id', '=', $userId)
->join('guilds', 'guilds_members.guild_id', '=', 'guilds.id')
->inRandomOrder()
->take(6)
->get();
}
}
@@ -1,33 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Services\RconService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
class ReferralController extends Controller
{
public function __invoke(RconService $rcon): RedirectResponse
{
$user = Auth::user();
if (! $user->referrals || $user->referrals->referrals_total < setting('referrals_needed')) {
return back()->withErrors([
'message' => __('You do not have enough referrals to claim your reward'),
]);
}
// Decrease the total amount of referrals with the amount needed to claim reward
$user->referrals->decrement('referrals_total', setting('referrals_needed'));
$rcon->giveDiamonds($user, setting('referral_reward_amount'));
// Log the claim
$user->claimedReferralLog()->create([
'ip_address' => request()->ip(),
]);
return back()->with('success', __('Woah! You have successfully claimed your reward - Keep up the good work!'));
}
}
@@ -1,42 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Laravel\Fortify\Actions\DisableTwoFactorAuthentication;
use Laravel\Fortify\Actions\EnableTwoFactorAuthentication;
class TwoFactorAuthenticationController extends Controller
{
public function index(): View
{
return view('user.settings.two-factor');
}
public function store(Request $request, EnableTwoFactorAuthentication $enable): RedirectResponse
{
$enable($request->user());
return to_route('settings.two-factor')->with('success', __('Two-factor authentication has been enabled. Please scan the QR code to continue.'));
}
public function verify(Request $request): RedirectResponse
{
$confirmed = $request->user()->confirmTwoFactorAuthentication($request->input('code'));
if (! $confirmed) {
return back()->withErrors('Invalid Two Factor Authentication code');
}
return to_route('settings.two-factor')->with('success', __('Two-factor authentication has been confirmed.'));
}
public function destroy(Request $request, DisableTwoFactorAuthentication $disable): RedirectResponse
{
$disable($request->user());
return to_route('settings.two-factor')->with('success', __('Two-factor authentication has been disabled.'));
}
}
@@ -1,18 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\User;
class UserReferralController extends Controller
{
public function __invoke(string $referralCode)
{
User::where('referral_code', '=', $referralCode)->firstOrFail();
return view('auth.register', [
'referral_code' => $referralCode,
]);
}
}