Compare commits
No commits in common. "ed5fb3d346d498317d90c3891edae91ffa45bf1a" and "f9149361cf30717b44a0f9088f3502184bd603a2" have entirely different histories.
ed5fb3d346
...
f9149361cf
|
@ -2,6 +2,7 @@ FROM docker.io/perl:5.36
|
||||||
|
|
||||||
# Move it
|
# Move it
|
||||||
WORKDIR /opt
|
WORKDIR /opt
|
||||||
|
COPY assets/ ./assets/
|
||||||
COPY lib/ ./lib/
|
COPY lib/ ./lib/
|
||||||
COPY migrations/ ./migrations/
|
COPY migrations/ ./migrations/
|
||||||
COPY public/ ./public/
|
COPY public/ ./public/
|
||||||
|
@ -14,6 +15,9 @@ COPY post_text.conf .
|
||||||
# Dependency time
|
# Dependency time
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get -y upgrade
|
RUN apt-get -y upgrade
|
||||||
|
# Work around for test failing due to headers being lowercase now that
|
||||||
|
# cpan.org is on HTTP/2
|
||||||
|
RUN cpanm --notest Net::HTTP
|
||||||
RUN cpanm --installdeps .
|
RUN cpanm --installdeps .
|
||||||
|
|
||||||
# Finish setting up the environment
|
# Finish setting up the environment
|
||||||
|
|
14
README.md
14
README.md
|
@ -60,10 +60,22 @@ tests locally:
|
||||||
|
|
||||||
## TODOs
|
## TODOs
|
||||||
|
|
||||||
|
1. Re-visit this TODO list because it doesn't seem like I'm gunna
|
||||||
|
bother with all new posts flagged mode lmao. There's a CAPTCHA now
|
||||||
|
so it's not as painfully open...
|
||||||
|
1. Automate the holiday backgrounds with JS
|
||||||
|
1. Test JS with LibreJS or something like that (I don't like RMS I
|
||||||
|
just want free JS!!)
|
||||||
|
1. "All new posts flagged" mode (require approval for new posts)
|
||||||
|
1. Tests for mod-only user?
|
||||||
|
|
||||||
|
## Crazy future ideas
|
||||||
|
|
||||||
|
### (Lord knows there's TODOs I could be working on...)
|
||||||
|
|
||||||
1. Is `remark_tally` counting hidden remarks? Tried to add a `WHERE
|
1. Is `remark_tally` counting hidden remarks? Tried to add a `WHERE
|
||||||
NOT hidden_status` but that returns null, probably need a different
|
NOT hidden_status` but that returns null, probably need a different
|
||||||
`JOIN` which may not be worth the trouble/processing
|
`JOIN` which may not be worth the trouble/processing
|
||||||
1. Nah it needs a subquery instead of just `COUNT(*)` (dude trust me)
|
|
||||||
1. Implement tripcodes (moving this down in priority due to complexity...)
|
1. Implement tripcodes (moving this down in priority due to complexity...)
|
||||||
1. Post thread via SMS (twil.io??)
|
1. Post thread via SMS (twil.io??)
|
||||||
|
|
||||||
|
|
12
assets/assetpack.db
Normal file
12
assets/assetpack.db
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[css-min:css/PostText.css]
|
||||||
|
checksum=3698d7bf52
|
||||||
|
format=css
|
||||||
|
minified=1
|
||||||
|
[css-min:https://unpkg.com/98.css]
|
||||||
|
checksum=4f089bc53f
|
||||||
|
format=css
|
||||||
|
minified=1
|
||||||
|
[sass:sass/post_text.scss]
|
||||||
|
checksum=ecda188939
|
||||||
|
format=css
|
||||||
|
minified=0
|
5
assets/assetpack.def
Normal file
5
assets/assetpack.def
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
! app.css
|
||||||
|
< https://unpkg.com/normalize.css@8.0.1/normalize.css
|
||||||
|
< css/elements.css
|
||||||
|
< css/simple.css
|
||||||
|
< css/nested.css
|
|
@ -28,6 +28,14 @@
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-image: url('/images/background_stars_anm.gif');
|
background-image: url('/images/background_stars_anm.gif');
|
||||||
|
/* Was feelin this for September idk */
|
||||||
|
/* background-image: url('/images/topwwbackground.gif'); */
|
||||||
|
/* Spooky time! */
|
||||||
|
/* background-image: url('/images/halloween_background_1.gif'); */
|
||||||
|
/* Winter/snow */
|
||||||
|
/* background-image: url('/images/jwsfp1.gif'); */
|
||||||
|
/* Christmas */
|
||||||
|
/* background-image: url('/images/christmas.gif'); */
|
||||||
width: 95vmin;
|
width: 95vmin;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
font-family: 'w95fa', sans-serif;
|
font-family: 'w95fa', sans-serif;
|
3
cpanfile
3
cpanfile
|
@ -1,9 +1,12 @@
|
||||||
requires 'Mojolicious';
|
requires 'Mojolicious';
|
||||||
requires 'Mojo::Pg';
|
requires 'Mojo::Pg';
|
||||||
requires 'Mojolicious::Plugin::TagHelpers::Pagination';
|
requires 'Mojolicious::Plugin::TagHelpers::Pagination';
|
||||||
|
requires 'Mojolicious::Plugin::AssetPack';
|
||||||
requires 'Crypt::Passphrase::Argon2';
|
requires 'Crypt::Passphrase::Argon2';
|
||||||
requires 'Date::Format';
|
requires 'Date::Format';
|
||||||
requires 'XML::RSS';
|
requires 'XML::RSS';
|
||||||
|
requires 'CSS::Minifier::XS';
|
||||||
requires 'Text::Markdown';
|
requires 'Text::Markdown';
|
||||||
requires 'HTML::Restrict';
|
requires 'HTML::Restrict';
|
||||||
|
requires 'IO::Socket::SSL';
|
||||||
requires 'Roman::Unicode';
|
requires 'Roman::Unicode';
|
||||||
|
|
|
@ -18,6 +18,7 @@ use PostText::Model::Page;
|
||||||
sub startup($self) {
|
sub startup($self) {
|
||||||
$self->plugin('Config');
|
$self->plugin('Config');
|
||||||
$self->plugin('TagHelpers::Pagination');
|
$self->plugin('TagHelpers::Pagination');
|
||||||
|
$self->plugin(AssetPack => {pipes => [qw{Css Combine}]});
|
||||||
|
|
||||||
# Helpers
|
# Helpers
|
||||||
$self->helper(pg => sub ($c) {
|
$self->helper(pg => sub ($c) {
|
||||||
|
@ -107,6 +108,8 @@ sub startup($self) {
|
||||||
$self->thread->max_pages($max_thread_pages)
|
$self->thread->max_pages($max_thread_pages)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$self->asset->process;
|
||||||
|
|
||||||
push @{$self->commands->namespaces}, 'PostText::Command';
|
push @{$self->commands->namespaces}, 'PostText::Command';
|
||||||
|
|
||||||
# Begin routing
|
# Begin routing
|
||||||
|
@ -147,8 +150,6 @@ sub startup($self) {
|
||||||
|
|
||||||
$r->get('/feeds')->to('page#feeds')->name('feeds_page');
|
$r->get('/feeds')->to('page#feeds')->name('feeds_page');
|
||||||
|
|
||||||
$r->get('/javascript')->to('page#javascript')->name('javascript_page');
|
|
||||||
|
|
||||||
# Not-so-static but I mean they're all 'pages' c'mon
|
# Not-so-static but I mean they're all 'pages' c'mon
|
||||||
$human->get('/search')->to('page#search')->name('search_page');
|
$human->get('/search')->to('page#search')->name('search_page');
|
||||||
|
|
||||||
|
@ -233,10 +234,6 @@ sub startup($self) {
|
||||||
->to('moderator#mod_reset')
|
->to('moderator#mod_reset')
|
||||||
->name('mod_reset');
|
->name('mod_reset');
|
||||||
|
|
||||||
$moderator->get('/list')
|
|
||||||
->to('moderator#list')
|
|
||||||
->name('mod_list');
|
|
||||||
|
|
||||||
my $mod_thread = $moderator->any('/thread');
|
my $mod_thread = $moderator->any('/thread');
|
||||||
|
|
||||||
$mod_thread->get('/unflag/:thread_id', [thread_id => qr/\d+/])
|
$mod_thread->get('/unflag/:thread_id', [thread_id => qr/\d+/])
|
||||||
|
|
|
@ -344,12 +344,4 @@ sub remark_by_id($self) {
|
||||||
$self->render;
|
$self->render;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub list($self) {
|
|
||||||
my $moderators = $self->moderator->list;
|
|
||||||
|
|
||||||
$self->stash(moderators => $moderators);
|
|
||||||
|
|
||||||
$self->render;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -10,8 +10,6 @@ sub rules($self) { $self->render }
|
||||||
|
|
||||||
sub feeds($self) { $self->render }
|
sub feeds($self) { $self->render }
|
||||||
|
|
||||||
sub javascript($self) { $self->render }
|
|
||||||
|
|
||||||
sub captcha($self) {
|
sub captcha($self) {
|
||||||
my $v;
|
my $v;
|
||||||
|
|
||||||
|
|
|
@ -259,19 +259,4 @@ sub remark_by_id($self, $remark_id) {
|
||||||
END_SQL
|
END_SQL
|
||||||
}
|
}
|
||||||
|
|
||||||
sub list($self) {
|
|
||||||
my $date_format = $self->date_format;
|
|
||||||
|
|
||||||
$self->pg->db->query(<<~'END_SQL', $date_format)->hashes;
|
|
||||||
SELECT moderator_id AS id,
|
|
||||||
moderator_name AS name,
|
|
||||||
email_addr,
|
|
||||||
TO_CHAR(creation_date, $1) AS creation_date,
|
|
||||||
TO_CHAR(last_login_date, $1) AS last_login_date,
|
|
||||||
lock_status,
|
|
||||||
admin_status
|
|
||||||
FROM moderators;
|
|
||||||
END_SQL
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
|
@ -1,28 +0,0 @@
|
||||||
(function () {
|
|
||||||
const bodyStyle = document.body.style;
|
|
||||||
|
|
||||||
function setImage(url) {
|
|
||||||
bodyStyle.backgroundImage = "url('" + url + "')";
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (new Date().getMonth()) {
|
|
||||||
case 0:
|
|
||||||
setImage('/images/jwsfp1.gif');
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
setImage('/images/outofthedarknessbkgtile.gif');
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
setImage('/images/background2.gif');
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
setImage('/images/halloween_background_1.gif');
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
setImage('/images/topwwbackground.gif');
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
setImage('/images/christmas.gif');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
})();
|
|
|
@ -5,8 +5,8 @@ use Test::Mojo;
|
||||||
my $t = Test::Mojo->new('PostText');
|
my $t = Test::Mojo->new('PostText');
|
||||||
|
|
||||||
my %valid_login = (
|
my %valid_login = (
|
||||||
email => 'swaggboi@gangstalking.agency',
|
email => 'swaggboi@slackware.uk',
|
||||||
password => 'i also like to party'
|
password => 'i like to party'
|
||||||
);
|
);
|
||||||
|
|
||||||
my %invalid_login = (
|
my %invalid_login = (
|
||||||
|
@ -114,12 +114,6 @@ subtest Login => sub {
|
||||||
->element_exists('form input[name="password"]')
|
->element_exists('form input[name="password"]')
|
||||||
};
|
};
|
||||||
|
|
||||||
subtest List => sub {
|
|
||||||
$t->get_ok('/moderator/list')
|
|
||||||
->status_is(200)
|
|
||||||
->text_like(h2 => qr/Moderator List/)
|
|
||||||
};
|
|
||||||
|
|
||||||
# Mod session ends
|
# Mod session ends
|
||||||
$t->get_ok('/logout')
|
$t->get_ok('/logout')
|
||||||
->status_is(302)
|
->status_is(302)
|
||||||
|
@ -133,7 +127,6 @@ subtest Login => sub {
|
||||||
->element_exists_not('a[href*="/unflag/1"]' )
|
->element_exists_not('a[href*="/unflag/1"]' )
|
||||||
->element_exists_not('a[href*="/moderator/flagged"]')
|
->element_exists_not('a[href*="/moderator/flagged"]')
|
||||||
->element_exists_not('a[href*="/moderator/hidden"]' )
|
->element_exists_not('a[href*="/moderator/hidden"]' )
|
||||||
->element_exists_not('a[href*="/moderator/list"]' )
|
|
||||||
->element_exists_not('a[href*="/logout"]' );
|
->element_exists_not('a[href*="/logout"]' );
|
||||||
|
|
||||||
$t->get_ok('/remark/single/1')
|
$t->get_ok('/remark/single/1')
|
||||||
|
@ -143,7 +136,6 @@ subtest Login => sub {
|
||||||
->element_exists_not('a[href*="/unflag/1"]' )
|
->element_exists_not('a[href*="/unflag/1"]' )
|
||||||
->element_exists_not('a[href*="/moderator/flagged"]')
|
->element_exists_not('a[href*="/moderator/flagged"]')
|
||||||
->element_exists_not('a[href*="/moderator/hidden"]' )
|
->element_exists_not('a[href*="/moderator/hidden"]' )
|
||||||
->element_exists_not('a[href*="/moderator/list"]' )
|
|
||||||
->element_exists_not('a[href*="/logout"]' );
|
->element_exists_not('a[href*="/logout"]' );
|
||||||
|
|
||||||
$t->get_ok('/moderator/flagged')
|
$t->get_ok('/moderator/flagged')
|
||||||
|
@ -153,10 +145,6 @@ subtest Login => sub {
|
||||||
$t->get_ok('/moderator/hidden')
|
$t->get_ok('/moderator/hidden')
|
||||||
->status_is(302)
|
->status_is(302)
|
||||||
->header_like(Location => qr/login/);
|
->header_like(Location => qr/login/);
|
||||||
|
|
||||||
$t->get_ok('/moderator/list')
|
|
||||||
->status_is(302)
|
|
||||||
->header_like(Location => qr/login/);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
3
t/page.t
3
t/page.t
|
@ -10,7 +10,4 @@ $t->get_ok('/rules')->status_is(200)->text_like(h2 => qr/The Rules/);
|
||||||
|
|
||||||
$t->get_ok('/feeds')->status_is(200)->text_like(h2 => qr/Feeds/);
|
$t->get_ok('/feeds')->status_is(200)->text_like(h2 => qr/Feeds/);
|
||||||
|
|
||||||
$t->get_ok('/javascript')->status_is(200)
|
|
||||||
->text_like(h2 => qr/JavaScript License Information/);
|
|
||||||
|
|
||||||
done_testing;
|
done_testing;
|
||||||
|
|
|
@ -29,10 +29,7 @@
|
||||||
content="<%= url_for('/images/logo.png')->to_abs %>">
|
content="<%= url_for('/images/logo.png')->to_abs %>">
|
||||||
<meta name="twitter:image:alt"
|
<meta name="twitter:image:alt"
|
||||||
content="Post::Text logo; a small nerdy anime girl giving a V sign">
|
content="Post::Text logo; a small nerdy anime girl giving a V sign">
|
||||||
<%= stylesheet '/css/elements.css' %>
|
<%= asset 'app.css' %>
|
||||||
<%= stylesheet '/css/simple.css' %>
|
|
||||||
<%= stylesheet '/css/nested.css' %>
|
|
||||||
<%= javascript '/js/background.js', defer => undef %>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header class="header">
|
<header class="header">
|
||||||
|
@ -51,7 +48,6 @@
|
||||||
<%= link_to Flagged => flagged_list => (class => 'click') %>
|
<%= link_to Flagged => flagged_list => (class => 'click') %>
|
||||||
<%= link_to Hidden => hidden_list => (class => 'click') %>
|
<%= link_to Hidden => hidden_list => (class => 'click') %>
|
||||||
<%= link_to Reset => mod_reset => (class => 'click') %>
|
<%= link_to Reset => mod_reset => (class => 'click') %>
|
||||||
<%= link_to List => mod_list => (class => 'click') %>
|
|
||||||
<%= link_to Logout => mod_logout => (class => 'click') %>
|
<%= link_to Logout => mod_logout => (class => 'click') %>
|
||||||
</nav>
|
</nav>
|
||||||
<% } =%>
|
<% } =%>
|
||||||
|
@ -93,9 +89,6 @@
|
||||||
<%= content =%>
|
<%= content =%>
|
||||||
<footer class="site-footer">
|
<footer class="site-footer">
|
||||||
<p>In UTF-8 we trust. 🫡</p>
|
<p>In UTF-8 we trust. 🫡</p>
|
||||||
<p><%= link_to javascript_page =>
|
|
||||||
('data-jslicense', 1),
|
|
||||||
begin %>JavaScript License Information<% end %></p>
|
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
% layout 'default';
|
|
||||||
% title 'Moderator List';
|
|
||||||
<h2 class="page-title"><%= title %></h2>
|
|
||||||
<main class="page-body">
|
|
||||||
<% if (scalar @{$moderators}) { =%>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Moderator ID</th>
|
|
||||||
<th>Moderator Name</th>
|
|
||||||
<th>Email Address</th>
|
|
||||||
<th>Creation Date</th>
|
|
||||||
<th>Last Login Date</th>
|
|
||||||
<th>Locked?</th>
|
|
||||||
<th>Admin?</th>
|
|
||||||
</tr>
|
|
||||||
<% for my $moderator (@{$moderators}) { =%>
|
|
||||||
<tr>
|
|
||||||
<td><%= $moderator->{'id' } %></td>
|
|
||||||
<td><%= $moderator->{'name' } %></td>
|
|
||||||
<td><%= $moderator->{'email_addr' } %></td>
|
|
||||||
<td><%= $moderator->{'creation_date' } %></td>
|
|
||||||
<td><%= $moderator->{'last_login_date'} %></td>
|
|
||||||
<td><%= $moderator->{'lock_status' } %></td>
|
|
||||||
<td><%= $moderator->{'admin_status' } %></td>
|
|
||||||
</tr>
|
|
||||||
<% } =%>
|
|
||||||
</table>
|
|
||||||
<% } =%>
|
|
||||||
</main>
|
|
|
@ -1,28 +0,0 @@
|
||||||
% layout 'default';
|
|
||||||
% title 'JavaScript License Information';
|
|
||||||
% content_for open_graph => begin
|
|
||||||
<meta property="og:type" content="website">
|
|
||||||
<meta property="og:title" content="<%= title %>">
|
|
||||||
<meta
|
|
||||||
property="og:description"
|
|
||||||
content="Post::Text is a textboard a bit like 2channel. You can post whatever you want anonymously just please mind the rules."
|
|
||||||
>
|
|
||||||
% end
|
|
||||||
% content_for twitter_card => begin
|
|
||||||
<meta name="twitter:title" content="<%= title %>">
|
|
||||||
<meta
|
|
||||||
name="twitter:description"
|
|
||||||
content="Post::Text is a textboard a bit like 2channel. You can post whatever you want anonymously just please mind the rules."
|
|
||||||
>
|
|
||||||
% end
|
|
||||||
<h2 class="page-title"><%= title %></h2>
|
|
||||||
<main class="page-body">
|
|
||||||
<table id="jslicense-labels1">
|
|
||||||
<tr>
|
|
||||||
<td><%= link_to 'background.js', '/js/background.js' %></td>
|
|
||||||
<td><%= link_to 'http://www.gnu.org/licenses/gpl-3.0.html',
|
|
||||||
begin%>GNU General Public License 3.0 or later<% end %></td>
|
|
||||||
<td><%= link_to 'background.js', '/js/background.js' %></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</main>
|
|
Loading…
Reference in New Issue
Block a user