Compare commits
152 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a75911ab7 | ||
|
|
8181d174a5 | ||
|
|
c618440878 | ||
|
|
0bc6298cc0 | ||
|
|
93b452c497 | ||
|
|
b2d46c9021 | ||
|
|
f972d91137 | ||
|
|
f8a6b32b5f | ||
|
|
439ab7583a | ||
|
|
5800b1bf1d | ||
|
|
1ba53b7688 | ||
|
|
dd2eb90230 | ||
|
|
2319327917 | ||
|
|
89dfe68b32 | ||
|
|
c4dadd21fc | ||
|
|
812d7cfd9d | ||
|
|
415f0d6e39 | ||
|
|
08d97147b8 | ||
|
|
23614275eb | ||
|
|
1eca5c59e3 | ||
|
|
91953148e8 | ||
|
|
c5a5fb57d9 | ||
|
|
5b8d338840 | ||
|
|
5bc7c92e71 | ||
|
|
f32bd8c946 | ||
|
|
ca333e06ac | ||
|
|
9aab7addb1 | ||
|
|
0b984d0dcd | ||
|
|
73b254367f | ||
|
|
a9c09e57e9 | ||
|
|
d8b57e2189 | ||
|
|
7ce22cefb7 | ||
|
|
2de555f176 | ||
|
|
68c071e318 | ||
|
|
077b61270c | ||
|
|
5975383349 | ||
|
|
46ca31066f | ||
|
|
9db627d07f | ||
|
|
014dbdfa95 | ||
|
|
ea06f5498f | ||
|
|
c2d60063ee | ||
|
|
0ebd2241e5 | ||
|
|
0aca177c86 | ||
|
|
9bb45cd896 | ||
|
|
7458a884d5 | ||
|
|
6392a606c4 | ||
|
|
693bcdeffd | ||
|
|
81a398ab26 | ||
|
|
7296bc6944 | ||
|
|
e97c4bab53 | ||
|
|
2c03b8fd6b | ||
|
|
2f3742fa7c | ||
|
|
ff816fd556 | ||
|
|
585d4cbff1 | ||
|
|
0d388b19ee | ||
|
|
a8e870a099 | ||
|
|
32c4dcbe69 | ||
|
|
a3571f541b | ||
|
|
39dbe314d6 | ||
|
|
63e2614983 | ||
|
|
0623077a40 | ||
|
|
f05d43af89 | ||
|
|
68b73ff1dd | ||
|
|
0613350420 | ||
|
|
37af910c89 | ||
|
|
6286a6529c | ||
|
|
51bdf9609f | ||
|
|
b5d60f1431 | ||
|
|
56f8fc8b91 | ||
|
|
e0de5dfbf5 | ||
|
|
d122da98b5 | ||
|
|
e6a38af5ee | ||
|
|
abf3da5900 | ||
|
|
a40aad33d1 | ||
|
|
9a6f3ef4ed | ||
|
|
372a8767ee | ||
|
|
f7a31012e8 | ||
|
|
5cf11d50d4 | ||
|
|
a4f3e4ffa4 | ||
|
|
60de698f2c | ||
|
|
1c4f4630c2 | ||
|
|
9974628f62 | ||
|
|
2ea928417d | ||
|
|
eede0c55dc | ||
|
|
c6780cfd27 | ||
|
|
34b2e18587 | ||
|
|
38d3bc4481 | ||
|
|
e556d6d2be | ||
|
|
22a3564f22 | ||
|
|
b695d97e82 | ||
|
|
64e4c3320d | ||
|
|
7c7d07434d | ||
|
|
d2b9e76389 | ||
|
|
f91bd642a5 | ||
|
|
9459e1758d | ||
|
|
24b2bd8e15 | ||
|
|
8ad13c8e45 | ||
|
|
c6e6c2e5d6 | ||
|
|
9690156fbf | ||
|
|
dea611c1ba | ||
|
|
0e0f35e6dc | ||
|
|
5370898da9 | ||
|
|
1020fae1dd | ||
|
|
6bcfff0269 | ||
|
|
5fbf75a77d | ||
|
|
86744c9349 | ||
|
|
24b6d87381 | ||
|
|
649cc96269 | ||
|
|
a9e377563d | ||
|
|
9229aa62bd | ||
|
|
f9c9028a0b | ||
|
|
5fa12dcda8 | ||
|
|
8c0a4ac6b0 | ||
|
|
bd279547d2 | ||
|
|
1ad6432576 | ||
|
|
4b007fa759 | ||
|
|
abe985b6c5 | ||
|
|
6091934884 | ||
|
|
7db701b23a | ||
|
|
00816c1a95 | ||
|
|
713f8a7d19 | ||
|
|
da42b8fc7d | ||
|
|
27bf7de803 | ||
|
|
4fd443dce4 | ||
|
|
f8d3f85a4d | ||
|
|
007851056f | ||
|
|
f97b5a56e5 | ||
|
|
7495c3e843 | ||
|
|
713ff950e7 | ||
|
|
64a7a6e6aa | ||
|
|
6aa9475c91 | ||
|
|
a9ac1207c0 | ||
|
|
539033ec6d | ||
|
|
80041baf1e | ||
|
|
b83b21df59 | ||
|
|
69c30e0685 | ||
|
|
0ed2bad9f1 | ||
|
|
41d3cb467b | ||
|
|
476ae002c2 | ||
|
|
6f0b518391 | ||
|
|
f673a10768 | ||
|
|
8668d1aa08 | ||
|
|
d2babe367b | ||
|
|
3b5937f2d9 | ||
|
|
1896060218 | ||
|
|
9d2461c716 | ||
|
|
85d60a1928 | ||
|
|
6eb42d4cf7 | ||
|
|
37df9ef131 | ||
|
|
450d07d6e5 | ||
|
|
047a63ec20 | ||
|
|
3821562cf6 |
8
.gitignore
vendored
@@ -8,7 +8,8 @@
|
||||
.\#*
|
||||
|
||||
# srnd config files
|
||||
*.ini
|
||||
srnd.ini
|
||||
feeds.ini
|
||||
|
||||
# default article store directory
|
||||
articles
|
||||
@@ -24,4 +25,7 @@ srndv2
|
||||
*.key
|
||||
|
||||
# certificates
|
||||
certs
|
||||
certs
|
||||
|
||||
|
||||
rebuild.sh
|
||||
|
||||
19
README.md
@@ -6,25 +6,18 @@ This repository contains resources used by the core daemon which is located [her
|
||||
|
||||
## getting started ##
|
||||
|
||||
Get the dependancies
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get --no-install-recommends install imagemagick libsodium-dev ffmpeg sox build-essential git golang ca-certificates
|
||||
|
||||
Check out this repo and build it
|
||||
|
||||
git clone https://github.com/majestrate/nntpchan
|
||||
cd nntpchan
|
||||
./build.sh
|
||||
|
||||
Now configure the database. [Next](doc/database.md)
|
||||
|
||||
[see build documentation](doc/build.md)
|
||||
|
||||
---
|
||||
|
||||
*PLEASE* report any bugs you find while setting up or building [(here)](https://github.com/majestrate/nntpchan/issues) so that the problems get fixed :^)
|
||||
|
||||
For peering requests, questions or support find me on [rizon](https://qchat.rizon.net/?channels=#nntpchan) as \__uguu\__
|
||||
IRC:
|
||||
|
||||
[freenode: #nntpchan](https://webchat.freenode.net/?channels=#nntpchan)
|
||||
|
||||
[rizon: #nntpchan](https://qchat.rizon.net/?channels=#nntpchan)
|
||||
|
||||
|
||||
Like this project? Fund it:
|
||||
|
||||
27
build.sh
@@ -1,8 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
root=$(readlink -e $(dirname $0))
|
||||
|
||||
tags=""
|
||||
|
||||
help_text="usage: $0 [--disable-redis]"
|
||||
|
||||
# check for help flags first
|
||||
for arg in $@ ; do
|
||||
case $arg in
|
||||
-h|--help)
|
||||
echo $help_text
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# check for build flags
|
||||
for arg in $@ ; do
|
||||
case $arg in
|
||||
"--disable-redis")
|
||||
tags="$tags -tags disable_redis"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
cd $root
|
||||
export GOPATH=$root/go
|
||||
mkdir -p $GOPATH
|
||||
go get -u github.com/majestrate/srndv2
|
||||
go get -v -u $tags github.com/majestrate/srndv2
|
||||
cp -a $GOPATH/bin/srndv2 $root
|
||||
echo "Built"
|
||||
|
||||
BIN
contrib/static/404.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 550 B After Width: | Height: | Size: 135 B |
84
contrib/static/bloodgod.css
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
bloodgod theme css override
|
||||
*/
|
||||
|
||||
body {
|
||||
color: #666;
|
||||
background: #111;
|
||||
}
|
||||
|
||||
|
||||
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, pre {
|
||||
background: #D80000;
|
||||
}
|
||||
|
||||
.reply, .ukko_thread_header {
|
||||
border-color: #CA0101;
|
||||
}
|
||||
|
||||
.ukko_thread_header {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
|
||||
hr, .name {
|
||||
color: #6B1919;
|
||||
}
|
||||
|
||||
.subject {
|
||||
color: #4E0000;
|
||||
}
|
||||
|
||||
.reply , .ukko_thread_header {
|
||||
background: #0C0C0C;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #500707;
|
||||
}
|
||||
|
||||
.postno, .postnol {
|
||||
color: #B70000;
|
||||
}
|
||||
|
||||
.postform >tr, th {
|
||||
background: #6B1919;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
21
contrib/static/dayman.css
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
.navbar, table, thead, th, table, pre {
|
||||
background: #FFECBE;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
contrib/static/maymface.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
@@ -87,19 +87,25 @@ function nntpchan_admin_board(method) {
|
||||
})
|
||||
}
|
||||
|
||||
function nntpchan_admin(method, param) {
|
||||
nntpchan_mod({
|
||||
name:"admin",
|
||||
parser: function(target) {
|
||||
return method;
|
||||
},
|
||||
handle: function(j) {
|
||||
function nntpchan_admin(method, param, handler_cb) {
|
||||
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?";
|
||||
}
|
||||
}
|
||||
}
|
||||
nntpchan_mod({
|
||||
name:"admin",
|
||||
parser: function(target) {
|
||||
return method;
|
||||
},
|
||||
handle: handler_cb,
|
||||
method: ( param && "POST" ) || "GET",
|
||||
data: param
|
||||
})
|
||||
@@ -136,6 +142,81 @@ function nntpchan_delete() {
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function nntpchan_mod(mod_action) {
|
||||
|
||||
@@ -171,13 +252,7 @@ function nntpchan_mod(mod_action) {
|
||||
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 if (status) {
|
||||
|
||||
@@ -24,3 +24,33 @@ function nntpchan_inject_banners(elem, prefix) {
|
||||
e.id = "nntpchan_banner";
|
||||
elem.appendChild(e);
|
||||
}
|
||||
|
||||
function get_storage() {
|
||||
var st = null;
|
||||
if (window.localStorage) {
|
||||
st = window.localStorage;
|
||||
} else if (localStorage) {
|
||||
st = localStorage;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
// do other initialization here
|
||||
}
|
||||
|
||||
// apply themes
|
||||
var st = get_storage();
|
||||
enable_theme(st.nntpchan_prefix, st.nntpchan_theme);
|
||||
|
||||
BIN
contrib/static/placeholder.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
@@ -1,6 +1,25 @@
|
||||
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;
|
||||
}
|
||||
|
||||
.frontend , .subject {
|
||||
color: #928BFF;
|
||||
|
||||
main,
|
||||
aside,
|
||||
section {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.frontend , .subject, .catalog_subject {
|
||||
color: #0F0C5D;
|
||||
}
|
||||
|
||||
.name {
|
||||
@@ -15,13 +34,6 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
input.button {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 350px;
|
||||
@@ -37,33 +49,84 @@ textarea {
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
background: #3f3f3f;
|
||||
color: #d17600;
|
||||
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;
|
||||
}
|
||||
|
||||
td {
|
||||
background-color: #1C1C1C;
|
||||
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;
|
||||
}
|
||||
|
||||
.board_td {
|
||||
position: relative; left: 2px;
|
||||
.postform >tr, th {
|
||||
background: #98E;
|
||||
font-size: 10pt;
|
||||
text-align: left;
|
||||
padding-right: 10px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.posts_td {
|
||||
position: relative; left: -2px;
|
||||
|
||||
#postform-inner tr {
|
||||
background-color: transparent!important;
|
||||
}
|
||||
|
||||
#overview_graph {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
background: #1C1C1C;
|
||||
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 {
|
||||
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: #202331;
|
||||
background: #D6DAF0;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
legend {
|
||||
@@ -75,18 +138,79 @@ hr {
|
||||
border-width: 1px medium medium;
|
||||
border-color: #b7c5d9;
|
||||
border-style: solid none none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
a:hover , a:visited:hover {
|
||||
color: #f13333;
|
||||
.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 {
|
||||
color: cornflowerblue;
|
||||
.board_header_catalog {
|
||||
text-align: center;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #0C2FF3;
|
||||
.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: #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;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
@@ -96,54 +220,52 @@ a:visited {
|
||||
right: 0px;
|
||||
margin-top: 0px;
|
||||
z-index: 20;
|
||||
box-shadow: 0px 1px 20px rgba(0, 0, 0, 0.15);
|
||||
background: #202331;
|
||||
color: lightgray;
|
||||
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.15);
|
||||
border-bottom: 1px solid;
|
||||
background: #D6DAF0;
|
||||
color: #34345C;
|
||||
}
|
||||
|
||||
.navbar-sep {
|
||||
color: darkgray;
|
||||
}
|
||||
|
||||
.navbar-link > label {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#postform_container {
|
||||
margin-top: 5em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.navLinks {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
.ukko_thread_header {
|
||||
padding: 5px 5px;
|
||||
margin: 5px 5px;
|
||||
float: left;
|
||||
clear: both;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #4DA6BD;
|
||||
font-size: 10pt;
|
||||
padding-left: 10px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
color: whitesmoke;
|
||||
background: #2d2d2d;
|
||||
border-color: #4D28CA;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
html {
|
||||
color: #ededed;
|
||||
background: black;
|
||||
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 {
|
||||
@@ -152,14 +274,19 @@ html {
|
||||
}
|
||||
|
||||
.op {
|
||||
margin-right: 20px;
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 1px;
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.post {
|
||||
display: inline;
|
||||
margin-bottom: 5px;
|
||||
min-width: 500px;
|
||||
}
|
||||
|
||||
.postheader {
|
||||
padding-top: 3px;
|
||||
padding-right: 5px
|
||||
}
|
||||
|
||||
.tripcode {
|
||||
@@ -189,12 +316,15 @@ html {
|
||||
|
||||
|
||||
.memearrows {
|
||||
color: #29D029;
|
||||
color: #789922;
|
||||
margin-left: none;
|
||||
}
|
||||
|
||||
.redtext {
|
||||
color: #d50505;
|
||||
color: #AF0A0F;
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
margin-left: none;
|
||||
}
|
||||
|
||||
.spoiler {
|
||||
@@ -227,26 +357,55 @@ html {
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.reply, .ukko_thread_header , pre {
|
||||
padding: 7px 7px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 1px 1px 3px black;
|
||||
}
|
||||
|
||||
.post_body > p {
|
||||
margin: 0px 0px;
|
||||
.reply {
|
||||
padding: 3px 5px 3px 5px;
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.post_body {
|
||||
display: inline;
|
||||
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;
|
||||
width: 80%;
|
||||
overflow: hidden;
|
||||
|
||||
}
|
||||
|
||||
#postform_attachment {
|
||||
.pagelist {
|
||||
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, .backlink:hover, .backlink:visited, .backlink:visited:hover {
|
||||
margin-left: none;
|
||||
color: #D00
|
||||
}
|
||||
|
||||
|
||||
.origin > img{
|
||||
height: 20px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
.postform_attachment {
|
||||
max-width: 330px;
|
||||
}
|
||||
|
||||
@@ -257,35 +416,18 @@ html {
|
||||
}
|
||||
|
||||
#captcha_img {
|
||||
background: #4DA6BD;
|
||||
background: white;
|
||||
}
|
||||
|
||||
figure {
|
||||
float: left;
|
||||
margin: 1ex;
|
||||
}
|
||||
figure img {
|
||||
max-width:256px;
|
||||
max-height:128px;
|
||||
max-width:100%;
|
||||
}
|
||||
fieldset {
|
||||
overflow: auto;
|
||||
border-radius: 5px 0px 5px 0px;
|
||||
img.thumbnail {
|
||||
max-width: 350px;
|
||||
max-height: 350px;
|
||||
}
|
||||
|
||||
fieldset > img {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.thread {
|
||||
float: left;
|
||||
width: 90%;
|
||||
padding-left: 10px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
background-color: #252525;
|
||||
}
|
||||
|
||||
.replybar {
|
||||
float: left;
|
||||
@@ -293,9 +435,9 @@ fieldset > img {
|
||||
top: 2ex;
|
||||
right: 0;
|
||||
width: 34%
|
||||
}
|
||||
}
|
||||
@media (max-width: 100ex) {
|
||||
.replybar, .thread {
|
||||
.replybar {
|
||||
width: 100%;
|
||||
position: static;
|
||||
}
|
||||
@@ -318,11 +460,15 @@ textarea#reply-text {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
#nntpchan_banner {
|
||||
align: center;
|
||||
}
|
||||
|
||||
.legal {
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.attachments {
|
||||
float: left;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.6 KiB |
25
contrib/templates/default/404.mustache
Normal file
@@ -0,0 +1,25 @@
|
||||
{{!
|
||||
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>
|
||||
@@ -16,11 +16,11 @@
|
||||
<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>{{board.Board}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<body onload="main()">
|
||||
<!-- begin navbar -->
|
||||
{{{board.Navbar}}}
|
||||
<!-- end navbar -->
|
||||
@@ -28,6 +28,8 @@
|
||||
<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}}}
|
||||
@@ -36,21 +38,32 @@
|
||||
<div id="threads_container">
|
||||
{{#board.Threads}}
|
||||
<div class="thread" id="thread_{{OP.PostHash}}">
|
||||
<div clsss="thread_header">
|
||||
<div class="thread_header">
|
||||
</div>
|
||||
{{{OP.Truncate.RenderPost}}}
|
||||
{{#Truncate.Replies}}
|
||||
{{{Truncate.RenderPost}}}
|
||||
<br />
|
||||
{{/Truncate.Replies}}
|
||||
<hr />
|
||||
</div>
|
||||
{{/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 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>
|
||||
|
||||
@@ -10,20 +10,22 @@
|
||||
<head>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css"></link>
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css"></link>
|
||||
<title> {{frontend}} board list </title>
|
||||
<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">
|
||||
<tbody>
|
||||
<thead>
|
||||
<tr>
|
||||
<th> Board </th>
|
||||
<th> Post per Hour </th>
|
||||
<th> Post per Day </th>
|
||||
<th> Total </th>
|
||||
<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>
|
||||
@@ -46,4 +48,4 @@
|
||||
</div>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
45
contrib/templates/default/catalog.mustache
Normal file
@@ -0,0 +1,45 @@
|
||||
<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}}{{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,9 @@
|
||||
{{!
|
||||
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 )
|
||||
- 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 )
|
||||
- totalposts ( the number of total posts we have ever seen )
|
||||
- frontend ( the name of the frontend )
|
||||
- prefix ( the site's prefix )
|
||||
@@ -12,11 +12,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<script src="{{prefix}}static/nntpchan.js" type="text/javascript"></script>
|
||||
<title> {{frontend}} on nntpchan </title>
|
||||
</head>
|
||||
<body>
|
||||
<body onload="main()">
|
||||
{{{navbar}}}
|
||||
<center>
|
||||
<div class="index-outer">
|
||||
<div class="index-inner">
|
||||
@@ -36,18 +37,20 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="posts_td">
|
||||
{{{postsgraph.Render}}}
|
||||
{{{postsgraph}}}
|
||||
</td>
|
||||
<td class="board_td">
|
||||
{{! todo: move boardgraph into its own file like postsgraph }}
|
||||
<table id="board_graph">
|
||||
<tbody>
|
||||
<thead>
|
||||
<tr>
|
||||
<th> Board </th>
|
||||
<th> Posts this Hour </th>
|
||||
<th> Posts Today </th>
|
||||
<th> Total </th>
|
||||
<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>
|
||||
@@ -70,7 +73,7 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{{{overview.Render}}}
|
||||
{{{overview}}}
|
||||
</div>
|
||||
</div>
|
||||
</center>
|
||||
@@ -78,6 +81,10 @@
|
||||
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>
|
||||
|
||||
@@ -9,15 +9,15 @@ template parameters:
|
||||
<meta charset="utf-8"></meta>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<title> Post History</title>
|
||||
<title>{{#i18n.Translations}}{{post_history_title}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<td>
|
||||
<table id="history_graph">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Month</th>
|
||||
<th>Posts</th>
|
||||
<th>{{#i18n.Translations}}{{month}}{{/i18n.Translations}}</th>
|
||||
<th>{{#i18n.Translations}}{{posts}}{{/i18n.Translations}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
<head>
|
||||
<meta charset="utf-8"></meta>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<title> here is a new tripcode </title>
|
||||
<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>
|
||||
</head>
|
||||
<body>
|
||||
<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>{{#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>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<title>login</title>
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<title>{{#i18n.Translations}}{{login}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<form action="login" method="POST" name="modlogin">
|
||||
<label for="mod_key">secret</label>
|
||||
<label for="mod_key">{{#i18n.Translations}}{{secret_key}}{{/i18n.Translations}}</label>
|
||||
<input type="password" id="mod_key" name="privkey" />
|
||||
<input type="submit" value="login" />
|
||||
<input type="submit" value="{{#i18n.Translations}}{{login}}{{/i18n.Translations}}" />
|
||||
{{{csrfField}}}
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<meta http-equiv="refresh" content="1; {{mod_prefix}}"></meta>
|
||||
<title>login</title>
|
||||
<title>{{#i18n.Translations}}{{login}}{{/i18n.Translations}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>{{message}}</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -7,96 +7,109 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.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>
|
||||
<title> nntpchan mod page </title>
|
||||
<title> {{#i18n.Translations}}{{modpage_title}}{{/i18n.Translations}} </title>
|
||||
</head>
|
||||
<body>
|
||||
<body onload="main()">
|
||||
<div>
|
||||
<div> post actions </div>
|
||||
<div> {{#i18n.Translations}}{{post_actions_label}}{{/i18n.Translations}} </div>
|
||||
<hr />
|
||||
<div>
|
||||
<label for="nntpchan_mod_target">target</label>
|
||||
<label for="nntpchan_mod_target">{{#i18n.Translations}}{{target_label}}{{/i18n.Translations}}</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>
|
||||
<button onclick="nntpchan_ban()">{{#i18n.Translations}}{{ban_url_prompt}}{{/i18n.Translations}}</button>
|
||||
<button onclick="nntpchan_delete()">{{#i18n.Translations}}{{delete_url_prompt}}{{/i18n.Translations}}</button>
|
||||
<button onclick="nntpchan_unban()">{{#i18n.Translations}}{{unban_ip_prompt}}{{/i18n.Translations}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<div> key actions </div>
|
||||
<div> {{#i18n.Translations}}{{key_actions_label}}{{/i18n.Translations}} </div>
|
||||
<div>
|
||||
<label for="nntpchan_board_target">pubkey:</label>
|
||||
<label for="nntpchan_board_target">{{#i18n.Translations}}{{pubkey_label}}{{/i18n.Translations}}:</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>
|
||||
<button onclick="nntpchan_key_add()">{{#i18n.Translations}}{{add_key_prompt}}{{/i18n.Translations}}</button>
|
||||
<button onclick="nntpchan_key_del()">{{#i18n.Translations}}{{remove_key_prompt}}{{/i18n.Translations}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<div> nntp login </div>
|
||||
<div> {{#i18n.Translations}}{{nntp_login_label}}{{/i18n.Translations}} </div>
|
||||
<div>
|
||||
<label for="nntpchan_nntp_username">username:</label>
|
||||
<label for="nntpchan_nntp_username">{{#i18n.Translations}}{{username}}{{/i18n.Translations}}:</label>
|
||||
<input id="nntpchan_nntp_username" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="nntpchan_nntp_passwd">password:</label>
|
||||
<label for="nntpchan_nntp_passwd">{{#i18n.Translations}}{{password}}{{/i18n.Translations}}:</label>
|
||||
<input type="password" id="nntpchan_nntp_passwd" />
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="nntpchan_admin_nntp('nntp.login.add')">add user</button>
|
||||
<button onclick="nntpchan_admin_nntp('nntp.login.add')">{{#i18n.Translations}}{{add_user_prompt}}{{/i18n.Translations}}</button>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="nntpchan_admin_nntp('nntp.login.del')">remove user</button>
|
||||
<button onclick="nntpchan_admin_nntp('nntp.login.del')">{{#i18n.Translations}}{{remove_user_prompt}}{{/i18n.Translations}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<div> board actions </div>
|
||||
<div> {{#i18n.Translations}}{{board_actions_label}}{{/i18n.Translations}} </div>
|
||||
<div>
|
||||
<label for="nntpchan_board_target">board name:</label>
|
||||
<label for="nntpchan_board_target">{{#i18n.Translations}}{{board_name_title}}{{/i18n.Translations}}:</label>
|
||||
<input id="nntpchan_board_target" />
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="nntpchan_admin_board('frontend.add')">add board</button>
|
||||
<button onclick="nntpchan_admin_board('frontend.add')">{{#i18n.Translations}}{{add_board_prompt}}{{/i18n.Translations}}</button>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="nntpchan_admin_board('frontend.regen')">regenerate</button>
|
||||
<button onclick="nntpchan_admin_board('frontend.regen')">{{#i18n.Translations}}{{regenerate_prompt}}{{/i18n.Translations}}</button>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="nntpchan_admin_board('frontend.ban')">ban</button>
|
||||
<button onclick="nntpchan_admin_board('frontend.unban')">unban</button>
|
||||
<button onclick="nntpchan_admin_board('frontend.ban')">{{#i18n.Translations}}{{ban_prompt}}{{/i18n.Translations}}</button>
|
||||
<button onclick="nntpchan_admin_board('frontend.unban')">{{#i18n.Translations}}{{unban_prompt}}{{/i18n.Translations}}</button>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="nntpchan_admin_board('frontend.nuke')">nuke</button>
|
||||
<button onclick="nntpchan_admin_board('frontend.nuke')">{{#i18n.Translations}}{{nuke_prompt}}{{/i18n.Translations}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<div>
|
||||
lightweight actions
|
||||
{{#i18n.Translations}}{{light_actions_label}}{{/i18n.Translations}}
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="nntpchan_admin('template.reload')">reload all templates</button>
|
||||
<button onclick="nntpchan_admin('template.reload')">{{#i18n.Translations}}{{reload_templates_prompt}}{{/i18n.Translations}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<label>very load heavy actions, use with care</label>
|
||||
<label>{{#i18n.Translations}}{{heavy_actions_label}}{{/i18n.Translations}}</label>
|
||||
<div>
|
||||
<button onclick="nntpchan_admin('frontend.regen')">regenerate all pages</button>
|
||||
<button onclick="nntpchan_admin('thumbnail.regen')">regenerate all thumbnails</button>
|
||||
<button onclick="nntpchan_admin('frontend.regen')">{{#i18n.Translations}}{{regenerate_markup_prompt}}{{/i18n.Translations}}</button>
|
||||
<button onclick="nntpchan_admin('thumbnail.regen')">{{#i18n.Translations}}{{regenerate_thumbs_prompt}}{{/i18n.Translations}}</button>
|
||||
<button onclick="nntpchan_admin('feed.sync')">{{#i18n.Translations}}{{feed_sync_prompt}}{{/i18n.Translations}}</button>
|
||||
<button onclick="nntpchan_admin('store.expire')">{{#i18n.Translations}}{{expire_old_prompt}}{{/i18n.Translations}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="nntpchan_mod_result"></div>
|
||||
<div id="nntpchan_feeds"></div>
|
||||
<script>
|
||||
// start nntp feed stats ticker
|
||||
var e = document.getElementById("nntpchan_feeds");
|
||||
if (e) {
|
||||
setInterval(function() {
|
||||
update_nntpchan_feed_ticker(e);
|
||||
}, 2000);
|
||||
}
|
||||
</script>
|
||||
<noscript>
|
||||
<b>enable js to use the mod panel kthx</b>
|
||||
<b>{{#i18n.Translations}}{{nojs_info}}{{/i18n.Translations}}</b>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="navbar">
|
||||
<span class="navbar-name">
|
||||
<span class="board_title">{{name}}</span>
|
||||
on
|
||||
{{#i18n.Translations}}{{navbar_on}}{{/i18n.Translations}}
|
||||
<span class="frontend_title">{{frontend}}</span>
|
||||
</span>
|
||||
<span class="navbar-sep">
|
||||
@@ -31,16 +31,24 @@
|
||||
|
|
||||
</span>
|
||||
<span class="navbar-links">
|
||||
<span class="navbar-link"><a href="{{prefix}}">front page</a></span>
|
||||
<span class="navbar-link"><a href="{{prefix}}">{{#i18n.Translations}}{{front_page_title}}{{/i18n.Translations}}</a></span>
|
||||
</span>
|
||||
<span class="navbar-sep">
|
||||
|
|
||||
</span>
|
||||
<span class="navbar-links">
|
||||
<span class="navbar-link"><a href="{{prefix}}ukko.html">overboard</a></span>
|
||||
<span class="navbar-link"><a href="{{prefix}}ukko.html">{{#i18n.Translations}}{{overboard_title}}{{/i18n.Translations}}</a></span>
|
||||
</span>
|
||||
<span class="navbar-sep">
|
||||
|
|
||||
</span>
|
||||
<span class="navbar-links">
|
||||
<span class="navbar-link"><label onclick="enable_theme('{{prefix}}','bloodgod')">bloodgod</a></span>
|
||||
<span class="navbar-link"><label onclick="enable_theme('{{prefix}}','dayman')">dayman</a></span>
|
||||
<span class="navbar-link"><label onclick="enable_theme('{{prefix}}','site')">yotsuba</a></span>
|
||||
</span>
|
||||
<span class="navbar-sep">
|
||||
|
|
||||
</span>
|
||||
</div>
|
||||
<hr />
|
||||
<hr />
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>create new board</title>
|
||||
<title>{{#i18n.Translations}}{{new_board_title}}{{/i18n.Translations}}</title>
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{prefix}}static/newboard.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p>make your first post</p>
|
||||
<p>{{#i18n.Translations}}{{first_post_label}}{{/i18n.Translations}}</p>
|
||||
<hr />
|
||||
<form action="{{prefix}}post/" enctype="multipart/form-data" name="post" method="post" id="postform" >
|
||||
<div id="postform-outer">
|
||||
@@ -16,7 +16,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
Board Name
|
||||
{{#i18n.Translations}}{{board_name_title}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="name" value="" id="boardname" />
|
||||
@@ -25,7 +25,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Comment
|
||||
{{#i18n.Translations}}{{comment}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<textarea id="postform_message" name="message" cols=40 rows=5></textarea>
|
||||
@@ -33,7 +33,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Captcha
|
||||
{{#i18n.Translations}}{{captcha}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<img id="captcha_img" src="{{prefix}}captcha/img" alt="captcha" />
|
||||
@@ -41,7 +41,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Solution
|
||||
{{#i18n.Translations}}{{solution}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="captcha" />
|
||||
|
||||
@@ -8,9 +8,9 @@ paramters:
|
||||
<table id="overview_graph">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Newsgroup</th>
|
||||
<th>Posted</th>
|
||||
<th>Subject</th>
|
||||
<th>{{#i18n.Translations}}{{newsgroup}}{{/i18n.Translations}}</th>
|
||||
<th>{{#i18n.Translations}}{{posted}}{{/i18n.Translations}}</th>
|
||||
<th>{{#i18n.Translations}}{{subject}}{{/i18n.Translations}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -1,26 +1,33 @@
|
||||
<fieldset>
|
||||
{{#IsI2P}}
|
||||
<img src="{{Prefix}}static/i2p.png" title="post from i2p" />
|
||||
{{/IsI2P}}
|
||||
{{#IsTor}}
|
||||
<img src="{{Prefix}}static/tor.png" title="post from tor" />
|
||||
{{/IsTor}}
|
||||
{{#IsClearnet}}
|
||||
<img src="{{Prefix}}static/clearnet.png" title="post from clearnet" />
|
||||
{{/IsClearnet}}
|
||||
<legend>
|
||||
<span class="subject">{{Subject}}</span> <span class="name">{{Name}}</span> {{Date}}
|
||||
No. <a onclick="nntpchan_backlink('{{ShortHash}}');" title="{{MessageID}}">{{ShortHash}}</a>
|
||||
<a href="{{PostURL}}">[reply]</a> <span class="tripcode">{{{Pubkey}}}</span><br />
|
||||
<div id="{{post.PostHash}}" class="{{post.CSSClass}}">
|
||||
<legend class="postheader">
|
||||
<span class="origin">
|
||||
{{#post.IsI2P}}
|
||||
<img src="{{post.Prefix}}static/i2p.png" title="{{#i18n.Translations}}{{from_i2p}}{{/i18n.Translations}}" />
|
||||
{{/post.IsI2P}}
|
||||
{{#post.IsTor}}
|
||||
<img src="{{post.Prefix}}static/tor.png" title="{{#i18n.Translations}}{{from_tor}}{{/i18n.Translations}}" />
|
||||
{{/post.IsTor}}
|
||||
{{#post.IsClearnet}}
|
||||
<img src="{{post.Prefix}}static/clearnet.png" title="{{#i18n.Translations}}{{from_clearnet}}{{/i18n.Translations}}" />
|
||||
{{/post.IsClearnet}}
|
||||
</span>
|
||||
<span class="subject">{{post.Subject}}</span>
|
||||
<span class="name">{{post.Name}}</span>
|
||||
<time datetime="{{post.DateRFC}}">{{post.Date}}</time>
|
||||
<a href="#" class="postnol">No.</a><a class="postno" onclick="nntpchan_backlink('{{post.ShortHash}}');" title="{{post.MessageID}}">{{post.ShortHash}}</a>
|
||||
<a href="{{post.PostURL}}">[{{#i18n.Translations}}{{reply_label}}{{/i18n.Translations}}]</a>
|
||||
<span class="tripcode">{{{post.Pubkey}}}</span>
|
||||
</legend>
|
||||
{{#Attachments}}
|
||||
<div class="attachments">
|
||||
{{#post.Attachments}}
|
||||
<figure>
|
||||
<figcaption>
|
||||
<a href="{{Source}}" title="{{Filename}}" target="_blank"><img src="{{Thumbnail}}" alt="{{Filename}}" /></a>
|
||||
<a href="{{Source}}" title="{{Filename}}" target="_blank"><img src="{{Thumbnail}}" alt="{{Filename}}" class="thumbnail"/></a>
|
||||
</figcaption>
|
||||
</figure>
|
||||
{{/Attachments}}
|
||||
<label class="post_body">
|
||||
{{{RenderBody}}}
|
||||
</label>
|
||||
</fieldset>
|
||||
{{/post.Attachments}}
|
||||
</div>
|
||||
<div class="post_body">
|
||||
{{{post.RenderBody}}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<html>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{prefix}}static/nntpchan.js"></script>
|
||||
<meta http-equiv="refresh" content="1; {{redirect_url}}" />
|
||||
<body>
|
||||
<p>post failed: {{reason}}</p>
|
||||
<pre>{{#i18n.Translations}}{{post_failed_label}}{{/i18n.Translations}}: {{reason}}</pre>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
Captcha
|
||||
{{#i18n.Translations}}{{captcha}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<img id="captcha_img" src="{{prefix}}captcha/{{captcha_id}}.png" alt="captcha" />
|
||||
@@ -32,7 +32,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Solution
|
||||
{{#i18n.Translations}}{{solution}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="captcha" />
|
||||
@@ -45,4 +45,4 @@
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
<html>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{prefix}}static/nntpchan.js"></script>
|
||||
<meta http-equiv="refresh" content="2; {{redirect_url}}" />
|
||||
<body>
|
||||
<pre>posted as {{message_id}}</pre>
|
||||
<pre>{{#i18n.Translations}}{{posted_as_label}}{{/i18n.Translations}} {{message_id}}</pre>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
- reference ( the post we are replying to, or empty string if it's an op )
|
||||
- button ( the text for the reply button )
|
||||
- files ( bool, do we allow attachments ? )
|
||||
- csrf ( csrf token )
|
||||
}}
|
||||
<form action="{{post_url}}" enctype="multipart/form-data" name="post" method="post">
|
||||
{{{csrf}}}
|
||||
<input type="hidden" name="reference" value="{{reference}}" />
|
||||
<div id="postform-outer">
|
||||
<div id="postform-inner">
|
||||
@@ -15,7 +17,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
Name
|
||||
{{#i18n.Translations}}{{name}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="name" value="" />
|
||||
@@ -23,7 +25,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Subject
|
||||
{{#i18n.Translations}}{{subject}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="subject" value="" />
|
||||
@@ -32,25 +34,25 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Comment
|
||||
{{#i18n.Translations}}{{comment}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<textarea id="postform_message" name="message" cols=40 rows=5></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
{{#files}}
|
||||
<tr>
|
||||
<tr>
|
||||
<th>
|
||||
File
|
||||
{{#i18n.Translations}}{{file}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input id="postform_attachment" type="file" name="attachment" />
|
||||
<input class="postform_attachment" id="postform_attachments" type="file" name="attachment_uploaded" multiple />
|
||||
</td>
|
||||
</tr>
|
||||
{{/files}}
|
||||
<tr>
|
||||
<th>
|
||||
Get Dubs
|
||||
{{#i18n.Translations}}{{dubs}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="dubs" />
|
||||
@@ -58,7 +60,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Captcha
|
||||
{{#i18n.Translations}}{{captcha}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<img id="captcha_img" src="{{prefix}}captcha/img" alt="captcha" />
|
||||
@@ -66,10 +68,10 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Solution
|
||||
{{#i18n.Translations}}{{solution}}{{/i18n.Translations}}
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" name="captcha" />
|
||||
<input type="text" name="captcha" autocomplete="off" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -8,8 +8,8 @@ parameters:
|
||||
<table id="posts_graph">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Day</th>
|
||||
<th>Posts</th>
|
||||
<th>{{#i18n.Translations}}{{day}}{{/i18n.Translations}}</th>
|
||||
<th>{{#i18n.Translations}}{{posts}}{{/i18n.Translations}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
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
|
||||
@@ -16,12 +15,11 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1" />
|
||||
<link rel="stylesheet" href="{{thread.Prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{thread.Prefix}}static/user.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{thread.Prefix}}static/user.css" />
|
||||
<script src="{{thread.Prefix}}static/nntpchan.js" type="text/javascript"></script>
|
||||
<title> {{thread.OP.Subject}} </title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body onload="main()">
|
||||
<!-- begin navbar -->
|
||||
{{{thread.Navbar}}}
|
||||
<!-- end navbar -->
|
||||
@@ -29,6 +27,7 @@
|
||||
<div id="nntpchan_banner">
|
||||
</div>
|
||||
</center>
|
||||
<div class="board_header">{{thread.Board}}</div>
|
||||
<!-- postform -->
|
||||
<div id="postform_container">
|
||||
{{{form}}}
|
||||
@@ -43,12 +42,17 @@
|
||||
<br/>
|
||||
{{/ thread.Replies}}
|
||||
</div>
|
||||
<br/>
|
||||
<hr/>
|
||||
<div class="navLinks">[<a href="{{thread.BoardURL}}" accesskey="a">{{#i18n.Translations}}{{return}}{{/i18n.Translations}}</a>] [<a href="{{thread.Prefix}}catalog-{{thread.Board}}.html" accesskey="r">{{#i18n.Translations}}{{catalog_label}}{{/i18n.Translations}}</a>] [<a href="#thread_{{thread.OP.PostHash}}">{{#i18n.Translations}}{{to_top_label}}{{/i18n.Translations}}</a>] [<a href="#navlinks" accesskey="r" onclick="location.reload();">{{#i18n.Translations}}{{update}}{{/i18n.Translations}}</a>]</div>
|
||||
<script type="text/javascript">
|
||||
var e = document.getElementById("nntpchan_banner");
|
||||
nntpchan_inject_banners(e, "{{thread.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>
|
||||
|
||||
@@ -6,32 +6,32 @@
|
||||
}}
|
||||
<html>
|
||||
<head>
|
||||
<title> ukko / overboard </title>
|
||||
<title> {{#i18n.Translations}}{{overboard_title}}{{/i18n.Translations}} </title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/site.css" />
|
||||
<link rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<link id="current_theme" rel="stylesheet" href="{{prefix}}static/user.css" />
|
||||
<script type="text/javascript" src="{{prefix}}static/nntpchan.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<body onload="main()">
|
||||
<center>
|
||||
<div id="nntpchan_banner">
|
||||
</div>
|
||||
</center>
|
||||
<!-- begin navbar -->
|
||||
{{{navbar}}}
|
||||
<!-- end navbar -->
|
||||
<div class="board_header"> {{#i18n.Translations}}{{overboard_title}}{{/i18n.Translations}} </div>
|
||||
<div id="ukko_threads">
|
||||
{{#threads}}
|
||||
<!--
|
||||
<div class="ukko_thread_header">
|
||||
<p> Posted on <a href="{{{BoardURL}}}"><span class="ukko_boardname">{{OP.Board}}</span></a></p>
|
||||
</div>
|
||||
-->
|
||||
<div class="thread" id="thread_{{OP.PostHash}}">
|
||||
<div clsss="thread_header">
|
||||
</div>
|
||||
<div class="ukko_thread_header">
|
||||
<p>{{#i18n.Translations}}{{posted_on_label}}{{/i18n.Translations}} <a href="{{{BoardURL}}}"><span class="ukko_boardname">{{OP.Board}}</span></a></p>
|
||||
</div>
|
||||
{{{OP.Truncate.RenderPost}}}
|
||||
{{#Truncate.Replies}}
|
||||
{{{Truncate.RenderPost}}}
|
||||
<br />
|
||||
{{/Truncate.Replies}}
|
||||
<hr />
|
||||
</div>
|
||||
{{/threads}}
|
||||
</div>
|
||||
@@ -40,5 +40,10 @@
|
||||
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>
|
||||
|
||||
51
contrib/tools/api/moderate.js
Normal file
@@ -0,0 +1,51 @@
|
||||
var http = require('http');
|
||||
|
||||
var makeIpBans = function(cidrs, privkey, cb) {
|
||||
cb({
|
||||
message: cidrs.join("\noverchan-inet-ban "),
|
||||
name: "mod#"+privkey,
|
||||
frontend: "memegod.censor",
|
||||
newsgroup: "ctl"
|
||||
})
|
||||
}
|
||||
|
||||
var makeDeletePosts = function(msgids, privkey, cb) {
|
||||
cb({
|
||||
message: msgids.join("\ndelete "),
|
||||
name: "mod#"+privkey,
|
||||
frontend: "memegod.censor",
|
||||
newsgroup: "ctl",
|
||||
})
|
||||
}
|
||||
|
||||
var moderate = function(req) {
|
||||
|
||||
j = JSON.stringify(req);
|
||||
|
||||
var r = http.request({
|
||||
port: 8800,
|
||||
method: "POST",
|
||||
path: "/api/post",
|
||||
auth: "user:pass",
|
||||
headers: {
|
||||
"Content-Type": "text/json",
|
||||
"Content-Length": j.length
|
||||
}
|
||||
}, function (res) {
|
||||
res.on('data', function (chunk) {
|
||||
var r = chunk.toString();
|
||||
var rj = JSON.parse(r);
|
||||
console.log(rj.id);
|
||||
});
|
||||
});
|
||||
|
||||
r.write(j);
|
||||
r.end();
|
||||
}
|
||||
|
||||
var privateKey = "longhexgoestripcodegoeshere";
|
||||
|
||||
// ban 192.168.0.1/16 and sign with private key
|
||||
makeIpBans(["192.168.0.1/16"], privateKey, moderate);
|
||||
// delete <msg1@place.tld> and <msg2@otherplace.tld> and sign with private key
|
||||
makeDeletPosts(["<msg1@place.tld>", "<msg2@otherplace.tld>"], privateKey, moderate);
|
||||
@@ -75,6 +75,28 @@ class Article:
|
||||
if msg:
|
||||
return "{}\n{}".format(self.header(), msg)
|
||||
|
||||
def getAttachmentPart(self, j):
|
||||
msg = ''
|
||||
mtype = 'image'
|
||||
if j['ext'] in ['.mp4', '.webm']:
|
||||
mtype = 'video'
|
||||
url = 'https://{}/{}/src/{}{}'.format(self.site, self.board, j['tim'], j['ext'])
|
||||
print ('obtain {}'.format(url))
|
||||
|
||||
r = requests.get(url)
|
||||
if r.status_code == 200:
|
||||
msg += '--{}\n'.format(self.boundary)
|
||||
msg += 'Content-Type: {}/{}\n'.format(mtype, j['ext'])
|
||||
msg += 'Content-Disposition: form-data; filename="{}{}"; name="import"\n'.format(j['filename'], j['ext'])
|
||||
msg += 'Content-Transfer-Encoding: base64\n'
|
||||
msg += '\n'
|
||||
msg += base64.b64encode(r.content).decode('ascii')
|
||||
msg += '\n'
|
||||
else:
|
||||
print ('failed to obtain attachment: {} != 200'.format(r.status_code))
|
||||
return msg
|
||||
|
||||
|
||||
def bodyMultipart(self):
|
||||
self.boundary = '========{}'.format(random.randint(0, 10000000))
|
||||
msg = self.header() + '\n'
|
||||
@@ -82,24 +104,10 @@ class Article:
|
||||
msg += 'Content-Type: text/plain; encoding=UTF-8\n'
|
||||
msg += '\n'
|
||||
msg += self.message() + '\n'
|
||||
msg += '--{}\n'.format(self.boundary)
|
||||
mtype = 'image'
|
||||
if self.j['ext'] in ['.mp4', '.webm']:
|
||||
mtype = 'video'
|
||||
msg += 'Content-Type: {}/{}\n'.format(mtype, self.j['ext'])
|
||||
msg += 'Content-Disposition: form-data; filename="{}{}"; name="import"\n'.format(self.j['filename'], self.j['ext'])
|
||||
msg += 'Content-Transfer-Encoding: base64\n'
|
||||
msg += '\n'
|
||||
url = 'https://{}/{}/src/{}{}'.format(self.site, self.board, self.j['tim'], self.j['ext'])
|
||||
print ('obtain {}'.format(url))
|
||||
|
||||
r = requests.get(url)
|
||||
if r.status_code == 200:
|
||||
msg += base64.b64encode(r.content).decode('ascii')
|
||||
msg += '\n'
|
||||
else:
|
||||
print ('failed to obtain attachment: {} != 200'.format(r.status_code))
|
||||
return
|
||||
msg += self.getAttachmentPart(self.j)
|
||||
if 'extra_files' in self.j:
|
||||
for j in self.j['extra_files']:
|
||||
msg += self.getAttachmentPart(j)
|
||||
msg += '\n--{}--\n'.format(self.boundary)
|
||||
return msg
|
||||
|
||||
@@ -111,8 +119,9 @@ class Article:
|
||||
|
||||
class Poster:
|
||||
|
||||
def __init__(self, host, port):
|
||||
def __init__(self, host, port, user, passwd):
|
||||
self.host, self.port = host, port
|
||||
self.user, self.passwd = user, passwd
|
||||
|
||||
def post(self, articles):
|
||||
"""
|
||||
@@ -121,7 +130,7 @@ class Poster:
|
||||
if isinstance(articles, Article):
|
||||
return self.post([articles])
|
||||
else:
|
||||
n = nntplib.NNTP(self.host, self.port)
|
||||
n = nntplib.NNTP(self.host, self.port, self.user, self.passwd)
|
||||
for article in articles:
|
||||
body = article.body()
|
||||
if body:
|
||||
@@ -144,7 +153,7 @@ class Getter:
|
||||
self.site = url_parse(url).hostname
|
||||
self.board = url_parse(url).path.split('/')[1]
|
||||
|
||||
def get(self):
|
||||
def get(self, thread=False):
|
||||
"""
|
||||
yield a bunch of articles
|
||||
"""
|
||||
@@ -155,12 +164,17 @@ class Getter:
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
if 'threads' in j:
|
||||
for t in j['threads']:
|
||||
posts = t['posts']
|
||||
for post in posts:
|
||||
if thread:
|
||||
if 'posts' in j:
|
||||
for post in j['posts']:
|
||||
yield Article(post, self.board, self.site)
|
||||
|
||||
else:
|
||||
if 'threads' in j:
|
||||
for t in j['threads']:
|
||||
posts = t['posts']
|
||||
for post in posts:
|
||||
yield Article(post, self.board, self.site)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
@@ -169,11 +183,21 @@ def main():
|
||||
ap.add_argument('--server', type=str, required=True)
|
||||
ap.add_argument('--port', type=int, required=True)
|
||||
ap.add_argument('--board', type=str, required=True)
|
||||
ap.add_argument('--thread', type=str, required=False)
|
||||
ap.add_argument('--user', type=str, required=True)
|
||||
ap.add_argument('--passwd', type=str, requried=True)
|
||||
args = ap.parse_args()
|
||||
poster = Poster(args.server, args.port)
|
||||
for n in range(10):
|
||||
getter = Getter('https://8ch.net/{}/{}.json'.format(args.board, n))
|
||||
poster.post(getter.get())
|
||||
poster = Poster(args.server, args.port, args.user, args.passwd)
|
||||
|
||||
if args.thread:
|
||||
# only archive 1 thread
|
||||
getter = Getter('https://8ch.net/{}/res/{}.json'.format(args.board, thread))
|
||||
poster.post(getter.get(thread=True))
|
||||
else:
|
||||
# archive the entire board
|
||||
for n in range(10):
|
||||
getter = Getter('https://8ch.net/{}/{}.json'.format(args.board, n))
|
||||
poster.post(getter.get())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
209
contrib/tools/migrate/lynxchan/lynx2nntp.js
Executable file
@@ -0,0 +1,209 @@
|
||||
#!/usr/bin/env nodejs
|
||||
|
||||
var memegod = require("mongodb");
|
||||
var memegodClient = memegod.MongoClient;
|
||||
var assert = require("assert");
|
||||
var http = require("http");
|
||||
|
||||
|
||||
// memegod daemon url
|
||||
var url = "mongodb://127.0.0.1:27017/lynxchan";
|
||||
|
||||
// nntp frontend name for article import
|
||||
var frontendName = "memegod.import";
|
||||
// srndv2 http frontend server to do api requests against
|
||||
var srndApiServ = "localhost";
|
||||
var srndApiPort = 18000;
|
||||
// username password combo for using api
|
||||
var srndApiLogin = "user:pass";
|
||||
// some memegod thing
|
||||
var idPrefix="v1-";
|
||||
|
||||
|
||||
// create a newsgroup name given board name
|
||||
var makeGroupName = function(board) {
|
||||
return "overchan.test.endchan." + board.boardUri;
|
||||
}
|
||||
|
||||
// call function for each op on a board
|
||||
var foreachOpsOnBoard = function(db, board, callback, done) {
|
||||
var cur = db.collection("threads").find({boardUri: board});
|
||||
var ops = [];
|
||||
cur.each(function(err, doc) {
|
||||
if (doc) {
|
||||
ops.push(doc)
|
||||
} else {
|
||||
for (var idx = 0 ; ops.length > idx ; idx ++ ) {
|
||||
callback(ops[idx]);
|
||||
}
|
||||
if(done)
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// call a callback for each reply to op
|
||||
// pass in the memegod post
|
||||
var foreachReplyForOP = function(db, op, callback, done) {
|
||||
var doit = function(op, msgid) {// we don't has got it
|
||||
var cur = db.collection("posts").find({ threadId: op.threadId});
|
||||
var repls = [];
|
||||
cur.each(function(err, doc) {
|
||||
if (doc) {
|
||||
repls.push(doc)
|
||||
} else {
|
||||
for (var idx = 0 ; repls.length > idx ; idx ++ ) {
|
||||
callback(repls[idx]);
|
||||
}
|
||||
if(done)
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
checkPostExists(op, doit, doit);
|
||||
}
|
||||
|
||||
// find all boards in memegod
|
||||
// call callback for each board
|
||||
var foreachBoard = function(db, callback, done) {
|
||||
var cursor = db.collection('boards').find();
|
||||
var boards = [];
|
||||
cursor.each(function(err, doc) {
|
||||
if (doc) {
|
||||
boards.push(doc)
|
||||
} else {
|
||||
for (var idx = 0 ; boards.length > idx ; idx ++ ) {
|
||||
callback(boards[idx]);
|
||||
}
|
||||
if(done)
|
||||
done();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// convert a memegod post from board into an overchan article
|
||||
// call a callback with the created post
|
||||
var createArticle = function(post, board, callback) {
|
||||
if (post == null) {
|
||||
callback(null);
|
||||
return
|
||||
}
|
||||
var article = {
|
||||
ip: post.ip.join("."),
|
||||
message: post.message || " ",
|
||||
subject: post.subject || "MongoDB is web scale",
|
||||
frontend: frontendName,
|
||||
newsgroup: makeGroupName(board),
|
||||
headers: {
|
||||
}
|
||||
};
|
||||
if (post.postId) {
|
||||
article.headers["X-Memegod-Post-Id"] = idPrefix+post.postId
|
||||
}
|
||||
if (post.threadId) {
|
||||
article.headers["X-Memegod-Thread-Id"] = idPrefix+post.threadId;
|
||||
}
|
||||
article.headers["X-Memegod-Id"] = idPrefix+post._id;
|
||||
article.headers["X-Migrated-From"] = "MemeGod";
|
||||
article.name = post.name || "Stephen Lynx";
|
||||
callback(article);
|
||||
}
|
||||
|
||||
// post an overchan article via the api
|
||||
// call callback passing in the message-id of the new post
|
||||
var postArticle = function(article, callback) {
|
||||
if (article == null) { callback(null); return; }
|
||||
checkViaHeader("X-Memegod-Id", article.headers["X-Memegod-Id"], function(msgid) {
|
||||
// we has got it already
|
||||
callback(msgid);
|
||||
}, function(msgid) {
|
||||
// we don't has got it
|
||||
var req = http.request({
|
||||
port: srndApiPort,
|
||||
method: "POST",
|
||||
path: "/api/post",
|
||||
auth: srndApiLogin,
|
||||
headers: {
|
||||
"Content-Type": "text/json",
|
||||
}
|
||||
}, function(res) {
|
||||
var data = "";
|
||||
res.on("data", function (chunk) {
|
||||
data += chunk;
|
||||
});
|
||||
res.on("end", function() {
|
||||
var j = JSON.parse(data)
|
||||
var msgid = j.id;
|
||||
callback(msgid);
|
||||
})
|
||||
});
|
||||
req.write(JSON.stringify(article));
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
// check if an article exists given header name and header value
|
||||
var checkViaHeader = function(name, value, yesCb, noCb) {
|
||||
var req = http.request({
|
||||
port: srndApiPort,
|
||||
method: "GET",
|
||||
path: "/api/header?name="+name+"&value="+value,
|
||||
}, function (res) {
|
||||
var data = "";
|
||||
res.on("data", function(chnk) {
|
||||
data += chnk;
|
||||
});
|
||||
res.on("end", function() {
|
||||
var j = JSON.parse(data);
|
||||
if ( j.length > 0 ) {
|
||||
// it exists
|
||||
yesCb(j[0]);
|
||||
} else {
|
||||
// does not exist
|
||||
noCb();
|
||||
}
|
||||
});
|
||||
});
|
||||
req.end();
|
||||
}
|
||||
|
||||
// check if a post exists
|
||||
var checkPostExists = function(post, yescb, nocb) {
|
||||
checkViaHeader("X-Memegod-Id", idPrefix + post._id,
|
||||
function(msgid) { yescb(post, msgid); },
|
||||
function() { nocb(post); });
|
||||
}
|
||||
|
||||
var putBoard = function(db, board, done) {
|
||||
foreachOpsOnBoard(db, board.boardUri, function(originalPost) {
|
||||
var doit = function(op) {
|
||||
createArticle(op, board, function(opArticle) {
|
||||
postArticle(opArticle, function(opMsgId) {
|
||||
// for each reply for OP
|
||||
foreachReplyForOP(db, op, function(post) {
|
||||
checkPostExists(post , function(msgid) {
|
||||
// we have this post
|
||||
}, function(post, msgid) {
|
||||
// put create reply
|
||||
createArticle(post, board, function(article) {
|
||||
// set references header
|
||||
article.headers["References"] = opMsgId;
|
||||
postArticle(article, function(msgid) {});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
checkPostExists(originalPost, doit, doit);
|
||||
});
|
||||
}
|
||||
|
||||
memegodClient.connect(url, function(err, db) {
|
||||
console.log("connected to the meme god");
|
||||
foreachBoard(db, function(board) {
|
||||
console.log("updating "+board.boardUri);
|
||||
putBoard(db, board);
|
||||
});
|
||||
});
|
||||
117
contrib/translations/de-DE.ini
Normal file
@@ -0,0 +1,117 @@
|
||||
[formats]
|
||||
full_date_format=15:04:05 02.01.2006
|
||||
month_date_format=01.2006
|
||||
day_date_format=02.01
|
||||
|
||||
[strings]
|
||||
|
||||
#catalog
|
||||
catalog_title=Katalog für
|
||||
replies_short_label=A
|
||||
pictures_short_label=B
|
||||
|
||||
#board
|
||||
catalog_label=Katalog
|
||||
|
||||
#board list
|
||||
board_list_title=Boardliste
|
||||
board_label=Board
|
||||
pph_label=Posts pro Stunde
|
||||
ppd_label=Posts pro Tag
|
||||
total=Gesamt
|
||||
|
||||
#front page
|
||||
posts_today=Posts heute
|
||||
posts_hour=Posts diese Stunde
|
||||
|
||||
#history
|
||||
month=Monat
|
||||
posts=Posts
|
||||
post_history_title=Postverlauf
|
||||
|
||||
#keygen
|
||||
new_tripcode_title=Hier ist der neue Tripcode
|
||||
new_tripcode_label=Neuer Tripcode
|
||||
secret_key=Privater Schlüssel
|
||||
public_key=Öffentlicher Schlüssel
|
||||
tripcode=Tripcode
|
||||
|
||||
#login
|
||||
login=Anmeldung
|
||||
|
||||
#modpage
|
||||
modpage_title=nntpchan-Moderationsseite
|
||||
post_actions_label=Postfunktionen
|
||||
target_label=Ziel
|
||||
ban_url_prompt=Bannen (URL)
|
||||
delete_url_prompt=Löschen (URL)
|
||||
unban_ip_prompt=Bann aufheben (IP)
|
||||
key_actions_label=Schlüsselfunktionen
|
||||
pubkey_label=Öffentlicher Schlüssel
|
||||
add_key_prompt=Schlüssel hinzufügen
|
||||
remove_key_prompt=Schlüssen entfernen
|
||||
nntp_login_label=NNTP-Benutzer
|
||||
username=Benutzername
|
||||
password=Password
|
||||
add_user_prompt=Benutzer hinzufügen
|
||||
remove_user_prompt=Benutzer entfernen
|
||||
board_actions_label=Boardfunktionen
|
||||
board_name_title=Boardname
|
||||
add_board_prompt=Board hinzufügen
|
||||
regenerate_prompt=Regenerieren
|
||||
ban_prompt=Bannen
|
||||
unban_prompt=Bann aufheben
|
||||
nuke_prompt=Sprengen
|
||||
light_actions_label=Schnelle Funktionen
|
||||
reload_templates_prompt=Alle Templates erneut laden
|
||||
heavy_actions_label=Rechenintensive Funktionen (mit Vorsicht verwenden)
|
||||
regenerate_markup_prompt=Alle HTML-Seiten regenerieren
|
||||
regenerate_thumbs_prompt=Alle Vorschaubilder regenerieren
|
||||
nojs_info=Bitte aktivieren Sie JavaScript, um diese Seite zu nutzen.
|
||||
|
||||
#navbar
|
||||
navbar_on=@
|
||||
front_page_title=Startseite
|
||||
overboard_label=Überboard
|
||||
|
||||
#newboard
|
||||
new_board_title=Neues Board erstellen
|
||||
first_post_label=Machen Sie den ersten Post
|
||||
comment=Kommentar
|
||||
captcha=Captcha
|
||||
solution=Lösung
|
||||
|
||||
#overview
|
||||
newsgroup=Newsgroup
|
||||
posted=Gepostet
|
||||
subject=Betreff
|
||||
|
||||
#post
|
||||
from_i2p=Vom I2P-Netzwerk gepostet
|
||||
from_tor=Vom Tor-Netzwerk gepostet
|
||||
from_clearnet=Vom Clearnet gepostet
|
||||
reply_label=Antworten
|
||||
|
||||
#post failed
|
||||
post_failed_label=Post fehlgeschlagen
|
||||
|
||||
#post form
|
||||
name=Name
|
||||
file=Anhang
|
||||
dubs=Doppel?
|
||||
|
||||
#posts graph
|
||||
day=Tag
|
||||
|
||||
#post success
|
||||
posted_as_label=Gepostet als
|
||||
|
||||
#thread
|
||||
return=Zurück
|
||||
to_top_label=Nach oben
|
||||
update=Updaten
|
||||
|
||||
#ukko
|
||||
overboard_title=ukko / Überboard
|
||||
posted_on_label=Gepostet in
|
||||
|
||||
121
contrib/translations/en-US.ini
Normal file
@@ -0,0 +1,121 @@
|
||||
[formats]
|
||||
full_date_format=Mon Jan _2 15:04:05 2006
|
||||
month_date_format=2006-02
|
||||
day_date_format=01-02
|
||||
|
||||
[strings]
|
||||
|
||||
#catalog
|
||||
catalog_title=Catalog for
|
||||
replies_short_label=R
|
||||
pictures_short_label=P
|
||||
|
||||
#board
|
||||
catalog_label=Catalog
|
||||
|
||||
#board list
|
||||
board_list_title=board list
|
||||
board_label=Board
|
||||
pph_label=Posts per Hour
|
||||
ppd_label=Posts per Day
|
||||
total=Total
|
||||
|
||||
#front page
|
||||
posts_today=Posts Today
|
||||
posts_hour=Posts this Hour
|
||||
|
||||
#history
|
||||
month=Month
|
||||
posts=Posts
|
||||
post_history_title=Post History
|
||||
|
||||
#keygen
|
||||
new_tripcode_title=here is a new tripcode
|
||||
new_tripcode_label=New Tripcode
|
||||
secret_key=secret
|
||||
public_key=public
|
||||
tripcode=tripcode
|
||||
|
||||
#login
|
||||
login=login
|
||||
|
||||
#modpage
|
||||
modpage_title=nntpchan mod page
|
||||
post_actions_label=post actions
|
||||
target_label=target
|
||||
ban_url_prompt=ban (url)
|
||||
delete_url_prompt=delete (url)
|
||||
unban_ip_prompt=unban (ip)
|
||||
key_actions_label=key actions
|
||||
pubkey_label=pubkey
|
||||
add_key_prompt=add key
|
||||
remove_key_prompt=remove key
|
||||
nntp_login_label=nntp login
|
||||
username=username
|
||||
password=password
|
||||
add_user_prompt=add user
|
||||
remove_user_prompt=remove user
|
||||
board_actions_label=board actions
|
||||
board_name_title=board name
|
||||
add_board_prompt=add board
|
||||
regenerate_prompt=regenerate
|
||||
ban_prompt=ban
|
||||
unban_prompt=unban
|
||||
nuke_prompt=nuke
|
||||
light_actions_label=lightweight actions
|
||||
reload_templates_prompt=reload all templates
|
||||
heavy_actions_label=very load heavy actions, use with care
|
||||
regenerate_markup_prompt=regenerate all markup
|
||||
regenerate_thumbs_prompt=regenerate all thumbnails
|
||||
feed_sync_prompt=manually synchronize all articles
|
||||
expire_old_prompt=manually expire orphaned articles
|
||||
nojs_info=enable js to use the mod panel kthx
|
||||
|
||||
#navbar
|
||||
navbar_on=on
|
||||
front_page_title=front page
|
||||
overboard_title=overboard
|
||||
|
||||
#newboard
|
||||
new_board_title=create new board
|
||||
first_post_label=make your first post
|
||||
comment=Comment
|
||||
captcha=Captcha
|
||||
solution=Solution
|
||||
|
||||
#overview
|
||||
newsgroup=Newsgroup
|
||||
posted=Posted
|
||||
subject=Subject
|
||||
|
||||
#post
|
||||
from_i2p=posted from i2p
|
||||
from_tor=posted from tor
|
||||
from_clearnet=posted from clearnet
|
||||
reply_label=Reply
|
||||
|
||||
#post failed
|
||||
post_failed_label=post failed
|
||||
|
||||
#post form
|
||||
name=Name
|
||||
file=File
|
||||
dubs=Get Dubs
|
||||
|
||||
#posts graph
|
||||
day=Day
|
||||
|
||||
#post success
|
||||
posted_as_label=posted as
|
||||
|
||||
#thread
|
||||
return=Return
|
||||
to_top_label=Top
|
||||
update=Update
|
||||
|
||||
#ukko
|
||||
overboard_title=ukko / overboard
|
||||
posted_on_label=Posted on
|
||||
|
||||
#404 page
|
||||
resource_not_found=The page you are looking for isn't here
|
||||
117
contrib/translations/es-ES.ini
Normal file
@@ -0,0 +1,117 @@
|
||||
[formats]
|
||||
full_date_format=Lunes 2_Enero 15:04:05 2006
|
||||
month_date_format=02-2006
|
||||
day_date_format=01-02
|
||||
|
||||
[strings]
|
||||
|
||||
#catalog
|
||||
catalog_title=Catálogo para
|
||||
replies_short_label=R
|
||||
pictures_short_label=P
|
||||
|
||||
#board
|
||||
catalog_label=Catálogo
|
||||
|
||||
#board list
|
||||
board_list_title=Lista de canales
|
||||
board_label=Canales
|
||||
pph_label=Envíos a la hora
|
||||
ppd_label=Envíos al Día
|
||||
total=Total
|
||||
|
||||
#front page
|
||||
posts_today=Envíos de hoy
|
||||
posts_hour=Envíos de esta última hora
|
||||
|
||||
#history
|
||||
month=Mes
|
||||
posts=Envíos
|
||||
post_history_title=Historial de envíos
|
||||
|
||||
#keygen
|
||||
new_tripcode_title=Esto es un nuevo tripcode
|
||||
new_tripcode_label=Nuevo Tripcode
|
||||
secret_key=secreto
|
||||
public_key=público
|
||||
tripcode=tripcode
|
||||
|
||||
#login
|
||||
login=inicio de sesión
|
||||
|
||||
#modpage
|
||||
modpage_title=página configuración nntpchan
|
||||
post_actions_label=acciones de envíos
|
||||
target_label=objetivo
|
||||
ban_url_prompt=prohibir (url)
|
||||
delete_url_prompt=borrar (url)
|
||||
unban_ip_prompt=permitir (ip)
|
||||
key_actions_label=opciones de claves
|
||||
pubkey_label=pubkey
|
||||
add_key_prompt=añadir clave
|
||||
remove_key_prompt=eliminar clave
|
||||
nntp_login_label=inicio de sesión nntp
|
||||
username=nombre de usuario
|
||||
password=contraseña
|
||||
add_user_prompt=añadir usuario
|
||||
remove_user_prompt=eliminar usuario
|
||||
board_actions_label=acciones sobre los canales
|
||||
board_name_title=nombre del canal
|
||||
add_board_prompt=añadir canal
|
||||
regenerate_prompt=regenerar
|
||||
ban_prompt=prohibir
|
||||
unban_prompt=permitir
|
||||
nuke_prompt=destruir
|
||||
light_actions_label=acciones sencillas
|
||||
reload_templates_prompt=recargar todas las plantillas
|
||||
heavy_actions_label=acciones que consumen muchos recursos, usar con cuidado
|
||||
regenerate_markup_prompt=regenerar todos los formatos
|
||||
regenerate_thumbs_prompt=regenerar todas las miniaturas
|
||||
nojs_info=habilitar JS para utilizar el panel de mods kthx
|
||||
|
||||
#navbar
|
||||
navbar_on=on
|
||||
front_page_title=página principal
|
||||
overboard_title=overboard
|
||||
|
||||
#newboard
|
||||
new_board_title=crear un nuevo canal
|
||||
first_post_label=crear tu primer envío
|
||||
comment=Comentario
|
||||
captcha=Captcha
|
||||
solution=Solución
|
||||
|
||||
#overview
|
||||
newsgroup=Grupo de noticias
|
||||
posted=Enviado
|
||||
subject=Asunto
|
||||
|
||||
#post
|
||||
from_i2p=enviado desde i2p
|
||||
from_tor=enviado desde tor
|
||||
from_clearnet=enviado desde clearnet
|
||||
reply_label=Responder
|
||||
|
||||
#post failed
|
||||
post_failed_label=el envío a fallado
|
||||
|
||||
#post form
|
||||
name=Nombre
|
||||
file=Archivo
|
||||
dubs=Obtener 'Dubs' (dobles)
|
||||
|
||||
#posts graph
|
||||
day=Día
|
||||
|
||||
#post success
|
||||
posted_as_label=enviado como
|
||||
|
||||
#thread
|
||||
return=Volver
|
||||
to_top_label=Arriba
|
||||
update=Actualizar
|
||||
|
||||
#ukko
|
||||
overboard_title=ukko / overboard
|
||||
posted_on_label=Enviado en
|
||||
|
||||
116
contrib/translations/pt-BR.ini
Normal file
@@ -0,0 +1,116 @@
|
||||
[formats]
|
||||
full_date_format=Segunda, _2 de Janeiro 15:04:05 2006
|
||||
month_date_format=20-2006
|
||||
day_date_format=01-02
|
||||
|
||||
[strings]
|
||||
|
||||
#catalog
|
||||
catalog_title=Catálogo para
|
||||
replies_short_label=R
|
||||
pictures_short_label=I
|
||||
|
||||
#board
|
||||
catalog_label=Menu
|
||||
|
||||
#board list
|
||||
board_list_title=lista de canais
|
||||
board_label=Canais
|
||||
pph_label=Envios por hora
|
||||
ppd_label=Envios por dia
|
||||
total=Total
|
||||
|
||||
#front page
|
||||
posts_today=Envios hoje
|
||||
posts_hour=Envios na ultima hora
|
||||
|
||||
#history
|
||||
month=Mês
|
||||
posts=Envios
|
||||
post_history_title=Histórico
|
||||
|
||||
#keygen
|
||||
new_tripcode_title=Isto é um novo tripcode
|
||||
new_tripcode_label=Novo tripcode
|
||||
secret_key=segredo
|
||||
public_key=público
|
||||
tripcode=tripcode
|
||||
|
||||
#login
|
||||
login=login
|
||||
|
||||
#modpage
|
||||
modpage_title=Página de configuração do nntpchan
|
||||
post_actions_label=ações dos envios
|
||||
target_label=objetivo
|
||||
ban_url_prompt=banir (url)
|
||||
delete_url_prompt=deletar (url)
|
||||
unban_ip_prompt=permitir (ip)
|
||||
key_actions_label=opções de teclas
|
||||
pubkey_label=pubkey
|
||||
add_key_prompt=adicionar chave
|
||||
remove_key_prompt=remover chave
|
||||
nntp_login_label=iniciar sessão nntp
|
||||
username=nome de usuário
|
||||
password=senha
|
||||
add_user_prompt=adicionar usuário
|
||||
remove_user_prompt=remover usuário
|
||||
board_actions_label=ações de canais
|
||||
board_name_title=nome do canal
|
||||
add_board_prompt=adicionar canal
|
||||
regenerate_prompt=gerar novamente
|
||||
ban_prompt=banir
|
||||
unban_prompt=permitir
|
||||
nuke_prompt=destruir
|
||||
light_actions_label=ações leves
|
||||
reload_templates_prompt=recarregar todos os padrões
|
||||
heavy_actions_label=ações que consumem muitos recursos, usar com cuidado
|
||||
regenerate_markup_prompt=recarregar todos os formatos
|
||||
regenerate_thumbs_prompt=recarregar todas as miniaturas
|
||||
nojs_info=habilitar JS para usar o painel de mods kthx
|
||||
|
||||
#navbar
|
||||
navbar_on=on
|
||||
front_page_title=página inicial
|
||||
overboard_title=overboard
|
||||
|
||||
#newboard
|
||||
new_board_title=criar um novo canal
|
||||
first_post_label=fazer seu primeiro envio
|
||||
comment=Comentário
|
||||
captcha=Captcha
|
||||
solution=Solução
|
||||
|
||||
#overview
|
||||
newsgroup=Grupo de notícias
|
||||
posted=Enviado
|
||||
subject=Assunto
|
||||
|
||||
#post
|
||||
from_i2p=enviado da i2p
|
||||
from_tor=enviado da tor
|
||||
from_clearnet=enviado da clearnet
|
||||
reply_label=Responder
|
||||
|
||||
#post failed
|
||||
post_failed_label=o envio falhou
|
||||
|
||||
#post form
|
||||
name=Nome
|
||||
file=Arquivo
|
||||
dubs=Obter "Dubs" (pares)
|
||||
|
||||
#posts graph
|
||||
day=Dia
|
||||
|
||||
#post success
|
||||
posted_as_label=enviado como
|
||||
|
||||
#thread
|
||||
return=Voltar
|
||||
to_top_label=Acima
|
||||
update=Atualizar
|
||||
|
||||
#ukko
|
||||
overboard_title=ukko / overboard
|
||||
posted_on_label=Enviado em
|
||||
116
contrib/translations/ru-RU.ini
Normal file
@@ -0,0 +1,116 @@
|
||||
[formats]
|
||||
full_date_format=_2 Янв 2006 г. Пн 15:04:05
|
||||
month_date_format=01.2006
|
||||
day_date_format=02.01
|
||||
|
||||
[strings]
|
||||
|
||||
#catalog
|
||||
catalog_title=Каталог
|
||||
replies_short_label=О
|
||||
pictures_short_label=И
|
||||
|
||||
#board
|
||||
catalog_label=Каталог
|
||||
|
||||
#board list
|
||||
board_list_title=Список досок
|
||||
board_label=Доска
|
||||
pph_label=Постов в час
|
||||
ppd_label=Постов в день
|
||||
total=Всего
|
||||
|
||||
#front page
|
||||
posts_today=Постов за сегодня
|
||||
posts_hour=Постов за этот час
|
||||
|
||||
#history
|
||||
month=Месяц
|
||||
posts=Посты
|
||||
post_history_title=История поста
|
||||
|
||||
#keygen
|
||||
new_tripcode_title=вот новый трипкод
|
||||
new_tripcode_label=Новый трипкод
|
||||
secret_key=закрытый
|
||||
public_key=открытый
|
||||
tripcode=трипкод
|
||||
|
||||
#login
|
||||
login=войти
|
||||
|
||||
#modpage
|
||||
modpage_title=страница модерации nntpchan
|
||||
post_actions_label=опции поста
|
||||
target_label=цель
|
||||
ban_url_prompt=забанить (url)
|
||||
delete_url_prompt=удалить (url)
|
||||
unban_ip_prompt=разбанить (ip)
|
||||
key_actions_label=опции ключа
|
||||
pubkey_label=открытый ключ
|
||||
add_key_prompt=добавить ключ
|
||||
remove_key_prompt=удалить ключ
|
||||
nntp_login_label=nntp авторизация
|
||||
username=имя пользователя
|
||||
password=пароль
|
||||
add_user_prompt=добавить пользователя
|
||||
remove_user_prompt=удалить пользователя
|
||||
board_actions_label=опции доски
|
||||
board_name_title=название доски
|
||||
add_board_prompt=добавить доску
|
||||
regenerate_prompt=восстановить
|
||||
ban_prompt=забанить
|
||||
unban_prompt=разбанить
|
||||
nuke_prompt=уничтожить
|
||||
light_actions_label=малопотребляющие опции
|
||||
reload_templates_prompt=перезагрузить все шаблоны
|
||||
heavy_actions_label=многопотребляющие опции (использовать с осторожностью)
|
||||
regenerate_markup_prompt=восстановить всю разметку
|
||||
regenerate_thumbs_prompt=восстановить все миниатюры
|
||||
nojs_info=включи JS чтобы пользоваться панелью модерации ок спс
|
||||
|
||||
#navbar
|
||||
navbar_on=вкл
|
||||
front_page_title=главная страница
|
||||
overboard_title=сверхдоска
|
||||
|
||||
#newboard
|
||||
new_board_title=создать новую доску
|
||||
first_post_label=сделай свой первый пост
|
||||
comment=Комментарий
|
||||
captcha=Капча
|
||||
solution=Ответ
|
||||
|
||||
#overview
|
||||
newsgroup=Группа новостей
|
||||
posted=Отправлено
|
||||
subject=Тема
|
||||
|
||||
#post
|
||||
from_i2p=отправлено через i2p
|
||||
from_tor=отправлено через tor
|
||||
from_clearnet=отправлено через чистонет
|
||||
reply_label=Ответить
|
||||
|
||||
#post failed
|
||||
post_failed_label=отправка не удалась
|
||||
|
||||
#post form
|
||||
name=Имя
|
||||
file=Файл
|
||||
dubs=Получить Дабл
|
||||
|
||||
#posts graph
|
||||
day=День
|
||||
|
||||
#post success
|
||||
posted_as_label=отправлено как
|
||||
|
||||
#thread
|
||||
return=Вернуться
|
||||
to_top_label=К началу
|
||||
update=Обновить
|
||||
|
||||
#ukko
|
||||
overboard_title=ukko / сверхдоска
|
||||
posted_on_label=Опубликованно в
|
||||
11
doc/build.md
@@ -4,12 +4,17 @@
|
||||
## requirements ##
|
||||
|
||||
* linux or freebsd
|
||||
* go 1.3 or higher
|
||||
* libsodium 1.0 or higher
|
||||
* imagemagick
|
||||
* ffmpegthumbnailer
|
||||
* sox
|
||||
|
||||
## supported go versions ##
|
||||
|
||||
* `go 1.6` or higher with redis driver
|
||||
|
||||
* `go 1.3` or higher without redis driver
|
||||
|
||||
## debian ##
|
||||
|
||||
|
||||
@@ -25,4 +30,8 @@ Check out the repo and build it
|
||||
cd nntpchan
|
||||
./build.sh
|
||||
|
||||
If you want to build without supporting redis then build with the `--no-redis` flag
|
||||
|
||||
./build.sh --no-redis
|
||||
|
||||
Now configure the database. [next](database.md)
|
||||
|
||||
@@ -1,28 +1,5 @@
|
||||
You have 2 choices for database backend:
|
||||
|
||||
Postgres on Debian (as root)
|
||||
* [postgres](postgres.md)
|
||||
|
||||
# install as root
|
||||
apt-get install --no-install-recommends postgresql postgresql-client
|
||||
|
||||
|
||||
Setting up postgres (as root)
|
||||
|
||||
# become postgres user
|
||||
su postgres
|
||||
# spawn postgres admin shell
|
||||
psql
|
||||
|
||||
You'll get a prompt, enter the following:
|
||||
|
||||
CREATE ROLE srnd WITH LOGIN PASSWORD 'srnd';
|
||||
CREATE DATABASE srnd WITH ENCODING 'UTF8' OWNER srnd;
|
||||
\q
|
||||
|
||||
For demo purposes we'll use these credentials.
|
||||
These are default values, please change them later.
|
||||
|
||||
## important
|
||||
|
||||
these credentials assume you are going to run using a user called `srnd`, if your username you plan to run the daemon as is different please change `srnd` to your username.
|
||||
|
||||
Now run it, [next](running.md)
|
||||
* [redis](redis.md)
|
||||
|
||||
28
doc/postgres.md
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
Postgres on Debian (as root)
|
||||
|
||||
# install as root
|
||||
apt-get install --no-install-recommends postgresql postgresql-client
|
||||
|
||||
|
||||
Setting up postgres (as root)
|
||||
|
||||
# become postgres user
|
||||
su postgres
|
||||
# spawn postgres admin shell
|
||||
psql
|
||||
|
||||
You'll get a prompt, enter the following:
|
||||
|
||||
CREATE ROLE srnd WITH LOGIN PASSWORD 'srnd';
|
||||
CREATE DATABASE srnd WITH ENCODING 'UTF8' OWNER srnd;
|
||||
\q
|
||||
|
||||
For demo purposes we'll use these credentials.
|
||||
These are default values, please change them later.
|
||||
|
||||
## important
|
||||
|
||||
these credentials assume you are going to run using a user called `srnd`, if your username you plan to run the daemon as is different please change `srnd` to your username.
|
||||
|
||||
Now run it, [next](running.md)
|
||||
@@ -314,6 +314,47 @@ The following part is signed:
|
||||
Above example in octets:
|
||||
|
||||
Content-Type: text/plain; charset=UTF-8\\r\\nDate: Thu, 02 May 2013 12:16:44 +0000\\r\\n\\r\\ndelete-x-all <message-ID>\\r\\ndelete <message-ID>\\r\\n\\r\\ndelete <message-ID>
|
||||
|
||||
## RPC
|
||||
Remote procedure calls can be sent via ``ctl`` or on a group basis by using the group ``ctl.overchan.*``, where * is the group for which you want to execute a certain operation.
|
||||
|
||||
### Default format
|
||||
The default format uses the MIME type ``text/plain`` where the first line of the body opens an array with ``[`` the next line is the name of the procedure you want to call, and on the lines following you can add one or more parameters. Each of these lines is terminated with `,` and indention can be added as well. The arry is closed with `]`.
|
||||
|
||||
#### Exapmple
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
From: anonymous <foo@bar.ano>
|
||||
Date: Thu, 02 May 2013 12:16:44 +0000
|
||||
Message-ID: <h2cykk1lwlmuqao2qiy@foo.bar>
|
||||
Newsgroups: ctl.overchan.foo
|
||||
Subject: RPC
|
||||
Path: hschan.ano
|
||||
|
||||
[
|
||||
setSetting,
|
||||
bumplimit,
|
||||
350,
|
||||
]
|
||||
|
||||
|
||||
### JSON RPC
|
||||
If the MIME type is specified as ``application/json`` the body is interpreted as [JSON RPC](http://json-rpc.org/).
|
||||
|
||||
#### Exapmple
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
From: anonymous <foo@bar.ano>
|
||||
Date: Thu, 02 May 2013 12:16:44 +0000
|
||||
Message-ID: <h2cykk1lwlmuqao2qiy@foo.bar>
|
||||
Newsgroups: ctl.overchan.foo
|
||||
Subject: RPC
|
||||
Path: hschan.ano
|
||||
|
||||
{"method": "setSetting", "params": ["bumplimit", "350"], "id": null}
|
||||
|
||||
### Additional details
|
||||
As described above, muliple RPC's can be sent via the multipart format. It is also expected that these articles are signed.
|
||||
|
||||
# Glossary
|
||||
|
||||
|
||||
37
doc/redis.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# configuring redis database backend
|
||||
|
||||
|
||||
0) Install redis
|
||||
|
||||
Redis 3.x or higher is required
|
||||
|
||||
0.A) debian/ubuntu
|
||||
|
||||
# apt update
|
||||
# apt install redis-server
|
||||
|
||||
0.B) redhat
|
||||
|
||||
# yum install redis
|
||||
|
||||
0.C) from source
|
||||
|
||||
* see http://redis.io/download
|
||||
|
||||
|
||||
|
||||
1) Configuration
|
||||
|
||||
In srnd.ini the database sections should look like this:
|
||||
|
||||
[database]
|
||||
type=redis
|
||||
schema=single
|
||||
host=localhost
|
||||
port=6379
|
||||
user=
|
||||
password=
|
||||
|
||||
2) Run the daemon
|
||||
|
||||
* see the [next step](running.md)
|
||||
77
install.sh
Executable file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
root=$(readlink -e $(dirname $0))
|
||||
|
||||
prefix="/opt/nntpchan"
|
||||
|
||||
help_text="usage: $0 [--prefix /opt/nntpchan] [-q|--quiet] [-r|--rebuild] [--disable-redis]"
|
||||
|
||||
# check for help flags first
|
||||
for arg in $@ ; do
|
||||
case $arg in
|
||||
-h|--help)
|
||||
echo $help_text
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
_next=""
|
||||
want_rebuild="0"
|
||||
want_quiet="0"
|
||||
build_args=""
|
||||
|
||||
# check for main flags
|
||||
for arg in $@ ; do
|
||||
case $arg in
|
||||
-q|--quiet)
|
||||
want_quiet="1"
|
||||
;;
|
||||
-r|--rebuild)
|
||||
want_rebuild="1"
|
||||
;;
|
||||
--prefix)
|
||||
_next="prefix"
|
||||
;;
|
||||
--prefix=*)
|
||||
prefix=$(echo $arg | cut -d'=' -f2)
|
||||
;;
|
||||
--disable-redis)
|
||||
build_args="$build_args --disable-redis"
|
||||
;;
|
||||
*)
|
||||
if [ "X$_next" == "Xprefix" ] ; then
|
||||
# set prefix
|
||||
prefix="$arg"
|
||||
_next=""
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
_cmd() {
|
||||
if [ "X$want_quiet" == "X1" ] ; then
|
||||
$@ &> /dev/null
|
||||
else
|
||||
$@
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "X$want_rebuild" == "X1" ] ; then
|
||||
_cmd echo "rebuilding daemon";
|
||||
_cmd $root/build.sh $build_args
|
||||
fi
|
||||
|
||||
if [ ! -e $root/srndv2 ] ; then
|
||||
_cmd echo "building daemon"
|
||||
# TODO: use different GOPATH for root?
|
||||
_cmd $root/build.sh $build_args
|
||||
fi
|
||||
|
||||
|
||||
_cmd mkdir -p $prefix
|
||||
_cmd mkdir -p $prefix/webroot/thm
|
||||
_cmd mkdir -p $prefix/webroot/img
|
||||
_cmd cp -f $root/srndv2 $prefix/srndv2
|
||||
_cmd cp -rf $root/{doc,contrib,certs} $prefix/
|
||||
_cmd echo "installed to $prefix"
|
||||