Implement thread hiding

This commit is contained in:
David Hoppenbrouwers
2022-10-11 21:05:45 +02:00
parent 61ad1e2716
commit 77e9051334
7 changed files with 181 additions and 15 deletions

View File

@@ -35,24 +35,49 @@ class DB:
(forum_id,) (forum_id,)
).fetchone() ).fetchone()
def get_threads(self, forum_id, offset, limit): def get_threads(self, forum_id, offset, limit, user_id):
return self._db().execute(''' return self._db().execute('''
select t.thread_id, title, t.create_time, t.update_time, t.author_id, name, count(c.thread_id) select
from threads t, users t.thread_id,
left join comments c on t.thread_id = c.thread_id title,
where forum_id = ? and user_id = t.author_id t.create_time,
t.update_time,
t.author_id,
name,
count(c.thread_id),
t.hidden
from
threads t,
users
left join
comments c
on
t.thread_id = c.thread_id
where forum_id = ?
and user_id = t.author_id
and (
t.hidden = 0 or (
select 1 from users
where user_id = ?
and (
user_id = t.author_id
-- 1 = moderator, 2 = admin
or role in (1, 2)
)
)
)
group by t.thread_id group by t.thread_id
order by t.update_time desc order by t.update_time desc
limit ? limit ?
offset ? offset ?
''', ''',
(forum_id, limit, offset) (forum_id, user_id, limit, offset)
) )
def get_thread(self, thread): def get_thread(self, thread):
db = self._db() db = self._db()
title, text, author, author_id, create_time, modify_time = db.execute(''' title, text, author, author_id, create_time, modify_time, hidden = db.execute('''
select title, text, name, author_id, create_time, modify_time select title, text, name, author_id, create_time, modify_time, hidden
from threads, users from threads, users
where thread_id = ? and author_id = user_id where thread_id = ? and author_id = user_id
''', ''',
@@ -67,7 +92,7 @@ class DB:
''', ''',
(thread,) (thread,)
) )
return title, text, author, author_id, create_time, modify_time, comments return title, text, author, author_id, create_time, modify_time, comments, hidden
def get_thread_title(self, thread_id): def get_thread_title(self, thread_id):
return self._db().execute(''' return self._db().execute('''
@@ -475,6 +500,15 @@ class DB:
(role, user_id) (role, user_id)
) )
def set_thread_hidden(self, thread_id, hide):
return self.change_one('''
update threads
set hidden = ?
where thread_id = ?
''',
(hide, thread_id)
)
def change_one(self, query, values): def change_one(self, query, values):
db = self._db() db = self._db()
c = db.cursor() c = db.cursor()

27
main.py
View File

