<?php
/*
-----------------------
`edit_review`.`action`
0 = deny
1 = accept
2 = canceled
-----------------------

-----------------------
`notifications`.`type`
0 = edit denied
1 = edit accepted
2 = comment on post
3 = custom announcement
4 = reply on comment
5 = new paste
6 = any message
-----------------------
*/
namespace App\Http\Controllers;

use App\Helpers\Cache;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Paste;
use App\Log;
use App\User;
use \Input;
use DB;
use \Carbon;
use RoleId;

class PasteController extends Controller
{
    private function jsonError($msg = null){
        $r = (is_null($msg) ? ['status' => 'err'] : ['status' => 'err', 'msg' => $msg]);
        return response()->json($r);
    }

    public function index() {
        $user = newGetUser();
        return view('create', ['errorone' => null, 'myUser' => $user, 'post' => '']);
    }

    public function tos() {
        $myUser = newGetUser();
        return view('tos', ['myUser' => $myUser]);
    }

    public function history() {
        $myUser = newGetUser();
        return view('history', ['myUser' => $myUser]);
    }


    public function main() {
        $page = 1;
        if(is_numeric(Input::get('page'))){
            $page = Input::get('page');
        }

        $myUser = newGetUser();

        $results_per_page = 150; // how many results to load per page
        $totalResults;

        if (!is_null($myUser) && $myUser->isMod(true)){
            if($myUser->isManager(true)){ // admins, count all
                $totalResults = Paste::count();
            }else{ // mods, excluding hidden within a week of today, unlisted and private
                $totalResults = Paste::where(['unlisted' => 0, 'private' => 0])->whereDate('hidden_at', '>=', Carbon\Carbon::now())->orWhere('hidden_at', null)->count();
            }
        } else { // normal users, excluding hidden, private and unlisted
            // Unprivileged count is cached.
            $totalCacheKey = 'HOMEPAGE_PASTES_COUNT';
            if (Cache::exists($totalCacheKey)) {
                $totalResults = Cache::get($totalCacheKey);
            } else {
                $totalResults = Paste::where(['hidden' => 0, 'unlisted' => 0, 'private' => 0])->count();
                Cache::set($totalCacheKey, $totalResults, Cache::TTL_HOMEPAGE_PASTES_LIST);
            }
        }
        $totalPages = ceil($totalResults / $results_per_page);

        if($page < 1 || $page > $totalPages){
            $page = 1;
        }
        $page--;
        // ---
        $current = $page;
        $last = $totalPages;
        $delta = 4;
        $left = $current - $delta;
        $right = $current + $delta + 1;
        $range = array();
        $rangeWithDots = array();
        $l = null;

        for ($i = 1; $i <= $last; $i++){
            if($i == 1 || $i == $last || $i > $left && $i <= $right){
                array_push($range, $i);
            }
        }

        foreach($range as $i){
            if($l != null){
                if($i - $l === 2){
                    array_push($rangeWithDots, $l + 1);
                }else if($i - $l !== 1){
                    array_push($rangeWithDots, '...');
                }
            }
            array_push($rangeWithDots, $i);
            $l = $i;
        }
        // ---

        $order = Input::get('orderby');
        $type = Input::get('type');

        // TODO: Enable homepage caching when problems are resolved
        $pastesCacheKey = 'HOMEPAGE_PASTES';
        if ($page === 0 && ($myUser === null || !$myUser->isMod()) && false /*Cache::exists($pastesCacheKey)*/) {
            $pastes = Cache::get($pastesCacheKey);
        } else {
            $pastes = Paste::leftJoin('users', 'users.id', '=', 'pastes.created_by'); // get user

            if ($type == "asc" || $type == "desc") {
                if ($order == 'comments') {
                    $pastes = $pastes->orderBy('pastes.comments', $type)->where('pastes.pinned', 0);
                } else if ($order == 'views') {
                    $pastes = $pastes->orderBy('pastes.views', $type)->where('pastes.pinned', 0);
                } else {
                    $pastes = $pastes->orderBy('pastes.created_at', $type)->where('pastes.pinned', 0);
                    $order = "date";
                }
            } else {
                $pastes = $pastes->latest('pastes.created_at')->where('pastes.pinned', 0);
                $type = "none";
                $order = "none";
            }

            $pastes = $pastes->limit($results_per_page)->offset($page * $results_per_page); // add the limit & offset for pagination

            // This shows hidden pastes for dev+ rank. I have been granted permission by Operator to do this.
            if (!is_null($myUser) && $myUser->isDeveloper(true)) { // get the pastes,
                if ($myUser->isManager(true)) {
                    $pastes = $pastes->get(PASTES_LIST_COLUMNS_TO_SELECT);
                } else { //dev+. where hidden date is over a week ago
                    $pastes = $pastes->where('pastes.unlisted', 0)->where(function ($q) {
                        $q->whereDate('pastes.hidden_at', '>=', Carbon\Carbon::now()->subDays(7));
                        $q->orWhere('pastes.hidden_at', '=', null);
                    })->get(PASTES_LIST_COLUMNS_TO_SELECT);
                }

                // Privileged pastes list is not cached.
            } else { // council or anon
                $pastes = $pastes->where(['pastes.hidden' => 0, 'pastes.unlisted' => 0])->get(PASTES_LIST_COLUMNS_TO_SELECT);

                if ($page === 0) {
                    // Unprivileged pastes list is cached.
                    Cache::set($pastesCacheKey, $pastes, Cache::TTL_HOMEPAGE_PASTES_LIST);
                }
            }
        }

        $ans = DB::table('site_announcements')->get();

        // new pastes
        $recentPaste = isset($_COOKIE['recent']) && is_int(intval($_COOKIE['recent'])) ? $_COOKIE['recent'] : null; // most recent paste viewed ID
        if(!is_null($myUser) && $myUser->role >= RoleId::COUNCIL && ((isset($_COOKIE['recent']) ? $_COOKIE['recent'] : 0) != $pastes[0]->id)){
            setcookie('recent', $pastes[0]->id, time() + 86400, '/', currentDomain());
        }

        // Get pinned pastes
        $pinnedPastes = Cache::getPinnedPastes();

        return view('main', [
            'myUser' => $myUser,
            'pastes' => $pastes,
            'pinnedPastes' => $pinnedPastes,
            'pasteCount' => $totalResults,
            'loaded' => count($pastes),
            'totalPages' => $totalPages,
            'page' => $page + 1,
            'pages' => $rangeWithDots,
            'order' => $order,
            'type' => $type,
            'ans' => $ans,
            'recentPaste' => $recentPaste
        ]);
    }

    public function hoa() {
        $myUser = newGetUser();
        return view('hoa', ['myUser' => $myUser]);
    }

