summaryrefslogtreecommitdiff
path: root/src/server/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/api')
-rw-r--r--src/server/api/common/inject-featured.ts45
-rw-r--r--src/server/api/common/inject-promo.ts10
-rw-r--r--src/server/api/common/signup.ts1
-rw-r--r--src/server/api/define.ts1
-rw-r--r--src/server/api/endpoints/i/update.ts5
-rw-r--r--src/server/api/endpoints/notes/featured.ts1
-rw-r--r--src/server/api/endpoints/notes/global-timeline.ts4
-rw-r--r--src/server/api/endpoints/notes/hybrid-timeline.ts4
-rw-r--r--src/server/api/endpoints/notes/local-timeline.ts4
-rw-r--r--src/server/api/endpoints/notes/timeline.ts4
10 files changed, 69 insertions, 10 deletions
diff --git a/src/server/api/common/inject-featured.ts b/src/server/api/common/inject-featured.ts
new file mode 100644
index 0000000000..ce6d421bb1
--- /dev/null
+++ b/src/server/api/common/inject-featured.ts
@@ -0,0 +1,45 @@
+import rndstr from 'rndstr';
+import { Note } from '../../../models/entities/note';
+import { User } from '../../../models/entities/user';
+import { Notes, UserProfiles } from '../../../models';
+import { generateMuteQuery } from './generate-mute-query';
+import { ensure } from '../../../prelude/ensure';
+
+// TODO: リアクション、Renote、返信などをしたノートは除外する
+
+export async function injectFeatured(timeline: Note[], user?: User | null) {
+ if (timeline.length < 5) return;
+
+ if (user) {
+ const profile = await UserProfiles.findOne(user.id).then(ensure);
+ if (!profile.injectFeaturedNote) return;
+ }
+
+ const max = 30;
+ const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで
+
+ const query = Notes.createQueryBuilder('note')
+ .addSelect('note.score')
+ .where('note.userHost IS NULL')
+ .andWhere(`note.score > 0`)
+ .andWhere(`note.createdAt > :date`, { date: new Date(Date.now() - day) })
+ .andWhere(`note.visibility = 'public'`)
+ .leftJoinAndSelect('note.user', 'user');
+
+ if (user) generateMuteQuery(query, user);
+
+ const notes = await query
+ .orderBy('note.score', 'DESC')
+ .take(max)
+ .getMany();
+
+ if (notes.length === 0) return;
+
+ // Pick random one
+ const featured = notes[Math.floor(Math.random() * notes.length)];
+
+ (featured as any)._featuredId_ = rndstr('a-z0-9', 8);
+
+ // Inject featured
+ timeline.splice(3, 0, featured);
+}
diff --git a/src/server/api/common/inject-promo.ts b/src/server/api/common/inject-promo.ts
index 60817329c3..f694ce6ea0 100644
--- a/src/server/api/common/inject-promo.ts
+++ b/src/server/api/common/inject-promo.ts
@@ -4,14 +4,14 @@ import { User } from '../../../models/entities/user';
import { PromoReads, PromoNotes, Notes, Users } from '../../../models';
import { ensure } from '../../../prelude/ensure';
-export async function injectPromo(user: User, timeline: Note[]) {
+export async function injectPromo(timeline: Note[], user?: User | null) {
if (timeline.length < 5) return;
// TODO: readやexpireフィルタはクエリ側でやる
- const reads = await PromoReads.find({
+ const reads = user ? await PromoReads.find({
userId: user.id
- });
+ }) : [];
let promos = await PromoNotes.find();
@@ -20,15 +20,15 @@ export async function injectPromo(user: User, timeline: Note[]) {
if (promos.length === 0) return;
+ // Pick random promo
const promo = promos[Math.floor(Math.random() * promos.length)];
- // Pick random promo
const note = await Notes.findOne(promo.noteId).then(ensure);
// Join
note.user = await Users.findOne(note.userId).then(ensure);
- (note as any)._prInjectionId_ = rndstr('a-z0-9', 8);
+ (note as any)._prId_ = rndstr('a-z0-9', 8);
// Inject promo
timeline.splice(3, 0, note);
diff --git a/src/server/api/common/signup.ts b/src/server/api/common/signup.ts
index f0eb27e5e4..b6e13b36f1 100644
--- a/src/server/api/common/signup.ts
+++ b/src/server/api/common/signup.ts
@@ -88,7 +88,6 @@ export async function signup(username: User['username'], password: UserProfile['
await transactionalEntityManager.save(new UserProfile({
userId: account.id,
autoAcceptFollowed: true,
- autoWatch: false,
password: hash,
}));
diff --git a/src/server/api/define.ts b/src/server/api/define.ts
index d4ca5aa809..1fd4543bd0 100644
--- a/src/server/api/define.ts
+++ b/src/server/api/define.ts
@@ -5,6 +5,7 @@ import { ApiError } from './error';
import { App } from '../../models/entities/app';
import { SchemaType } from '../../misc/schema';
+// TODO: defaultが設定されている場合はその型も考慮する
type Params<T extends IEndpointMeta> = {
[P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends Function
? ReturnType<NonNullable<T['params']>[P]['transform']>
diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
index 08c37a4f63..5c4a9576e1 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -126,6 +126,10 @@ export const meta = {
}
},
+ injectFeaturedNote: {
+ validator: $.optional.bool,
+ },
+
alwaysMarkNsfw: {
validator: $.optional.bool,
desc: {
@@ -195,6 +199,7 @@ export default define(meta, async (ps, user, app) => {
if (typeof ps.autoAcceptFollowed == 'boolean') profileUpdates.autoAcceptFollowed = ps.autoAcceptFollowed;
if (typeof ps.isCat == 'boolean') updates.isCat = ps.isCat;
if (typeof ps.autoWatch == 'boolean') profileUpdates.autoWatch = ps.autoWatch;
+ if (typeof ps.injectFeaturedNote == 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote;
if (typeof ps.alwaysMarkNsfw == 'boolean') profileUpdates.alwaysMarkNsfw = ps.alwaysMarkNsfw;
if (ps.avatarId) {
diff --git a/src/server/api/endpoints/notes/featured.ts b/src/server/api/endpoints/notes/featured.ts
index 5fc60eeccf..0dc705de7a 100644
--- a/src/server/api/endpoints/notes/featured.ts
+++ b/src/server/api/endpoints/notes/featured.ts
@@ -46,6 +46,7 @@ export default define(meta, async (ps, user) => {
const query = Notes.createQueryBuilder('note')
.addSelect('note.score')
.where('note.userHost IS NULL')
+ .andWhere(`note.score > 0`)
.andWhere(`note.createdAt > :date`, { date: new Date(Date.now() - day) })
.andWhere(`note.visibility = 'public'`)
.leftJoinAndSelect('note.user', 'user');
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
index 0f69896de2..26b0cb0f5a 100644
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ b/src/server/api/endpoints/notes/global-timeline.ts
@@ -9,6 +9,7 @@ import { generateMuteQuery } from '../../common/generate-mute-query';
import { activeUsersChart } from '../../../../services/chart';
import { generateRepliesQuery } from '../../common/generate-replies-query';
import { injectPromo } from '../../common/inject-promo';
+import { injectFeatured } from '../../common/inject-featured';
export const meta = {
desc: {
@@ -90,7 +91,8 @@ export default define(meta, async (ps, user) => {
const timeline = await query.take(ps.limit!).getMany();
- await injectPromo(user, timeline);
+ await injectPromo(timeline, user);
+ await injectFeatured(timeline, user);
process.nextTick(() => {
if (user) {
diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts
index f30fbab8a1..b0a73d1d7d 100644
--- a/src/server/api/endpoints/notes/hybrid-timeline.ts
+++ b/src/server/api/endpoints/notes/hybrid-timeline.ts
@@ -11,6 +11,7 @@ import { generateMuteQuery } from '../../common/generate-mute-query';
import { activeUsersChart } from '../../../../services/chart';
import { generateRepliesQuery } from '../../common/generate-replies-query';
import { injectPromo } from '../../common/inject-promo';
+import { injectFeatured } from '../../common/inject-featured';
export const meta = {
desc: {
@@ -170,7 +171,8 @@ export default define(meta, async (ps, user) => {
const timeline = await query.take(ps.limit!).getMany();
- await injectPromo(user, timeline);
+ await injectPromo(timeline, user);
+ await injectFeatured(timeline, user);
process.nextTick(() => {
if (user) {
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
index 68558fb84b..a74dc3b15c 100644
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ b/src/server/api/endpoints/notes/local-timeline.ts
@@ -11,6 +11,7 @@ import { activeUsersChart } from '../../../../services/chart';
import { Brackets } from 'typeorm';
import { generateRepliesQuery } from '../../common/generate-replies-query';
import { injectPromo } from '../../common/inject-promo';
+import { injectFeatured } from '../../common/inject-featured';
export const meta = {
desc: {
@@ -123,7 +124,8 @@ export default define(meta, async (ps, user) => {
const timeline = await query.take(ps.limit!).getMany();
- await injectPromo(user, timeline);
+ await injectPromo(timeline, user);
+ await injectFeatured(timeline, user);
process.nextTick(() => {
if (user) {
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index 8edf303e0d..3eed9f0ca8 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -9,6 +9,7 @@ import { activeUsersChart } from '../../../../services/chart';
import { Brackets } from 'typeorm';
import { generateRepliesQuery } from '../../common/generate-replies-query';
import { injectPromo } from '../../common/inject-promo';
+import { injectFeatured } from '../../common/inject-featured';
export const meta = {
desc: {
@@ -156,7 +157,8 @@ export default define(meta, async (ps, user) => {
const timeline = await query.take(ps.limit!).getMany();
- await injectPromo(user, timeline);
+ await injectPromo(timeline, user);
+ await injectFeatured(timeline, user);
process.nextTick(() => {
if (user) {