Sudetekešní upravování

This commit is contained in:
sneedmaster
2026-04-21 15:56:37 +02:00
parent 1806796545
commit 5b882564cf
6 changed files with 153 additions and 7 deletions

View File

@@ -30,7 +30,7 @@ Jestli jste na debian založené distribuci linuxu a nahrávání souborů vám
- cd imei
- sudo ./imei.sh
## Vývoj
## Vývoj / Roadmap
Základní funkce jsou již implementované, ale plánujeme přidat i nové
@@ -55,10 +55,10 @@ Základní funkce jsou již implementované, ale plánujeme přidat i nové
- [x] Vlastní stránky
- [x] Záznamy
- [x] Archiv
- [ ] Upravování příspěvků
- [ ] Přesouvání příspěvků
- [X] Upravování příspěvků
- [ ] Více info o IP na IP stránce
- [ ] Poznámky k IP adrese
- [ ] Přesouvání příspěvků
- [ ] Nastavení stránky a správa assetů z UI
- [ ] phash
- [ ] Přímé zprávy

View File

@@ -82,8 +82,13 @@ const CreatePostForm = z.object({
deletion_code: zRequiredField(zDeletionCode),
});
// Generic
const UpdatePostContentForm = z.object({
board: zRequiredField(zBoardID),
id: zRequiredField(zPostID),
content: zRequiredField(z.string()),
});
// Post actions
const ZPostActionsForm = z.object({
// Common
posts: zMultiField(zCompPostID),
@@ -131,5 +136,6 @@ export {
zCaptcha,
zDeletionCode,
CreatePostForm,
UpdatePostContentForm,
ZPostActionsForm,
};

View File

@@ -152,8 +152,15 @@ const PostComponent = ({
{canUser(ctx.user, CzchanPerm.VIEW_METADATA) && (
<>
<b>
<a href={`/mod/post-info/${board.id}/${post.id}`}>[M]</a>
</b>
<a href={`/mod/post_info/${board.id}/${post.id}`}>[I]</a>
</b>{" "}
</>
)}
{canUser(ctx.user, CzchanPerm.EDIT_POSTS) && (
<>
<b>
<a href={`/mod/edit/post_content/${board.id}/${post.id}`}>[ED]</a>
</b>{" "}
</>
)}
</div>

View File

@@ -0,0 +1,46 @@
import { readBoard } from "../../../../db/board.js";
import { readPost, updatePostContent } from "../../../../db/post.js";
import { CzchanError } from "../../../../lib/error.js";
import { formatContent } from "../../../../lib/formatting.js";
import { czchanLog } from "../../../../lib/log.js";
import { canUser, CzchanPerm } from "../../../../lib/permissions.js";
import { canonicalPostURL } from "../../../../lib/util.js";
import { UpdatePostContentForm } from "../../../../schema/validation/post.js";
import type { Request, Response } from "express";
import formidable from "formidable";
export default async (req: Request, res: Response) => {
if (!canUser(req.user, CzchanPerm.EDIT_POSTS)) {
throw new CzchanError("K tomuto nemáš oprávnění.", 403);
}
const parser = formidable({});
const [fields, _] = await parser.parse(req);
const { board, id, content } = UpdatePostContentForm.parse(fields);
const board_ = await readBoard(board);
if (
board_.config.private &&
!canUser(req.user, CzchanPerm.VIEW_PRIVATE_BOARDS)
) {
throw new CzchanError(`K nástěnce /${board_.id}/ nemáš přístup.`, 403);
}
const post = await readPost(board_.id, id);
const content_unformatted = content;
const content_formatted = (await formatContent(req, board_.id, content))
.output;
await updatePostContent(post, content_unformatted, content_formatted);
await czchanLog(
"mod",
"info",
`Upraven obsah příspěvku: >>>/${board_.id}/${post.id}`,
req.user?.username,
);
res.redirect(canonicalPostURL(post));
};

View File

@@ -0,0 +1,80 @@
import { readBoard } from "../../../../db/board.js";
import { readPost } from "../../../../db/post.js";
import { CzchanError } from "../../../../lib/error.js";
import { canUser, CzchanPerm } from "../../../../lib/permissions.js";
import { canonicalPostURL } from "../../../../lib/util.js";
import type { Board, Post } from "../../../../schema/tables.js";
import { zBoardID } from "../../../../schema/validation/common.js";
import { zPostID } from "../../../../schema/validation/post.js";
import Page from "../../../components/chrome/page.js";
import PageBody from "../../../components/chrome/page_body.js";
import PageHead from "../../../components/chrome/page_head.js";
import { Form, FormButton, FormField } from "../../../components/forms/form.js";
import { getCtx, type TemplateCtx } from "../../../ctx.js";
import type { PropsWithChildren } from "@kitajs/html";
import type { Request, Response } from "express";
export default async (req: Request, res: Response) => {
const ctx = await getCtx(req);
if (!canUser(ctx.user, CzchanPerm.EDIT_POSTS)) {
throw new CzchanError("K tomuto nemáš oprávnění.", 403);
}
const board = await readBoard(zBoardID.parse(req.params.board));
if (
board.config.private &&
!canUser(ctx.user, CzchanPerm.VIEW_PRIVATE_BOARDS)
) {
throw new CzchanError(`K nástěnce /${board.id}/ nemáš přístup.`, 403);
}
const post = await readPost(board.id, zPostID.parse(req.params.id));
const html = Template(ctx, board, post);
res.send(html);
};
const Template = (ctx: TemplateCtx, board: Board, post: Post) => (
<Page>
<PageHead ctx={ctx} title="Úprava příspěvku" description="" />
<PageBody ctx={ctx}>
<h1 class="title center">
Úprava příspěvku (
<a href={canonicalPostURL(post)}>
&gt;&gt;&gt;/<span safe>{board.id}</span>/{post.id}
</a>
)
</h1>
<UpdateForm ctx={ctx} board={board} post={post} />
<hr />
</PageBody>
</Page>
);
const UpdateForm = ({
board,
post,
}: PropsWithChildren<{ ctx: TemplateCtx; board: Board; post: Post }>) => (
<form method="post" action="/mod/actions/update_post_content">
<input name="board" type="hidden" value={board.id} />
<input name="id" type="hidden" value={post.id.toString()} />
<Form center>
<FormField
label={
<>
Obsah
<br />
<small>(max {board.config.max_length})</small>
</>
}
>
<textarea name="content" rows="10" cols="35" safe>
{post.content_unformatted}
</textarea>
</FormField>
<FormButton submit="Upravit" action="update_post_content" />
</Form>
</form>
);

View File

@@ -12,6 +12,7 @@ import modActionNewsActions from "../routes/mod/actions/news_actions.js";
import modActionRestrictionActions from "../routes/mod/actions/restriction_actions.js";
import modActionUpdateBoardConfig from "../routes/mod/actions/update_board_config.js";
import modActionUpdateNewsContent from "../routes/mod/actions/update_news_content.js";
import modActionUpdatePostContent from "../routes/mod/actions/update_post_content.js";
import modActionUpdateUserPassword from "../routes/mod/actions/update_user_password.js";
import modActionUpdateUserPermissions from "../routes/mod/actions/update_user_permissions.js";
import modActionUserActions from "../routes/mod/actions/user_actions.js";
@@ -20,6 +21,7 @@ import modBans from "../routes/mod/bans.js";
import modBoards from "../routes/mod/boards.js";
import modEditBoardConfig from "../routes/mod/edit/board_config.js";
import modEditNewsContent from "../routes/mod/edit/news_content.js";
import modEditPostContent from "../routes/mod/edit/post_content.js";
import modEditUserPermissions from "../routes/mod/edit/user_permissions.js";
import modFilters from "../routes/mod/filters.js";
import modIndex from "../routes/mod/index.js";
@@ -50,12 +52,13 @@ const registerModRoutes = (router: Router) => {
// Mod info
router.get("/mod/ip/:ip", e(modIP));
router.get("/mod/post-info/:board/:id", e(modPostInfo));
router.get("/mod/post_info/:board/:id", e(modPostInfo));
// Edit pages
router.get("/mod/edit/user_permissions/:user", e(modEditUserPermissions));
router.get("/mod/edit/board_config/:board", e(modEditBoardConfig));
router.get("/mod/edit/news_content/:news", e(modEditNewsContent));
router.get("/mod/edit/post_content/:board/:id", e(modEditPostContent));
// Edit page actions
router.post(
@@ -70,6 +73,10 @@ const registerModRoutes = (router: Router) => {
"/mod/actions/update_news_content",
e(modActionUpdateNewsContent),
);
router.post(
"/mod/actions/update_post_content",
e(modActionUpdatePostContent),
);
// Action pages
router.post("/mod/actions/create_user", e(modActionCreateUser));