blog: move to a seperate package

This commit is contained in:
undefined committed 2023-02-27 19:48:45 +08:00
1 parent 58d2f59f19
commit 1a4fde4119
18 files changed
+251 -253

No files matched your search

-1
View File
@@ -84,7 +84,6 @@ Begin Time: 시작 시각
Belongs to: 소유
Bio Visibility: 소개 공개
Bio: 소개
Blog: Blog
Bold: 굵게
Boom!: 펑!
Browser: 브라우저
-4
View File
@@ -97,10 +97,6 @@ Begin Time: 开始时间
Belongs to: 属于
Bio Visibility: 个人简介可见性
Bio: 个人简介
blog_detail: 博客详情
blog_edit: 编辑博客
blog_main: 博客
Blog: 博客
Bold: 加粗
Boom!: 炸了!
Browser: 浏览器
-1
View File
@@ -50,7 +50,6 @@ Begin Time: 開始時間
Belongs to: 屬於
Bio Visibility: 個人簡介可見性
Bio: 個人簡介
Blog: 部落格
Boom!: 炸了!
Browser: 瀏覽器
Built-in: 內建
-125
View File
@@ -1,125 +0,0 @@
import { ObjectId } from 'mongodb';
import { DiscussionNotFoundError } from '../error';
import { BlogDoc } from '../interface';
import paginate from '../lib/paginate';
import * as blog from '../model/blog';
import { PRIV } from '../model/builtin';
import * as oplog from '../model/oplog';
import * as system from '../model/system';
import user from '../model/user';
import { Handler, param, Types } from '../service/server';
class BlogHandler extends Handler {
ddoc?: BlogDoc;
@param('did', Types.ObjectId, true)
async _prepare(domainId: string, did: ObjectId) {
if (did) {
this.ddoc = await blog.get(did);
if (!this.ddoc) throw new DiscussionNotFoundError(domainId, did);
}
}
}
class BlogUserHandler extends BlogHandler {
@param('uid', Types.Int)
@param('page', Types.PositiveInt, true)
async get(domainId: string, uid: number, page = 1) {
const [ddocs, dpcount] = await paginate(
blog.getMulti({ owner: uid }),
page,
10,
);
const udoc = await user.getById(domainId, uid);
this.response.template = 'blog_main.html';
this.response.body = {
ddocs,
dpcount,
udoc,
page,
};
}
}
class BlogDetailHandler extends BlogHandler {
@param('did', Types.ObjectId)
async get(domainId: string, did: ObjectId) {
const dsdoc = this.user.hasPriv(PRIV.PRIV_USER_PROFILE)
? await blog.getStatus(did, this.user._id)
: null;
const udoc = await user.getById(domainId, this.ddoc.owner);
if (!dsdoc?.view) {
await Promise.all([
blog.inc(did, 'views', 1),
blog.setStatus(did, this.user._id, { view: true }),
]);
}
this.response.template = 'blog_detail.html';
this.response.body = {
ddoc: this.ddoc, dsdoc, udoc,
};
}
async post() {
this.checkPriv(PRIV.PRIV_USER_PROFILE);
}
@param('did', Types.ObjectId)
async postStar(domainId: string, did: ObjectId) {
await blog.setStar(did, this.user._id, true);
this.back({ star: true });
}
@param('did', Types.ObjectId)
async postUnstar(domainId: string, did: ObjectId) {
await blog.setStar(did, this.user._id, false);
this.back({ star: false });
}
}
class BlogEditHandler extends BlogHandler {
async get() {
this.response.template = 'blog_edit.html';
this.response.body = { ddoc: this.ddoc };
}
@param('title', Types.Title)
@param('content', Types.Content)
async postCreate(domainId: string, title: string, content: string) {
await this.limitRate('add_blog', 3600, 60);
const did = await blog.add(this.user._id, title, content, this.request.ip);
this.response.body = { did };
this.response.redirect = this.url('blog_detail', { uid: this.user._id, did });
}
@param('did', Types.ObjectId)
@param('title', Types.Title)
@param('content', Types.Content)
async postUpdate(domainId: string, did: ObjectId, title: string, content: string) {
if (!this.user.own(this.ddoc)) this.checkPriv(PRIV.PRIV_EDIT_SYSTEM);
await Promise.all([
blog.edit(did, title, content),
oplog.log(this, 'blog.edit', this.ddoc),
]);
this.response.body = { did };
this.response.redirect = this.url('blog_detail', { uid: this.user._id, did });
}
@param('did', Types.ObjectId)
async postDelete(domainId: string, did: ObjectId) {
if (!this.user.own(this.ddoc)) this.checkPriv(PRIV.PRIV_EDIT_SYSTEM);
await Promise.all([
blog.del(did),
oplog.log(this, 'blog.delete', this.ddoc),
]);
this.response.redirect = this.url('blog_main', { uid: this.ddoc.owner });
}
}
export async function apply(ctx) {
if (!system.get('server.blog')) return;
ctx.Route('blog_main', '/blog/:uid', BlogUserHandler);
ctx.Route('blog_create', '/blog/:uid/create', BlogEditHandler, PRIV.PRIV_USER_PROFILE);
ctx.Route('blog_detail', '/blog/:uid/:did', BlogDetailHandler);
ctx.Route('blog_edit', '/blog/:uid/:did/edit', BlogEditHandler, PRIV.PRIV_USER_PROFILE);
}
-15
View File
@@ -486,20 +486,6 @@ export interface DiscussionTailReplyDoc {
editor?: number;
}
export interface BlogDoc {
docType: document['TYPE_BLOG'];
docId: ObjectId;
owner: number;
title: string;
content: string;
ip: string;
updateAt: Date;
nReply: number;
views: number;
reply: any[];
react: Record<string, number>;
}
export interface TokenDoc {
_id: string,
tokenType: number,
@@ -677,7 +663,6 @@ declare module './service/db' {
export interface Model {
blacklist: typeof import('./model/blacklist').default,
blog: typeof import('./model/blog'),
builtin: typeof import('./model/builtin'),
contest: typeof import('./model/contest'),
discussion: typeof import('./model/discussion'),
-89
View File
@@ -1,89 +0,0 @@
import { omit } from 'lodash';
import { Filter, ObjectId } from 'mongodb';
import { BlogDoc } from '../interface';
import { NumberKeys } from '../typeutils';
import * as document from './document';
export async function add(
owner: number, title: string, content: string,
ip: string | null = null,
): Promise<ObjectId> {
const payload: Partial<BlogDoc> = {
content,
owner,
title,
ip,
nReply: 0,
updateAt: new Date(),
views: 0,
};
const res = await document.add(
'system', payload.content!, payload.owner!, document.TYPE_BLOG,
null, null, null, omit(payload, ['domainId', 'content', 'owner']),
);
payload.docId = res;
return payload.docId;
}
export async function get(did: ObjectId): Promise<BlogDoc> {
return await document.get('system', document.TYPE_BLOG, did);
}
export function edit(did: ObjectId, title: string, content: string): Promise<BlogDoc> {
const payload = { title, content };
return document.set('system', document.TYPE_BLOG, did, payload);
}
export function inc(did: ObjectId, key: NumberKeys<BlogDoc>, value: number): Promise<BlogDoc | null> {
return document.inc('system', document.TYPE_BLOG, did, key, value);
}
export function del(did: ObjectId): Promise<never> {
return Promise.all([
document.deleteOne('system', document.TYPE_BLOG, did),
document.deleteMultiStatus('system', document.TYPE_BLOG, { docId: did }),
]) as any;
}
export function count(query: Filter<BlogDoc>) {
return document.count('system', document.TYPE_BLOG, query);
}
export function getMulti(query: Filter<BlogDoc> = {}) {
return document.getMulti('system', document.TYPE_BLOG, query)
.sort({ _id: -1 });
}
export async function addReply(did: ObjectId, owner: number, content: string, ip: string): Promise<ObjectId> {
const [[, drid]] = await Promise.all([
document.push('system', document.TYPE_BLOG, did, 'reply', content, owner, { ip }),
document.incAndSet('system', document.TYPE_BLOG, did, 'nReply', 1, { updateAt: new Date() }),
]);
return drid;
}
export function setStar(did: ObjectId, uid: number, star: boolean) {
return document.setStatus('system', document.TYPE_BLOG, did, uid, { star });
}
export function getStatus(did: ObjectId, uid: number) {
return document.getStatus('system', document.TYPE_BLOG, did, uid);
}
export function setStatus(did: ObjectId, uid: number, $set) {
return document.setStatus('system', document.TYPE_BLOG, did, uid, $set);
}
global.Hydro.model.blog = {
add,
get,
inc,
edit,
del,
count,
getMulti,
addReply,
setStar,
getStatus,
setStatus,
};
+1 -4
View File
@@ -5,7 +5,7 @@ import {
} from 'mongodb';
import { Context } from '../context';
import {
BlogDoc, Content, DiscussionDoc,
Content, DiscussionDoc,
DiscussionReplyDoc, ProblemDoc, ProblemStatusDoc,
Tdoc, TrainingDoc,
} from '../interface';
@@ -30,7 +30,6 @@ export const TYPE_CONTEST: 30 = 30;
export const TYPE_TRAINING: 40 = 40;
/** @deprecated use `TYPE_CONTEST` with rule `homework` instead. */
export const TYPE_HOMEWORK: 60 = 60;
export const TYPE_BLOG: 70 = 70;
export interface DocType {
[TYPE_PROBLEM]: ProblemDoc;
@@ -41,7 +40,6 @@ export interface DocType {
[TYPE_DISCUSSION_REPLY]: DiscussionReplyDoc;
[TYPE_CONTEST]: Tdoc;
[TYPE_TRAINING]: TrainingDoc;
[TYPE_BLOG]: BlogDoc;
}
export interface DocStatusType {
@@ -499,5 +497,4 @@ global.Hydro.model.document = {
TYPE_PROBLEM_LIST,
TYPE_PROBLEM_SOLUTION,
TYPE_TRAINING,
TYPE_BLOG,
};
-1
View File
@@ -254,7 +254,6 @@ SystemSetting(
Setting('setting_server', 'server.language', 'zh_CN', langRange, 'server.language', 'Default display language'),
Setting('setting_server', 'server.login', true, 'boolean', 'server.login', 'Allow builtin-login', FLAG_PRO),
Setting('setting_server', 'server.message', true, 'boolean', 'server.message', 'Allow users send messages'),
Setting('setting_server', 'server.blog', true, 'boolean', 'server.blog', 'Allow users post blog'),
Setting('setting_server', 'server.checkUpdate', true, 'boolean', 'server.checkUpdate', 'Daily update check'),
Setting('setting_server', 'server.ignoreUA', ignoreUA, 'textarea', 'server.ignoreUA', 'ignoredUA'),
ServerLangSettingNode,
-1
View File
@@ -12,7 +12,6 @@ export * as SystemModel from './model/system';
export * as TrainingModel from './model/training';
export * as OpcountModel from './model/opcount';
export * as OplogModel from './model/oplog';
export * as BlogModel from './model/blog';
export * as SettingModel from './model/setting';
export * as DiscussionModel from './model/discussion';
export * as DocumentModel from './model/document';