OP moderation and color differentiation of deleted items

This commit is contained in:
Juribiyan 2020-02-11 22:32:47 +05:00
parent 9968454db5
commit d6ced732a8
11 changed files with 102 additions and 21 deletions

View File

@ -0,0 +1 @@
ALTER TABLE `boards` ADD COLUMN `opmod` TINYINT(1) NOT NULL DEFAULT '0' AFTER `duplication`;

View File

@ -148,6 +148,7 @@ CREATE TABLE `PREFIX_boards` (
`dice` tinyint(1) NOT NULL DEFAULT '0',
`useragent` tinyint(1) NOT NULL DEFAULT '0',
`duplication` tinyint(1) NOT NULL DEFAULT '0',
`opmod` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=KU_DBCHARSET COLLATE=KU_COLLATION;

View File

@ -532,6 +532,11 @@ elseif (
&&
Manage::CurrentUserIsModeratorOfBoard($board_class->board['name'], $_SESSION['manageusername'])
);
$isop = (
$_POST['opdelete']=="true"
&&
$board_class->board['opmod']=='1'
);
// Post-related actions
if (isset($_POST['post'])) foreach ($_POST['post'] as $val) {
@ -560,10 +565,19 @@ elseif (
// Post deleting
if (isset($_POST['deletepost'])) {
$post_action->action = 'delete';
if ($isop && $post_class->post['parentid'] != '0') {
$op_post_class = new Post($post_class->post['parentid'], $board_class->board['name'], $board_class->board['id']);
// TODO: check if not deleted, check if not empty
$pwd_ref_post = $op_post_class;
}
else {
$isop = false;
$pwd_ref_post = $post_class;
}
if ($pass) {
$passtype = $post_class->post['password'] [0];
$passtype = $pwd_ref_post->post['password'] [0];
if ($passtype == '+') { // modern hash with salt: +md5(password+postid+boardid+randomseed)
$pass_for_this_post = '+'.md5($pass . $post_class->post['id'] . $board_class->board['id'] . KU_RANDOMSEED);
$pass_for_this_post = '+'.md5($pass . $pwd_ref_post->post['id'] . $board_class->board['id'] . KU_RANDOMSEED);
}
elseif ($passtype == '-') { // modern hash w/o salt: -md5(password+randomseed)
if (!$passmd5_new)
@ -576,9 +590,9 @@ elseif (
$pass_for_this_post = $passmd5_old;
}
}
$pwd_ok = ($pass && $pass_for_this_post == $post_class->post['password']);
$pwd_ok = ($pass && $pass_for_this_post == $pwd_ref_post->post['password']);
if ($pwd_ok || $ismod) {
$isownpost = !$ismod;
$isownpost = !$ismod && !$isop;
$thread_id = $post_class->post['parentid'] != '0' ? $post_class->post['parentid'] : $post_class->post['id'];
$before = $board_class->GetPageNumber($thread_id);
$delres = $post_class->Delete(false, $isownpost && I0_ERASE_DELETED);
@ -590,7 +604,9 @@ elseif (
$notifications[$room_id] []= array(
'action' => 'delete_post',
'id' => $post_class->post['id'],
'thread_id' => $thread_id
'thread_id' => $thread_id,
'by_mod' => $ismod,
'by_op' => $isop
);
if ($post_class->post['parentid'] != '0') { // Deleting a reply
if (! in_array($thread_id, $threads_to_regenerate)) {
@ -621,7 +637,8 @@ elseif (
}
}
$post_action->succ(_gettext('Post successfully deleted.')
.($ismod ? ' '._gettext('(By mod)') : ''));
.($ismod ? ' '._gettext('(By mod)') : '')
.($isop ? ' '._gettext('(By OP)') : ''));
}
else { // Deleting a threda
$page_to = INF;
@ -639,13 +656,16 @@ elseif (
$notifications[$room_id] = array();
$notifications[$room_id] []= array(
'action' => 'delete_thread',
'id' => $thread_id
'id' => $thread_id,
'by_mod' => $ismod,
'by_op' => $isop
);
if ($ismod) {
management_addlogentry(_gettext('Deleted thread') . ' #<a href="?action=viewthread&thread='. $thread_id . '&board='. $board_class->board['name'] . '">'. $val . '</a> ('. ($delres-1) . ' replies) - /'. $board_class->board['name'] . '/', 7);
}
$post_action->succ(_gettext('Thread successfully deleted.')
.($ismod ? ' '._gettext('(By mod)') : '')
.($isop ? ' '._gettext('(By OP)') : '')
.' '.($delres-1)._gettext('replies deleted').'.');
}

View File

@ -2659,9 +2659,21 @@ figure:not(.unwrapped):hover .playable-thumb {
.deleted.reply, figure.deleted {
box-shadow: inset 0 0 59px rgba(255, 15, 15, 0.33);
}
.mod-deleted.reply, figure.mod-deleted {
box-shadow: inset 0 0 59px rgba(255, 195, 15, 0.22);
}
.op-deleted.reply, figure.op-deleted {
box-shadow: inset 0 0 59px rgba(15, 252, 255, 0.22);
}
.deleted.reply {
border: 1px solid rgba(255, 15, 15, 0.51);
}
.mod-deleted.reply {
border: 1px solid rgba(255, 195, 15, 0.33);
}
.op-deleted.reply {
border: 1px solid rgba(15, 252, 255, 0.33);
}
figure.deleted {
position: relative;
}
@ -2675,6 +2687,12 @@ figure.deleted:after {
left: 0;
pointer-events: none;
}
figure.mod-deleted:after {
box-shadow: inset 0 0 0 1px rgba(255, 195, 15, 0.33);
}
figure.op-deleted:after {
box-shadow: inset 0 0 0 1px rgba(15, 252, 255, 0.33);
}
.deleted[id^=thread] .op .posthead {
position: relative;
z-index: 1;

View File

@ -17,6 +17,7 @@
var force_html_nocache = !!'{%I0_FORCE_HTML_NOCACHE}';
var allowed_filetypes = [{foreach name=files item=filetype from=$board.filetypes_allowed}"{$filetype}"{if $.foreach.files.last}{else}, {/if}{/foreach}];
var maxfiles = {$board.maxfiles};
var opmod = '{$board.opmod}';
{if $replythread > 0}
var ispage = false;
{else}

View File

@ -241,6 +241,9 @@
{if $board.duplication}
<li>{t}File end embed duplication is allowed{/t}.</li>
{/if}
{if $board.opmod}
<li>{t}OP moderation is enabled{/t}.</li>
{/if}
</ul>
<script>
if (getCookie('ku_showblotter') != '1') {

View File

@ -3065,7 +3065,8 @@ class Manage {
'balls',
'dice',
'useragent',
'duplication'
'duplication',
'opmod'
) as $prop) {
$set []= "`$prop` = ".$tc_db->qstr(isset($_POST[$prop]) ? '1' : '0');
}
@ -3334,6 +3335,15 @@ class Manage {
$tpl_page .= ' />'. "\n" .
'<div class="desc">'. _gettext('Enable file and embed duplication') .'</div><br />';
/* OP moderation */
$tpl_page .= '<label for="opmod">'. _gettext('OP moderation') .':</label>
<input type="checkbox" name="opmod"';
if ($lineboard['opmod'] == '1') {
$tpl_page .= ' checked';
}
$tpl_page .= ' />'. "\n" .
'<div class="desc">'. _gettext('Allow thread starters to delete replies') .'</div><br />';
/* Enable captcha */
$tpl_page .= '<label for="enablecaptcha">'. _gettext('Enable captcha') .':</label>
<input type="checkbox" name="enablecaptcha"';
@ -3499,7 +3509,8 @@ class Manage {
'balls',
'dice',
'useragent',
'duplication'
'duplication',
'opmod'
) as $prop) {
$set []= "`$prop` = ".$tc_db->qstr(isset($_POST[$prop]) ? '1' : '0');
}
@ -3674,6 +3685,15 @@ class Manage {
$tpl_page .= ' />'. "\n" .
'<div class="desc">'. _gettext('Enable file and embed duplication') .'</div><br />';
/* OP moderation */
$tpl_page .= '<label for="opmod">'. _gettext('OP moderation') .':</label>
<input type="checkbox" name="opmod"';
if ($lineboard['opmod'] == '1') {
$tpl_page .= ' checked';
}
$tpl_page .= ' />'. "\n" .
'<div class="desc">'. _gettext('Allow thread starters to delete replies') .'</div><br />';
/* Enable "no file" posting */
$tpl_page .= '<label for="enablenofile">'. _gettext('Enable \'no file\' posting') .':</label>
<input type="checkbox" name="enablenofile"';

View File

@ -2132,4 +2132,13 @@ msgid "Red quotes"
msgstr "Красные стрелки"
msgid "Alternating quotes"
msgstr "Перекрестное цитирование"
msgstr "Перекрестное цитирование"
msgid "OP moderation"
msgstr "ОП-модерация"
msgid "Allow thread starters to delete replies"
msgstr "Разрешить создателям тредов удалять ответы"
msgid "OP moderation is enabled"
msgstr "ОП-модерация включена"

View File

@ -90,6 +90,7 @@ var _messages = {
files: 'Files',
collapse: 'Collapse',
asMod: 'as Mod',
asOP: 'as OP',
historyEmpty: 'History is empty',
noDataLoaded: 'No data was loaded',
unable_load_20: 'Unable to load 2.0 boards list',
@ -205,6 +206,7 @@ var _messages = {
files: 'Файлы',
collapse: 'Свернуть',
asMod: 'от лица модератора',
asOP: 'от лица ОПа',
historyEmpty: 'История пуста',
noDataLoaded: 'Данные не загружены',
unable_load_20: 'Unable to load 2.0 boards list',
@ -2452,6 +2454,7 @@ function readyset() {
<ul>
<li class="menu-delete">${makeIcon('x')}<span>${_l.del}</span></li>
${!isOP ? `
${+opmod ? `<li class="menu-delete menu-delete-op">${makeIcon('x')}<span>${_l.del} ${_l.asOP}</span></li>`: ''}
<li class="menu-hide">${makeIcon('hide')}<span>${_l.hidePost}</span></li>
<li class="menu-unhide">${makeIcon('unhide')}<span>${_l.unhidePost}</span></li>
`: ''}
@ -2559,6 +2562,7 @@ function readyset() {
else
fd.append('post[]', $item.parents('.postnode').data('id'))
fd.append('moddelete', $this.hasClass('menu-delete-mod'))
fd.append('opdelete', $this.hasClass('menu-delete-op'))
fd.append('board', isFile
? menu.__menuProps.board
: $item.parents('.postnode').data('board'))
@ -3040,6 +3044,10 @@ function deleteItems(items, bySelf=true, markOnly=false) {
, fileErrors = []
items.forEach(item => {
let deletedClasses = 'deleted'
+ (item.by_op ? ' op-deleted' : '')
+ (item.by_mod ? ' mod-deleted' : '')
if (item.action == 'delete_post' || item.itemtype == 'post') {
if (bySelf && !item.success) {
postErrors.push(item)
@ -3051,7 +3059,7 @@ function deleteItems(items, bySelf=true, markOnly=false) {
if ($thread.length) {
if (markOnly || !ispage) {
$thread.addClass('deleted')
.find('.reply, figure').addClass('deleted')
.find('.reply, figure').addClass(deletedClasses)
if (!ispage) {
insideDeletedThread = true
$('form[name=postform], .qrl, #rswapper').remove()
@ -3067,7 +3075,7 @@ function deleteItems(items, bySelf=true, markOnly=false) {
}
else if ($reply.length) {
if (markOnly)
$reply.addClass('deleted')
$reply.addClass(deletedClasses)
else {
let $reply = $(`#delform [id^=reply${item.id}]`)
if ($reply.length) {
@ -3091,7 +3099,7 @@ function deleteItems(items, bySelf=true, markOnly=false) {
}
let $fig = $(`figure[data-fileid=${item.id}]`)
if (markOnly)
$fig.addClass('deleted')
$fig.addClass(deletedClasses)
else
$fig.replaceWith(`<div class="nothumb">${_l.fileRemoved}</div>`)
filesDeleted.push('#'+item.id)
@ -3111,15 +3119,15 @@ function deleteItems(items, bySelf=true, markOnly=false) {
}
if (postsDeleted.length) {
let msg = postsDeleted.length > 1 ?
`${_l.posts} ${postsDeleted.join(', ')} ${_l.deletedMulti}.`
:`${_l.post} ${postsDeleted[0]} ${_l.deleted}.`
let msg = postsDeleted.length > 1
? `${_l.posts} ${postsDeleted.join(', ')} ${_l.deletedMulti}.`
: `${_l.post} ${postsDeleted[0]} ${_l.deleted}.`
pups[bySelf ? 'succ' : 'info'](msg, {time: 2 + postsDeleted.length})
}
if (filesDeleted.length) {
let msg = filesDeleted.length > 1 ?
`${_l.files} ${filesDeleted.join(', ')} ${_l.deletedMulti}.`
:`${_l.file} ${filesDeleted[0]} ${_l.deleted}.`
let msg = filesDeleted.length > 1
? `${_l.files} ${filesDeleted.join(', ')} ${_l.deletedMulti}.`
: `${_l.file} ${filesDeleted[0]} ${_l.deleted}.`
pups[bySelf ? 'succ' : 'info'](msg, {time: 2 + filesDeleted.length})
}
if (postErrors.length)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long