70 Commits
dank ... 0.3.0

Author SHA1 Message Date
Jeff Becker
85a968ad40 add cli docs 2016-02-01 21:27:14 -05:00
Jeff Becker
c169616471 add no attachments detection 2016-02-01 11:06:01 -05:00
Jeff Becker
c0d5800bd4 fix up readme 2016-01-23 11:08:00 -05:00
Jeff Becker
6bd5518249 clairity 2016-01-23 11:06:59 -05:00
Jeff Becker
b3da008694 add api docs 2016-01-23 11:06:10 -05:00
Jeff Becker
3a2529561f add comment 2016-01-23 10:58:14 -05:00
Jeff Becker
110e607839 add json api example 2016-01-23 10:57:27 -05:00
Jeff Becker
54fa915aeb add banners 2016-01-20 12:20:04 -05:00
Jeff Becker
273d28d237 same as last commit 2016-01-20 12:18:22 -05:00
Jeff Becker
ec56bbe8f9 center all banners 2016-01-20 12:18:04 -05:00
Jeff Becker
9340b9088e i hate js 2016-01-20 12:16:30 -05:00
Jeff Becker
329eca6af3 fix banner placements 2016-01-20 12:13:14 -05:00
Jeff Becker
06d4535eaa try fixing banners more 2016-01-20 12:11:38 -05:00
Jeff Becker
9f78414098 try usimg correct prefixes 2016-01-20 12:09:55 -05:00
Jeff Becker
97faee8d1d try fixing banners 2016-01-20 12:08:01 -05:00
Jeff Becker
33d95c2ef3 trying this 2016-01-20 12:04:22 -05:00
Jeff Becker
97ee132989 fix more again 2016-01-20 12:02:13 -05:00
Jeff Becker
ab3da1edee try fixing banners more 2016-01-20 12:00:28 -05:00
Jeff Becker
ba0f5471a3 try fixing banners more D: 2016-01-20 11:58:19 -05:00
Jeff Becker
9f84ab4ca9 try fixing banners 2016-01-20 11:52:04 -05:00
Jeff Becker
3274536134 revert banner injection 2016-01-20 11:49:38 -05:00
Jeff Becker
bc5b22f7a1 move banners arround 2016-01-20 11:49:23 -05:00
Jeff Becker
0199230489 fix banner inject function 2016-01-20 11:48:08 -05:00
Jeff Becker
98bb655a3c add banners 2016-01-20 11:42:18 -05:00
Jeff Becker
c4090303ec ammend todo 2016-01-19 09:05:03 -05:00
Jeff
0be5982d39 Merge pull request #44 from chen-chan/patch-2
typo: lable -> label
2016-01-17 18:43:14 -05:00
chen-chan
c7975c67ef typo: lable -> label 2016-01-15 21:12:56 +01:00
jeff
59173f055e add sync = 1 documentation 2016-01-13 00:22:08 -05:00
jeff
0b8c977aad add password auth docs 2016-01-12 18:02:01 -05:00
jeff
2c0426d1a4 change password field to use type="password" 2016-01-12 15:14:24 -05:00
jeff
e6de8a1d20 fix mod panel 2016-01-12 10:29:23 -05:00
jeff
9ebe7d7c5d add nntp login actions in mod panel 2016-01-12 10:23:36 -05:00
no
84626f6f96 add info for peering over internet with tls 2016-01-07 13:27:43 -05:00
no
3a35dc5575 add tls related stuff to .gitignore 2016-01-07 11:56:08 -05:00
no
13b8a18e21 detect webm/mp4 and set mime type correctly 2016-01-07 09:32:50 -05:00
no
4557503256 for plaintext posts add content-type header 2016-01-07 09:31:11 -05:00
no
689ced2ae4 Merge branch 'master' of https://github.com/majestrate/nntpchan 2016-01-06 16:18:34 -05:00
no
ccc5972e67 add attachment ability to archiver 2016-01-06 16:17:34 -05:00
Jeff
e07260d068 Merge pull request #43 from chen-chan/master
my shitty template btw. enjoy~ :3
2016-01-04 09:49:22 -05:00
chen-chan
7854b0b81d faq update 2016-01-04 14:53:56 +01:00
chen-chan
177e0156cc faq update 2016-01-04 14:50:41 +01:00
chen-chan
10d47779d3 faq update 2016-01-04 14:47:43 +01:00
chen-chan
d26d6ecacb faq update 2016-01-04 14:43:58 +01:00
chen-chan
85200d9284 faq tweak 2016-01-04 14:29:25 +01:00
chen-chan
8bcd0b790c gitignore /go and /srndv2 2016-01-04 13:20:59 +01:00
chen-chan
68e4e9162f rm xmas, change faq, frontpage 2016-01-04 13:19:47 +01:00
chen-chan
05d1290344 minor fix 2 2015-12-23 17:03:40 +01:00
chen-chan
d1bb6b59b0 minor fix 2015-12-23 16:59:18 +01:00
chen-chan
64111298f6 minor fixes 2015-12-23 16:53:36 +01:00
chen-chan
6df6fd807a xmas 2015-12-23 14:25:25 +01:00
chen-chan
d140c9ee99 little tweak: date and buttons 2015-12-23 13:05:58 +01:00
chen-chan
50fafb4531 wrong thread js path 2015-12-23 06:29:01 +01:00
chen-chan
5591b56df0 css and frontpage fixes 2015-12-23 06:08:00 +01:00
chen-chan
6041a7d608 wrong js dir 2015-12-23 05:43:58 +01:00
chen-chan
111522d08e workaroung static not being hosted recursively 2015-12-23 05:04:50 +01:00
chen-chan
7d89ab06c7 chen-chan got its own dir in static 2015-12-23 03:25:52 +01:00
chen-chan
cab35af8c4 merge 2015-12-23 03:03:13 +01:00
chen-chan
5abbe123c3 merge 2015-12-23 02:53:35 +01:00
chen-chan
404d9952f2 merge from upstream 2015-12-23 02:38:08 +01:00
chen-chan
a6b7235b12 add back default empty user.css 2015-12-23 01:40:11 +01:00
chen-chan
55f4461475 rename css file 2015-12-23 01:36:22 +01:00
chen-chan
bb1c6890ac change css filename 2015-12-23 01:33:03 +01:00
chen-chan
e545bab034 new template dir 2015-12-23 01:07:29 +01:00
chen-chan
21ec8e5f3a table css 2015-12-23 01:02:11 +01:00
Jeff
35c6875b00 Merge pull request #38 from chen-chan/patch-2
target="_blank" needs to be after href or it no werk
2015-12-20 21:42:31 -05:00
chen-chan
45f217fa78 target="_blank" needs to be after href or it no werk
tbh smh onii-fam

