Merge branch 'develop' of https://codeberg.org/calckey/calckey into hints
This commit is contained in:
commit
6d66bee740
105 changed files with 2433 additions and 1382 deletions
|
@ -82,23 +82,28 @@ redis:
|
||||||
# user:
|
# user:
|
||||||
# pass:
|
# pass:
|
||||||
|
|
||||||
|
# ┌───────────────────────────┐
|
||||||
|
#───┘ Meilisearch configuration └─────────────────────────────────────
|
||||||
|
#meilisearch:
|
||||||
|
# host: meilisearch
|
||||||
|
# port: 7700
|
||||||
|
# ssl: false
|
||||||
|
# apiKey:
|
||||||
|
|
||||||
# ┌───────────────┐
|
# ┌───────────────┐
|
||||||
#───┘ ID generation └───────────────────────────────────────────
|
#───┘ ID generation └───────────────────────────────────────────
|
||||||
|
|
||||||
# You can select the ID generation method.
|
# No need to uncomment in most cases, but you may want to change
|
||||||
# You don't usually need to change this setting, but you can
|
# these settings if you plan to run a large and/or distributed server.
|
||||||
# change it according to your preferences.
|
|
||||||
|
|
||||||
# Available methods:
|
# cuid:
|
||||||
# aid ... Short, Millisecond accuracy
|
# # Min 16, Max 24
|
||||||
# meid ... Similar to ObjectID, Millisecond accuracy
|
# length: 16
|
||||||
# ulid ... Millisecond accuracy
|
#
|
||||||
# objectid ... This is left for backward compatibility
|
# # Set this to a unique string across workers (e.g., machine's hostname)
|
||||||
|
# # if your workers are running in multiple hosts.
|
||||||
|
# fingerprint: my-fingerprint
|
||||||
|
|
||||||
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
|
|
||||||
# ID SETTINGS AFTER THAT!
|
|
||||||
|
|
||||||
id: 'aid'
|
|
||||||
|
|
||||||
# ┌─────────────────────┐
|
# ┌─────────────────────┐
|
||||||
#───┘ Other configuration └─────────────────────────────────────
|
#───┘ Other configuration └─────────────────────────────────────
|
||||||
|
|
20
README.md
20
README.md
|
@ -89,7 +89,8 @@ If you have access to a server that supports one of the sources below, I recomme
|
||||||
|
|
||||||
- [FFmpeg](https://ffmpeg.org/) for video transcoding
|
- [FFmpeg](https://ffmpeg.org/) for video transcoding
|
||||||
- Full text search (one of the following)
|
- Full text search (one of the following)
|
||||||
- 🦔 [Sonic](https://crates.io/crates/sonic-server) (recommended)
|
- 🦔 [Sonic](https://crates.io/crates/sonic-server)
|
||||||
|
- [MeiliSearch](https://www.meilisearch.com/)
|
||||||
- [ElasticSearch](https://www.elastic.co/elasticsearch/)
|
- [ElasticSearch](https://www.elastic.co/elasticsearch/)
|
||||||
|
|
||||||
### 🏗️ Build dependencies
|
### 🏗️ Build dependencies
|
||||||
|
@ -148,7 +149,11 @@ psql postgres -c "create database calckey with encoding = 'UTF8';"
|
||||||
|
|
||||||
In Calckey's directory, fill out the `db` section of `.config/default.yml` with the correct information, where the `db` key is `calckey`.
|
In Calckey's directory, fill out the `db` section of `.config/default.yml` with the correct information, where the `db` key is `calckey`.
|
||||||
|
|
||||||
## 🦔 Set up search
|
## 🔎 Set up search
|
||||||
|
|
||||||
|
### 🦔 Sonic
|
||||||
|
|
||||||
|
Sonic is better suited for self hosters with smaller deployments. It's easier to use, uses almost no resources, and takes barely any any disk space.
|
||||||
|
|
||||||
Follow sonic's [installation guide](https://github.com/valeriansaliou/sonic#installation)
|
Follow sonic's [installation guide](https://github.com/valeriansaliou/sonic#installation)
|
||||||
|
|
||||||
|
@ -157,6 +162,17 @@ Follow sonic's [installation guide](https://github.com/valeriansaliou/sonic#inst
|
||||||
|
|
||||||
In Calckey's directory, fill out the `sonic` section of `.config/default.yml` with the correct information.
|
In Calckey's directory, fill out the `sonic` section of `.config/default.yml` with the correct information.
|
||||||
|
|
||||||
|
### Meilisearch
|
||||||
|
|
||||||
|
Meilisearch is better suited for larger deployments. It's faster but uses far more resources and disk space.
|
||||||
|
|
||||||
|
Follow Meilisearch's [quick start guide](https://www.meilisearch.com/docs/learn/getting_started/quick_start)
|
||||||
|
|
||||||
|
In Calckey's directory, fill out the `meilisearch` section of `.config/default.yml` with the correct information.
|
||||||
|
|
||||||
|
### ElasticSearch
|
||||||
|
|
||||||
|
Please don't use ElasticSearch unless you already have an ElasticSearch setup and want to continue using it for Calckey. ElasticSearch is slow, heavy, and offers very few benefits over Sonic/Meilisearch.
|
||||||
|
|
||||||
## 💅 Customize
|
## 💅 Customize
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ services:
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
- redis
|
- redis
|
||||||
- sonic
|
- meilisearch
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
networks:
|
networks:
|
||||||
|
@ -40,14 +40,30 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- ./db:/var/lib/postgresql/data
|
- ./db:/var/lib/postgresql/data
|
||||||
|
|
||||||
sonic:
|
### Only one of the below should be used.
|
||||||
restart: unless-stopped
|
### Meilisearch is better overall, but resource-intensive. Sonic is a very light full text search engine.
|
||||||
image: docker.io/valeriansaliou/sonic:v1.4.0
|
|
||||||
networks:
|
# meilisearch:
|
||||||
- calcnet
|
# container_name: meilisearch
|
||||||
volumes:
|
# image: getmeili/meilisearch:v1.1.1
|
||||||
- ./sonic:/var/lib/sonic/store
|
# environment:
|
||||||
- ./sonic/config.cfg:/etc/sonic.cfg
|
# - MEILI_ENV=${MEILI_ENV:-development}
|
||||||
|
# ports:
|
||||||
|
# - "7700:7700"
|
||||||
|
# networks:
|
||||||
|
# - calcnet
|
||||||
|
# volumes:
|
||||||
|
# - ./meili_data:/meili_data
|
||||||
|
# restart: unless-stopped
|
||||||
|
|
||||||
|
# sonic:
|
||||||
|
# restart: unless-stopped
|
||||||
|
# image: docker.io/valeriansaliou/sonic:v1.4.0
|
||||||
|
# networks:
|
||||||
|
# - calcnet
|
||||||
|
# volumes:
|
||||||
|
# - ./sonic:/var/lib/sonic/store
|
||||||
|
# - ./sonic/config.cfg:/etc/sonic.cfg
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
calcnet:
|
calcnet:
|
||||||
|
|
|
@ -5,6 +5,7 @@ introMisskey: "Welcome! Calckey is an open source, decentralized social media pl
|
||||||
\ that's free forever! \U0001F680"
|
\ that's free forever! \U0001F680"
|
||||||
monthAndDay: "{month}/{day}"
|
monthAndDay: "{month}/{day}"
|
||||||
search: "Search"
|
search: "Search"
|
||||||
|
searchPlaceholder: "Search Calckey"
|
||||||
notifications: "Notifications"
|
notifications: "Notifications"
|
||||||
username: "Username"
|
username: "Username"
|
||||||
password: "Password"
|
password: "Password"
|
||||||
|
@ -1529,30 +1530,35 @@ _weekday:
|
||||||
friday: "Friday"
|
friday: "Friday"
|
||||||
saturday: "Saturday"
|
saturday: "Saturday"
|
||||||
_widgets:
|
_widgets:
|
||||||
memo: "Sticky notes"
|
memo: "Sticky Notes"
|
||||||
notifications: "Notifications"
|
notifications: "Notifications"
|
||||||
timeline: "Timeline"
|
timeline: "Timeline"
|
||||||
calendar: "Calendar"
|
calendar: "Calendar"
|
||||||
trends: "Trending"
|
trends: "Trending"
|
||||||
clock: "Clock"
|
clock: "Clock"
|
||||||
rss: "RSS reader"
|
rss: "RSS Reader"
|
||||||
rssTicker: "RSS-Ticker"
|
rssTicker: "RSS Ticker"
|
||||||
activity: "Activity"
|
activity: "Activity"
|
||||||
photos: "Photos"
|
photos: "Photos"
|
||||||
digitalClock: "Digital clock"
|
digitalClock: "Digital Clock"
|
||||||
unixClock: "UNIX clock"
|
unixClock: "UNIX Clock"
|
||||||
federation: "Federation"
|
federation: "Federation"
|
||||||
instanceCloud: "Server cloud"
|
instanceCloud: "Server Cloud"
|
||||||
postForm: "Posting form"
|
postForm: "Posting Form"
|
||||||
slideshow: "Slideshow"
|
slideshow: "Slideshow"
|
||||||
button: "Button"
|
button: "Button"
|
||||||
onlineUsers: "Online users"
|
onlineUsers: "Online Users"
|
||||||
jobQueue: "Job Queue"
|
jobQueue: "Job Queue"
|
||||||
serverMetric: "Server metrics"
|
serverMetric: "Server Metrics"
|
||||||
aiscript: "AiScript console"
|
aiscript: "AiScript Console"
|
||||||
userList: "User list"
|
userList: "User List"
|
||||||
|
serverInfo: "Server Info"
|
||||||
_userList:
|
_userList:
|
||||||
chooseList: "Select a list"
|
chooseList: "Select a list"
|
||||||
|
meiliStatus: "Server Status"
|
||||||
|
meiliSize: "Index size"
|
||||||
|
meiliIndexCount: "Indexed posts"
|
||||||
|
|
||||||
_cw:
|
_cw:
|
||||||
hide: "Hide"
|
hide: "Hide"
|
||||||
show: "Show content"
|
show: "Show content"
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "calckey",
|
"name": "calckey",
|
||||||
"version": "14.0.0-dev26",
|
"version": "14.0.0-dev31",
|
||||||
"codename": "aqua",
|
"codename": "aqua",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://codeberg.org/calckey/calckey.git"
|
"url": "https://codeberg.org/calckey/calckey.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@8.5.1",
|
"packageManager": "pnpm@8.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"rebuild": "pnpm run clean && pnpm -r run build && pnpm run gulp",
|
"rebuild": "pnpm run clean && pnpm -r run build && pnpm run gulp",
|
||||||
|
|
|
@ -4,10 +4,5 @@
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"allowSyntheticDefaultImports": true
|
"allowSyntheticDefaultImports": true
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": ["node_modules", "jspm_packages", "tmp", "temp"]
|
||||||
"node_modules",
|
|
||||||
"jspm_packages",
|
|
||||||
"tmp",
|
|
||||||
"temp"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
import test from "ava";
|
import test from "ava";
|
||||||
|
|
||||||
import { sum } from "../index.js";
|
import { convertId, IdConvertType } from "../built/index.js";
|
||||||
|
|
||||||
test("sum from native", (t) => {
|
test("convert to mastodon id", (t) => {
|
||||||
t.is(sum(1, 2), 3);
|
t.is(convertId("9gf61ehcxv", IdConvertType.MastodonId), "960365976481219");
|
||||||
|
t.is(
|
||||||
|
convertId("9fbr9z0wbrjqyd3u", IdConvertType.MastodonId),
|
||||||
|
"3954607381600562394",
|
||||||
|
);
|
||||||
|
t.is(
|
||||||
|
convertId("9fbs680oyviiqrol9md73p8g", IdConvertType.MastodonId),
|
||||||
|
"3494513243013053824",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
"@koa/cors": "3.4.3",
|
"@koa/cors": "3.4.3",
|
||||||
"@koa/multer": "3.0.0",
|
"@koa/multer": "3.0.0",
|
||||||
"@koa/router": "9.0.1",
|
"@koa/router": "9.0.1",
|
||||||
|
"@paralleldrive/cuid2": "2.2.0",
|
||||||
"@peertube/http-signature": "1.7.0",
|
"@peertube/http-signature": "1.7.0",
|
||||||
"@redocly/openapi-core": "1.0.0-beta.120",
|
"@redocly/openapi-core": "1.0.0-beta.120",
|
||||||
"@sinonjs/fake-timers": "9.1.2",
|
"@sinonjs/fake-timers": "9.1.2",
|
||||||
|
@ -85,6 +86,7 @@
|
||||||
"koa-send": "5.0.1",
|
"koa-send": "5.0.1",
|
||||||
"koa-slow": "2.1.0",
|
"koa-slow": "2.1.0",
|
||||||
"koa-views": "7.0.2",
|
"koa-views": "7.0.2",
|
||||||
|
"meilisearch": "0.32.4",
|
||||||
"mfm-js": "0.23.3",
|
"mfm-js": "0.23.3",
|
||||||
"mime-types": "2.1.35",
|
"mime-types": "2.1.35",
|
||||||
"multer": "1.4.4-lts.1",
|
"multer": "1.4.4-lts.1",
|
||||||
|
|
|
@ -39,6 +39,12 @@ export type Source = {
|
||||||
collection?: string;
|
collection?: string;
|
||||||
bucket?: string;
|
bucket?: string;
|
||||||
};
|
};
|
||||||
|
meilisearch: {
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
apiKey?: string;
|
||||||
|
ssl: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
proxy?: string;
|
proxy?: string;
|
||||||
proxySmtp?: string;
|
proxySmtp?: string;
|
||||||
|
@ -54,7 +60,10 @@ export type Source = {
|
||||||
|
|
||||||
onlyQueueProcessor?: boolean;
|
onlyQueueProcessor?: boolean;
|
||||||
|
|
||||||
id: string;
|
cuid?: {
|
||||||
|
length?: number;
|
||||||
|
fingerprint?: string;
|
||||||
|
};
|
||||||
|
|
||||||
outgoingAddressFamily?: "ipv4" | "ipv6" | "dual";
|
outgoingAddressFamily?: "ipv4" | "ipv6" | "dual";
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import si from "systeminformation";
|
import si from "systeminformation";
|
||||||
import Xev from "xev";
|
import Xev from "xev";
|
||||||
import * as osUtils from "os-utils";
|
import * as osUtils from "os-utils";
|
||||||
|
import meilisearch from "../db/meilisearch.js";
|
||||||
|
|
||||||
const ev = new Xev();
|
const ev = new Xev();
|
||||||
|
|
||||||
|
@ -24,6 +25,7 @@ export default function () {
|
||||||
const memStats = await mem();
|
const memStats = await mem();
|
||||||
const netStats = await net();
|
const netStats = await net();
|
||||||
const fsStats = await fs();
|
const fsStats = await fs();
|
||||||
|
const meilisearchStats = await meilisearchStatus();
|
||||||
|
|
||||||
const stats = {
|
const stats = {
|
||||||
cpu: roundCpu(cpu),
|
cpu: roundCpu(cpu),
|
||||||
|
@ -39,6 +41,7 @@ export default function () {
|
||||||
r: round(Math.max(0, fsStats.rIO_sec ?? 0)),
|
r: round(Math.max(0, fsStats.rIO_sec ?? 0)),
|
||||||
w: round(Math.max(0, fsStats.wIO_sec ?? 0)),
|
w: round(Math.max(0, fsStats.wIO_sec ?? 0)),
|
||||||
},
|
},
|
||||||
|
meilisearch: meilisearchStats,
|
||||||
};
|
};
|
||||||
ev.emit("serverStats", stats);
|
ev.emit("serverStats", stats);
|
||||||
log.unshift(stats);
|
log.unshift(stats);
|
||||||
|
@ -77,3 +80,16 @@ async function fs() {
|
||||||
const data = await si.disksIO().catch(() => ({ rIO_sec: 0, wIO_sec: 0 }));
|
const data = await si.disksIO().catch(() => ({ rIO_sec: 0, wIO_sec: 0 }));
|
||||||
return data || { rIO_sec: 0, wIO_sec: 0 };
|
return data || { rIO_sec: 0, wIO_sec: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MEILI STAT
|
||||||
|
async function meilisearchStatus() {
|
||||||
|
if (meilisearch) {
|
||||||
|
return meilisearch.serverStats();
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
health: "unconfigured",
|
||||||
|
size: 0,
|
||||||
|
indexed_count: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
292
packages/backend/src/db/meilisearch.ts
Normal file
292
packages/backend/src/db/meilisearch.ts
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
import { Health, MeiliSearch, Stats } from "meilisearch";
|
||||||
|
import { dbLogger } from "./logger.js";
|
||||||
|
|
||||||
|
import config from "@/config/index.js";
|
||||||
|
import { Note } from "@/models/entities/note.js";
|
||||||
|
import * as url from "url";
|
||||||
|
import { ILocalUser, User } from "@/models/entities/user.js";
|
||||||
|
import { Followings, Users } from "@/models/index.js";
|
||||||
|
|
||||||
|
const logger = dbLogger.createSubLogger("meilisearch", "gray", false);
|
||||||
|
|
||||||
|
const hasConfig =
|
||||||
|
config.meilisearch &&
|
||||||
|
(config.meilisearch.host ||
|
||||||
|
config.meilisearch.port ||
|
||||||
|
config.meilisearch.apiKey);
|
||||||
|
|
||||||
|
if (hasConfig) {
|
||||||
|
const host = hasConfig ? config.meilisearch.host ?? "localhost" : "";
|
||||||
|
const port = hasConfig ? config.meilisearch.port ?? 7700 : 0;
|
||||||
|
const auth = hasConfig ? config.meilisearch.apiKey ?? "" : "";
|
||||||
|
const ssl = hasConfig ? config.meilisearch.ssl ?? false : false;
|
||||||
|
|
||||||
|
logger.info("Connecting to MeiliSearch");
|
||||||
|
|
||||||
|
const client: MeiliSearch = new MeiliSearch({
|
||||||
|
host: `${ssl ? "https" : "http"}://${host}:${port}`,
|
||||||
|
apiKey: auth,
|
||||||
|
});
|
||||||
|
|
||||||
|
const posts = client.index("posts");
|
||||||
|
|
||||||
|
posts
|
||||||
|
.updateSearchableAttributes(["text"])
|
||||||
|
.catch((e) =>
|
||||||
|
logger.error(`Setting searchable attr failed, searches won't work: ${e}`),
|
||||||
|
);
|
||||||
|
|
||||||
|
posts
|
||||||
|
.updateFilterableAttributes([
|
||||||
|
"userName",
|
||||||
|
"userHost",
|
||||||
|
"mediaAttachment",
|
||||||
|
"createdAt",
|
||||||
|
"userId",
|
||||||
|
])
|
||||||
|
.catch((e) =>
|
||||||
|
logger.error(
|
||||||
|
`Setting filterable attr failed, advanced searches won't work: ${e}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
posts
|
||||||
|
.updateSortableAttributes(["createdAt"])
|
||||||
|
.catch((e) =>
|
||||||
|
logger.error(
|
||||||
|
`Setting sortable attr failed, placeholder searches won't sort properly: ${e}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.info("Connected to MeiliSearch");
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MeilisearchNote = {
|
||||||
|
id: string;
|
||||||
|
text: string;
|
||||||
|
userId: string;
|
||||||
|
userHost: string;
|
||||||
|
userName: string;
|
||||||
|
channelId: string;
|
||||||
|
mediaAttachment: string;
|
||||||
|
createdAt: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default hasConfig
|
||||||
|
? {
|
||||||
|
search: async (
|
||||||
|
query: string,
|
||||||
|
limit: number,
|
||||||
|
offset: number,
|
||||||
|
userCtx: ILocalUser | null,
|
||||||
|
) => {
|
||||||
|
/// Advanced search syntax
|
||||||
|
/// from:user => filter by user + optional domain
|
||||||
|
/// has:image/video/audio/text/file => filter by attachment types
|
||||||
|
/// domain:domain.com => filter by domain
|
||||||
|
/// before:Date => show posts made before Date
|
||||||
|
/// after: Date => show posts made after Date
|
||||||
|
/// "text" => get posts with exact text between quotes
|
||||||
|
/// filter:following => show results only from users you follow
|
||||||
|
/// filter:followers => show results only from followers
|
||||||
|
|
||||||
|
let constructedFilters: string[] = [];
|
||||||
|
|
||||||
|
let splitSearch = query.split(" ");
|
||||||
|
|
||||||
|
// Detect search operators and remove them from the actual query
|
||||||
|
let filteredSearchTerms = (
|
||||||
|
await Promise.all(
|
||||||
|
splitSearch.map(async (term) => {
|
||||||
|
if (term.startsWith("has:")) {
|
||||||
|
let fileType = term.slice(4);
|
||||||
|
constructedFilters.push(`mediaAttachment = "${fileType}"`);
|
||||||
|
return null;
|
||||||
|
} else if (term.startsWith("from:")) {
|
||||||
|
let user = term.slice(5);
|
||||||
|
constructedFilters.push(`userName = ${user}`);
|
||||||
|
return null;
|
||||||
|
} else if (term.startsWith("domain:")) {
|
||||||
|
let domain = term.slice(7);
|
||||||
|
constructedFilters.push(`userHost = ${domain}`);
|
||||||
|
return null;
|
||||||
|
} else if (term.startsWith("after:")) {
|
||||||
|
let timestamp = term.slice(6);
|
||||||
|
// Try to parse the timestamp as JavaScript Date
|
||||||
|
let date = Date.parse(timestamp);
|
||||||
|
if (isNaN(date)) return null;
|
||||||
|
constructedFilters.push(`createdAt > ${date / 1000}`);
|
||||||
|
return null;
|
||||||
|
} else if (term.startsWith("before:")) {
|
||||||
|
let timestamp = term.slice(7);
|
||||||
|
// Try to parse the timestamp as JavaScript Date
|
||||||
|
let date = Date.parse(timestamp);
|
||||||
|
if (isNaN(date)) return null;
|
||||||
|
constructedFilters.push(`createdAt < ${date / 1000}`);
|
||||||
|
return null;
|
||||||
|
} else if (term.startsWith("filter:following")) {
|
||||||
|
// Check if we got a context user
|
||||||
|
if (userCtx) {
|
||||||
|
// Fetch user follows from DB
|
||||||
|
let followedUsers = await Followings.find({
|
||||||
|
where: {
|
||||||
|
followerId: userCtx.id,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
followeeId: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
let followIDs = followedUsers.map((user) => user.followeeId);
|
||||||
|
|
||||||
|
if (followIDs.length === 0) return null;
|
||||||
|
|
||||||
|
constructedFilters.push(`userId IN [${followIDs.join(",")}]`);
|
||||||
|
} else {
|
||||||
|
logger.warn(
|
||||||
|
"search filtered to follows called without user context",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} else if (term.startsWith("filter:followers")) {
|
||||||
|
// Check if we got a context user
|
||||||
|
if (userCtx) {
|
||||||
|
// Fetch users follows from DB
|
||||||
|
let followedUsers = await Followings.find({
|
||||||
|
where: {
|
||||||
|
followeeId: userCtx.id,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
followerId: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
let followIDs = followedUsers.map((user) => user.followerId);
|
||||||
|
|
||||||
|
if (followIDs.length === 0) return null;
|
||||||
|
|
||||||
|
constructedFilters.push(`userId IN [${followIDs.join(",")}]`);
|
||||||
|
} else {
|
||||||
|
logger.warn(
|
||||||
|
"search filtered to followers called without user context",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return term;
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
).filter((term) => term !== null);
|
||||||
|
|
||||||
|
let sortRules = [];
|
||||||
|
|
||||||
|
// An empty search term with defined filters means we have a placeholder search => https://www.meilisearch.com/docs/reference/api/search#placeholder-search
|
||||||
|
// These have to be ordered manually, otherwise the *oldest* posts are returned first, which we don't want
|
||||||
|
if (filteredSearchTerms.length === 0 && constructedFilters.length > 0) {
|
||||||
|
sortRules.push("createdAt:desc");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(`Searching for ${filteredSearchTerms.join(" ")}`);
|
||||||
|
logger.info(`Limit: ${limit}`);
|
||||||
|
logger.info(`Offset: ${offset}`);
|
||||||
|
logger.info(`Filters: ${constructedFilters}`);
|
||||||
|
logger.info(`Ordering: ${sortRules}`);
|
||||||
|
|
||||||
|
return posts.search(filteredSearchTerms.join(" "), {
|
||||||
|
limit: limit,
|
||||||
|
offset: offset,
|
||||||
|
filter: constructedFilters,
|
||||||
|
sort: sortRules,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ingestNote: async (ingestNotes: Note | Note[]) => {
|
||||||
|
if (ingestNotes instanceof Note) {
|
||||||
|
ingestNotes = [ingestNotes];
|
||||||
|
}
|
||||||
|
|
||||||
|
let indexingBatch: MeilisearchNote[] = [];
|
||||||
|
|
||||||
|
for (let note of ingestNotes) {
|
||||||
|
if (note.user === undefined) {
|
||||||
|
note.user = await Users.findOne({
|
||||||
|
where: {
|
||||||
|
id: note.userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let attachmentType = "";
|
||||||
|
if (note.attachedFileTypes.length > 0) {
|
||||||
|
attachmentType = note.attachedFileTypes[0].split("/")[0];
|
||||||
|
switch (attachmentType) {
|
||||||
|
case "image":
|
||||||
|
case "video":
|
||||||
|
case "audio":
|
||||||
|
case "text":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
attachmentType = "file";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
indexingBatch.push(<MeilisearchNote>{
|
||||||
|
id: note.id.toString(),
|
||||||
|
text: note.text ? note.text : "",
|
||||||
|
userId: note.userId,
|
||||||
|
userHost:
|
||||||
|
note.userHost !== ""
|
||||||
|
? note.userHost
|
||||||
|
: url.parse(config.host).host,
|
||||||
|
channelId: note.channelId ? note.channelId : "",
|
||||||
|
mediaAttachment: attachmentType,
|
||||||
|
userName: note.user?.username ?? "UNKNOWN",
|
||||||
|
createdAt: note.createdAt.getTime() / 1000, // division by 1000 is necessary because Node returns in ms-accuracy
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return posts
|
||||||
|
.addDocuments(indexingBatch, {
|
||||||
|
primaryKey: "id",
|
||||||
|
})
|
||||||
|
.then(() =>
|
||||||
|
console.log(`sent ${indexingBatch.length} posts for indexing`),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
serverStats: async () => {
|
||||||
|
let health: Health = await client.health();
|
||||||
|
let stats: Stats = await client.getStats();
|
||||||
|
|
||||||
|
return {
|
||||||
|
health: health.status,
|
||||||
|
size: stats.databaseSize,
|
||||||
|
indexed_count: stats.indexes["posts"].numberOfDocuments,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
deleteNotes: async (note: Note | Note[] | string | string[]) => {
|
||||||
|
if (note instanceof Note) {
|
||||||
|
note = [note];
|
||||||
|
}
|
||||||
|
if (typeof note === "string") {
|
||||||
|
note = [note];
|
||||||
|
}
|
||||||
|
|
||||||
|
let deletionBatch = note.map((n) => {
|
||||||
|
if(n instanceof Note) {
|
||||||
|
return n.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(n.length > 0) return n;
|
||||||
|
|
||||||
|
logger.error(`Failed to delete note from Meilisearch, invalid post ID: ${JSON.stringify(n)}`)
|
||||||
|
|
||||||
|
throw new Error(`Invalid note ID passed to meilisearch deleteNote: ${JSON.stringify(n)}`)
|
||||||
|
}).filter((el) => el !== null);
|
||||||
|
|
||||||
|
await posts.deleteDocuments(deletionBatch as string[]).then(() => {
|
||||||
|
logger.info(`submitted ${deletionBatch.length} large batch for deletion`)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: null;
|
|
@ -1,27 +1,27 @@
|
||||||
import { ulid } from "ulid";
|
import { init, createId } from "@paralleldrive/cuid2";
|
||||||
import { genAid } from "./id/aid.js";
|
|
||||||
import { genMeid } from "./id/meid.js";
|
|
||||||
import { genMeidg } from "./id/meidg.js";
|
|
||||||
import { genObjectId } from "./id/object-id.js";
|
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
|
|
||||||
const metohd = config.id.toLowerCase();
|
const TIME2000 = 946684800000;
|
||||||
|
const TIMESTAMP_LENGTH = 8;
|
||||||
|
|
||||||
|
const length =
|
||||||
|
Math.min(Math.max(config.cuid?.length ?? 16, 16), 24) - TIMESTAMP_LENGTH;
|
||||||
|
const fingerprint = `${config.cuid?.fingerprint ?? ""}${createId()}`;
|
||||||
|
|
||||||
|
const genCuid2 = init({ length, fingerprint });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The generated ID results in the form of `[8 chars timestamp] + [cuid2]`.
|
||||||
|
* The minimum and maximum lengths are 16 and 24, respectively.
|
||||||
|
* With the length of 16, namely 8 for cuid2, roughly 1427399 IDs are needed
|
||||||
|
* in the same millisecond to reach 50% chance of collision.
|
||||||
|
*
|
||||||
|
* Ref: https://github.com/paralleldrive/cuid2#parameterized-length
|
||||||
|
*/
|
||||||
export function genId(date?: Date): string {
|
export function genId(date?: Date): string {
|
||||||
if (!date || date > new Date()) date = new Date();
|
const now = (date ?? new Date()).getTime();
|
||||||
|
const time = Math.max(now - TIME2000, 0);
|
||||||
|
const timestamp = time.toString(36).padStart(TIMESTAMP_LENGTH, "0");
|
||||||
|
|
||||||
switch (metohd) {
|
return `${timestamp}${genCuid2()}`;
|
||||||
case "aid":
|
|
||||||
return genAid(date);
|
|
||||||
case "meid":
|
|
||||||
return genMeid(date);
|
|
||||||
case "meidg":
|
|
||||||
return genMeidg(date);
|
|
||||||
case "ulid":
|
|
||||||
return ulid(date.getTime());
|
|
||||||
case "objectid":
|
|
||||||
return genObjectId(date);
|
|
||||||
default:
|
|
||||||
throw new Error("unrecognized id generation method");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ export class AbuseUserReport {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the AbuseUserReport.',
|
comment: "The created date of the AbuseUserReport.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ export class AbuseUserReport {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public targetUserId: User["id"];
|
public targetUserId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public targetUser: User | null;
|
public targetUser: User | null;
|
||||||
|
@ -34,8 +34,8 @@ export class AbuseUserReport {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public reporterId: User["id"];
|
public reporterId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public reporter: User | null;
|
public reporter: User | null;
|
||||||
|
@ -46,40 +46,42 @@ export class AbuseUserReport {
|
||||||
})
|
})
|
||||||
public assigneeId: User["id"] | null;
|
public assigneeId: User["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public assignee: User | null;
|
public assignee: User | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public resolved: boolean;
|
public resolved: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false
|
default: false,
|
||||||
})
|
})
|
||||||
public forwarded: boolean;
|
public forwarded: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 2048,
|
length: 2048,
|
||||||
})
|
})
|
||||||
public comment: string;
|
public comment: string;
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public targetUserHost: string | null;
|
public targetUserHost: string | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public reporterHost: string | null;
|
public reporterHost: string | null;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -15,31 +15,31 @@ export class AccessToken {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the AccessToken.',
|
comment: "The created date of the AccessToken.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public lastUsedAt: Date | null;
|
public lastUsedAt: Date | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public token: string;
|
public token: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public session: string | null;
|
public session: string | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public hash: string;
|
public hash: string;
|
||||||
|
@ -48,8 +48,8 @@ export class AccessToken {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -60,37 +60,38 @@ export class AccessToken {
|
||||||
})
|
})
|
||||||
public appId: App["id"] | null;
|
public appId: App["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => App, {
|
@ManyToOne((type) => App, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public app: App | null;
|
public app: App | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public name: string | null;
|
public name: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public description: string | null;
|
public description: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public iconUrl: string | null;
|
public iconUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64, array: true,
|
length: 64,
|
||||||
default: '{}',
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public permission: string[];
|
public permission: string[];
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public fetched: boolean;
|
public fetched: boolean;
|
||||||
|
|
|
@ -7,45 +7,51 @@ export class Ad {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Ad.',
|
comment: "The created date of the Ad.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The expired date of the Ad.',
|
comment: "The expired date of the Ad.",
|
||||||
})
|
})
|
||||||
public expiresAt: Date;
|
public expiresAt: Date;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 32, nullable: false,
|
length: 32,
|
||||||
|
nullable: false,
|
||||||
})
|
})
|
||||||
public place: string;
|
public place: string;
|
||||||
|
|
||||||
// 今は使われていないが将来的に活用される可能性はある
|
// 今は使われていないが将来的に活用される可能性はある
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 32, nullable: false,
|
length: 32,
|
||||||
|
nullable: false,
|
||||||
})
|
})
|
||||||
public priority: string;
|
public priority: string;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 1, nullable: false,
|
default: 1,
|
||||||
|
nullable: false,
|
||||||
})
|
})
|
||||||
public ratio: number;
|
public ratio: number;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024, nullable: false,
|
length: 1024,
|
||||||
|
nullable: false,
|
||||||
})
|
})
|
||||||
public url: string;
|
public url: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024, nullable: false,
|
length: 1024,
|
||||||
|
nullable: false,
|
||||||
})
|
})
|
||||||
public imageUrl: string;
|
public imageUrl: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 8192, nullable: false,
|
length: 8192,
|
||||||
|
nullable: false,
|
||||||
})
|
})
|
||||||
public memo: string;
|
public memo: string;
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,13 @@ import { Announcement } from "./announcement.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'announcementId'], { unique: true })
|
@Index(["userId", "announcementId"], { unique: true })
|
||||||
export class AnnouncementRead {
|
export class AnnouncementRead {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the AnnouncementRead.',
|
comment: "The created date of the AnnouncementRead.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ export class AnnouncementRead {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -35,8 +35,8 @@ export class AnnouncementRead {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public announcementId: Announcement["id"];
|
public announcementId: Announcement["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Announcement, {
|
@ManyToOne((type) => Announcement, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public announcement: Announcement | null;
|
public announcement: Announcement | null;
|
||||||
|
|
|
@ -7,29 +7,32 @@ export class Announcement {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Announcement.',
|
comment: "The created date of the Announcement.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The updated date of the Announcement.',
|
comment: "The updated date of the Announcement.",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public updatedAt: Date | null;
|
public updatedAt: Date | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 8192, nullable: false,
|
length: 8192,
|
||||||
|
nullable: false,
|
||||||
})
|
})
|
||||||
public text: string;
|
public text: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: false,
|
length: 256,
|
||||||
|
nullable: false,
|
||||||
})
|
})
|
||||||
public title: string;
|
public title: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024, nullable: true,
|
length: 1024,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public imageUrl: string | null;
|
public imageUrl: string | null;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { Antenna } from "./antenna.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['noteId', 'antennaId'], { unique: true })
|
@Index(["noteId", "antennaId"], { unique: true })
|
||||||
export class AntennaNote {
|
export class AntennaNote {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
@ -19,12 +19,12 @@ export class AntennaNote {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The note ID.',
|
comment: "The note ID.",
|
||||||
})
|
})
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
@ -32,18 +32,18 @@ export class AntennaNote {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The antenna ID.',
|
comment: "The antenna ID.",
|
||||||
})
|
})
|
||||||
public antennaId: Antenna["id"];
|
public antennaId: Antenna["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Antenna, {
|
@ManyToOne((type) => Antenna, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public antenna: Antenna | null;
|
public antenna: Antenna | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public read: boolean;
|
public read: boolean;
|
||||||
|
|
|
@ -16,31 +16,33 @@ export class Antenna {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Antenna.',
|
comment: "The created date of the Antenna.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The owner ID.',
|
comment: "The owner ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
comment: 'The name of the Antenna.',
|
comment: "The name of the Antenna.",
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
||||||
@Column('enum', { enum: ['home', 'all', 'users', 'list', 'group', 'instances'] })
|
@Column("enum", {
|
||||||
|
enum: ["home", "all", "users", "list", "group", "instances"],
|
||||||
|
})
|
||||||
public src: "home" | "all" | "users" | "list" | "group" | "instances";
|
public src: "home" | "all" | "users" | "list" | "group" | "instances";
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
|
@ -49,8 +51,8 @@ export class Antenna {
|
||||||
})
|
})
|
||||||
public userListId: UserList["id"] | null;
|
public userListId: UserList["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => UserList, {
|
@ManyToOne((type) => UserList, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public userList: UserList | null;
|
public userList: UserList | null;
|
||||||
|
@ -61,51 +63,53 @@ export class Antenna {
|
||||||
})
|
})
|
||||||
public userGroupJoiningId: UserGroupJoining["id"] | null;
|
public userGroupJoiningId: UserGroupJoining["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => UserGroupJoining, {
|
@ManyToOne((type) => UserGroupJoining, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public userGroupJoining: UserGroupJoining | null;
|
public userGroupJoining: UserGroupJoining | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024, array: true,
|
length: 1024,
|
||||||
default: '{}',
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public users: string[];
|
public users: string[];
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: [],
|
default: [],
|
||||||
})
|
})
|
||||||
public instances: string[];
|
public instances: string[];
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: [],
|
default: [],
|
||||||
})
|
})
|
||||||
public keywords: string[][];
|
public keywords: string[][];
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: [],
|
default: [],
|
||||||
})
|
})
|
||||||
public excludeKeywords: string[][];
|
public excludeKeywords: string[][];
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public caseSensitive: boolean;
|
public caseSensitive: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public withReplies: boolean;
|
public withReplies: boolean;
|
||||||
|
|
||||||
@Column('boolean')
|
@Column("boolean")
|
||||||
public withFile: boolean;
|
public withFile: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 2048, nullable: true,
|
length: 2048,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public expression: string | null;
|
public expression: string | null;
|
||||||
|
|
||||||
@Column('boolean')
|
@Column("boolean")
|
||||||
public notify: boolean;
|
public notify: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ export class App {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the App.',
|
comment: "The created date of the App.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -17,44 +17,46 @@ export class App {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The owner ID.',
|
comment: "The owner ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"] | null;
|
public userId: User["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64,
|
length: 64,
|
||||||
comment: 'The secret key of the App.',
|
comment: "The secret key of the App.",
|
||||||
})
|
})
|
||||||
public secret: string;
|
public secret: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
comment: 'The name of the App.',
|
comment: "The name of the App.",
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
comment: 'The description of the App.',
|
comment: "The description of the App.",
|
||||||
})
|
})
|
||||||
public description: string;
|
public description: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64, array: true,
|
length: 64,
|
||||||
comment: 'The permission of the App.',
|
array: true,
|
||||||
|
comment: "The permission of the App.",
|
||||||
})
|
})
|
||||||
public permission: string[];
|
public permission: string[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The callbackUrl of the App.',
|
nullable: true,
|
||||||
|
comment: "The callbackUrl of the App.",
|
||||||
})
|
})
|
||||||
public callbackUrl: string | null;
|
public callbackUrl: string | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,27 +18,27 @@ export class AttestationChallenge {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64,
|
length: 64,
|
||||||
comment: 'Hex-encoded sha256 hash of the challenge.',
|
comment: "Hex-encoded sha256 hash of the challenge.",
|
||||||
})
|
})
|
||||||
public challenge: string;
|
public challenge: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The date challenge was created for expiry purposes.',
|
comment: "The date challenge was created for expiry purposes.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
comment:
|
comment:
|
||||||
'Indicates that the challenge is only for registration purposes if true to prevent the challenge for being used as authentication.',
|
"Indicates that the challenge is only for registration purposes if true to prevent the challenge for being used as authentication.",
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public registrationChallenge: boolean;
|
public registrationChallenge: boolean;
|
||||||
|
|
|
@ -15,13 +15,13 @@ export class AuthSession {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the AuthSession.',
|
comment: "The created date of the AuthSession.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public token: string;
|
public token: string;
|
||||||
|
@ -32,8 +32,8 @@ export class AuthSession {
|
||||||
})
|
})
|
||||||
public userId: User["id"] | null;
|
public userId: User["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -42,8 +42,8 @@ export class AuthSession {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public appId: App["id"];
|
public appId: App["id"];
|
||||||
|
|
||||||
@ManyToOne(type => App, {
|
@ManyToOne((type) => App, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public app: App | null;
|
public app: App | null;
|
||||||
|
|
|
@ -10,26 +10,26 @@ import { User } from "./user.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['blockerId', 'blockeeId'], { unique: true })
|
@Index(["blockerId", "blockeeId"], { unique: true })
|
||||||
export class Blocking {
|
export class Blocking {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Blocking.',
|
comment: "The created date of the Blocking.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The blockee user ID.',
|
comment: "The blockee user ID.",
|
||||||
})
|
})
|
||||||
public blockeeId: User["id"];
|
public blockeeId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public blockee: User | null;
|
public blockee: User | null;
|
||||||
|
@ -37,12 +37,12 @@ export class Blocking {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The blocker user ID.',
|
comment: "The blocker user ID.",
|
||||||
})
|
})
|
||||||
public blockerId: User["id"];
|
public blockerId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public blocker: User | null;
|
public blocker: User | null;
|
||||||
|
|
|
@ -11,26 +11,26 @@ import { id } from "../id.js";
|
||||||
import { Channel } from "./channel.js";
|
import { Channel } from "./channel.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['followerId', 'followeeId'], { unique: true })
|
@Index(["followerId", "followeeId"], { unique: true })
|
||||||
export class ChannelFollowing {
|
export class ChannelFollowing {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the ChannelFollowing.',
|
comment: "The created date of the ChannelFollowing.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The followee channel ID.',
|
comment: "The followee channel ID.",
|
||||||
})
|
})
|
||||||
public followeeId: Channel["id"];
|
public followeeId: Channel["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Channel, {
|
@ManyToOne((type) => Channel, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public followee: Channel | null;
|
public followee: Channel | null;
|
||||||
|
@ -38,12 +38,12 @@ export class ChannelFollowing {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The follower user ID.',
|
comment: "The follower user ID.",
|
||||||
})
|
})
|
||||||
public followerId: User["id"];
|
public followerId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public follower: User | null;
|
public follower: User | null;
|
||||||
|
|
|
@ -11,13 +11,13 @@ import { Channel } from "./channel.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['channelId', 'noteId'], { unique: true })
|
@Index(["channelId", "noteId"], { unique: true })
|
||||||
export class ChannelNotePining {
|
export class ChannelNotePining {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the ChannelNotePining.',
|
comment: "The created date of the ChannelNotePining.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ export class ChannelNotePining {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public channelId: Channel["id"];
|
public channelId: Channel["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Channel, {
|
@ManyToOne((type) => Channel, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public channel: Channel | null;
|
public channel: Channel | null;
|
||||||
|
@ -34,8 +34,8 @@ export class ChannelNotePining {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
|
|
@ -16,13 +16,13 @@ export class Channel {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Channel.',
|
comment: "The created date of the Channel.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public lastNotedAt: Date | null;
|
public lastNotedAt: Date | null;
|
||||||
|
@ -31,52 +31,53 @@ export class Channel {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The owner ID.',
|
comment: "The owner ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"] | null;
|
public userId: User["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
comment: 'The name of the Channel.',
|
comment: "The name of the Channel.",
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 2048, nullable: true,
|
length: 2048,
|
||||||
comment: 'The description of the Channel.',
|
nullable: true,
|
||||||
|
comment: "The description of the Channel.",
|
||||||
})
|
})
|
||||||
public description: string | null;
|
public description: string | null;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The ID of banner Channel.',
|
comment: "The ID of banner Channel.",
|
||||||
})
|
})
|
||||||
public bannerId: DriveFile["id"] | null;
|
public bannerId: DriveFile["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => DriveFile, {
|
@ManyToOne((type) => DriveFile, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public banner: DriveFile | null;
|
public banner: DriveFile | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
comment: 'The count of notes.',
|
comment: "The count of notes.",
|
||||||
})
|
})
|
||||||
public notesCount: number;
|
public notesCount: number;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
comment: 'The count of users.',
|
comment: "The count of users.",
|
||||||
})
|
})
|
||||||
public usersCount: number;
|
public usersCount: number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { Clip } from "./clip.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['noteId', 'clipId'], { unique: true })
|
@Index(["noteId", "clipId"], { unique: true })
|
||||||
export class ClipNote {
|
export class ClipNote {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
@ -19,12 +19,12 @@ export class ClipNote {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The note ID.',
|
comment: "The note ID.",
|
||||||
})
|
})
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
@ -32,12 +32,12 @@ export class ClipNote {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The clip ID.',
|
comment: "The clip ID.",
|
||||||
})
|
})
|
||||||
public clipId: Clip["id"];
|
public clipId: Clip["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Clip, {
|
@ManyToOne((type) => Clip, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public clip: Clip | null;
|
public clip: Clip | null;
|
||||||
|
|
|
@ -14,38 +14,39 @@ export class Clip {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Clip.',
|
comment: "The created date of the Clip.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The owner ID.',
|
comment: "The owner ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
comment: 'The name of the Clip.',
|
comment: "The name of the Clip.",
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public isPublic: boolean;
|
public isPublic: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 2048, nullable: true,
|
length: 2048,
|
||||||
comment: 'The description of the Clip.',
|
nullable: true,
|
||||||
|
comment: "The description of the Clip.",
|
||||||
})
|
})
|
||||||
public description: string | null;
|
public description: string | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,14 @@ import { DriveFolder } from "./drive-folder.js";
|
||||||
import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js";
|
import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'folderId', 'id'])
|
@Index(["userId", "folderId", "id"])
|
||||||
export class DriveFile {
|
export class DriveFile {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the DriveFile.',
|
comment: "The created date of the DriveFile.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -27,64 +27,67 @@ export class DriveFile {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The owner ID.',
|
comment: "The owner ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"] | null;
|
public userId: User["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: 'The host of owner. It will be null if the user in local.',
|
nullable: true,
|
||||||
|
comment: "The host of owner. It will be null if the user in local.",
|
||||||
})
|
})
|
||||||
public userHost: string | null;
|
public userHost: string | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 32,
|
length: 32,
|
||||||
comment: 'The MD5 hash of the DriveFile.',
|
comment: "The MD5 hash of the DriveFile.",
|
||||||
})
|
})
|
||||||
public md5: string;
|
public md5: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: 256,
|
||||||
comment: 'The file name of the DriveFile.',
|
comment: "The file name of the DriveFile.",
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
comment: 'The content type (MIME) of the DriveFile.',
|
comment: "The content type (MIME) of the DriveFile.",
|
||||||
})
|
})
|
||||||
public type: string;
|
public type: string;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
comment: 'The file size (bytes) of the DriveFile.',
|
comment: "The file size (bytes) of the DriveFile.",
|
||||||
})
|
})
|
||||||
public size: number;
|
public size: number;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: DB_MAX_IMAGE_COMMENT_LENGTH,
|
length: DB_MAX_IMAGE_COMMENT_LENGTH,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The comment of the DriveFile.',
|
comment: "The comment of the DriveFile.",
|
||||||
})
|
})
|
||||||
public comment: string | null;
|
public comment: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: 'The BlurHash string.',
|
nullable: true,
|
||||||
|
comment: "The BlurHash string.",
|
||||||
})
|
})
|
||||||
public blurhash: string | null;
|
public blurhash: string | null;
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: {},
|
default: {},
|
||||||
comment: 'The any properties of the DriveFile. For example, it includes image width/height.',
|
comment:
|
||||||
|
"The any properties of the DriveFile. For example, it includes image width/height.",
|
||||||
})
|
})
|
||||||
public properties: {
|
public properties: {
|
||||||
width?: number;
|
width?: number;
|
||||||
|
@ -93,59 +96,68 @@ export class DriveFile {
|
||||||
avgColor?: string;
|
avgColor?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@Column('boolean')
|
@Column("boolean")
|
||||||
public storedInternal: boolean;
|
public storedInternal: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
comment: 'The URL of the DriveFile.',
|
comment: "The URL of the DriveFile.",
|
||||||
})
|
})
|
||||||
public url: string;
|
public url: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The URL of the thumbnail of the DriveFile.',
|
nullable: true,
|
||||||
|
comment: "The URL of the thumbnail of the DriveFile.",
|
||||||
})
|
})
|
||||||
public thumbnailUrl: string | null;
|
public thumbnailUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The URL of the webpublic of the DriveFile.',
|
nullable: true,
|
||||||
|
comment: "The URL of the webpublic of the DriveFile.",
|
||||||
})
|
})
|
||||||
public webpublicUrl: string | null;
|
public webpublicUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public webpublicType: string | null;
|
public webpublicType: string | null;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public accessKey: string | null;
|
public accessKey: string | null;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public thumbnailAccessKey: string | null;
|
public thumbnailAccessKey: string | null;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public webpublicAccessKey: string | null;
|
public webpublicAccessKey: string | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The URI of the DriveFile. it will be null when the DriveFile is local.',
|
nullable: true,
|
||||||
|
comment:
|
||||||
|
"The URI of the DriveFile. it will be null when the DriveFile is local.",
|
||||||
})
|
})
|
||||||
public uri: string | null;
|
public uri: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public src: string | null;
|
public src: string | null;
|
||||||
|
|
||||||
|
@ -153,32 +165,33 @@ export class DriveFile {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The parent folder ID. If null, it means the DriveFile is located in root.',
|
comment:
|
||||||
|
"The parent folder ID. If null, it means the DriveFile is located in root.",
|
||||||
})
|
})
|
||||||
public folderId: DriveFolder["id"] | null;
|
public folderId: DriveFolder["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => DriveFolder, {
|
@ManyToOne((type) => DriveFolder, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public folder: DriveFolder | null;
|
public folder: DriveFolder | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the DriveFile is NSFW.',
|
comment: "Whether the DriveFile is NSFW.",
|
||||||
})
|
})
|
||||||
public isSensitive: boolean;
|
public isSensitive: boolean;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the DriveFile is NSFW. (predict)',
|
comment: "Whether the DriveFile is NSFW. (predict)",
|
||||||
})
|
})
|
||||||
public maybeSensitive: boolean;
|
public maybeSensitive: boolean;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public maybePorn: boolean;
|
public maybePorn: boolean;
|
||||||
|
@ -187,20 +200,21 @@ export class DriveFile {
|
||||||
* 外部の(信頼されていない)URLへの直リンクか否か
|
* 外部の(信頼されていない)URLへの直リンクか否か
|
||||||
*/
|
*/
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the DriveFile is direct link to remote server.',
|
comment: "Whether the DriveFile is direct link to remote server.",
|
||||||
})
|
})
|
||||||
public isLink: boolean;
|
public isLink: boolean;
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: {},
|
default: {},
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public requestHeaders: Record<string, string> | null;
|
public requestHeaders: Record<string, string> | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public requestIp: string | null;
|
public requestIp: string | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,14 @@ export class DriveFolder {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the DriveFolder.',
|
comment: "The created date of the DriveFolder.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
comment: 'The name of the DriveFolder.',
|
comment: "The name of the DriveFolder.",
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ export class DriveFolder {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The owner ID.',
|
comment: "The owner ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"] | null;
|
public userId: User["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -44,12 +44,13 @@ export class DriveFolder {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The parent folder ID. If null, it means the DriveFolder is located in root.',
|
comment:
|
||||||
|
"The parent folder ID. If null, it means the DriveFolder is located in root.",
|
||||||
})
|
})
|
||||||
public parentId: DriveFolder["id"] | null;
|
public parentId: DriveFolder["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => DriveFolder, {
|
@ManyToOne((type) => DriveFolder, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public parent: DriveFolder | null;
|
public parent: DriveFolder | null;
|
||||||
|
|
|
@ -2,73 +2,82 @@ import { PrimaryColumn, Entity, Index, Column } from "typeorm";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['name', 'host'], { unique: true })
|
@Index(["name", "host"], { unique: true })
|
||||||
export class Emoji {
|
export class Emoji {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public updatedAt: Date | null;
|
public updatedAt: Date | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public host: string | null;
|
public host: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public category: string | null;
|
public category: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
})
|
})
|
||||||
public originalUrl: string;
|
public originalUrl: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
default: '',
|
default: "",
|
||||||
})
|
})
|
||||||
public publicUrl: string;
|
public publicUrl: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public uri: string | null;
|
public uri: string | null;
|
||||||
|
|
||||||
// publicUrlの方のtypeが入る
|
// publicUrlの方のtypeが入る
|
||||||
// (mime)
|
// (mime)
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64, nullable: true,
|
length: 64,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public type: string | null;
|
public type: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
array: true, length: 128, default: '{}',
|
array: true,
|
||||||
|
length: 128,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public aliases: string[];
|
public aliases: string[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024, nullable: true,
|
length: 1024,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public license: string | null;
|
public license: string | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
nullable: true, comment: 'Image width',
|
nullable: true,
|
||||||
|
comment: "Image width",
|
||||||
})
|
})
|
||||||
public width: number | null;
|
public width: number | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
nullable: true, comment: "Image height",
|
nullable: true,
|
||||||
|
comment: "Image height",
|
||||||
})
|
})
|
||||||
public height: number | null;
|
public height: number | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,25 +10,25 @@ import { User } from "./user.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['followerId', 'followeeId'], { unique: true })
|
@Index(["followerId", "followeeId"], { unique: true })
|
||||||
export class FollowRequest {
|
export class FollowRequest {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the FollowRequest.',
|
comment: "The created date of the FollowRequest.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The followee user ID.',
|
comment: "The followee user ID.",
|
||||||
})
|
})
|
||||||
public followeeId: User["id"];
|
public followeeId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public followee: User | null;
|
public followee: User | null;
|
||||||
|
@ -36,56 +36,63 @@ export class FollowRequest {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The follower user ID.',
|
comment: "The follower user ID.",
|
||||||
})
|
})
|
||||||
public followerId: User["id"];
|
public followerId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public follower: User | null;
|
public follower: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: 'id of Follow Activity.',
|
nullable: true,
|
||||||
|
comment: "id of Follow Activity.",
|
||||||
})
|
})
|
||||||
public requestId: string | null;
|
public requestId: string | null;
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followerHost: string | null;
|
public followerHost: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followerInbox: string | null;
|
public followerInbox: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followerSharedInbox: string | null;
|
public followerSharedInbox: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followeeHost: string | null;
|
public followeeHost: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followeeInbox: string | null;
|
public followeeInbox: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followeeSharedInbox: string | null;
|
public followeeSharedInbox: string | null;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -10,26 +10,26 @@ import { User } from "./user.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['followerId', 'followeeId'], { unique: true })
|
@Index(["followerId", "followeeId"], { unique: true })
|
||||||
export class Following {
|
export class Following {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Following.',
|
comment: "The created date of the Following.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The followee user ID.',
|
comment: "The followee user ID.",
|
||||||
})
|
})
|
||||||
public followeeId: User["id"];
|
public followeeId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public followee: User | null;
|
public followee: User | null;
|
||||||
|
@ -37,52 +37,58 @@ export class Following {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The follower user ID.',
|
comment: "The follower user ID.",
|
||||||
})
|
})
|
||||||
public followerId: User["id"];
|
public followerId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public follower: User | null;
|
public follower: User | null;
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followerHost: string | null;
|
public followerHost: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followerInbox: string | null;
|
public followerInbox: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followerSharedInbox: string | null;
|
public followerSharedInbox: string | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followeeHost: string | null;
|
public followeeHost: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followeeInbox: string | null;
|
public followeeInbox: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public followeeSharedInbox: string | null;
|
public followeeSharedInbox: string | null;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -11,20 +11,20 @@ import { id } from "../id.js";
|
||||||
import { GalleryPost } from "./gallery-post.js";
|
import { GalleryPost } from "./gallery-post.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'postId'], { unique: true })
|
@Index(["userId", "postId"], { unique: true })
|
||||||
export class GalleryLike {
|
export class GalleryLike {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone')
|
@Column("timestamp with time zone")
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -32,8 +32,8 @@ export class GalleryLike {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public postId: GalleryPost["id"];
|
public postId: GalleryPost["id"];
|
||||||
|
|
||||||
@ManyToOne(type => GalleryPost, {
|
@ManyToOne((type) => GalleryPost, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public post: GalleryPost | null;
|
public post: GalleryPost | null;
|
||||||
|
|
|
@ -16,36 +16,37 @@ export class GalleryPost {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the GalleryPost.',
|
comment: "The created date of the GalleryPost.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The updated date of the GalleryPost.',
|
comment: "The updated date of the GalleryPost.",
|
||||||
})
|
})
|
||||||
public updatedAt: Date;
|
public updatedAt: Date;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: 256,
|
||||||
})
|
})
|
||||||
public title: string;
|
public title: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 2048, nullable: true,
|
length: 2048,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public description: string | null;
|
public description: string | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The ID of author.',
|
comment: "The ID of author.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -53,26 +54,29 @@ export class GalleryPost {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
array: true, default: '{}',
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public fileIds: DriveFile["id"][];
|
public fileIds: DriveFile["id"][];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the post is sensitive.',
|
comment: "Whether the post is sensitive.",
|
||||||
})
|
})
|
||||||
public isSensitive: boolean;
|
public isSensitive: boolean;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public likedCount: number;
|
public likedCount: number;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, array: true, default: '{}',
|
length: 128,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public tags: string[];
|
public tags: string[];
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ export class Hashtag {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
@ -20,7 +20,7 @@ export class Hashtag {
|
||||||
public mentionedUserIds: User["id"][];
|
public mentionedUserIds: User["id"][];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public mentionedUsersCount: number;
|
public mentionedUsersCount: number;
|
||||||
|
@ -32,7 +32,7 @@ export class Hashtag {
|
||||||
public mentionedLocalUserIds: User["id"][];
|
public mentionedLocalUserIds: User["id"][];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public mentionedLocalUsersCount: number;
|
public mentionedLocalUsersCount: number;
|
||||||
|
@ -44,7 +44,7 @@ export class Hashtag {
|
||||||
public mentionedRemoteUserIds: User["id"][];
|
public mentionedRemoteUserIds: User["id"][];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public mentionedRemoteUsersCount: number;
|
public mentionedRemoteUsersCount: number;
|
||||||
|
@ -56,7 +56,7 @@ export class Hashtag {
|
||||||
public attachedUserIds: User["id"][];
|
public attachedUserIds: User["id"][];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public attachedUsersCount: number;
|
public attachedUsersCount: number;
|
||||||
|
@ -68,7 +68,7 @@ export class Hashtag {
|
||||||
public attachedLocalUserIds: User["id"][];
|
public attachedLocalUserIds: User["id"][];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public attachedLocalUsersCount: number;
|
public attachedLocalUsersCount: number;
|
||||||
|
@ -80,7 +80,7 @@ export class Hashtag {
|
||||||
public attachedRemoteUserIds: User["id"][];
|
public attachedRemoteUserIds: User["id"][];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public attachedRemoteUsersCount: number;
|
public attachedRemoteUsersCount: number;
|
||||||
|
|
|
@ -10,8 +10,8 @@ export class Instance {
|
||||||
* このインスタンスを捕捉した日時
|
* このインスタンスを捕捉した日時
|
||||||
*/
|
*/
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The caught date of the Instance.',
|
comment: "The caught date of the Instance.",
|
||||||
})
|
})
|
||||||
public caughtAt: Date;
|
public caughtAt: Date;
|
||||||
|
|
||||||
|
@ -19,34 +19,34 @@ export class Instance {
|
||||||
* ホスト
|
* ホスト
|
||||||
*/
|
*/
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
comment: 'The host of the Instance.',
|
comment: "The host of the Instance.",
|
||||||
})
|
})
|
||||||
public host: string;
|
public host: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* インスタンスのユーザー数
|
* インスタンスのユーザー数
|
||||||
*/
|
*/
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
comment: 'The count of the users of the Instance.',
|
comment: "The count of the users of the Instance.",
|
||||||
})
|
})
|
||||||
public usersCount: number;
|
public usersCount: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* インスタンスの投稿数
|
* インスタンスの投稿数
|
||||||
*/
|
*/
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
comment: 'The count of the notes of the Instance.',
|
comment: "The count of the notes of the Instance.",
|
||||||
})
|
})
|
||||||
public notesCount: number;
|
public notesCount: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* このインスタンスのユーザーからフォローされている、自インスタンスのユーザーの数
|
* このインスタンスのユーザーからフォローされている、自インスタンスのユーザーの数
|
||||||
*/
|
*/
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public followingCount: number;
|
public followingCount: number;
|
||||||
|
@ -54,7 +54,7 @@ export class Instance {
|
||||||
/**
|
/**
|
||||||
* このインスタンスのユーザーをフォローしている、自インスタンスのユーザーの数
|
* このインスタンスのユーザーをフォローしている、自インスタンスのユーザーの数
|
||||||
*/
|
*/
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public followersCount: number;
|
public followersCount: number;
|
||||||
|
@ -62,7 +62,7 @@ export class Instance {
|
||||||
/**
|
/**
|
||||||
* 直近のリクエスト送信日時
|
* 直近のリクエスト送信日時
|
||||||
*/
|
*/
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public latestRequestSentAt: Date | null;
|
public latestRequestSentAt: Date | null;
|
||||||
|
@ -70,7 +70,7 @@ export class Instance {
|
||||||
/**
|
/**
|
||||||
* 直近のリクエスト送信時のHTTPステータスコード
|
* 直近のリクエスト送信時のHTTPステータスコード
|
||||||
*/
|
*/
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public latestStatus: number | null;
|
public latestStatus: number | null;
|
||||||
|
@ -78,7 +78,7 @@ export class Instance {
|
||||||
/**
|
/**
|
||||||
* 直近のリクエスト受信日時
|
* 直近のリクエスト受信日時
|
||||||
*/
|
*/
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public latestRequestReceivedAt: Date | null;
|
public latestRequestReceivedAt: Date | null;
|
||||||
|
@ -86,13 +86,13 @@ export class Instance {
|
||||||
/**
|
/**
|
||||||
* このインスタンスと最後にやり取りした日時
|
* このインスタンスと最後にやり取りした日時
|
||||||
*/
|
*/
|
||||||
@Column('timestamp with time zone')
|
@Column("timestamp with time zone")
|
||||||
public lastCommunicatedAt: Date;
|
public lastCommunicatedAt: Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* このインスタンスと不通かどうか
|
* このインスタンスと不通かどうか
|
||||||
*/
|
*/
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public isNotResponding: boolean;
|
public isNotResponding: boolean;
|
||||||
|
@ -101,63 +101,72 @@ export class Instance {
|
||||||
* このインスタンスへの配信を停止するか
|
* このインスタンスへの配信を停止するか
|
||||||
*/
|
*/
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public isSuspended: boolean;
|
public isSuspended: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64, nullable: true,
|
length: 64,
|
||||||
comment: 'The software of the Instance.',
|
nullable: true,
|
||||||
|
comment: "The software of the Instance.",
|
||||||
})
|
})
|
||||||
public softwareName: string | null;
|
public softwareName: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64, nullable: true,
|
length: 64,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public softwareVersion: string | null;
|
public softwareVersion: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public openRegistrations: boolean | null;
|
public openRegistrations: boolean | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public name: string | null;
|
public name: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 4096, nullable: true,
|
length: 4096,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public description: string | null;
|
public description: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public maintainerName: string | null;
|
public maintainerName: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public maintainerEmail: string | null;
|
public maintainerEmail: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public iconUrl: string | null;
|
public iconUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public faviconUrl: string | null;
|
public faviconUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64, nullable: true,
|
length: 64,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public themeColor: string | null;
|
public themeColor: string | null;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public infoUpdatedAt: Date | null;
|
public infoUpdatedAt: Date | null;
|
||||||
|
|
|
@ -17,68 +17,73 @@ export class MessagingMessage {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the MessagingMessage.',
|
comment: "The created date of the MessagingMessage.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The sender user ID.',
|
comment: "The sender user ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(), nullable: true,
|
...id(),
|
||||||
comment: 'The recipient user ID.',
|
nullable: true,
|
||||||
|
comment: "The recipient user ID.",
|
||||||
})
|
})
|
||||||
public recipientId: User["id"] | null;
|
public recipientId: User["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public recipient: User | null;
|
public recipient: User | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(), nullable: true,
|
...id(),
|
||||||
comment: 'The recipient group ID.',
|
nullable: true,
|
||||||
|
comment: "The recipient group ID.",
|
||||||
})
|
})
|
||||||
public groupId: UserGroup["id"] | null;
|
public groupId: UserGroup["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => UserGroup, {
|
@ManyToOne((type) => UserGroup, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public group: UserGroup | null;
|
public group: UserGroup | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 4096, nullable: true,
|
length: 4096,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public text: string | null;
|
public text: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public isRead: boolean;
|
public isRead: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public uri: string | null;
|
public uri: string | null;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
array: true, default: '{}',
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public reads: User["id"][];
|
public reads: User["id"][];
|
||||||
|
|
||||||
|
@ -88,8 +93,8 @@ export class MessagingMessage {
|
||||||
})
|
})
|
||||||
public fileId: DriveFile["id"] | null;
|
public fileId: DriveFile["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => DriveFile, {
|
@ManyToOne((type) => DriveFile, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public file: DriveFile | null;
|
public file: DriveFile | null;
|
||||||
|
|
|
@ -6,119 +6,144 @@ import type { Clip } from "./clip.js";
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Meta {
|
export class Meta {
|
||||||
@PrimaryColumn({
|
@PrimaryColumn({
|
||||||
type: 'varchar',
|
type: "varchar",
|
||||||
length: 32,
|
length: 32,
|
||||||
})
|
})
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public name: string | null;
|
public name: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024, nullable: true,
|
length: 1024,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public description: string | null;
|
public description: string | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* メンテナの名前
|
* メンテナの名前
|
||||||
*/
|
*/
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public maintainerName: string | null;
|
public maintainerName: string | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* メンテナの連絡先
|
* メンテナの連絡先
|
||||||
*/
|
*/
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public maintainerEmail: string | null;
|
public maintainerEmail: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public disableRegistration: boolean;
|
public disableRegistration: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public disableLocalTimeline: boolean;
|
public disableLocalTimeline: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public disableRecommendedTimeline: boolean;
|
public disableRecommendedTimeline: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public disableGlobalTimeline: boolean;
|
public disableGlobalTimeline: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, default: '⭐',
|
length: 256,
|
||||||
|
default: "⭐",
|
||||||
})
|
})
|
||||||
public defaultReaction: string;
|
public defaultReaction: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64, array: true, default: '{}',
|
length: 64,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public langs: string[];
|
public langs: string[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, array: true, default: '{}',
|
length: 256,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public pinnedUsers: string[];
|
public pinnedUsers: string[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, array: true, default: '{}',
|
length: 256,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public recommendedInstances: string[];
|
public recommendedInstances: string[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, array: true, default: '{}',
|
length: 256,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public customMOTD: string[];
|
public customMOTD: string[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, array: true, default: '{}',
|
length: 256,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public customSplashIcons: string[];
|
public customSplashIcons: string[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, array: true, default: '{}',
|
length: 256,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public hiddenTags: string[];
|
public hiddenTags: string[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, array: true, default: '{}',
|
length: 256,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public blockedHosts: string[];
|
public blockedHosts: string[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, array: true, default: '{}',
|
length: 256,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public silencedHosts: string[];
|
public silencedHosts: string[];
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public secureMode: boolean;
|
public secureMode: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public privateMode: boolean;
|
public privateMode: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, array: true, default: '{}',
|
length: 256,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public allowedHosts: string[];
|
public allowedHosts: string[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, array: true, default: '{/featured,/channels,/explore,/pages,/about-calckey}',
|
length: 512,
|
||||||
|
array: true,
|
||||||
|
default: "{/featured,/channels,/explore,/pages,/about-calckey}",
|
||||||
})
|
})
|
||||||
public pinnedPages: string[];
|
public pinnedPages: string[];
|
||||||
|
|
||||||
|
@ -128,51 +153,51 @@ export class Meta {
|
||||||
})
|
})
|
||||||
public pinnedClipId: Clip["id"] | null;
|
public pinnedClipId: Clip["id"] | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public themeColor: string | null;
|
public themeColor: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
default: '/assets/ai.png',
|
default: "/assets/ai.png",
|
||||||
})
|
})
|
||||||
public mascotImageUrl: string | null;
|
public mascotImageUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public bannerUrl: string | null;
|
public bannerUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public backgroundImageUrl: string | null;
|
public backgroundImageUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public logoImageUrl: string | null;
|
public logoImageUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
default: 'https://xn--931a.moe/aiart/yubitun.png',
|
default: "https://xn--931a.moe/aiart/yubitun.png",
|
||||||
})
|
})
|
||||||
public errorImageUrl: string | null;
|
public errorImageUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public iconUrl: string | null;
|
public iconUrl: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public cacheRemoteFiles: boolean;
|
public cacheRemoteFiles: boolean;
|
||||||
|
@ -183,60 +208,60 @@ export class Meta {
|
||||||
})
|
})
|
||||||
public proxyAccountId: User["id"] | null;
|
public proxyAccountId: User["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public proxyAccount: User | null;
|
public proxyAccount: User | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public emailRequiredForSignup: boolean;
|
public emailRequiredForSignup: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public enableHcaptcha: boolean;
|
public enableHcaptcha: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64,
|
length: 64,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public hcaptchaSiteKey: string | null;
|
public hcaptchaSiteKey: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64,
|
length: 64,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public hcaptchaSecretKey: string | null;
|
public hcaptchaSecretKey: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public enableRecaptcha: boolean;
|
public enableRecaptcha: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64,
|
length: 64,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public recaptchaSiteKey: string | null;
|
public recaptchaSiteKey: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64,
|
length: 64,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public recaptchaSecretKey: string | null;
|
public recaptchaSecretKey: string | null;
|
||||||
|
|
||||||
@Column('enum', {
|
@Column("enum", {
|
||||||
enum: ['none', 'all', 'local', 'remote'],
|
enum: ["none", "all", "local", "remote"],
|
||||||
default: 'none',
|
default: "none",
|
||||||
})
|
})
|
||||||
public sensitiveMediaDetection: "none" | "all" | "local" | "remote";
|
public sensitiveMediaDetection: "none" | "all" | "local" | "remote";
|
||||||
|
|
||||||
@Column('enum', {
|
@Column("enum", {
|
||||||
enum: ['medium', 'low', 'high', 'veryLow', 'veryHigh'],
|
enum: ["medium", "low", "high", "veryLow", "veryHigh"],
|
||||||
default: 'medium',
|
default: "medium",
|
||||||
})
|
})
|
||||||
public sensitiveMediaDetectionSensitivity:
|
public sensitiveMediaDetectionSensitivity:
|
||||||
| "medium"
|
| "medium"
|
||||||
|
@ -245,279 +270,279 @@ export class Meta {
|
||||||
| "veryLow"
|
| "veryLow"
|
||||||
| "veryHigh";
|
| "veryHigh";
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public setSensitiveFlagAutomatically: boolean;
|
public setSensitiveFlagAutomatically: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public enableSensitiveMediaDetectionForVideos: boolean;
|
public enableSensitiveMediaDetectionForVideos: boolean;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 1024,
|
default: 1024,
|
||||||
comment: 'Drive capacity of a local user (MB)',
|
comment: "Drive capacity of a local user (MB)",
|
||||||
})
|
})
|
||||||
public localDriveCapacityMb: number;
|
public localDriveCapacityMb: number;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 32,
|
default: 32,
|
||||||
comment: 'Drive capacity of a remote user (MB)',
|
comment: "Drive capacity of a remote user (MB)",
|
||||||
})
|
})
|
||||||
public remoteDriveCapacityMb: number;
|
public remoteDriveCapacityMb: number;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public summalyProxy: string | null;
|
public summalyProxy: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public enableEmail: boolean;
|
public enableEmail: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public email: string | null;
|
public email: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public smtpSecure: boolean;
|
public smtpSecure: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public smtpHost: string | null;
|
public smtpHost: string | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public smtpPort: number | null;
|
public smtpPort: number | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public smtpUser: string | null;
|
public smtpUser: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public smtpPass: string | null;
|
public smtpPass: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public enableServiceWorker: boolean;
|
public enableServiceWorker: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public swPublicKey: string | null;
|
public swPublicKey: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public swPrivateKey: string | null;
|
public swPrivateKey: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public enableTwitterIntegration: boolean;
|
public enableTwitterIntegration: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public twitterConsumerKey: string | null;
|
public twitterConsumerKey: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public twitterConsumerSecret: string | null;
|
public twitterConsumerSecret: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public enableGithubIntegration: boolean;
|
public enableGithubIntegration: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public githubClientId: string | null;
|
public githubClientId: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public githubClientSecret: string | null;
|
public githubClientSecret: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public enableDiscordIntegration: boolean;
|
public enableDiscordIntegration: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public discordClientId: string | null;
|
public discordClientId: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public discordClientSecret: string | null;
|
public discordClientSecret: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public deeplAuthKey: string | null;
|
public deeplAuthKey: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public deeplIsPro: boolean;
|
public deeplIsPro: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public libreTranslateApiUrl: string | null;
|
public libreTranslateApiUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public libreTranslateApiKey: string | null;
|
public libreTranslateApiKey: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public ToSUrl: string | null;
|
public ToSUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
default: 'https://codeberg.org/calckey/calckey',
|
default: "https://codeberg.org/calckey/calckey",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
})
|
})
|
||||||
public repositoryUrl: string;
|
public repositoryUrl: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
default: 'https://codeberg.org/calckey/calckey/issues/new',
|
default: "https://codeberg.org/calckey/calckey/issues/new",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public feedbackUrl: string | null;
|
public feedbackUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 8192,
|
length: 8192,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public defaultLightTheme: string | null;
|
public defaultLightTheme: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 8192,
|
length: 8192,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public defaultDarkTheme: string | null;
|
public defaultDarkTheme: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public useObjectStorage: boolean;
|
public useObjectStorage: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public objectStorageBucket: string | null;
|
public objectStorageBucket: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public objectStoragePrefix: string | null;
|
public objectStoragePrefix: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public objectStorageBaseUrl: string | null;
|
public objectStorageBaseUrl: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public objectStorageEndpoint: string | null;
|
public objectStorageEndpoint: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public objectStorageRegion: string | null;
|
public objectStorageRegion: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public objectStorageAccessKey: string | null;
|
public objectStorageAccessKey: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public objectStorageSecretKey: string | null;
|
public objectStorageSecretKey: string | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public objectStoragePort: number | null;
|
public objectStoragePort: number | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public objectStorageUseSSL: boolean;
|
public objectStorageUseSSL: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public objectStorageUseProxy: boolean;
|
public objectStorageUseProxy: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public objectStorageSetPublicRead: boolean;
|
public objectStorageSetPublicRead: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public objectStorageS3ForcePathStyle: boolean;
|
public objectStorageS3ForcePathStyle: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public enableIpLogging: boolean;
|
public enableIpLogging: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public enableActiveEmailValidation: boolean;
|
public enableActiveEmailValidation: boolean;
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: {},
|
default: {},
|
||||||
})
|
})
|
||||||
public experimentalFeatures: Record<string, unknown>;
|
public experimentalFeatures: Record<string, unknown>;
|
||||||
|
|
|
@ -14,8 +14,8 @@ export class ModerationLog {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the ModerationLog.',
|
comment: "The created date of the ModerationLog.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -23,17 +23,17 @@ export class ModerationLog {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public type: string;
|
public type: string;
|
||||||
|
|
||||||
@Column('jsonb')
|
@Column("jsonb")
|
||||||
public info: Record<string, any>;
|
public info: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { id } from "../id.js";
|
||||||
import { mutedNoteReasons } from "../../types.js";
|
import { mutedNoteReasons } from "../../types.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['noteId', 'userId'], { unique: true })
|
@Index(["noteId", "userId"], { unique: true })
|
||||||
export class MutedNote {
|
export class MutedNote {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
@ -20,12 +20,12 @@ export class MutedNote {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The note ID.',
|
comment: "The note ID.",
|
||||||
})
|
})
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
@ -33,12 +33,12 @@ export class MutedNote {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The user ID.',
|
comment: "The user ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -47,9 +47,9 @@ export class MutedNote {
|
||||||
* ミュートされた理由。
|
* ミュートされた理由。
|
||||||
*/
|
*/
|
||||||
@Index()
|
@Index()
|
||||||
@Column('enum', {
|
@Column("enum", {
|
||||||
enum: mutedNoteReasons,
|
enum: mutedNoteReasons,
|
||||||
comment: 'The reason of the MutedNote.',
|
comment: "The reason of the MutedNote.",
|
||||||
})
|
})
|
||||||
public reason: typeof mutedNoteReasons[number];
|
public reason: typeof mutedNoteReasons[number];
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,19 +10,19 @@ import { User } from "./user.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['muterId', 'muteeId'], { unique: true })
|
@Index(["muterId", "muteeId"], { unique: true })
|
||||||
export class Muting {
|
export class Muting {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Muting.',
|
comment: "The created date of the Muting.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public expiresAt: Date | null;
|
public expiresAt: Date | null;
|
||||||
|
@ -30,12 +30,12 @@ export class Muting {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The mutee user ID.',
|
comment: "The mutee user ID.",
|
||||||
})
|
})
|
||||||
public muteeId: User["id"];
|
public muteeId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public mutee: User | null;
|
public mutee: User | null;
|
||||||
|
@ -43,12 +43,12 @@ export class Muting {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The muter user ID.',
|
comment: "The muter user ID.",
|
||||||
})
|
})
|
||||||
public muterId: User["id"];
|
public muterId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public muter: User | null;
|
public muter: User | null;
|
||||||
|
|
|
@ -18,34 +18,36 @@ export class NoteEdit {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The ID of note.',
|
comment: "The ID of note.",
|
||||||
})
|
})
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
|
||||||
@Column('text', {
|
@Column("text", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public text: string | null;
|
public text: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public cw: string | null;
|
public cw: string | null;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
array: true, default: '{}',
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public fileIds: DriveFile["id"][];
|
public fileIds: DriveFile["id"][];
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The updated date of the Note.',
|
comment: "The updated date of the Note.",
|
||||||
})
|
})
|
||||||
public updatedAt: Date;
|
public updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ import { User } from "./user.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'noteId'], { unique: true })
|
@Index(["userId", "noteId"], { unique: true })
|
||||||
export class NoteFavorite {
|
export class NoteFavorite {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the NoteFavorite.',
|
comment: "The created date of the NoteFavorite.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ export class NoteFavorite {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -34,8 +34,8 @@ export class NoteFavorite {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
|
|
@ -11,14 +11,14 @@ import { Note } from "./note.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'noteId'], { unique: true })
|
@Index(["userId", "noteId"], { unique: true })
|
||||||
export class NoteReaction {
|
export class NoteReaction {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the NoteReaction.',
|
comment: "The created date of the NoteReaction.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ export class NoteReaction {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user?: User | null;
|
public user?: User | null;
|
||||||
|
@ -36,15 +36,15 @@ export class NoteReaction {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note?: Note | null;
|
public note?: Note | null;
|
||||||
|
|
||||||
// TODO: 対象noteのuserIdを非正規化したい(「受け取ったリアクション一覧」のようなものを(JOIN無しで)実装したいため)
|
// TODO: 対象noteのuserIdを非正規化したい(「受け取ったリアクション一覧」のようなものを(JOIN無しで)実装したいため)
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 260,
|
length: 260,
|
||||||
})
|
})
|
||||||
public reaction: string;
|
public reaction: string;
|
||||||
|
|
|
@ -11,13 +11,12 @@ import { Note } from "./note.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'threadId'], { unique: true })
|
@Index(["userId", "threadId"], { unique: true })
|
||||||
export class NoteThreadMuting {
|
export class NoteThreadMuting {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {})
|
||||||
})
|
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
|
@ -26,14 +25,14 @@ export class NoteThreadMuting {
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: 256,
|
||||||
})
|
})
|
||||||
public threadId: string;
|
public threadId: string;
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { id } from "../id.js";
|
||||||
import type { Channel } from "./channel.js";
|
import type { Channel } from "./channel.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'noteId'], { unique: true })
|
@Index(["userId", "noteId"], { unique: true })
|
||||||
export class NoteUnread {
|
export class NoteUnread {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
@ -21,8 +21,8 @@ export class NoteUnread {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -31,8 +31,8 @@ export class NoteUnread {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
@ -41,21 +41,21 @@ export class NoteUnread {
|
||||||
* メンションか否か
|
* メンションか否か
|
||||||
*/
|
*/
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean')
|
@Column("boolean")
|
||||||
public isMentioned: boolean;
|
public isMentioned: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ダイレクト投稿か否か
|
* ダイレクト投稿か否か
|
||||||
*/
|
*/
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean')
|
@Column("boolean")
|
||||||
public isSpecified: boolean;
|
public isSpecified: boolean;
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: '[Denormalized]',
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public noteUserId: User["id"];
|
public noteUserId: User["id"];
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ export class NoteUnread {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: '[Denormalized]',
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public noteChannelId: Channel["id"] | null;
|
public noteChannelId: Channel["id"] | null;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -11,26 +11,26 @@ import { Note } from "./note.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'noteId'], { unique: true })
|
@Index(["userId", "noteId"], { unique: true })
|
||||||
export class NoteWatching {
|
export class NoteWatching {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the NoteWatching.',
|
comment: "The created date of the NoteWatching.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The watcher ID.',
|
comment: "The watcher ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -38,12 +38,12 @@ export class NoteWatching {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The target Note ID.',
|
comment: "The target Note ID.",
|
||||||
})
|
})
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
@ -52,7 +52,7 @@ export class NoteWatching {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: '[Denormalized]',
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public noteUserId: Note["userId"];
|
public noteUserId: Note["userId"];
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -13,16 +13,16 @@ import { noteVisibilities } from "../../types.js";
|
||||||
import { Channel } from "./channel.js";
|
import { Channel } from "./channel.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index('IDX_NOTE_TAGS', { synchronize: false })
|
@Index("IDX_NOTE_TAGS", { synchronize: false })
|
||||||
@Index('IDX_NOTE_MENTIONS', { synchronize: false })
|
@Index("IDX_NOTE_MENTIONS", { synchronize: false })
|
||||||
@Index('IDX_NOTE_VISIBLE_USER_IDS', { synchronize: false })
|
@Index("IDX_NOTE_VISIBLE_USER_IDS", { synchronize: false })
|
||||||
export class Note {
|
export class Note {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Note.',
|
comment: "The created date of the Note.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ export class Note {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The ID of reply target.',
|
comment: "The ID of reply target.",
|
||||||
})
|
})
|
||||||
public replyId: Note["id"] | null;
|
public replyId: Note["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public reply: Note | null;
|
public reply: Note | null;
|
||||||
|
@ -44,66 +44,69 @@ export class Note {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The ID of renote target.',
|
comment: "The ID of renote target.",
|
||||||
})
|
})
|
||||||
public renoteId: Note["id"] | null;
|
public renoteId: Note["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public renote: Note | null;
|
public renote: Note | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public threadId: string | null;
|
public threadId: string | null;
|
||||||
|
|
||||||
@Column('text', {
|
@Column("text", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public text: string | null;
|
public text: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public name: string | null;
|
public name: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public cw: string | null;
|
public cw: string | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The ID of author.',
|
comment: "The ID of author.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public localOnly: boolean;
|
public localOnly: boolean;
|
||||||
|
|
||||||
@Column('smallint', {
|
@Column("smallint", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public renoteCount: number;
|
public renoteCount: number;
|
||||||
|
|
||||||
@Column('smallint', {
|
@Column("smallint", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public repliesCount: number;
|
public repliesCount: number;
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: {},
|
default: {},
|
||||||
})
|
})
|
||||||
public reactions: Record<string, number>;
|
public reactions: Record<string, number>;
|
||||||
|
@ -115,71 +118,84 @@ export class Note {
|
||||||
* followers ... フォロワーのみ
|
* followers ... フォロワーのみ
|
||||||
* specified ... visibleUserIds で指定したユーザーのみ
|
* specified ... visibleUserIds で指定したユーザーのみ
|
||||||
*/
|
*/
|
||||||
@Column('enum', { enum: noteVisibilities })
|
@Column("enum", { enum: noteVisibilities })
|
||||||
public visibility: typeof noteVisibilities[number];
|
public visibility: typeof noteVisibilities[number];
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The URI of a note. it will be null when the note is local.',
|
nullable: true,
|
||||||
|
comment: "The URI of a note. it will be null when the note is local.",
|
||||||
})
|
})
|
||||||
public uri: string | null;
|
public uri: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The human readable url of a note. it will be null when the note is local.',
|
nullable: true,
|
||||||
|
comment:
|
||||||
|
"The human readable url of a note. it will be null when the note is local.",
|
||||||
})
|
})
|
||||||
public url: string | null;
|
public url: string | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0, select: false,
|
default: 0,
|
||||||
|
select: false,
|
||||||
})
|
})
|
||||||
public score: number;
|
public score: number;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
array: true, default: '{}',
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public fileIds: DriveFile["id"][];
|
public fileIds: DriveFile["id"][];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, array: true, default: '{}',
|
length: 256,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public attachedFileTypes: string[];
|
public attachedFileTypes: string[];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
array: true, default: '{}',
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public visibleUserIds: User["id"][];
|
public visibleUserIds: User["id"][];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
array: true, default: '{}',
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public mentions: User["id"][];
|
public mentions: User["id"][];
|
||||||
|
|
||||||
@Column('text', {
|
@Column("text", {
|
||||||
default: '[]',
|
default: "[]",
|
||||||
})
|
})
|
||||||
public mentionedRemoteUsers: string;
|
public mentionedRemoteUsers: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, array: true, default: '{}',
|
length: 128,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public emojis: string[];
|
public emojis: string[];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, array: true, default: '{}',
|
length: 128,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public tags: string[];
|
public tags: string[];
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public hasPoll: boolean;
|
public hasPoll: boolean;
|
||||||
|
@ -188,53 +204,56 @@ export class Note {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The ID of source channel.',
|
comment: "The ID of source channel.",
|
||||||
})
|
})
|
||||||
public channelId: Channel["id"] | null;
|
public channelId: Channel["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => Channel, {
|
@ManyToOne((type) => Channel, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public channel: Channel | null;
|
public channel: Channel | null;
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public userHost: string | null;
|
public userHost: string | null;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: '[Denormalized]',
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public replyUserId: User["id"] | null;
|
public replyUserId: User["id"] | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public replyUserHost: string | null;
|
public replyUserHost: string | null;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: '[Denormalized]',
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public renoteUserId: User["id"] | null;
|
public renoteUserId: User["id"] | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public renoteUserHost: string | null;
|
public renoteUserHost: string | null;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The updated date of the Note.',
|
comment: "The updated date of the Note.",
|
||||||
})
|
})
|
||||||
public updatedAt: Date;
|
public updatedAt: Date;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -20,8 +20,8 @@ export class Notification {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Notification.',
|
comment: "The created date of the Notification.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@ export class Notification {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The ID of recipient user of the Notification.',
|
comment: "The ID of recipient user of the Notification.",
|
||||||
})
|
})
|
||||||
public notifieeId: User["id"];
|
public notifieeId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public notifiee: User | null;
|
public notifiee: User | null;
|
||||||
|
@ -48,12 +48,12 @@ export class Notification {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The ID of sender user of the Notification.',
|
comment: "The ID of sender user of the Notification.",
|
||||||
})
|
})
|
||||||
public notifierId: User["id"] | null;
|
public notifierId: User["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public notifier: User | null;
|
public notifier: User | null;
|
||||||
|
@ -74,9 +74,9 @@ export class Notification {
|
||||||
* app - App notifications.
|
* app - App notifications.
|
||||||
*/
|
*/
|
||||||
@Index()
|
@Index()
|
||||||
@Column('enum', {
|
@Column("enum", {
|
||||||
enum: notificationTypes,
|
enum: notificationTypes,
|
||||||
comment: 'The type of the Notification.',
|
comment: "The type of the Notification.",
|
||||||
})
|
})
|
||||||
public type: typeof notificationTypes[number];
|
public type: typeof notificationTypes[number];
|
||||||
|
|
||||||
|
@ -84,9 +84,9 @@ export class Notification {
|
||||||
* Whether the notification was read.
|
* Whether the notification was read.
|
||||||
*/
|
*/
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the notification was read.',
|
comment: "Whether the notification was read.",
|
||||||
})
|
})
|
||||||
public isRead: boolean;
|
public isRead: boolean;
|
||||||
|
|
||||||
|
@ -96,8 +96,8 @@ export class Notification {
|
||||||
})
|
})
|
||||||
public noteId: Note["id"] | null;
|
public noteId: Note["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
@ -108,8 +108,8 @@ export class Notification {
|
||||||
})
|
})
|
||||||
public followRequestId: FollowRequest["id"] | null;
|
public followRequestId: FollowRequest["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => FollowRequest, {
|
@ManyToOne((type) => FollowRequest, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public followRequest: FollowRequest | null;
|
public followRequest: FollowRequest | null;
|
||||||
|
@ -120,18 +120,19 @@ export class Notification {
|
||||||
})
|
})
|
||||||
public userGroupInvitationId: UserGroupInvitation["id"] | null;
|
public userGroupInvitationId: UserGroupInvitation["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => UserGroupInvitation, {
|
@ManyToOne((type) => UserGroupInvitation, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public userGroupInvitation: UserGroupInvitation | null;
|
public userGroupInvitation: UserGroupInvitation | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public reaction: string | null;
|
public reaction: string | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public choice: number | null;
|
public choice: number | null;
|
||||||
|
@ -139,8 +140,9 @@ export class Notification {
|
||||||
/**
|
/**
|
||||||
* App notification body
|
* App notification body
|
||||||
*/
|
*/
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 2048, nullable: true,
|
length: 2048,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public customBody: string | null;
|
public customBody: string | null;
|
||||||
|
|
||||||
|
@ -148,8 +150,9 @@ export class Notification {
|
||||||
* App notification header
|
* App notification header
|
||||||
* (If omitted, it is expected to be displayed with the app name)
|
* (If omitted, it is expected to be displayed with the app name)
|
||||||
*/
|
*/
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public customHeader: string | null;
|
public customHeader: string | null;
|
||||||
|
|
||||||
|
@ -157,8 +160,9 @@ export class Notification {
|
||||||
* App notification icon (URL)
|
* App notification icon (URL)
|
||||||
* (If omitted, it is expected to be displayed as an app icon)
|
* (If omitted, it is expected to be displayed as an app icon)
|
||||||
*/
|
*/
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024, nullable: true,
|
length: 1024,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public customIcon: string | null;
|
public customIcon: string | null;
|
||||||
|
|
||||||
|
@ -172,8 +176,8 @@ export class Notification {
|
||||||
})
|
})
|
||||||
public appAccessTokenId: AccessToken["id"] | null;
|
public appAccessTokenId: AccessToken["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => AccessToken, {
|
@ManyToOne((type) => AccessToken, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public appAccessToken: AccessToken | null;
|
public appAccessToken: AccessToken | null;
|
||||||
|
|
|
@ -11,20 +11,20 @@ import { id } from "../id.js";
|
||||||
import { Page } from "./page.js";
|
import { Page } from "./page.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'pageId'], { unique: true })
|
@Index(["userId", "pageId"], { unique: true })
|
||||||
export class PageLike {
|
export class PageLike {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone')
|
@Column("timestamp with time zone")
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -32,8 +32,8 @@ export class PageLike {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public pageId: Page["id"];
|
public pageId: Page["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Page, {
|
@ManyToOne((type) => Page, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public page: Page | null;
|
public page: Page | null;
|
||||||
|
|
|
@ -11,51 +11,52 @@ import { id } from "../id.js";
|
||||||
import { DriveFile } from "./drive-file.js";
|
import { DriveFile } from "./drive-file.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'name'], { unique: true })
|
@Index(["userId", "name"], { unique: true })
|
||||||
export class Page {
|
export class Page {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Page.',
|
comment: "The created date of the Page.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The updated date of the Page.',
|
comment: "The updated date of the Page.",
|
||||||
})
|
})
|
||||||
public updatedAt: Date;
|
public updatedAt: Date;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: 256,
|
||||||
})
|
})
|
||||||
public title: string;
|
public title: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: 256,
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, nullable: true,
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public summary: string | null;
|
public summary: string | null;
|
||||||
|
|
||||||
@Column('boolean')
|
@Column("boolean")
|
||||||
public alignCenter: boolean;
|
public alignCenter: boolean;
|
||||||
|
|
||||||
@Column('boolean')
|
@Column("boolean")
|
||||||
public isPublic: boolean;
|
public isPublic: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public hideTitleWhenPinned: boolean;
|
public hideTitleWhenPinned: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 32,
|
length: 32,
|
||||||
})
|
})
|
||||||
public font: string;
|
public font: string;
|
||||||
|
@ -63,12 +64,12 @@ export class Page {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The ID of author.',
|
comment: "The ID of author.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -79,25 +80,25 @@ export class Page {
|
||||||
})
|
})
|
||||||
public eyeCatchingImageId: DriveFile["id"] | null;
|
public eyeCatchingImageId: DriveFile["id"] | null;
|
||||||
|
|
||||||
@ManyToOne(type => DriveFile, {
|
@ManyToOne((type) => DriveFile, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public eyeCatchingImage: DriveFile | null;
|
public eyeCatchingImage: DriveFile | null;
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: [],
|
default: [],
|
||||||
})
|
})
|
||||||
public content: Record<string, any>[];
|
public content: Record<string, any>[];
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: [],
|
default: [],
|
||||||
})
|
})
|
||||||
public variables: Record<string, any>[];
|
public variables: Record<string, any>[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 16384,
|
length: 16384,
|
||||||
default: '',
|
default: "",
|
||||||
})
|
})
|
||||||
public script: string;
|
public script: string;
|
||||||
|
|
||||||
|
@ -106,17 +107,18 @@ export class Page {
|
||||||
* followers ... フォロワーのみ
|
* followers ... フォロワーのみ
|
||||||
* specified ... visibleUserIds で指定したユーザーのみ
|
* specified ... visibleUserIds で指定したユーザーのみ
|
||||||
*/
|
*/
|
||||||
@Column('enum', { enum: ['public', 'followers', 'specified'] })
|
@Column("enum", { enum: ["public", "followers", "specified"] })
|
||||||
public visibility: "public" | "followers" | "specified";
|
public visibility: "public" | "followers" | "specified";
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
array: true, default: '{}',
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public visibleUserIds: User["id"][];
|
public visibleUserIds: User["id"][];
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public likedCount: number;
|
public likedCount: number;
|
||||||
|
|
|
@ -14,11 +14,11 @@ export class PasswordResetRequest {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone')
|
@Column("timestamp with time zone")
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: 256,
|
||||||
})
|
})
|
||||||
public token: string;
|
public token: string;
|
||||||
|
@ -29,8 +29,8 @@ export class PasswordResetRequest {
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
|
@ -11,14 +11,14 @@ import { Note } from "./note.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'noteId', 'choice'], { unique: true })
|
@Index(["userId", "noteId", "choice"], { unique: true })
|
||||||
export class PollVote {
|
export class PollVote {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the PollVote.',
|
comment: "The created date of the PollVote.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ export class PollVote {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -36,12 +36,12 @@ export class PollVote {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
|
||||||
@Column('integer')
|
@Column("integer")
|
||||||
public choice: number;
|
public choice: number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,48 +16,51 @@ export class Poll {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@OneToOne(type => Note, {
|
@OneToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public expiresAt: Date | null;
|
public expiresAt: Date | null;
|
||||||
|
|
||||||
@Column('boolean')
|
@Column("boolean")
|
||||||
public multiple: boolean;
|
public multiple: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256, array: true, default: '{}',
|
length: 256,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public choices: string[];
|
public choices: string[];
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
array: true,
|
array: true,
|
||||||
})
|
})
|
||||||
public votes: number[];
|
public votes: number[];
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Column('enum', {
|
@Column("enum", {
|
||||||
enum: noteVisibilities,
|
enum: noteVisibilities,
|
||||||
comment: '[Denormalized]',
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public noteVisibility: typeof noteVisibilities[number];
|
public noteVisibility: typeof noteVisibilities[number];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: '[Denormalized]',
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public userHost: string | null;
|
public userHost: string | null;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -15,20 +15,20 @@ export class PromoNote {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@OneToOne(type => Note, {
|
@OneToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
|
||||||
@Column('timestamp with time zone')
|
@Column("timestamp with time zone")
|
||||||
public expiresAt: Date;
|
public expiresAt: Date;
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: '[Denormalized]',
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -11,13 +11,13 @@ import { User } from "./user.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'noteId'], { unique: true })
|
@Index(["userId", "noteId"], { unique: true })
|
||||||
export class PromoRead {
|
export class PromoRead {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the PromoRead.',
|
comment: "The created date of the PromoRead.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ export class PromoRead {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -34,8 +34,8 @@ export class PromoRead {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
|
|
@ -6,11 +6,11 @@ export class RegistrationTicket {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone')
|
@Column("timestamp with time zone")
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 64,
|
length: 64,
|
||||||
})
|
})
|
||||||
public code: string;
|
public code: string;
|
||||||
|
|
|
@ -15,51 +15,55 @@ export class RegistryItem {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the RegistryItem.',
|
comment: "The created date of the RegistryItem.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The updated date of the RegistryItem.',
|
comment: "The updated date of the RegistryItem.",
|
||||||
})
|
})
|
||||||
public updatedAt: Date;
|
public updatedAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The owner ID.',
|
comment: "The owner ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024,
|
length: 1024,
|
||||||
comment: 'The key of the RegistryItem.',
|
comment: "The key of the RegistryItem.",
|
||||||
})
|
})
|
||||||
public key: string;
|
public key: string;
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: {}, nullable: true,
|
default: {},
|
||||||
comment: 'The value of the RegistryItem.',
|
nullable: true,
|
||||||
|
comment: "The value of the RegistryItem.",
|
||||||
})
|
})
|
||||||
public value: any | null;
|
public value: any | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024, array: true, default: '{}',
|
length: 1024,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public scope: string[];
|
public scope: string[];
|
||||||
|
|
||||||
// サードパーティアプリに開放するときのためのカラム
|
// サードパーティアプリに開放するときのためのカラム
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public domain: string | null;
|
public domain: string | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,14 @@ export class Relay {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: false,
|
length: 512,
|
||||||
|
nullable: false,
|
||||||
})
|
})
|
||||||
public inbox: string;
|
public inbox: string;
|
||||||
|
|
||||||
@Column('enum', {
|
@Column("enum", {
|
||||||
enum: ['requesting', 'accepted', 'rejected'],
|
enum: ["requesting", "accepted", "rejected"],
|
||||||
})
|
})
|
||||||
public status: "requesting" | "accepted" | "rejected";
|
public status: "requesting" | "accepted" | "rejected";
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ export class RenoteMuting {
|
||||||
})
|
})
|
||||||
public muteeId: User["id"];
|
public muteeId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: "CASCADE",
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -41,7 +41,7 @@ export class RenoteMuting {
|
||||||
})
|
})
|
||||||
public muterId: User["id"];
|
public muterId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: "CASCADE",
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -14,8 +14,8 @@ export class Signin {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Signin.',
|
comment: "The created date of the Signin.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -23,20 +23,20 @@ export class Signin {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public ip: string;
|
public ip: string;
|
||||||
|
|
||||||
@Column('jsonb')
|
@Column("jsonb")
|
||||||
public headers: Record<string, any>;
|
public headers: Record<string, any>;
|
||||||
|
|
||||||
@Column('boolean')
|
@Column("boolean")
|
||||||
public success: boolean;
|
public success: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,35 +14,35 @@ export class SwSubscription {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone')
|
@Column("timestamp with time zone")
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
})
|
})
|
||||||
public endpoint: string;
|
public endpoint: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: 256,
|
||||||
})
|
})
|
||||||
public auth: string;
|
public auth: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public publickey: string;
|
public publickey: string;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public sendReadMessage: boolean;
|
public sendReadMessage: boolean;
|
||||||
|
|
|
@ -2,12 +2,12 @@ import { PrimaryColumn, Entity, Column } from "typeorm";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class UsedUsername {
|
export class UsedUsername {
|
||||||
@PrimaryColumn('varchar', {
|
@PrimaryColumn("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public username: string;
|
public username: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone')
|
@Column("timestamp with time zone")
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
constructor(data: Partial<UsedUsername>) {
|
constructor(data: Partial<UsedUsername>) {
|
||||||
|
|
|
@ -11,25 +11,25 @@ import { UserGroup } from "./user-group.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'userGroupId'], { unique: true })
|
@Index(["userId", "userGroupId"], { unique: true })
|
||||||
export class UserGroupInvitation {
|
export class UserGroupInvitation {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the UserGroupInvitation.',
|
comment: "The created date of the UserGroupInvitation.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The user ID.',
|
comment: "The user ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -37,12 +37,12 @@ export class UserGroupInvitation {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The group ID.',
|
comment: "The group ID.",
|
||||||
})
|
})
|
||||||
public userGroupId: UserGroup["id"];
|
public userGroupId: UserGroup["id"];
|
||||||
|
|
||||||
@ManyToOne(type => UserGroup, {
|
@ManyToOne((type) => UserGroup, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public userGroup: UserGroup | null;
|
public userGroup: UserGroup | null;
|
||||||
|
|
|
@ -11,25 +11,25 @@ import { UserGroup } from "./user-group.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'userGroupId'], { unique: true })
|
@Index(["userId", "userGroupId"], { unique: true })
|
||||||
export class UserGroupJoining {
|
export class UserGroupJoining {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the UserGroupJoining.',
|
comment: "The created date of the UserGroupJoining.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The user ID.',
|
comment: "The user ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -37,12 +37,12 @@ export class UserGroupJoining {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The group ID.',
|
comment: "The group ID.",
|
||||||
})
|
})
|
||||||
public userGroupId: UserGroup["id"];
|
public userGroupId: UserGroup["id"];
|
||||||
|
|
||||||
@ManyToOne(type => UserGroup, {
|
@ManyToOne((type) => UserGroup, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public userGroup: UserGroup | null;
|
public userGroup: UserGroup | null;
|
||||||
|
|
|
@ -15,12 +15,12 @@ export class UserGroup {
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the UserGroup.',
|
comment: "The created date of the UserGroup.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: 256,
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
@ -28,17 +28,17 @@ export class UserGroup {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The ID of owner.',
|
comment: "The ID of owner.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public isPrivate: boolean;
|
public isPrivate: boolean;
|
||||||
|
|
|
@ -12,20 +12,19 @@ import { Note } from "./note.js";
|
||||||
import type { User } from "./user.js";
|
import type { User } from "./user.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'ip'], { unique: true })
|
@Index(["userId", "ip"], { unique: true })
|
||||||
export class UserIp {
|
export class UserIp {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {})
|
||||||
})
|
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public ip: string;
|
public ip: string;
|
||||||
|
|
|
@ -7,18 +7,18 @@ export class UserKeypair {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@OneToOne(type => User, {
|
@OneToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 4096,
|
length: 4096,
|
||||||
})
|
})
|
||||||
public publicKey: string;
|
public publicKey: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 4096,
|
length: 4096,
|
||||||
})
|
})
|
||||||
public privateKey: string;
|
public privateKey: string;
|
||||||
|
|
|
@ -11,25 +11,25 @@ import { UserList } from "./user-list.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'userListId'], { unique: true })
|
@Index(["userId", "userListId"], { unique: true })
|
||||||
export class UserListJoining {
|
export class UserListJoining {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the UserListJoining.',
|
comment: "The created date of the UserListJoining.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The user ID.',
|
comment: "The user ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -37,12 +37,12 @@ export class UserListJoining {
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The list ID.',
|
comment: "The list ID.",
|
||||||
})
|
})
|
||||||
public userListId: UserList["id"];
|
public userListId: UserList["id"];
|
||||||
|
|
||||||
@ManyToOne(type => UserList, {
|
@ManyToOne((type) => UserList, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public userList: UserList | null;
|
public userList: UserList | null;
|
||||||
|
|
|
@ -14,27 +14,27 @@ export class UserList {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the UserList.',
|
comment: "The created date of the UserList.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The owner ID.',
|
comment: "The owner ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
comment: 'The name of the UserList.',
|
comment: "The name of the UserList.",
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ import { User } from "./user.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['userId', 'noteId'], { unique: true })
|
@Index(["userId", "noteId"], { unique: true })
|
||||||
export class UserNotePining {
|
export class UserNotePining {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the UserNotePinings.',
|
comment: "The created date of the UserNotePinings.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ export class UserNotePining {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -34,8 +34,8 @@ export class UserNotePining {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note["id"];
|
public noteId: Note["id"];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne((type) => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public note: Note | null;
|
public note: Note | null;
|
||||||
|
|
|
@ -6,26 +6,26 @@ export class UserPending {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone')
|
@Column("timestamp with time zone")
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public code: string;
|
public code: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public username: string;
|
public username: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public email: string;
|
public email: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
})
|
})
|
||||||
public password: string;
|
public password: string;
|
||||||
|
|
|
@ -18,31 +18,34 @@ export class UserProfile {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@OneToOne(type => User, {
|
@OneToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: 'The location of the User.',
|
nullable: true,
|
||||||
|
comment: "The location of the User.",
|
||||||
})
|
})
|
||||||
public location: string | null;
|
public location: string | null;
|
||||||
|
|
||||||
@Column('char', {
|
@Column("char", {
|
||||||
length: 10, nullable: true,
|
length: 10,
|
||||||
comment: 'The birthday (YYYY-MM-DD) of the User.',
|
nullable: true,
|
||||||
|
comment: "The birthday (YYYY-MM-DD) of the User.",
|
||||||
})
|
})
|
||||||
public birthday: string | null;
|
public birthday: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 2048, nullable: true,
|
length: 2048,
|
||||||
comment: 'The description (bio) of the User.',
|
nullable: true,
|
||||||
|
comment: "The description (bio) of the User.",
|
||||||
})
|
})
|
||||||
public description: string | null;
|
public description: string | null;
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: [],
|
default: [],
|
||||||
})
|
})
|
||||||
public fields: {
|
public fields: {
|
||||||
|
@ -50,136 +53,145 @@ export class UserProfile {
|
||||||
value: string;
|
value: string;
|
||||||
}[];
|
}[];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 32, nullable: true,
|
length: 32,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public lang: string | null;
|
public lang: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'Remote URL of the user.',
|
nullable: true,
|
||||||
|
comment: "Remote URL of the user.",
|
||||||
})
|
})
|
||||||
public url: string | null;
|
public url: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: 'The email address of the User.',
|
nullable: true,
|
||||||
|
comment: "The email address of the User.",
|
||||||
})
|
})
|
||||||
public email: string | null;
|
public email: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public emailVerifyCode: string | null;
|
public emailVerifyCode: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public emailVerified: boolean;
|
public emailVerified: boolean;
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: ['follow', 'receiveFollowRequest', 'groupInvited'],
|
default: ["follow", "receiveFollowRequest", "groupInvited"],
|
||||||
})
|
})
|
||||||
public emailNotificationTypes: string[];
|
public emailNotificationTypes: string[];
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public publicReactions: boolean;
|
public publicReactions: boolean;
|
||||||
|
|
||||||
@Column('enum', {
|
@Column("enum", {
|
||||||
enum: ffVisibility,
|
enum: ffVisibility,
|
||||||
default: 'public',
|
default: "public",
|
||||||
})
|
})
|
||||||
public ffVisibility: typeof ffVisibility[number];
|
public ffVisibility: typeof ffVisibility[number];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public twoFactorTempSecret: string | null;
|
public twoFactorTempSecret: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
public twoFactorSecret: string | null;
|
public twoFactorSecret: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public twoFactorEnabled: boolean;
|
public twoFactorEnabled: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public securityKeysAvailable: boolean;
|
public securityKeysAvailable: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public usePasswordLessLogin: boolean;
|
public usePasswordLessLogin: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: 'The password hash of the User. It will be null if the origin of the user is local.',
|
nullable: true,
|
||||||
|
comment:
|
||||||
|
"The password hash of the User. It will be null if the origin of the user is local.",
|
||||||
})
|
})
|
||||||
public password: string | null;
|
public password: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 8192, default: '',
|
length: 8192,
|
||||||
|
default: "",
|
||||||
})
|
})
|
||||||
public moderationNote: string | null;
|
public moderationNote: string | null;
|
||||||
|
|
||||||
// TODO: そのうち消す
|
// TODO: そのうち消す
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: {},
|
default: {},
|
||||||
comment: 'The client-specific data of the User.',
|
comment: "The client-specific data of the User.",
|
||||||
})
|
})
|
||||||
public clientData: Record<string, any>;
|
public clientData: Record<string, any>;
|
||||||
|
|
||||||
// TODO: そのうち消す
|
// TODO: そのうち消す
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: {},
|
default: {},
|
||||||
comment: 'The room data of the User.',
|
comment: "The room data of the User.",
|
||||||
})
|
})
|
||||||
public room: Record<string, any>;
|
public room: Record<string, any>;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public autoAcceptFollowed: boolean;
|
public autoAcceptFollowed: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether reject index by crawler.',
|
comment: "Whether reject index by crawler.",
|
||||||
})
|
})
|
||||||
public noCrawle: boolean;
|
public noCrawle: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public preventAiLearning: boolean;
|
public preventAiLearning: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public alwaysMarkNsfw: boolean;
|
public alwaysMarkNsfw: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public autoSensitive: boolean;
|
public autoSensitive: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public carefulBot: boolean;
|
public carefulBot: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public injectFeaturedNote: boolean;
|
public injectFeaturedNote: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public receiveAnnouncementEmail: boolean;
|
public receiveAnnouncementEmail: boolean;
|
||||||
|
@ -190,35 +202,36 @@ export class UserProfile {
|
||||||
})
|
})
|
||||||
public pinnedPageId: Page["id"] | null;
|
public pinnedPageId: Page["id"] | null;
|
||||||
|
|
||||||
@OneToOne(type => Page, {
|
@OneToOne((type) => Page, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public pinnedPage: Page | null;
|
public pinnedPage: Page | null;
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: {},
|
default: {},
|
||||||
})
|
})
|
||||||
public integrations: Record<string, any>;
|
public integrations: Record<string, any>;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false, select: false,
|
default: false,
|
||||||
|
select: false,
|
||||||
})
|
})
|
||||||
public enableWordMute: boolean;
|
public enableWordMute: boolean;
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: [],
|
default: [],
|
||||||
})
|
})
|
||||||
public mutedWords: string[][];
|
public mutedWords: string[][];
|
||||||
|
|
||||||
@Column('jsonb', {
|
@Column("jsonb", {
|
||||||
default: [],
|
default: [],
|
||||||
comment: 'List of instances muted by the user.',
|
comment: "List of instances muted by the user.",
|
||||||
})
|
})
|
||||||
public mutedInstances: string[];
|
public mutedInstances: string[];
|
||||||
|
|
||||||
@Column('enum', {
|
@Column("enum", {
|
||||||
enum: notificationTypes,
|
enum: notificationTypes,
|
||||||
array: true,
|
array: true,
|
||||||
default: [],
|
default: [],
|
||||||
|
@ -227,9 +240,10 @@ export class UserProfile {
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: '[Denormalized]',
|
nullable: true,
|
||||||
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public userHost: string | null;
|
public userHost: string | null;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -14,19 +14,19 @@ export class UserPublickey {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@OneToOne(type => User, {
|
@OneToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: 256,
|
||||||
})
|
})
|
||||||
public keyId: string;
|
public keyId: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 4096,
|
length: 4096,
|
||||||
})
|
})
|
||||||
public keyPem: string;
|
public keyPem: string;
|
||||||
|
|
|
@ -11,8 +11,8 @@ import { id } from "../id.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class UserSecurityKey {
|
export class UserSecurityKey {
|
||||||
@PrimaryColumn('varchar', {
|
@PrimaryColumn("varchar", {
|
||||||
comment: 'Variable-length id given to navigator.credentials.get()',
|
comment: "Variable-length id given to navigator.credentials.get()",
|
||||||
})
|
})
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
|
@ -20,27 +20,27 @@ export class UserSecurityKey {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
comment:
|
comment:
|
||||||
'Variable-length public key used to verify attestations (hex-encoded).',
|
"Variable-length public key used to verify attestations (hex-encoded).",
|
||||||
})
|
})
|
||||||
public publicKey: string;
|
public publicKey: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment:
|
comment:
|
||||||
'The date of the last time the UserSecurityKey was successfully validated.',
|
"The date of the last time the UserSecurityKey was successfully validated.",
|
||||||
})
|
})
|
||||||
public lastUsed: Date;
|
public lastUsed: Date;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
comment: 'User-defined name for this key',
|
comment: "User-defined name for this key",
|
||||||
length: 30,
|
length: 30,
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
|
@ -10,99 +10,101 @@ import { id } from "../id.js";
|
||||||
import { DriveFile } from "./drive-file.js";
|
import { DriveFile } from "./drive-file.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(['usernameLower', 'host'], { unique: true })
|
@Index(["usernameLower", "host"], { unique: true })
|
||||||
export class User {
|
export class User {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the User.',
|
comment: "The created date of the User.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The updated date of the User.',
|
comment: "The updated date of the User.",
|
||||||
})
|
})
|
||||||
public updatedAt: Date | null;
|
public updatedAt: Date | null;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public lastFetchedAt: Date | null;
|
public lastFetchedAt: Date | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public lastActiveDate: Date | null;
|
public lastActiveDate: Date | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public hideOnlineStatus: boolean;
|
public hideOnlineStatus: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
comment: 'The username of the User.',
|
comment: "The username of the User.",
|
||||||
})
|
})
|
||||||
public username: string;
|
public username: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, select: false,
|
length: 128,
|
||||||
comment: 'The username (lowercased) of the User.',
|
select: false,
|
||||||
|
comment: "The username (lowercased) of the User.",
|
||||||
})
|
})
|
||||||
public usernameLower: string;
|
public usernameLower: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: 'The name of the User.',
|
nullable: true,
|
||||||
|
comment: "The name of the User.",
|
||||||
})
|
})
|
||||||
public name: string | null;
|
public name: string | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
comment: 'The count of followers.',
|
comment: "The count of followers.",
|
||||||
})
|
})
|
||||||
public followersCount: number;
|
public followersCount: number;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
comment: 'The count of following.',
|
comment: "The count of following.",
|
||||||
})
|
})
|
||||||
public followingCount: number;
|
public followingCount: number;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The URI of the new account of the User',
|
comment: "The URI of the new account of the User",
|
||||||
})
|
})
|
||||||
public movedToUri: string | null;
|
public movedToUri: string | null;
|
||||||
|
|
||||||
@Column('simple-array', {
|
@Column("simple-array", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'URIs the user is known as too',
|
comment: "URIs the user is known as too",
|
||||||
})
|
})
|
||||||
public alsoKnownAs: string[] | null;
|
public alsoKnownAs: string[] | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
default: 0,
|
default: 0,
|
||||||
comment: 'The count of notes.',
|
comment: "The count of notes.",
|
||||||
})
|
})
|
||||||
public notesCount: number;
|
public notesCount: number;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The ID of avatar DriveFile.',
|
comment: "The ID of avatar DriveFile.",
|
||||||
})
|
})
|
||||||
public avatarId: DriveFile["id"] | null;
|
public avatarId: DriveFile["id"] | null;
|
||||||
|
|
||||||
@OneToOne(type => DriveFile, {
|
@OneToOne((type) => DriveFile, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public avatar: DriveFile | null;
|
public avatar: DriveFile | null;
|
||||||
|
@ -110,143 +112,162 @@ export class User {
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'The ID of banner DriveFile.',
|
comment: "The ID of banner DriveFile.",
|
||||||
})
|
})
|
||||||
public bannerId: DriveFile["id"] | null;
|
public bannerId: DriveFile["id"] | null;
|
||||||
|
|
||||||
@OneToOne(type => DriveFile, {
|
@OneToOne((type) => DriveFile, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public banner: DriveFile | null;
|
public banner: DriveFile | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, array: true, default: '{}',
|
length: 128,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public tags: string[];
|
public tags: string[];
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the User is suspended.',
|
comment: "Whether the User is suspended.",
|
||||||
})
|
})
|
||||||
public isSuspended: boolean;
|
public isSuspended: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the User is silenced.',
|
comment: "Whether the User is silenced.",
|
||||||
})
|
})
|
||||||
public isSilenced: boolean;
|
public isSilenced: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the User is locked.',
|
comment: "Whether the User is locked.",
|
||||||
})
|
})
|
||||||
public isLocked: boolean;
|
public isLocked: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the User is a bot.',
|
comment: "Whether the User is a bot.",
|
||||||
})
|
})
|
||||||
public isBot: boolean;
|
public isBot: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the User is a cat.',
|
comment: "Whether the User is a cat.",
|
||||||
})
|
})
|
||||||
public isCat: boolean;
|
public isCat: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
comment: 'Whether to speak as a cat if isCat.',
|
comment: "Whether to speak as a cat if isCat.",
|
||||||
})
|
})
|
||||||
public speakAsCat: boolean;
|
public speakAsCat: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the User is the admin.',
|
comment: "Whether the User is the admin.",
|
||||||
})
|
})
|
||||||
public isAdmin: boolean;
|
public isAdmin: boolean;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the User is a moderator.',
|
comment: "Whether the User is a moderator.",
|
||||||
})
|
})
|
||||||
public isModerator: boolean;
|
public isModerator: boolean;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
comment: 'Whether the User is explorable.',
|
comment: "Whether the User is explorable.",
|
||||||
})
|
})
|
||||||
public isExplorable: boolean;
|
public isExplorable: boolean;
|
||||||
|
|
||||||
// アカウントが削除されたかどうかのフラグだが、完全に削除される際は物理削除なので実質削除されるまでの「削除が進行しているかどうか」のフラグ
|
// アカウントが削除されたかどうかのフラグだが、完全に削除される際は物理削除なので実質削除されるまでの「削除が進行しているかどうか」のフラグ
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether the User is deleted.',
|
comment: "Whether the User is deleted.",
|
||||||
})
|
})
|
||||||
public isDeleted: boolean;
|
public isDeleted: boolean;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, array: true, default: '{}',
|
length: 128,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public emojis: string[];
|
public emojis: string[];
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, nullable: true,
|
length: 128,
|
||||||
comment: 'The host of the User. It will be null if the origin of the user is local.',
|
nullable: true,
|
||||||
|
comment:
|
||||||
|
"The host of the User. It will be null if the origin of the user is local.",
|
||||||
})
|
})
|
||||||
public host: string | null;
|
public host: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The inbox URL of the User. It will be null if the origin of the user is local.',
|
nullable: true,
|
||||||
|
comment:
|
||||||
|
"The inbox URL of the User. It will be null if the origin of the user is local.",
|
||||||
})
|
})
|
||||||
public inbox: string | null;
|
public inbox: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The sharedInbox URL of the User. It will be null if the origin of the user is local.',
|
nullable: true,
|
||||||
|
comment:
|
||||||
|
"The sharedInbox URL of the User. It will be null if the origin of the user is local.",
|
||||||
})
|
})
|
||||||
public sharedInbox: string | null;
|
public sharedInbox: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The featured URL of the User. It will be null if the origin of the user is local.',
|
nullable: true,
|
||||||
|
comment:
|
||||||
|
"The featured URL of the User. It will be null if the origin of the user is local.",
|
||||||
})
|
})
|
||||||
public featured: string | null;
|
public featured: string | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The URI of the User. It will be null if the origin of the user is local.',
|
nullable: true,
|
||||||
|
comment:
|
||||||
|
"The URI of the User. It will be null if the origin of the user is local.",
|
||||||
})
|
})
|
||||||
public uri: string | null;
|
public uri: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 512, nullable: true,
|
length: 512,
|
||||||
comment: 'The URI of the user Follower Collection. It will be null if the origin of the user is local.',
|
nullable: true,
|
||||||
|
comment:
|
||||||
|
"The URI of the user Follower Collection. It will be null if the origin of the user is local.",
|
||||||
})
|
})
|
||||||
public followersUri: string | null;
|
public followersUri: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
comment: 'Whether to show users replying to other users in the timeline.',
|
comment: "Whether to show users replying to other users in the timeline.",
|
||||||
})
|
})
|
||||||
public showTimelineReplies: boolean;
|
public showTimelineReplies: boolean;
|
||||||
|
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column('char', {
|
@Column("char", {
|
||||||
length: 16, nullable: true, unique: true,
|
length: 16,
|
||||||
comment: 'The native access token of the User. It will be null if the origin of the user is local.',
|
nullable: true,
|
||||||
|
unique: true,
|
||||||
|
comment:
|
||||||
|
"The native access token of the User. It will be null if the origin of the user is local.",
|
||||||
})
|
})
|
||||||
public token: string | null;
|
public token: string | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: 'Overrides user drive capacity limit',
|
comment: "Overrides user drive capacity limit",
|
||||||
})
|
})
|
||||||
public driveCapacityOverrideMb: number | null;
|
public driveCapacityOverrideMb: number | null;
|
||||||
|
|
||||||
|
|
|
@ -25,48 +25,50 @@ export class Webhook {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
comment: 'The created date of the Antenna.',
|
comment: "The created date of the Antenna.",
|
||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
comment: 'The owner ID.',
|
comment: "The owner ID.",
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne((type) => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
comment: 'The name of the Antenna.',
|
comment: "The name of the Antenna.",
|
||||||
})
|
})
|
||||||
public name: string;
|
public name: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 128, array: true, default: '{}',
|
length: 128,
|
||||||
|
array: true,
|
||||||
|
default: "{}",
|
||||||
})
|
})
|
||||||
public on: typeof webhookEventTypes[number][];
|
public on: typeof webhookEventTypes[number][];
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024,
|
length: 1024,
|
||||||
})
|
})
|
||||||
public url: string;
|
public url: string;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column("varchar", {
|
||||||
length: 1024,
|
length: 1024,
|
||||||
})
|
})
|
||||||
public secret: string;
|
public secret: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('boolean', {
|
@Column("boolean", {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public active: boolean;
|
public active: boolean;
|
||||||
|
@ -74,7 +76,7 @@ export class Webhook {
|
||||||
/**
|
/**
|
||||||
* 直近のリクエスト送信日時
|
* 直近のリクエスト送信日時
|
||||||
*/
|
*/
|
||||||
@Column('timestamp with time zone', {
|
@Column("timestamp with time zone", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public latestSentAt: Date | null;
|
public latestSentAt: Date | null;
|
||||||
|
@ -82,7 +84,7 @@ export class Webhook {
|
||||||
/**
|
/**
|
||||||
* 直近のリクエスト送信時のHTTPステータスコード
|
* 直近のリクエスト送信時のHTTPステータスコード
|
||||||
*/
|
*/
|
||||||
@Column('integer', {
|
@Column("integer", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public latestStatus: number | null;
|
public latestStatus: number | null;
|
||||||
|
|
|
@ -257,7 +257,9 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
|
|
||||||
async getHasUnreadAntenna(userId: User["id"]): Promise<boolean> {
|
async getHasUnreadAntenna(userId: User["id"]): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const myAntennas = (await getAntennas()).filter((a) => a.userId === userId);
|
const myAntennas = (await getAntennas()).filter(
|
||||||
|
(a) => a.userId === userId,
|
||||||
|
);
|
||||||
|
|
||||||
const unread =
|
const unread =
|
||||||
myAntennas.length > 0
|
myAntennas.length > 0
|
||||||
|
@ -267,7 +269,10 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return unread != null; } catch(e) { return false; }
|
return unread != null;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async getHasUnreadChannel(userId: User["id"]): Promise<boolean> {
|
async getHasUnreadChannel(userId: User["id"]): Promise<boolean> {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { Notes } from "@/models/index.js";
|
||||||
import { MoreThan } from "typeorm";
|
import { MoreThan } from "typeorm";
|
||||||
import { index } from "@/services/note/create.js";
|
import { index } from "@/services/note/create.js";
|
||||||
import { Note } from "@/models/entities/note.js";
|
import { Note } from "@/models/entities/note.js";
|
||||||
|
import meilisearch from "../../../db/meilisearch.js";
|
||||||
|
|
||||||
const logger = queueLogger.createSubLogger("index-all-notes");
|
const logger = queueLogger.createSubLogger("index-all-notes");
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ export default async function indexAllNotes(
|
||||||
order: {
|
order: {
|
||||||
id: 1,
|
id: 1,
|
||||||
},
|
},
|
||||||
|
relations: ["user"],
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(`Failed to query notes ${e}`);
|
logger.error(`Failed to query notes ${e}`);
|
||||||
|
@ -58,7 +60,12 @@ export default async function indexAllNotes(
|
||||||
|
|
||||||
for (let i = 0; i < notes.length; i += batch) {
|
for (let i = 0; i < notes.length; i += batch) {
|
||||||
const chunk = notes.slice(i, i + batch);
|
const chunk = notes.slice(i, i + batch);
|
||||||
await Promise.all(chunk.map((note) => index(note)));
|
|
||||||
|
if (meilisearch) {
|
||||||
|
await meilisearch.ingestNote(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(chunk.map((note) => index(note, true)));
|
||||||
|
|
||||||
indexedCount += chunk.length;
|
indexedCount += chunk.length;
|
||||||
const pct = (indexedCount / total) * 100;
|
const pct = (indexedCount / total) * 100;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
import { MoreThan } from "typeorm";
|
import { MoreThan } from "typeorm";
|
||||||
import { deleteFileSync } from "@/services/drive/delete-file.js";
|
import { deleteFileSync } from "@/services/drive/delete-file.js";
|
||||||
import { sendEmail } from "@/services/send-email.js";
|
import { sendEmail } from "@/services/send-email.js";
|
||||||
|
import meilisearch from "@/db/meilisearch.js";
|
||||||
|
|
||||||
const logger = queueLogger.createSubLogger("delete-account");
|
const logger = queueLogger.createSubLogger("delete-account");
|
||||||
|
|
||||||
|
@ -43,6 +44,9 @@ export async function deleteAccount(
|
||||||
cursor = notes[notes.length - 1].id;
|
cursor = notes[notes.length - 1].id;
|
||||||
|
|
||||||
await Notes.delete(notes.map((note) => note.id));
|
await Notes.delete(notes.map((note) => note.id));
|
||||||
|
if (meilisearch) {
|
||||||
|
await meilisearch.deleteNotes(notes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.succ("All of notes deleted");
|
logger.succ("All of notes deleted");
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { Note } from "@/models/entities/note.js";
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import es from "../../../../db/elasticsearch.js";
|
import es from "../../../../db/elasticsearch.js";
|
||||||
import sonic from "../../../../db/sonic.js";
|
import sonic from "../../../../db/sonic.js";
|
||||||
|
import meilisearch, { MeilisearchNote } from "../../../../db/meilisearch.js";
|
||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
||||||
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js";
|
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js";
|
||||||
|
@ -62,7 +63,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, me) => {
|
export default define(meta, paramDef, async (ps, me) => {
|
||||||
if (es == null && sonic == null) {
|
if (es == null && sonic == null && meilisearch == null) {
|
||||||
const query = makePaginationQuery(
|
const query = makePaginationQuery(
|
||||||
Notes.createQueryBuilder("note"),
|
Notes.createQueryBuilder("note"),
|
||||||
ps.sinceId,
|
ps.sinceId,
|
||||||
|
@ -170,6 +171,70 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
found.length = ps.limit;
|
found.length = ps.limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
} else if (meilisearch) {
|
||||||
|
let start = 0;
|
||||||
|
const chunkSize = 100;
|
||||||
|
|
||||||
|
// Use meilisearch to fetch and step through all search results that could match the requirements
|
||||||
|
const ids = [];
|
||||||
|
while (true) {
|
||||||
|
const results = await meilisearch.search(ps.query, chunkSize, start, me);
|
||||||
|
|
||||||
|
start += chunkSize;
|
||||||
|
|
||||||
|
if (results.hits.length === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = results.hits
|
||||||
|
.filter((key: MeilisearchNote) => {
|
||||||
|
if (ps.userId && key.userId !== ps.userId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ps.channelId && key.channelId !== ps.channelId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ps.sinceId && key.id <= ps.sinceId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ps.untilId && key.id >= ps.untilId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.map((key) => key.id);
|
||||||
|
|
||||||
|
ids.push(...res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort all the results by note id DESC (newest first)
|
||||||
|
ids.sort((a, b) => b - a);
|
||||||
|
|
||||||
|
// Fetch the notes from the database until we have enough to satisfy the limit
|
||||||
|
start = 0;
|
||||||
|
const found = [];
|
||||||
|
while (found.length < ps.limit && start < ids.length) {
|
||||||
|
const chunk = ids.slice(start, start + chunkSize);
|
||||||
|
const notes: Note[] = await Notes.find({
|
||||||
|
where: {
|
||||||
|
id: In(chunk),
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
id: "DESC",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// The notes are checked for visibility and muted/blocked users when packed
|
||||||
|
found.push(...(await Notes.packMany(notes, me)));
|
||||||
|
start += chunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have more results than the limit, trim them
|
||||||
|
if (found.length > ps.limit) {
|
||||||
|
found.length = ps.limit;
|
||||||
|
}
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
} else {
|
} else {
|
||||||
const userQuery =
|
const userQuery =
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import * as os from "node:os";
|
import * as os from "node:os";
|
||||||
import si from "systeminformation";
|
import si from "systeminformation";
|
||||||
import define from "../define.js";
|
import define from "../define.js";
|
||||||
|
import meilisearch from "../../../db/meilisearch.js";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: false,
|
requireCredential: false,
|
||||||
|
@ -18,6 +19,7 @@ export const paramDef = {
|
||||||
export default define(meta, paramDef, async () => {
|
export default define(meta, paramDef, async () => {
|
||||||
const memStats = await si.mem();
|
const memStats = await si.mem();
|
||||||
const fsStats = await si.fsSize();
|
const fsStats = await si.fsSize();
|
||||||
|
const meilisearchStats = await meilisearchStatus();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
machine: os.hostname(),
|
machine: os.hostname(),
|
||||||
|
@ -34,3 +36,15 @@ export default define(meta, paramDef, async () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function meilisearchStatus() {
|
||||||
|
if (meilisearch) {
|
||||||
|
return meilisearch.serverStats();
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
health: "unconfigured",
|
||||||
|
size: 0,
|
||||||
|
indexed_count: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
"url": "url"
|
"url": "url"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"screenshots" : [
|
"screenshots": [
|
||||||
{
|
{
|
||||||
"src": "/static-assets/screenshots/1.webp",
|
"src": "/static-assets/screenshots/1.webp",
|
||||||
"sizes": "1195x579",
|
"sizes": "1195x579",
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
"label": "Posts"
|
"label": "Posts"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"shortcuts" : [
|
"shortcuts": [
|
||||||
{
|
{
|
||||||
"name": "Notifications",
|
"name": "Notifications",
|
||||||
"short_name": "Notifs",
|
"short_name": "Notifs",
|
||||||
|
@ -68,7 +68,5 @@
|
||||||
"url": "/my/messaging"
|
"url": "/my/messaging"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": ["social"]
|
||||||
"social"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ import type { UserProfile } from "@/models/entities/user-profile.js";
|
||||||
import { db } from "@/db/postgre.js";
|
import { db } from "@/db/postgre.js";
|
||||||
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
||||||
import { shouldSilenceInstance } from "@/misc/should-block-instance.js";
|
import { shouldSilenceInstance } from "@/misc/should-block-instance.js";
|
||||||
|
import meilisearch from "../../db/meilisearch.js";
|
||||||
|
|
||||||
const mutedWordsCache = new Cache<
|
const mutedWordsCache = new Cache<
|
||||||
{ userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[]
|
{ userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[]
|
||||||
|
@ -748,7 +749,7 @@ async function insertNote(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function index(note: Note): Promise<void> {
|
export async function index(note: Note, reindexing: boolean): Promise<void> {
|
||||||
if (!note.text) return;
|
if (!note.text) return;
|
||||||
|
|
||||||
if (config.elasticsearch && es) {
|
if (config.elasticsearch && es) {
|
||||||
|
@ -776,6 +777,10 @@ export async function index(note: Note): Promise<void> {
|
||||||
note.text,
|
note.text,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (meilisearch && !reindexing) {
|
||||||
|
await meilisearch.ingestNote(note);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function notifyToWatchersOfRenotee(
|
async function notifyToWatchersOfRenotee(
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
import { countSameRenotes } from "@/misc/count-same-renotes.js";
|
import { countSameRenotes } from "@/misc/count-same-renotes.js";
|
||||||
import { registerOrFetchInstanceDoc } from "../register-or-fetch-instance-doc.js";
|
import { registerOrFetchInstanceDoc } from "../register-or-fetch-instance-doc.js";
|
||||||
import { deliverToRelays } from "../relay.js";
|
import { deliverToRelays } from "../relay.js";
|
||||||
|
import meilisearch from "@/db/meilisearch.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 投稿を削除します。
|
* 投稿を削除します。
|
||||||
|
@ -119,6 +120,10 @@ export default async function (
|
||||||
id: note.id,
|
id: note.id,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(meilisearch) {
|
||||||
|
await meilisearch.deleteNotes(note.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findCascadingNotes(note: Note) {
|
async function findCascadingNotes(note: Note) {
|
||||||
|
|
|
@ -34,9 +34,7 @@
|
||||||
"tsd": "^0.19.1",
|
"tsd": "^0.19.1",
|
||||||
"typescript": "4.5.4"
|
"typescript": "4.5.4"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": ["built"],
|
||||||
"built"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"autobind-decorator": "^2.4.0",
|
"autobind-decorator": "^2.4.0",
|
||||||
"eventemitter3": "^4.0.7",
|
"eventemitter3": "^4.0.7",
|
||||||
|
|
|
@ -15,11 +15,6 @@
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"esModuleInterop": true
|
"esModuleInterop": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src/**/*"],
|
||||||
"src/**/*"
|
"exclude": ["node_modules", "test/**/*"]
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules",
|
|
||||||
"test/**/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
"typescript": "4.9.4",
|
"typescript": "4.9.4",
|
||||||
"uuid": "9.0.0",
|
"uuid": "9.0.0",
|
||||||
"vanilla-tilt": "1.8.0",
|
"vanilla-tilt": "1.8.0",
|
||||||
"vite": "^4.1.1",
|
"vite": "4.3.9",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vue": "3.2.45",
|
"vue": "3.2.45",
|
||||||
"vue-isyourpasswordsafe": "^2.0.0",
|
"vue-isyourpasswordsafe": "^2.0.0",
|
||||||
|
|
|
@ -91,7 +91,7 @@ watch(
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
background: rgba(0,0,0,0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
|
||||||
> .wrapper {
|
> .wrapper {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
|
|
|
@ -11,10 +11,7 @@
|
||||||
:data-count="previewableCount < 5 ? previewableCount : null"
|
:data-count="previewableCount < 5 ? previewableCount : null"
|
||||||
:class="{ dmWidth: inDm }"
|
:class="{ dmWidth: inDm }"
|
||||||
>
|
>
|
||||||
<div
|
<div ref="gallery" @click.stop>
|
||||||
ref="gallery"
|
|
||||||
@click.stop
|
|
||||||
>
|
|
||||||
<template
|
<template
|
||||||
v-for="media in mediaList.filter((media) =>
|
v-for="media in mediaList.filter((media) =>
|
||||||
previewable(media)
|
previewable(media)
|
||||||
|
@ -189,7 +186,9 @@ const previewable = (file: misskey.entities.DriveFile): boolean => {
|
||||||
FILE_TYPE_BROWSERSAFE.includes(file.type)
|
FILE_TYPE_BROWSERSAFE.includes(file.type)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const previewableCount = props.mediaList.filter((media) => previewable(media)).length;
|
const previewableCount = props.mediaList.filter((media) =>
|
||||||
|
previewable(media)
|
||||||
|
).length;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -251,14 +250,14 @@ const previewableCount = props.mediaList.filter((media) => previewable(media)).l
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-gap: 8px;
|
grid-gap: 8px;
|
||||||
|
|
||||||
> div, > button {
|
> div,
|
||||||
|
> button {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
> :nth-child(1) {
|
> :nth-child(1) {
|
||||||
grid-column: 1 / 2;
|
grid-column: 1 / 2;
|
||||||
grid-row: 1 / 2;
|
grid-row: 1 / 2;
|
||||||
|
|
|
@ -75,11 +75,11 @@ const hide = ref(
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
mini.value = plyr.value.player.media.scrollWidth < 300;
|
mini.value = plyr.value.player.media.scrollWidth < 300;
|
||||||
if (mini.value) {
|
if (mini.value) {
|
||||||
plyr.value.player.on('play', () => {
|
plyr.value.player.on("play", () => {
|
||||||
plyr.value.player.fullscreen.enter();
|
plyr.value.player.fullscreen.enter();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
:note="note"
|
:note="note"
|
||||||
:detailedView="true"
|
:detailedView="true"
|
||||||
/>
|
/>
|
||||||
<MkLoading v-else-if="appearNote.reply" mini />
|
<MkLoading v-else-if="note.reply" mini />
|
||||||
<MkNoteSub
|
<MkNoteSub
|
||||||
v-if="appearNote.reply"
|
v-if="note.reply"
|
||||||
:note="appearNote.reply"
|
:note="note.reply"
|
||||||
class="reply-to"
|
class="reply-to"
|
||||||
:detailedView="true"
|
:detailedView="true"
|
||||||
/>
|
/>
|
||||||
|
@ -29,21 +29,21 @@
|
||||||
ref="noteEl"
|
ref="noteEl"
|
||||||
@contextmenu.stop="onContextmenu"
|
@contextmenu.stop="onContextmenu"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
:note="appearNote"
|
:note="note"
|
||||||
detailedView
|
detailedView
|
||||||
></MkNote>
|
></MkNote>
|
||||||
|
|
||||||
<MkTab v-model="tab" :style="'underline'" @update:modelValue="loadTab">
|
<MkTab v-model="tab" :style="'underline'" @update:modelValue="loadTab">
|
||||||
<option value="replies">
|
<option value="replies">
|
||||||
<!-- <i class="ph-arrow-u-up-left ph-bold ph-lg"></i> -->
|
<!-- <i class="ph-arrow-u-up-left ph-bold ph-lg"></i> -->
|
||||||
<span v-if="appearNote.repliesCount > 0" class="count">{{
|
<span v-if="note.repliesCount > 0" class="count">{{
|
||||||
appearNote.repliesCount
|
note.repliesCount
|
||||||
}}</span>
|
}}</span>
|
||||||
{{ i18n.ts._notification._types.reply }}
|
{{ i18n.ts._notification._types.reply }}
|
||||||
</option>
|
</option>
|
||||||
<option value="renotes" v-if="appearNote.renoteCount > 0">
|
<option value="renotes" v-if="note.renoteCount > 0">
|
||||||
<!-- <i class="ph-repeat ph-bold ph-lg"></i> -->
|
<!-- <i class="ph-repeat ph-bold ph-lg"></i> -->
|
||||||
<span class="count">{{ appearNote.renoteCount }}</span>
|
<span class="count">{{ note.renoteCount }}</span>
|
||||||
{{ i18n.ts._notification._types.renote }}
|
{{ i18n.ts._notification._types.renote }}
|
||||||
</option>
|
</option>
|
||||||
<option value="reactions" v-if="reactionsCount > 0">
|
<option value="reactions" v-if="reactionsCount > 0">
|
||||||
|
@ -71,11 +71,9 @@
|
||||||
class="reply"
|
class="reply"
|
||||||
:conversation="replies"
|
:conversation="replies"
|
||||||
:detailedView="true"
|
:detailedView="true"
|
||||||
:parentId="appearNote.id"
|
:parentId="note.id"
|
||||||
/>
|
|
||||||
<MkLoading
|
|
||||||
v-else-if="tab === 'replies' && appearNote.repliesCount > 0"
|
|
||||||
/>
|
/>
|
||||||
|
<MkLoading v-else-if="tab === 'replies' && note.repliesCount > 0" />
|
||||||
|
|
||||||
<MkNoteSub
|
<MkNoteSub
|
||||||
v-if="directQuotes && tab === 'quotes'"
|
v-if="directQuotes && tab === 'quotes'"
|
||||||
|
@ -85,7 +83,7 @@
|
||||||
class="reply"
|
class="reply"
|
||||||
:conversation="replies"
|
:conversation="replies"
|
||||||
:detailedView="true"
|
:detailedView="true"
|
||||||
:parentId="appearNote.id"
|
:parentId="note.id"
|
||||||
/>
|
/>
|
||||||
<MkLoading v-else-if="tab === 'quotes' && directQuotes.length > 0" />
|
<MkLoading v-else-if="tab === 'quotes' && directQuotes.length > 0" />
|
||||||
|
|
||||||
|
@ -103,9 +101,7 @@
|
||||||
:with-chart="false"
|
:with-chart="false"
|
||||||
/>
|
/>
|
||||||
<!-- </MkPagination> -->
|
<!-- </MkPagination> -->
|
||||||
<MkLoading
|
<MkLoading v-else-if="tab === 'renotes' && note.renoteCount > 0" />
|
||||||
v-else-if="tab === 'renotes' && appearNote.renoteCount > 0"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div v-if="tab === 'clips' && clips.length > 0" class="_content clips">
|
<div v-if="tab === 'clips' && clips.length > 0" class="_content clips">
|
||||||
<MkA
|
<MkA
|
||||||
|
@ -132,7 +128,7 @@
|
||||||
|
|
||||||
<MkReactedUsers
|
<MkReactedUsers
|
||||||
v-if="tab === 'reactions' && reactionsCount > 0"
|
v-if="tab === 'reactions' && reactionsCount > 0"
|
||||||
:note-id="appearNote.id"
|
:note-id="note.id"
|
||||||
></MkReactedUsers>
|
></MkReactedUsers>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="_panel muted" @click="muted.muted = false">
|
<div v-else class="_panel muted" @click="muted.muted = false">
|
||||||
|
@ -217,23 +213,11 @@ if (noteViewInterruptors.length > 0) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const isRenote =
|
|
||||||
note.renote != null &&
|
|
||||||
note.text == null &&
|
|
||||||
note.fileIds.length === 0 &&
|
|
||||||
note.poll == null;
|
|
||||||
|
|
||||||
const el = ref<HTMLElement>();
|
const el = ref<HTMLElement>();
|
||||||
const noteEl = $ref();
|
const noteEl = $ref();
|
||||||
const menuButton = ref<HTMLElement>();
|
const menuButton = ref<HTMLElement>();
|
||||||
const starButton = ref<InstanceType<typeof XStarButton>>();
|
|
||||||
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
|
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
|
||||||
const renoteTime = ref<HTMLElement>();
|
|
||||||
const reactButton = ref<HTMLElement>();
|
const reactButton = ref<HTMLElement>();
|
||||||
let appearNote = $computed(() =>
|
|
||||||
isRenote ? (note.renote as misskey.entities.Note) : note
|
|
||||||
);
|
|
||||||
const isMyRenote = $i && $i.id === note.userId;
|
|
||||||
const showContent = ref(false);
|
const showContent = ref(false);
|
||||||
const isDeleted = ref(false);
|
const isDeleted = ref(false);
|
||||||
const muted = ref(getWordSoftMute(note, $i, defaultStore.state.mutedWords));
|
const muted = ref(getWordSoftMute(note, $i, defaultStore.state.mutedWords));
|
||||||
|
@ -263,14 +247,14 @@ const keymap = {
|
||||||
|
|
||||||
useNoteCapture({
|
useNoteCapture({
|
||||||
rootEl: el,
|
rootEl: el,
|
||||||
note: $$(appearNote),
|
note: $$(note),
|
||||||
isDeletedRef: isDeleted,
|
isDeletedRef: isDeleted,
|
||||||
});
|
});
|
||||||
|
|
||||||
function reply(viaKeyboard = false): void {
|
function reply(viaKeyboard = false): void {
|
||||||
pleaseLogin();
|
pleaseLogin();
|
||||||
os.post({
|
os.post({
|
||||||
reply: appearNote,
|
reply: note,
|
||||||
animation: !viaKeyboard,
|
animation: !viaKeyboard,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
focus();
|
focus();
|
||||||
|
@ -284,7 +268,7 @@ function react(viaKeyboard = false): void {
|
||||||
reactButton.value,
|
reactButton.value,
|
||||||
(reaction) => {
|
(reaction) => {
|
||||||
os.api("notes/reactions/create", {
|
os.api("notes/reactions/create", {
|
||||||
noteId: appearNote.id,
|
noteId: note.id,
|
||||||
reaction: reaction,
|
reaction: reaction,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -355,27 +339,27 @@ function blur() {
|
||||||
|
|
||||||
directReplies = null;
|
directReplies = null;
|
||||||
os.api("notes/children", {
|
os.api("notes/children", {
|
||||||
noteId: appearNote.id,
|
noteId: note.id,
|
||||||
limit: 30,
|
limit: 30,
|
||||||
depth: 12,
|
depth: 12,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
res = res.reduce((acc, note) => {
|
res = res.reduce((acc, resNote) => {
|
||||||
if (note.userId == appearNote.userId) {
|
if (resNote.userId == note.userId) {
|
||||||
return [...acc, note];
|
return [...acc, resNote];
|
||||||
}
|
}
|
||||||
return [note, ...acc];
|
return [resNote, ...acc];
|
||||||
}, []);
|
}, []);
|
||||||
replies.value = res;
|
replies.value = res;
|
||||||
directReplies = res
|
directReplies = res
|
||||||
.filter((note) => note.replyId === appearNote.id)
|
.filter((resNote) => resNote.replyId === note.id)
|
||||||
.reverse();
|
.reverse();
|
||||||
directQuotes = res.filter((note) => note.renoteId === appearNote.id);
|
directQuotes = res.filter((resNote) => resNote.renoteId === note.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
conversation = null;
|
conversation = null;
|
||||||
if (appearNote.replyId) {
|
if (note.replyId) {
|
||||||
os.api("notes/conversation", {
|
os.api("notes/conversation", {
|
||||||
noteId: appearNote.replyId,
|
noteId: note.replyId,
|
||||||
limit: 30,
|
limit: 30,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
conversation = res.reverse();
|
conversation = res.reverse();
|
||||||
|
@ -385,14 +369,14 @@ if (appearNote.replyId) {
|
||||||
|
|
||||||
clips = null;
|
clips = null;
|
||||||
os.api("notes/clips", {
|
os.api("notes/clips", {
|
||||||
noteId: appearNote.id,
|
noteId: note.id,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
clips = res;
|
clips = res;
|
||||||
});
|
});
|
||||||
|
|
||||||
// const pagination = {
|
// const pagination = {
|
||||||
// endpoint: "notes/renotes",
|
// endpoint: "notes/renotes",
|
||||||
// noteId: appearNote.id,
|
// noteId: note.id,
|
||||||
// limit: 10,
|
// limit: 10,
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
@ -402,7 +386,7 @@ renotes = null;
|
||||||
function loadTab() {
|
function loadTab() {
|
||||||
if (tab === "renotes" && !renotes) {
|
if (tab === "renotes" && !renotes) {
|
||||||
os.api("notes/renotes", {
|
os.api("notes/renotes", {
|
||||||
noteId: appearNote.id,
|
noteId: note.id,
|
||||||
limit: 100,
|
limit: 100,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
renotes = res;
|
renotes = res;
|
||||||
|
@ -414,7 +398,7 @@ async function onNoteUpdated(noteData: NoteUpdatedEvent): Promise<void> {
|
||||||
const { type, id, body } = noteData;
|
const { type, id, body } = noteData;
|
||||||
|
|
||||||
let found = -1;
|
let found = -1;
|
||||||
if (id === appearNote.id) {
|
if (id === note.id) {
|
||||||
found = 0;
|
found = 0;
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < replies.value.length; i++) {
|
for (let i = 0; i < replies.value.length; i++) {
|
||||||
|
|
|
@ -97,7 +97,10 @@
|
||||||
:to="`/notes/${note.renoteId}`"
|
:to="`/notes/${note.renoteId}`"
|
||||||
>{{ i18n.ts.quoteAttached }}: ...</MkA
|
>{{ i18n.ts.quoteAttached }}: ...</MkA
|
||||||
>
|
>
|
||||||
<XMediaList v-if="note.files.length > 0" :media-list="note.files" />
|
<XMediaList
|
||||||
|
v-if="note.files.length > 0"
|
||||||
|
:media-list="note.files"
|
||||||
|
/>
|
||||||
<XPoll v-if="note.poll" :note="note" class="poll" />
|
<XPoll v-if="note.poll" :note="note" class="poll" />
|
||||||
<template v-if="detailed">
|
<template v-if="detailed">
|
||||||
<MkUrlPreview
|
<MkUrlPreview
|
||||||
|
@ -151,7 +154,10 @@
|
||||||
<i class="ph-stop ph-bold"></i> {{ i18n.ts._mfm.stop }}
|
<i class="ph-stop ph-bold"></i> {{ i18n.ts._mfm.stop }}
|
||||||
</template>
|
</template>
|
||||||
</MkButton>
|
</MkButton>
|
||||||
<div v-if="(isLong && !collapsed) || (props.note.cw && showContent)" class="fade"></div>
|
<div
|
||||||
|
v-if="(isLong && !collapsed) || (props.note.cw && showContent)"
|
||||||
|
class="fade"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -188,13 +194,13 @@ const emit = defineEmits<{
|
||||||
|
|
||||||
const cwButton = ref<HTMLElement>();
|
const cwButton = ref<HTMLElement>();
|
||||||
const showMoreButton = ref<HTMLElement>();
|
const showMoreButton = ref<HTMLElement>();
|
||||||
const isLong = !props.detailedView
|
const isLong =
|
||||||
&& ( props.note.cw == null
|
!props.detailedView &&
|
||||||
&& (props.note.text != null
|
((props.note.cw == null &&
|
||||||
&& (props.note.text.split("\n").length > 9 || props.note.text.length > 500)
|
props.note.text != null &&
|
||||||
)
|
(props.note.text.split("\n").length > 9 ||
|
||||||
|| props.note.files.length > 4
|
props.note.text.length > 500)) ||
|
||||||
);
|
props.note.files.length > 4);
|
||||||
|
|
||||||
const collapsed = $ref(props.note.cw == null && isLong);
|
const collapsed = $ref(props.note.cw == null && isLong);
|
||||||
|
|
||||||
|
@ -238,7 +244,8 @@ function focusFooter(ev) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
:deep(a), :deep(button) {
|
:deep(a),
|
||||||
|
:deep(button) {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
@ -390,7 +397,7 @@ function focusFooter(ev) {
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
mask: linear-gradient(to top, var(--gradient));
|
mask: linear-gradient(to top, var(--gradient));
|
||||||
-webkit-mask: linear-gradient(to top, var(--gradient));
|
-webkit-mask: linear-gradient(to top, var(--gradient));
|
||||||
transition: background .2s;
|
transition: background 0.2s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
:name="$store.state.animation ? 'fade' : ''"
|
:name="$store.state.animation ? 'fade' : ''"
|
||||||
mode="out-in"
|
mode="out-in"
|
||||||
>
|
>
|
||||||
<div v-if="note" class="note">
|
<div v-if="appearNote" class="note">
|
||||||
<div v-if="showNext" class="_gap">
|
<div v-if="showNext" class="_gap">
|
||||||
<XNotes
|
<XNotes
|
||||||
class="_content"
|
class="_content"
|
||||||
|
@ -33,12 +33,12 @@
|
||||||
</MkButton>
|
</MkButton>
|
||||||
<div class="note _gap">
|
<div class="note _gap">
|
||||||
<MkRemoteCaution
|
<MkRemoteCaution
|
||||||
v-if="note.user.host != null"
|
v-if="appearNote.user.host != null"
|
||||||
:href="note.url ?? note.uri"
|
:href="appearNote.url ?? appearNote.uri"
|
||||||
/>
|
/>
|
||||||
<XNoteDetailed
|
<XNoteDetailed
|
||||||
:key="note.id"
|
:key="appearNote.id"
|
||||||
v-model:note="note"
|
v-model:note="appearNote"
|
||||||
class="note"
|
class="note"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -71,7 +71,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, defineComponent, watch } from "vue";
|
import { computed, defineComponent, watch } from "vue";
|
||||||
import * as misskey from "calckey-js";
|
import * as misskey from "calckey-js";
|
||||||
import XNote from "@/components/MkNote.vue";
|
|
||||||
import XNoteDetailed from "@/components/MkNoteDetailed.vue";
|
import XNoteDetailed from "@/components/MkNoteDetailed.vue";
|
||||||
import XNotes from "@/components/MkNotes.vue";
|
import XNotes from "@/components/MkNotes.vue";
|
||||||
import MkRemoteCaution from "@/components/MkRemoteCaution.vue";
|
import MkRemoteCaution from "@/components/MkRemoteCaution.vue";
|
||||||
|
@ -90,15 +89,17 @@ let hasNext = $ref(false);
|
||||||
let showPrev = $ref(false);
|
let showPrev = $ref(false);
|
||||||
let showNext = $ref(false);
|
let showNext = $ref(false);
|
||||||
let error = $ref();
|
let error = $ref();
|
||||||
|
let isRenote = $ref(false);
|
||||||
|
let appearNote = $ref<null | misskey.entities.Note>();
|
||||||
|
|
||||||
const prevPagination = {
|
const prevPagination = {
|
||||||
endpoint: "users/notes" as const,
|
endpoint: "users/notes" as const,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
params: computed(() =>
|
params: computed(() =>
|
||||||
note
|
appearNote
|
||||||
? {
|
? {
|
||||||
userId: note.userId,
|
userId: appearNote.userId,
|
||||||
untilId: note.id,
|
untilId: appearNote.id,
|
||||||
}
|
}
|
||||||
: null
|
: null
|
||||||
),
|
),
|
||||||
|
@ -109,10 +110,10 @@ const nextPagination = {
|
||||||
endpoint: "users/notes" as const,
|
endpoint: "users/notes" as const,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
params: computed(() =>
|
params: computed(() =>
|
||||||
note
|
appearNote
|
||||||
? {
|
? {
|
||||||
userId: note.userId,
|
userId: appearNote.userId,
|
||||||
sinceId: note.id,
|
sinceId: appearNote.id,
|
||||||
}
|
}
|
||||||
: null
|
: null
|
||||||
),
|
),
|
||||||
|
@ -129,6 +130,15 @@ function fetchNote() {
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
note = res;
|
note = res;
|
||||||
|
isRenote =
|
||||||
|
note.renote != null &&
|
||||||
|
note.text == null &&
|
||||||
|
note.fileIds.length === 0 &&
|
||||||
|
note.poll == null;
|
||||||
|
appearNote = isRenote
|
||||||
|
? (note.renote as misskey.entities.Note)
|
||||||
|
: note;
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
os.api("users/notes", {
|
os.api("users/notes", {
|
||||||
userId: note.userId,
|
userId: note.userId,
|
||||||
|
@ -160,19 +170,21 @@ const headerTabs = $computed(() => []);
|
||||||
|
|
||||||
definePageMetadata(
|
definePageMetadata(
|
||||||
computed(() =>
|
computed(() =>
|
||||||
note
|
appearNote
|
||||||
? {
|
? {
|
||||||
title: i18n.t("noteOf", {
|
title: i18n.t("noteOf", {
|
||||||
user: note.user.name || note.user.username,
|
user: appearNote.user.name || appearNote.user.username,
|
||||||
}),
|
}),
|
||||||
subtitle: new Date(note.createdAt).toLocaleString(),
|
subtitle: new Date(appearNote.createdAt).toLocaleString(),
|
||||||
avatar: note.user,
|
avatar: appearNote.user,
|
||||||
path: `/notes/${note.id}`,
|
path: `/notes/${appearNote.id}`,
|
||||||
share: {
|
share: {
|
||||||
title: i18n.t("noteOf", {
|
title: i18n.t("noteOf", {
|
||||||
user: note.user.name || note.user.username,
|
user:
|
||||||
|
appearNote.user.name ||
|
||||||
|
appearNote.user.username,
|
||||||
}),
|
}),
|
||||||
text: note.text,
|
text: appearNote.text,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: null
|
: null
|
||||||
|
|
|
@ -134,20 +134,19 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="follow-container">
|
<div class="follow-container">
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<MkFollowButton
|
|
||||||
:user="user"
|
|
||||||
@refresh="emit('refresh')"
|
|
||||||
:inline="true"
|
|
||||||
:transparent="false"
|
|
||||||
:full="!narrow"
|
|
||||||
class="koudoku"
|
|
||||||
/>
|
|
||||||
<button class="menu _button" @click="menu">
|
<button class="menu _button" @click="menu">
|
||||||
<i
|
<i
|
||||||
class="ph-dots-three-outline ph-bold ph-lg"
|
class="ph-dots-three-outline ph-bold ph-lg"
|
||||||
></i>
|
></i>
|
||||||
</button>
|
</button>
|
||||||
<!-- <MkFollowButton v-else-if="$i == null" :user="user" :remote="true" :inline="true" :transparent="false" :full="true" class="koudoku"/> -->
|
<MkFollowButton
|
||||||
|
:user="user"
|
||||||
|
@refresh="emit('refresh')"
|
||||||
|
:inline="true"
|
||||||
|
:transparent="false"
|
||||||
|
:full="true"
|
||||||
|
class="koudoku"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
|
@ -490,29 +489,6 @@ onUnmounted(() => {
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .actions {
|
|
||||||
position: absolute;
|
|
||||||
top: 12px;
|
|
||||||
right: 12px;
|
|
||||||
padding: 8px;
|
|
||||||
border-radius: 24px;
|
|
||||||
|
|
||||||
> .menu {
|
|
||||||
vertical-align: bottom;
|
|
||||||
height: 31px;
|
|
||||||
width: 31px;
|
|
||||||
color: #fff;
|
|
||||||
text-shadow: 0 0 8px var(--shadow);
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .koudoku {
|
|
||||||
margin-left: 4px;
|
|
||||||
width: 31px;
|
|
||||||
vertical-align: bottom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .title {
|
> .title {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
@ -581,22 +557,23 @@ onUnmounted(() => {
|
||||||
|
|
||||||
> .actions {
|
> .actions {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 12px;
|
top: 6px;
|
||||||
right: 12px;
|
right: 12px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
> .menu {
|
> .menu {
|
||||||
vertical-align: bottom;
|
|
||||||
height: 31px;
|
height: 31px;
|
||||||
width: 31px;
|
width: 31px;
|
||||||
color: --fg;
|
color: --fg;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .koudoku {
|
> :deep(.follow-button) {
|
||||||
margin-left: 4px;
|
margin-left: 8px;
|
||||||
vertical-align: bottom;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,6 +774,13 @@ onUnmounted(() => {
|
||||||
|
|
||||||
> .title {
|
> .title {
|
||||||
display: block;
|
display: block;
|
||||||
|
border-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
> .bottom {
|
||||||
|
> .username {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .avatar {
|
> .avatar {
|
||||||
|
@ -822,15 +806,19 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
> .description {
|
> .description {
|
||||||
top: -55px;
|
top: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .follow-container {
|
> .follow-container {
|
||||||
overflow: visible !important;
|
overflow: visible !important;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
height: auto;
|
||||||
|
border-bottom: 1px solid var(--divider);
|
||||||
|
padding-bottom: 5px;
|
||||||
> .actions {
|
> .actions {
|
||||||
top: -110px;
|
position: static;
|
||||||
right: 0px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,17 @@ import { mainRouter } from "@/router";
|
||||||
export async function search() {
|
export async function search() {
|
||||||
const { canceled, result: query } = await os.inputText({
|
const { canceled, result: query } = await os.inputText({
|
||||||
title: i18n.ts.search,
|
title: i18n.ts.search,
|
||||||
|
placeholder: i18n.ts.searchPlaceholder,
|
||||||
|
text:
|
||||||
|
"Advanced search operators\n" +
|
||||||
|
"from:user => filter by user\n" +
|
||||||
|
"has:image/video/audio/text/file => filter by attachment types\n" +
|
||||||
|
"domain:domain.com => filter by domain\n" +
|
||||||
|
"before:Date => show posts made before Date\n" +
|
||||||
|
"after:Date => show posts made after Date\n" +
|
||||||
|
'"text" => get posts with exact text between quotes\n' +
|
||||||
|
"filter:following => show results only from users you follow\n" +
|
||||||
|
"filter:followers => show results only from followers\n",
|
||||||
});
|
});
|
||||||
if (canceled || query == null || query === "") return;
|
if (canceled || query == null || query === "") return;
|
||||||
|
|
||||||
|
|
|
@ -212,6 +212,11 @@ hr {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> i:only-child {
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
._buttonPrimary {
|
._buttonPrimary {
|
||||||
|
|
|
@ -89,6 +89,10 @@ export default function (app: App) {
|
||||||
"MkwUserList",
|
"MkwUserList",
|
||||||
defineAsyncComponent(() => import("./user-list.vue")),
|
defineAsyncComponent(() => import("./user-list.vue")),
|
||||||
);
|
);
|
||||||
|
app.component(
|
||||||
|
"MkwServerInfo",
|
||||||
|
defineAsyncComponent(() => import("./server-info.vue")),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const widgets = [
|
export const widgets = [
|
||||||
|
@ -110,6 +114,7 @@ export const widgets = [
|
||||||
"postForm",
|
"postForm",
|
||||||
"slideshow",
|
"slideshow",
|
||||||
"serverMetric",
|
"serverMetric",
|
||||||
|
"serverInfo",
|
||||||
"onlineUsers",
|
"onlineUsers",
|
||||||
"jobQueue",
|
"jobQueue",
|
||||||
"button",
|
"button",
|
||||||
|
|
113
packages/client/src/widgets/server-info.vue
Normal file
113
packages/client/src/widgets/server-info.vue
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<template>
|
||||||
|
<div class="_panel">
|
||||||
|
<div
|
||||||
|
:class="$style.container"
|
||||||
|
:style="{
|
||||||
|
backgroundImage: $instance.bannerUrl
|
||||||
|
? `url(${$instance.bannerUrl})`
|
||||||
|
: null,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div :class="$style.iconContainer">
|
||||||
|
<img
|
||||||
|
:src="
|
||||||
|
$instance.iconUrl ??
|
||||||
|
$instance.faviconUrl ??
|
||||||
|
'/favicon.ico'
|
||||||
|
"
|
||||||
|
alt=""
|
||||||
|
:class="$style.icon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div :class="$style.bodyContainer">
|
||||||
|
<div :class="$style.body">
|
||||||
|
<MkA :class="$style.name" to="/about" behavior="window">{{
|
||||||
|
$instance.name
|
||||||
|
}}</MkA>
|
||||||
|
<div :class="$style.host">{{ host }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {
|
||||||
|
useWidgetPropsManager,
|
||||||
|
Widget,
|
||||||
|
WidgetComponentEmits,
|
||||||
|
WidgetComponentExpose,
|
||||||
|
WidgetComponentProps,
|
||||||
|
} from "./widget";
|
||||||
|
import { GetFormResultType } from "@/scripts/form";
|
||||||
|
import { host } from "@/config";
|
||||||
|
|
||||||
|
const name = "serverInfo";
|
||||||
|
|
||||||
|
const widgetPropsDef = {};
|
||||||
|
|
||||||
|
type WidgetProps = GetFormResultType<typeof widgetPropsDef>;
|
||||||
|
|
||||||
|
const props = defineProps<{ widget?: Widget<WidgetProps> }>();
|
||||||
|
const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>();
|
||||||
|
|
||||||
|
const { widgetProps, configure } = useWidgetPropsManager(
|
||||||
|
name,
|
||||||
|
widgetPropsDef,
|
||||||
|
props,
|
||||||
|
emit
|
||||||
|
);
|
||||||
|
|
||||||
|
defineExpose<WidgetComponentExpose>({
|
||||||
|
name,
|
||||||
|
configure,
|
||||||
|
id: props.widget ? props.widget.id : null,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
.container {
|
||||||
|
position: relative;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconContainer {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: inline-block;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: solid 3px var(--panelBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bodyContainer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
min-width: 0;
|
||||||
|
padding: 0 16px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name,
|
||||||
|
.host {
|
||||||
|
color: var(--fg);
|
||||||
|
text-shadow: -1px -1px 0 var(--bg), 1px -1px 0 var(--bg),
|
||||||
|
-1px 1px 0 var(--bg), 1px 1px 0 var(--bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.host {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue