summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/VNWeb/Auth.pm11
-rw-r--r--lib/VNWeb/Discussions/Edit.pm3
-rw-r--r--lib/VNWeb/Discussions/PostEdit.pm3
-rw-r--r--lib/VNWeb/Discussions/Thread.pm5
-rw-r--r--lib/VNWeb/Reviews/Edit.pm1
-rw-r--r--lib/VNWeb/Reviews/Page.pm6
-rw-r--r--lib/VNWeb/User/Notifications.pm18
-rw-r--r--sql/tableattrs.sql2
-rw-r--r--util/updates/wip-notifications.sql13
9 files changed, 46 insertions, 16 deletions
diff --git a/lib/VNWeb/Auth.pm b/lib/VNWeb/Auth.pm
index 907fb2f4..9707108f 100644
--- a/lib/VNWeb/Auth.pm
+++ b/lib/VNWeb/Auth.pm
@@ -287,6 +287,17 @@ sub prefSet {
}
+# Mark any notifications for a particular item for the current user as read.
+# Arguments: $vndbid, $num||[@nums]||<missing>
+sub notiRead {
+ my($self, $id, $num) = @_;
+ tuwf->dbExeci('
+ UPDATE notifications SET read = NOW() WHERE read IS NULL AND uid =', \$self->uid, 'AND iid =', \$id,
+ @_ == 2 ? () : !defined $num ? 'AND num IS NULL' : !ref $num ? sql 'AND num =', \$num : sql 'AND num IN', $num
+ ) if $self->uid;
+}
+
+
# Add an entry to the audit log.
sub audit {
my($self, $affected_uid, $action, $detail) = @_;
diff --git a/lib/VNWeb/Discussions/Edit.pm b/lib/VNWeb/Discussions/Edit.pm
index dddc1ac8..b85514ec 100644
--- a/lib/VNWeb/Discussions/Edit.pm
+++ b/lib/VNWeb/Discussions/Edit.pm
@@ -47,10 +47,11 @@ elm_api DiscussionsEdit => $FORM_OUT, $FORM_IN, sub {
return tuwf->resNotFound if $tid && !$t->{id};
return elm_Unauth if !can_edit t => $t;
+ tuwf->dbExeci(q{DELETE FROM notifications WHERE iid =}, \$tid) if $tid && auth->permBoardmod && ($data->{delete} || $data->{hidden});
+
if($tid && $data->{delete} && auth->permBoardmod) {
auth->audit($t->{user_id}, 'post delete', "deleted $tid.1");
tuwf->dbExeci('DELETE FROM threads WHERE id =', \$tid);
- tuwf->dbExeci(q{DELETE FROM notifications WHERE iid =}, \$tid);
return elm_Redirect '/t';
}
auth->audit($t->{user_id}, 'post edit', "edited $tid.1") if $tid && $t->{user_id} != auth->uid;
diff --git a/lib/VNWeb/Discussions/PostEdit.pm b/lib/VNWeb/Discussions/PostEdit.pm
index a645fb6f..520a215f 100644
--- a/lib/VNWeb/Discussions/PostEdit.pm
+++ b/lib/VNWeb/Discussions/PostEdit.pm
@@ -44,11 +44,12 @@ elm_api DiscussionsPostEdit => $FORM_OUT, $FORM_IN, sub {
return tuwf->resNotFound if !$t->{id};
return elm_Unauth if !can_edit t => $t;
+ tuwf->dbExeci(q{DELETE FROM notifications WHERE iid =}, \$id, 'AND num =', \$num) if auth->permBoardmod && ($data->{delete} || $data->{hidden});
+
if($data->{delete} && auth->permBoardmod) {
auth->audit($t->{user_id}, 'post delete', "deleted $id.$num");
tuwf->dbExeci('DELETE FROM threads_posts WHERE tid =', \$id, 'AND num =', \$num);
tuwf->dbExeci('DELETE FROM reviews_posts WHERE id =', \$id, 'AND num =', \$num);
- tuwf->dbExeci(q{DELETE FROM notifications WHERE iid =}, \$id, 'AND num =', \$num);
return elm_Redirect "/$id";
}
auth->audit($t->{user_id}, 'post edit', "edited $id.$num") if $t->{user_id} != auth->uid;
diff --git a/lib/VNWeb/Discussions/Thread.pm b/lib/VNWeb/Discussions/Thread.pm
index 3fd67dbe..39de4b96 100644
--- a/lib/VNWeb/Discussions/Thread.pm
+++ b/lib/VNWeb/Discussions/Thread.pm
@@ -192,10 +192,7 @@ TUWF::get qr{/$RE{tid}(?:(?<sep>[\./])$RE{num})?}, sub {
GROUP BY tpo.id, tpo.option, tpm.optid'
);
- # Mark a notification for this thread as read, if there is one.
- tuwf->dbExeci(
- 'UPDATE notifications SET read = NOW() WHERE uid =', \auth->uid, 'AND iid =', \$id, 'AND read IS NULL'
- ) if auth && $t->{count} <= $page*25;
+ auth->notiRead($id, [ map $_->{num}, $posts->@* ]) if @$posts;
framework_ title => $t->{title}, $num ? (js => 1, pagevars => {sethash=>$num}) : (), sub {
metabox_ $t;
diff --git a/lib/VNWeb/Reviews/Edit.pm b/lib/VNWeb/Reviews/Edit.pm
index a3323d62..c7b829bc 100644
--- a/lib/VNWeb/Reviews/Edit.pm
+++ b/lib/VNWeb/Reviews/Edit.pm
@@ -101,6 +101,7 @@ elm_api ReviewsDelete => undef, { id => { vndbid => 'w' } }, sub {
my $review = tuwf->dbRowi('SELECT id, uid AS user_id FROM reviews WHERE id =', \$data->{id});
return elm_Unauth if !can_edit w => $review;
auth->audit($review->{user_id}, 'review delete', "deleted $review->{id}");
+ tuwf->dbExeci('DELETE FROM notifications WHERE iid =', \$data->{id});
tuwf->dbExeci('DELETE FROM reviews WHERE id =', \$data->{id});
elm_Success
};
diff --git a/lib/VNWeb/Reviews/Page.pm b/lib/VNWeb/Reviews/Page.pm
index 927a39f4..8aa35d4c 100644
--- a/lib/VNWeb/Reviews/Page.pm
+++ b/lib/VNWeb/Reviews/Page.pm
@@ -119,10 +119,8 @@ TUWF::get qr{/$RE{wid}(?:(?<sep>[\./])$RE{num})?}, sub {
);
return tuwf->resNotFound if $num && !grep $_->{num} == $num, @$posts;
- # Mark a notification for this thread as read, if there is one.
- tuwf->dbExeci(
- 'UPDATE notifications SET read = NOW() WHERE uid =', \auth->uid, 'AND iid =', \$id, 'AND read IS NULL'
- ) if auth && $w->{count} <= $page*25;
+ auth->notiRead($id, undef);
+ auth->notiRead($id, [ map $_->{num}, $posts->@* ]) if @$posts;
my $title = "Review of $w->{title}";
framework_ title => $title, index => 1, type => 'w', dbobj => $w,
diff --git a/lib/VNWeb/User/Notifications.pm b/lib/VNWeb/User/Notifications.pm
index e4bc0b06..3831402b 100644
--- a/lib/VNWeb/User/Notifications.pm
+++ b/lib/VNWeb/User/Notifications.pm
@@ -3,7 +3,7 @@ package VNWeb::User::Notifications;
use VNWeb::Prelude;
my %ntypes = (
- pm => 'Private Message',
+ pm => 'Message on your board',
dbdel => 'Entry you contributed to has been deleted',
listdel => 'VN in your list has been deleted',
dbedit => 'Entry you contributed to has been edited',
@@ -74,20 +74,20 @@ sub listing_ {
tr_ $_->{read} ? () : (class => 'unread'), sub {
my $l = $_;
my $lid = $l->{iid}.($l->{num}?'.'.$l->{num}:'');
- my $url = "/u$id/notify/$l->{id}/$lid";
td_ class => 'tc1', sub { input_ type => 'checkbox', name => 'notifysel', value => $l->{id}; };
td_ class => 'tc2', sub {
# Hide some not very interesting overlapping notification types
my %t = map +($_,1), $l->{ntype}->@*;
- delete $t{subpost} if $t{post} || $t{comment};
+ delete $t{subpost} if $t{post} || $t{comment} || $t{pm};
+ delete $t{post} if $t{pm};
delete $t{subedit} if $t{dbedit};
delete $t{dbedit} if $t{dbdel};
join_ \&br_, sub { txt_ $ntypes{$_} }, sort keys %t;
};
td_ class => 'tc3', fmtage $l->{date};
- td_ class => 'tc4', sub { a_ href => $url, $lid };
+ td_ class => 'tc4', sub { a_ href => "/$lid", $lid };
td_ class => 'tc5', sub {
- a_ href => $url, sub {
+ a_ href => "/$lid", sub {
txt_ $l->{iid} =~ /^w/ ? ($l->{num} ? 'Comment on ' : 'Review of ') :
$l->{iid} =~ /^t/ ? ($l->{num} == 1 ? 'New thread ' : 'Reply to ') : 'Edit of ';
i_ $l->{title};
@@ -190,6 +190,8 @@ TUWF::post qr{/$RE{uid}/notify_update}, sub {
};
+# XXX: Not currently used anymore, just visiting the destination pages will mark the relevant notifications as read
+# (but that's subject to change in the future, so let's keep this around)
TUWF::get qr{/$RE{uid}/notify/$RE{num}/(?<lid>[a-z0-9\.]+)}, sub {
my $id = tuwf->capture('id');
return tuwf->resNotFound if !auth || $id != auth->uid;
@@ -197,4 +199,10 @@ TUWF::get qr{/$RE{uid}/notify/$RE{num}/(?<lid>[a-z0-9\.]+)}, sub {
tuwf->resRedirect('/'.tuwf->capture('lid'), 'temp');
};
+
+# It's a bit annoying to add auth->notiRead() to each revision page, so do that in bulk with a simple hook.
+TUWF::hook before => sub {
+ auth->notiRead($+{vndbid}, $+{rev}) if auth && tuwf->reqPath() =~ qr{^/(?<vndbid>[vrpcsd]$RE{num})\.(?<rev>$RE{num})$};
+};
+
1;
diff --git a/sql/tableattrs.sql b/sql/tableattrs.sql
index 23dd362a..8e408b92 100644
--- a/sql/tableattrs.sql
+++ b/sql/tableattrs.sql
@@ -119,7 +119,7 @@ CREATE INDEX chars_vns_vid ON chars_vns (vid);
CREATE INDEX chars_image ON chars (image);
CREATE UNIQUE INDEX image_votes_pkey ON image_votes (uid, id);
CREATE INDEX image_votes_id ON image_votes (id);
-CREATE INDEX notifications_uid ON notifications (uid);
+CREATE INDEX notifications_uid_iid ON notifications (uid,iid);
CREATE INDEX releases_producers_pid ON releases_producers (pid);
CREATE INDEX releases_vn_vid ON releases_vn (vid);
CREATE INDEX reports_new ON reports (date) WHERE status = 'new';
diff --git a/util/updates/wip-notifications.sql b/util/updates/wip-notifications.sql
index 1a817b33..ef0f574b 100644
--- a/util/updates/wip-notifications.sql
+++ b/util/updates/wip-notifications.sql
@@ -13,6 +13,19 @@ ALTER TABLE notifications ALTER COLUMN ntype TYPE notification_ntype[] USING ARR
ALTER TABLE notifications DROP COLUMN c_title;
ALTER TABLE notifications DROP COLUMN c_byuser;
+DROP INDEX notifications_uid;
+CREATE INDEX notifications_uid_iid ON notifications (uid,iid);
+
+-- Merge duplicate notifications (dbdel & listdel could cause duplicates)
+UPDATE notifications n SET ntype = ntype || ARRAY['dbdel'::notification_ntype]
+ WHERE ntype = ARRAY['listdel'::notification_ntype]
+ AND EXISTS(SELECT 1 FROM notifications m WHERE m.id <> n.id AND m.uid = n.uid AND m.iid = n.iid AND m.num IS NOT DISTINCT FROM n.num AND m.ntype = ARRAY['dbdel'::notification_ntype]);
+DELETE FROM notifications n
+ WHERE ntype = ARRAY['dbdel'::notification_ntype]
+ AND EXISTS(SELECT 1 FROM notifications m WHERE m.id <> n.id AND m.uid = n.uid AND m.iid = n.iid AND m.num IS NOT DISTINCT FROM n.num AND m.ntype = ARRAY['listdel'::notification_ntype,'dbdel']);
+-- For some reason a few notifications from 2014 were duplicated, let's just get rid of those.
+DELETE FROM notifications n WHERE EXISTS(SELECT 1 FROM notifications m WHERE m.id <> n.id AND m.uid = n.uid AND m.iid = n.iid AND m.num IS NOT DISTINCT FROM n.num AND m.id > n.id);
+
-- Subscriptions
ALTER TYPE notification_ntype ADD VALUE 'subpost' AFTER 'comment';
ALTER TYPE notification_ntype ADD VALUE 'subedit' AFTER 'subpost';