also figcaption is completely unnecessary here tbh.
2015-12-21 01:58:25 +01:00
Jeff
e6ca1b07ed Merge pull request #35 from 4cdn/patch-3
legibility
2015-11-23 16:54:47 -05:00
4cdn
3e3680c9be legibility 2015-11-23 16:49:05 -05:00
Jeff
7501dae72e Merge pull request #34 from 4cdn/patch-1
table color to one lolz had
2015-11-22 18:42:15 -05:00
4cdn
93328cb480 table color to one lolz had 2015-11-22 16:16:47 -05:00
42 changed files with 752 additions and 70 deletions

12
.gitignore vendored
View File

@@ -14,4 +14,14 @@
articles
# generated files
webroot
webroot
# built binaries
go
srndv2
# private key
*.key
# certificates
certs

View File

@@ -9,7 +9,7 @@ This repository contains resources used by the core daemon which is located [her
Get the dependancies
sudo apt-get update
sudo apt-get --no-install-recommends install imagemagick libsodium-dev ffmpegthumbnailer sox build-essential git golang ca-certificates
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

View File

@@ -1,6 +1,6 @@
## TODO ##
* extra stylesheets
* alternative templates
* more alternative templates
* javascript free mod panel
* liveui
* liveui

BIN
contrib/static/banner_0.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
contrib/static/banner_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
contrib/static/banner_2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -0,0 +1,52 @@
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>nntpchan faq</title></head><body>
<audio loop controls><source src="/static/about.mp3" type="audio/mpeg">[can't play audio.]</audio>
<p>nntpchan faq</p>
<dl>
<dt>What is nntpchan?</dt>
<dd>NNTPCchan is a federated imageboard that spans across several networks including tor, i2p and anonet. There are no central servers so that as long as 1 server is left the forum will continue to function.</dd>
<br>
<dt>How is this different from *chan?</dt>
<dd>NNTPChan is by design invulnerable to global censorship. All moderation is local to each server.</dd>
<br>
<dt>How does moderation work then?</dt>
<dd>Moderation is done with our special tripcodes (ed25519-sha512 signed posts). Anyone can give moderation suggestions, but that doesn't mean anyone will accept them. Those who trust the actions of a moderator can have their frontend whitelist the moderation actions and have them performed without oversight by another moderator.</dd>
<br>
<dt>How can I remove content from nntpchan completely?</dt>
<dd>‾\(._.)/‾ I don't know. You probably can't unless every server agrees to remove the content, even then, nothing prevents someone from reposting it. You can't delete what you post on the internet.</dd>
<br>
<dt>do you allow child porn?</dt>
<dd>no.</dd>
<br>
<dt>Do you allow XYZ content?</dt>
<dd>If it violates USA Law or causes problems with my host, no. Otherwise, probably.</dd>
<br>
<dt>Someone posted something I don't like but it's not illegal</dt>
<dd>That is not my problem. All posts on this site are the responsibility of the individual poster and not the administration of this server</dd>
<br>
<dt>code, bugs, feature requests</dt>
<dd><a href="https://github.com/majestrate/nntpchan/">frontend</a> <a href="https://github.com/majestrate/srndv2/">core</a></dd>
<br></dl>
<p>Please send any gripes/questions/inqueries/suggestions/complaints to ampernand [|at\] gmail {dot} com with subject starting with "nntpchan question"</p>
<hr>
<p>ucavviu7wl6azuw7.onion frontend specific</p>
<dl>
<dt>admin's pubkey</dt>
<dd>06833a90237c61f59558c1726fbe71c63e972722b2cf1147867be286cb020b32<br>
▆☃►☐▣◼◡♵☕◘♁◲◯☾◱♆▾☗▧▢☲♏░◇☆◻♢☆♋▂▋▲</dd>
<br>
<dt>peering</dt>
<dd>just open a thread for now.</dd>
<br>
<dt>rules</dt>
<dd>basically no stuff that will fuck with the functioning of the site.<br>
- stuff that will get me in trouble like cp.<br>
- flood/spam. duplicate posts may also get baleeted.
</dd>
<br>
<dt>guidelines and things to keep in mind</dt>
<dd>
- i don't owe you shiieet. you don't owe me shieet.<br>
- administration style: benevolent dictatorship.
</dd>
</dl>
</body></html>

View File

@@ -0,0 +1,7 @@
body{font-family:monospace}
dl{max-width:84ch}
dd{margin-left:4ch;overflow:auto}
.memearrows{color:green}
pre{margin: 0 0 0 0}
table,th,td{border:1px solid gray}
table {border-collapse:collapse}

View File

@@ -64,6 +64,23 @@ function nntpchan_key_add() {
});
}
function get_nntp_username() {
var e = document.getElementById("nntpchan_nntp_username");
return e.value;
}
function get_nntp_passwd() {
var e = document.getElementById("nntpchan_nntp_passwd");
return e.value;
}
function nntpchan_admin_nntp(method) {
nntpchan_admin(method, {
username: get_nntp_username(),
passwd: get_nntp_passwd()
})
}
function nntpchan_admin_board(method) {
nntpchan_admin(method, {
newsgroup: get_board_target()

View File

@@ -12,3 +12,15 @@ function nntpchan_backlink(shorthash)
elem.value += ">>" + shorthash.substr(0,10) + "\n";
}
}
var banner_count = 3;
// inject a banner into an element
function nntpchan_inject_banners(elem, prefix) {
var n = Math.floor(Math.random() * banner_count);
var banner = prefix + "static/banner_"+n+".jpg";
var e = document.createElement("img");
e.src = banner;
e.id = "nntpchan_banner";
elem.appendChild(e);
}

View File

@@ -45,7 +45,7 @@ pre {
}
td {
background-color: dimgrey;
background-color: #1C1C1C;
}
.board_td {
@@ -59,7 +59,7 @@ td {
#overview_graph {
position: relative;
top: 2px;
background: dimgrey;
background: #1C1C1C;
}
.reply, .ukko_thread_header {
@@ -82,11 +82,11 @@ a:hover , a:visited:hover {
}
a {
color: #0C2FF3;
color: cornflowerblue;
}
a:visited {
color: #5E00A0;
color: #0C2FF3;
}
.navbar {
@@ -98,11 +98,11 @@ a:visited {
z-index: 20;
box-shadow: 0px 1px 20px rgba(0, 0, 0, 0.15);
background: #202331;
color: #616383;
color: lightgray;
}
.navbar-sep {
color: black;
color: darkgray;
}
#postform_container {
@@ -321,3 +321,8 @@ textarea#reply-text {
hr {
padding-bottom: 20px;
}
#nntpchan_banner {
align: center;
}

View File

@@ -0,0 +1,27 @@
{{!
board.mustache, displays the contents of page N of the board
template parameters:
- board ( the model of the current page )
- page ( the page number of the current page )
board has the properties:
- Prefix ( absolute path like //site.tld/ or /path/ )
- Board ( the name of the board )
- Navbar ( a function that renders the navbar, should not be escaped )
- Threads ( a list of Thread Models with the last few replies )
}}
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>{{board.Board}}</title></head><body>
{{{board.Navbar}}}
{{{form}}}
<dl>
<hr>
{{#board.Threads}}
{{{OP.Truncate.RenderPost}}}
{{#Truncate.Replies}}
{{{Truncate.RenderPost}}}
{{/Truncate.Replies}}
<hr>
{{/board.Threads}}
</dl>
</body></html>

View File

@@ -0,0 +1,33 @@
{{!
boardlist.mustache -- full list of every board
template parameters:
- graph ( a list of 4 string tuples: (board, posts_per_hour, posts_per_day, total_posts) )
- frontend ( the name of the frontend )
- prefix ( the site's prefix )
}}
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>{{frontend}} boards</title></head><body>
<table>
<tr>
<th>board</th>
<th>posts per hour</th>
<th>posts per day</th>
<th>total</th>
</tr>
{{# graph}}
<tr>
<td>
<a href="{{prefix}}{{Board}}-0.html">{{Board}}</a>
</td>
<td>
{{Hour}}
</td>
<td>
{{Day}}
</td>
<td>
{{All}}
</td>
</tr>
{{/ graph}}
</table>
</body></html>

View File

@@ -0,0 +1,11 @@
{{!
frontpage.mustache -- template for index.html
template parameters:
- boardgraph ( a boardPageRows instance, see srnd/model.go )
- postgraph ( a postsGraph instance , see srnd/model.go )
- overview ( an overviewModel instance, see srnd/model.go )
- totalposts ( the number of total posts we have ever seen )
- frontend ( the name of the frontend )
- prefix ( the site's prefix )
}}
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>{{frontend}} on nntpchan</title></head><body><p>{{frontend}} on nntpchan</p><p><a href="ukko.html">overboard</a> <a href="{{prefix}}boards.html">boards</a> <a href="{{prefix}}static/chen-chan-faq.html">faq</a></p><dl><dt>last posts:</dt><dd>{{{overview.Render}}}</dd></dl><dl><dt>board stats:</dt><dd><table><tr><th>board</th><th>posts this hour</th><th>posts today</th><th>total</th></tr>{{# boardgraph}}<tr><td><a href="{{prefix}}{{Board}}-0.html">{{Board}}</a></td><td>{{Hour}}</td><td>{{Day}}</td><td>{{All}}</td></tr>{{/ boardgraph}}</table></dd></dl><dl><dt>total stats:</dt><dd>{{{postsgraph.Render}}}</dd></dl><p>{{totalposts}} posts total since 2015-12-23</p></body></html>

View File

@@ -0,0 +1,36 @@
{{!
graph_history.mustache
template parameters:
- history ( a list of PostEntry instances, see srnd/model.go )
}}
<html>
<head>
<meta charset="utf-8"></meta>
<link rel="stylesheet" href="{{prefix}}site.css" />
<link rel="stylesheet" href="{{prefix}}user.css" />
<title> Post History</title>
</head>
<body>
<td>
<table id="history_graph">
<thead>
<tr>
<th>Month</th>
<th>Posts</th>
<th></th>
</tr>
</thead>
<tbody>
{{#history.Scale}}
<tr>
<td>{{Date}}</td>
<td class="history_num">{{Num}}</td>
<td>{{OvercockGraph}}</td>
</tr>
{{/history.Scale}}
</tbody>
</table>
</td>
</body>
</html>

View File

@@ -0,0 +1,15 @@
{{!
keygen.mustache -- page containing a newly generated tripcode
template parameters:
- prefix ( the site prefix )
- public ( the public key in hex )
- secret ( the secret key in hex )
- tripcode ( html version of the public key )
}}
<!doctype html><html><head><title>new tripcode</title></head><body><pre>
new tripcode
secret: {{secret}}
public: {{public}}
tripcode: {{{tripcode}}}
</pre></body></html>

View File

@@ -0,0 +1,7 @@
<!doctype html><html><head><link rel="stylesheet" href="{{prefix}}static/chen-chan.css"><title>login</title></head><body>
<form action="login" method="POST" name="modlogin">
<label for="mod_key">secret</label>
<input type="password" id="mod_key" name="privkey">
<input type="submit" value="login">
</form>
</body></html>

View File

@@ -0,0 +1,9 @@
{{!
modlogin_result.mustache -- shows the result of a login attempt
template parameters:
- prefix ( the site prefix )
- mod_prefix ( the prefix to the mod panel, could be something like https://mod.site.tld/ or /mod/ )
- message ( the message returned from the login attempt )
- fail ( present if the login failed ) // not yet added
}}
<!doctype html><html><head><meta http-equiv="refresh" content="1; {{mod_prefix}}"><title>login</title></head><body><p>{{message}}</p></body></html>

View File

@@ -0,0 +1,79 @@
{{!
modpage.mustache -- the moderator panel when logged in
template parameters:
- prefix ( the site's prefix )
}}
<!doctype html><html><head>
<link rel="stylesheet" href="{{prefix}}static/chen-chan.css">
<!-- yes it uses js -->
<script src="{{prefix}}static/mod.js"></script>
<title>nntpchan mod page</title>
</head><body>
<dl>
<dt>post actions</dt>
<dd>
<div>
<label for="nntpchan_mod_target">target</label>
<input id="nntpchan_mod_target" type="text">
</div>
<div>
<button onclick="nntpchan_ban()">ban (url)</button>
<button onclick="nntpchan_delete()">delete (url)</button>
<button onclick="nntpchan_unban()">unban (ip)</button>
</div>
</dd>
</dl>
<dl>
<dt>key actions</dt>
<dd>
<div>
<label for="nntpchan_board_target">pubkey:</label>
<input type="text" id="nntpchan_key_target" />
</div>
<div>
<button onclick="nntpchan_key_add()">add key</button>
<button onclick="nntpchan_key_del()">remove key</button>
</div>
</dd>
</dl>
<dl>
<dt>board actions</dt>
<dd>
<div>
<label for="nntpchan_board_target">board name:</label>
<input type="text" id="nntpchan_board_target">
</div>
<div>
<button onclick="nntpchan_admin_board('frontend.add')">add board</button>
<button onclick="nntpchan_admin_board('frontend.regen')">regenerate</button>
<button onclick="nntpchan_admin_board('frontend.ban')">ban</button>
<button onclick="nntpchan_admin_board('frontend.unban')">unban</button>
<button onclick="nntpchan_admin_board('frontend.nuke')">nuke</button>
</div>
</dd>
</dl>
<dl>
<dt>lightweight actions</dt>
<dd>
<button onclick="nntpchan_admin('template.reload')">reload all templates</button>
</dd>
</dl>
<dl>
<dt>very load heavy actions, use with care</dt>
<dd>
<div>
<button onclick="nntpchan_admin('frontend.regen')">regenerate all pages</button>
<button onclick="nntpchan_admin('thumbnail.regen')">regenerate all thumbnails</button>
</div>
</dd>
</dl>
<dl>
<dt>status</dt>
<dd>
<div id="nntpchan_mod_result"></div>
<noscript>
<b>enable js to use the mod panel kthx</b>
</noscript>
</dd>
</dl>
</body></html>

View File

@@ -0,0 +1,12 @@
{{!
navbar.mustache -- element on the top of each nod-mod page
TODO: make this not suck, have a board list, have board page list
template parameters:
- name ( the name of whatever resource we are on, board/thread )
- frontend ( the name of the frontend we are on )
- links ( a list of Link Models to display )
- prefix ( site prefix )
}}
<p>{{name}} on {{frontend}} | {{# links}} <a href="{{LinkURL}}">{{Text}}</a> {{/ links}} | <a href="{{prefix}}">front page</a> <a href="{{prefix}}ukko.html">overboard</a></p>

View File

@@ -0,0 +1 @@
no apparently.

View File

@@ -0,0 +1,7 @@
{{! overview.mustache
paramters:
- overview (list of PostModels in order of last posted)
}}
<table><tr><th>date</th><th>board</th><th>subject</th></tr>{{#overview}}<tr><td>{{Date}}</td><td><a href="{{Prefix}}{{Board}}-0.html">{{Board}}</a></td><td><a href="{{PostURL}}">{{Truncate.Subject}}</a></td></tr>{{/overview}}</table>

View File

@@ -0,0 +1,15 @@
<dt id="{{PostHash}}">
<a onclick="nntpchan_backlink('{{ShortHash}}');" title="{{MessageID}}">{{ShortHash}}</a>
{{Date}}
{{#IsI2P}}i2p{{/IsI2P}}{{#IsTor}}tor{{/IsTor}}{{#IsClearnet}}clr{{/IsClearnet}}
{{Subject}}
{{Name}}
{{{Pubkey}}}
<a href="{{PostURL}}">[reply]</a>
</dt>
<dd>
{{{RenderBody}}}
{{#Attachments}}
file: <a href="{{Source}}" target="_blank">{{Filename}}</a><br><br>
{{/Attachments}}
</dd>

View File

@@ -0,0 +1,3 @@
<!doctype html><html><head>
<meta http-equiv="refresh" content="1; {{redirect_url}}"></head>
<body><p>fail: {{reason}}</p></body></html>

View File

@@ -0,0 +1,40 @@
<html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>try again</title></head><body>
<form enctype="multipart/form-data" name="post" method="post">
{{#attachment}}
<input type="hidden" name="attachment_data" value="{{attachment}}">
<input type="hidden" name="attachment_filename" value="{{attachment_filename}}">
<input type="hidden" name="attachment_mime" value="{{attachment_type}}">
{{/attachment}}
<input type="hidden" name="reference" value="{{reference}}">
<input type="hidden" name="name" value="{{name}}">
<input type="hidden" name="subject" value="{{subject}}">
<input type="hidden" name="captcha_id" value="{{captcha_id}}">
<input type="hidden" name="message" value="{{message}}">
<div id="postform-outer">
<div id="postform-inner">
<div>{{fail_message}}</div>
<table class="postform">
<tbody>
<tr>
<th>
Captcha
</th>
<td>
<img id="captcha_img" src="{{prefix}}captcha/{{captcha_id}}.png" alt="captcha" />
</td>
</tr>
<tr>
<th>
Solution
</th>
<td>
<input type="text" name="captcha" />
<input type="submit" value="Post" class="button" />
</td>
</tr>
</tbody>
</table>
</div>
</div>
</form>
</body></html>

View File

@@ -0,0 +1,7 @@
{{!
post_success.mustache -- shown when we do a successful post
template parameters:
- redirect_url ( the url of the next page we should redirect to )
- message_id ( the value of the Message-ID header in the post we made, the truncated sha1 of this is the >>posthash )
}}
<!doctype html><html><head><meta http-equiv="refresh" content="2; {{redirect_url}}"></head><body><pre>posted as {{message_id}}</pre></body></html>

View File

@@ -0,0 +1,20 @@
{{!
postform.mustache -- the form for posting
template parameters:
- post_url ( the url of the post form )
- reference ( the post we are replying to, or empty string if it's an op )
- button ( the text for the reply button )
}}
<form action="{{post_url}}" enctype="multipart/form-data" name="post" method="post" style="overflow:auto">
<input type="hidden" name="reference" value="{{reference}}">
<textarea id="postform_message" name="message" placeholder="text" cols="40" rows="10" style="float:left" ></textarea><br>
<div style="float:left">
<input type="file" name="attachment"><br>
<input type="text" name="subject" placeholder="subject"><br>
<input type="text" name="name" placeholder="name"><br>
<input type="text" name="captcha" placeholder="captcha"><br>
<input type="submit" value="{{button}}" class="button"><br>
</div>
<img id="captcha_img" src="{{prefix}}captcha/img" alt="captcha" style="float:left">
</form>

View File

@@ -0,0 +1,7 @@
{{!
posts graph.mustache -- post frequence graph
parameters:
* graph - a postsGraph instance (see srnd/model.go)
}}
<table><tr><th>date</th><th>posts</th><th>cock</th></tr>{{#graph.Scale}}<tr><td>{{Day}}</td><td>{{Num}}</td><td>{{OvercockGraph}}</td></tr>{{/graph.Scale}}</table>

View File

@@ -0,0 +1,23 @@
{{!
thread.mustache -- renders to a thread-*.html page, shows the entire thread
template parameters:
- board ( the Board Model of the board this thread was posted in )
- thread ( the Thread Model of the current thread being rendered )
- form ( the post form markup )
Thread Model attributes:
- OP , the Post Model of the original poster
- Replies , a list of all the replies or empty if none
- Board , the name of the Board this thread is on
- BoardURL , the url that points to the board index page
}}
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>{{thread.OP.Subject}}</title><script src="{{thread.Prefix}}static/nntpchan.js"></script></head><body>
{{{thread.Navbar}}}
{{{form}}}
<dl>
{{{thread.OP.RenderPost}}}
{{# thread.Replies}}
{{{RenderPost}}}
{{/ thread.Replies}}
</dl>
</body></html>

View File

@@ -0,0 +1,19 @@
{{!
ukko.mustache -- overboard, contains the last threads posted regardless of newsgroup
template parameters:
- prefix ( site prefix )
- threads ( a list of Thread Models that represent the latest threads )
}}
<!doctype html><html><head><link rel="stylesheet" href="/static/chen-chan.css"><title>ukko/overboard</title></head><body>
<a href="/">frontpage</a>
{{#threads}}
<hr>
<p>posted on <a href="{{{BoardURL}}}">{{OP.Board}}</a></p>
<dl>
{{{OP.Truncate.RenderPost}}}
{{#Truncate.Replies}}
{{{Truncate.RenderPost}}}
{{/Truncate.Replies}}
</dl>
{{/threads}}
</body></html>

View File

@@ -24,7 +24,10 @@
<!-- begin navbar -->
{{{board.Navbar}}}
<!-- end navbar -->
<center>
<div id="nntpchan_banner">
</div>
</center>
<!-- postform -->
<div id="postform_container">
{{{form}}}
@@ -43,5 +46,11 @@
</div>
{{/board.Threads}}
</div>
<script type="text/javascript">
var e = document.getElementById("nntpchan_banner");
nntpchan_inject_banners(e, "{{board.Prefix}}");
</script>
</body>
</html>

View File

@@ -13,6 +13,7 @@
<head>
<link rel="stylesheet" href="{{prefix}}static/site.css" />
<link rel="stylesheet" href="{{prefix}}static/user.css" />
<script src="{{prefix}}static/nntpchan.js" type="text/javascript"></script>
<title> {{frontend}} on nntpchan </title>
</head>
<body>
@@ -28,6 +29,8 @@
<h3>Fork on github: <a href="https://github.com/majestrate/nntpchan/">frontend</a> and <a href="https://github.com/majestrate/srndv2/">core</a></h3>
<h4>We've Had {{totalposts}} Posts Since August 01 2015 </h4>
</div>
<div id="nntpchan_banner">
</div>
<div class="index-inner">
<table>
<tbody>
@@ -71,5 +74,10 @@
</div>
</div>
</center>
<script type="text/javascript">
var e = document.getElementById("nntpchan_banner");
nntpchan_inject_banners(e, "{{prefix}}");
</script>
</body>
</html>

View File

@@ -39,11 +39,29 @@
</div>
</div>
<hr />
<div>
<div> nntp login </div>
<div>
<label for="nntpchan_nntp_username">username:</label>
<input id="nntpchan_nntp_username" />
</div>
<div>
<label for="nntpchan_nntp_passwd">password:</label>
<input type="password" id="nntpchan_nntp_passwd" />
</div>
<div>
<button onclick="nntpchan_admin_nntp('nntp.login.add')">add user</button>
</div>
<div>
<button onclick="nntpchan_admin_nntp('nntp.login.del')">remove user</button>
</div>
</div>
<hr />
<div>
<div> board actions </div>
<div>
<label for="nntpchan_board_target">board name:</label>
<input type="text" id="nntpchan_board_target" />
<input id="nntpchan_board_target" />
</div>
<div>
<button onclick="nntpchan_admin_board('frontend.add')">add board</button>

View File

@@ -16,7 +16,7 @@
{{#Attachments}}
<figure>
<figcaption>
<a target="_blank" href="{{Source}}" title="{{Filename}}"><img src="{{Thumbnail}}" alt="{{Filename}}" /></a>
<a href="{{Source}}" title="{{Filename}}" target="_blank"><img src="{{Thumbnail}}" alt="{{Filename}}" /></a>
</figcaption>
</figure>
{{/Attachments}}

View File

@@ -5,6 +5,7 @@
- post_url ( the url of the post form )
- reference ( the post we are replying to, or empty string if it's an op )
- button ( the text for the reply button )
- files ( bool, do we allow attachments ? )
}}
<form action="{{post_url}}" enctype="multipart/form-data" name="post" method="post">
<input type="hidden" name="reference" value="{{reference}}" />
@@ -37,6 +38,7 @@
<textarea id="postform_message" name="message" cols=40 rows=5></textarea>
</td>
</tr>
{{#files}}
<tr>
<th>
File
@@ -45,8 +47,9 @@
<input id="postform_attachment" type="file" name="attachment" />
</td>
</tr>
{{/files}}
<tr>
<th>
<th>
Get Dubs
</th>
<td>

View File

@@ -17,7 +17,7 @@
<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" />
<script type="text/javascript" src="{{thread.Prefix}}static/nntpchan.js"></script>
<script src="{{thread.Prefix}}static/nntpchan.js" type="text/javascript"></script>
<title> {{thread.OP.Subject}} </title>
</head>
<body>
@@ -25,7 +25,10 @@
<!-- begin navbar -->
{{{thread.Navbar}}}
<!-- end navbar -->
<center>
<div id="nntpchan_banner">
</div>
</center>
<!-- postform -->
<div id="postform_container">
{{{form}}}
@@ -41,5 +44,11 @@
{{/ thread.Replies}}
</div>
<br/>
<script type="text/javascript">
var e = document.getElementById("nntpchan_banner");
nntpchan_inject_banners(e, "{{thread.Prefix}}");
</script>
</body>
</html>

View File

@@ -11,8 +11,12 @@
<link rel="stylesheet" href="{{prefix}}static/site.css" />
<link rel="stylesheet" href="{{prefix}}static/user.css" />
<script type="text/javascript" src="{{prefix}}static/nntpchan.js"></script>
</head>
</head>
<body>
<center>
<div id="nntpchan_banner">
</div>
</center>
<div id="ukko_threads">
{{#threads}}
<!--
@@ -30,6 +34,11 @@
{{/Truncate.Replies}}
</div>
{{/threads}}
</div>
</div>
<script type="text/javascript" >
var e = document.getElementById("nntpchan_banner");
nntpchan_inject_banners(e, "{{prefix}}");
</script>
</body>
</html>

44
contrib/tools/api/post.js Normal file
View File

@@ -0,0 +1,44 @@
var http = require('http');
req = {
message: "test api",
frontend: "benis.tld",
name: "benisname",
subject: "ayyyyyy testing api",
/*
file: {
name: "benis.gif",
type: "image/gif",
data: // base64'd string here
},
*/
email: "sage",
ip: "8.8.8.8",
dubs: false,
newsgroup: "overchan.test",
// only include if we are replying to someone
reference: "<b7dee1453564515@benis.tld>"
}
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();

View File

@@ -8,6 +8,8 @@ import io
import nntplib
import time
import urllib.parse
import base64
import random
class Article:
"""
@@ -25,7 +27,6 @@ class Article:
self.board = board
self.site = site
self.messageID = self.genMessageID(j['no'])
self.attachments = list()
def formatDate(self):
return datetime.datetime.utcfromtimestamp(self.j['time']).strftime(self.timeFormat)
@@ -62,6 +63,11 @@ class Article:
"Path: {}\n").format(self.subject(), self.name(), self.formatDate(), self.group(), self.messageID, self.site)
if self.j['resto'] > 0:
hdr += "References: {}\n".format(self.genMessageID(self.j['resto']))
if 'filename' in self.j:
hdr += 'Mime-Version: 1.0\n'
hdr += 'Content-Type: multipart/mixed; boundary="{}"\n'.format(self.boundary)
else:
hdr += 'Content-Type: text/plain; encoding="UTF-8"\n'
return hdr
def bodyPlain(self):
@@ -70,10 +76,35 @@ class Article:
return "{}\n{}".format(self.header(), msg)
def bodyMultipart(self):
pass
self.boundary = '========{}'.format(random.randint(0, 10000000))
msg = self.header() + '\n'
msg += '--{}\n'.format(self.boundary)
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 += '\n--{}--\n'.format(self.boundary)
return msg
def body(self):
if len(self.attachments) > 0:
if 'filename' in self.j:
return self.bodyMultipart()
else:
return self.bodyPlain()
@@ -124,10 +155,11 @@ class Getter:
except:
pass
else:
for t in j['threads']:
posts = t['posts']
for post in posts:
yield Article(post, self.board, self.site)
if 'threads' in j:
for t in j['threads']:
posts = t['posts']
for post in posts:
yield Article(post, self.board, self.site)

11
doc/api.md Normal file
View File

@@ -0,0 +1,11 @@
# nntpchan jsonrpc api
To enable set the following in `srnd.ini` section `frontend`
[frontend]
...
json-api = 1
json-api-username = something-really-long
json-api-password = somethine-different-but-also-very-long
see the example tool at `contrib/tools/api/post.js`

20
doc/cli.md Normal file
View File

@@ -0,0 +1,20 @@
# command line interface
# rebuild all thumbnails
srndv2 tool rethumb
# generate a new tripcode keypair
# print out to stdout
srndv2 tool keygen
# add an nntp login
srndv2 tool nntp add-login username password
# remove an nntp login
srndv2 tool nntp del-login username
# add public key to moderation trust
srndv2 tool mod add publickeygoeshere
# remove public key from moderation trust
srndv2 tool mod del publickeygoeshere

View File

@@ -4,7 +4,92 @@
In order to actually be distributed, you need another person to sync posts with, otherwise what's the point right?
Right now peering information is private, there is no link level authentication (yet) so everything is done via either a vpn tunnel or a tor hidden service.
### Peering over the regular internet with tls ###
Requirements:
* Each Side's server must have a domain name
* Each Side must have each other's certificates (.crt files) in the `certs` folder
* Each Side's `srnd.ini` crypto section must have entry `tls-hostname = domain.tld` where domain.tld is the domain name of the server it is on
* Each Side's `srnd.ini` nntp section must have entry `require_tls = 1`
If Alice owns `nntp.alice.net` and Bob owns `nntp.bob.com` and are both using port 1199 the configs for each side are as follows:
# alice's srnd.ini crypto section
...
[crypto]
tls-hostname = nntp.alice.net
tls-trust-dir = certs
tls-keyname = overchan-alice
# alice's feeds.ini
[feed-bob]
host = nntp.bob.com
port = 1199
[bob]
overchan.* = 1
ctl = 1
# bob's srnd.ini crypto section
...
[crypto]
tls-hostname = nntp.bob.com
tls-trust-dir = certs
tls-keyname = overchan-bob
# bob's feeds.ini
[feed-alice]
host = nntp.alice.net
port = 1199
[alice]
overchan.* = 1
ctl = 1
each side's `certs` directory contains 2 files:
* overchan-alice-nntp.alice.net.crt (alice's certificate)
* overchan-bob-nntp.bob.com.crt (bob's certificate)
Alice keeps `overchan-alice-nntp.alice.net.key` secret and never shares it
Bob keeps `overchan-bob-nntp.bob.com.key` secret and never shares it
### Peering Authentication with passwords ###
adding / removing credentials via the command line:
# add an nntp login via command line
srndv2 tool nntp add-login user-name-here pass-word-here
# remove an nntp login via command line
srndv2 tool nntp del-login user-name-here
exmaple feeds.ini:
# section pair in feeds.ini
# connects to nntp.something.tld:1199 and authenticates with a username and password
# sync = 1 makes you download all applicable posts from the remote server on startup
[feed-authenticated]
host = nntp.something.tld
port = 1199
username = user-user-here
password = pass-word-here
sync = 1
[authenticated]
overchan.* = 1
ctl = 1
### Peering over tor ###
@@ -24,6 +109,8 @@ restart/reload tor then
This is your in feed address
If you use an onion with tls, `srnd.ini` crypto section should have the entry `tls-hostname = youroniongoeshere.onion`. If you don't use tls NEVER disclose the onion address to anyone not trusted.
Then to peer with someone over tor add this to you feeds.ini
[feed-ourpeer.onion]
@@ -38,50 +125,6 @@ Then to peer with someone over tor add this to you feeds.ini
ctl=1
### Peering over cjdns ###
Set up cjdns, read more [here](https://github.com/cjdelisle/cjdns/blob/master/doc/configure.md#connection-interfaces)
git clone https://github.com/cjdelisle/cjdns
cd cjdns && ./do
./cjdroute --genconf >> cjdroute.conf
./cjdroute < cjdroute.conf
Get your ipv6 address for cjdns
ip addr show tun0
Edit srnd.ini to bind nntp on that ipv6 address, make sure to use the square braces `[` and `]`
[nntp]
...
bind=[xxxx:xxxx:xxxx:xxx:xx....]:1199
Say you have 2 friends at fc33:3:3::aadd and fc03:9f:123::a3df.
Add to feeds.ini the following:
[feed-bob]
host=[fc33:3:3::aadd]
port=1199
proxy-type=none
[bob]
overchan=1
ctl=1
[feed-charlie]
host=[fc03:9f:123::a3df]
port=1199
proxy-type=none
[charlie]
overchan=1
ctl=1
## Options ##
#### You need one connection and one settings block for each connection ####
@@ -94,6 +137,8 @@ Here is an example entry in feeds.ini
proxy-type=socks4a
proxy-host=127.0.0.1
proxy-port=9050
username=somerandomusername
password=somerandompassword
[them.onion]
overchan=1