222 Commits
dank ... 0.4.0

Author SHA1 Message Date
Jeff Becker
9a75911ab7 update mod ui 2016-03-12 11:24:04 -05:00
Jeff Becker
8181d174a5 add hr in connection state 2016-03-12 10:18:43 -05:00
Jeff Becker
c618440878 span -> div 2016-03-12 10:16:45 -05:00
Jeff Becker
0bc6298cc0 update mod ui to have more details 2016-03-12 10:15:56 -05:00
Jeff Becker
93b452c497 update mod ui feed connection elements 2016-03-12 10:13:17 -05:00
Jeff Becker
b2d46c9021 fix typo 2016-03-12 09:45:31 -05:00
Jeff Becker
f972d91137 update mod panel connections view 2016-03-12 09:44:51 -05:00
Jeff Becker
f8a6b32b5f add expiration of orphaned articles command to mod page 2016-03-12 08:29:57 -05:00
Jeff Becker
439ab7583a add synchronize feeds command in mod panel 2016-03-12 07:56:29 -05:00
Jeff Becker
5800b1bf1d add note about redis version 2016-03-11 20:16:10 -05:00
Jeff Becker
1ba53b7688 update archiver to support multiple attachments 2016-03-10 10:07:19 -05:00
Jeff Becker
dd2eb90230 update post fail page 2016-03-09 13:27:34 -05:00
Jeff Becker
2319327917 update older templates to be aware of themes 2016-03-09 13:23:58 -05:00
Jeff Becker
89dfe68b32 update bloodgod theme for 404 page 2016-03-09 13:21:19 -05:00
Jeff Becker
c4dadd21fc update 404 page 2016-03-09 13:16:46 -05:00
Jeff Becker
812d7cfd9d 404 page 2016-03-09 12:54:21 -05:00
Jeff Becker
415f0d6e39 update install.sh to have build options passed into build.sh 2016-03-09 10:59:22 -05:00
Jeff Becker
08d97147b8 add simple install script 2016-03-09 10:41:24 -05:00
Jeff Becker
23614275eb spacing 2016-03-09 10:05:52 -05:00
Jeff Becker
1eca5c59e3 update readme irc links 2016-03-09 10:05:23 -05:00
Jeff Becker
91953148e8 update readme to point to build instructions 2016-03-09 08:41:37 -05:00
Jeff Becker
c5a5fb57d9 update build documentation 2016-03-09 08:40:18 -05:00
Jeff Becker
5b8d338840 add --disable-redis option to build.sh 2016-03-09 08:36:44 -05:00
Jeff Becker
5bc7c92e71 only apply theme if parameters are correct 2016-03-08 20:35:03 -05:00
Jeff Becker
f32bd8c946 update dayman theme 2016-03-08 18:18:28 -05:00
Jeff Becker
ca333e06ac update dayman theme 2016-03-08 18:16:27 -05:00
Jeff Becker
9aab7addb1 update dayman theme 2016-03-08 18:11:48 -05:00
Jeff Becker
0b984d0dcd color -> background-color 2016-03-08 18:10:03 -05:00
Jeff Becker
73b254367f update dayman theme 2016-03-08 18:09:27 -05:00
Jeff Becker
a9c09e57e9 dayman css initial 2016-03-08 18:02:33 -05:00
Jeff Becker
d8b57e2189 add default theme (yostuba) option 2016-03-08 17:02:23 -05:00
Jeff Becker
7ce22cefb7 try again inverting image colors via css 2016-03-08 16:58:47 -05:00
Jeff Becker
2de555f176 invert origin image color in bloodgod theme 2016-03-08 16:53:29 -05:00
Jeff Becker
68c071e318 don't use main/onload for theme application 2016-03-08 10:45:39 -05:00
Jeff Becker
077b61270c navbar on front page 2016-03-08 08:42:52 -05:00
Jeff Becker
5975383349 have navbar theme changer text underlined 2016-03-08 08:35:34 -05:00
Jeff Becker
46ca31066f add hover for navbar theme changers 2016-03-08 08:34:07 -05:00
Jeff Becker
9db627d07f update themes to be more consistant 2016-03-08 08:31:12 -05:00
Jeff Becker
014dbdfa95 add navbar to ukko 2016-03-08 08:25:31 -05:00
Jeff Becker
ea06f5498f add nntpchan.js stuff to mod panel 2016-03-08 08:13:57 -05:00
Jeff Becker
c2d60063ee add onload to modpage 2016-03-08 08:13:00 -05:00
Jeff Becker
0ebd2241e5 fix mod.js error 2016-03-08 07:25:54 -05:00
Jeff Becker
0aca177c86 fix color in bloodgod theme 2016-03-08 07:24:29 -05:00
Jeff Becker
9bb45cd896 update bloodgod theme 2016-03-08 07:23:18 -05:00
Jeff Becker
7458a884d5 add onload to frontpage too 2016-03-08 07:17:48 -05:00
Jeff Becker
6392a606c4 add onload to body 2016-03-07 21:00:54 -05:00
Jeff Becker
693bcdeffd try fixing localstorage again 2016-03-07 20:57:14 -05:00
Jeff Becker
81a398ab26 don't check for non existant key in localstorage 2016-03-07 20:55:46 -05:00
Jeff Becker
7296bc6944 fix localstorage 2016-03-07 20:55:05 -05:00
Jeff Becker
e97c4bab53 fix onload 2016-03-07 20:51:41 -05:00
Jeff Becker
2c03b8fd6b persist theme changes 2016-03-07 20:50:58 -05:00
Jeff Becker
2f3742fa7c update bloodgod theme 2016-03-07 20:41:10 -05:00
Jeff Becker
ff816fd556 update bloodgod theme 2016-03-07 20:37:38 -05:00
Jeff Becker
585d4cbff1 fix up bloodgod theme 2016-03-07 20:35:28 -05:00
Jeff Becker
0d388b19ee have bloodgod theme include buttons 2016-03-07 20:34:19 -05:00
Jeff Becker
a8e870a099 update bloodgod theme to include inputs and textares 2016-03-07 20:32:08 -05:00
Jeff Becker
32c4dcbe69 update bloodgood theme to apply to navbar 2016-03-07 20:29:00 -05:00
Jeff Becker
a3571f541b fix bloodgod theme background 2016-03-07 20:27:14 -05:00
Jeff Becker
39dbe314d6 ammend theme changing 2016-03-07 20:25:29 -05:00
Jeff Becker
63e2614983 try fixing theme switcher 2016-03-07 20:21:20 -05:00
Jeff Becker
0623077a40 add more themes and support for switching themes 2016-03-07 20:18:28 -05:00
Jeff Becker
f05d43af89 fix 2016-03-07 12:05:52 -05:00
Jeff Becker
68b73ff1dd fix 2016-03-07 12:03:27 -05:00
Jeff Becker
0613350420 fix 2016-03-07 12:00:32 -05:00
Jeff Becker
37af910c89 more nntp feed stuffs 2016-03-07 11:59:33 -05:00
Jeff Becker
6286a6529c disable checking for mod handler 2016-03-07 11:50:16 -05:00
Jeff Becker
51bdf9609f setinterval was backwards 2016-03-07 11:44:42 -05:00
Jeff Becker
b5d60f1431 syntax error 2016-03-07 11:43:11 -05:00
Jeff Becker
56f8fc8b91 add nntpchan feed ticker to mod panel 2016-03-07 11:42:21 -05:00
Jeff Becker
e0de5dfbf5 russian translations, thanks siger 2016-03-01 18:30:20 -05:00
Jeff Becker
d122da98b5 float: left for attachments 2016-02-29 09:07:42 -05:00
Jeff Becker
e6a38af5ee sorround attachments in div 2016-02-29 09:06:13 -05:00
Jeff Becker
abf3da5900 multiple files 2016-02-29 08:35:26 -05:00
Jeff Becker
a40aad33d1 * add 2 file support
* TODO: add nicer widget for multifile
2016-02-29 08:14:19 -05:00
Jeff Becker
9a6f3ef4ed add portugeese translations, thanks pyr 2016-02-28 10:16:47 -05:00
Jeff Becker
372a8767ee add es tranlsations, thanks trolly 2016-02-28 09:47:19 -05:00
Jeff
f7a31012e8 Merge pull request #48 from ZiRo-/master
Add internationalization
2016-02-28 08:13:55 -05:00
ZiRo
5cf11d50d4 Fix date format 2016-02-28 14:00:22 +01:00
ZiRo
a4f3e4ffa4 Fix date format 2016-02-28 13:59:38 +01:00
ZiRo
60de698f2c Add German translation 2016-02-28 13:57:51 +01:00
ZiRo
1c4f4630c2 localize templates 2016-02-28 13:40:16 +01:00
ZiRo
9974628f62 Make it possible to add more parameters to post template 2016-02-28 10:19:55 +01:00
ZiRo
2ea928417d Localize time formats 2016-02-28 09:48:07 +01:00
ZiRo
eede0c55dc Merge branch 'master' of github.com:ZiRo-/nntpchan 2016-02-28 08:55:33 +01:00
ZiRo
c6780cfd27 Merge remote-tracking branch 'upstream/master' 2016-02-28 08:54:23 +01:00
ZiRo
34b2e18587 Add dummy translation files 2016-02-28 08:54:05 +01:00
Jeff
38d3bc4481 Merge pull request #47 from ZiRo-/patch-1
Add RPC
2016-02-26 07:53:49 -05:00
ZiRo-
e556d6d2be Add RPC 2016-02-25 20:25:10 +01:00
ZiRo-
22a3564f22 Merge pull request #1 from majestrate/master
rebase
2016-02-25 20:02:06 +01:00
Jeff Becker
b695d97e82 even out front page 2016-02-22 07:39:06 -05:00
Jeff Becker
64e4c3320d fix front page 2016-02-22 07:32:49 -05:00
Jeff Becker
7c7d07434d undo changes with post form 2016-02-21 17:08:38 -05:00
Jeff Becker
d2b9e76389 update templates 2016-02-21 16:51:56 -05:00
Jeff Becker
f91bd642a5 fix moderate.js 2016-02-20 09:42:22 -05:00
Jeff Becker
9459e1758d fix moderate.js tool 2016-02-20 09:41:03 -05:00
Jeff Becker
24b2bd8e15 add moderate example script 2016-02-20 09:35:20 -05:00
Jeff
8ad13c8e45 Merge pull request #46 from ZiRo-/master
add images to catalog; style catalog properly
2016-02-20 13:54:16 +00:00
ZiRo
c6e6c2e5d6 Catalog improvements 2016-02-20 11:16:54 +01:00
Jeff
9690156fbf Merge pull request #45 from ZiRo-/master
Add catalog
2016-02-19 15:57:01 +00:00
ZiRo
dea611c1ba initial for catalog 2016-02-19 16:48:41 +01:00
Jeff Becker
0e0f35e6dc fix legal footer 2016-02-17 14:13:58 -05:00
Jeff Becker
5370898da9 * add legal notice
* fix front page graph
2016-02-17 14:10:50 -05:00
ZiRo
1020fae1dd Add Board titles 2016-02-17 15:31:28 +01:00
ZiRo
6bcfff0269 post form fixes 2016-02-17 15:06:00 +01:00
ZiRo
5fbf75a77d Add update link 2016-02-17 14:59:39 +01:00
ZiRo
86744c9349 fix posting form 2016-02-17 14:51:25 +01:00
ZiRo
24b6d87381 add page list to the bottom of board pages 2016-02-17 11:30:19 +01:00
ZiRo
649cc96269 add footer links to threads 2016-02-17 10:53:20 +01:00
ZiRo
a9e377563d Fix board list a bit 2016-02-17 10:27:16 +01:00
ZiRo
9229aa62bd Merge remote-tracking branch 'upstream/master' 2016-02-16 18:35:34 +01:00
ZiRo
f9c9028a0b The posts and threads are now pretty much done 2016-02-16 16:52:20 +01:00
ZiRo
5fa12dcda8 some more CSS fuckery 2016-02-16 16:37:02 +01:00
ZiRo
8c0a4ac6b0 crop i2p icon 2016-02-16 14:56:59 +01:00
ZiRo
bd279547d2 some css fuckery 2016-02-16 14:48:56 +01:00
Jeff Becker
1ad6432576 make reply button/link obvious 2016-02-16 08:32:51 -05:00
ZiRo
4b007fa759 Use 8chin post borders 2016-02-16 13:59:10 +01:00
ZiRo
abe985b6c5 Make origin icon smaller 2016-02-16 13:47:56 +01:00
ZiRo
6091934884 Make origin icon smaller 2016-02-16 13:47:30 +01:00
ZiRo
7db701b23a Don't use a maring for threads 2016-02-16 13:42:28 +01:00
Jeff Becker
00816c1a95 rename mod action 2016-02-15 17:04:59 -05:00
Jeff Becker
713f8a7d19 fix up ukko 2016-02-15 17:02:38 -05:00
Jeff Becker
da42b8fc7d fix ukko more 2016-02-15 17:00:35 -05:00
Jeff Becker
27bf7de803 style tweaks 2016-02-15 16:55:36 -05:00
Jeff Becker
4fd443dce4 tweaks 2016-02-15 16:53:17 -05:00
Jeff Becker
f8d3f85a4d fix typos 2016-02-15 16:52:38 -05:00
Jeff Becker
007851056f fix ukko 2016-02-15 16:50:52 -05:00
Jeff Becker
f97b5a56e5 uncomment out ukko threads header 2016-02-15 16:48:18 -05:00
Jeff Becker
7495c3e843 fix bad end tag 2016-02-15 16:44:35 -05:00
Jeff Becker
713ff950e7 fix origin icon more 2016-02-15 16:42:42 -05:00
Jeff Becker
64a7a6e6aa fix origin icons 2016-02-15 16:36:56 -05:00
Jeff Becker
6aa9475c91 * move origin image to be inside postheader
* style tweaks
2016-02-15 16:29:54 -05:00
Jeff Becker
a9ac1207c0 * add thumnail class to post thumbnails
* fix typo in css
2016-02-15 15:51:17 -05:00
ZiRo
539033ec6d looking pretty good by now 2016-02-15 21:20:37 +01:00
ZiRo
80041baf1e fix some colors 2016-02-15 20:00:56 +01:00
ZiRo
b83b21df59 some more styling 2016-02-15 19:04:03 +01:00
ZiRo
69c30e0685 no more br 2016-02-15 18:42:46 +01:00
ZiRo
0ed2bad9f1 no more rounded rectangles, stupid boarders or shadows 2016-02-15 18:38:32 +01:00
ZiRo
41d3cb467b seperator line for threads 2016-02-15 18:26:30 +01:00
ZiRo
476ae002c2 beginn style change 2016-02-15 18:14:22 +01:00
ZiRo
6f0b518391 ... and No. for everyone 2016-02-15 17:20:41 +01:00
ZiRo
f673a10768 Reply only for OP 2016-02-15 17:17:00 +01:00
ZiRo
8668d1aa08 fix backlinks & CSS classes 2016-02-15 17:06:59 +01:00
ZiRo
d2babe367b use proper timestamps + fix double prefix
This has the benefit that modern browsers see timestamps in their local time zone
2016-02-15 16:13:28 +01:00
ZiRo
3b5937f2d9 Add my rebuild script to gitignore 2016-02-15 15:54:43 +01:00
Jeff Becker
1896060218 fix post template to include prefix 2016-02-13 17:26:00 -05:00
Jeff Becker
9d2461c716 make build.sh verbose when doing go get 2016-02-09 09:02:33 -05:00
Jeff Becker
85d60a1928 fix up more 2016-02-08 15:05:57 -05:00
Jeff Becker
6eb42d4cf7 fix up lynxchan migrate script such that it exits 2016-02-08 14:09:30 -05:00
Jeff Becker
37df9ef131 fixes to migration script 2016-02-08 13:47:06 -05:00
Jeff Becker
450d07d6e5 fix typo 2016-02-08 13:10:26 -05:00
Jeff Becker
047a63ec20 add initial lynxhub importer 2016-02-08 12:42:25 -05:00
Jeff Becker
3821562cf6 add redis database documentation 2016-02-07 09:36:46 -05:00
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
78 changed files with 2595 additions and 360 deletions

