Fixed 267U.pre2

This commit is contained in:
2026-07-26 18:25:37 +09:00
parent 50bfaeafdf
commit 317d00a284
1286 changed files with 80222 additions and 1 deletions
@@ -0,0 +1,173 @@
import define from "../../define.js";
import { genId } from "../../../../misc/gen-id.js";
import { Antennas, UserLists, UserGroupJoinings } from "../../../../models/index.js";
import { ApiError } from "../../error.js";
import { publishInternalEvent } from "../../../../services/stream.js";
export const meta = {
tags: [
"antennas"
],
requireCredential: true,
kind: "write:account",
errors: {
noSuchUserList: {
message: "No such user list.",
code: "NO_SUCH_USER_LIST",
id: "95063e93-a283-4b8b-9aa5-bcdb8df69a7f"
},
noSuchUserGroup: {
message: "No such user group.",
code: "NO_SUCH_USER_GROUP",
id: "aa3c0b9a-8cae-47c0-92ac-202ce5906682"
},
tooManyAntennas: {
message: "Too many antennas.",
code: "TOO_MANY_ANTENNAS",
id: "c3a5a51e-04d4-11ee-be56-0242ac120002"
},
noKeywords: {
message: "No keywords.",
code: "NO_KEYWORDS",
id: "aa975b74-1ddb-11ee-be56-0242ac120002"
}
},
res: {
type: "object",
optional: false,
nullable: false,
ref: "Antenna"
}
};
export const paramDef = {
type: "object",
properties: {
name: {
type: "string",
minLength: 1,
maxLength: 100
},
src: {
type: "string",
enum: [
"home",
"all",
"users",
"list",
"group",
"instances"
]
},
userListId: {
type: "string",
format: "misskey:id",
nullable: true
},
userGroupId: {
type: "string",
format: "misskey:id",
nullable: true
},
keywords: {
type: "array",
items: {
type: "array",
items: {
type: "string"
}
}
},
excludeKeywords: {
type: "array",
items: {
type: "array",
items: {
type: "string"
}
}
},
users: {
type: "array",
items: {
type: "string"
}
},
instances: {
type: "array",
items: {
type: "string"
}
},
caseSensitive: {
type: "boolean"
},
withReplies: {
type: "boolean"
},
withFile: {
type: "boolean"
},
notify: {
type: "boolean"
}
},
required: [
"name",
"src",
"keywords",
"excludeKeywords",
"users",
"instances",
"caseSensitive",
"withReplies",
"withFile",
"notify"
]
};
export default define(meta, paramDef, async (ps, user)=>{
if (user.movedToUri != null) throw new ApiError(meta.errors.noSuchUserGroup);
if (ps.keywords.length === 0) throw new ApiError(meta.errors.noKeywords);
let userList;
let userGroupJoining;
const antennas = await Antennas.findBy({
userId: user.id
});
if (antennas.length > 5 && !user.isAdmin) {
throw new ApiError(meta.errors.tooManyAntennas);
}
if (ps.src === "list" && ps.userListId) {
userList = await UserLists.findOneBy({
id: ps.userListId,
userId: user.id
});
if (userList == null) {
throw new ApiError(meta.errors.noSuchUserList);
}
} else if (ps.src === "group" && ps.userGroupId) {
userGroupJoining = await UserGroupJoinings.findOneBy({
userGroupId: ps.userGroupId,
userId: user.id
});
if (userGroupJoining == null) {
throw new ApiError(meta.errors.noSuchUserGroup);
}
}
const antenna = await Antennas.insert({
id: genId(),
createdAt: new Date(),
userId: user.id,
name: ps.name,
src: ps.src,
userListId: userList ? userList.id : null,
userGroupJoiningId: userGroupJoining ? userGroupJoining.id : null,
keywords: ps.keywords,
excludeKeywords: ps.excludeKeywords,
users: ps.users,
instances: ps.instances,
caseSensitive: ps.caseSensitive,
withReplies: ps.withReplies,
withFile: ps.withFile,
notify: ps.notify
}).then((x)=>Antennas.findOneByOrFail(x.identifiers[0]));
publishInternalEvent("antennaCreated", antenna);
return await Antennas.pack(antenna);
});
@@ -0,0 +1,41 @@
import define from "../../define.js";
import { ApiError } from "../../error.js";
import { Antennas } from "../../../../models/index.js";
import { publishInternalEvent } from "../../../../services/stream.js";
export const meta = {
tags: [
"antennas"
],
requireCredential: true,
kind: "write:account",
errors: {
noSuchAntenna: {
message: "No such antenna.",
code: "NO_SUCH_ANTENNA",
id: "b34dcf9d-348f-44bb-99d0-6c9314cfe2df"
}
}
};
export const paramDef = {
type: "object",
properties: {
antennaId: {
type: "string",
format: "misskey:id"
}
},
required: [
"antennaId"
]
};
export default define(meta, paramDef, async (ps, user)=>{
const antenna = await Antennas.findOneBy({
id: ps.antennaId,
userId: user.id
});
if (antenna == null) {
throw new ApiError(meta.errors.noSuchAntenna);
}
await Antennas.delete(antenna.id);
publishInternalEvent("antennaDeleted", antenna);
});
@@ -0,0 +1,32 @@
import define from "../../define.js";
import { Antennas } from "../../../../models/index.js";
export const meta = {
tags: [
"antennas",
"account"
],
requireCredential: true,
kind: "read:account",
res: {
type: "array",
optional: false,
nullable: false,
items: {
type: "object",
optional: false,
nullable: false,
ref: "Antenna"
}
}
};
export const paramDef = {
type: "object",
properties: {},
required: []
};
export default define(meta, paramDef, async (ps, me)=>{
const antennas = await Antennas.findBy({
userId: me.id
});
return await Promise.all(antennas.map((x)=>Antennas.pack(x)));
});
@@ -0,0 +1,41 @@
import define from "../../define.js";
import { Antennas } from "../../../../models/index.js";
export const meta = {
tags: [
"antennas",
"account"
],
requireCredential: true,
kind: "write:account"
};
export const paramDef = {
type: "object",
properties: {
antennaId: {
type: "string",
format: "misskey:id"
}
},
required: [
"antennaId"
]
};
export default define(meta, paramDef, async (ps, me)=>{
const antenna = await Antennas.findOneBy({
userId: me.id,
id: ps.antennaId
});
if (!antenna) {
return null;
}
// await AntennaNotes.update(
// {
// antennaId: antenna.id,
// read: false,
// },
// {
// read: true,
// },
// );
return true;
});
@@ -0,0 +1,125 @@
import define from "../../define.js";
import readNote from "../../../../services/note/read.js";
import { Antennas, Notes } from "../../../../models/index.js";
import { redisClient } from "../../../../db/redis.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js";
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js";
import { ApiError } from "../../error.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js";
import { generateExcludeMemorietQuery } from "../../common/generate-exclude-memoriet-query.js";
export const meta = {
tags: [
"antennas",
"account",
"notes"
],
requireCredential: true,
kind: "read:account",
errors: {
noSuchAntenna: {
message: "No such antenna.",
code: "NO_SUCH_ANTENNA",
id: "850926e0-fd3b-49b6-b69a-b28a5dbd82fe"
}
},
res: {
type: "object",
optional: false,
nullable: false,
properties: {
pagination: {
type: "string",
nullable: false,
optional: false
},
notes: {
type: "array",
optional: false,
nullable: false,
items: {
type: "object",
optional: false,
nullable: false,
ref: "Note"
}
}
}
}
};
export const paramDef = {
type: "object",
properties: {
antennaId: {
type: "string",
format: "misskey:id"
},
limit: {
type: "integer",
minimum: 1,
maximum: 100,
default: 10
},
pagination: {
type: "string",
default: "+"
}
},
required: [
"antennaId"
]
};
export default define(meta, paramDef, async (ps, user)=>{
const antenna = await Antennas.findOneBy({
id: ps.antennaId,
userId: user.id
});
let pagination = ps.pagination || "+";
if (antenna == null) {
throw new ApiError(meta.errors.noSuchAntenna);
}
let notes = [];
let paginationMap = [];
while(notes.length < ps.limit && pagination !== "-1"){
// exclusive range
if (pagination != "+" && !pagination.startsWith("(")) pagination = `(${pagination}`;
const noteIdsRes = await redisClient.xrevrange(`antennaTimeline:${antenna.id}`, pagination, "-", "COUNT", ps.limit - notes.length);
const noteIds = noteIdsRes.map((x)=>x[1][1]);
if (noteIds.length === 0) {
pagination = "-1";
break;
}
const query = makePaginationQuery(Notes.createQueryBuilder("note")).where("note.id IN (:...noteIds)", {
noteIds: noteIds
}).innerJoinAndSelect("note.user", "user").leftJoinAndSelect("note.reply", "reply").leftJoinAndSelect("note.renote", "renote").leftJoinAndSelect("reply.user", "replyUser").leftJoinAndSelect("renote.user", "renoteUser").andWhere("note.visibility != 'home'");
generateVisibilityQuery(query, user);
generateMutedUserQuery(query, user);
generateBlockedUserQuery(query, user);
generateExcludeMemorietQuery(query);
pagination = noteIdsRes[noteIdsRes.length - 1][0];
paginationMap = paginationMap.concat(noteIdsRes.map((x)=>[
x[1][1],
x[0]
]));
notes = notes.concat(await query.take(ps.limit - notes.length).getMany());
}
if (notes.length === 0) {
return {
pagination: "-1",
notes: []
};
} else {
readNote(user.id, notes);
}
const packedNotes = (await Notes.packMany(notes, user)).sort((a, b)=>paginationMap.findIndex((p)=>p[0] == a.id) - paginationMap.findIndex((p)=>p[0] == b.id));
if (notes.length < ps.limit) {
pagination = "-1";
} else {
// I'm so sorry, FIXME: rewrite pagination system
pagination = paginationMap.find((p)=>p[0] == packedNotes[packedNotes.length - (packedNotes.length > 1 ? 2 : 1)].id)[1];
}
return {
pagination: pagination,
notes: packedNotes
};
});
@@ -0,0 +1,47 @@
import define from "../../define.js";
import { ApiError } from "../../error.js";
import { Antennas } from "../../../../models/index.js";
export const meta = {
tags: [
"antennas",
"account"
],
requireCredential: true,
kind: "read:account",
errors: {
noSuchAntenna: {
message: "No such antenna.",
code: "NO_SUCH_ANTENNA",
id: "c06569fb-b025-4f23-b22d-1fcd20d2816b"
}
},
res: {
type: "object",
optional: false,
nullable: false,
ref: "Antenna"
}
};
export const paramDef = {
type: "object",
properties: {
antennaId: {
type: "string",
format: "misskey:id"
}
},
required: [
"antennaId"
]
};
export default define(meta, paramDef, async (ps, me)=>{
// Fetch the antenna
const antenna = await Antennas.findOneBy({
id: ps.antennaId,
userId: me.id
});
if (antenna == null) {
throw new ApiError(meta.errors.noSuchAntenna);
}
return await Antennas.pack(antenna);
});
@@ -0,0 +1,171 @@
import define from "../../define.js";
import { ApiError } from "../../error.js";
import { Antennas, UserLists, UserGroupJoinings } from "../../../../models/index.js";
import { publishInternalEvent } from "../../../../services/stream.js";
export const meta = {
tags: [
"antennas"
],
requireCredential: true,
kind: "write:account",
errors: {
noSuchAntenna: {
message: "No such antenna.",
code: "NO_SUCH_ANTENNA",
id: "10c673ac-8852-48eb-aa1f-f5b67f069290"
},
noSuchUserList: {
message: "No such user list.",
code: "NO_SUCH_USER_LIST",
id: "1c6b35c9-943e-48c2-81e4-2844989407f7"
},
noSuchUserGroup: {
message: "No such user group.",
code: "NO_SUCH_USER_GROUP",
id: "109ed789-b6eb-456e-b8a9-6059d567d385"
}
},
res: {
type: "object",
optional: false,
nullable: false,
ref: "Antenna"
}
};
export const paramDef = {
type: "object",
properties: {
antennaId: {
type: "string",
format: "misskey:id"
},
name: {
type: "string",
minLength: 1,
maxLength: 100
},
src: {
type: "string",
enum: [
"home",
"all",
"users",
"list",
"group",
"instances"
]
},
userListId: {
type: "string",
format: "misskey:id",
nullable: true
},
userGroupId: {
type: "string",
format: "misskey:id",
nullable: true
},
keywords: {
type: "array",
items: {
type: "array",
items: {
type: "string"
}
}
},
excludeKeywords: {
type: "array",
items: {
type: "array",
items: {
type: "string"
}
}
},
users: {
type: "array",
items: {
type: "string"
}
},
instances: {
type: "array",
items: {
type: "string"
}
},
caseSensitive: {
type: "boolean"
},
withReplies: {
type: "boolean"
},
withFile: {
type: "boolean"
},
notify: {
type: "boolean"
}
},
required: [
"antennaId",
"name",
"src",
"keywords",
"excludeKeywords",
"users",
"instances",
"caseSensitive",
"withReplies",
"withFile",
"notify"
]
};
export default define(meta, paramDef, async (ps, user)=>{
// Fetch the antenna
const antenna = await Antennas.findOneBy({
id: ps.antennaId,
userId: user.id
});
if (antenna == null) {
throw new ApiError(meta.errors.noSuchAntenna);
}
let userList;
let userGroupJoining;
if (ps.src === "list" && ps.userListId) {
userList = await UserLists.findOneBy({
id: ps.userListId,
userId: user.id
});
if (userList == null) {
throw new ApiError(meta.errors.noSuchUserList);
}
} else if (ps.src === "group" && ps.userGroupId) {
userGroupJoining = await UserGroupJoinings.findOneBy({
userGroupId: ps.userGroupId,
userId: user.id
});
if (userGroupJoining == null) {
throw new ApiError(meta.errors.noSuchUserGroup);
}
}
await Antennas.update(antenna.id, {
name: ps.name,
src: ps.src,
userListId: userList ? userList.id : null,
userGroupJoiningId: userGroupJoining ? userGroupJoining.id : null,
keywords: ps.keywords,
excludeKeywords: ps.excludeKeywords,
users: ps.users,
instances: ps.instances,
caseSensitive: ps.caseSensitive,
withReplies: ps.withReplies,
withFile: ps.withFile,
notify: ps.notify
});
publishInternalEvent("antennaUpdated", await Antennas.findOneByOrFail({
id: antenna.id
}));
return await Antennas.pack(antenna.id);
});