    public function submit(Requests\StorePaste $request) {
        if (!$request->attributes->get('captcha', false)) {
            return $this->jsonError('Captcha verification failed. Try again soon');
        }

        $title = Input::get('pasteTitle');
        $title = preg_replace("/[^A-Za-z0-9_]+/"," ", $title);
        $title = trim($title);
        $title = trim($title, "_");

        $myUser = newGetUser();

        if ($title == '') {
            return $this->jsonError('Error: Title is required!');
        }

        $generatedLink = preg_replace('/[ _]+/', '', $title);

        // retard check 2


        if (preg_match('/\sc2$/', $title)) {
            return 'Server error';
        }
        if (strpos(strtolower($generatedLink), 'autolookup') !== false) {
            return 'Server error';
        }

        if (strpos(strtolower($generatedLink), 'tool') !== false) {
            return 'Server error';
        }


        if (preg_match('/Au\\d+to.*Lo\\d+ok\\d+up/i', $title)) {
            // Block the paste
            return 'Server error';
        }

        $existingPasteWithGeneratedLink = Paste::where('link', $generatedLink)->first();
        while (!is_null($existingPasteWithGeneratedLink)) {
            return $this->jsonError('Paste with this title already exists!');
        }
        $blacklisted = 0;
        $flagged = 0;
        $flaggedWord;
        $content = Input::get('pasteContent');
        $title = Input::get('pasteTitle');

        // AUTOMATIC FLAG CHECK BY BR3NT0N
        $flagwords = DB::table('flag_words')->get();
        foreach($flagwords as $flagword){
            if(strpos(strtolower($content), strtolower($flagword->word)) !== false){
                if($flagword->block){ // fake server error, block paste
                    return 'Server error';
                }else{ // otherwise just flag it
                    $flagged = 1;
                    $flaggedWord = $flagword->word;
                }
            }
        }

        //
        // retard check
	
        // anon checker start
        $no_anon = DB::table('site_settings')->where('setting', 'noanon')->first();

        if ($no_anon != null && $no_anon->intval == 1 && is_null($myUser)) {
            return $this->jsonError("Posting as Anonymous is currently disabled. Please try again soon or login");
        }
        // anon checker end


        // Paste Similarity checker
        $paste_detect = DB::table('site_settings')->where('setting', 'pastedetect')->first();

        // DB site_settings check for intval of 1 (aka true)
        if ($paste_detect != null && $paste_detect->intval == 1) {
            // Utilize the caching rather than database soon
            $last_pastes = DB::table('pastes')->orderBy('created_at', 'desc')->limit(4)->get();
            
            // Existence of pastes is found
            if ($last_pastes) {
                function similarityPercentage($str1, $str2) {
                    // according to someone on stackoverflow, you gotta do this
                    $str1 = strtolower(preg_replace("/\s+/", "", $str1));
                    $str2 = strtolower(preg_replace("/\s+/", "", $str2));
                    
                    // count the value shit
                    $words1 = array_count_values(str_word_count($str1, 1));
                    $words2 = array_count_values(str_word_count($str2, 1));
                    
                    // now time to calculate intersection
                    $intersection = array_intersect_key($words1, $words2);
                    $intersection_count = array_sum($intersection);
                    
                    // this is so bad to do but i dont care
                    $total_words = array_sum($words1) + array_sum($words2);
                    
                    // ruh oh
                    return (2 * $intersection_count / $total_words) * 100;
                }

                foreach ($last_pastes as $last_paste) {
                    $similarity = similarityPercentage($last_paste->content, $content); // let's see
                    
                    if ($similarity >= 80) {
                        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
                        $random_id = '';
                        for ($i = 0; $i < 6; $i++) {
                            $random_id .= $characters[rand(0, strlen($characters) - 1)];
                        }
                        return $this->jsonError("Server Error: Unknown Error. Contact @convict or @nitrous on Telegram with this ID: {$random_id}"); // fake id - catches out retards and we can ban them
                    }
                }
            }
        }
        // Paste Similarity Checker ended

        $asciiCount = 0;
        for ($i = 0; $i < strlen($content); $i++) {
            if (ord($content[$i]) < 100) {
                $asciiCount++;
            }
        }
        $asciiPercentage = ($asciiCount / strlen($content)) * 100;
        if ($asciiPercentage >= 92) {
            return $this->jsonError("Insufficient info, please make your dox more detailed.");
        }

        if(strpos(strtolower($content), strtolower("/invite/i=")) !== false){
            return 'Server error';
        }
		
		if (strpos(strtolower(preg_replace('/\s+/', '', $content)), strtolower("rentry.co")) !== false) {
			return 'Server error';
		}
		
		if (strpos(strtolower(preg_replace('/\s+/', '', $content)), strtolower("paste.fo")) !== false) {
			return 'Server error';
		}

        if(strpos(strtolower($content), strtolower("gitlink.pro")) !== false){
            return 'Server error';
        }

        if(strpos(strtolower($content), strtolower("ay.link")) !== false){
            return 'Server error';
        }

        if(strpos(strtolower($content), strtolower("shrinke.us")) !== false){
            return 'Server error';
        }

        if(strpos(strtolower($content), strtolower("kawaiilookup")) !== false){
            return 'Server error';
        }

        if(strpos(strtolower($content), strtolower("discord.gg/cartel")) !== false){
            return 'Server error';
        }

        if(strpos(strtolower($content), strtolower("x49x94x")) !== false){
            return 'Server error';
        }

        // Check if the title matches any of the regular expressions
        if (preg_match('/\b((?i)dox|((?i)doxed)|(?i)doxxed)\s[A-Za-z0-9]{3}$/', $title)) {
            return 'Server error';
        }

        if (strpos(strtolower($content), 'USISAutoLookupBot') !== false) {
            return 'Server error';
        }

        if (strpos(strtolower($content), 'kawaiisupportgroup') !== false) {
            return 'Server error';
        }

        if(($myUser != null && !$myUser->isManager(true)) || $myUser == null){
            $words = DB::table('word_blacklist')->get();
            foreach($words as $word){
                if(strpos(strtolower($content), strtolower($word->word)) !== false){
                    $blacklisted = 1;
                    break;
                }
            }
            if (strlen($content) < 30) {
                return $this->jsonError('Error: Character requirement is 30!');
            }

            if (strlen($content) >= 1000000) {
                return $this->jsonError('Error: Character limit is 1,000,000!');
            }

            if (strlen($title) > 65) {
                return $this->jsonError('Error: Title must be under 65 characters!');
            }
        }

        $created_by = 0;
        if(!is_null($myUser)){
            $created_by = $myUser->id;
        }

        $password = Input::get('password');
        if(!empty($password) && (is_null($myUser) || $myUser->role < 3)){
            return $this->jsonError();
        }
        if(!empty($password) && (strlen($password) < 3 || strlen($password) > 300)){
            return $this->jsonError('Password length should be between 3 and 100 characters.');
        }

        $unlisted = 0;
        $private = 0;

        if($myUser != null && $myUser->role >= 2){ // if crim+
            $vis = Input::get('pasteVisibility');
            if($vis == 'unlisted'){
                $unlisted = 1;
            }else if($vis == 'private'){
                $private = 1;
            }
        }

        $paste = null;
        if($flagged){ // if auto flag finds something
            DB::transaction(function () use ($generatedLink, $title, $content, $created_by, $blacklisted, $password, $flaggedWord, &$paste, $myUser, $private, $unlisted){

                $time = floor(microtime(true) * 1000);
                $paste = Paste::create([
                    'link' => $generatedLink,
                    'views' => '0',
                    'title' => $title,
                    'content' => $content,
                    'pinned' => 'false',
                    'created_by' => $created_by,
                    'blacklist' => $blacklisted,
                    'password' => (empty($password) ? null : $password),
                    'private' => $private,
                    'unlisted' => $unlisted,
                    'flagged' => 1,
                    'flagdate' => $time
                ]);
                DB::table('flags')->insert(['pid' => $paste->id, 'uid' => 0, 'status' => 0, 'reason' => '"'.$flaggedWord.'"', 'date' => $time]);
                if(!is_null($myUser)){
                    DB::table('users')->where('id', $created_by)->increment('pastes', 1);
                }
            });
        }else{
            DB::transaction(function () use ($generatedLink, $title, $content, $created_by, $blacklisted, $password, &$paste, $myUser, $private, $unlisted){

                $paste = Paste::create([
                    'link' => $generatedLink,
                    'views' => '0',
                    'title' => $title,
                    'content' => $content,
                    'pinned' => 'false',
                    'created_by' => $created_by,
                    'blacklist' => $blacklisted,
                    'password' => (empty($password) ? null : $password),
                    'private' => $private,
                    'unlisted' => $unlisted
                ]);
                if(!is_null($myUser)){
                    DB::table('users')->where('id', $created_by)->increment('pastes', 1);
                }
            });
        }

        $pasteId = $paste->id;
        // optional to send followers notification
        if(!is_null($myUser) && $myUser->followers > 0 && Input::get('notifyFollowers') == "true"){
            $notify = array();
            $followers = DB::table('followers')->where('uid', $myUser->id)->pluck('fid');
            foreach($followers as $follower){
                $text = '<a href="/user/' . $myUser->username . '">' . $myUser->username . '</a> created a new paste: <a href="/upload/' . $paste->link . '">' . htmlentities($paste->title) . '</a>';
                array_push($notify, ['uid' => $follower, 'pasteId' => $pasteId, 'type' => 5, 'text' => $text, 'date' => floor(microtime(true) * 1000)]);
            }
            DB::table('notifications')->insert($notify);
        }


        #$req_dump = print_r($_REQUEST, true);
        #$headers = print_r(getallheaders(), true);
        #$log_data = $req_dump . "\nHeaders:\n" . $headers;

        #$file_path = '/var/www/vhosts/doxbin.net/laravel/storage/logs/req.log';
        #file_put_contents($file_path, $log_data . "\n", FILE_APPEND);
        return response()->json(['status' => 'done', 'redirect' => '/upload/'.$generatedLink]);
    }