18
.gitignore vendored
View File

@@ -8,10 +8,24 @@
.\#*
# srnd config files
*.ini
srnd.ini
feeds.ini
# default article store directory
articles
# generated files
webroot
webroot
# built binaries
go
srndv2
# private key
*.key
# certificates
certs
rebuild.sh

View File

@@ -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 ffmpegthumbnailer 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:

View File

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

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 B

After

Width:  |  Height:  |  Size: 135 B

View 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);
}

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}

21
contrib/static/dayman.css Normal file
View 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;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
contrib/static/maymface.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@@ -64,25 +64,48 @@ function nntpchan_key_add() {
});
}
function get_nntp_username() {
var e = document.getElementById("nntpchan_nntp_username");
return e.value;
}
function get_nntp_passwd() {
var e = document.getElementById("nntpchan_nntp_passwd");
return e.value;
}
function nntpchan_admin_nntp(method) {
nntpchan_admin(method, {
username: get_nntp_username(),
passwd: get_nntp_passwd()
})
}
function nntpchan_admin_board(method) {
nntpchan_admin(method, {
newsgroup: get_board_target()
})
}
function nntpchan_admin(method, param) {
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
})
@@ -119,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) {
@@ -154,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) {

View File

@@ -12,3 +12,45 @@ 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);
}
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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -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: dimgrey;
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: dimgrey;
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: #0C2FF3;
.board_header_catalog {
text-align: center;
margin-top: 1em;
}
a:visited {
color: #5E00A0;
.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: #616383;
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.15);
border-bottom: 1px solid;
background: #D6DAF0;
color: #34345C;
}
.navbar-sep {
color: black;
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,6 +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;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

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

@@ -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>

View File

@@ -16,15 +16,20 @@
<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 -->
<center>
<div id="nntpchan_banner">
</div>
</center>
<div class="board_header">{{board.Board}}</div>
<div class="board_header_catalog"><a href="{{board.Prefix}}catalog-{{board.Name}}.html"> {{#i18n.Translations}}{{catalog_label}}{{/i18n.Translations}} </a></div>
<!-- postform -->
<div id="postform_container">
{{{form}}}
@@ -33,15 +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>

View File

@@ -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>

View 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>

View File

@@ -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,10 +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">
@@ -28,23 +30,27 @@
<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>
<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>
@@ -67,9 +73,18 @@
</tr>
</tbody>
</table>
{{{overview.Render}}}
{{{overview}}}
</div>
</div>
</center>
<script type="text/javascript">
var e = document.getElementById("nntpchan_banner");
nntpchan_inject_banners(e, "{{prefix}}");
</script>
<hr/>
<footer>
<p class="legal">All posts on this site are the responsibility of the individual poster and not the administration, pursuant to 47 U.S.C. § 230.</p>
<p class="legal">To make a DMCA request or report illegal content, please contact the administration</p>
</footer>
</body>
</html>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -7,78 +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> board actions </div>
<div> {{#i18n.Translations}}{{nntp_login_label}}{{/i18n.Translations}} </div>
<div>
<label for="nntpchan_board_target">board name:</label>
<input type="text" id="nntpchan_board_target" />
<label for="nntpchan_nntp_username">{{#i18n.Translations}}{{username}}{{/i18n.Translations}}:</label>
<input id="nntpchan_nntp_username" />
</div>
<div>
<button onclick="nntpchan_admin_board('frontend.add')">add board</button>
<label for="nntpchan_nntp_passwd">{{#i18n.Translations}}{{password}}{{/i18n.Translations}}:</label>
<input type="password" id="nntpchan_nntp_passwd" />
</div>
<div>
<button onclick="nntpchan_admin_board('frontend.regen')">regenerate</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')">{{#i18n.Translations}}{{remove_user_prompt}}{{/i18n.Translations}}</button>
</div>
</div>
<hr />
<div>
<div> {{#i18n.Translations}}{{board_actions_label}}{{/i18n.Translations}} </div>
<div>
<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')">{{#i18n.Translations}}{{add_board_prompt}}{{/i18n.Translations}}</button>
</div>
<div>
<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>

View File

@@ -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 />

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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 target="_blank" href="{{Source}}" title="{{Filename}}"><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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -5,8 +5,11 @@
- 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 ? )
- 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">
@@ -14,7 +17,7 @@
<tbody>
<tr>
<th>
Name
{{#i18n.Translations}}{{name}}{{/i18n.Translations}}
</th>
<td>
<input type="text" name="name" value="" />
@@ -22,7 +25,7 @@
</tr>
<tr>
<th>
Subject
{{#i18n.Translations}}{{subject}}{{/i18n.Translations}}
</th>
<td>
<input type="text" name="subject" value="" />
@@ -31,23 +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>
<tr>
{{#files}}
<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
<th>
{{#i18n.Translations}}{{dubs}}{{/i18n.Translations}}
</th>
<td>
<input type="checkbox" name="dubs" />
@@ -55,7 +60,7 @@
</tr>
<tr>
<th>
Captcha
{{#i18n.Translations}}{{captcha}}{{/i18n.Translations}}
</th>
<td>
<img id="captcha_img" src="{{prefix}}captcha/img" alt="captcha" />
@@ -63,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>

View File

@@ -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>

View File

@@ -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,16 +15,19 @@
<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" />
<script type="text/javascript" src="{{thread.Prefix}}static/nntpchan.js"></script>
<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 -->
<center>
<div id="nntpchan_banner">
</div>
</center>
<div class="board_header">{{thread.Board}}</div>
<!-- postform -->
<div id="postform_container">
{{{form}}}
@@ -40,6 +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>

View File

@@ -6,30 +6,44 @@
}}
<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>
</head>
<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>
</div>
<script type="text/javascript" >
var e = document.getElementById("nntpchan_banner");
nntpchan_inject_banners(e, "{{prefix}}");
</script>
<hr/>
<footer>
<p class="legal">All posts on this site are the responsibility of the individual poster and not the administration, pursuant to 47 U.S.C. § 230.</p>
<p class="legal">To make a DMCA request or report illegal content, please contact the administration</p>
</footer>
</body>
</html>

View 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);

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):
@@ -69,19 +75,53 @@ 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):
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 += 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
def body(self):
if len(self.attachments) > 0:
if 'filename' in self.j:
return self.bodyMultipart()
else:
return self.bodyPlain()
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):
"""
@@ -90,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:
@@ -113,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
"""
@@ -124,11 +164,17 @@ 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 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():
@@ -137,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__":

View 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);
});
});

View 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

View 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

View 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

View 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

View 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/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`

View File

@@ -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)

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

@@ -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)

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

28
doc/postgres.md Normal file
View 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)

View File

@@ -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
View 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
View 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"