diff --git a/LICENSE b/LICENSE
index 3d98fad..5a5ab3e 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2014-2015, flashwave <me@flash.moe>
+Copyright (c) 2014-2025, flashwave <me@flash.moe>
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 4823356..0571088 100644
--- a/README.md
+++ b/README.md
@@ -1,33 +1,9 @@
-ninechan
-========
+# ninechan
 
-A simple text based discussion board of which you can find the demo, live development, suggestions and support boards on http://ninechan.flash.moe/
+After the release of the final ninechan package/version, I've done a bunch of maintenance.
+This repository makes all of that public.
+So far this is not a continuation of the project and 2.1x isn't a drop-in update since it has a bunch of changes specific to my environment, most of which being an attempt to stop the flood of spam...
 
-The version on GitHub is _usually_ in sync with the one on the development board.
+The source code is still licenced under the MIT licence.
 
-When downloading ninechan make sure to download it from the Releases tab thing and not master to ensure the stability of your board.
-
-Requirements
-------------
-
-| *Server-Side*                      | *Client-Side*                | 
-| ---------------------------------- | ---------------------------- |
-| PHP >= 5.3                         | Enabled JavaScript           |
-| Any PDO compatible Database Engine | CSS Compatibility            |
-| Short PHP Tags                     | Cookies enabled              |
-
-Features
---------
-- Easy Installation and Upgrading
-- Moderation
-- Tripcodes
-- Youtube Embedding
-- Easy language changing and adding
-- Quoting/"greentexting"
-- Multiple styles
-- reCAPTCHAs
-- Password based post deletion
-
-Help
-----
-Although I don't really see when you need help with the script just send me an email (email address is on github profile) or ask about it in the issues section
+Thank you for your interest in ninechan :)
diff --git a/config.example.php b/config.example.php
index e2a9429..492feb8 100644
--- a/config.example.php
+++ b/config.example.php
@@ -119,3 +119,14 @@ $ninechan['reCaptchaPublic'] = "6LdQwAYTAAAAAKSW9Q7U6qS6HFTwotccCMr1Ejri";
 
 // reCAPTCHA Private key
 $ninechan['reCaptchaPrivate'] = "6LdQwAYTAAAAAJ3NUhUmFyc814B7AM1LGbVwWKp2";
+
+$navBoards = [
+    'dev' => ['ninechan', 'dev', 'Board'],
+    //'sup' => ['ninechan', 'sup', 'Support'],
+    //'sug' => ['ninechan', 'sug', 'Suggestions'],
+];
+
+$navLinks = [
+    'Home' => '/',
+    'Downloads' => '/dl',
+];
diff --git a/index.php b/index.php
index d5f787c..ec35fff 100644
--- a/index.php
+++ b/index.php
@@ -6,13 +6,21 @@
  */
 
 // Set ninechan version, don't change this or it'll probably break things.
-$version = '2.1';
+$version = '2.1x';
 
 // Language file versions this version is compatible with
 $langCompat = [
     '2.1'
 ];
 