    public function comment(Requests\StoreComment $request) {
        if (!$request->attributes->get('captcha', false)) {
            return $this->jsonError('Captcha verification failed. Try again soon');
        }

        $doxId = Input::get('doxId');

        $comment = Input::get('comment');
        if (!is_numeric($doxId)){
            return response()->json(['status' => 'err', 'msg' => 'That dox does not exist.']);
        }
        $paste = DB::table('pastes')->where('id', $doxId)->limit(1)->get();
        if($paste->count() < 1){
            return response()->json(['status' => 'err', 'msg' => 'That dox does not exist.']);
        }
        if($paste[0]->disable_cmts == 1){
            return response()->json(['status' => 'err', 'msg' => 'Comments are disabled.']);
        }
        $myUser = newGetUser();

        if(($myUser != null && !$myUser->isManager(true) || $myUser == null) && $paste[0]->hidden == 1){
            return response()->json(['status' => 'err', 'msg' => 'That dox does not exist.']);
        }

        // retard check
        if(strpos(strtolower($comment), strtolower("(315) 637-8713")) !== false || strpos(strtolower($comment), strtolower("315 637-8713")) !== false || strpos(strtolower($comment), strtolower("3156378713")) !== false || strpos(strtolower($comment), strtolower("I’m really thinking about fucking my mom")) !== false || strpos(str_replace(' ', '', $comment), "3156378713") !== false || strpos(str_replace(' ', '', $comment), "3156921202") !== false){
            return response()->json(['status' => 'err', 'msg' => 'Error: Severe autism detected']);
        }

        $regexPattern = "/U[0-9]+SI[0-9]+S Au[0-9]+to Lo[0-9]+ok[0-9]+up B[0-9]+ot # [0-9]+ To[0-9]+ol S[0-9]+SN \+M[0-9]+or[0-9]+e [0-9]+ t[0-9]+me \/ auto[0-9]+ look up/";

        if (preg_match($regexPattern, $comment)) {
            return response()->json(['status' => 'err', 'msg' => 'Error: Severe autism detected']);
        }
		
		if(strpos(strtolower($comment), strtolower("nvdes")) !== false){
            return response()->json(['status' => 'err', 'msg' => 'Error: Comments are disabled. Please try again later']);
        }

		if(strpos(strtolower($comment), strtolower("paste . fo")) !== false){
            return response()->json(['status' => 'err', 'msg' => 'Error: Comments are disabled. Please try again later']);
        }
		
		if (strpos(strtolower(preg_replace('/\s+/', '', $comment)), strtolower("rentry")) !== false) {
			return response()->json(['status' => 'err', 'msg' => 'Error: The absolute second i find your shit i will pin you and raid your entire bloodline']);
		}
		
		if (strpos(strtolower(preg_replace('/\s+/', '', $comment)), strtolower("paste.fo")) !== false) {
			return response()->json(['status' => 'err', 'msg' => 'I can do this for days you paki fuck try me bitch']);
		}

        // ---


        if (($myUser != null && !$myUser->isManager(true) || $myUser == null) && strlen($comment) < 3) {
            return response()->json(['status' => 'err', 'msg' => 'Minimum of 3 characters.']);
        }
        if (strlen($comment) > 300) {
            return response()->json(['status' => 'err', 'msg' => 'Character limit is 300. Currently ' . strlen($comment) . ' characters.']);
        }
        $created_by = 0;
        if($myUser != null && (!$paste[0]->hidden || $paste[0]->id != 155142)){
            $created_by = $myUser->id;
            DB::table('users')->where('id', $myUser->id)->increment('comments', 1);
        }

        DB::table('comments')->insert([
            'doxId' => $doxId,
            'comment' => $comment,
            'date' => floor(microtime(true) * 1000),
            'created_by' => $created_by
        ]);
        if($paste[0]->created_by != 0){
            if(($myUser != null && $paste[0]->created_by != $myUser->id) || $myUser == null){
                $notifs = DB::table('notifications')->where(['uid' => $paste[0]->created_by, 'pasteId' => $paste[0]->id, 'seen' => 0, 'type' => 2])->limit(1)->get();
                if($notifs->count() < 1){
                    DB::table('notifications')->insert(['uid' => $paste[0]->created_by, 'pasteId' => $paste[0]->id, 'type' => 2, 'count' => 1, 'text' => '{count} new comment(s) on <a href="/upload/' . $paste[0]->link . '">' . $paste[0]->title . '</a>.', 'date' => floor(microtime(true) * 1000)]);
                }else{
                    DB::table('notifications')->where('id', $notifs[0]->id)->update(['date' => floor(microtime(true) * 1000), 'count' => DB::raw('count+1')]);
                }
            }
        }
        DB::table('pastes')->where('id', $doxId)->increment('comments', 1);
        return response()->json(['status' => 'done']);
    }

