You've already forked Epicnabbo-Catalogus-Updated-Daily
🆙 Forget data back 🆙
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<?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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?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!'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?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]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?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),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?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'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?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!'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?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;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?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(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?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!'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?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!'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?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(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?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(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?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!']);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?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),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?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')],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?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');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?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!'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?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]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?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!'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?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!'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?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.'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user