+function ncCheckRemoteAddr(string $addr): float {
+    $addr = rawurlencode($addr);
+    $mail = rawurlencode('ninechan-ipintel@flash.moe');
+    // banned from the system, bother with this at some point
+    //$result = file_get_contents("https://check.getipintel.net/check.php?ip={$addr}&contact={$mail}");
+    return 0;
+}
+
 // Error messages
 function error($data) {
 
@@ -219,7 +227,7 @@ function nHead() {
             foreach($styles as $url => $name) {
 
                 // Get the key of the first entry
-                $main = key($styles); 
+                $main = key($styles);
 
                 // Append styles to the header
                 $header .= '<link rel="'. ($url == $main ? null : 'alternate ') .'stylesheet" type="text/css" href="'. $url .'" title="'. $name .'" '. ($url == $main ? null : 'disabled ') .'/>';
@@ -232,7 +240,14 @@ function nHead() {
     <body>
         <h1><a href="./">'. getConfig('title') .'</a></h1>'.
         (getConfig('desc') ? '&nbsp;<i>'. getConfig('desc') .'</i>' : '')
-        .'<hr /><h6>[<a href="?v=index">'. getLang('INDEX') .'</a>] [<a href="?v=post">'. getLang('NEWTHREAD') .'</a>] [<a href="?v=mod">'. getLang('MANAGE') .'</a>]</h6><hr />';
+        .'<hr />';
+
+    $header .= '<h5>';
+    foreach($GLOBALS['navLinks'] as $title => $url)
+        $header .= " [<a href='{$url}'>{$title}</a>]";
+    foreach($GLOBALS['navBoards'] as $link => $board)
+        $header .= " [<a href='/{$link}/'>{$board[2]}</a>]";
+    $header .= '</h5><hr/><h6>[<a href="?v=index">'. getLang('INDEX') .'</a>] [<a href="?v=soup">'. getLang('NEWTHREAD') .'</a>]</h6><hr />';
 
     return $header;
 
@@ -269,9 +284,9 @@ function nFoot() {
     */
 
     $footer .= '<h6>
-            <a href="http://ninechan.flash.moe/" target="_blank">ninechan</a>
+            <a href="https://patchii.net/flash/ninechan" target="_blank">ninechan</a>
             '. (getConfig('showVersion') ? $version : '') .'
-            &copy; <a href="http://flash.moe/" target="_blank">Flashwave</a>
+            &copy; <a href="https://flash.moe" target="_blank">flashwave</a>
         </h6>
     </body>
 </html>';
@@ -413,6 +428,15 @@ CREATE TABLE IF NOT EXISTS `". $sql['table'] ."` (
 session_start(); // Start a session
 $auth = @$_SESSION['mod']; // Set an alias for mod
 
+$remoteAddr = $_SERVER['REMOTE_ADDR'];
+$remoteAddrKey = 'ip_' . $remoteAddr;
+if(true || !isset($_SESSION[$remoteAddrKey]) || $_SESSION[$remoteAddrKey] < 0) {
+    $_SESSION[$remoteAddrKey] = $remoteAddrState = ncCheckRemoteAddr($remoteAddr);
+    if($remoteAddrState >= .8)
+        file_put_contents(__DIR__ . '/../shame.txt', sprintf('[%s] %s - %F - %s%s', date('Y-m-d H:i:s'), $remoteAddr, $remoteAddrState, htmlspecialchars($_SERVER['HTTP_USER_AGENT'] ?? '(none)'), PHP_EOL), FILE_APPEND | LOCK_EX);
+} else
+    $remoteAddrState = $_SESSION[$remoteAddrKey];
+
 // Print the header
 print nHead();
 
@@ -438,6 +462,10 @@ if(isset($_GET['t'])) {
 
 }
 
+// Check if the current IP is banned
+if($remoteAddrState >= .6)
+    print '<div class="banmsg">You have been automatically banned from posting on this board. <a href="/bot.html">Click here for more info</a>.</div><hr />';
+
 // Check if the current IP is banned
 if(checkBan($_SERVER['REMOTE_ADDR']))
     print '<div class="banmsg">'. getLang('USERBANNEDMSG') .'</div><hr />';
@@ -458,7 +486,7 @@ if(isset($_GET['v'])) {
             print '<h2>'. getLang('THREADS') .'</h2>';
 
             // New thread link
-            print '<h3><a href="'. $_SERVER['PHP_SELF'] .'?v=post">'. getLang('NEWTHREAD') .'</a></h3>';
+            print '<h3><a href="'. $_SERVER['PHP_SELF'] .'?v=soup">'. getLang('NEWTHREAD') .'</a></h3>';
 
             // Get threads
             $threads = array_chunk(getPosts(), getConfig('threadsPerPage'), true);
@@ -469,7 +497,7 @@ if(isset($_GET['v'])) {
                 print '<ol>';
 
                 foreach($threads[(isset($_GET['p']) && ($_GET['p'] - 1) >= 0 && array_key_exists(($_GET['p'] - 1), $threads)) ? $_GET['p'] - 1 : 0] as $thread)
-                    print '<li><a href="'. $_SERVER['PHP_SELF'] .'?v=thread&amp;id='. $thread['tid'] .'">'. $thread['title'] .'</a> <span style="font-size: x-small;">[<b title="'. date(getConfig('dateFormat'), $thread['lastreply']) .'">'. (count(getPosts($thread['tid'])) - 1) .'</b>]</span>';
+                    print '<li><a href="'. $_SERVER['PHP_SELF'] .'?v=thread&id='. $thread['tid'] .'">'. $thread['title'] .'</a> <span style="font-size: x-small;">[<b title="'. date(getConfig('dateFormat'), $thread['lastreply']) .'">'. (count(getPosts($thread['tid'])) - 1) .'</b>]</span>';
 
                 print '</ol>';
 
@@ -489,7 +517,7 @@ if(isset($_GET['v'])) {
             }
 
             // New thread link
-            print '<h3><a href="'. $_SERVER['PHP_SELF'] .'?v=post">'. getLang('NEWTHREAD') .'</a></h3>';
+            print '<h3><a href="'. $_SERVER['PHP_SELF'] .'?v=soup">'. getLang('NEWTHREAD') .'</a></h3>';
             break;
 
         // Thread view
@@ -518,7 +546,7 @@ if(isset($_GET['v'])) {
                 if($thread[0]['locked'])
                     print '<h3>'. getLang('LOCKED') .'</h3>';
                 else
-                    print '<h3><a href='. $_SERVER['PHP_SELF'] .'?v=post&amp;id='. $thread[0]['tid'] .'>'. getLang('NEWREPLY') .'</a></h3>';
+                    print '<h3><a href='. $_SERVER['PHP_SELF'] .'?v=soup&id='. $thread[0]['tid'] .'>'. getLang('NEWREPLY') .'</a></h3>';
 
                 // Moderator tools
                 if($auth == $ninechan['modPass']) {
@@ -526,12 +554,12 @@ if(isset($_GET['v'])) {
                     print '<h6>';
 
                     // Purge button
-                    print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&amp;del=purge&amp;id='. $thread[0]['tid'] .'">'. getLang('PURGE') .'</a>]'."\r\n";
+                    print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&del=purge&id='. $thread[0]['tid'] .'">'. getLang('PURGE') .'</a>]'."\r\n";
 
                     if($thread[0]['locked'])
-                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&amp;lock=false&amp;id='. $thread[0]['tid'] .'">'. getLang('UNLOCK') .'</a>]';
+                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&lock=false&id='. $thread[0]['tid'] .'">'. getLang('UNLOCK') .'</a>]';
                     else
-                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&amp;lock=true&amp;id='. $thread[0]['tid'] .'">'. getLang('LOCK') .'</a>]';
+                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&lock=true&id='. $thread[0]['tid'] .'">'. getLang('LOCK') .'</a>]';
 
                     print '</h6>';
 
@@ -595,15 +623,15 @@ if(isset($_GET['v'])) {
                     if($auth == $ninechan['modPass']) {
 
                         print '<h6>';
-                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&amp;del=true&id='. $post['id'] .'&amp;id='. $post['tid'] .'">'. getLang('DELETE') .'</a>]'."\r\n";
-                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&amp;ban='. ($post['ban'] ? 'false' : 'true') .'&amp;id='. $post['id'] .'&amp;id='. $post['tid'] .'">'. getLang($post['ban'] ? 'UNBAN' : 'BAN') .'</a>]'."\r\n";
+                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&del=true&id='. $post['id'] .'&tid='. $post['tid'] .'">'. getLang('DELETE') .'</a>]'."\r\n";
+                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&ban='. ($post['ban'] ? 'false' : 'true') .'&id='. $post['id'] .'&tid='. $post['tid'] .'">'. getLang($post['ban'] ? 'UNBAN' : 'BAN') .'</a>]'."\r\n";
                         print '[IP: '.base64_decode($post['ip']).']';
                         print '</h6>';
 
                     }
 
                     // Date and ID
-                    print '<h6><i>'. date(getConfig('dateFormat'), $post['date']) .' <a href="#'. $post['id'] .'">No.</a> <a href="'. $_SERVER['PHP_SELF'] .'?v=post&amp;id='. $post['tid'] .'&amp;text=>>'. $post['id'] .'">'. $post['id'] .'</a> [<a href="'. $_SERVER['PHP_SELF'] .'?v=del&amp;id='. $post['id'] .'" title="'. getLang('DELPOST') .'">X</a>]</i></h6>';
+                    print '<h6><i>'. date(getConfig('dateFormat'), $post['date']) .' <a href="#'. $post['id'] .'">No.</a> <a href="'. $_SERVER['PHP_SELF'] .'?v=soup&id='. $post['tid'] .'&text=>>'. $post['id'] .'">'. $post['id'] .'</a> [<a href="'. $_SERVER['PHP_SELF'] .'?v=del&id='. $post['id'] .'" title="'. getLang('DELPOST') .'">X</a>]</i></h6>';
 
                     print '</fieldset>';
 
@@ -615,12 +643,12 @@ if(isset($_GET['v'])) {
                     print '<h6>';
 
                     // Purge button
-                    print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&amp;del=purge&amp;id='. $thread[0]['tid'] .'">'. getLang('PURGE') .'</a>]'."\r\n";
+                    print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&del=purge&id='. $thread[0]['tid'] .'">'. getLang('PURGE') .'</a>]'."\r\n";
 
                     if($thread[0]['locked'])
-                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&amp;lock=false&amp;id='. $thread[0]['tid'] .'">'. getLang('UNLOCK') .'</a>]';
+                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&lock=false&id='. $thread[0]['tid'] .'">'. getLang('UNLOCK') .'</a>]';
                     else
-                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&amp;lock=true&amp;id='. $thread[0]['tid'] .'">'. getLang('LOCK') .'</a>]';
+                        print '[<a href="'. $_SERVER['PHP_SELF'] .'?v=mod&lock=true&id='. $thread[0]['tid'] .'">'. getLang('LOCK') .'</a>]';
 
                     print '</h6>';
 
@@ -630,7 +658,7 @@ if(isset($_GET['v'])) {
                 if($thread[0]['locked'])
                     print '<h3>'. getLang('LOCKED') .'</h3>';
                 else
-                    print '<h3><a href="'. $_SERVER['PHP_SELF'] .'?v=post&amp;id='. $thread[0]['tid'] .'">'. getLang('NEWREPLY') .'</a></h3>';
+                    print '<h3><a href="'. $_SERVER['PHP_SELF'] .'?v=soup&id='. $thread[0]['tid'] .'">'. getLang('NEWREPLY') .'</a></h3>';
 
             } else {
 
@@ -642,7 +670,11 @@ if(isset($_GET['v'])) {
             break;
 
         // Posting
-        case 'post':
+        case 'soup':
+            if($remoteAddrState >= .6) {
+                header('Location: /bot.html');
+                exit;
+            }
 
             // Check if user is banned and if so don't display the form at all
             if(checkBan($_SERVER['REMOTE_ADDR'])) {
@@ -651,7 +683,7 @@ if(isset($_GET['v'])) {
             }
 
             // Print "global" form elements
-            print '<form method="post" action="'. $_SERVER['PHP_SELF'] .'?v=submit">';                    
+            print '<form method="post" action="'. $_SERVER['PHP_SELF'] .'?v=boat">';
             print '<table id="postForm" class="postForm">';
 
             // Predefine that we're creating a new thread
@@ -700,7 +732,7 @@ if(isset($_GET['v'])) {
                 if($locked) {
 
                     print '<h2>'. getLang('LOCKEDMSG') .'</h2>';
-                    print '<meta http-equiv="refresh" content="2; URL="'. $_SERVER['PHP_SELF'] .'?v=thread&amp;id='. $thread['tid'] .'" />';
+                    print '<meta http-equiv="refresh" content="2; URL="'. $_SERVER['PHP_SELF'] .'?v=thread&id='. $thread['tid'] .'" />';
 
                 } else {
 
@@ -749,7 +781,11 @@ if(isset($_GET['v'])) {
             break;
 
         // Submitting posts
-        case 'submit':
+        case 'boat':
+            if($remoteAddrState >= .6) {
+                header('Location: /bot.html');
+                exit;
+            }
 
                 // Check if IP banned
             if(checkBan($_SERVER['REMOTE_ADDR'])) {
@@ -858,10 +894,14 @@ if(isset($_GET['v'])) {
 
             print '<h1>'. getLang('POSTED') .'</h1>';
 
-            print '<meta http-equiv="refresh" content="1; URL='. $_SERVER['PHP_SELF'] . ($submitData['noredir'] ? '?v=index' : '?v=thread&amp;id='. $submitData['id']) .'" />';
+            print '<meta http-equiv="refresh" content="1; URL='. $_SERVER['PHP_SELF'] . ($submitData['noredir'] ? '?v=index' : '?v=thread&id='. $submitData['id']) .'" />';
             break;
 
         case 'del':
+            if($remoteAddrState >= .6) {
+                header('Location: /bot.html');
+                exit;
+            }
 
             // Check if IP banned
             if(checkBan($_SERVER['REMOTE_ADDR'])) {
@@ -963,103 +1003,10 @@ if(isset($_GET['v'])) {
             }
             break;
 
-        // Moderator Authentication
-        case 'mod':
-            if($auth == getConfig('modPass')) { // Check if authenticated
-
-                // Page title
-                print '<h2>'. getLang('MODLOGOUT') .'</h2>';
-
-                if(isset($_POST['modkill'])) { // POST request modkill is set...
-
-                    session_destroy(); // ...kill moderator session...
-                    header('Location: '. $_SERVER['PHP_SELF'] .'?v=mod'); // ...and redirect to ?v=mod
-                    print '<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=mod" />'; // fallback
-                    exit;
-
-                }
-
-                // Print logout form
-                print '<form method="post" action="'.$_SERVER['PHP_SELF'].'?v=mod">';
-                print getLang('MODTOOLS') .'<br />';
-                print '<input type="submit" value="'. getLang('LOGOUT') .'" name="modkill" />';
-                print '</form>';
-
-                // Ban handler
-                if(isset($_GET['ban']) && isset($_GET['id']) && isset($_GET['id'])) {
-
-                    if($_GET['ban'] == "true")
-                        nMod('ban', $_GET['id'], true);
-                    else
-                        nMod('ban', $_GET['id'], false);
-
-                    header('Location: '. $_SERVER['PHP_SELF'] .'?v=thread&amp;id='.$_GET['id']);
-                    print '<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=thread&amp;id='.$_GET['id'].'" />'; // fallback
-                    exit;
-
-                }
-
-                // Deletion handler
-                if(isset($_GET['del']) && isset($_GET['id'])) {
-
-                    if($_GET['del'] == "purge") {
-
-                        nMod('prune', $_GET['id'], true);
-
-                        header('Location: '. $_SERVER['PHP_SELF'] .'?v=index');
-                        print '<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=index" />'; // fallback
-                            exit;
-
-                    } else {
-
-                        if($_GET['del'] == "true")
-                            nMod('del', $_GET['id'], true);
-                        else
-                            nMod('del', $_GET['id'], false);
-
-                        header('Location: '. $_SERVER['PHP_SELF'] .'?v=thread&amp;id='.$_GET['id']);
-                        print '<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=thread&amp;id='.$_GET['id'].'" />'; // fallback
-                        exit;
-
-                    }
-
-                }
-
-                // Lock handler
-                if(isset($_GET['lock']) && isset($_GET['id'])) {
-
-                    if($_GET['lock'] == "true")
-                        nMod('lock', $_GET['id'], true);
-                    else
-                        nMod('lock', $_GET['id'], false);
-
-                    header('Location: '. $_SERVER['PHP_SELF'] .'?v=thread&amp;id='.$_GET['id']);
-                    print '<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=thread&amp;id='.$_GET['id'].'" />'; // fallback
-                    exit;
-
-                }
-
-            } else {
-
-                // Else display login screen
-                if(isset($_POST['modPass'])) {
-
-                    if($_POST['modPass'] == $ninechan['modPass'])
-                            $_SESSION['mod'] = $ninechan['modPass'];
-
-                        header('Location: '. $_SERVER['PHP_SELF'] .'?v=mod');
-                        print '<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=mod" />'; // fallback
-                        exit;
-
-                    }
-
-                    print '<h2>'. getLang('MODLOGIN') .'</h2>';
-                    print '<form method="post" action="'. $_SERVER['PHP_SELF'] .'?v=mod">';
-                    print '<input type="password" name="modPass" /><input type="submit" value="'. getLang('LOGIN') .'" />';
-                    print '</form>';
-
-            }
-            break;
+        case 'destroy':
+            header('Location: ./');
+            session_destroy();
+            exit;
 
         // Default action
         default:
diff --git a/lang/en.php b/lang/en.php
index 58e8405..26d0d38 100644
--- a/lang/en.php
+++ b/lang/en.php
@@ -12,8 +12,8 @@ $language = [
     // Board
     'THREADS'   => 'Threads',
     'THREAD'    => 'Thread',
-    'NEWTHREAD' => 'New Thread',
-    'NEWREPLY'  => 'New Reply',
+    'NEWTHREAD' => '&#8288;N&#8288;e&#8288;w&#8288; &#8288;T&#8288;h&#8288;r&#8288;e&#8288;a&#8288;d&#8288;',
+    'NEWREPLY'  => '&#8288;N&#8288;e&#8288;w&#8288; &#8288;R&#8288;e&#8288;p&#8288;l&#8288;y&#8288;',
     'LOCKED'    => 'Locked',
     'BY'        => 'by',
     'RETURN'    => 'Return to Index',