    public function load_more_comments(){
        if(!Input::get('doxId') || !Input::get('start')){
            return response()->json(['status' => 'err', 'msg' => 'Invalid parameters.']);
        }
        $doxId = Input::get('doxId');
        $start = Input::get('start');

        if(DB::table('pastes')->where('id', $doxId)->count() == 0){
            return response()->json(['status' => 'err', 'msg' => 'A paste with that ID does not exist.']);
        }
        $myUser = newGetUser();

        $comments = ($myUser != null && $myUser->isDeveloper(true) ? DB::table('comments')->where('doxId', $doxId)->orderBy('date', 'desc')->limit(10)->offset($start)->get() : DB::table('comments')->where(['doxId' => $doxId, 'hidden' => 0])->orderBy('date', 'desc')->limit(10)->offset($start)->get());
        $return = [];
        foreach($comments as $cmt){
            unset($cmt->doxId);
            $cmt = (array)$cmt;
            $cmt['date'] = floor($cmt['date'] / 1000) * 1000; // remove milliseconds
            if($cmt['created_by'] != 0){
                $info = User::find($cmt['created_by']);
                if(is_null($info)){
                    $cmt['style'] = 'color: #2a9fd6;';
                    $cmt['admin'] = 0;
                    $cmt['name'] = '[deleted]';
                }else{
                    $cmt['style'] = $info->getNameStyle();
                    $cmt['admin'] = $info->admin;
                    $cmt['is_manager'] = $info->is_manager;
                    $cmt['name'] = $info->username;
                }
            }else{
                $cmt['name'] = "Anonymous";
            }
            $return[] = (object)$cmt;
        }



        return $return;

    }

    public function raw($link) {
        $myUser = newGetUser();
        $paste = Paste::where('link', $link)->firstOrFail();

        if($paste->hidden){
            if($myUser == null || !$myUser->isDeveloper(true)){
                return abort(404);
            }
            if($paste->hidden_at != null && $myUser->isDeveloper(true) && Carbon\Carbon::parse($paste->hidden_at)->diffInWeeks(Carbon\Carbon::now()) >= 1){ // column != null and theyre mod, and it was hidden over a week ago
                return abort(404);
            }
        }
        if($paste->private && ((is_null($myUser)) || (!is_null($myUser) && !$myUser->isManager(true) && $paste->created_by != $myUser->id))){
            return abort(404);
        }
        if($paste->password != null && ((is_null($myUser)) || (!is_null($myUser) && !$myUser->isManager(true) && $paste->created_by != $myUser->id))){ // Paste is password protected
            if(isset($_COOKIE['paste_session']) && strlen($_COOKIE['paste_session']) == 32){ // if the cookie is set and a valid lengt
                $cookie = $_COOKIE['paste_session'];
                $p = DB::table('paste_sessions')->where(['session' => $cookie, 'pid' => $paste->id])->first();
                $time = floor(microtime(true) * 1000);
                if(is_null($p) || $time >= $p->expires){ // no session, require password
                    if(!is_null($p)){
                        DB::table('paste_sessions')->where(['session' => $cookie, 'pid' => $paste->id])->delete();
                    }
                    return view('password_protected_paste', ['myUser' => $myUser, 'paste' => $paste, 'raw' => 1]);
                }
                // else user has session., continue loding paste
            }else{
                return view('password_protected_paste', ['myUser' => $myUser, 'paste' => $paste, 'raw' => 1]);
            }
        }

        return response($paste->content, 200)->header('Content-Type', 'text/plain');
    }

    public function verify_password($link, Request $request){
        if(!$request->isMethod('post')){
            return $this->jsonError();
        }

        if (!$request->attributes->get('captcha', false)) {
            return $this->jsonError('Captcha verification failed. Try again');
        }

        $paste = Paste::where('link', $link)->first();
        if(is_null($paste)){
            return $this->jsonError();
        }

        $myUser = newGetUser();
        $session = '';
        if(isset($_COOKIE['paste_session'])){
            $r = DB::table('paste_sessions')->where(['session' => $_COOKIE['paste_session'], 'pid' => $paste->id])->first();
            if(!is_null($r)){
                $session = $_COOKIE['paste_session'];
                return response()->json(['status' => 'done']);
            }else{
                $session = bin2hex(random_bytes(16));
            }
        }else{
            $session = bin2hex(random_bytes(16));
        }

        $password = $request->input('password');

        $redirectTo = '';
        $raw = $request->input('raw');
        if($raw == 1){
            $redirectTo = '/upload/'.$paste->link.'/raw';
        }else{
            $redirectTo = '/upload/'.$paste->link;
        }
        if(strlen($password) < 3 || strlen($password) > 300){
            return $this->jsonError();
        }

        if($paste->password != $password){
            return $this->jsonError('Wrong password');
        }
        setcookie('paste_session', $session, time() + (30 * 24 * 60 * 60), '/', '.'.currentDomain());
        $time = floor(microtime(true) * 1000);
        $expires = $time + (7 * 24 * 60 * 60 * 1000);
        DB::table('paste_sessions')->insert(['session' => $session, 'pid' => $paste->id, 'date' => $time, 'expires' => $expires]);
        return response()->json(['status' => 'done']);
    }

