From 0ceb814ab383587e5ff2d017b8c528a893d2ee4e Mon Sep 17 00:00:00 2001
From: 8n-tech <8n-tech@users.noreply.github.com>
Date: Mon, 13 Apr 2015 14:24:55 +1000
Subject: [PATCH] - Added board-search.php with improved board directory
searching. - Added new functions to functions.php for fetching board meta. -
Added new styling for non-index page 12-col layouts. - Modified templating
for board directories. - Moved CSS from the index page to CSS files.
Signed-off-by: 8n-tech <8n-tech@users.noreply.github.com>
---
board-search.php | 162 +++++++++++++++++
boards.php | 11 +-
inc/functions.php | 84 ++++++++-
stylesheets/style.css | 298 ++++++++++++++++++++++++-------
templates/8chan/boards-tags.html | 252 ++++++++++----------------
templates/8chan/boards.html | 102 ++++-------
templates/8chan/index.html | 27 ---
7 files changed, 609 insertions(+), 327 deletions(-)
create mode 100644 board-search.php
diff --git a/board-search.php b/board-search.php
new file mode 100644
index 00000000..d9fb3ec2
--- /dev/null
+++ b/board-search.php
@@ -0,0 +1,162 @@
+ false,
+ 'nsfw' => true,
+ 'tags' => false,
+);
+
+// Include NSFW boards?
+if (isset( $_GET['nsfw'] )) {
+ $search['nsfw'] = (bool) $_GET['nsfw'];
+}
+
+// Include what language (if the language is not blank and we recognize it)?
+if (isset( $_GET['lang'] ) && isset($languages[$search['lang']])) {
+ $search['lang'] = $_GET['lang'];
+}
+
+// Include what tag?
+if (isset( $_GET['tags'] )) {
+ $search['tags'] = $_GET['tags'];
+}
+
+/* Search boards */
+$boards = listBoards();
+$response['boards'] = array();
+
+// Loop through our available boards and filter out inapplicable ones based on standard filtering.
+foreach ($boards as $board) {
+ // Checks we can do without looking at config.
+ if (
+ // Indexed, or we are staff,
+ ( $CanViewUnindexed !== true && !$board['indexed'] )
+ // Not filtering NSFW, or board is SFW.
+ || ( $search['nsfw'] !== true && $board['sfw'] != 1 )
+ ) {
+ continue;
+ }
+
+ // Load board config.
+ $boardConfig = loadBoardConfig( $board['uri'] );
+
+ // Determine language/locale and tags.
+ $boardLang = strtolower( array_slice( explode( "_", $boardConfig['locale'] ?: "" ), 0 )[0] ); // en_US -> en OR en -> en
+
+ // Check against our config search options.
+ if ( $search['lang'] !== false && $search['lang'] != $boardLang ) {
+ continue;
+ }
+
+ $board['locale'] = $boardLang;
+
+ $response['boards'][ $board['uri'] ] = $board;
+}
+
+
+/* Tag Fetching */
+// (We have do this even if we're not filtering by tags so that we know what each board's tags are)
+
+// Fetch all board tags for our boards.
+$boardTags = fetchBoardTags( array_keys( $response['boards'] ) );
+
+// Loop through each board and determine if there are tag matches.
+foreach ($response['boards'] as $boardUri => &$board) {
+ // If we are filtering by tag and there is no match, remove from the response.
+ if ( $search['tags'] !== false && ( !isset( $boardTags[ $boardUri ] ) || !in_array( $search['tags'], $boardTags[ $boardUri ] )) ) {
+ unset( $response['boards'][$boardUri] );
+ }
+ // If we aren't filtering / there is a match AND we have tags, set the tags.
+ else if ( isset( $boardTags[ $boardUri ] ) && $boardTags[ $boardUri ] ) {
+ $board['tags'] = $boardTags[ $boardUri ];
+ }
+ // Othrwise, just declare our tag array blank.
+ else {
+ $board['tags'] = array();
+ }
+}
+
+
+/* Activity Fetching */
+$boardActivity = fetchBoardActivity( array_keys( $response['boards'] ) );
+
+// Loop through each board and record activity to it.
+// We will also be weighing and building a tag list.
+foreach ($response['boards'] as $boardUri => &$board) {
+ $board['active'] = (int) $boardActivity['active'][ $boardUri ];
+ $board['pph'] = (int) $boardActivity['average'][ $boardUri ];
+
+ if (isset($board['tags']) && count($board['tags']) > 0) {
+ foreach ($board['tags'] as $tag) {
+ if (isset($response['tag'][$tag])) {
+ $response['tag'][$tag] += $board['active'];
+ }
+ else {
+ $response['tag'][$tag] = $board['active'];
+ }
+ }
+ }
+}
+
+// Get the top most popular tags.
+if (count($response['tag']) > 0) {
+ // Sort by most active tags.
+ arsort( $response['tag'] );
+ // Get the first n most active tags.
+ $response['tag'] = array_splice( $response['tag'], 0, 200 );
+
+ $tagLightest = end( array_keys( $response['tag'] ) );
+}
+
+
+/* (Please) Respond */
+$json = json_encode( $response );
+
+// Error Handling
+switch (json_last_error()) {
+ case JSON_ERROR_NONE:
+ $jsonError = false;
+ break;
+ case JSON_ERROR_DEPTH:
+ $jsonError = 'Maximum stack depth exceeded';
+ break;
+ case JSON_ERROR_STATE_MISMATCH:
+ $jsonError = 'Underflow or the modes mismatch';
+ break;
+ case JSON_ERROR_CTRL_CHAR:
+ $jsonError = 'Unexpected control character found';
+ break;
+ case JSON_ERROR_SYNTAX:
+ $jsonError = 'Syntax error, malformed JSON';
+ break;
+ case JSON_ERROR_UTF8:
+ $jsonError = 'Malformed UTF-8 characters, possibly incorrectly encoded';
+ break;
+ default:
+ $jsonError = 'Unknown error';
+ break;
+}
+
+if ($jsonError) {
+ $json = "{\"error\":\"{$jsonError}\"}";
+}
+
+// Successful output
+echo $json;
\ No newline at end of file
diff --git a/boards.php b/boards.php
index 87ba7ddf..a1cb260b 100644
--- a/boards.php
+++ b/boards.php
@@ -122,7 +122,7 @@ $body = Element("8chan/boards-tags.html", array("config" => $config, "n_boards"
$html = Element("page.html", array("config" => $config, "body" => $body, "title" => "Boards on ∞chan"));
$boards_top2k = $boards;
-array_splice($boards_top2k, 2000);
+array_splice($boards_top2k, 100);
$boards_top2k = array_values($boards_top2k);
$body = Element("8chan/boards-tags.html", array("config" => $config, "n_boards" => $n_boards, "t_boards" => $t_boards, "hidden_boards_total" => $hidden_boards_total, "total_posts" => $total_posts, "total_posts_hour" => $total_posts_hour, "boards" => $boards_top2k, "last_update" => date('r'), "uptime_p" => shell_exec('uptime -p'), 'tags' => $all_tags, 'top2k' => true));
$html_top2k = Element("page.html", array("config" => $config, "body" => $body, "title" => "Boards on ∞chan"));
@@ -133,10 +133,10 @@ if ($admin) {
foreach ($boards as $i => &$b) { unset($b['img']); }
file_write("boards.json", json_encode($boards));
file_write("tags.json", json_encode($all_tags));
- foreach ($boards as $i => $b) {
+ foreach ($boards as $i => $b) {/*
if (in_array($b['uri'], $config['no_top_bar_boards'])) {
unset($boards[$i]);
- }
+ }*/
unset($boards[$i]['img']);
}
@@ -147,6 +147,5 @@ if ($admin) {
file_write("boards-top20.json", json_encode($boards));
file_write("boards.html", $html_top2k);
file_write("boards_full.html", $html);
- echo 'Done';
-}
-
+ echo $html;
+}
\ No newline at end of file
diff --git a/inc/functions.php b/inc/functions.php
index 4a4969ae..1e2b9be7 100755
--- a/inc/functions.php
+++ b/inc/functions.php
@@ -516,9 +516,9 @@ function setupBoard($array) {
$board = array(
'uri' => $array['uri'],
'title' => $array['title'],
- 'subtitle' => $array['subtitle'],
- 'indexed' => $array['indexed'],
- 'public_logs' => $array['public_logs']
+ 'subtitle' => isset($array['subtitle']) ? $array['subtitle'] : "",
+ 'indexed' => isset($array['indexed']) ? $array['indexed'] : true,
+ 'public_logs' => isset($array['public_logs']) ? $array['public_logs'] : true,
);
// older versions
@@ -804,6 +804,84 @@ function listBoards($just_uri = false, $indexed_only = false) {
return $boards;
}
+function loadBoardConfig( $uri ) {
+ $config = array(
+ "locale" => "en_US",
+ );
+ $configPath = "/{$uri}/config.php";
+
+ if (file_exists( $configPath ) && is_readable( $configPath )) {
+ include( $configPath );
+ }
+
+ // **DO NOT** use $config outside of this local scope.
+ // It's used by our global config array.
+ return $config;
+}
+
+function fetchBoardActivity( $uris ) {
+ $boardActivity = array();
+
+ /*
+ $uris = "\"" . implode( (array) $uris, "\",\"" ) . "\"";
+
+ $tagQuery = prepare("SELECT * FROM ``board_tags`` WHERE `uri` IN ({$uris})");
+ $tagQuery->execute() or error(db_error($tagQuery));
+ $tagResult = $tagQuery->fetchAll(PDO::FETCH_ASSOC);
+
+ if ($tagResult) {
+ foreach ($tagResult as $tagRow) {
+ $tag = $tagRow['tag'];
+ $tag = trim($tag);
+ $tag = strtolower($tag);
+ $tag = str_replace(['_', ' '], '-', $tag);
+
+ if (!isset($boardTags[ $tagRow['uri'] ])) {
+ $boardTags[ $tagRow['uri'] ] = array();
+ }
+
+ $boardTags[ $tagRow['uri'] ][] = htmlentities( utf8_encode( $tag ) );
+ }
+ }
+ */
+
+ foreach( (array) $uris as $uri ) {
+ $random = rand( -1000, 1000 );
+ if( $random < 0 ) $random = 0;
+
+ $boardActivity['active'][ $uri ] = $random;
+ $boardActivity['average'][ $uri ] = $random * 72;
+ }
+
+ return $boardActivity;
+}
+
+function fetchBoardTags( $uris ) {
+ $boardTags = array();
+ $uris = "\"" . implode( (array) $uris, "\",\"" ) . "\"";
+
+ $tagQuery = prepare("SELECT * FROM ``board_tags`` WHERE `uri` IN ({$uris})");
+ $tagQuery->execute() or error(db_error($tagQuery));
+ $tagResult = $tagQuery->fetchAll(PDO::FETCH_ASSOC);
+
+ if ($tagResult) {
+ foreach ($tagResult as $tagRow) {
+ $tag = $tagRow['tag'];
+ $tag = trim($tag);
+ $tag = strtolower($tag);
+ $tag = str_replace(['_', ' '], '-', $tag);
+
+ if (!isset($boardTags[ $tagRow['uri'] ])) {
+ $boardTags[ $tagRow['uri'] ] = array();
+ }
+
+ $boardTags[ $tagRow['uri'] ][] = htmlentities( utf8_encode( $tag ) );
+ }
+ }
+
+ return $boardTags;
+}
+
function until($timestamp) {
$difference = $timestamp - time();
switch(TRUE){
diff --git a/stylesheets/style.css b/stylesheets/style.css
index b5706afc..e862b9f6 100644
--- a/stylesheets/style.css
+++ b/stylesheets/style.css
@@ -1,3 +1,6 @@
+/* === GENERAL TAG SETTINGS === */
+
+/* Page Layouts */
body {
background: #EEF2FF url('img/fade-blue.png') repeat-x 50% 0%;
color: black;
@@ -8,6 +11,69 @@ body {
padding-right: 4px;
}
+main,
+aside,
+section {
+ display: block;
+ margin: 0 auto;
+ width: 100%;
+}
+
+main {
+ max-width: 1110px;
+}
+
+/* Tables */
+table {
+ margin: auto;
+ width: 100%;
+}
+
+table {
+ margin: auto;
+ width: 100%;
+}
+table tbody td {
+ margin: 0;
+ padding: 4px 15px 4px 4px;
+
+ text-align: left;
+}
+table thead th {
+ border: 1px solid #000333;
+ padding: 4px 15px 5px 5px;
+
+ background: #98E;
+ color: #000333;
+ text-align: left;
+ white-space: nowrap;
+}
+table tbody tr:nth-of-type( even ) {
+ background-color: #D6DAF0;
+}
+
+td.minimal,th.minimal {
+ width: 1%;
+ white-space: nowrap;
+}
+
+table.mod.config-editor {
+ font-size: 9pt;
+ width: 100%;
+}
+
+table.mod.config-editor td {
+ text-align: left;
+ padding: 5px;
+ border-bottom: 1px solid #98e;
+}
+
+table.mod.config-editor input[type="text"] {
+ width: 98%;
+}
+
+
+/* Uncategorized */
#post-form-outer {
text-align: center;
}
@@ -538,50 +604,10 @@ hr {
clear: left;
}
-div.boardlist {
- color: #89A;
- font-size: 9pt;
- margin-top: 3px;
-}
-
-div.boardlist.bottom {
- margin-top: 20px;
-}
-
-div.boardlist a {
- text-decoration: none;
-}
-
div.report {
color: #333;
}
-table.modlog {
- margin: auto;
- width: 100%;
-}
-
-table.modlog tr td {
- text-align: left;
- margin: 0;
- padding: 4px 15px 0 0;
-}
-
-table.modlog tr th {
- text-align: left;
- padding: 4px 15px 5px 5px;
- white-space: nowrap;
-}
-
-table.modlog tr th {
- background: #98E;
-}
-
-td.minimal,th.minimal {
- width: 1%;
- white-space: nowrap;
-}
-
div.top_notice {
text-align: center;
margin: 5px auto;
@@ -605,21 +631,6 @@ div.blotter {
text-align: center;
}
-table.mod.config-editor {
- font-size: 9pt;
- width: 100%;
-}
-
-table.mod.config-editor td {
- text-align: left;
- padding: 5px;
- border-bottom: 1px solid #98e;
-}
-
-table.mod.config-editor input[type="text"] {
- width: 98%;
-}
-
.desktop-style div.boardlist:not(.bottom) {
position: fixed;
top: 0;
@@ -1012,7 +1023,6 @@ span.pln {
color:grey;
}
-
@media screen and (min-width: 768px) {
p.intro {
clear: none;
@@ -1023,8 +1033,67 @@ span.pln {
}
}
-/* threadwatcher */
+/* === GENERAL CLASSES === */
+.loading {
+ background: none;
+ background-color: none;
+ background-image: url('/static/infinity.gif');
+ background-position: center center;
+ background-repeat: no-repeat;
+ min-height: 76px;
+ min-width: 128px;
+}
+
+/* Responsive helpers */
+.col {
+ box-sizing: border-box;
+ float: left;
+}
+
+.col-12 { width: 100%; }
+.col-11 { width: 91.66666667%; }
+.col-10 { width: 83.33333333%; }
+.col-9 { width: 75%; }
+.col-8 { width: 66.66666667%; }
+.col-7 { width: 58.33333333%; }
+.col-6 { width: 50%; }
+.col-5 { width: 41.66666667%; }
+.col-4 { width: 33.33333333%; }
+.col-3 { width: 25%; }
+.col-2 { width: 16.66666667%; }
+.col-1 { width: 8.33333333%; }
+
+.left-push {
+ float: left;
+}
+.right-push {
+ float: right;
+}
+
+/* Layout design */
+.box {
+ background: #D6DAF0;
+ border: 1px solid #000333;
+ color: #000333;
+ margin: 0 0 12px 0;
+}
+.box-title {
+ background: #98E;
+ color: #000333;
+ font-size: 120%;
+ font-weight: bold;
+ padding: 4px 8px;
+}
+.box-content {
+ padding: 0 8px;
+ margin: 4px 0;
+}
+
+
+/* === SPECIFIC PAGES & FEATURES === */
+
+/* threadwatcher */
#watchlist {
display: none;
max-height: 250px;
@@ -1067,25 +1136,25 @@ div.mix {
}
/* Mona Font */
-
.aa {
font-family: Mona, "MS PGothic", "MS Pゴシック", sans-serif;
display: block!important;
font-size: 12pt;
}
-
-.dx,.dy,.dz {
+.dx,
+.dy,
+.dz {
width: 30px;
text-align: right;
display: inline-block;
}
+/* Dice */
.dice-option table {
border: 1px dotted black;
margin: 0;
border-collapse: collapse;
}
-
.dice-option table td {
text-align: center;
border-left: 1px dotted black;
@@ -1095,7 +1164,6 @@ div.mix {
}
/* Quick reply (why was most of this ever in the script?) */
-
#quick-reply {
position: fixed;
right: 5%;
@@ -1261,3 +1329,109 @@ div.mix {
.dropzone .remove-btn:hover {
color: rgba(125, 125, 125, 1);
}
+
+/* Board List */
+div.boardlist {
+ margin-top: 3px;
+
+ color: #89A;
+ font-size: 9pt;
+}
+div.boardlist.bottom {
+ margin-top: 20px;
+}
+div.boardlist a {
+ text-decoration: none;
+}
+
+table.board-list-table {
+ display: table;
+ margin: -2px;
+ overflow: hidden;
+ table-layout: fixed;
+}
+
+table.board-list-table .board-meta {
+ padding-right: 4px;
+ width: 44px;
+}
+table.board-list-table .board-uri {
+ max-width: 196px;
+}
+table.board-list-table .board-title {
+ width: auto;
+}
+table.board-list-table .board-pph {
+ width: 55px;
+}
+table.board-list-table .board-max {
+ width: 90px;
+}
+table.board-list-table .board-unique {
+ width: 100px;
+}
+table.board-list-table .board-tags {
+ width: auto;
+}
+
+table.board-list-table div.board-cell {
+ max-width: 100%;
+ overflow: hidden;
+}
+
+aside.search-container {
+}
+aside.search-container .box {
+ margin-right: 12px;
+}
+
+.board-search {
+ padding: 0 0 8px 0;
+ margin: 8px;
+ border-bottom: 1px solid #000333;
+}
+.search-item {
+ margin: 8px 0;
+}
+.search-sfw {
+ cursor: pointer;
+ font-size: 110%;
+ line-height: 120%;
+ vertical-align: bottom;
+}
+#search-sfw-input {
+ margin: 0;
+ padding: 0;
+ transform: scale(1.20);
+}
+#search-lang-input,
+#search-tag-input {
+ box-sizing: border-box;
+ font-size: 110%;
+ line-height: 120%;
+ vertical-align: top;
+ padding: 2px 0 2px 4px;
+ max-width: 100%;
+ min-width: 100%;
+ width: 100%:
+}
+
+ul.tag-list {
+ display: block;
+ list-style: none;
+ padding: 0;
+ margin: 0 8px;
+}
+ul.tag-list::after {
+ content: ' ';
+ display: block;
+ clear: both;
+}
+li.tag-item {
+ display: inline-block;
+ float: left;
+ font-size: 100%;
+ list-style: none;
+ margin: 0;
+ padding: 0 0.6em 0 0;
+}
\ No newline at end of file
diff --git a/templates/8chan/boards-tags.html b/templates/8chan/boards-tags.html
index baf1e6d0..71515f1e 100644
--- a/templates/8chan/boards-tags.html
+++ b/templates/8chan/boards-tags.html
@@ -1,162 +1,90 @@
-
-
-
{% trans %}There are currently {{n_boards}} boards + {{hidden_boards_total}} unindexed boards = {{t_boards}} total boards. Site-wide, {{total_posts_hour}} posts have been made in the last hour, with {{total_posts}} being made on all active boards since October 23, 2013.{% endtrans %}
-
-{% if top2k %}
-{% trans %}This list only shows the top 2000 boards. Until we can move tag searching onto the server side, click here for the full list.{% endtrans %}
-{% endif %}
-
-
-
-
-
- B
- {% trans %}Board{% endtrans %}
- {% trans %}Title{% endtrans %}
- {% trans %}PPH{% endtrans %}
- {% trans %}Total posts{% endtrans %}
- {% trans %}Active users{% endtrans %}
- {% trans %}Tags{% endtrans %}
-
-{% for board in boards %}
-
- {{ board.img|raw }} {% if board['sfw'] %} {% else %} {% endif %}
-
- {{ board['title'] }}
- {{board['pph']}}
- {{board['max']}}
- {{board['uniq_ip']}}
- {% for tag in board.tags %}{{ tag }} {% endfor %}
-{% endfor %}
-
-Page last updated: {{last_update}}
-{{uptime_p}} without interruption (read)
-
-
+
+
+ Global Statistics
+ {% trans %}There are currently {{t_boards}} total boards, {{hidden_boards_total}} of which are unindexed. Site-wide, {{total_posts_hour}} posts have been made in the last hour, with {{total_posts}} being made on all active boards since October 23, 2013.{% endtrans %}
+ {% if uptime %}{{uptime_p}} without interruption
{% endif %}
+ This page last updated {{last_update}} .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% trans %}Board{% endtrans %}
+ {% trans %}Title{% endtrans %}
+ {% trans %}PPH{% endtrans %}
+ {% trans %}Total posts{% endtrans %}
+ {% trans %}Active users{% endtrans %}
+ {% trans %}Tags{% endtrans %}
+
+
+
+
+ {% for board in boards %}
+
+ {{ board.img|raw }} {% if board['sfw'] %} {% else %} {% endif %}
+
+ {{ board['title'] }}
+ {{board['pph']}}
+ {{board['max']}}
+ {{board['uniq_ip']}}
+ {% for tag in board.tags %}{{ tag }} {% endfor %}
+
+ {% endfor %}
+
+
+
+
+
\ No newline at end of file
diff --git a/templates/8chan/boards.html b/templates/8chan/boards.html
index 15fdad01..4687a6dd 100644
--- a/templates/8chan/boards.html
+++ b/templates/8chan/boards.html
@@ -1,68 +1,36 @@
-
-
-{% trans %}There are currently {{n_boards}} boards + {{hidden_boards_total}} unindexed boards = {{t_boards}} total boards. Site-wide, {{total_posts_hour}} posts have been made in the last hour, with {{total_posts}} being made on all active boards since October 23, 2013.{% endtrans %}
-
-
-
- L
- {% trans %}Board{% endtrans %}
- {% trans %}Board title{% endtrans %}
- {% trans %}Posts in last hour{% endtrans %}
- {% trans %}Total posts{% endtrans %}
- {% trans %}Unique IPs{% endtrans %}
- {% trans %}Created{% endtrans %}
-
-{% for board in boards %}
-
- {{ board.img|raw }}
- /{{board['uri']}}/ {{lock|raw}}
- {{ board['title'] }}
- {{board['pph']}}
- {{board['max']}}
- {{board['uniq_ip']}}
- {{board['time']}} ({{board['ago']}} ago)
-{% endfor %}
-
-Page last updated: {{last_update}}
-{{uptime_p}} without interruption
-
+
+
{% trans %}There are currently {{n_boards}} boards + {{hidden_boards_total}} unindexed boards = {{t_boards}} total boards. Site-wide, {{total_posts_hour}} posts have been made in the last hour, with {{total_posts}} being made on all active boards since October 23, 2013.{% endtrans %}
+
+
+
+
+ L
+ {% trans %}Board{% endtrans %}
+ {% trans %}Board title{% endtrans %}
+ {% trans %}Posts in last hour{% endtrans %}
+ {% trans %}Total posts{% endtrans %}
+ {% trans %}Unique IPs{% endtrans %}
+ {% trans %}Created{% endtrans %}
+
+
+
+
+
+
+ {% for board in boards %}
+
+ {{ board.img|raw }}
+ /{{board['uri']}}/ {{lock|raw}}
+ {{ board['title'] }}
+ {{board['pph']}}
+ {{board['max']}}
+ {{board['uniq_ip']}}
+ {{board['time']}} ({{board['ago']}} ago)
+
+ {% endfor %}
+
+
+
Page last updated: {{last_update}}
+
{{uptime_p}} without interruption
+
\ No newline at end of file
diff --git a/templates/8chan/index.html b/templates/8chan/index.html
index 19b42dc1..d8c6d40a 100644
--- a/templates/8chan/index.html
+++ b/templates/8chan/index.html
@@ -4,33 +4,6 @@
∞chan