@@ -1,4 +1,4 @@
VERSION = 'agreper-v0.1' VERSION = 'agreper-v0.1.1'
# TODO put in config table # TODO put in config table
THREADS_PER_PAGE = 50 THREADS_PER_PAGE = 50
@@ -42,7 +42,8 @@ def index():
def forum(forum_id): def forum(forum_id):
title, description = db.get_forum(forum_id) title, description = db.get_forum(forum_id)
offset = int(request.args.get('p', 0)) offset = int(request.args.get('p', 0))
threads = [*db.get_threads(forum_id, offset, THREADS_PER_PAGE + 1)] user_id = session.get('user_id', -1)
threads = [*db.get_threads(forum_id, offset, THREADS_PER_PAGE + 1, user_id)]
if len(threads) == THREADS_PER_PAGE + 1: if len(threads) == THREADS_PER_PAGE + 1:
threads.pop() threads.pop()
next_page = offset + THREADS_PER_PAGE next_page = offset + THREADS_PER_PAGE
@@ -63,7 +64,7 @@ def forum(forum_id):
@app.route('/thread/<int:thread_id>/') @app.route('/thread/<int:thread_id>/')
def thread(thread_id): def thread(thread_id):
user_id = session.get('user_id') user_id = session.get('user_id')
title, text, author, author_id, create_time, modify_time, comments = db.get_thread(thread_id) title, text, author, author_id, create_time, modify_time, comments, hidden = db.get_thread(thread_id)
comments = create_comment_tree(comments) comments = create_comment_tree(comments)
return render_template( return render_template(
'thread.html', 'thread.html',
@@ -74,6 +75,7 @@ def thread(thread_id):
author = author, author = author,
author_id = author_id, author_id = author_id,
thread_id = thread_id, thread_id = thread_id,
hidden = hidden,
create_time = create_time, create_time = create_time,
modify_time = modify_time, modify_time = modify_time,
comments = comments, comments = comments,
@@ -574,6 +576,25 @@ def admin_restart():
restart() restart()
return redirect(url_for('admin')) return redirect(url_for('admin'))
@app.route('/thread/<int:thread_id>/hide/', methods = ['POST'])
def set_hide_thread(thread_id):
chk, user = _moderator_check()
if not chk:
return user
try:
print(request.form['hide'])
hide = request.form['hide'] != '0'
hide_str = 'Hidden' if hide else 'Unhidden'
if db.set_thread_hidden(thread_id, hide):
flash(f'{hide_str} thread', 'success')
else:
flash(f'Failed to {hide_str.lower()} thread', 'error')
except Exception as e:
flash(str(e), 'error')
return redirect(request.form['redirect'])
# TODO can probably be a static-esque page, maybe? # TODO can probably be a static-esque page, maybe?
@app.route('/help/') @app.route('/help/')
def help(): def help():

View File

@@ -1,4 +1,5 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{%- from 'moderator.html' import moderate_thread with context %}
{%- macro nav() -%} {%- macro nav() -%}
<p style=text-align:center> <p style=text-align:center>
@@ -19,14 +20,22 @@
<th>Created</th> <th>Created</th>
<th>Updated</th> <th>Updated</th>
<th>Comments</th> <th>Comments</th>
{%- if user is not none and user.is_moderator() -%}
<th>Action</th>
{%- endif -%}
</tr> </tr>
{% for id, title, ctime, utime, author_id, author, comment_count in threads %} {% for id, title, ctime, utime, author_id, author, comment_count, hidden in threads %}
<tr> <tr>
<th><a href="{{ url_for('thread', thread_id = id) }}">{{ title }}</a></th> <th>{{ '[hidden] ' if hidden else '' }}<a href="{{ url_for('thread', thread_id = id) }}">{{ title }}</a></th>
<td><a href="{{ url_for('user_info', user_id = author_id) }}">{{ author }}</a></td> <td><a href="{{ url_for('user_info', user_id = author_id) }}">{{ author }}</a></td>
<td>{{ format_since(ctime) }}</td> <td>{{ format_since(ctime) }}</td>
<td>{{ format_since(utime) }}</td> <td>{{ format_since(utime) }}</td>
<td>{{ comment_count }}</td> <td>{{ comment_count }}</td>
<td>
{%- if user is not none and user.is_moderator() %}
{{- moderate_thread(id, hidden) }}
{%- endif -%}
</td>
</tr> </tr>
{%- endfor -%} {%- endfor -%}
</table> </table>

7
templates/moderator.html Normal file
View File

@@ -0,0 +1,7 @@
{% macro moderate_thread(id, hidden) %}
<form method=post action="{{ url_for('set_hide_thread', thread_id = id) }}">
<input name=redirect value="{{ request.full_path }}" hidden>
<input name=hide value={{ 0 if hidden else 1 }} hidden>
<input type=submit value="{{ 'Unhide' if hidden else 'Hide' }}">
</form>
{% endmacro %}

View File

@@ -1,8 +1,12 @@
{%- extends 'base.html' %} {%- extends 'base.html' %}
{%- from 'comment.html' import render_comment, reply, thread_author with context %} {%- from 'comment.html' import render_comment, reply, thread_author with context %}
{%- from 'moderator.html' import moderate_thread with context %}
{%- block content %} {%- block content %}
{{ thread_author(author_id, author, create_time, modify_time) }} {%- if user is not none and user.is_moderator() -%}
<p>{{ moderate_thread(thread_id, hidden) }}</p>
{%- endif -%}
{{- thread_author(author_id, author, create_time, modify_time) }}
<p>{{ minimd(text) | safe }}</p> <p>{{ minimd(text) | safe }}</p>
{{- reply() }} {{- reply() }}

9
upgrade/sqlite/v0.1.sh Normal file
View File

@@ -0,0 +1,9 @@
set -ex
test $# == 1
"$SQLITE" "$1" "
begin exclusive;
alter table threads rename dead to hidden;
alter table comments rename dead to hidden;
update config set version = 'agreper-v0.1.1';
end;
"

82
upgrade_sqlite.sh Executable file
View File

@@ -0,0 +1,82 @@
#!/usr/bin/env bash
# Script to upgrade a database from one version to another by adding columns,
# tables etc.
LAST_VERSION=agreper-v0.1.1
SQLITE=sqlite3
export SQLITE
set -e
if [ $# -lt 1 ]
then
echo "Usage: $0 <file.db> [--no-backup]" >&2
exit 1
fi
make_backup=0
if [ $# -ge 2 ]
then
case "$2" in
--no-backup)
make_backup=1
;;
*)
echo "Unknown option $2"
exit 1
;;
esac
fi
if ! [ -f "$1" ]
then
echo "Database '$1' doesn't exist" >&2
exit 1
fi
version=$(sqlite3 "$1" 'select version from config')
while true
do
case "$version" in
# Last version, do nothing
agreper-v0.1.1)
echo "$version is the latest version"
exit 0
;;
# Try to upgrade
agreper-*)
echo "Upgrading from $version"
if [ $make_backup ]
then
backup="$1.bak-$version"
if [ -f "$backup" ]
then
echo "Backup '$backup' already exists (did a previous upgrade fail?)" >&2
exit 1
fi
echo "Creating backup of $1 at $backup"
cp --reflink=auto "$1" "$backup"
make_backup=1
fi
script="./upgrade/sqlite/${version#agreper-}.sh"
if ! bash "$script" "$1"
then
echo "Error while executing $script"
exit 1
fi
;;
# Unrecognized version
*)
echo "Unknown version $version" >&2
exit 1
;;
esac
version=$(sqlite3 "$1" 'select version from config')
done