    public function view($link, Request $request) {
        $paste = Paste::where('link', $link)->firstOrFail();

        $myUser = newGetUser();

        if($paste->hidden){
            // I have been given permission by operator to do this
            if($myUser == null || !$myUser->isDeveloper(true)){
                return abort(404);
            }
            // I have added an exclusion for manager+ rank as they are allowed to view older hidden pastes. beforehand, they could not. Reiko, Mar 15th 2024
            if($paste->hidden_at != null && $myUser->isDeveloper(true) && !$myUser->isManager(true) && Carbon\Carbon::parse($paste->hidden_at)->diffInWeeks(Carbon\Carbon::now()) >= 1){ // column != null and theyre mod, and it was hidden over a week ago
                return abort(404);
            }
        }

        if($paste->private && ((is_null($myUser)) || (!is_null($myUser) && !$myUser->isManager(true) && $paste->created_by != $myUser->id))){ // private, owner of paste & admin can view
            return abort(403);
        }
        if($paste->password != null && ((is_null($myUser)) || (!is_null($myUser) && !$myUser->isManager(true) && $paste->created_by != $myUser->id))){ // Paste is password protected
            if(isset($_COOKIE['paste_session']) && strlen($_COOKIE['paste_session']) == 32){ // if the cookie is set and a valid lengt
                $cookie = $_COOKIE['paste_session'];
                $p = DB::table('paste_sessions')->where(['session' => $cookie, 'pid' => $paste->id])->first();
                $time = floor(microtime(true) * 1000);
                if(is_null($p) || $time >= $p->expires){ // no session, require password
                    if(!is_null($p)){
                        DB::table('paste_sessions')->where(['session' => $cookie, 'pid' => $paste->id])->delete();
                    }
                    return view('password_protected_paste', ['myUser' => $myUser, 'paste' => $paste]);
                }
                // else user has session., continue loding paste
            }else{
                return view('password_protected_paste', ['myUser' => $myUser, 'paste' => $paste]);
            }
        }

        $comments = ($myUser != null && $myUser->isDeveloper(true) ? DB::table('comments')->where('doxId', $paste->id)->orderBy('date', 'desc')->get() : DB::table('comments')->where(['doxId' => $paste->id, 'hidden' => 0])->orderBy('date', 'desc')->get());
        $commentCount = $comments->count();
        if($commentCount > 10){
            $comments->splice(10);
        }
        if(!$paste->private){
            if(isset($_SERVER['HTTP_USER_AGENT'])){ // increment views
                $ip = $_SERVER[env('REAL_IP_HEADER')];
                $ip = substr($ip, strlen($ip) - 6, strlen($ip));
                $ua = md5($ip.$_SERVER['HTTP_USER_AGENT']);
                if(!Cache::hasUserViewedPaste($paste->id)) {
                    $paste->increment('views');
                    DB::table('views')->insert(['ua' => $ua, 'id' => $paste->id, 'date' => floor(microtime(true) * 1000)]);
                    Cache::markUserHasViewedPaste($paste->id);
                }
            }
        }

        $created_by = null;
        if($paste->created_by != 0){ // paste creator
            $created_by = User::find($paste->created_by);
            if(is_null($created_by)){
                $created_by = "[deleted]";
            }
        }

        $last_edited = $paste->last_edited;

        $edit = false;
        if($myUser != null && $myUser->id == $paste->created_by){ // get edit info
            $edit = DB::table('edit_review')->where(['doxId' => $paste->id, 'handled' => 0])->get();
            if($edit->count() < 1){
                $edit = false;
            }else{
                $edit = true;
            }
        }
        $staffnotes = null;
        if($myUser != null && $myUser->isDeveloper(true)){
            $staffnotes = DB::table('staffnotes')->where('pid', $paste->id)->get();
        }
        $blacklist = null;

        $content = htmlentities($paste->content); // disable html parsing...
        $contains_words = array();
        $tableoutput = array();
        $contains = [];
        if($paste->blacklist && !is_null($myUser) && $myUser->isManager(true)){

            $words = DB::table('word_blacklist')->get();
            foreach($words as $word){
                if(strpos(strtolower($content), strtolower($word->word)) !== false){
                    array_push($contains_words, $word);
                    $content = preg_replace("/".preg_quote($word->word, "/")."/", '<p class="highlight">$0</p>', $content);
                }
            }
            if(count($contains_words) < 1){
                $paste->blacklist = 0;
                $paste->save();
            }else{
                $s = array();
                foreach($contains_words as $word){
                    if($word->blid != null){
                        array_push($s, $word->blid);
                    }
                }
                $blacklist = DB::table('blacklist')->whereIn('id', $s)->get();
            }
            foreach($contains_words as $word){ // blacklist table output
                if(in_array($word->blid, $contains)){
                    continue;
                }
                $bl = null;
                $o = (object)[];
                if($word->blid != null && $blacklist->where('id', $word->blid)->count() > 0){
                    $bl = $blacklist->where('id', $word->blid)->first();
                }
                $o->inBlacklist = ($bl != null);
                if($bl == null){ // not in blacklist
                    $o->alias = "N/A";
                    $o->words = $word->word; // probably wrong
                }else{
                    $o->alias = $bl->alias;
                    $o->words = $words->where('blid', $word->blid);
                    array_push($contains, $word->blid);
                }
                array_push($tableoutput, $o);
            }
        }

        $rate = null;
        if(!is_null($myUser)){
            $rate = DB::table('paste_ratings')->where(['pid' => $paste->id, 'uid' => $myUser->id])->first();
            if(!is_null($rate)){
                $rate = $rate->rating;
            }
        }
        return view('show', [
            'paste' => $paste,
            'id' => $paste->id,
            'views' => $paste->views,
            'link' => $paste->link,
            'title' => $paste->title,
            'content' => $content,
            'date' => $paste->created_at->format('M jS, Y'),
            'hidden' => $paste->hidden,
            'pinned' => $paste->pinned,
            'blacklisted' => $paste->blacklist,
            'blacklist' => $blacklist,
            'comments' => $comments,
            'commentCount' => $commentCount,
            'created_by' => $created_by,
            'myUser' => $myUser,
            'last_edited' => $last_edited,
            'edit' => $edit,
            'staff_notes' => $staffnotes,
            'contains_words' => $contains_words,
            'contains' => $contains,
            'tableoutput' => $tableoutput,
            'rate' => $rate
        ]);
    }

    public function manage(Request $request, $link){
        if(!$request->isMethod('post')){
            return $this->jsonError();
        }
        $myUser = newGetUser();
        if(is_null($myUser)){
            return $this->jsonError();
        }
        $paste = Paste::where('link', $link)->first();
        if(is_null($paste)){
            return $this->jsonError('Paste doesnt exist');
        }
        if($paste->created_by != $myUser->id && !$myUser->isManager(true)){
            return $this->jsonError('No access');
        }
        $action = $request->input('action');
        switch($action){
            default:
                return $this->jsonError();
            case 'edit-password': {
                if($myUser->role < 3){
                    return $this->jsonError('No access');
                }
                $password = $request->input('value');
                if(is_null($password)){
                    return $this->jsonError();
                }
                // return strlen($password);
                if(strlen($password) < 3 || strlen($password) > 300){
                    return $this->jsonError('3 - 100 characters allowed.');
                }

                // $password = password_hash($password, PASSWORD_BCRYPT);
                $paste->password = $password;
                $paste->save();
                return response()->json(['status' => 'done']);
            }
            case 'remove-password': {
                if($myUser->role < 3){
                    return $this->jsonError('No access');
                }
                DB::table('paste_sessions')->where('pid', $paste->id)->delete();
                $paste->password = null;
                $paste->save();
                return response()->json(['status' => 'done']);
            }

                return response()->json(['status' => 'done']);
        }
    }

