Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9405848c07 |
29
.gitignore
vendored
@@ -8,35 +8,10 @@
|
||||
.\#*
|
||||
|
||||
# srnd config files
|
||||
srnd.ini
|
||||
feeds.ini
|
||||
*.ini
|
||||
|
||||
# default article store directory
|
||||
articles
|
||||
|
||||
# generated files
|
||||
webroot
|
||||
|
||||
# built binaries
|
||||
go
|
||||
srndv2
|
||||
|
||||
# private key
|
||||
*.key
|
||||
*.txt
|
||||
|
||||
# certificates
|
||||
certs
|
||||
|
||||
|
||||
rebuild.sh
|
||||
vendor
|
||||
.gx
|
||||
|
||||
# generated js
|
||||
contrib/static/nntpchan.js
|
||||
contrib/static/js/nntpchan.js
|
||||
contrib/static/miner-js.js
|
||||
|
||||
#docs trash
|
||||
doc/.trash
|
||||
webroot
|
||||
34
.gxignore
@@ -1,34 +0,0 @@
|
||||
#
|
||||
# .gxignore for nntpchan repo
|
||||
#
|
||||
|
||||
# emacs temp files
|
||||
*~
|
||||
\#*
|
||||
.\#*
|
||||
|
||||
# srnd config files
|
||||
srnd.ini
|
||||
feeds.ini
|
||||
|
||||
# default article store directory
|
||||
articles/
|
||||
|
||||
# generated files
|
||||
webroot/
|
||||
|
||||
# built binaries
|
||||
go/
|
||||
srndv2
|
||||
nntpchan
|
||||
|
||||
# private key
|
||||
*.key
|
||||
*.txt
|
||||
|
||||
# certificates
|
||||
certs/
|
||||
|
||||
rebuild.sh
|
||||
|
||||
.git
|
||||
60
README.md
@@ -1,56 +1,34 @@
|
||||
NNTPChan
|
||||
========
|
||||
# NNTPChan #
|
||||
|
||||
**NNTPChan** (previously known as overchan) is a decentralized imageboard that uses the [NNTP protocol](https://en.wikipedia.org/wiki/Network_News_Transfer_Protocol) (network-news transfer protocol) to synchronize content between many different servers. It utilizes cryptographically signed posts to perform optional/opt-in decentralized moderation.
|
||||
NNTPChan (previously known as overchan) is a decentralized imageboard that uses nntp to synchronize content between many different servers. It utilizes cryptographically signed posts to perform optional/opt-in decentralized moderation.
|
||||
|
||||
This repository contains resources used by the core daemon which is located on [GitHub](https://github.com/majestrate/srndv2) (for now) along with general documentation, [here](doc/).
|
||||
This repository contains resources used by the core daemon which is located [here](https://github.com/majestrate/srndv2) along with general documentation, [here](doc/)
|
||||
|
||||
##Getting started
|
||||
## getting started ##
|
||||
|
||||
[This](doc) is a step-by-step guide for getting up-and-running with NNTPChan as well as documentation for developers who want to either work on NNTPChan directly or use NNTPChan in their aplications with the API.
|
||||
After you [built and installed the daemon](doc/build.md) and [set up your database](doc/database.md), clone this repository and start up the daemon
|
||||
|
||||
##Bugs and issues
|
||||
# clone it
|
||||
git clone https://github.com/majestrate/nntpchan ~/nntpchan
|
||||
# get the latest stable release
|
||||
cd ~/nntpchan/
|
||||
git checkout tags/0.2.1
|
||||
|
||||
*PLEASE* report any bugs you find while building, setting-up or using NNTPChan on the [GitHub issue tracker](https://github.com/majestrate/nntpchan/issues) or on the [GitGud issue tracker](https://gitgud.io/uguu/nntpchan/issues) so that the probelms can be resolved or discussed.
|
||||
# set up the workspace
|
||||
srndv2 setup
|
||||
|
||||
##Active NNTPChan nodes
|
||||
|
||||
Below is a list of known NNTPChan nodes:
|
||||
|
||||
1. [2hu-ch.org](https://2hu-ch.org)
|
||||
2. [nsfl.tk](https://nsfl.tk)
|
||||
3. [gchan](https://gchan.xyz/)
|
||||
|
||||
Tor node list:
|
||||
|
||||
1. [textpunk](http://ucavviu7wl6azuw7.onion/)
|
||||
2. [chan](http://ev7fnjzjdbtu3miq.onion/)
|
||||
3. [oniichan](http://sfw.oniichanylo2tsi4.onion/)
|
||||
|
||||
##Clients
|
||||
|
||||
NNTP (confirmed working):
|
||||
|
||||
* Thunderbird
|
||||
|
||||
Web:
|
||||
|
||||
* [Yukko](https://github.com/faissaloo/Yukko): ncurses based nntpchan web ui reader
|
||||
# run the daemon
|
||||
srndv2 run
|
||||
|
||||
|
||||
##Support
|
||||
Then open http://127.0.0.1:18000/ukko.html in your browser.
|
||||
|
||||
Need help? Join us on IRC.
|
||||
*PLEASE* report any bugs you find while setting up or building [(here)](https://github.com/majestrate/nntpchan/issues) so that the problems get fixed (^:
|
||||
|
||||
1. [freenode: #nntpchan](https://webchat.freenode.net/?channels=#nntpchan)
|
||||
2. [rizon: #nntpchan](https://qchat.rizon.net/?channels=#nntpchan) - Most active
|
||||
For peering requests, questions or support find me on [rizon](https://qchat.rizon.net/?channels=#nntpchan) as \__uguu\__
|
||||
|
||||
##Donations
|
||||
|
||||
Like this project? Why not help by funding it?
|
||||
Like this project? Fund it:
|
||||
|
||||
Bitcoin: [15yuMzuueV8y5vPQQ39ZqQVz5Ey98DNrjE](bitcoin://15yuMzuueV8y5vPQQ39ZqQVz5Ey98DNrjE)
|
||||
bitcoin: 15yuMzuueV8y5vPQQ39ZqQVz5Ey98DNrjE
|
||||
|
||||
##Acknowledgements
|
||||
|
||||
* [Deavmi](https://deavmi.carteronline.net/) - Making the documentation beautiful.
|
||||
|
||||
7
TODO.md
@@ -1,7 +0,0 @@
|
||||
## TODO ##
|
||||
|
||||
* extra stylesheets
|
||||
* more alternative templates
|
||||
* javascript free mod panel
|
||||
* liveui
|
||||
* easier peering
|
||||
119
build-js.sh
@@ -1,119 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
neochan="yes"
|
||||
if [ "$1" == "--disable-neochan" ] ; then
|
||||
neochan="no"
|
||||
fi
|
||||
|
||||
root=$(readlink -e "$(dirname "$0")")
|
||||
set -e
|
||||
if [ "x" == "x$root" ] ; then
|
||||
root=$PWD/${0##*}
|
||||
fi
|
||||
cd "$root"
|
||||
|
||||
if [ -z "$GOPATH" ]; then
|
||||
export GOPATH=$root/go
|
||||
mkdir -p "$GOPATH"
|
||||
fi
|
||||
|
||||
if [ ! -f "$GOPATH/bin/minify" ]; then
|
||||
echo "set up minifiy"
|
||||
go get -v github.com/tdewolff/minify/cmd/minify
|
||||
fi
|
||||
|
||||
outfile="$PWD/contrib/static/nntpchan.js"
|
||||
neochan_js_outfile="$PWD/contrib/static/neochan.js"
|
||||
neochan_css_outfile="$PWD/contrib/static/neochan.css"
|
||||
|
||||
mini() {
|
||||
echo "minify $1"
|
||||
echo "" >> $2
|
||||
echo "/* begin $1 */" >> $2
|
||||
"$GOPATH/bin/minify" --mime=text/javascript >> $2 < $1
|
||||
echo "" >> $2
|
||||
echo "/* end $1 */" >> $2
|
||||
}
|
||||
|
||||
css() {
|
||||
echo "minify $1"
|
||||
echo "" >> $2
|
||||
echo "/* begin $1 */" >> $2
|
||||
lessc $1 >> $2
|
||||
echo "" >> $2
|
||||
echo "/* end $1 */" >> $2
|
||||
}
|
||||
|
||||
initfile() {
|
||||
|
||||
rm -f "$1"
|
||||
|
||||
echo '/*' >> "$1"
|
||||
echo ' * For source code and license information please check https://github.com/majestrate/nntpchan' >> "$1"
|
||||
brandingfile=./contrib/branding.txt
|
||||
if [ -e "$brandingfile" ] ; then
|
||||
echo ' *' >> "$1"
|
||||
while read line; do
|
||||
echo -n ' * ' >> "$1";
|
||||
echo $line >> "$1";
|
||||
done < $brandingfile;
|
||||
fi
|
||||
echo ' */' >> "$1"
|
||||
}
|
||||
echo
|
||||
echo "building nntpchan.js ..."
|
||||
echo
|
||||
initfile "$outfile"
|
||||
|
||||
if [ -e ./contrib/js/contrib/*.js ] ; then
|
||||
for f in ./contrib/js/contrib/*.js ; do
|
||||
mini "$f" "$outfile"
|
||||
done
|
||||
fi
|
||||
|
||||
mini ./contrib/js/entry.js "$outfile"
|
||||
|
||||
# local js
|
||||
for f in ./contrib/js/nntpchan/*.js ; do
|
||||
mini "$f" "$outfile"
|
||||
done
|
||||
|
||||
# vendor js
|
||||
for f in ./contrib/js/vendor/*.js ; do
|
||||
mini "$f" "$outfile"
|
||||
done
|
||||
|
||||
if [ "$neochan" == "yes" ] ; then
|
||||
set +e
|
||||
for exe in lessc coffee ; do
|
||||
which $exe &> /dev/null
|
||||
if [ "$?" != "0" ] ; then
|
||||
echo "$exe not installed";
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "building neochan.js ..."
|
||||
echo
|
||||
|
||||
initfile "$neochan_js_outfile"
|
||||
for f in ./contrib/js/neochan/*.coffee ; do
|
||||
echo "compile $f"
|
||||
coffee -cs < "$f" > "$f.js"
|
||||
done
|
||||
for f in ./contrib/js/neochan/*.js ; do
|
||||
mini "$f" "$neochan_js_outfile"
|
||||
done
|
||||
|
||||
echo
|
||||
echo "building neochan.css ..."
|
||||
echo
|
||||
initfile "$neochan_css_outfile"
|
||||
for f in ./contrib/js/neochan/*.less ; do
|
||||
css "$f" "$neochan_css_outfile"
|
||||
done
|
||||
|
||||
fi
|
||||
echo
|
||||
echo "ok"
|
||||
106
build.sh
@@ -1,106 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
root=$(readlink -e "$(dirname "$0")")
|
||||
set -e
|
||||
if [ "" == "$root" ] ; then
|
||||
root=$PWD/${0##*}
|
||||
fi
|
||||
cd "$root"
|
||||
|
||||
tags="-tags disable_redis"
|
||||
|
||||
help_text="usage: $0 [--disable-neochan]"
|
||||
|
||||
# check for help flags first
|
||||
for arg in "$@" ; do
|
||||
case $arg in
|
||||
-h|--help)
|
||||
echo "$help_text"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
rev="QmPAqM7anxdr1ngPmJz9J9AAxDLinDz2Eh9aAzLF9T7LNa"
|
||||
ipfs="no"
|
||||
rebuildjs="yes"
|
||||
_next=""
|
||||
unstable="no"
|
||||
neochan="yes"
|
||||
# check for build flags
|
||||
for arg in "$@" ; do
|
||||
case $arg in
|
||||
"--disable-neochan")
|
||||
neochan="no"
|
||||
;;
|
||||
"--unstable")
|
||||
unstable="yes"
|
||||
;;
|
||||
"--no-js")
|
||||
rebuildjs="no"
|
||||
;;
|
||||
"--ipfs")
|
||||
ipfs="yes"
|
||||
;;
|
||||
"--revision")
|
||||
_next="rev"
|
||||
;;
|
||||
"--revision=*")
|
||||
rev=$(echo "$arg" | cut -d'=' -f2)
|
||||
;;
|
||||
*)
|
||||
if [ "x$_next" == "xrev" ] ; then
|
||||
rev="$arg"
|
||||
fi
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$rev" == "" ] ; then
|
||||
echo "revision not specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$root"
|
||||
if [ "$rebuildjs" == "yes" ] ; then
|
||||
echo "rebuilding generated js..."
|
||||
if [ "$neochan" == "no" ] ; then
|
||||
./build-js.sh --disable-neochan
|
||||
else
|
||||
./build-js.sh
|
||||
fi
|
||||
fi
|
||||
|
||||
unset GOPATH
|
||||
export GOPATH=$PWD/go
|
||||
mkdir -p "$GOPATH"
|
||||
|
||||
if [ "$ipfs" == "yes" ] ; then
|
||||
if [ ! -e "$GOPATH/bin/gx" ] ; then
|
||||
echo "obtaining gx"
|
||||
go get -u -v github.com/whyrusleeping/gx
|
||||
fi
|
||||
if [ ! -e "$GOPATH/bin/gx-go" ] ; then
|
||||
echo "obtaining gx-go"
|
||||
go get -u -v github.com/whyrusleeping/gx-go
|
||||
fi
|
||||
echo "building stable revision, this will take a bit. to speed this part up install and run ipfs locally"
|
||||
mkdir -p "$GOPATH/src/gx/ipfs"
|
||||
cd "$GOPATH/src/gx/ipfs"
|
||||
"$GOPATH/bin/gx" get "$rev"
|
||||
cd "$root"
|
||||
go get -d -v
|
||||
go build -v .
|
||||
mv nntpchan srndv2
|
||||
echo -e "Built\n"
|
||||
echo "Now configure NNTPChan with ./srndv2 setup"
|
||||
else
|
||||
if [ "$unstable" == "yes" ] ; then
|
||||
go get -u -v github.com/majestrate/srndv2/cmd/nntpchan
|
||||
cp "$GOPATH/bin/nntpchan" "$root"
|
||||
echo "built unstable, if you don't know what to do, run without --unstable"
|
||||
else
|
||||
go get -u -v github.com/majestrate/srndv2
|
||||
cp "$GOPATH/bin/srndv2" "$root"
|
||||
echo -e "Built\n"
|
||||
echo "Now configure NNTPChan with ./srndv2 setup"
|
||||
fi
|
||||
fi
|
||||
@@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=NNTPChan Server
|
||||
Requires=redis_6379.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/opt/nntpchan
|
||||
ExecStart=/opt/nntpchan/srndv2 run
|
||||
ExecStop=/bin/kill -15 $MAINPID
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,76 +0,0 @@
|
||||
Date: October 2015.
|
||||
|
||||
Getting the srndv2 tool
|
||||
|
||||
I am using debian, you should be able to use most any linux distro for this. Known to work are: debian, arch linux, <TODO: add more>.
|
||||
|
||||
Most commands should be done as a normal user, but some special commands need to be done as root. I find it useful to have two terminals open. I'll denote normal user level commands with '$' and root command with '#'.
|
||||
|
||||
Some dependencies you will need to install (as root) are:
|
||||
|
||||
# apt-get install build-essential golang git
|
||||
# apt-get install libsodium-dev ffmpegthumbnailer
|
||||
# apt-get install imagemagick ffmpegthumbnailer sox
|
||||
|
||||
The source code is in these two repos:
|
||||
|
||||
* https://github.com/majestrate/nntpchan
|
||||
* https://github.com/majestrate/srndv2
|
||||
|
||||
set up your GOPATH (notes on that here: https://golang.org/doc/code.html#GOPATH ) and then install and build it:
|
||||
|
||||
$ go get -u github.com/majestrate/srndv2
|
||||
|
||||
If that command didn't work read the errors and check if you lacked any dependencies.
|
||||
|
||||
Now you have the srndv2 tool which you can run, but it will not work yet: You need to step up an SQL database first.
|
||||
|
||||
--------------
|
||||
|
||||
Setting up an SQL database
|
||||
|
||||
* https://wiki.postgresql.org/wiki/Detailed_installation_guides
|
||||
|
||||
Install postgresql.
|
||||
|
||||
# apt-get install postgresql postgresql-client
|
||||
|
||||
Create a postgresql user called 'srnd' and a database 'srnd':
|
||||
|
||||
# su postgres
|
||||
$ whoami
|
||||
postgres
|
||||
$ psql -f nntpchan/nntp.psql
|
||||
|
||||
TODO: Get correct filename here.
|
||||
|
||||
Test if you can log in to that SQL user this way:
|
||||
|
||||
$ psql -d srnd -U srnd
|
||||
|
||||
If there is an issue with that try the following from the debian wiki:
|
||||
|
||||
------------
|
||||
edit pg_hba.conf in /etc/postgresql/X.Y/main/pg_hba.conf
|
||||
|
||||
local all all trust # replace ident or peer with trust
|
||||
|
||||
reload postgresql
|
||||
|
||||
# /etc/init.d/postgresql reload
|
||||
------------
|
||||
|
||||
hit Contol-D to get back your root terminal after doing this.
|
||||
|
||||
|
||||
Once SQL setup is successful..
|
||||
|
||||
|
||||
Now as your regular user that installed the srndv2 tool, you should be able to set up srndv2
|
||||
|
||||
First clone nntpchan and cd into it, then ask the srndv2 tool to setup your node:
|
||||
|
||||
$ git clone https://github.com/majestrate/nntpchan.git
|
||||
$ cd nntpchann
|
||||
ntpchan/$ srndv2 setup
|
||||
ntpchan/$ srndv2 tool keygen
|
||||
@@ -1,89 +0,0 @@
|
||||
<?php
|
||||
|
||||
function gennntp($headers, $files) {
|
||||
if (count($files) == 0) {
|
||||
}
|
||||
else if (count($files) == 1 && $files[0]['type'] == 'text/plain') {
|
||||
$content = $files[0]['text'] . "\r\n";
|
||||
$headers['Content-Type'] = "text/plain; charset=UTF-8";
|
||||
}
|
||||
else {
|
||||
$boundary = sha1($headers['Message-Id']);
|
||||
$content = "";
|
||||
$headers['Content-Type'] = "multipart/mixed; boundary=$boundary";
|
||||
foreach ($files as $file) {
|
||||
$content .= "--$boundary\r\n";
|
||||
if (isset($file['name'])) {
|
||||
$file['name'] = preg_replace('/[\r\n\0"]/', '', $file['name']);
|
||||
$content .= "Content-Disposition: form-data; filename=\"$file[name]\"; name=\"attachment\"\r\n";
|
||||
}
|
||||
$type = explode('/', $file['type'])[0];
|
||||
if ($type == 'text') {
|
||||
$file['type'] .= '; charset=UTF-8';
|
||||
}
|
||||
$content .= "Content-Type: $file[type]\r\n";
|
||||
if ($type != 'text' && $type != 'message') {
|
||||
$file['text'] = base64_encode($file['text']);
|
||||
$content .= "Content-Transfer-Encoding: base64\r\n";
|
||||
}
|
||||
$content .= "\r\n";
|
||||
$content .= $file['text'];
|
||||
$content .= "\r\n";
|
||||
}
|
||||
$content .= "--$boundary--\r\n";
|
||||
}
|
||||
|
||||
//$headers['Content-Length'] = strlen($content);
|
||||
$headers['Mime-Version'] = '1.0';
|
||||
$headers['Date'] = date('r', $headers['Date']);
|
||||
|
||||
$out = "";
|
||||
foreach ($headers as $id => $val) {
|
||||
$val = str_replace("\n", "\n\t", $val);
|
||||
$out .= "$id: $val\r\n";
|
||||
}
|
||||
$out .= "\r\n";
|
||||
$out .= $content;
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
function shoveitup($msg, $id) {
|
||||
$s = fsockopen("tcp://localhost:1119");
|
||||
fgets($s);
|
||||
fputs($s, "MODE STREAM\r\n");
|
||||
fgets($s);
|
||||
fputs($s, "TAKETHIS $id\r\n");
|
||||
fputs($s, $msg);
|
||||
fputs($s, "\r\n.\r\n");
|
||||
fgets($s);
|
||||
fclose($s);
|
||||
}
|
||||
|
||||
$time = time();
|
||||
|
||||
echo "\n@@@@ Thread:\n";
|
||||
echo $m0 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.0000.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None"],
|
||||
[['type' => 'text/plain', 'text' => "THIS IS A NEW TEST THREAD"]]);
|
||||
|
||||
echo "\n@@@@ Single msg:\n";
|
||||
echo $m1 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.1234.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"],
|
||||
[['type' => 'text/plain', 'text' => "hello world, with no image :("]]);
|
||||
|
||||
echo "\n@@@@ Single msg and pseudoimage:\n";
|
||||
echo $m2 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.2137.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"],
|
||||
[['type' => 'text/plain', 'text' => "hello world, now with an image!"],
|
||||
['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif.gif"]]);
|
||||
|
||||
echo "\n@@@@ Single msg and two pseudoimages:\n";
|
||||
echo $m3 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.1488.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"],
|
||||
[['type' => 'text/plain', 'text' => "hello world, now WITH TWO IMAGES!!!"],
|
||||
['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif.gif"],
|
||||
['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif2.gif"]]);
|
||||
|
||||
shoveitup($m0, "<1234.0000.".$time."@example.vichan.net>");
|
||||
sleep(1);
|
||||
shoveitup($m1, "<1234.1234.".$time."@example.vichan.net>");
|
||||
sleep(1);
|
||||
shoveitup($m2, "<1234.2137.".$time."@example.vichan.net>");
|
||||
shoveitup($m3, "<1234.2131.".$time."@example.vichan.net>");
|
||||
9842
contrib/js/contrib/jquery.js
vendored
@@ -1 +0,0 @@
|
||||
3rd party javascript
|
||||
@@ -1,11 +0,0 @@
|
||||
onready_callbacks = [];
|
||||
function onready(fnc) {
|
||||
onready_callbacks.push(fnc);
|
||||
}
|
||||
|
||||
function ready() {
|
||||
for (var i = 0; i < onready_callbacks.length; i++) {
|
||||
onready_callbacks[i]();
|
||||
}
|
||||
}
|
||||
|
||||
1
contrib/js/neochan/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
*.coffee.js
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# neochan javascript directory
|
||||
|
||||
sass files for neochan templates
|
||||
@@ -1,41 +0,0 @@
|
||||
// call an api method
|
||||
// handler(json_object) on success
|
||||
// handler(null) on fail
|
||||
function nntpchan_apicall(url, handler, err_handler) {
|
||||
var ajax = new XMLHttpRequest();
|
||||
ajax.onreadystatechange = function() {
|
||||
if (ajax.readyState == XMLHttpRequest.DONE ) {
|
||||
var status = ajax.status;
|
||||
var j = null;
|
||||
if (status == 200) {
|
||||
// found
|
||||
try {
|
||||
j = JSON.parse(ajax.responseText);
|
||||
} catch (e) {} // ignore parse error
|
||||
} else if (status == 410) {
|
||||
if (err_handler) {err_handler("cannot fetch post: api disabled");}
|
||||
return;
|
||||
}
|
||||
handler(j);
|
||||
}
|
||||
};
|
||||
ajax.open("GET", url);
|
||||
ajax.send();
|
||||
}
|
||||
|
||||
// build post from json
|
||||
// inject into parent
|
||||
// if j is null then inject "not found" post
|
||||
function nntpchan_buildpost(parent, j) {
|
||||
var post = document.createElement("div");
|
||||
if (j) {
|
||||
// huehuehue
|
||||
post.innerHTML = j.PostMarkup;
|
||||
inject_hover_for_element(post);
|
||||
} else {
|
||||
post.setAttribute("class", "notfound post");
|
||||
post.appendChild(document.createTextNode("post not found"));
|
||||
}
|
||||
parent.appendChild(post);
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
var banner_count = 5;
|
||||
|
||||
// inject a banner into an element
|
||||
function nntpchan_inject_banners(elem, prefix) {
|
||||
var n = Math.floor(Math.random() * banner_count);
|
||||
var banner = prefix + "static/banner_"+n+".jpg";
|
||||
var e = document.createElement("img");
|
||||
e.src = banner;
|
||||
e.id = "nntpchan_banner";
|
||||
elem.appendChild(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
function setSrcQuery(e, q) {
|
||||
var src = e.src;
|
||||
var p = src.indexOf('?');
|
||||
if (p >= 0) {
|
||||
src = src.substr(0, p);
|
||||
}
|
||||
e.src = src + "?" + q
|
||||
}
|
||||
|
||||
|
||||
function reload(el) {
|
||||
setSrcQuery(el, "reload=" + (new Date()).getTime());
|
||||
return false;
|
||||
}
|
||||
|
||||
onready(function(){
|
||||
document.getElementById("captcha_img").onclick = function() {
|
||||
reload(document.getElementById("captcha_img"));
|
||||
};
|
||||
});
|
||||
@@ -1,70 +0,0 @@
|
||||
//
|
||||
// expand images inline
|
||||
//
|
||||
// released into the public domain by Jeff on 2016-04-30
|
||||
//
|
||||
|
||||
// is the filename matching an image?
|
||||
function filenameIsImage(fname) {
|
||||
return /\.(gif|jpeg|jpg|png|webp)/.test(fname.toLowerCase());
|
||||
}
|
||||
|
||||
// setup image inlining for 1 element
|
||||
function setupInlineImage(thumb, url) {
|
||||
if(thumb.inlineIsSetUp) return;
|
||||
thumb.inlineIsSetUp = true;
|
||||
var img = thumb.querySelector("img.thumbnail");
|
||||
var expanded = false;
|
||||
var oldurl = img.src;
|
||||
thumb.onclick = function() {
|
||||
if (expanded) {
|
||||
img.setAttribute("class", "thumbnail");
|
||||
img.src = oldurl;
|
||||
expanded = false;
|
||||
} else {
|
||||
img.setAttribute("class", "expanded-thumbnail");
|
||||
img.src = url;
|
||||
expanded = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// set up image inlining for all applicable children in an element
|
||||
function setupInlineImageIn(element) {
|
||||
var thumbs = element.querySelectorAll("a.file");
|
||||
for ( var i = 0 ; i < thumbs.length ; i++ ) {
|
||||
var url = thumbs[i].href;
|
||||
if (filenameIsImage(url)) {
|
||||
// match
|
||||
console.log("matched url", url);
|
||||
setupInlineImage(thumbs[i], url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onready(function(){
|
||||
|
||||
// Setup Javascript events for document
|
||||
setupInlineImageIn(document);
|
||||
|
||||
|
||||
// Setup Javascript events via updatoer
|
||||
if (window.MutationObserver) {
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
for (var i = 0; i < mutations.length; i++) {
|
||||
var additions = mutations[i].addedNodes;
|
||||
if (additions == null) continue;
|
||||
for (var j = 0; j < additions.length; j++) {
|
||||
var node = additions[j];
|
||||
if (node.nodeType == 1) {
|
||||
setupInlineImageIn(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(document.body, {childList: true, subtree: true});
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,246 +0,0 @@
|
||||
/* This file is dedicated to the public domain; you may do as you wish with it. */
|
||||
/* Note: This code expects the global variable configRoot to be set. */
|
||||
var configRoot = "";
|
||||
|
||||
|
||||
if (typeof _ == 'undefined') {
|
||||
var _ = function(a) { return a; };
|
||||
}
|
||||
|
||||
function setupVideo(thumb, url) {
|
||||
if (thumb.videoAlreadySetUp) return;
|
||||
thumb.videoAlreadySetUp = true;
|
||||
|
||||
var video = null;
|
||||
var videoContainer, videoHide;
|
||||
var expanded = false;
|
||||
var hovering = false;
|
||||
//var loop = setting("videoloop");
|
||||
var loop = true;
|
||||
var loopControls = [document.createElement("span"), document.createElement("span")];
|
||||
var fileInfo = thumb.parentNode.querySelector(".fileinfo");
|
||||
var mouseDown = false;
|
||||
|
||||
function unexpand() {
|
||||
if (expanded) {
|
||||
expanded = false;
|
||||
if (video.pause) video.pause();
|
||||
videoContainer.style.display = "none";
|
||||
thumb.style.display = "inline";
|
||||
video.style.maxWidth = "inherit";
|
||||
video.style.maxHeight = "inherit";
|
||||
}
|
||||
}
|
||||
|
||||
function unhover() {
|
||||
if (hovering) {
|
||||
hovering = false;
|
||||
if (video.pause) video.pause();
|
||||
videoContainer.style.display = "none";
|
||||
video.style.maxWidth = "inherit";
|
||||
video.style.maxHeight = "inherit";
|
||||
}
|
||||
}
|
||||
|
||||
// Create video element if does not exist yet
|
||||
function getVideo() {
|
||||
if (video == null) {
|
||||
video = document.createElement("video");
|
||||
video.src = url;
|
||||
video.loop = loop;
|
||||
video.innerText = _("Your browser does not support HTML5 video.");
|
||||
|
||||
videoHide = document.createElement("img");
|
||||
videoHide.src = configRoot + "static/collapse.gif";
|
||||
videoHide.alt = "[ - ]";
|
||||
videoHide.title = "Collapse video";
|
||||
videoHide.style.marginLeft = "-15px";
|
||||
videoHide.style.cssFloat = "left";
|
||||
videoHide.addEventListener("click", unexpand, false);
|
||||
|
||||
videoContainer = document.createElement("div");
|
||||
videoContainer.style.paddingLeft = "15px";
|
||||
videoContainer.style.display = "none";
|
||||
videoContainer.appendChild(videoHide);
|
||||
videoContainer.appendChild(video);
|
||||
thumb.parentNode.insertBefore(videoContainer, thumb.nextSibling);
|
||||
|
||||
// Dragging to the left collapses the video
|
||||
video.addEventListener("mousedown", function(e) {
|
||||
if (e.button == 0) mouseDown = true;
|
||||
}, false);
|
||||
video.addEventListener("mouseup", function(e) {
|
||||
if (e.button == 0) mouseDown = false;
|
||||
}, false);
|
||||
video.addEventListener("mouseenter", function(e) {
|
||||
mouseDown = false;
|
||||
}, false);
|
||||
video.addEventListener("mouseout", function(e) {
|
||||
if (mouseDown && e.clientX - video.getBoundingClientRect().left <= 0) {
|
||||
unexpand();
|
||||
}
|
||||
mouseDown = false;
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Clicking on thumbnail expands video
|
||||
thumb.addEventListener("click", function(e) {
|
||||
if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
||||
getVideo();
|
||||
expanded = true;
|
||||
hovering = false;
|
||||
|
||||
video.style.position = "static";
|
||||
video.style.pointerEvents = "inherit";
|
||||
video.style.display = "inline";
|
||||
videoHide.style.display = "inline";
|
||||
videoContainer.style.display = "block";
|
||||
videoContainer.style.position = "static";
|
||||
video.parentNode.parentNode.removeAttribute('style');
|
||||
thumb.style.display = "none";
|
||||
|
||||
//video.muted = (setting("videovolume") == 0);
|
||||
//video.volume = setting("videovolume");
|
||||
video.controls = true;
|
||||
if (video.readyState == 0) {
|
||||
video.addEventListener("loadedmetadata", expand2, false);
|
||||
} else {
|
||||
setTimeout(expand2, 0);
|
||||
}
|
||||
video.play();
|
||||
e.preventDefault();
|
||||
}
|
||||
}, false);
|
||||
|
||||
function expand2() {
|
||||
video.style.maxWidth = "100%";
|
||||
video.style.maxHeight = window.innerHeight + "px";
|
||||
var bottom = video.getBoundingClientRect().bottom;
|
||||
if (bottom > window.innerHeight) {
|
||||
window.scrollBy(0, bottom - window.innerHeight);
|
||||
}
|
||||
// work around Firefox volume control bug
|
||||
//video.volume = Math.max(setting("videovolume") - 0.001, 0);
|
||||
//video.volume = setting("videovolume");
|
||||
}
|
||||
|
||||
// Hovering over thumbnail displays video
|
||||
thumb.addEventListener("mouseover", function(e) {
|
||||
//if (setting("videohover")) {
|
||||
if (false) { // DOESN'T WORK YET
|
||||
getVideo();
|
||||
expanded = false;
|
||||
hovering = true;
|
||||
|
||||
var docRight = document.documentElement.getBoundingClientRect().right;
|
||||
var thumbRight = thumb.querySelector("img, video").getBoundingClientRect().right;
|
||||
var maxWidth = docRight - thumbRight - 20;
|
||||
if (maxWidth < 250) maxWidth = 250;
|
||||
|
||||
video.style.position = "fixed";
|
||||
video.style.right = "0px";
|
||||
video.style.top = "0px";
|
||||
var docRight = document.documentElement.getBoundingClientRect().right;
|
||||
var thumbRight = thumb.querySelector("img, video").getBoundingClientRect().right;
|
||||
video.style.maxWidth = maxWidth + "px";
|
||||
video.style.maxHeight = "100%";
|
||||
video.style.pointerEvents = "none";
|
||||
|
||||
video.style.display = "inline";
|
||||
videoHide.style.display = "none";
|
||||
videoContainer.style.display = "inline";
|
||||
videoContainer.style.position = "fixed";
|
||||
|
||||
//video.muted = (setting("videovolume") == 0);
|
||||
//video.volume = setting("videovolume");
|
||||
video.controls = false;
|
||||
video.play();
|
||||
}
|
||||
}, false);
|
||||
|
||||
thumb.addEventListener("mouseout", unhover, false);
|
||||
|
||||
// Scroll wheel on thumbnail adjusts default volume
|
||||
thumb.addEventListener("wheel", function(e) {
|
||||
//if (setting("videohover")) {
|
||||
if (true) {
|
||||
//var volume = setting("videovolume");
|
||||
if (e.deltaY > 0) volume -= 0.1;
|
||||
if (e.deltaY < 0) volume += 0.1;
|
||||
if (volume < 0) volume = 0;
|
||||
if (volume > 1) volume = 1;
|
||||
if (video != null) {
|
||||
video.muted = (volume == 0);
|
||||
video.volume = volume;
|
||||
}
|
||||
//changeSetting("videovolume", volume);
|
||||
e.preventDefault();
|
||||
}
|
||||
}, false);
|
||||
|
||||
// [play once] vs [loop] controls
|
||||
/*function setupLoopControl(i) {
|
||||
loopControls[i].addEventListener("click", function(e) {
|
||||
loop = (i != 0);
|
||||
thumb.href = thumb.href.replace(/([\?&])loop=\d+/, "$1loop=" + i);
|
||||
if (video != null) {
|
||||
video.loop = loop;
|
||||
if (loop && video.currentTime >= video.duration) {
|
||||
video.currentTime = 0;
|
||||
}
|
||||
}
|
||||
loopControls[i].style.fontWeight = "bold";
|
||||
loopControls[1-i].style.fontWeight = "inherit";
|
||||
}, false);
|
||||
}
|
||||
|
||||
loopControls[0].textContent = _("[play once]");
|
||||
loopControls[1].textContent = _("[loop]");
|
||||
loopControls[(setting("videoloop") ? 1 : 0)].style.fontWeight = "bold";
|
||||
for (var i = 0; i < 2; i++) {
|
||||
setupLoopControl(i);
|
||||
loopControls[i].style.whiteSpace = "nowrap";
|
||||
fileInfo.appendChild(document.createTextNode(" "));
|
||||
fileInfo.appendChild(loopControls[i]);
|
||||
}*/
|
||||
}
|
||||
|
||||
function setupVideosIn(element) {
|
||||
var thumbs = element.querySelectorAll("a.file");
|
||||
for (var i = 0; i < thumbs.length; i++) {
|
||||
if (/(\.webm)|(\.mp4)$/.test(thumbs[i].pathname)) {
|
||||
setupVideo(thumbs[i], thumbs[i].href);
|
||||
} else {
|
||||
var url = thumbs[i].href;
|
||||
if (/(\.webm)|(\.mp4)$/.test(url)) setupVideo(thumbs[i], url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onready(function(){
|
||||
// Insert menu from settings.js
|
||||
if (typeof settingsMenu != "undefined" && typeof Options == "undefined")
|
||||
document.body.insertBefore(settingsMenu, document.getElementsByTagName("hr")[0]);
|
||||
|
||||
// Setup Javascript events for videos in document now
|
||||
setupVideosIn(document);
|
||||
|
||||
// Setup Javascript events for videos added by updater
|
||||
if (window.MutationObserver) {
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
for (var i = 0; i < mutations.length; i++) {
|
||||
var additions = mutations[i].addedNodes;
|
||||
if (additions == null) continue;
|
||||
for (var j = 0; j < additions.length; j++) {
|
||||
var node = additions[j];
|
||||
if (node.nodeType == 1) {
|
||||
setupVideosIn(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(document.body, {childList: true, subtree: true});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,206 +0,0 @@
|
||||
/** hidepost.js -- hides posts from page given $things */
|
||||
|
||||
|
||||
function get_hidden_posts() {
|
||||
var st = get_storage();
|
||||
var prefix = "nntpchan_hide_post_";
|
||||
return {
|
||||
all : function() {
|
||||
var msgids = [];
|
||||
for ( var k in st) {
|
||||
if (k.indexOf(prefix) == 0) {
|
||||
var m = k.substring(prefix.length);
|
||||
msgids.push(m);
|
||||
}
|
||||
}
|
||||
return msgids;
|
||||
},
|
||||
|
||||
add : function (msg) {
|
||||
st[prefix+msg] = "post";
|
||||
},
|
||||
|
||||
del : function (msg) {
|
||||
st.removeItem(prefix+msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// is a post elem an OP?
|
||||
function postIsOP(elem) {
|
||||
var ds = elem.dataset;
|
||||
return ds && ds.rootmsgid == ds.msgid ;
|
||||
}
|
||||
|
||||
function _hide_elem(elem, fade) {
|
||||
if(!fade) {
|
||||
if (elem.style) {
|
||||
elem.style.display = "none";
|
||||
} else {
|
||||
elem.style = {display: "none" };
|
||||
}
|
||||
elem.dataset.userhide = "yes";
|
||||
} else {
|
||||
$(elem).fadeOut(400, function() {
|
||||
_hide_elem(elem);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function _unhide_elem(elem) {
|
||||
$(elem).fadeIn();
|
||||
elem.dataset.userhide = "no";
|
||||
}
|
||||
|
||||
// return true if element is hidden
|
||||
function _elemIsHidden(elem) {
|
||||
return elem.dataset && elem.dataset.userhide == "yes";
|
||||
}
|
||||
|
||||
// hide a post
|
||||
function hidepost(elem, nofade) {
|
||||
console.log("hidepost("+elem.dataset.msgid+")");
|
||||
var posts = get_hidden_posts();
|
||||
if (posts) {
|
||||
// add to persitant hide
|
||||
posts.add(elem.dataset.msgidhash);
|
||||
}
|
||||
if(postIsOP(elem)) {
|
||||
// hide thread it's an OP
|
||||
var thread = document.getElementById("thread_"+elem.dataset.rootmsgidhash);
|
||||
if (thread) {
|
||||
var e = thread.getElementsByClassName("post");
|
||||
for ( var idx = 0; idx < e.length ; idx ++ ) {
|
||||
if (e[idx].dataset.msgid == elem.dataset.msgid) continue; // don't apply
|
||||
hidepost(e[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// hide attachments and post body
|
||||
var es = elem.getElementsByClassName("attachments");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_hide_elem(es[idx], !nofade);
|
||||
}
|
||||
es = elem.getElementsByClassName("post_body");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_hide_elem(es[idx], !nofade);
|
||||
}
|
||||
es = elem.getElementsByClassName("postheader");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_hide_elem(es[idx], !nofade);
|
||||
}
|
||||
elem.dataset.userhide = "yes";
|
||||
elem.setHideLabel("[show]");
|
||||
}
|
||||
|
||||
// unhide a post
|
||||
function unhidepost(elem) {
|
||||
console.log("unhidepost("+elem.dataset.msgid+")");
|
||||
var posts = get_hidden_posts();
|
||||
if (posts) {
|
||||
// remove from persiting hide
|
||||
posts.del(elem.dataset.msgidhash);
|
||||
}
|
||||
if(postIsOP(elem)) {
|
||||
var thread = document.getElementById("thread_"+elem.dataset.rootmsgidhash);
|
||||
if(thread) {
|
||||
var e = thread.getElementsByClassName("post");
|
||||
for ( var idx = 0; idx < e.length ; idx ++ ) {
|
||||
if(e[idx].dataset.msgid == elem.dataset.msgid) continue;
|
||||
unhidepost(e[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// unhide attachments and post body
|
||||
var es = elem.getElementsByClassName("attachments");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_unhide_elem(es[idx]);
|
||||
}
|
||||
es = elem.getElementsByClassName("post_body");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_unhide_elem(es[idx]);
|
||||
}
|
||||
es = elem.getElementsByClassName("postheader");
|
||||
for (var idx = 0; idx < es.length ; idx ++ ) {
|
||||
_unhide_elem(es[idx]);
|
||||
}
|
||||
|
||||
elem.dataset.userhide = "no";
|
||||
elem.setHideLabel("[hide]");
|
||||
}
|
||||
|
||||
// hide a post given a callback that checks each post
|
||||
function hideposts(check_func) {
|
||||
var es = document.getElementsByClassName("post");
|
||||
for ( var idx = 0; idx < es.length ; idx ++ ) {
|
||||
var elem = es[idx];
|
||||
if(check_func && elem && check_func(elem)) {
|
||||
hidepost(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unhide all posts given callback
|
||||
// if callback is null unhide all
|
||||
function unhideall(check_func) {
|
||||
var es = document.getElementsByClassName("post");
|
||||
for (var idx=0 ; idx < es.length; idx ++ ) {
|
||||
var elem = es[idx];
|
||||
if(!check_func) { unhide(elem); }
|
||||
else if(check_func(elem)) { unhide(elem); }
|
||||
}
|
||||
}
|
||||
|
||||
// inject posthide into page
|
||||
onready(function() {
|
||||
var posts = document.getElementsByClassName("post");
|
||||
for (var idx = 0 ; idx < posts.length; idx++ ) {
|
||||
console.log("inject hide: "+posts[idx].dataset.msgid);
|
||||
var inject = function (elem) {
|
||||
var hider = document.createElement("a");
|
||||
hider.setAttribute("class", "hider");
|
||||
elem.setHideLabel = function (txt) {
|
||||
var e_hider = hider;
|
||||
e_hider.innerHTML = txt;
|
||||
}
|
||||
elem.hidepost = function() {
|
||||
var e_self = elem;
|
||||
var e_hider = hider;
|
||||
hidepost(e_self);
|
||||
}
|
||||
elem.unhidepost = function() {
|
||||
var e_self = elem;
|
||||
var e_hider = hider;
|
||||
unhidepost(e_self);
|
||||
}
|
||||
elem.isHiding = function() {
|
||||
var e_self = elem;
|
||||
return _elemIsHidden(e_self);
|
||||
}
|
||||
hider.appendChild(document.createTextNode("[hide]"));
|
||||
hider.onclick = function() {
|
||||
var e_self = elem;
|
||||
if(e_self.isHiding()) {
|
||||
e_self.unhidepost();
|
||||
} else {
|
||||
e_self.hidepost();
|
||||
}
|
||||
}
|
||||
elem.appendChild(hider);
|
||||
};
|
||||
inject(posts[idx]);
|
||||
}
|
||||
// apply persiting hidden posts
|
||||
var posts = get_hidden_posts();
|
||||
if(posts) {
|
||||
var all = posts.all();
|
||||
for ( var idx = 0 ; idx < all.length; idx ++ ) {
|
||||
var id = all[idx];
|
||||
var elem = document.getElementById(id);
|
||||
if(elem)
|
||||
hidepost(elem, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
function get_storage() {
|
||||
var st = null;
|
||||
if (window.localStorage) {
|
||||
st = window.localStorage;
|
||||
} else if (localStorage) {
|
||||
st = localStorage;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
function livechan_got_post(widget, j) {
|
||||
// do scroll
|
||||
while (widget.children.length > 5) {
|
||||
// remove top element
|
||||
widget.removeChild(widget.children[0]);
|
||||
}
|
||||
nntpchan_buildpost(widget, j);
|
||||
// scroll to bottom
|
||||
widget.scrollTop = widget.scrollHeight;
|
||||
}
|
||||
|
||||
// inject post form into an element
|
||||
function inject_postform(prefix, parent) {
|
||||
|
||||
}
|
||||
|
||||
// inject livechan widget into parent
|
||||
function inject_livechan_widget(prefix, parent) {
|
||||
if ( "WebSocket" in window ) {
|
||||
var url = "ws://"+document.location.host+prefix+"live";
|
||||
if ( document.location.protocol == "https:" ) {
|
||||
url = "wss://"+document.location.host+prefix+"live";
|
||||
}
|
||||
var socket = new WebSocket(url);
|
||||
var progress = function(str) {
|
||||
parent.innerHTML = "<pre>livechan: "+str+"</pre>";
|
||||
};
|
||||
progress("initialize");
|
||||
socket.onopen = function () {
|
||||
progress("streaming");
|
||||
}
|
||||
socket.onmessage = function(ev) {
|
||||
var j = null;
|
||||
try {
|
||||
j = JSON.parse(ev.data);
|
||||
} catch(e) {
|
||||
// ignore
|
||||
}
|
||||
if (j) {
|
||||
livechan_got_post(parent, j);
|
||||
}
|
||||
}
|
||||
socket.onclose = function(ev) {
|
||||
progress("connection closed");
|
||||
setTimeout(function() {
|
||||
inject_livechan_widget(prefix, parent);
|
||||
}, 1000);
|
||||
}
|
||||
} else {
|
||||
parent.innerHTML = "<pre>livechan mode requires websocket support</pre>";
|
||||
setTimeout(function() {
|
||||
parent.innerHTML = "";
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
function ukko_livechan(prefix) {
|
||||
var ukko = document.getElementById("ukko_threads");
|
||||
if (ukko) {
|
||||
// remove children
|
||||
ukko.innerHTML = "";
|
||||
inject_livechan_widget(prefix, ukko);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
main nntpchan javascript files
|
||||
@@ -1,426 +0,0 @@
|
||||
|
||||
function getReplyTo() {
|
||||
if(!document.dynreply) {
|
||||
var e = document.getElementById("postform_container");
|
||||
if (e) {
|
||||
// use existing postform
|
||||
document.dynreply = new DynReply(e);
|
||||
} else {
|
||||
// build a new postform
|
||||
document.dynreply = new DynReply();
|
||||
}
|
||||
e = document.dynreply.elem;
|
||||
e.style.position = "fixed";
|
||||
e.setAttribute("class", "shadow");
|
||||
}
|
||||
return document.dynreply;
|
||||
}
|
||||
|
||||
function table_insert_row(table, header, items) {
|
||||
var tr = document.createElement("tr");
|
||||
// insert header element
|
||||
var th = document.createElement("th");
|
||||
th.appendChild(header);
|
||||
tr.appendChild(th);
|
||||
// insert the rest of the elements
|
||||
for (var idx = 0; idx < items.length; idx ++ ) {
|
||||
var elem = document.createElement("td");
|
||||
elem.appendChild(items[idx]);
|
||||
tr.appendChild(elem);
|
||||
}
|
||||
table.appendChild(tr);
|
||||
}
|
||||
|
||||
/**
|
||||
build dynamic reply box
|
||||
*/
|
||||
function DynReply(existingElem) {
|
||||
if (existingElem) {
|
||||
// wrap existing post form
|
||||
// XXX: wrap it here
|
||||
this.elem = existingElem;
|
||||
this.form = this.elem.querySelector("form");
|
||||
this._error = document.getElementById("postform_msg");
|
||||
this.url = this.form.action + "?t=json";
|
||||
this.x = 1;
|
||||
this.y = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// build new post form
|
||||
|
||||
var elem = document.createElement("div");
|
||||
elem.setAttribute("id", "postform_container");
|
||||
this.elem = elem;
|
||||
// build post form
|
||||
this.form = document.createElement("form");
|
||||
this.form.enctype = "multipart/form-data";
|
||||
this.form.name = "post";
|
||||
this.form.method = "post";
|
||||
// reference
|
||||
elem = document.createElement("input");
|
||||
elem.setAttribute("id", "postform_reference");
|
||||
elem.name = "reference";
|
||||
elem.type = "hidden";
|
||||
this.form.appendChild(elem);
|
||||
|
||||
var table = document.createElement("table");
|
||||
table.setAttribute("class", "postform");
|
||||
var tbody = document.createElement("tbody");
|
||||
|
||||
var span = document.createElement("span");
|
||||
// name
|
||||
elem = document.createElement("input");
|
||||
elem.setAttribute("name", "name");
|
||||
elem.setAttribute("value", "Anonymous");
|
||||
elem.setAttribute("id", "postform_name");
|
||||
span.appendChild(elem);
|
||||
// error message
|
||||
var err_elem = document.createElement("span");
|
||||
err_elem.setAttribute("id", "postform_msg");
|
||||
span.appendChild(err_elem);
|
||||
this._error = err_elem;
|
||||
table_insert_row(tbody, document.createTextNode("Name"), [span])
|
||||
|
||||
// subject
|
||||
elem = document.createElement("input");
|
||||
elem.setAttribute("name", "subject");
|
||||
elem.setAttribute("value", "");
|
||||
elem.setAttribute("id", "postform_subject");
|
||||
// submit
|
||||
var submit = document.createElement("input");
|
||||
submit.setAttribute("value", "reply");
|
||||
submit.setAttribute("class", "button");
|
||||
submit.setAttribute("type", "submit");
|
||||
submit.setAttribute("id", "postform_submit");
|
||||
table_insert_row(tbody, document.createTextNode("Subject"), [elem, submit]);
|
||||
|
||||
|
||||
// Comment
|
||||
elem = document.createElement("textarea");
|
||||
elem.setAttribute("id", "postform_message");
|
||||
elem.setAttribute("name", "message");
|
||||
elem.setAttribute("cols", "40");
|
||||
elem.setAttribute("rows", "5");
|
||||
table_insert_row(tbody, document.createTextNode("Comment"), [elem]);
|
||||
|
||||
// file
|
||||
elem = document.createElement("input");
|
||||
elem.setAttribute("class", "postform_attachment");
|
||||
elem.setAttribute("id", "postform_attachments");
|
||||
elem.setAttribute("type", "file");
|
||||
elem.setAttribute("name", "attachment_uploaded");
|
||||
elem.setAttribute("multiple", "multiple");
|
||||
table_insert_row(tbody, document.createTextNode("Files"), [elem]);
|
||||
|
||||
// dubs
|
||||
elem = document.createElement("input");
|
||||
elem.setAttribute("type", "checkbox");
|
||||
elem.setAttribute("name", "dubs");
|
||||
table_insert_row(tbody, document.createTextNode("Get Dubs"), [elem]);
|
||||
|
||||
// captcha
|
||||
elem = document.createElement("img");
|
||||
elem.setAttribute("id", "captcha_img");
|
||||
elem.alt = "captcha";
|
||||
table_insert_row(tbody, document.createTextNode("Captcha"), [elem]);
|
||||
|
||||
// captcha solution
|
||||
elem = document.createElement("input");
|
||||
elem.name = "captcha";
|
||||
elem.autocomplete = "off";
|
||||
elem.setAttribute("id", "captcha_solution");
|
||||
table_insert_row(tbody, document.createTextNode("Solution"), [elem])
|
||||
|
||||
table.appendChild(tbody);
|
||||
this.form.appendChild(table);
|
||||
this.elem.appendChild(this.form);
|
||||
document.body.appendChild(this.elem);
|
||||
this.board = null;
|
||||
this.roothash = null;
|
||||
this.prefix = null;
|
||||
this.url = null;
|
||||
this.x = 1;
|
||||
this.y = 1;
|
||||
|
||||
}
|
||||
|
||||
DynReply.prototype.update = function() {
|
||||
if (this.prefix) {
|
||||
// update captcha
|
||||
this.updateCaptcha();
|
||||
if (this.board) {
|
||||
// update post form
|
||||
var ref = document.getElementById("postform_reference");
|
||||
|
||||
if (this.roothash) {
|
||||
ref.setAttribute("value", this.roothash);
|
||||
} else {
|
||||
ref.setAttribute("value", "");
|
||||
}
|
||||
this.url = this.prefix + "post/" + this.board + "?t=json";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DynReply.prototype.show = function() {
|
||||
console.log("show dynreply");
|
||||
this.update();
|
||||
this.elem.style.display = 'inline';
|
||||
}
|
||||
|
||||
DynReply.prototype.hide = function() {
|
||||
console.log("hide dynreply");
|
||||
this.elem.style.display = "none";
|
||||
}
|
||||
|
||||
// clear all fields
|
||||
DynReply.prototype.clear = function() {
|
||||
this.clearSolution();
|
||||
this.clearPostbox();
|
||||
}
|
||||
|
||||
|
||||
// clear captcha solution
|
||||
DynReply.prototype.clearSolution = function() {
|
||||
var e = document.getElementById("captcha_solution");
|
||||
// reset value
|
||||
e.value = "";
|
||||
}
|
||||
|
||||
// clear postform elements
|
||||
DynReply.prototype.clearPostbox = function() {
|
||||
var e = document.getElementById("postform_subject");
|
||||
e.value = "";
|
||||
e = document.getElementById("postform_message");
|
||||
e.value = "";
|
||||
e = document.getElementById("postform_attachments");
|
||||
e.value = null;
|
||||
}
|
||||
|
||||
DynReply.prototype.post = function(cb, err_cb) {
|
||||
if (this.url && this.form) {
|
||||
var data = new FormData(this.form);
|
||||
var ajax = new XMLHttpRequest();
|
||||
ajax.onreadystatechange = function(ev) {
|
||||
if (ajax.readyState == XMLHttpRequest.DONE) {
|
||||
var j = null;
|
||||
try {
|
||||
j = JSON.parse(ajax.responseText);
|
||||
cb(j);
|
||||
} catch (e) {
|
||||
if(err_cb) {
|
||||
err_cb(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ajax.open("POST", this.url);
|
||||
ajax.send(data);
|
||||
}
|
||||
}
|
||||
|
||||
DynReply.prototype.updateCaptcha = function() {
|
||||
if (this.prefix) {
|
||||
var captcha_img = document.getElementById("captcha_img");
|
||||
captcha_img.src = this.prefix + "captcha/img";
|
||||
}
|
||||
this.clearSolution();
|
||||
}
|
||||
|
||||
DynReply.prototype.setPrefix = function(prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
DynReply.prototype.hide = function() {
|
||||
this.elem.style.display = 'none';
|
||||
}
|
||||
|
||||
|
||||
DynReply.prototype.setBoard = function(boardname) {
|
||||
if (boardname) {
|
||||
this.board = boardname;
|
||||
}
|
||||
}
|
||||
|
||||
DynReply.prototype.setRoot = function(roothash) {
|
||||
if (roothash) {
|
||||
this.roothash = roothash;
|
||||
}
|
||||
}
|
||||
|
||||
DynReply.prototype.showError = function(msg) {
|
||||
console.log("error in dynreply: "+msg);
|
||||
this._error.setAttribute("class", "error message");
|
||||
this._error.appendChild(document.createTextNode(msg));
|
||||
this.updateCaptcha();
|
||||
}
|
||||
|
||||
DynReply.prototype.showMessage = function(msg) {
|
||||
this._error.setAttribute("class", "message");
|
||||
this._error.innerHTML = "";
|
||||
this._error.appendChild(document.createTextNode(msg));
|
||||
var e = this._error;
|
||||
setTimeout(function() {
|
||||
// clear it
|
||||
e.innerHTML = "";
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
|
||||
// reply box function
|
||||
function nntpchan_reply(parent, shorthash) {
|
||||
if (parent && document.dynreply) {
|
||||
var boardname = parent.getAttribute("boardname");
|
||||
var roothash = parent.getAttribute("root");
|
||||
var replyto = getReplyTo();
|
||||
// set target
|
||||
replyto.setBoard(boardname);
|
||||
replyto.setRoot(roothash);
|
||||
// show it
|
||||
replyto.show();
|
||||
}
|
||||
var elem = document.getElementById("postform_message");
|
||||
if ( elem )
|
||||
{
|
||||
elem.value += ">>" + shorthash.substr(0,10) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// inject post hover behavior
|
||||
function inject_hover(prefix, el, parent) {
|
||||
if (!prefix) { throw "prefix is not defined"; }
|
||||
var linkhash = el.getAttribute("backlinkhash");
|
||||
if (!linkhash) { throw "linkhash undefined"; }
|
||||
console.log("rewrite linkhash "+linkhash);
|
||||
|
||||
var elem = document.createElement("span");
|
||||
elem.setAttribute("class", "backlink_rewritten");
|
||||
elem.appendChild(document.createTextNode(">>"+linkhash.substr(0,10)));
|
||||
if (!parent) {
|
||||
parent = el.parentNode;
|
||||
}
|
||||
parent.removeChild(el);
|
||||
parent.appendChild(elem);
|
||||
|
||||
elem.onclick = function(ev) {
|
||||
if(parent.backlink) {
|
||||
nntpchan_apicall(prefix+"api/find?hash="+linkhash, function(j) {
|
||||
var wrapper = document.createElement("div");
|
||||
wrapper.setAttribute("class", "hover "+linkhash);
|
||||
if (j == null) {
|
||||
// not found?
|
||||
wrapper.setAttribute("class", "hover notfound-hover "+linkhash);
|
||||
wrapper.appendChild(document.createTextNode("not found"));
|
||||
} else {
|
||||
// wrap backlink
|
||||
nntpchan_buildpost(wrapper, j);
|
||||
}
|
||||
parent.appendChild(wrapper);
|
||||
parent.backlink = false;
|
||||
}, function(msg) {
|
||||
var wrapper = document.createElement("div");
|
||||
wrapper.setAttribute("class", "hover "+linkhash);
|
||||
wrapper.appendChild(document.createTextNode(msg));
|
||||
parent.appendChild(wrapper);
|
||||
parent.backlink = false;
|
||||
});
|
||||
} else {
|
||||
var elems = document.getElementsByClassName(linkhash);
|
||||
if (!elems) throw "bad state, no backlinks open?";
|
||||
for (var idx = 0 ; idx < elems.length; idx ++ ) {
|
||||
elems[idx].parentNode.removeChild(elems[idx]);
|
||||
}
|
||||
parent.backlink = true;
|
||||
}
|
||||
};
|
||||
parent.backlink = true;
|
||||
}
|
||||
|
||||
// inject post hover for all backlinks in an element
|
||||
function inject_hover_for_element(elem) {
|
||||
var elems = elem.getElementsByClassName("backlink");
|
||||
var ls = [];
|
||||
var l = elems.length;
|
||||
for ( var idx = 0 ; idx < l ; idx ++ ) {
|
||||
var e = elems[idx];
|
||||
ls.push(e);
|
||||
}
|
||||
for( var elem in ls ) {
|
||||
inject_hover(prefix, ls[elem]);
|
||||
}
|
||||
}
|
||||
|
||||
function init(prefix) {
|
||||
// because no one cares about this feature :|
|
||||
return;
|
||||
// inject posthover ...
|
||||
inject_hover_for_element(document);
|
||||
if ( /\.html$/.test(document.location.pathname) && ! (/ukko/.test(document.location.pathname)) ) {
|
||||
// board / thread page
|
||||
console.log("not loading reply widget");
|
||||
} else {
|
||||
// ukko / livechan page
|
||||
var rpl = getReplyTo();
|
||||
rpl.setPrefix(prefix);
|
||||
// set livechan
|
||||
rpl.setBoard("overchan.random");
|
||||
rpl.update();
|
||||
rpl.updateCaptcha();
|
||||
|
||||
// position replyto widget
|
||||
var e = rpl.elem;
|
||||
var mouseDownX, mouseDownY;
|
||||
|
||||
var $dragging = null;
|
||||
|
||||
$(rpl.elem).on("mousemove", function(ev) {
|
||||
if ($dragging) {
|
||||
var x = ev.pageX - $(this).width() / 2,
|
||||
y = ev.pageY - $(this).height() / 2;
|
||||
$dragging.offset({
|
||||
top: y,
|
||||
left: x
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$(rpl.elem).on("mousedown", e, function (ev) {
|
||||
$dragging = $(rpl.elem);
|
||||
});
|
||||
|
||||
$(rpl.elem).on("mouseup", function (e) {
|
||||
$dragging = null;
|
||||
});
|
||||
|
||||
// add replyto post handlers
|
||||
e = document.getElementById("postform_submit");
|
||||
var postit = function() {
|
||||
var f = document.querySelector("form");
|
||||
// do ajax request to post data
|
||||
var r = getReplyTo();
|
||||
r.showMessage("posting... ");
|
||||
r.post(function(j) {
|
||||
if(j.error) {
|
||||
// an error happened
|
||||
r.showError(j.error);
|
||||
} else {
|
||||
// we're good
|
||||
r.showMessage("posted :^)");
|
||||
r.updateCaptcha();
|
||||
r.clear();
|
||||
}
|
||||
}, function(err) {
|
||||
r.showError(err);
|
||||
r.clearSolution();
|
||||
});
|
||||
}
|
||||
var f = document.querySelector("form");
|
||||
f.onsubmit = function() {
|
||||
postit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
function enable_theme(prefix, name) {
|
||||
if (prefix && name) {
|
||||
var theme = document.getElementById("current_theme");
|
||||
if (theme) {
|
||||
theme.href = prefix + "static/"+ name + ".css";
|
||||
var st = get_storage();
|
||||
st.nntpchan_prefix = prefix;
|
||||
st.nntpchan_theme = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// apply themes
|
||||
var st = get_storage();
|
||||
enable_theme(st.nntpchan_prefix, st.nntpchan_theme);
|
||||
@@ -1,66 +0,0 @@
|
||||
var easiness = 55.0;
|
||||
var miner_threads = 4;
|
||||
var randoffs = 64;
|
||||
|
||||
/*
|
||||
onready(function(){
|
||||
document.getElementById("start_miner").onclick = function() {
|
||||
var btn = document.getElementById("start_miner");
|
||||
var label = btn.value;
|
||||
btn.value = "..."
|
||||
btn.disabled = true;
|
||||
|
||||
|
||||
var b = new Uint8Array(randoffs);
|
||||
window.crypto.getRandomValues(b);
|
||||
var b_cur = 0;
|
||||
var b_i = 0;
|
||||
var tmp = new Uint8Array(randoffs+b_i+1);
|
||||
tmp.set(b)
|
||||
tmp[b.length]=0
|
||||
b = tmp;
|
||||
|
||||
var workers = new Array(miner_threads);
|
||||
|
||||
var worker_cb = function(e) {
|
||||
if (e.data[0] == "ok") {
|
||||
miner_cb(e.data[1]);
|
||||
btn.value=label;
|
||||
btn.disabled = false;
|
||||
for (i=0; i<miner_threads; i++) {
|
||||
workers[i].terminate();
|
||||
}
|
||||
} else {
|
||||
if (b_cur >= 256) {
|
||||
var tmp = new Uint8Array(randoffs+b_i+1);
|
||||
tmp.set(b)
|
||||
tmp[b.length]=0
|
||||
b = tmp;
|
||||
b_i++;
|
||||
b_cur=0;
|
||||
}
|
||||
b[randoffs+b_i]=b_cur;
|
||||
b_cur++;
|
||||
var params = [b, easiness, e.data[2]];
|
||||
workers[e.data[2]].postMessage(params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
for (i=0; i<miner_threads; i++) {
|
||||
b[randoffs+b_i]=b_cur;
|
||||
b_cur++;
|
||||
var params = [b, easiness, i];
|
||||
workers[i] = new Worker("./static/mineworker.js");
|
||||
workers[i].onmessage = worker_cb;
|
||||
workers[i].postMessage(params); // Start the worker.
|
||||
}
|
||||
b_cur=4;
|
||||
};
|
||||
});
|
||||
function miner_cb(s) {
|
||||
document.getElementById("miner_result").value = s;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
this directory holds unused javascript files for nntpchan
|
||||
don't delete files move them here
|
||||
@@ -1,2 +0,0 @@
|
||||
javascript files for nntpchan
|
||||
|
||||
16
contrib/live/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<html>
|
||||
<head>
|
||||
<title> nntpchan liveposting </title>
|
||||
<link rel="stylesheet" src="live.css" />
|
||||
<script type="text/javascript" src="live.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<p>nntpchan liveposting is done entirly via javascript and websockets</P>
|
||||
<p>this frontend will not work without javascript enabled</p>
|
||||
</noscript>
|
||||
<div onload="nntpchan_load_ui(this)">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
83
contrib/live/live.js
Normal file
@@ -0,0 +1,83 @@
|
||||
|
||||
function create_captcha_pane() {
|
||||
var elem = document.createElement("div");
|
||||
elem.setAttribute("class", "nntpchan_captcha_slash");
|
||||
|
||||
}
|
||||
|
||||
// create the base ui
|
||||
// pass in a function that does posting
|
||||
// return the model
|
||||
function create_ui(elem) {
|
||||
|
||||
var pane = document.createElement("div");
|
||||
|
||||
|
||||
var output = document.createElement("div");
|
||||
output.setAttribute("class", "nntpchan_output");
|
||||
|
||||
var output_elem = document.createElemen("div");
|
||||
output_elem.setAttribute("class", "nntpchan_output_root");
|
||||
output.appendChild(output_elem);
|
||||
|
||||
pane.appendChild(output);
|
||||
|
||||
var input = document.createElement("div");
|
||||
input.setAttribute("class", "nntpchan_input");
|
||||
|
||||
var input_elem = document.createElement("textarea");
|
||||
input_elem.setAttribute("class", "nntpchan_textarea");
|
||||
input.appendChild(input_elem);
|
||||
|
||||
var submit_elem = document.createElement("input");
|
||||
submit_elem.setAttrbute("type", "button");
|
||||
input.appendChild(submit_elem);
|
||||
|
||||
pane.appendChild(input);
|
||||
|
||||
|
||||
elem.appendChild(pane);
|
||||
|
||||
var captcha_elem = create_captcha_pane();
|
||||
|
||||
elem.appendChild(captcha_elem);
|
||||
|
||||
return {
|
||||
input: input_elem,
|
||||
submit: submit_elem,
|
||||
output: output_elem,
|
||||
captcha: captcha_elem
|
||||
}
|
||||
}
|
||||
|
||||
// load ui elements and start stuff up
|
||||
function nntpchan_load_ui(elem) {
|
||||
// check for websockets
|
||||
if (!("WebSocket" in window)) {
|
||||
elem.value = "websockets are needed for nntpchan liveposting";
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: make configurable url
|
||||
var url = "ws://" + location.hostname + ":18080/ws";
|
||||
|
||||
var socket = new WebSocket(url);
|
||||
|
||||
var send = function(obj) {
|
||||
socket.send(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
var ui = create_ui(elem);
|
||||
ui.submit.addEventListener("click", function(ev) {
|
||||
|
||||
});
|
||||
|
||||
socket.onopen = function() {
|
||||
|
||||
}
|
||||
|
||||
socket.onmessage = function() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
3
contrib/static/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
nntpchan.js
|
||||
neochan.js
|
||||
neochan.css
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
BIN
contrib/static/about.mp3
Normal file
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 135 B After Width: | Height: | Size: 550 B |
@@ -1,112 +0,0 @@
|
||||
/**
|
||||
bloodgod theme css override
|
||||
*/
|
||||
|
||||
body {
|
||||
color: #666;
|
||||
background: #111;
|
||||
}
|
||||
|
||||
.post_body > pre {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
input, textarea, button, input[type="text"], input[type="password"],
|
||||
input[type="checkbox"], input[type="file"], input[type="submit"],
|
||||
input[type="button"] {
|
||||
color: #666;
|
||||
background: #050505;
|
||||
border-color: #D80000;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background: #980000;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#captcha_img {
|
||||
background: #D80000;
|
||||
}
|
||||
|
||||
.reply, .ukko_thread_header {
|
||||
border-color: #0c0c0c;
|
||||
}
|
||||
|
||||
.ukko_thread_header {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
|
||||
hr, .name {
|
||||
color: #6B1919;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 0px;
|
||||
border-width: 1px medium medium;
|
||||
border-color: #0C0C0C;
|
||||
border-style: solid none none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.subject {
|
||||
color: #4E0000;
|
||||
}
|
||||
|
||||
.reply , .ukko_thread_header {
|
||||
background: #0C0C0C;
|
||||
}
|
||||
|
||||
.op {
|
||||
background-color: #1a1a1a;
|
||||
border-style: hidden;
|
||||
}
|
||||
|
||||
.pagelist {
|
||||
background: #0c0c0c;
|
||||
border-style: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #500707;
|
||||
}
|
||||
|
||||
.post:target {
|
||||
background-color: #1a1a1a;
|
||||
}
|
||||
|
||||
.postno, .postnol {
|
||||
color: #B70000;
|
||||
}
|
||||
|
||||
.postform >tr, th {
|
||||
background: #6B1919;
|
||||
}
|
||||
|
||||
#postform_container {
|
||||
background-color: #111;
|
||||
}
|
||||
table tbody tr:nth-of-type( even ) {
|
||||
background-color: #430000;
|
||||
}
|
||||
|
||||
table thead th {
|
||||
color: #6B1919;
|
||||
background: #430000;
|
||||
border-color: #270000;
|
||||
}
|
||||
|
||||
.navbar-sep {
|
||||
color: #270000;
|
||||
}
|
||||
|
||||
.navbar-link > label:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.origin > img , .not_found > img {
|
||||
-webkit-filter: invert(1);
|
||||
filter: invert(1);
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>nntpchan faq</title></head><body>
|
||||
<audio loop controls><source src="/static/about.mp3" type="audio/mpeg">[can't play audio.]</audio>
|
||||
<p>nntpchan faq</p>
|
||||
<dl>
|
||||
<dt>What is nntpchan?</dt>
|
||||
<dd>NNTPCchan is a federated imageboard that spans across several networks including tor, i2p and anonet. There are no central servers so that as long as 1 server is left the forum will continue to function.</dd>
|
||||
<br>
|
||||
<dt>How is this different from *chan?</dt>
|
||||
<dd>NNTPChan is by design invulnerable to global censorship. All moderation is local to each server.</dd>
|
||||
<br>
|
||||
<dt>How does moderation work then?</dt>
|
||||
<dd>Moderation is done with our special tripcodes (ed25519-sha512 signed posts). Anyone can give moderation suggestions, but that doesn't mean anyone will accept them. Those who trust the actions of a moderator can have their frontend whitelist the moderation actions and have them performed without oversight by another moderator.</dd>
|
||||
<br>
|
||||
<dt>How can I remove content from nntpchan completely?</dt>
|
||||
<dd>‾\(._.)/‾ I don't know. You probably can't unless every server agrees to remove the content, even then, nothing prevents someone from reposting it. You can't delete what you post on the internet.</dd>
|
||||
<br>
|
||||
<dt>do you allow child porn?</dt>
|
||||
<dd>no.</dd>
|
||||
<br>
|
||||
<dt>Do you allow XYZ content?</dt>
|
||||
<dd>If it violates USA Law or causes problems with my host, no. Otherwise, probably.</dd>
|
||||
<br>
|
||||
<dt>Someone posted something I don't like but it's not illegal</dt>
|
||||
<dd>That is not my problem. All posts on this site are the responsibility of the individual poster and not the administration of this server</dd>
|
||||
<br>
|
||||
<dt>code, bugs, feature requests</dt>
|
||||
<dd><a href="https://github.com/majestrate/nntpchan/">frontend</a> <a href="https://github.com/majestrate/srndv2/">core</a></dd>
|
||||
<br></dl>
|
||||
<p>Please send any gripes/questions/inqueries/suggestions/complaints to ampernand [|at\] gmail {dot} com with subject starting with "nntpchan question"</p>
|
||||
<hr>
|
||||
<p>ucavviu7wl6azuw7.onion frontend specific</p>
|
||||
<dl>
|
||||
<dt>admin's pubkey</dt>
|
||||
<dd>06833a90237c61f59558c1726fbe71c63e972722b2cf1147867be286cb020b32<br>
|
||||
▆☃►☐▣◼◡♵☕◘♁◲◯☾◱♆▾☗▧▢☲♏░◇☆◻♢☆♋▂▋▲</dd>
|
||||
<br>
|
||||
<dt>peering</dt>
|
||||
<dd>just open a thread for now.</dd>
|
||||
<br>
|
||||
<dt>rules</dt>
|
||||
<dd>basically no stuff that will fuck with the functioning of the site.<br>
|
||||
- stuff that will get me in trouble like cp.<br>
|
||||
- flood/spam. duplicate posts may also get baleeted.
|
||||
</dd>
|
||||
<br>
|
||||
<dt>guidelines and things to keep in mind</dt>
|
||||
<dd>
|
||||
- i don't owe you shiieet. you don't owe me shieet.<br>
|
||||
- administration style: benevolent dictatorship.
|
||||
</dd>
|
||||
</dl>
|
||||
</body></html>
|
||||
@@ -1,7 +0,0 @@
|
||||
body{font-family:monospace}
|
||||
dl{max-width:84ch}
|
||||
dd{margin-left:4ch;overflow:auto}
|
||||
.memearrows{color:green}
|
||||
pre{margin: 0 0 0 0}
|
||||
table,th,td{border:1px solid gray}
|
||||
table {border-collapse:collapse}
|
||||
|
Before Width: | Height: | Size: 60 B |
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
dayman
|
||||
fighter of the night man
|
||||
champion of the sun
|
||||
*/
|
||||
|
||||
body {
|
||||
background-color: #FFEFC9;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: 100% 100%;
|
||||
background-image: url('maymface.png');
|
||||
}
|
||||
|
||||
.reply, .ukko_thread_header, th, .postform > tr , tbody > tr:nth-of-type( even ) {
|
||||
background: #FBFFC9;
|
||||
}
|
||||
|
||||
#postform_container {
|
||||
background-color: rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
.post:target {
|
||||
background-color: #ffda9b;
|
||||
box-shadow: 0px 0px 5px 1px;
|
||||
}
|
||||
|
||||
img#nntpchan_banner {
|
||||
box-shadow: 0px 0px 10px 0px #FFECBE;
|
||||
}
|
||||
|
||||
#postform_inner {
|
||||
box-shadow: 0px 1px 5px 1px;
|
||||
}
|
||||
|
||||
.navbar, table, thead, th, table, pre, .op {
|
||||
background: #FFECBE;
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
<!DOCTYPE html5>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="site.css" />
|
||||
<title> NNTPChan Frequently Asked Questions </title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="site.css"></link>
|
||||
<title> NNTPChan Frequently Asked Questions</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>NNTPChan faq </h2>
|
||||
@@ -49,6 +47,14 @@
|
||||
<div><a href="https://github.com/majestrate/nntpchan/issues">github</a></div>
|
||||
</p>
|
||||
<hr />
|
||||
<p>
|
||||
<div>Please send any gripes/questions/inqueries/suggestions/complaints to ampernand [|at\] gmail {dot} com with subject starting with "nntpchan question" </div>
|
||||
</p>
|
||||
<hr />
|
||||
</div>
|
||||
<audio autoplay="autoplay" loop="loop">
|
||||
<source src="about.mp3" type="audio/mpeg">
|
||||
<embed src="about.mp3">
|
||||
</audio>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
|
||||
function createConnectionElement(j) {
|
||||
var e = document.createElement("div");
|
||||
e.setAttribute("class", "connection");
|
||||
var auth = document.createElement("div");
|
||||
auth.appendChild(document.createTextNode("Connection: "+j.name));
|
||||
// authentication state
|
||||
if (j.authed) {
|
||||
auth.setAttribute("class", "authed");
|
||||
auth.appendChild(document.createTextNode("(authenticated)"));
|
||||
} else {
|
||||
auth.appendChild(document.createTextNode("(not authenticated)"));
|
||||
}
|
||||
e.appendChild(auth);
|
||||
|
||||
// connection mode
|
||||
var mode = document.createElement("div");
|
||||
mode.setAttribute("class", "mode");
|
||||
mode.appendChild(document.createTextNode("mode: "+j.mode));
|
||||
e.appendChild(mode);
|
||||
|
||||
var pending = document.createElement("div");
|
||||
pending.setAttribute("class", "pending");
|
||||
// pending articles
|
||||
var articles = Object.keys(j.pending);
|
||||
pending.appendChild(document.createTextNode("pending articles: "+articles.length));
|
||||
for ( var idx = 0 ; idx < articles.length; idx ++ ) {
|
||||
var msgid = articles[idx];
|
||||
var state = j.pending[msgid];
|
||||
var elem = document.createElement("div");
|
||||
elem.appendChild(document.createTextNode(msgid + ": " + state));
|
||||
elem.setAttribute("class", "pending_item "+state);
|
||||
pending.appendChild(elem);
|
||||
}
|
||||
e.appendChild(pending);
|
||||
// e.appendChild(document.createTextNode(JSON.stringify(j)));
|
||||
return e;
|
||||
}
|
||||
|
||||
function inject_nntp_feed_element(feed, elem) {
|
||||
elem.appendChild(document.createElement("hr"));
|
||||
var name = document.createElement("div");
|
||||
name.setAttribute("class", "feeds_name");
|
||||
name_elem = document.createTextNode("Name: "+feed.State.Config.Name);
|
||||
name.appendChild(name_elem);
|
||||
elem.appendChild(name);
|
||||
var conns = document.createElement("div");
|
||||
conns.setAttribute("class", "connections");
|
||||
for ( var idx = 0 ; idx < feed.Conns.length; idx ++ ) {
|
||||
conns.appendChild(createConnectionElement(feed.Conns[idx]));
|
||||
}
|
||||
elem.appendChild(conns);
|
||||
}
|
||||
|
||||
function update_nntpchan_feed_ticker(elem, result_elem) {
|
||||
nntpchan_admin("feed.list", null, function(j) {
|
||||
if (j) {
|
||||
if (j.error) {
|
||||
console.log("nntpchan_feed_ticker: error, "+j.error);
|
||||
} else {
|
||||
// remove all children
|
||||
while(elem.children.length) {
|
||||
elem.children[0].remove();
|
||||
}
|
||||
var result = j.result;
|
||||
for (var idx = 0; idx < result.length; idx++) {
|
||||
var item = result[idx];
|
||||
var entry = document.createElement("div");
|
||||
inject_nntp_feed_element(item, entry);
|
||||
elem.appendChild(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, result_elem);
|
||||
}
|
||||
|
||||
|
||||
function nntp_feed_add() {
|
||||
var param = {};
|
||||
|
||||
var e = document.getElementById("add_feed_name");
|
||||
param.name = e.value;
|
||||
e = document.getElementById("add_feed_host");
|
||||
param.host = e.value;
|
||||
e = document.getElementById("add_feed_port");
|
||||
param.port = parseInt(e.value);
|
||||
|
||||
e = document.getElementById("nntpchan_feed_result");
|
||||
nntpchan_admin("feed.add", param, null, e);
|
||||
}
|
||||
|
||||
function nntp_feed_del() {
|
||||
var e = document.getElementById("del_feed_name");
|
||||
var name = e.value;
|
||||
e = document.getElementById("nntpchan_feed_result");
|
||||
nntpchan_admin("feed.del", {name: name}, null, e);
|
||||
}
|
||||
|
||||
function nntp_feed_update() {
|
||||
var e = document.getElementById("nntpchan_feeds");
|
||||
if (e) {
|
||||
setInterval(function(){
|
||||
var e1 = document.getElementById("nntpchan_feed_result");
|
||||
update_nntpchan_feed_ticker(e, e1);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
BIN
contrib/static/fieri.png
Normal file
|
After Width: | Height: | Size: 858 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -1,249 +0,0 @@
|
||||
input {
|
||||
-moz-border-radius: 0px;
|
||||
-webkit-border-radius: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.livechan_captcha_input {
|
||||
color: black;
|
||||
}
|
||||
|
||||
textarea, select {
|
||||
-moz-border-radius: 0px;
|
||||
-webkit-border-radius: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
|
||||
.livechan_chat_input {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #d6daf0;
|
||||
}
|
||||
|
||||
.livechan_chat_input_name, .livechan_chat_input_convo {
|
||||
padding: 0;
|
||||
padding-left: none;
|
||||
margin: 0;
|
||||
width: 80%;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.livechan_chat_input_left {
|
||||
width: 19%;
|
||||
}
|
||||
|
||||
.livechan_chat_input_message_div {
|
||||
padding:0;
|
||||
margin:0;
|
||||
position: absolute;
|
||||
width: 70%;
|
||||
left: 20%;
|
||||
top: 3px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.livechan_chat_input_message {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border:none;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.livechan_chat_input_submit {
|
||||
position: absolute;
|
||||
width: 8%;
|
||||
top: 3px;
|
||||
right: 1px;
|
||||
bottom: 0;
|
||||
border: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.livechan_chat_output {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 60px;
|
||||
overflow: auto;
|
||||
width: 89%;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.livechan_chat_output_chat {
|
||||
max-height: 200px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.livechan_chat_output_date {
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.livechan_chat_output_count:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.livechan_chat_capcode {
|
||||
margin: 0 4px;
|
||||
font-style: italic;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.livechan_image_thumb {
|
||||
max-width: 300px;
|
||||
max-height: 200px;
|
||||
float: left;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.livechan_captcha {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
position: fixed;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.livechan_captcha_inner {
|
||||
padding: 200px;
|
||||
}
|
||||
|
||||
.livechan_captcha_image {
|
||||
}
|
||||
|
||||
.livechan_captcha_input {
|
||||
float: down;
|
||||
}
|
||||
|
||||
.livechan_spoiler {
|
||||
color: black;
|
||||
background: black;
|
||||
}
|
||||
|
||||
.livechan_chat_output_chat {
|
||||
background: #d6daf0;
|
||||
}
|
||||
|
||||
.livechan_spoiler:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.livechan_convo_label {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.livechan_convobar_root {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 0;
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.livechan_convobar_item {
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
background: #d6daf0;
|
||||
}
|
||||
|
||||
.livechan_navbar {
|
||||
z-index: 3;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.livechan_navbar_mod_indicator_inactive, .livechan_navbar_mod_indicator_active, .livechan_navbar_status, .livechan_navbar_channel_label {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
background: #d6daf0;
|
||||
}
|
||||
|
||||
|
||||
.hover {
|
||||
position: relative;
|
||||
padding: 1px;
|
||||
left: -1000px
|
||||
border: 1px dashed black;
|
||||
visibility: hidden;
|
||||
}
|
||||
.hover > img {
|
||||
position: fixed;
|
||||
top: 0%;
|
||||
right: 0;
|
||||
max-width: 75%;
|
||||
max-height: 75%;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.livechan_captcha, .livechan_convobar_root, #chat {
|
||||
background: #EEF2FF;
|
||||
}
|
||||
|
||||
.livechan_chat_output_chat {
|
||||
font-family: monospace;
|
||||
margin: 4px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.livechan_chat_output_name {
|
||||
font-weight: bold;
|
||||
color: green;
|
||||
}
|
||||
|
||||
.livechan_chat_output_count:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.livechan_greentext {
|
||||
color: #789922;
|
||||
}
|
||||
|
||||
.livechan_boldtext {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.livechan_internallink , a {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.livechan_internallink:hover , a {
|
||||
color: red;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.livechan_chat_selected {
|
||||
background: blue;
|
||||
}
|
||||
|
||||
|
||||
.livechan_navbar_mod_indicator_active {
|
||||
background: #4a4ad4;
|
||||
color: #34d434;
|
||||
}
|
||||
|
||||
.livechan_navbar_mod_indicator_admin {
|
||||
background: #4a4ad4;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.livechan_navbar_mod_indicator_inactive {
|
||||
color: #aaaaaa;
|
||||
background: #EEF2FF;
|
||||
}
|
||||
|
||||
|
||||
.livechan_redtext {
|
||||
color: #af0a0f;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 84 KiB |
@@ -1,8 +0,0 @@
|
||||
importScripts('./siphash-lib.js');
|
||||
importScripts('./miner-js.js');
|
||||
|
||||
onmessage = function(e) {
|
||||
var s = cuckoo["mine_cuckoo"](e.data[0], e.data[1]);
|
||||
s.push(e.data[2]);
|
||||
postMessage(s);
|
||||
}
|
||||
@@ -64,51 +64,28 @@ function nntpchan_key_add() {
|
||||
});
|
||||
}
|
||||
|
||||
function get_nntp_username() {
|
||||
var e = document.getElementById("nntpchan_nntp_username");
|
||||
return e.value;
|
||||
}
|
||||
|
||||
function get_nntp_passwd() {
|
||||
var e = document.getElementById("nntpchan_nntp_passwd");
|
||||
return e.value;
|
||||
}
|
||||
|
||||
function nntpchan_admin_nntp(method) {
|
||||
nntpchan_admin(method, {
|
||||
username: get_nntp_username(),
|
||||
passwd: get_nntp_passwd()
|
||||
})
|
||||
}
|
||||
|
||||
function nntpchan_admin_board(method) {
|
||||
nntpchan_admin(method, {
|
||||
newsgroup: get_board_target()
|
||||
})
|
||||
}
|
||||
|
||||
function nntpchan_admin(method, param, handler_cb, result_elem) {
|
||||
if (handler_cb) {
|
||||
// we got a handler already set
|
||||
} else {
|
||||
// no handler set
|
||||
var handler_cb = function(j) {
|
||||
if (j.result) {
|
||||
return document.createTextNode(j.result);
|
||||
} else {
|
||||
return "nothing happened?";
|
||||
}
|
||||
}
|
||||
}
|
||||
function nntpchan_admin(method, param) {
|
||||
nntpchan_mod({
|
||||
name:"admin",
|
||||
parser: function(target) {
|
||||
return method;
|
||||
},
|
||||
handle: handler_cb,
|
||||
handle: function(j) {
|
||||
if (j.result) {
|
||||
return document.createTextNode(j.result);
|
||||
} else {
|
||||
return "nothing happened?";
|
||||
}
|
||||
},
|
||||
method: ( param && "POST" ) || "GET",
|
||||
data: param
|
||||
}, result_elem)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -142,83 +119,70 @@ function nntpchan_delete() {
|
||||
});
|
||||
}
|
||||
|
||||
function nntpchan_mod(mod_action, result_elem) {
|
||||
|
||||
|
||||
function nntpchan_mod(mod_action) {
|
||||
|
||||
// get the element
|
||||
var input = document.getElementById("nntpchan_mod_target");
|
||||
var target = null;
|
||||
if (input) {
|
||||
target = input.value;
|
||||
}
|
||||
var target = input.value;
|
||||
if (mod_action.parser) {
|
||||
target = mod_action.parser(target);
|
||||
}
|
||||
var elem;
|
||||
if (result_elem) {
|
||||
elem = result_elem;
|
||||
} else {
|
||||
elem = document.getElementById("nntpchan_mod_result");
|
||||
}
|
||||
|
||||
|
||||
var elem = document.getElementById("nntpchan_mod_result");
|
||||
// clear old results
|
||||
while( elem.firstChild ) {
|
||||
elem.removeChild(elem.firstChild);
|
||||
}
|
||||
|
||||
var csrf_ajax = new XMLHttpRequest();
|
||||
csrf_ajax.onreadystatechange = function() {
|
||||
if (csrf_ajax.readyState == XMLHttpRequest.DONE) {
|
||||
// get csrf token
|
||||
var csrf = csrf_ajax.getResponseHeader("X-CSRF-Token");
|
||||
// fire off ajax
|
||||
var ajax = new XMLHttpRequest();
|
||||
ajax.onreadystatechange = function() {
|
||||
if (ajax.readyState == XMLHttpRequest.DONE) {
|
||||
var status = ajax.status;
|
||||
// we gud?
|
||||
if (status == 200) {
|
||||
// yah
|
||||
var txt = ajax.responseText;
|
||||
var j = JSON.parse(txt);
|
||||
if (j.error) {
|
||||
var e = document.createTextNode(j.error);
|
||||
elem.appendChild(e);
|
||||
} else {
|
||||
if (mod_action.handle) {
|
||||
var result = mod_action.handle(j);
|
||||
if (result) {
|
||||
elem.appendChild(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (status) {
|
||||
// nah
|
||||
// http error
|
||||
elem.innerHTML = "error: HTTP "+status;
|
||||
}
|
||||
// clear input
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mod_action.name) {
|
||||
|
||||
var url = mod_action.name + "/" + target;
|
||||
ajax.open(mod_action.method || "GET", url);
|
||||
ajax.setRequestHeader("X-CSRF-Token", csrf);
|
||||
var data = mod_action.data;
|
||||
if (data) {
|
||||
ajax.setRequestHeader("Content-type","text/json");
|
||||
ajax.send(JSON.stringify(data));
|
||||
// fire off ajax
|
||||
var ajax = new XMLHttpRequest();
|
||||
ajax.onreadystatechange = function() {
|
||||
if (ajax.readyState == XMLHttpRequest.DONE) {
|
||||
var status = ajax.status;
|
||||
// we gud?
|
||||
if (status == 200) {
|
||||
// yah
|
||||
var txt = ajax.responseText;
|
||||
var j = JSON.parse(txt);
|
||||
if (j.error) {
|
||||
var e = document.createTextNode(j.error);
|
||||
elem.appendChild(e);
|
||||
} else {
|
||||
ajax.send();
|
||||
if (mod_action.handle) {
|
||||
var result = mod_action.handle(j);
|
||||
if (result) {
|
||||
elem.appendChild(result);
|
||||
} else {
|
||||
// fail
|
||||
alert("mod action failed, handler returned nothing");
|
||||
}
|
||||
} else {
|
||||
// fail
|
||||
alert("mod action has no handler");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
alert("mod action has no name");
|
||||
} else if (status) {
|
||||
// nah
|
||||
// http error
|
||||
elem.innerHTML = "error: HTTP "+status;
|
||||
}
|
||||
// clear input
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
csrf_ajax.open("GET", "");
|
||||
csrf_ajax.send();
|
||||
if (mod_action.name) {
|
||||
var url = mod_action.name + "/" + target;
|
||||
ajax.open(mod_action.method || "GET", url);
|
||||
var data = mod_action.data;
|
||||
if (data) {
|
||||
ajax.setRequestHeader("Content-type","text/json");
|
||||
ajax.send(JSON.stringify(data));
|
||||
} else {
|
||||
ajax.send();
|
||||
}
|
||||
} else {
|
||||
alert("mod action has no name");
|
||||
}
|
||||
}
|
||||
|
||||
14
contrib/static/nntpchan.js
Normal file
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// nntpchan.js -- frontend ui niceness
|
||||
//
|
||||
|
||||
|
||||
// insert a backlink for a post given its short hash
|
||||
function nntpchan_backlink(shorthash)
|
||||
{
|
||||
var elem = document.getElementById("postform_message");
|
||||
if ( elem )
|
||||
{
|
||||
elem.value += ">>" + shorthash + "\n";
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.3 KiB |
@@ -1,94 +0,0 @@
|
||||
var SipHash = (function() {
|
||||
function u8to64(p , i) {
|
||||
return { l: (p[i] | p[i+1]<<8 | p[i+2]<<16 | p[i+3]<<24) , h: (p[i+4] | p[i+5]<<8 | p[i+6]<<16 | p[i+7]<<24) };
|
||||
}
|
||||
|
||||
|
||||
function _add(a, b) {
|
||||
var rl = a.l + b.l,
|
||||
a2 = { h: a.h + b.h + (rl / 2 >>> 31) >>> 0,
|
||||
l: rl >>> 0 };
|
||||
a.h = a2.h; a.l = a2.l;
|
||||
}
|
||||
|
||||
function _xor(a, b) {
|
||||
a.h ^= b.h; a.h >>>= 0;
|
||||
a.l ^= b.l; a.l >>>= 0;
|
||||
}
|
||||
|
||||
function _rotl(a, n) {
|
||||
var a2 = {
|
||||
h: a.h << n | a.l >>> (32 - n),
|
||||
l: a.l << n | a.h >>> (32 - n)
|
||||
};
|
||||
a.h = a2.h; a.l = a2.l;
|
||||
}
|
||||
|
||||
function _rotl32(a) {
|
||||
var al = a.l;
|
||||
a.l = a.h; a.h = al;
|
||||
}
|
||||
|
||||
function _compress(v0, v1, v2, v3) {
|
||||
_add(v0, v1);
|
||||
_add(v2, v3);
|
||||
_rotl(v1, 13);
|
||||
_rotl(v3, 16);
|
||||
_xor(v1, v0);
|
||||
_xor(v3, v2);
|
||||
_rotl32(v0);
|
||||
_add(v2, v1);
|
||||
_add(v0, v3);
|
||||
_rotl(v1, 17);
|
||||
_rotl(v3, 21);
|
||||
_xor(v1, v2);
|
||||
_xor(v3, v0);
|
||||
_rotl32(v2);
|
||||
}
|
||||
|
||||
|
||||
function hash(v0h, v0l, v1h, v1l, v2h, v2l, v3h, v3l, mh, ml) {
|
||||
var mi = { h: mh, l: ml };
|
||||
|
||||
var v0 = { h: v0h, l: v0l };
|
||||
var v1 = { h: v1h, l: v1l };
|
||||
var v2 = { h: v2h, l: v2l };
|
||||
var v3 = { h: v3h, l: v3l };
|
||||
|
||||
/*var k0 = u8to64(key, 0);
|
||||
var k1 = u8to64(key, 8);
|
||||
|
||||
var v0 = { h: k0.h, l: k0.l }, v2 = k0;
|
||||
var v1 = { h: k1.h, l: k1.l }, v3 = k1;
|
||||
|
||||
_xor(v0, { h: 0x736f6d65, l: 0x70736575 });
|
||||
_xor(v1, { h: 0x646f7261, l: 0x6e646f6d });
|
||||
_xor(v2, { h: 0x6c796765, l: 0x6e657261 });
|
||||
_xor(v3, { h: 0x74656462, l: 0x79746573 });*/
|
||||
|
||||
_xor(v3, mi);
|
||||
_compress(v0, v1, v2, v3);
|
||||
_compress(v0, v1, v2, v3);
|
||||
_xor(v0, mi);
|
||||
_xor(v2, { h: 0, l: 0xff });
|
||||
_compress(v0, v1, v2, v3);
|
||||
_compress(v0, v1, v2, v3);
|
||||
_compress(v0, v1, v2, v3);
|
||||
_compress(v0, v1, v2, v3);
|
||||
|
||||
var h = v0;
|
||||
_xor(h, v1);
|
||||
_xor(h, v2);
|
||||
_xor(h, v3);
|
||||
|
||||
var res = new Uint32Array(2);
|
||||
res[0]=h.h; res[1]=h.l;
|
||||
return res;
|
||||
};
|
||||
|
||||
return {
|
||||
hash: hash,
|
||||
};
|
||||
})();
|
||||
|
||||
var module = module || { }, exports = module.exports = SipHash;
|
||||
@@ -1,59 +1,18 @@
|
||||
body {
|
||||
background: #EEF2FF url('bg.png') repeat-x 50% 0%;
|
||||
color: black;
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
font-size: 10pt;
|
||||
margin: 0 4px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
.thread {
|
||||
margin-bottom: 1em;
|
||||
display: inline-block;
|
||||
word-wrap: break-word;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
main,
|
||||
aside,
|
||||
section {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hover {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.notfound-hover {
|
||||
background: #EEF2FF;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#postform_container {
|
||||
background-color: #EEF2FF;
|
||||
}
|
||||
|
||||
.shadow {
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.55);
|
||||
}
|
||||
|
||||
.hover > div > .post , .notfound-hover {
|
||||
background-color: #D6DAF0;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.55);
|
||||
}
|
||||
|
||||
.frontend , .subject, .catalog_subject {
|
||||
color: #0F0C5D;
|
||||
.frontend , .subject {
|
||||
color: #928BFF;
|
||||
}
|
||||
|
||||
.name {
|
||||
color: #117743;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.postno {
|
||||
padding-right: 5px;
|
||||
}
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.name , .subject {
|
||||
font-weight: bold;
|
||||
@@ -64,6 +23,14 @@ section {
|
||||
}
|
||||
|
||||
|
||||
input {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
input.button {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 350px;
|
||||
}
|
||||
@@ -76,116 +43,16 @@ textarea {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
|
||||
.download_link,.fname_link {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 90%;
|
||||
height: auto
|
||||
padding: 0.5em 0;
|
||||
margin: auto;
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-height: 2.4em;
|
||||
pre > p {
|
||||
display: block-inline;
|
||||
}
|
||||
|
||||
.post_body > pre {
|
||||
font-size: 10pt;
|
||||
font-weight: unset;
|
||||
}
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
align: center;
|
||||
font-size: 12pt;
|
||||
color: black;
|
||||
display: inline-block;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
font-weight: bold;
|
||||
|
||||
font-family: sans;
|
||||
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table {
|
||||
margin: auto;
|
||||
}
|
||||
table.board-list-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table tbody td {
|
||||
margin: 0;
|
||||
padding: 4px 15px 4px 4px;
|
||||
vertical-align: top;
|
||||
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;
|
||||
}
|
||||
|
||||
.postform > tr, th {
|
||||
background: #98E;
|
||||
font-size: 10pt;
|
||||
text-align: left;
|
||||
padding-right: 10px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.postform td{
|
||||
padding: 0px 15px 0px 4px;
|
||||
}
|
||||
|
||||
.button {
|
||||
max-width: 10em;
|
||||
height: 2em;
|
||||
.reply, th, .ukko_thread_header {
|
||||
background: #202331;
|
||||
}
|
||||
|
||||
tr {
|
||||
background-color: transparent!important;
|
||||
}
|
||||
|
||||
input[type="text"],input[type="password"],textarea {
|
||||
border: 1px solid #a9a9a9;
|
||||
text-indent: 0;
|
||||
text-shadow: none;
|
||||
text-transform: none;
|
||||
word-spacing: normal;
|
||||
font-size: inherit;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#board_td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.reply, .pagelist, .op {
|
||||
background: #D6DAF0;
|
||||
border-width: 1px;
|
||||
border-style: none solid solid none;
|
||||
border-color: #B7C5D9;
|
||||
max-width: 94%!important;
|
||||
}
|
||||
|
||||
.reply, .ukko_thread_header {
|
||||
background: #D6DAF0;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
legend {
|
||||
/* background-color: #525252; */
|
||||
background: #202123;
|
||||
}
|
||||
|
||||
hr {
|
||||
@@ -193,78 +60,19 @@ hr {
|
||||
border-width: 1px medium medium;
|
||||
border-color: #b7c5d9;
|
||||
border-style: solid none none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.board_header {
|
||||
font-family: tahoma;
|
||||
letter-spacing: -2px;
|
||||
font-size: 20pt;
|
||||
margin: 0;
|
||||
color: #AF0A0F;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-top: 2em;
|
||||
|
||||
a:hover , a:visited:hover {
|
||||
color: #f13333;
|
||||
}
|
||||
|
||||
.board_header_catalog {
|
||||
text-align: center;
|
||||
margin-top: 1em;
|
||||
a {
|
||||
color: #4A4AFF;
|
||||
}
|
||||
|
||||
.catalog_thread {
|
||||
display: inline-block;
|
||||
width: 180px;
|
||||
text-align: center;
|
||||
padding: 0.25em;
|
||||
height: 240px;
|
||||
overflow: hidden;
|
||||
background-color: rgba(182, 182, 182 ,0.12);
|
||||
margin: 0.1em;
|
||||
border: 2px solid rgba(111, 111, 111, 0.34);
|
||||
}
|
||||
|
||||
.catalog_thread:hover {
|
||||
background-color: #D6DAF0;
|
||||
}
|
||||
|
||||
#catalog_container {
|
||||
width: 95%;
|
||||
margin: 1em auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.catalog_header, .catalog_subject {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.linkThumb img {
|
||||
max-height: 128px;
|
||||
max-width: 128px;
|
||||
box-shadow: 0 0 4px rgba(0,0,0,0.55);
|
||||
border: 2px solid rgba(153,153,153,0);
|
||||
}
|
||||
|
||||
a:hover , a:visited:hover, .navbar-link > label:hover {
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
a, a:visited, .navbar-link > label {
|
||||
color: #34345C;
|
||||
}
|
||||
|
||||
.postno {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.postno, .postnol, .postnol:visited {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.postno:hover, .postnol:hover, .postnol:visited:hover {
|
||||
color: #ff0000;
|
||||
text-decoration: underline;
|
||||
a:visited {
|
||||
color: #5E00A0;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
@@ -274,97 +82,74 @@ a, a:visited, .navbar-link > label {
|
||||
right: 0px;
|
||||
margin-top: 0px;
|
||||
z-index: 20;
|
||||
box-shadow: 1px 10px 20px rgba(0, 0, 0, 0.15);
|
||||
border-bottom: 1px solid;
|
||||
background: #D6DAF0;
|
||||
color: #34345C;
|
||||
min-height: 20px;
|
||||
padding-top: 2px;
|
||||
box-shadow: 0px 1px 20px rgba(0, 0, 0, 0.15);
|
||||
background: #202331;
|
||||
color: #616383;
|
||||
|
||||
}
|
||||
|
||||
.navbar-sep {
|
||||
color: darkgray;
|
||||
}
|
||||
|
||||
.navbar-link > label {
|
||||
text-decoration: underline;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#postform_container {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.navLinks {
|
||||
padding-bottom: 50px;
|
||||
margin-top: 5em;
|
||||
}
|
||||
|
||||
.ukko_thread_header {
|
||||
float: left;
|
||||
clear: both;
|
||||
padding: 5px 5px;
|
||||
margin: 5px 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
th {
|
||||
font-size: 10pt;
|
||||
padding-left: 10px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
#captcha_img {
|
||||
background: #d3d3d3;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
color: whitesmoke;
|
||||
background: #2d2d2d;
|
||||
border-color: #4D28CA;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
html {
|
||||
color: #ededed;
|
||||
background: #262230;
|
||||
height: 100%;
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
font-size: 10pt;
|
||||
margin: 0 4px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
|
||||
input, textarea {
|
||||
|
||||
}
|
||||
|
||||
.ukko_thread_header {
|
||||
border-color: #C0C3D4;
|
||||
border-top-left-radius: 0px;
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-style: dashed;
|
||||
.reply {
|
||||
margin-left: 1.8em;
|
||||
display: inline-block;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.frontend {
|
||||
margin-top: 0px;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.op , .reply {
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.op {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.post:target {
|
||||
background-color: #A99AFF;
|
||||
}
|
||||
|
||||
.postreply {
|
||||
float: right;
|
||||
margin-right: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.post {
|
||||
background-color: #D6DAF0;
|
||||
|
||||
border: 1px solid #B7C5D9;
|
||||
border-left: none;
|
||||
border-top: none;
|
||||
display: table;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
display: inline;
|
||||
margin-bottom: 5px;
|
||||
|
||||
display: inline-block;
|
||||
float: left;
|
||||
clear: both;
|
||||
|
||||
min-width: 500px;
|
||||
}
|
||||
|
||||
.postheader {
|
||||
width: 100%;
|
||||
padding-top: 3px;
|
||||
padding-right: 5px
|
||||
}
|
||||
|
||||
.tripcode {
|
||||
@@ -387,21 +172,19 @@ input, textarea {
|
||||
100% {background-color: green; color: white; }
|
||||
}
|
||||
|
||||
.psy {
|
||||
.psy > p {
|
||||
animation: psych 2s linear infinite;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
.memearrows {
|
||||
color: #789922;
|
||||
margin-left: none;
|
||||
color: green;
|
||||
}
|
||||
|
||||
.redtext {
|
||||
color: #AF0A0F;
|
||||
font-size: 12pt;
|
||||
color: #d50505;
|
||||
font-weight: bold;
|
||||
margin-left: none;
|
||||
}
|
||||
|
||||
.spoiler {
|
||||
@@ -426,70 +209,37 @@ input, textarea {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.expanded-thumbnail {
|
||||
display: inline;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
margin: 10px 10px 10px;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
display: block;
|
||||
margin: 5px 20px;
|
||||
.file-thumbnail {
|
||||
display: block;
|
||||
margin: 5px 20px 10px;
|
||||
border: medium none;
|
||||
max-width: 300px;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.reply {
|
||||
padding: 3px 5px 3px 5px;
|
||||
float: left;
|
||||
clear: both;
|
||||
.reply, .ukko_thread_header , pre {
|
||||
padding: 7px 7px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 1px 1px 3px black;
|
||||
}
|
||||
|
||||
.post_body > pre {
|
||||
background: #3f3f3f;
|
||||
color: #d17600;
|
||||
}
|
||||
|
||||
.post_body > p {
|
||||
margin: 0px 0px;
|
||||
}
|
||||
|
||||
.post_body {
|
||||
margin-left: 15px;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.post_body_line {
|
||||
margin-left: inherit;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
display: inline;
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
.pagelist {
|
||||
.post {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
margin-left: 15px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 50px;
|
||||
padding: 10px 10px 10px 10px;
|
||||
font-size: 12pt;
|
||||
font-weight: medium;
|
||||
|
||||
}
|
||||
|
||||
.backlink_rewritten {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.backlink, .backlink:hover, .backlink:visited, .backlink:visited:hover, .backlink_rewritten {
|
||||
margin-left: none;
|
||||
color: #D00
|
||||
}
|
||||
|
||||
|
||||
.origin > img{
|
||||
height: 25px;
|
||||
vertical-align: text-top;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.postform_attachment {
|
||||
max-width: 330px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
#faq > div {
|
||||
@@ -499,87 +249,5 @@ input, textarea {
|
||||
}
|
||||
|
||||
#captcha_img {
|
||||
background: white;
|
||||
}
|
||||
|
||||
figure {
|
||||
float: left;
|
||||
margin: 1ex;
|
||||
}
|
||||
img.thumbnail {
|
||||
max-width: 350px;
|
||||
max-height: 350px;
|
||||
}
|
||||
|
||||
|
||||
.replybar {
|
||||
float: left;
|
||||
position: fixed;
|
||||
top: 2ex;
|
||||
width: 500px;
|
||||
}
|
||||
@media (max-width: 100ex) {
|
||||
.replybar {
|
||||
width: 100%;
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
|
||||
.hide-reply:checked ~ div {
|
||||
width: 100%;
|
||||
position: static;
|
||||
}
|
||||
|
||||
textarea#reply-text {
|
||||
width: 100%;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.hide-reply {
|
||||
float: right;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#nntpchan_banner {
|
||||
align: center;
|
||||
}
|
||||
|
||||
.legal {
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.attachments {
|
||||
float: left;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.navbar-links, .navbar-link, .navbar-name {
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.board_title {
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.thread {
|
||||
padding-left: 10px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.hider {
|
||||
float: right;
|
||||
|
||||
}
|
||||
@keyframes rotate {
|
||||
0% { transform:rotate(0deg); }
|
||||
25% { transform:rotate(-1deg); }
|
||||
50% { transform:rotate(0deg); }
|
||||
75% { transform:rotate(1deg); }
|
||||
|
||||
}
|
||||
background: grey;
|
||||
}
|
||||
@@ -1,649 +0,0 @@
|
||||
body
|
||||
{
|
||||
background: #0B0B0B;
|
||||
color: #DADADA;
|
||||
font-family: arial, helvetica, sans-serif;
|
||||
font-size: 10pt;
|
||||
margin: 0 4px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.post_body > pre {
|
||||
color: #DADADA;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
main,
|
||||
aside,
|
||||
section
|
||||
{
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.frontend,
|
||||
.subject,
|
||||
.catalog_subject
|
||||
{
|
||||
color: #A03F4C;
|
||||
}
|
||||
|
||||
.name
|
||||
{
|
||||
color: #117743;
|
||||
}
|
||||
|
||||
.name,
|
||||
.subject
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#postform-outer
|
||||
{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
textarea
|
||||
{
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
#postform-inner
|
||||
{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.post
|
||||
{
|
||||
padding: 10px 10px;
|
||||
}
|
||||
|
||||
pre
|
||||
{
|
||||
white-space: pre-wrap;
|
||||
text-align: center;
|
||||
font-size: 13pt;
|
||||
background: #98E;
|
||||
color: black;
|
||||
display: inline-block;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
font-weight: bold;
|
||||
padding: 20px 20px 20px 20px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
table.board-list-table
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table tbody td
|
||||
{
|
||||
margin: 0;
|
||||
padding: 4px 15px 4px 4px;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table thead th
|
||||
{
|
||||
background-color: #121212;
|
||||
border: solid 1px #535353;
|
||||
color: #DADADA;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
table tbody tr:nth-of-type( even)
|
||||
{
|
||||
background-color: #121212;
|
||||
border: solid 1px #535353;
|
||||
}
|
||||
|
||||
.postform >tr,
|
||||
th
|
||||
{
|
||||
background-color: #121212;
|
||||
border: solid 1px #535353;
|
||||
color: #DADADA;
|
||||
font-size: 10pt;
|
||||
text-align: left;
|
||||
padding-right: 10px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
#postform-inner tr
|
||||
{
|
||||
background-color: transparent!important;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
textarea
|
||||
{
|
||||
text-indent: 0;
|
||||
text-shadow: none;
|
||||
text-transform: none;
|
||||
word-spacing: normal;
|
||||
font-size: inherit;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#board_td
|
||||
{
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.reply,
|
||||
.pagelist
|
||||
{
|
||||
background: #D6DAF0;
|
||||
border-width: 1px;
|
||||
border-style: none solid solid none;
|
||||
border-color: #B7C5D9;
|
||||
display: inline-block;
|
||||
max-width: 94%!important;
|
||||
}
|
||||
|
||||
.reply,
|
||||
.ukko_thread_header
|
||||
{
|
||||
background-color: #121212;
|
||||
border: solid 1px #535353;
|
||||
color: #DADADA;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
hr
|
||||
{
|
||||
height: 0px;
|
||||
border-width: 1px medium medium;
|
||||
border-color: #b7c5d9;
|
||||
border-style: solid none none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.board_header
|
||||
{
|
||||
font-family: tahoma;
|
||||
letter-spacing: -2px;
|
||||
font-size: 20pt;
|
||||
margin: 0;
|
||||
color: #AF0A0F;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.board_header_catalog
|
||||
{
|
||||
text-align: center;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.catalog_thread
|
||||
{
|
||||
display: inline-block;
|
||||
width: 180px;
|
||||
text-align: center;
|
||||
padding: 0.25em;
|
||||
height: 240px;
|
||||
overflow: hidden;
|
||||
background-color: rgba(182, 182, 182, 0.12);
|
||||
margin: 0.1em;
|
||||
border: 2px solid rgba(111, 111, 111, 0.34);
|
||||
}
|
||||
|
||||
.catalog_thread:hover
|
||||
{
|
||||
background-color: #D6DAF0;
|
||||
}
|
||||
|
||||
#catalog_container
|
||||
{
|
||||
width: 95%;
|
||||
margin: 1em auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.catalog_header,
|
||||
.catalog_subject
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.linkThumb img
|
||||
{
|
||||
max-height: 128px;
|
||||
max-width: 128px;
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.55);
|
||||
border: 2px solid rgba(153, 153, 153, 0);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:visited:hover,
|
||||
.navbar-link > label:hover
|
||||
{
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
a,
|
||||
a:visited,
|
||||
.navbar-link > label
|
||||
{
|
||||
color: #B8B8F7;
|
||||
;
|
||||
}
|
||||
|
||||
.postno
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.postno,
|
||||
.postnol,
|
||||
.postnol:visited
|
||||
{
|
||||
color: #B8B8F7;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.postno:hover,
|
||||
.postnol:hover,
|
||||
.postnol:visited:hover
|
||||
{
|
||||
color: #ff0000;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.navbar
|
||||
{
|
||||
position: fixed;
|
||||
padding: 0.25em;
|
||||
text-align: center;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
margin-top: 0px;
|
||||
z-index: 20;
|
||||
background-color: #121212;
|
||||
border-bottom: solid 1px #535353;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
|
||||
color: #B8B8F7;
|
||||
}
|
||||
|
||||
.navbar-sep
|
||||
{
|
||||
color: darkgray;
|
||||
}
|
||||
|
||||
.navbar-link > label
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#postform_container
|
||||
{
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.navLinks
|
||||
{
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
.ukko_thread_header
|
||||
{
|
||||
float: left;
|
||||
clear: both;
|
||||
display: inline-block;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea
|
||||
{
|
||||
background-color: #121212;
|
||||
border: solid 1px #535353;
|
||||
color: #DADADA;
|
||||
}
|
||||
|
||||
.ukko_thread_header
|
||||
{
|
||||
border-color: #C0C3D4;
|
||||
border-top-left-radius: 0px;
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
.frontend
|
||||
{
|
||||
margin-top: 0px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.op
|
||||
{
|
||||
margin-bottom: 1px;
|
||||
float: left;
|
||||
clear: both;
|
||||
background-color: #0f0f0f;
|
||||
border-color: #242424;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #0f0f0f;
|
||||
}
|
||||
|
||||
.post
|
||||
{
|
||||
margin-bottom: 5px;
|
||||
min-width: 500px;
|
||||
}
|
||||
|
||||
.postheader
|
||||
{
|
||||
padding-top: 3px;
|
||||
padding-right: 5px
|
||||
}
|
||||
|
||||
.tripcode
|
||||
{
|
||||
color: #de04ef;
|
||||
}
|
||||
|
||||
@keyframes psych
|
||||
{
|
||||
0%
|
||||
{
|
||||
background-color: red;
|
||||
color: blue;
|
||||
}
|
||||
10%
|
||||
{
|
||||
background-color: yellow;
|
||||
color: red;
|
||||
}
|
||||
20%
|
||||
{
|
||||
background-color: blue;
|
||||
color: green;
|
||||
}
|
||||
30%
|
||||
{
|
||||
background-color: green;
|
||||
color: yellow;
|
||||
}
|
||||
40%
|
||||
{
|
||||
background-color: red;
|
||||
color: blue;
|
||||
}
|
||||
50%
|
||||
{
|
||||
background-color: yellow;
|
||||
color: green;
|
||||
}
|
||||
60%
|
||||
{
|
||||
background-color: blue;
|
||||
color: yellow;
|
||||
}
|
||||
70%
|
||||
{
|
||||
background-color: green;
|
||||
color: blue;
|
||||
}
|
||||
80%
|
||||
{
|
||||
background-color: red;
|
||||
color: green;
|
||||
}
|
||||
90%
|
||||
{
|
||||
background-color: yellow;
|
||||
color: red;
|
||||
}
|
||||
95%
|
||||
{
|
||||
background-color: blue;
|
||||
color: yellow;
|
||||
}
|
||||
100%
|
||||
{
|
||||
background-color: green;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.psy
|
||||
{
|
||||
animation: psych 2s linear infinite;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.memearrows
|
||||
{
|
||||
color: #789922;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.redtext
|
||||
{
|
||||
color: #AF0A0F;
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.spoiler
|
||||
{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.spoiler > p
|
||||
{
|
||||
background: black;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.spoiler:hover > p
|
||||
{
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.intro
|
||||
{
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
|
||||
.file:not(.multiple) .file-thumbnail
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
.file-thumbnail
|
||||
{
|
||||
display: block;
|
||||
margin: 5px 20px 10px;
|
||||
border: medium none;
|
||||
max-width: 300px;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.reply
|
||||
{
|
||||
padding: 3px 5px 3px 5px;
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.post_body
|
||||
{
|
||||
margin-left: 15px;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.post_body_line
|
||||
{
|
||||
margin-left: inherit;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.post
|
||||
{
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pagelist
|
||||
{
|
||||
display: inline-block;
|
||||
background-color: #121212;
|
||||
border: solid 1px #535353;
|
||||
color: #DADADA;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
margin-left: 2em;
|
||||
padding: 10px 10px 10px 10px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.backlink,
|
||||
.backlink:hover,
|
||||
.backlink:visited,
|
||||
.backlink:visited:hover
|
||||
{
|
||||
margin-left: 0;
|
||||
color: #D00
|
||||
}
|
||||
|
||||
.origin > img
|
||||
{
|
||||
height: 20px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
.postform_attachment
|
||||
{
|
||||
max-width: 330px;
|
||||
}
|
||||
|
||||
#faq > div
|
||||
{
|
||||
margin-left: 20%;
|
||||
width: 50%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#captcha_img
|
||||
{
|
||||
background-color: #121212;
|
||||
border: solid 1px #535353;
|
||||
}
|
||||
|
||||
figure
|
||||
{
|
||||
float: left;
|
||||
margin: 1ex;
|
||||
}
|
||||
|
||||
img.thumbnail
|
||||
{
|
||||
max-width: 350px;
|
||||
max-height: 350px;
|
||||
}
|
||||
|
||||
.replybar
|
||||
{
|
||||
float: left;
|
||||
position: fixed;
|
||||
top: 2ex;
|
||||
right: 0;
|
||||
width: 34%
|
||||
}
|
||||
|
||||
@media (max-width: 100ex)
|
||||
{
|
||||
.replybar
|
||||
{
|
||||
width: 100%;
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
|
||||
.hide-reply:checked ~ div
|
||||
{
|
||||
width: 100%;
|
||||
position: static;
|
||||
}
|
||||
|
||||
textarea#reply-text
|
||||
{
|
||||
width: 100%;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.hide-reply
|
||||
{
|
||||
float: right;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#nntpchan_banner
|
||||
{
|
||||
text-align: center;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.legal
|
||||
{
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.attachments
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
hr
|
||||
{
|
||||
border: 1px solid #535353;
|
||||
height: 1px
|
||||
}
|
||||
|
||||
img#nntpchan_banner {
|
||||
box-shadow: 0px 0px 10px 0px;
|
||||
}
|
||||
|
||||
#postform_container {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.post:target {
|
||||
background-color: #2c2d3e;
|
||||
box-shadow: 0px 0px 10px 2px;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.5 KiB |
@@ -1,3 +0,0 @@
|
||||
/*
|
||||
put your custom stylesheet here
|
||||
*/
|
||||
@@ -1,27 +0,0 @@
|
||||
{{!
|
||||
board.mustache, displays the contents of page N of the board
|
||||
|
||||
template parameters:
|
||||
- board ( the model of the current page )
|
||||
- page ( the page number of the current page )
|
||||
|
||||
board has the properties:
|
||||
- Prefix ( absolute path like //site.tld/ or /path/ )
|
||||
- Board ( the name of the board )
|
||||
- Navbar ( a function that renders the navbar, should not be escaped )
|
||||
- Threads ( a list of Thread Models with the last few replies )
|
||||
}}
|
||||
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>{{board.Board}}</title></head><body>
|
||||
{{{board.Navbar}}}
|
||||
{{{form}}}
|
||||
<dl>
|
||||
<hr>
|
||||
{{#board.Threads}}
|
||||
{{{OP.Truncate.RenderPost}}}
|
||||
{{#Truncate.Replies}}
|
||||
{{{Truncate.RenderPost}}}
|
||||
{{/Truncate.Replies}}
|
||||
<hr>
|
||||
{{/board.Threads}}
|
||||
</dl>
|
||||
</body></html>
|
||||
@@ -1,33 +0,0 @@
|
||||
{{!
|
||||
boardlist.mustache -- full list of every board
|
||||
template parameters:
|
||||
- graph ( a list of 4 string tuples: (board, posts_per_hour, posts_per_day, total_posts) )
|
||||
- frontend ( the name of the frontend )
|
||||
- prefix ( the site's prefix )
|
||||
}}
|
||||
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>{{frontend}} boards</title></head><body>
|
||||
<table>
|
||||
<tr>
|
||||
<th>board</th>
|
||||
<th>posts per hour</th>
|
||||
<th>posts per day</th>
|
||||
<th>total</th>
|
||||
</tr>
|
||||
{{# graph}}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{prefix}}{{Board}}-0.html">{{Board}}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{Hour}}
|
||||
</td>
|
||||
<td>
|
||||
{{Day}}
|
||||
</td>
|
||||
<td>
|
||||
{{All}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/ graph}}
|
||||
</table>
|
||||
</body></html>
|
||||
@@ -1,11 +0,0 @@
|
||||
{{!
|
||||
frontpage.mustache -- template for index.html
|
||||
template parameters:
|
||||
- boardgraph ( a boardPageRows instance, see srnd/model.go )
|
||||
- postgraph ( a postsGraph instance , see srnd/model.go )
|
||||
- overview ( an overviewModel instance, see srnd/model.go )
|
||||
- totalposts ( the number of total posts we have ever seen )
|
||||
- frontend ( the name of the frontend )
|
||||
- prefix ( the site's prefix )
|
||||
}}
|
||||
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>{{frontend}} on nntpchan</title></head><body><p>{{frontend}} on nntpchan</p><p><a href="ukko.html">overboard</a> <a href="{{prefix}}boards.html">boards</a> <a href="{{prefix}}static/chen-chan-faq.html">faq</a></p><dl><dt>last posts:</dt><dd>{{{overview.Render}}}</dd></dl><dl><dt>board stats:</dt><dd><table><tr><th>board</th><th>posts this hour</th><th>posts today</th><th>total</th></tr>{{# boardgraph}}<tr><td><a href="{{prefix}}{{Board}}-0.html">{{Board}}</a></td><td>{{Hour}}</td><td>{{Day}}</td><td>{{All}}</td></tr>{{/ boardgraph}}</table></dd></dl><dl><dt>total stats:</dt><dd>{{{postsgraph.Render}}}</dd></dl><p>{{totalposts}} posts total since 2015-12-23</p></body></html>
|
||||
@@ -1,36 +0,0 @@
|
||||
{{!
|
||||
graph_history.mustache
|
||||
template parameters:
|
||||
- history ( a list of PostEntry instances, see srnd/model.go )
|
||||
|
||||
}}
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"></meta>
|
||||
<link rel="stylesheet" href="{{prefix}}site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}user.css" />
|
||||
<title> Post History</title>
|
||||
</head>
|
||||
<body>
|
||||
<td>
|
||||
<table id="history_graph">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Month</th>
|
||||
<th>Posts</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#history.Scale}}
|
||||
<tr>
|
||||
<td>{{Date}}</td>
|
||||
<td class="history_num">{{Num}}</td>
|
||||
<td>{{OvercockGraph}}</td>
|
||||
</tr>
|
||||
{{/history.Scale}}
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,15 +0,0 @@
|
||||
{{!
|
||||
keygen.mustache -- page containing a newly generated tripcode
|
||||
template parameters:
|
||||
- prefix ( the site prefix )
|
||||
- public ( the public key in hex )
|
||||
- secret ( the secret key in hex )
|
||||
- tripcode ( html version of the public key )
|
||||
}}
|
||||
<!doctype html><html><head><title>new tripcode</title></head><body><pre>
|
||||
new tripcode
|
||||
|
||||
secret: {{secret}}
|
||||
public: {{public}}
|
||||
tripcode: {{{tripcode}}}
|
||||
</pre></body></html>
|
||||
@@ -1,7 +0,0 @@
|
||||
<!doctype html><html><head><link rel="stylesheet" href="{{prefix}}static/chen-chan.css"><title>login</title></head><body>
|
||||
<form action="login" method="POST" name="modlogin">
|
||||
<label for="mod_key">secret</label>
|
||||
<input type="password" id="mod_key" name="privkey">
|
||||
<input type="submit" value="login">
|
||||
</form>
|
||||
</body></html>
|
||||
@@ -1,9 +0,0 @@
|
||||
{{!
|
||||
modlogin_result.mustache -- shows the result of a login attempt
|
||||
template parameters:
|
||||
- prefix ( the site prefix )
|
||||
- mod_prefix ( the prefix to the mod panel, could be something like https://mod.site.tld/ or /mod/ )
|
||||
- message ( the message returned from the login attempt )
|
||||
- fail ( present if the login failed ) // not yet added
|
||||
}}
|
||||
<!doctype html><html><head><meta http-equiv="refresh" content="1; {{mod_prefix}}"><title>login</title></head><body><p>{{message}}</p></body></html>
|
||||
@@ -1,79 +0,0 @@
|
||||
{{!
|
||||
modpage.mustache -- the moderator panel when logged in
|
||||
template parameters:
|
||||
- prefix ( the site's prefix )
|
||||
}}
|
||||
<!doctype html><html><head>
|
||||
<link rel="stylesheet" href="{{prefix}}static/chen-chan.css">
|
||||
<!-- yes it uses js -->
|
||||
<script src="{{prefix}}static/mod.js"></script>
|
||||
<title>nntpchan mod page</title>
|
||||
</head><body>
|
||||
<dl>
|
||||
<dt>post actions</dt>
|
||||
<dd>
|
||||
<div>
|
||||
<label for="nntpchan_mod_target">target</label>
|
||||
<input id="nntpchan_mod_target" type="text">
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="nntpchan_ban()">ban (url)</button>
|
||||
<button onclick="nntpchan_delete()">delete (url)</button>
|
||||
<button onclick="nntpchan_unban()">unban (ip)</button>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>key actions</dt>
|
||||
<dd>
|
||||
<div>
|
||||
<label for="nntpchan_board_target">pubkey:</label>
|
||||
<input type="text" id="nntpchan_key_target" />
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="nntpchan_key_add()">add key</button>
|
||||
<button onclick="nntpchan_key_del()">remove key</button>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>board actions</dt>
|
||||
<dd>
|
||||
<div>
|
||||
<label for="nntpchan_board_target">board name:</label>
|
||||
<input type="text" id="nntpchan_board_target">
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="nntpchan_admin_board('frontend.add')">add board</button>
|
||||
<button onclick="nntpchan_admin_board('frontend.regen')">regenerate</button>
|
||||
<button onclick="nntpchan_admin_board('frontend.ban')">ban</button>
|
||||
<button onclick="nntpchan_admin_board('frontend.unban')">unban</button>
|
||||
<button onclick="nntpchan_admin_board('frontend.nuke')">nuke</button>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>lightweight actions</dt>
|
||||
<dd>
|
||||
<button onclick="nntpchan_admin('template.reload')">reload all templates</button>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>very load heavy actions, use with care</dt>
|
||||
<dd>
|
||||
<div>
|
||||
<button onclick="nntpchan_admin('frontend.regen')">regenerate all pages</button>
|
||||
<button onclick="nntpchan_admin('thumbnail.regen')">regenerate all thumbnails</button>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>status</dt>
|
||||
<dd>
|
||||
<div id="nntpchan_mod_result"></div>
|
||||
<noscript>
|
||||
<b>enable js to use the mod panel kthx</b>
|
||||
</noscript>
|
||||
</dd>
|
||||
</dl>
|
||||
</body></html>
|
||||
@@ -1,12 +0,0 @@
|
||||
{{!
|
||||
navbar.mustache -- element on the top of each nod-mod page
|
||||
|
||||
TODO: make this not suck, have a board list, have board page list
|
||||
|
||||
template parameters:
|
||||
- name ( the name of whatever resource we are on, board/thread )
|
||||
- frontend ( the name of the frontend we are on )
|
||||
- links ( a list of Link Models to display )
|
||||
- prefix ( site prefix )
|
||||
}}
|
||||
<p>{{name}} on {{frontend}} | {{# links}} <a href="{{LinkURL}}">{{Text}}</a> {{/ links}} | <a href="{{prefix}}">front page</a> <a href="{{prefix}}ukko.html">overboard</a></p>
|
||||
@@ -1 +0,0 @@
|
||||
no apparently.
|
||||
@@ -1,7 +0,0 @@
|
||||
{{! overview.mustache
|
||||
paramters:
|
||||
|
||||
- overview (list of PostModels in order of last posted)
|
||||
|
||||
}}
|
||||
<table><tr><th>date</th><th>board</th><th>subject</th></tr>{{#overview}}<tr><td>{{Date}}</td><td><a href="{{Prefix}}{{Board}}-0.html">{{Board}}</a></td><td><a href="{{PostURL}}">{{Truncate.Subject}}</a></td></tr>{{/overview}}</table>
|
||||
@@ -1,15 +0,0 @@
|
||||
<dt id="{{PostHash}}">
|
||||
<a onclick="nntpchan_backlink('{{ShortHash}}');" title="{{MessageID}}">{{ShortHash}}</a>
|
||||
{{Date}}
|
||||
{{#IsI2P}}i2p{{/IsI2P}}{{#IsTor}}tor{{/IsTor}}{{#IsClearnet}}clr{{/IsClearnet}}
|
||||
{{Subject}}
|
||||
{{Name}}
|
||||
{{{Pubkey}}}
|
||||
<a href="{{PostURL}}">[reply]</a>
|
||||
</dt>
|
||||
<dd>
|
||||
{{{RenderBody}}}
|
||||
{{#Attachments}}
|
||||
file: <a href="{{Source}}" target="_blank">{{Filename}}</a><br><br>
|
||||
{{/Attachments}}
|
||||
</dd>
|
||||
@@ -1,3 +0,0 @@
|
||||
<!doctype html><html><head>
|
||||
<meta http-equiv="refresh" content="1; {{redirect_url}}"></head>
|
||||
<body><p>fail: {{reason}}</p></body></html>
|
||||
@@ -1,40 +0,0 @@
|
||||
<html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>try again</title></head><body>
|
||||
<form enctype="multipart/form-data" name="post" method="post">
|
||||
{{#attachment}}
|
||||
<input type="hidden" name="attachment_data" value="{{attachment}}">
|
||||
<input type="hidden" name="attachment_filename" value="{{attachment_filename}}">
|
||||
<input type="hidden" name="attachment_mime" value="{{attachment_type}}">
|
||||
{{/attachment}}
|
||||
<input type="hidden" name="reference" value="{{reference}}">
|
||||
<input type="hidden" name="name" value="{{name}}">
|
||||
<input type="hidden" name="subject" value="{{subject}}">
|
||||
<input type="hidden" name="captcha_id" value="{{captcha_id}}">
|
||||
<input type="hidden" name="message" value="{{message}}">
|
||||
<div id="postform-outer">
|
||||
<div id="postform-inner">
|
||||
<div>{{fail_message}}</div>
|
||||
<table class="postform">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
Captcha
|
||||
</th>
|
||||
<td>
|
||||
<img id="captcha_img" src="{{prefix}}captcha/{{captcha_id}}.png" alt="captcha" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Solution
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="captcha" />
|
||||
<input type="submit" value="Post" class="button" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body></html>
|
||||
@@ -1,7 +0,0 @@
|
||||
{{!
|
||||
post_success.mustache -- shown when we do a successful post
|
||||
template parameters:
|
||||
- redirect_url ( the url of the next page we should redirect to )
|
||||
- message_id ( the value of the Message-ID header in the post we made, the truncated sha1 of this is the >>posthash )
|
||||
}}
|
||||
<!doctype html><html><head><meta http-equiv="refresh" content="2; {{redirect_url}}"></head><body><pre>posted as {{message_id}}</pre></body></html>
|
||||
@@ -1,20 +0,0 @@
|
||||
{{!
|
||||
postform.mustache -- the form for posting
|
||||
|
||||
template parameters:
|
||||
- post_url ( the url of the post form )
|
||||
- reference ( the post we are replying to, or empty string if it's an op )
|
||||
- button ( the text for the reply button )
|
||||
}}
|
||||
<form action="{{post_url}}" enctype="multipart/form-data" name="post" method="post" style="overflow:auto">
|
||||
<input type="hidden" name="reference" value="{{reference}}">
|
||||
<textarea id="postform_message" name="message" placeholder="text" cols="40" rows="10" style="float:left" ></textarea><br>
|
||||
<div style="float:left">
|
||||
<input type="file" name="attachment"><br>
|
||||
<input type="text" name="subject" placeholder="subject"><br>
|
||||
<input type="text" name="name" placeholder="name"><br>
|
||||
<input type="text" name="captcha" placeholder="captcha"><br>
|
||||
<input type="submit" value="{{button}}" class="button"><br>
|
||||
</div>
|
||||
<img id="captcha_img" src="{{prefix}}captcha/img" alt="captcha" style="float:left">
|
||||
</form>
|
||||
@@ -1,7 +0,0 @@
|
||||
{{!
|
||||
posts graph.mustache -- post frequence graph
|
||||
parameters:
|
||||
|
||||
* graph - a postsGraph instance (see srnd/model.go)
|
||||
}}
|
||||
<table><tr><th>date</th><th>posts</th><th>cock</th></tr>{{#graph.Scale}}<tr><td>{{Day}}</td><td>{{Num}}</td><td>{{OvercockGraph}}</td></tr>{{/graph.Scale}}</table>
|
||||
@@ -1,23 +0,0 @@
|
||||
{{!
|
||||
thread.mustache -- renders to a thread-*.html page, shows the entire thread
|
||||
template parameters:
|
||||
- board ( the Board Model of the board this thread was posted in )
|
||||
- thread ( the Thread Model of the current thread being rendered )
|
||||
- form ( the post form markup )
|
||||
|
||||
Thread Model attributes:
|
||||
- OP , the Post Model of the original poster
|
||||
- Replies , a list of all the replies or empty if none
|
||||
- Board , the name of the Board this thread is on
|
||||
- BoardURL , the url that points to the board index page
|
||||
}}
|
||||
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>{{thread.OP.Subject}}</title><script src="{{thread.Prefix}}static/nntpchan.js"></script></head><body>
|
||||
{{{thread.Navbar}}}
|
||||
{{{form}}}
|
||||
<dl>
|
||||
{{{thread.OP.RenderPost}}}
|
||||
{{# thread.Replies}}
|
||||
{{{RenderPost}}}
|
||||
{{/ thread.Replies}}
|
||||
</dl>
|
||||
</body></html>
|
||||
@@ -1,19 +0,0 @@
|
||||
{{!
|
||||
ukko.mustache -- overboard, contains the last threads posted regardless of newsgroup
|
||||
template parameters:
|
||||
- prefix ( site prefix )
|
||||
- threads ( a list of Thread Models that represent the latest threads )
|
||||
}}
|
||||
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>ukko/overboard</title></head><body>
|
||||
<a href="/">frontpage</a>
|
||||
{{#threads}}
|
||||
<hr>
|
||||
<p>posted on <a href="{{{BoardURL}}}">{{OP.Board}}</a></p>
|
||||
<dl>
|
||||
{{{OP.Truncate.RenderPost}}}
|
||||
{{#Truncate.Replies}}
|
||||
{{{Truncate.RenderPost}}}
|
||||
{{/Truncate.Replies}}
|
||||
</dl>
|
||||
{{/threads}}
|
||||
</body></html>
|
||||
@@ -1,25 +0,0 @@
|
||||
{{!
|
||||
404.mustache -- 404 page
|
||||
template parameters:
|
||||
- prefix (the site prefix)
|
||||
}}
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title> 404 </title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{prefix}}static/nntpchan.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<div class="not_found">
|
||||
<img src="{{prefix}}static/404.png"></img>
|
||||
<div class="not_found_message">
|
||||
{{#i18n.Translations}}{{resource_not_found}}{{/i18n.Translations}}
|
||||
</div>
|
||||
</div>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
@@ -11,13 +11,10 @@
|
||||
- Navbar ( a function that renders the navbar, should not be escaped )
|
||||
- Threads ( a list of Thread Models with the last few replies )
|
||||
}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css"></link>
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{board.Board}}</title>
|
||||
</head>
|
||||
@@ -25,12 +22,7 @@
|
||||
<!-- begin navbar -->
|
||||
{{{board.Navbar}}}
|
||||
<!-- end navbar -->
|
||||
<center>
|
||||
<div id="nntpchan_banner">
|
||||
</div>
|
||||
</center>
|
||||
<div class="board_header">{{board.Board}}</div>
|
||||
<div class="board_header_catalog"><a href="{{board.Prefix}}catalog-{{board.Name}}.html"> {{#i18n.Translations}}{{catalog_label}}{{/i18n.Translations}} </a></div>
|
||||
|
||||
<!-- postform -->
|
||||
<div id="postform_container">
|
||||
{{{form}}}
|
||||
@@ -39,33 +31,17 @@
|
||||
<div id="threads_container">
|
||||
{{#board.Threads}}
|
||||
<div class="thread" id="thread_{{OP.PostHash}}">
|
||||
<div class="thread_header">
|
||||
<div clsss="thread_header">
|
||||
</div>
|
||||
{{{OP.Truncate.RenderPost}}}
|
||||
{{#Truncate.Replies}}
|
||||
{{{Truncate.RenderPost}}}
|
||||
<br />
|
||||
{{/Truncate.Replies}}
|
||||
<hr />
|
||||
</div>
|
||||
<br/>
|
||||
<hr/>
|
||||
{{/board.Threads}}
|
||||
</div>
|
||||
<div class="pagelist">{{# board.PageList }}[<a href="{{LinkURL}}"> {{Text}} </a>] {{/ board.PageList }}
|
||||
<span class="navbar-sep">
|
||||
|
|
||||
</span>
|
||||
<a href="{{board.Prefix}}catalog-{{board.Name}}.html"> {{#i18n.Translations}}{{catalog_label}}{{/i18n.Translations}} </a>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
var prefix = "{{board.Prefix}}";
|
||||
var e = document.getElementById("nntpchan_banner");
|
||||
nntpchan_inject_banners(e, prefix);
|
||||
init(prefix);
|
||||
ready();
|
||||
</script>
|
||||
<hr/>
|
||||
<footer>
|
||||
<p class="legal">All posts on this site are the responsibility of the individual poster and not the administration, pursuant to 47 U.S.C. § 230.</p>
|
||||
<p class="legal">To make a DMCA request or report illegal content, please contact the administration</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
{{!
|
||||
boardlist.mustache -- full list of every board
|
||||
template parameters:
|
||||
- graph ( a list of 4 string tuples: (board, posts_per_hour, posts_per_day, total_posts) )
|
||||
- frontend ( the name of the frontend )
|
||||
- prefix ( the site's prefix )
|
||||
}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css"></link>
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css"></link>
|
||||
<title> {{frontend}} {{#i18n.Translations}}{{board_list_title}}{{/i18n.Translations}} </title>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<div class="index-outer">
|
||||
<div class="index-inner">
|
||||
<table id="board_graph">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> {{#i18n.Translations}}{{board_label}}{{/i18n.Translations}} </th>
|
||||
<th> {{#i18n.Translations}}{{pph_label}}{{/i18n.Translations}} </th>
|
||||
<th> {{#i18n.Translations}}{{ppd_label}}{{/i18n.Translations}} </th>
|
||||
<th> {{#i18n.Translations}}{{total}}{{/i18n.Translations}} </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{# graph}}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{prefix}}{{Board}}-0.html">{{Board}}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{Hour}}
|
||||
</td>
|
||||
<td>
|
||||
{{Day}}
|
||||
</td>
|
||||
<td>
|
||||
{{All}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/ graph}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,47 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{catalog_title}}{{/i18n.Translations}} {{board.Name}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- begin navbar -->
|
||||
{{{board.Navbar}}}
|
||||
<!-- end navbar -->
|
||||
<center>
|
||||
<div id="nntpchan_banner">
|
||||
</div>
|
||||
</center>
|
||||
<div class="board_header">{{#i18n.Translations}}{{catalog_title}}{{/i18n.Translations}} {{board.Name}}</div>
|
||||
<!-- postform -->
|
||||
<hr />
|
||||
<div id="catalog_container">
|
||||
{{#board.Threads}}
|
||||
<div class="catalog_thread">
|
||||
<a class="linkThumb" href="{{OP.PostURL}}"><img src="{{OP.RepresentativeThumb}}"></a>
|
||||
<div class="catalog_header">{{#i18n.Translations}}{{replies_short_label}}{{/i18n.Translations}}: {{ReplyCount}} / {{#i18n.Translations}}{{pictures_short_label}}{{/i18n.Translations}}: {{Page}}</div>
|
||||
<div class="catalog_subject">{{OP.Subject}}</div>
|
||||
<div class="catalog_body">
|
||||
{{{OP.RenderBody}}}
|
||||
</div>
|
||||
</div>
|
||||
{{/board.Threads}}
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
|
||||
var e = document.getElementById("nntpchan_banner");
|
||||
nntpchan_inject_banners(e, "{{board.Prefix}}");
|
||||
|
||||
</script>
|
||||
<hr/>
|
||||
<footer>
|
||||
<p class="legal">All posts on this site are the responsibility of the individual poster and not the administration, pursuant to 47 U.S.C. § 230.</p>
|
||||
<p class="legal">To make a DMCA request or report illegal content, please contact the administration</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,9 +1,7 @@
|
||||
{{!
|
||||
frontpage.mustache -- template for index.html
|
||||
template parameters:
|
||||
- boardgraph ( markup of boardPageRows instance, see srnd/model.go )
|
||||
- postgraph ( markup of postsGraph instance , see srnd/model.go )
|
||||
- overview ( markup of overviewModel instance , see srnd/model.go )
|
||||
- graph ( a list of 4 string tuples: (board, posts_per_hour, posts_per_day, total_posts) )
|
||||
- totalposts ( the number of total posts we have ever seen )
|
||||
- frontend ( the name of the frontend )
|
||||
- prefix ( the site's prefix )
|
||||
@@ -11,78 +9,50 @@
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<script src="{{prefix}}static/nntpchan.js" type="text/javascript"></script>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css"></link>
|
||||
<title> {{frontend}} on nntpchan </title>
|
||||
</head>
|
||||
<body>
|
||||
{{{navbar}}}
|
||||
<center>
|
||||
<div class="index-outer">
|
||||
<div id="nntpchan_banner">
|
||||
</div>
|
||||
<div class="index-inner">
|
||||
<div>{{frontend}} on nntpchan</div>
|
||||
<div>View the <a href="{{prefix}}ukko.html">overboard</a></div>
|
||||
<div>Join the IRC on <a href="https://qchat.rizon.net/?channels=#nntpchan">rizon</a> or <a href="irc://127.0.0.1:6668/overchan">irc2p</a></div>
|
||||
<div>Check out the <a href="{{prefix}}boards.html">board list</a></div>
|
||||
<div>Fork on github: <a href="https://github.com/majestrate/nntpchan/">frontend</a> and <a href="https://github.com/majestrate/srndv2/">core</a></div>
|
||||
<div>We've Had {{totalposts}} Posts Since August 01 2015 </div>
|
||||
</div>
|
||||
<div class="index-inner">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="posts_td">
|
||||
{{{postsgraph}}}
|
||||
</td>
|
||||
<td class="board_td">
|
||||
{{! todo: move boardgraph into its own file like postsgraph }}
|
||||
<table id="board_graph">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> {{#i18n.Translations}}{{board_label}}{{/i18n.Translations}} </th>
|
||||
<th> {{#i18n.Translations}}{{posts_hour}}{{/i18n.Translations}} </th>
|
||||
<th> {{#i18n.Translations}}{{posts_today}}{{/i18n.Translations}} </th>
|
||||
<th> {{#i18n.Translations}}{{total}}{{/i18n.Translations}} </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{# boardgraph}}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{prefix}}{{Board}}-0.html">{{Board}}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{Hour}}
|
||||
</td>
|
||||
<td>
|
||||
{{Day}}
|
||||
</td>
|
||||
<td>
|
||||
{{All}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/ boardgraph}}
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{{{overview}}}
|
||||
</div>
|
||||
<div class="index-outer">
|
||||
<div class="index-inner">
|
||||
<h1> {{frontend}} on nntpchan </h1>
|
||||
<h2>View the <a href="ukko.html">overboard</a></h2>
|
||||
<h3>Read the <a href="{{prefix}}static/faq.html">FAQ</a></h3>
|
||||
<h3>Join the <a href="https://qchat.rizon.net/?channels=#nntpchan">IRC</a></h3>
|
||||
<h3>Create a <a href="{{prefix}}new/">new board</a></h3>
|
||||
<h3>Fork on github: <a href="https://github.com/majestrate/nntpchan/">frontend</a> and <a href="https://github.com/majestrate/srndv2/">core</a></h3>
|
||||
<h4>We've Had {{totalposts}} Posts Since August 01 2015 </h4>
|
||||
</div>
|
||||
<div class="index-inner">
|
||||
<table id="board_graph">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th> Board </th>
|
||||
<th> Post per Hour </th>
|
||||
<th> Post per Day </th>
|
||||
<th> Total </th>
|
||||
</tr>
|
||||
{{# graph}}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{prefix}}{{Board}}-0.html">{{Board}}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{Hour}}
|
||||
</td>
|
||||
<td>
|
||||
{{Day}}
|
||||
</td>
|
||||
<td>
|
||||
{{All}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/ graph}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</center>
|
||||
<script type="text/javascript">
|
||||
var e = document.getElementById("nntpchan_banner");
|
||||
nntpchan_inject_banners(e, "{{prefix}}");
|
||||
</script>
|
||||
<hr/>
|
||||
<footer>
|
||||
<p class="legal">All posts on this site are the responsibility of the individual poster and not the administration, pursuant to 47 U.S.C. § 230.</p>
|
||||
<p class="legal">To make a DMCA request or report illegal content, please contact the administration</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -1,37 +0,0 @@
|
||||
{{!
|
||||
graph_history.mustache
|
||||
template parameters:
|
||||
- history ( a list of PostEntry instances, see srnd/model.go )
|
||||
|
||||
}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"></meta>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<title>{{#i18n.Translations}}{{post_history_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<td>
|
||||
<table id="history_graph">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{#i18n.Translations}}{{month}}{{/i18n.Translations}}</th>
|
||||
<th>{{#i18n.Translations}}{{posts}}{{/i18n.Translations}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#history.Scale}}
|
||||
<tr>
|
||||
<td>{{Date}}</td>
|
||||
<td class="history_num">{{Num}}</td>
|
||||
<td>{{OvercockGraph}}</td>
|
||||
</tr>
|
||||
{{/history.Scale}}
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,64 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{api_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{api_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post" autocomplete="off">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{api_username}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="user" value="{{dialog.User}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{api_password_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="password" name="pass" value="">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{api_secret_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="secret" value="{{dialog.Secret}}">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,64 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{binary_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{binary_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post" autocomplete="off">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{convert_prompt}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="convert" value="{{dialog.Convert}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{ffmpeg_prompt}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="ffmpeg" value="{{dialog.FFmpeg}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{sox_prompt}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="sox" value="{{dialog.Sox}}">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,64 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{cache_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{cache_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
|
||||
</th>
|
||||
<td>
|
||||
<input type="radio" name="cache" value="file" checked> {{#i18n.Translations}}{{file_cache_name}}{{/i18n.Translations}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
|
||||
</th>
|
||||
<td>
|
||||
<input type="radio" name="cache" value="null"> {{#i18n.Translations}}{{null_cache_name}}{{/i18n.Translations}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
|
||||
</th>
|
||||
<td>
|
||||
<input type="radio" name="cache" value="redis"> {{#i18n.Translations}}{{redis_cache_name}}{{/i18n.Translations}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,56 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{crypto_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{crypto_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post" autocomplete="off">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{host_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="host" value="{{dialog.Host}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{key_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="key" value="{{dialog.Key}}">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,56 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{db_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{db_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
|
||||
</th>
|
||||
<td>
|
||||
<input type="radio" name="db" value="postgres"> {{#i18n.Translations}}{{postgres_name}}{{/i18n.Translations}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
|
||||
</th>
|
||||
<td>
|
||||
<input type="radio" name="db" value="redis" checked> {{#i18n.Translations}}{{redis_name}}{{/i18n.Translations}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,72 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{frontend_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{frontend_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post" autocomplete="off">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{frontend_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="name" value="{{dialog.Name}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{locale_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="locale" value="{{dialog.Locale}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{allow_files_prompt}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="allow_files" value="1" checked>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{enable_json_prompt}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="json" value="1">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,56 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{key_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{key_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post" autocomplete="off">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{pubkey_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="public" value="{{dialog.Public}}" size="65" readonly>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{secretkey_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="secret" value="{{dialog.Secret}}" size="65" readonly>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,80 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{nntp_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{nntp_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post" autocomplete="off">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{nntp_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="nntp_name" value="{{dialog.Name}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{allow_attachments_prompt}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="allow_attachments" value="1" checked>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{allow_anon_prompt}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="allow_anon" value="1" checked>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{allow_anon_attachments_prompt}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="allow_anon_attachments" value="1">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{require_tls_prompt}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="require_tls" value="1" checked>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,72 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{postgres_db_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{postgres_db_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post" autocomplete="off">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{host_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="host" value="{{dialog.Host}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{port_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="port" value="{{dialog.Port}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{username_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="user" value="{{dialog.Username}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{password_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="password" name="password" value="">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,64 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{redis_db_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{redis_db_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post" autocomplete="off">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{host_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="host" value="{{dialog.Host}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{port_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="port" value="{{dialog.Port}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{password_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="password" name="password" value="">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,64 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{board.Prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{board.Prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{redis_db_install_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="installer_header">{{#i18n.Translations}}{{redis_db_install_title}}{{/i18n.Translations}}</div>
|
||||
{{#dialog.HasError}}
|
||||
<p class="installer_error">{{dialog.Error}}</p>
|
||||
{{/dialog.HasError}}
|
||||
<form action="" method="post" autocomplete="off">
|
||||
<div id="install-outer">
|
||||
<div id="installer-inner">
|
||||
<table class="installer-tab">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{host_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="host" value="{{dialog.Host}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{port_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="port" value="{{dialog.Port}}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{{#i18n.Translations}}{{password_name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="password" name="password" value="">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{next_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
{{^dialog.HasNext}}
|
||||
<input type="submit" value="{{#i18n.Translations}}{{finish_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
{{/dialog.HasNext}}
|
||||
</div>
|
||||
</form>
|
||||
{{#dialog.HasPrevious}}
|
||||
<div class="back_button">
|
||||
<form action="" method="post">
|
||||
<input type="hidden" name="back" value="true" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{previous_prompt}}{{/i18n.Translations}}" class="button" />
|
||||
</form>
|
||||
</div>
|
||||
{{/dialog.HasPrevious}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,19 +5,16 @@
|
||||
- public ( the public key in hex )
|
||||
- secret ( the secret key in hex )
|
||||
- tripcode ( html version of the public key )
|
||||
}}
|
||||
<!doctype html>
|
||||
}}
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"></meta>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{prefix}}static/nntpchan.js"></script>
|
||||
<title>{{#i18n.Translations}}{{new_tripcode_title}}{{/i18n.Translations}}</title>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css"></link>
|
||||
<title> here is a new tripcode </title>
|
||||
</head>
|
||||
<body>
|
||||
<pre>{{#i18n.Translations}}{{new_tripcode_label}}{{/i18n.Translations}}:
|
||||
<div id="secret_key">{{#i18n.Translations}}{{secret_key}}{{/i18n.Translations}}: {{secret}}</div><div id="public_key">{{#i18n.Translations}}{{public_key}}{{/i18n.Translations}}: {{public}}</div><div>{{#i18n.Translations}}{{tripcode}}{{/i18n.Translations}}: <span class="tripcode" id="capcode_key">{{{tripcode}}}</span></div>
|
||||
<pre>New Tripcode:
|
||||
<div id="secret_key">secret: {{secret}}</div><div id="public_key">public: {{public}}</div><div>tripcode: <span class="tripcode" id="capcode_key">{{{tripcode}}}</span></div>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -1,32 +0,0 @@
|
||||
{{!
|
||||
live.mustache -- live ui
|
||||
template parameters:
|
||||
- prefix ( site prefix )
|
||||
}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title> {{#i18n.Translations}}{{overboard_title}}{{/i18n.Translations}} </title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/livechan.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<style type="text/css" id="convo_filter">
|
||||
</style>
|
||||
<script type="text/javascript" src="{{prefix}}static/nntpchan.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>you need js for livechan mode</noscript>
|
||||
<script type="text/javascript" >
|
||||
var e = document.createElement("div");
|
||||
e.setAttribute("id", "chat");
|
||||
e.setAttribute("style", "position:fixed;left:0;right:0;top:0;bottom:0;width:100%;height:100%;");
|
||||
document.body.appendChild(e);
|
||||
var board = "";
|
||||
if (location.hash != "" ) {
|
||||
board = location.hash.substr(1);
|
||||
}
|
||||
new Chat(e, board, { prefix : "{{prefix}}" });
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,49 +0,0 @@
|
||||
{{!
|
||||
modpage.mustache -- the moderator panel when logged in
|
||||
template parameters:
|
||||
- prefix ( the site's prefix )
|
||||
|
||||
}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<!-- yes it uses js -->
|
||||
<script type="text/javascript" src="{{prefix}}static/nntpchan.js"></script>
|
||||
<script type="text/javascript" src="{{prefix}}static/mod.js"></script>
|
||||
<script type="text/javascript" src="{{prefix}}static/feed.js"></script>
|
||||
<title> {{#i18n.Translations}}{{modpage_title}}{{/i18n.Translations}} </title>
|
||||
</head>
|
||||
<body onload="main()">
|
||||
<div id="nntpchan_mod_result"></div>
|
||||
<div class="nntpchan_feed_pane">
|
||||
<pre> Add Feed </pre>
|
||||
<label for="add_feed_host">Host</label>
|
||||
<input id="add_feed_host" />
|
||||
<label for="add_feed_host">Port</label>
|
||||
<input id="add_feed_port" />
|
||||
<label for="add_feed_name">Name</label>
|
||||
<input id="add_feed_name" />
|
||||
<button onclick="nntp_feed_add()">Add</button>
|
||||
</div>
|
||||
<div class="nntpchan_feed_pane">
|
||||
<pre> Remove Feed </pre>
|
||||
<label for="del_feed_name">Name</label>
|
||||
<input id="del_feed_name" />
|
||||
<button onclick="nntp_feed_del()">Remove</button>
|
||||
</div>
|
||||
<div class="nntpchan_feed_pane">
|
||||
<pre> Sync Feeds </pre>
|
||||
<button onclick="nntpchan_admin('feed.sync')">Sync All</button>
|
||||
</div>
|
||||
<div id="nntpchan_feed_result"></div>
|
||||
<div id="nntpchan_feeds"></div>
|
||||
<script>
|
||||
nntp_feed_update();
|
||||
</script>
|
||||
<noscript>
|
||||
<b>{{#i18n.Translations}}{{nojs_info}}{{/i18n.Translations}}</b>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
||||