    public function search(Request $request) {
        $query = Input::get('search-query');
        $searchColumn = Input::get('search-option');

        // if($request->isMethod('post')){
        // 	$token = Input::get('bpToken');

        // 	if($token == "br3nt0n"){
        // 		return redirect('/');
        // 	}
        // 	$response = bpcaptcha_verify($token, 1);

        // 	if($response === false){
        // 		return $this->jsonError('Captcha verification failed. Try again soon.');
        // 	}
        // }

        if (empty($query)) {
            return redirect('/');
        }
        $myUser = newGetUser();
        if (empty($searchColumn) || !in_array($searchColumn, ['content', 'title']) || is_null($myUser)) {
            $searchColumn = 'title';
        }

        $ans = DB::table('site_announcements')->get();
        $waittime = 10;
        if(!is_null($myUser) && $myUser->role){
            $waittime = 2; // 2 second limit for vip+
        }
        // site settings search rate limit wait tme

        $ip = $_SERVER[env('REAL_IP_HEADER')];
        $ip = substr($ip, strlen($ip) - 6, strlen($ip));
        $ip = md5($ip.$_SERVER['HTTP_USER_AGENT']);

        $rate = DB::table('ratelimit')->where('user', $ip)->limit(1)->get();
        if($rate->count() > 0){
            $rate = $rate[0];
            if($rate->date + $waittime <= time()){
                DB::table('ratelimit')->where('user', $ip)->update(['date' => time()]);
            }else{
                return view('search', ['query' => $query, 'limited' => 1, 'remaining' => $rate->date + $waittime - time(), 'results' => null, 'pasteCount' => 0, 'myUser' => $myUser, 'ans' => $ans, 'searchColumn' => $searchColumn]);
            }
        }else{
            DB::table('ratelimit')->insert(['user' => $ip, 'date' => time()]);
        }



        $rawQuery = trim($query);
        $query = str_replace(['\\', '%', '_'], ['\\\\', '\\%', '\\_'], trim($query));

        if($searchColumn == 'title' && strlen($query) < 2){
            return 'Minimum 2 characters';
        }else if($searchColumn == 'content' && strlen($query) < 5){
            return 'Minimum 5 characters when searching in paste';
        }

        if(is_null($myUser) || $myUser->role < 96){
            $searchBlockList = ['nude', 'teen'];
            foreach($searchBlockList as $word){
                if(str_contains($query, $word)){
                    return 'Search query contains a blocklisted word (\'' . $word . '\')';
                }
            }
        }
        //$results = DB::table('pastes')->where('title', 'like', '%'.str_replace(" ", "_", $query).'%')->orderByRaw('(title = "?")', [$query])->orderByRaw('length(title)')->get();


        $results_per_page = 100; // limit for srch results
        $columnsToSelect = PASTES_LIST_COLUMNS_TO_SELECT;


        $pastes = Paste::leftJoin('users', 'users.id', '=', 'pastes.created_by');
        $page = 0; // tmp until implement pagination
        $order = Input::get('orderby');
        $type = Input::get('type');
        if($type == "asc" || $type == "desc"){
            if($order == 'comments'){
                $pastes = $pastes->orderBy('hidden', 'asc')->orderBy('comments', $type);
            }else if($order == 'views'){
                $pastes = $pastes->orderBy('hidden', 'asc')->orderBy('views', $type);
            }else{
                $pastes = $pastes->orderBy('hidden', 'asc')->orderBy('created_at', $type);
                $order = "date";
            }
        }else{
            $pastes = $pastes->orderBy('hidden', 'asc')->latest('created_at');
            $type = "none";
            $order = "none";
        }

        $pastes = $pastes->limit($results_per_page)->offset($page * $results_per_page);

        if (!is_null($myUser) && $myUser->isDeveloper(true)) {
            if($myUser->isManager(true)){ // manager or higher. no limits
                $results = $pastes->where($searchColumn, 'like', '%'.$query.'%')->get($columnsToSelect);
            } else { //mod. where hidden date is over a week ago, remove unlisted
                $results = $pastes->where($searchColumn, 'like', '%'.$query.'%')->where('unlisted', 0)->where(function($q) use ($query){
                    $q->whereDate('hidden_at', '>=', Carbon\Carbon::now()->subDays(7));
                    $q->orWhere('hidden_at', '=', null);
                })->get($columnsToSelect);
            }
        }else{ // not staff. removed hidden & unlisted. private is handled in the page
            $results = $pastes->where($searchColumn, 'like', '%'.$query.'%')->where(['hidden' => 0, 'unlisted' => 0])->get($columnsToSelect);
        }


        return view('search', [
            'query' => $rawQuery,
            'limited' => 0,
            'results' => $results,
            'pasteCount' => count($results),
            'myUser' => $myUser,
            'ans' => $ans,
            'order' => $order,
            'type' => $type,
            'searchColumn' => $searchColumn
        ]);
    }


    public function hide(Request $request) {
        if (!$request->isMethod('post')){
            return abort(403);
        }

        $myUser = newGetUser();
        if($myUser == null){
            return response()->json(['status' => 'err']);
        }

        if (!$myUser->isDeveloper(true)) {
            return response()->json(['status' => 'err']);
        }

        $id = Input::get('pid');

        if (!is_numeric($id)) {
            return response()->json(['status' => 'err']);
        }

        $paste = Paste::where('id', $id)->first();
        if(is_null($paste)){
            return response()->json(['status' => 'err']);
        }

        if (($myUser->isDeveloper() || $myUser->isMod()) && $paste->hidden && Carbon\Carbon::now()->subDays(7)->gte($paste->hidden_at)) { // if theyre mod and the paste was hidden over 7 days ago
            return response()->json(['status' => 'err']);
        }

        $notifyUser = Input::get('notifyUser') == "true" ? 1 : 0;
        if (!$myUser->isMod()) {
            $notifyUser = 1; // Force non mods to notify user
        }

        $reason = null;
        $by = null;
        if(!$paste->hidden){
            // if($myUser->isMod() && strlen(Input::get('reason')) < 2){
            // 	$reason = Input::get('reason');
            // 	return $this->jsonError('Reason is required.');
            // }
            if(strlen(Input::get('reason')) > 255){
                return $this->jsonError('Reason max length is 255 chars');
            }
            $reason = Input::get('reason');
        }

        $by = ($myUser->role > RoleId::COUNCIL ? $myUser->id : 0);

        DB::transaction(function() use ($paste, $id, $by, $reason)  {
            $hidden = $paste->hidden;
            if($hidden){ // unhide
                DB::table('pastes')->where('id', $id)->update(['hidden' => 0, 'hidden_by' => null, 'hidden_reason' => null, 'hidden_at' => null]);
            }else{ // hide
                DB::table('pastes')->where('id', $id)->update(['hidden' => 1, 'hidden_by' => $by, 'hidden_reason' => $reason, 'hidden_at' => Carbon\Carbon::now()]);
            }
            // sync user comment count
            $comments = DB::table('comments')->where(['doxId' => $paste->id, 'hidden' => 0])->where('created_by', '!=', '0')->get();
            if($comments->count() > 0){
                foreach($comments as $comment){
                    if($hidden){
                        DB::table('users')->where('id', $comment->created_by)->increment('comments');
                    }else{
                        DB::table('users')->where('id', $comment->created_by)->decrement('comments');
                    }
                }
            }
            if($paste->created_by != 0){ // sync paste count
                if($hidden){ // unhiding
                    DB::table('users')->where('id', $paste->created_by)->increment('pastes');
                }else{ // hiding
                    DB::table('users')->where('id', $paste->created_by)->decrement('pastes');
                }
            }
        });


        if($notifyUser && strlen($reason) > 0){ // ntofiy user
            if($paste->created_by != 0){
                $user = \App\User::find($paste->created_by);
                if(!is_null($user)){
                    DB::table('notifications')->insert(['uid' => $user->id, 'pasteId' => $paste->id, 'type' => 6, 'text' => 'Paste <a href="/upload/'.$paste->link.'">'.htmlentities($paste->title).'</a> was removed by staff for:<br><b>'.htmlentities($reason).'</b>', 'date' => floor(microtime(true) * 1000)]);
                }
            }
        }

        if($myUser->role > RoleId::COUNCIL){
            Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => ($paste->hidden == 1 ? 'Unh' : 'H') . 'id paste: <a href="/upload/' . $paste->link . '">' . htmlspecialchars($paste->title) . '</a>']);
        }
        return response()->json(['status' => 'done', 'msg' => 'done', 'hidden' => !$paste->hidden]);
    }


    public function edit($paste){
        $myUser = newGetUser();
        if($myUser == null){
            return abort(404);
        }
        $paste = Paste::where('link', $paste)->firstOrFail();

        if($myUser->isManager(true) || $paste->hidden != 1){
            $created_by = User::find($paste->created_by);
            if($myUser->isManager(true) || $paste->created_by == $myUser->id){
                if(DB::table('edit_review')->where(['doxid' => $paste->id, 'handled' => 0])->count() > 0){
                    return 'Wait before editing again, or cancel the current edit request.';
                }
                return view('edit', ['error' => null,
                    'paste' => $paste,
                    'myUser' => $myUser,
                    'created_by' => $created_by
                ]);
            }else{
                return abort(403);
            }
        }
        return abort(404);
    }

    public function privacy(){
        $myUser = newGetUser();
        return view('privacy', ['myUser' => $myUser]);
    }

    private function like($paste, $myUser, $time, $currentRating, $rate){
        if($rate == 0){ // unlike
            DB::table('paste_ratings')->where(['pid' => $paste->id, 'uid' => $myUser->id])->delete(); // delete the like
            DB::table('pastes')->where('id', $paste->id)->decrement('likes');

            if(!is_null($myUser)){
                DB::table('users')->where('id', $myUser->id)->decrement('likes_given');
            }
            if($paste->created_by){
                DB::table('users')->where('id', $paste->created_by)->decrement('likes_received');
            }
        }else{ // like
            DB::table('paste_ratings')->insert(['pid' => $paste->id, 'uid' => $myUser->id, 'rating' => 1, 'created_at' => $time]); // add the like
            DB::table('pastes')->where('id', $paste->id)->increment('likes');
            if(!is_null($myUser)){
                DB::table('users')->where('id', $myUser->id)->increment('likes_given');
            }
            if($paste->created_by){
                DB::table('users')->where('id', $paste->created_by)->increment('likes_received');
            }
        }
    }

    private function dislike($paste, $myUser, $time, $currentRating, $rate){
        if($rate == 0){ // undislike
            DB::table('paste_ratings')->where(['pid' => $paste->id, 'uid' => $myUser->id])->delete(); // delete the dislike
            DB::table('pastes')->where('id', $paste->id)->decrement('dislikes');

            if(!is_null($myUser)){
                DB::table('users')->where('id', $myUser->id)->decrement('dislikes_given');
            }
            if($paste->created_by){
                DB::table('users')->where('id', $paste->created_by)->decrement('dislikes_received');
            }
        }else{ // dislike
            DB::table('paste_ratings')->insert(['pid' => $paste->id, 'uid' => $myUser->id, 'rating' => 0, 'created_at' => $time]); // add the dislike
            DB::table('pastes')->where('id', $paste->id)->increment('dislikes');
            if(!is_null($myUser)){
                DB::table('users')->where('id', $myUser->id)->increment('dislikes_given');
            }
            if($paste->created_by){
                DB::table('users')->where('id', $paste->created_by)->increment('dislikes_received');
            }
        }
    }

    public function rate(){
        $myUser = newGetUser();
        if(is_null($myUser)){
            return $this->jsonError();
        }

        $pasteName = Input::get('pname');
        if(empty($pasteName)){
            return $this->jsonError();
        }

        $paste = Paste::where('link', $pasteName)->first();
        if(is_null($paste) || $paste->hidden){ // if paste doesnt exist or is hidden
            return $this->jsonError();
        }

        $rate = Input::get('rating');

        if($paste->created_by == $myUser->id){ // trying to dislike own paset
            return $this->jsonError('cant like/dislike ur own paste');
        }

        if($rate != 1 && $rate != 0){ // invalid ratng
            return $this->jsonError();
        }

        $rating = DB::table('paste_ratings')->where(['pid' => $paste->id, 'uid' => $myUser->id])->first();

        $currentRating = (isset($rating->rating) ? $rating->rating : null);
        $time = Carbon\Carbon::now();
        $d = 0;
        $l = 0;
        DB::transaction(function() use ($rate, $paste, $myUser, $time, $rating, $currentRating, &$l, &$d) { // br3nt0n aug2021
            if(!is_null($currentRating)){ // already rated, nigea
                if($rate == 1){
                    if(!is_null($currentRating) && $currentRating == 1){ // just unlike
                        $this->like($paste, $myUser, $time, $currentRating, 0);
                        $l = 0;
                        $d = 0;
                    }else if(!is_null($currentRating) && $currentRating == 0){ // undislike & like
                        $this->dislike($paste, $myUser, $time, $currentRating, 0);
                        $this->like($paste, $myUser, $time, $currentRating, 1);
                        $l = 1;
                        $d = 0;
                    }
                }else if($rate == 0){
                    if(!is_null($currentRating) && $currentRating == 0){ // just undislike
                        $this->dislike($paste, $myUser, $time, $currentRating, 0);
                        $l = 0;
                        $d = 0;
                    }else if(!is_null($currentRating) && $currentRating == 1){ // unlike & dislike
                        $this->like($paste, $myUser, $time, $currentRating, 0);
                        $this->dislike($paste, $myUser, $time, $currentRating, 1);
                        $l = 0;
                        $d = 1;
                    }
                }
            }else{
                if($rate == 1){ // just like
                    $this->like($paste, $myUser, $time, $currentRating, 1);
                    $l = 1;
                    $d = 0;
                }else if($rate == 0){ // just dislike
                    $this->dislike($paste, $myUser, $time, $currentRating, 1);
                    $l = 0;
                    $d = 1;
                }
            }
        });
        return response()->json(['status' => 'done', 'l' => $l, 'd' => $d]);
    }

    public function editsubmit($paste, Requests\StoreEdit $request){
        $myUser = newGetUser();

        if($myUser == null){
            return $this->jsonError();
        }
        ;
        if(!$myUser->isManager(true)){ // if user isnt manager or higher, verify captcha
            if (!$request->attributes->get('captcha', false)) {
                return $this->jsonError('Captcha verification failed. Try again');
            }
        }
        $paste = Paste::where('link', $paste)->firstOrFail();


        if(!$myUser->isManager(true) && $paste->hidden == 1){
            return $this->jsonError();
        }
        if(!$myUser->isManager(true) && $paste->created_by != $myUser->id){
            return $this->jsonError();
        }
        if(!$myUser->isManager(true) && $paste->editbanned == 1){
            return $this->jsonError('You can\'t edit this paste');
        }
        if(DB::table('edit_review')->where(['doxid' => $paste->id, 'handled' => 0])->count() > 0){
            return $this->jsonError('Wait before editing again, or cancel the current edit request.');
        }
        if (!$myUser->isManager(true) && strlen(Input::get('pasteContent')) < 40) {
            return $this->jsonError('Character requirement is 40!');
        }
        if (!$myUser->isManager(true) && strlen(Input::get('pasteContent')) >= 1000000) {
            return $this->jsonError('Character limit is 1,000,000!');
        }
        if (strlen(Input::get('reason')) > 300){
            return $this->jsonError('Edit reason max length is 300! Currently '.strlen(Input::get('reason')));
        }
        $title = '';
        if($myUser->isManager(true)){
            $title = Input::get('pasteTitle');
            if(!empty($title)){
                $title = preg_replace("/[^A-Za-z0-9_]+/"," ", $title);
                $title = trim($title);
                $title = trim($title, "_");
            }

        }

        DB::transaction(function() use($myUser, $paste, $title){
            // global $paste;
            if($myUser->isManager(true) || $myUser->role >= 1){ // admin or VIP, skip edit request
                if(empty($title)){
                    DB::table('pastes')->where('id', $paste->id)->update(['content' => Input::get('pasteContent')]);
                }else{
                    DB::table('pastes')->where('id', $paste->id)->update(['content' => Input::get('pasteContent'), 'title' => $title]);
                }
            }else{
                DB::table('edit_review')->insert(['user_id' => $paste->created_by, 'title' => $paste->title, 'link' => $paste->link, 'newtitle' => $paste->title, 'newpost' => Input::get('pasteContent'), 'length' => strlen($paste->content), 'doxId' => $paste->id, 'edit_reason' => Input::get('reason'), 'date' => floor(microtime(true) * 1000)]);
                $embed = ["title" => "New Edit Request",
                    "description" => "**[" . $paste->title . "](https://". currentDomain() ."/admin/edits/" . $paste->link . ")**\nNew edit request by [" . $myUser->username . "](https://". currentDomain() ."/user/" . $myUser->username . ")",
                    "url" => "https://". currentDomain() ."/admin/edits/" . $paste->link,
                    'color' => 16711680,
                    'timestamp' => Carbon\Carbon::now()->toIso8601String()
                ];
                sendDiscordWebhook('Staff Notification', '@here', $embed);
            }

        });
        return response()->json(['status' => 'done', 'redirect' => '/upload/'.$paste->link]);
    }

    public function next_paste(Request $request){
        if(!$request->isMethod('get')){
            return $this->jsonError();
        }

        $maxAttempts = 10; // max attempts to look for the next paste

        $myUser = newGetUser();

        if(is_null($myUser)){
            return $this->jsonError();
        }

        if(!$myUser->isCouncil(true)){
            return $this->jsonError();
        }

        $id = Input::get('pid');

        $paste = Paste::where('id', $id)->first();

        if(is_null($paste)){
            return $this->jsonError();
        }

        $nextID = $id + 1;

        $nextPasteLink = null;
        $found = false;
        $attempts = 1;
        while($nextPasteLink == null){
            $nextPaste = Paste::where('id', $nextID)->first();
            if(!is_null($nextPaste) && !$nextPaste->hidden && $nextPaste->passord == null && !$nextPaste->unlisted && !$nextPaste->private){
                $nextPasteLink = $nextPaste->link;
                $found = true;
            }else{
                if($attempts < $maxAttempts){
                    $nextID = $nextID + 1;
                    $attempts += 1;
                }else{
                    $found = false;
                    $nextPasteLink = 'none';
                }
            }
        }
        if($found){
            return response()->json(['status' => 'done', 'redirect' => '/upload/'.$nextPasteLink]);
        }else{
            return response()->json(['status' => 'not_found', 'redirect' => null]);
        }
    }

    public function previous_paste(Request $request){
        if(!$request->isMethod('get')){
            return $this->jsonError();
        }

        $maxAttempts = 10; // max attempts to look for the next paste

        $myUser = newGetUser();

        if($myUser == null){
            return $this->jsonError();
        }

        if(!$myUser->isCouncil(true)){
            return $this->jsonError();
        }

        $id = Input::get('pid');

        $paste = Paste::where('id', $id)->first();

        if(is_null($paste)){
            return $this->jsonError();
        }

        $nextID = $id - 1;

        $nextPasteLink = null;
        $found = false;
        $attempts = 1;
        while($nextPasteLink == null){
            $nextPaste = Paste::where('id', $nextID)->first();
            if(!is_null($nextPaste) && !$nextPaste->hidden && $nextPaste->passord == null && !$nextPaste->unlisted && !$nextPaste->private){
                $nextPasteLink = $nextPaste->link;
                $found = true;
            }else{
                if($attempts < $maxAttempts){
                    $nextID = $nextID - 1;
                    $attempts += 1;
                }else{
                    $found = false;
                    $nextPasteLink = 'none';
                }
            }
        }
        if($found){
            return response()->json(['status' => 'done', 'redirect' => '/upload/'.$nextPasteLink]);
        }else{
            return response()->json(['status' => 'not_found', 'redirect' => null]);
        }
    }

    public function pin(Request $request){
        if(!$request->isMethod('post')){
            return $this->jsonError();
        }
        $myUser = newGetUser();
        if(is_null($myUser) || !$myUser->isManager(true)){
            return $this->jsonError();
        }

        $id = Input::get('pid');

        if(!is_numeric($id)) {
            return response()->json(['status' => 'err']);
        }

        $paste = Paste::where('id', $id)->first();

        if(is_null($paste)){
            return response()->json(['status' => 'err']);
        }

        $pinned_paste = DB::table('pinned_pastes')->where('id', $paste->id)->first();
        if (!is_null($pinned_paste)) { // already pinned; unpin
            DB::transaction(function() use ($paste, $myUser) {
                DB::table('pinned_pastes')->where('id', $paste->id)->delete();

                $paste->pinned = 0;
                $paste->save();

                if($myUser->role > RoleId::COUNCIL){
                    Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Unpinned paste: <a href="/upload/' . $paste->link . '">' . htmlspecialchars($paste->title) . '</a>']);
                }
            });

            Cache::clearPinnedPastesCache();

            return response()->json(['status' => 'done', 'msg' => 'done', 'pinned' => 0]);
        } else {
            DB::transaction(function() use ($paste, $myUser) {
                DB::table('pinned_pastes')->insert(['id' => $paste->id]);
                $paste->pinned = 1;
                $paste->save();

                if($myUser->role > RoleId::COUNCIL){
                    Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Pinned paste: <a href="/upload/' . $paste->link . '">' . htmlspecialchars($paste->title) . '</a>']);
                }
            });

            Cache::clearPinnedPastesCache();

            return response()->json(['status' => 'done', 'msg' => 'done', 'pinned' => 1]);
        }
    }

    public function dataleakshow(){
        $myUser = newGetUser();
        return view('dataleak', ['myUser' => $myUser]);
    }
}



// created by Brenton, twitter.com/brenton_xxx t.me/brenton