Compare commits
7 commits
07b5e90887
...
a4a619c4ae
Author | SHA1 | Date | |
---|---|---|---|
a4a619c4ae | |||
68f0de7c02 | |||
3f3d2082a9 | |||
b0875f7649 | |||
a4f958d8c4 | |||
d8d936250e | |||
50b822d103 |
84 changed files with 532 additions and 377 deletions
|
@ -42,6 +42,9 @@
|
|||
|
||||
### 細かい変更点
|
||||
|
||||
- コードブロックの構文ハイライトの対応言語を強化
|
||||
- TODO: CDN を利用しない設定でもこれを行えるようにする
|
||||
- TODO: 本家版にもマージリクエストを出す
|
||||
- モバイル表示の下部のウィジェットボタンを再読み込みボタンに変更可能に
|
||||
- スマートフォンでウィジェットは使わないけど再読み込みはたくさんする人はいそう
|
||||
- 設定のバックアップファイルに `misskeyVersion` の値が含まれていなくても警告しないように変更
|
||||
|
|
|
@ -1174,6 +1174,8 @@ pullDownToReload: "Pull down to reload"
|
|||
enableTimelineStreaming: "Update timelines automatically"
|
||||
useEmojiCdn: "Get Twemoji from CDN"
|
||||
useEmojiCdnDescription: "Use Twemoji from the JSDelivr CDN instead of the server's assets."
|
||||
useCdn: "Get assets from CDN"
|
||||
useCdnDescription: "Load some static assets like Twemoji from the JSDelivr CDN instead of this Firefish server."
|
||||
suggested: "Suggested"
|
||||
noLanguage: "No language"
|
||||
|
||||
|
|
|
@ -1008,6 +1008,8 @@ emphasizeFollowed: "フォロワーのアカウントに表示される「フォ
|
|||
iconSet: "アイコンのスタイル"
|
||||
useEmojiCdn: "CDNのTwemojiを利用する"
|
||||
useEmojiCdnDescription: "サーバー上に保存されているTwemojiのアセットの代わりに、JSDelivr CDNから配信されたものを用います。"
|
||||
useCdn: "CDNのアセットを利用する"
|
||||
useCdnDescription: "このFirefishサーバーからではなくJSDelivr CDNからTwiemojiなどのアセットを読み込みます。"
|
||||
|
||||
_sensitiveMediaDetection:
|
||||
description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てられます。サーバーの負荷が少し増えます。"
|
||||
|
|
|
@ -295,11 +295,13 @@ if (!nativeBinding) {
|
|||
throw new Error(`Failed to load native binding`)
|
||||
}
|
||||
|
||||
const { EnvConfig, readEnvironmentConfig, readServerConfig, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, stringToAcct, acctToString, getFullApAccount, isSelfHost, extractHost, toPuny, toPunyOptional, convertToHiddenPost, sqlLikeEscape, safeForSql, formatMilliseconds, nativeInitIdGenerator, nativeCreateId, nativeGetTimestamp, genString, IdConvertType, convertId } = nativeBinding
|
||||
const { EnvConfig, readEnvironmentConfig, readServerConfig, JsDbConn, connectToDatabase, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, stringToAcct, acctToString, getFullApAccount, isSelfHost, extractHost, toPuny, toPunyOptional, convertToHiddenPost, sqlLikeEscape, safeForSql, formatMilliseconds, nativeInitIdGenerator, nativeCreateId, nativeGetTimestamp, fetchMeta, metaToPugArgs, otherRenoteByUserExists, genString, IdConvertType, convertId } = nativeBinding
|
||||
|
||||
module.exports.EnvConfig = EnvConfig
|
||||
module.exports.readEnvironmentConfig = readEnvironmentConfig
|
||||
module.exports.readServerConfig = readServerConfig
|
||||
module.exports.JsDbConn = JsDbConn
|
||||
module.exports.connectToDatabase = connectToDatabase
|
||||
module.exports.AntennaSrcEnum = AntennaSrcEnum
|
||||
module.exports.MutedNoteReasonEnum = MutedNoteReasonEnum
|
||||
module.exports.NoteVisibilityEnum = NoteVisibilityEnum
|
||||
|
@ -324,6 +326,9 @@ module.exports.formatMilliseconds = formatMilliseconds
|
|||
module.exports.nativeInitIdGenerator = nativeInitIdGenerator
|
||||
module.exports.nativeCreateId = nativeCreateId
|
||||
module.exports.nativeGetTimestamp = nativeGetTimestamp
|
||||
module.exports.fetchMeta = fetchMeta
|
||||
module.exports.metaToPugArgs = metaToPugArgs
|
||||
module.exports.otherRenoteByUserExists = otherRenoteByUserExists
|
||||
module.exports.genString = genString
|
||||
module.exports.IdConvertType = IdConvertType
|
||||
module.exports.convertId = convertId
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
# prefix message filename with timestamp
|
||||
[ ! -f neko/flags/install_pgroonga ] || mv neko/flags/install_pgroonga neko/flags/20231128_install_pgroonga
|
||||
[ ! -f neko/flags/docker_compose_rename ] || mv neko/flags/docker_compose_rename neko/flags/20231129_docker_compose_rename
|
||||
[ ! -f neko/flags/temp_upgrade_node_to_v21 ] || mv neko/flags/temp_upgrade_node_to_v21 neko/flags/20231229_upgrade_node_to_v21
|
||||
[ ! -f neko/flags/add_volume_to_docker_compose ] || mv neko/flags/add_volume_to_docker_compose neko/flags/20240102_add_volume_to_docker_compose
|
||||
|
||||
# remove native-utils
|
||||
rm -rf packages/backend/native-utils/built
|
||||
rm -rf packages/backend/native-utils/node_modules
|
||||
rm -rf packages/backend/native-utils/target
|
||||
rmdir packages/backend/native-utils || :
|
||||
|
|
16
package.json
16
package.json
|
@ -9,7 +9,7 @@
|
|||
"engines": {
|
||||
"node": ">= 18.17.0"
|
||||
},
|
||||
"packageManager": "pnpm@8.14.2",
|
||||
"packageManager": "pnpm@8.14.3",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"rebuild": "pnpm run clean && pnpm run build",
|
||||
|
@ -44,14 +44,14 @@
|
|||
"js-yaml": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.5.2",
|
||||
"@biomejs/cli-darwin-arm64": "1.5.2",
|
||||
"@biomejs/cli-darwin-x64": "1.5.2",
|
||||
"@biomejs/cli-linux-arm64": "1.5.2",
|
||||
"@biomejs/cli-linux-x64": "1.5.2",
|
||||
"@types/node": "20.11.5",
|
||||
"@biomejs/biome": "1.5.3",
|
||||
"@biomejs/cli-darwin-arm64": "1.5.3",
|
||||
"@biomejs/cli-darwin-x64": "1.5.3",
|
||||
"@biomejs/cli-linux-arm64": "1.5.3",
|
||||
"@biomejs/cli-linux-x64": "1.5.3",
|
||||
"@types/node": "20.11.6",
|
||||
"execa": "8.0.1",
|
||||
"pnpm": "8.14.2",
|
||||
"pnpm": "8.14.3",
|
||||
"typescript": "5.3.3"
|
||||
}
|
||||
}
|
||||
|
|
19
packages/backend-rs/Cargo.lock
generated
19
packages/backend-rs/Cargo.lock
generated
|
@ -222,6 +222,7 @@ dependencies = [
|
|||
"thiserror",
|
||||
"tokio",
|
||||
"url",
|
||||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -412,9 +413,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
|||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.31"
|
||||
version = "0.4.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||
checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
|
@ -422,7 +423,7 @@ dependencies = [
|
|||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-targets 0.48.5",
|
||||
"windows-targets 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1271,9 +1272,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "napi"
|
||||
version = "2.14.2"
|
||||
version = "2.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fc1cb00cde484640da9f01a124edbb013576a6ae9843b23857c940936b76d91"
|
||||
checksum = "902495f6b80f53f8435aefbbd2241c9c675fa239cd7e5f8e28fb57f3b69ecd09"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"chrono",
|
||||
|
@ -2025,9 +2026,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sea-orm"
|
||||
version = "0.12.11"
|
||||
version = "0.12.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59f66e2129991acd51fcad7b59da1edd862edca69773cc9a19cb17b967fae2fb"
|
||||
checksum = "0cbf88748872fa54192476d6d49d0775e208566a72656e267e45f6980b926c8d"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"async-trait",
|
||||
|
@ -2053,9 +2054,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sea-orm-macros"
|
||||
version = "0.12.11"
|
||||
version = "0.12.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b03da1864306242678ac3b6567e69f70dd1252a72742baa23a4d92d2d45da3fc"
|
||||
checksum = "e0dbc880d47aa53c6a572e39c99402c7fad59b50766e51e0b0fc1306510b0555"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
|
|
|
@ -13,7 +13,7 @@ crate-type = ["cdylib", "lib"]
|
|||
[dependencies]
|
||||
async-trait = "0.1.77"
|
||||
cfg-if = "1.0.0"
|
||||
chrono = "0.4.31"
|
||||
chrono = "0.4.32"
|
||||
cuid2 = "0.1.2"
|
||||
idna = "0.5.0"
|
||||
jsonschema = "0.17.1"
|
||||
|
@ -21,7 +21,7 @@ once_cell = "1.19.0"
|
|||
parse-display = "0.8.2"
|
||||
rand = "0.8.5"
|
||||
schemars = { version = "0.8.16", features = ["chrono"] }
|
||||
sea-orm = { version = "0.12.11", features = ["sqlx-postgres", "runtime-tokio-rustls"] }
|
||||
sea-orm = { version = "0.12.12", features = ["sqlx-postgres", "runtime-tokio-rustls"] }
|
||||
serde = { version = "1.0.195", features = ["derive"] }
|
||||
serde_json = "1.0.111"
|
||||
serde_yaml = "0.9.30"
|
||||
|
@ -30,9 +30,10 @@ tokio = { version = "1.35.1", features = ["full"] }
|
|||
url = "2.5.0"
|
||||
|
||||
# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
|
||||
napi = { version = "2.14.2", default-features = false, features = ["napi9", "tokio_rt", "chrono_date", "serde-json"] }
|
||||
napi = { version = "2.14.4", default-features = false, features = ["napi9", "tokio_rt", "chrono_date", "serde-json"] }
|
||||
napi-derive = { version = "2.14.6", optional = true }
|
||||
basen = "0.1.0"
|
||||
urlencoding = "2.1.3"
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "1.4.0"
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@napi-rs/cli": "2.18.0",
|
||||
"ava": "6.0.1"
|
||||
"ava": "6.1.0"
|
||||
},
|
||||
"ava": {
|
||||
"timeout": "3m"
|
||||
|
|
|
@ -11,3 +11,12 @@ pub enum Error {
|
|||
}
|
||||
|
||||
impl_napi_error_from!(Error);
|
||||
|
||||
pub trait NapiDbErrExt {
|
||||
fn into(self) -> napi::Error;
|
||||
}
|
||||
impl NapiDbErrExt for DbErr {
|
||||
fn into(self) -> napi::Error {
|
||||
napi::Error::from_reason(self.to_string())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,50 @@
|
|||
pub mod error;
|
||||
pub use error::NapiDbErrExt;
|
||||
|
||||
use error::Error;
|
||||
use crate::config::server::DbConfig;
|
||||
use sea_orm::{Database, DbConn};
|
||||
use urlencoding::encode;
|
||||
|
||||
static DB_CONN: once_cell::sync::OnceCell<DbConn> = once_cell::sync::OnceCell::new();
|
||||
|
||||
pub async fn init_database(conn_uri: impl Into<String>) -> Result<(), Error> {
|
||||
let conn = Database::connect(conn_uri.into()).await?;
|
||||
DB_CONN.get_or_init(move || conn);
|
||||
Ok(())
|
||||
#[napi_derive::napi]
|
||||
pub struct JsDbConn {
|
||||
inner: DbConn,
|
||||
}
|
||||
impl JsDbConn {
|
||||
pub fn inner(&self) -> &DbConn {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_database() -> Result<&'static DbConn, Error> {
|
||||
DB_CONN.get().ok_or(Error::Uninitialized)
|
||||
#[napi_derive::napi]
|
||||
pub async fn connect_to_database(config: DbConfig) -> napi::Result<JsDbConn> {
|
||||
let conn_uri = format!(
|
||||
"postgres://{}:{}@{}:{}/{}",
|
||||
config.user,
|
||||
encode(&config.pass),
|
||||
config.host,
|
||||
config.port,
|
||||
config.db,
|
||||
);
|
||||
let conn = Database::connect(conn_uri)
|
||||
.await
|
||||
.map_err(NapiDbErrExt::into)?;
|
||||
Ok(JsDbConn { inner: conn })
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{error::Error, get_database};
|
||||
use super::connect_to_database;
|
||||
use crate::config::server::read_server_config;
|
||||
|
||||
#[test]
|
||||
fn error_uninitialized() {
|
||||
assert_eq!(get_database().unwrap_err(), Error::Uninitialized);
|
||||
#[tokio::test]
|
||||
async fn connect_with_server_config() {
|
||||
assert!(connect_to_database(read_server_config().db).await.is_ok());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn connect_with_incorrect_password() {
|
||||
let mut config = read_server_config().db;
|
||||
config.pass.push('.'); // password should be incorrect now
|
||||
assert!(connect_to_database(config).await.is_err());
|
||||
}
|
||||
}
|
||||
|
|
87
packages/backend-rs/src/util/meta.rs
Normal file
87
packages/backend-rs/src/util/meta.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
use crate::database::{JsDbConn, NapiDbErrExt};
|
||||
use crate::model::entity::meta;
|
||||
use rand::prelude::*;
|
||||
use sea_orm::{prelude::*, ActiveValue};
|
||||
use std::sync::Mutex;
|
||||
|
||||
type Meta = meta::Model;
|
||||
|
||||
static CACHE: Mutex<Option<Meta>> = Mutex::new(None);
|
||||
fn update_cache(meta: &Meta) {
|
||||
let _ = CACHE.lock().map(|mut cache| *cache = Some(meta.clone()));
|
||||
}
|
||||
|
||||
#[napi_derive::napi]
|
||||
pub async fn fetch_meta(conn: &JsDbConn, invalidate_cache: Option<bool>) -> napi::Result<Meta> {
|
||||
// try using cache
|
||||
if invalidate_cache == Some(true) {
|
||||
if let Some(cache) = CACHE.lock().ok().and_then(|cache| cache.clone()) {
|
||||
return Ok(cache);
|
||||
}
|
||||
}
|
||||
|
||||
// try fetching from db
|
||||
let db = conn.inner();
|
||||
let meta = meta::Entity::find()
|
||||
.one(db)
|
||||
.await
|
||||
.map_err(NapiDbErrExt::into)?;
|
||||
if let Some(meta) = meta {
|
||||
update_cache(&meta);
|
||||
return Ok(meta);
|
||||
}
|
||||
|
||||
// create a new meta object and insert into db
|
||||
let meta = meta::Entity::insert(meta::ActiveModel {
|
||||
id: ActiveValue::Set("x".to_owned()),
|
||||
..Default::default()
|
||||
})
|
||||
.exec_with_returning(db)
|
||||
.await
|
||||
.map_err(NapiDbErrExt::into)?;
|
||||
update_cache(&meta);
|
||||
Ok(meta)
|
||||
}
|
||||
|
||||
#[napi_derive::napi(object)]
|
||||
pub struct PugArgs {
|
||||
pub img: Option<String>,
|
||||
pub title: String,
|
||||
pub instance_name: String,
|
||||
pub desc: Option<String>,
|
||||
pub icon: Option<String>,
|
||||
pub splash_icon: Option<String>,
|
||||
pub theme_color: Option<String>,
|
||||
pub random_motd: String,
|
||||
pub private_mode: Option<bool>,
|
||||
}
|
||||
|
||||
#[napi_derive::napi]
|
||||
pub fn meta_to_pug_args(meta: Meta) -> PugArgs {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let splash_icon = meta
|
||||
.custom_splash_icons
|
||||
.choose(&mut rng)
|
||||
.map(|s| s.to_owned())
|
||||
.or_else(|| meta.icon_url.to_owned());
|
||||
|
||||
let random_motd = meta
|
||||
.custom_motd
|
||||
.choose(&mut rng)
|
||||
.map(|s| s.to_owned())
|
||||
.unwrap_or_else(|| "Loading...".to_owned());
|
||||
|
||||
let name = meta.name.unwrap_or_else(|| "Firefish".to_owned());
|
||||
PugArgs {
|
||||
img: meta.banner_url,
|
||||
title: name.clone(),
|
||||
instance_name: name.clone(),
|
||||
desc: meta.description,
|
||||
icon: meta.icon_url,
|
||||
splash_icon,
|
||||
theme_color: meta.theme_color,
|
||||
random_motd,
|
||||
private_mode: meta.private_mode,
|
||||
}
|
||||
}
|
|
@ -4,4 +4,6 @@ pub mod convert_to_hidden_post;
|
|||
pub mod escape_sql;
|
||||
pub mod format_milliseconds;
|
||||
pub mod id;
|
||||
pub mod meta;
|
||||
pub mod note;
|
||||
pub mod random;
|
||||
|
|
25
packages/backend-rs/src/util/note.rs
Normal file
25
packages/backend-rs/src/util/note.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use crate::database::{JsDbConn, NapiDbErrExt};
|
||||
use crate::model::entity::note;
|
||||
use sea_orm::prelude::*;
|
||||
|
||||
/**
|
||||
* Returns true if user {user_id}
|
||||
* has any renote of note {renote_id}
|
||||
* except the specified renote {excluded_note_id}
|
||||
*/
|
||||
#[napi_derive::napi]
|
||||
pub async fn other_renote_by_user_exists(
|
||||
conn: &JsDbConn,
|
||||
user_id: String,
|
||||
renote_id: String,
|
||||
excluded_note_id: String,
|
||||
) -> napi::Result<bool> {
|
||||
note::Entity::find()
|
||||
.filter(note::Column::UserId.eq(user_id))
|
||||
.filter(note::Column::RenoteId.eq(renote_id))
|
||||
.filter(note::Column::Id.ne(excluded_note_id))
|
||||
.one(conn.inner())
|
||||
.await
|
||||
.map(|row| row.is_some())
|
||||
.map_err(NapiDbErrExt::into)
|
||||
}
|
|
@ -28,14 +28,14 @@
|
|||
"@koa/router": "12.0.1",
|
||||
"@ladjs/koa-views": "9.0.0",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@redocly/openapi-core": "1.6.0",
|
||||
"@redocly/openapi-core": "1.7.0",
|
||||
"@sinonjs/fake-timers": "11.2.2",
|
||||
"@twemoji/parser": "^15.0.0",
|
||||
"adm-zip": "^0.5.10",
|
||||
"ajv": "8.12.0",
|
||||
"archiver": "6.0.1",
|
||||
"argon2": "^0.31.2",
|
||||
"aws-sdk": "2.1540.0",
|
||||
"aws-sdk": "2.1542.0",
|
||||
"axios": "1.6.5",
|
||||
"backend-rs": "workspace:*",
|
||||
"bcryptjs": "2.4.3",
|
||||
|
@ -48,7 +48,7 @@
|
|||
"cli-highlight": "2.1.11",
|
||||
"color-convert": "2.0.1",
|
||||
"content-disposition": "0.5.4",
|
||||
"date-fns": "3.3.0",
|
||||
"date-fns": "3.3.1",
|
||||
"decompress": "4.2.1",
|
||||
"deep-email-validator": "0.1.21",
|
||||
"deepl-node": "1.11.0",
|
||||
|
@ -59,7 +59,7 @@
|
|||
"firefish-js": "workspace:*",
|
||||
"got": "14.0.0",
|
||||
"gunzip-maybe": "1.4.2",
|
||||
"happy-dom": "13.2.0",
|
||||
"happy-dom": "13.3.1",
|
||||
"hpagent": "1.2.0",
|
||||
"ioredis": "5.3.2",
|
||||
"ip-cidr": "4.0.0",
|
||||
|
@ -125,7 +125,7 @@
|
|||
"xev": "3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@swc/cli": "0.1.64",
|
||||
"@swc/cli": "0.1.65",
|
||||
"@swc/core": "1.3.105",
|
||||
"@types/adm-zip": "0.5.5",
|
||||
"@types/bcryptjs": "2.4.6",
|
||||
|
@ -144,7 +144,7 @@
|
|||
"@types/koa__cors": "5.0.0",
|
||||
"@types/koa__multer": "2.0.7",
|
||||
"@types/koa__router": "12.0.4",
|
||||
"@types/node": "20.11.5",
|
||||
"@types/node": "20.11.6",
|
||||
"@types/node-fetch": "2.6.11",
|
||||
"@types/nodemailer": "6.4.14",
|
||||
"@types/oauth": "0.9.4",
|
||||
|
@ -177,7 +177,7 @@
|
|||
"ts-node": "10.9.2",
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"typescript": "5.3.3",
|
||||
"webpack": "5.89.0",
|
||||
"webpack": "5.90.0",
|
||||
"ws": "8.16.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import si from "systeminformation";
|
||||
import Xev from "xev";
|
||||
import * as osUtils from "os-utils";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
// import meilisearch from "@/db/meilisearch.js";
|
||||
|
||||
const ev = new Xev();
|
||||
|
|
|
@ -1,15 +1,28 @@
|
|||
import {
|
||||
readServerConfig,
|
||||
readEnvironmentConfig,
|
||||
connectToDatabase,
|
||||
otherRenoteByUserExists as otherRenoteByUserExistsImpl,
|
||||
fetchMeta as fetchMetaImpl,
|
||||
getFullApAccount as getFullApAccountImpl,
|
||||
isSelfHost as isSelfHostImpl,
|
||||
JsDbConn,
|
||||
} from "backend-rs";
|
||||
|
||||
export const serverConfig = readServerConfig();
|
||||
export const envConfig = readEnvironmentConfig();
|
||||
const dbPromise = connectToDatabase(serverConfig.db);
|
||||
|
||||
type Option<T> = T | null | undefined;
|
||||
|
||||
const curryDb =
|
||||
<P extends any[], R>(f: (db: JsDbConn, ...args: P) => Promise<R>) =>
|
||||
(...args: P) =>
|
||||
dbPromise.then((db) => f(db, ...args));
|
||||
|
||||
export const fetchMeta = curryDb(fetchMetaImpl);
|
||||
export const otherRenoteByUserExists = curryDb(otherRenoteByUserExistsImpl);
|
||||
|
||||
export function getFullApAccount(
|
||||
username: string,
|
||||
host: Option<string>,
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
import { Notes } from "@/models/index.js";
|
||||
|
||||
export async function countSameRenotes(
|
||||
userId: string,
|
||||
renoteId: string,
|
||||
excludeNoteId: string | undefined,
|
||||
): Promise<number> {
|
||||
// 指定したユーザーの指定したノートのリノートがいくつあるか数える
|
||||
const query = Notes.createQueryBuilder("note")
|
||||
.where("note.userId = :userId", { userId })
|
||||
.andWhere("note.renoteId = :renoteId", { renoteId });
|
||||
|
||||
// 指定した投稿を除く
|
||||
if (excludeNoteId) {
|
||||
query.andWhere("note.id != :excludeNoteId", { excludeNoteId });
|
||||
}
|
||||
|
||||
return await query.getCount();
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
import { db } from "@/db/postgre.js";
|
||||
import { Meta } from "@/models/entities/meta.js";
|
||||
|
||||
let cache: Meta;
|
||||
|
||||
export function metaToPugArgs(meta: Meta): object {
|
||||
let motd = ["Loading..."];
|
||||
if (meta.customMotd.length > 0) {
|
||||
motd = meta.customMotd;
|
||||
}
|
||||
let splashIconUrl = meta.iconUrl;
|
||||
if (meta.customSplashIcons.length > 0) {
|
||||
splashIconUrl =
|
||||
meta.customSplashIcons[
|
||||
Math.floor(Math.random() * meta.customSplashIcons.length)
|
||||
];
|
||||
}
|
||||
|
||||
return {
|
||||
img: meta.bannerUrl,
|
||||
title: meta.name || "Firefish",
|
||||
instanceName: meta.name || "Firefish",
|
||||
desc: meta.description,
|
||||
icon: meta.iconUrl,
|
||||
splashIcon: splashIconUrl,
|
||||
themeColor: meta.themeColor,
|
||||
randomMOTD: motd[Math.floor(Math.random() * motd.length)],
|
||||
privateMode: meta.privateMode,
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchMeta(noCache = false): Promise<Meta> {
|
||||
if (!noCache && cache) return cache;
|
||||
|
||||
return await db.transaction(async (transactionalEntityManager) => {
|
||||
// New IDs are prioritized because multiple records may have been created due to past bugs.
|
||||
const metas = await transactionalEntityManager.find(Meta, {
|
||||
order: {
|
||||
id: "DESC",
|
||||
},
|
||||
});
|
||||
|
||||
const meta = metas[0];
|
||||
|
||||
if (meta) {
|
||||
cache = meta;
|
||||
return meta;
|
||||
} else {
|
||||
// If fetchMeta is called at the same time when meta is empty, this part may be called at the same time, so use fail-safe upsert.
|
||||
const saved = await transactionalEntityManager
|
||||
.upsert(
|
||||
Meta,
|
||||
{
|
||||
id: "x",
|
||||
},
|
||||
["id"],
|
||||
)
|
||||
.then((x) =>
|
||||
transactionalEntityManager.findOneByOrFail(Meta, x.identifiers[0]),
|
||||
);
|
||||
|
||||
cache = saved;
|
||||
return saved;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
fetchMeta(true).then((meta) => {
|
||||
cache = meta;
|
||||
});
|
||||
}, 1000 * 10);
|
|
@ -1,4 +1,4 @@
|
|||
import { fetchMeta } from "./fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import type { ILocalUser } from "@/models/entities/user.js";
|
||||
import { Users } from "@/models/index.js";
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { emojiRegex } from "./emoji-regex.js";
|
||||
import { fetchMeta } from "./fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { Emojis } from "@/models/index.js";
|
||||
import { toPunyOptional } from "backend-rs";
|
||||
import { IsNull } from "typeorm";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import type { Instance } from "@/models/entities/instance.js";
|
||||
import type { Meta } from "@/models/entities/meta.js";
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Brackets } from "typeorm";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { Instances } from "@/models/index.js";
|
||||
import type { Instance } from "@/models/entities/instance.js";
|
||||
import { DAY } from "@/const.js";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import fetch from "node-fetch";
|
||||
import { Converter } from "opencc-js";
|
||||
import { getAgentByUrl } from "@/misc/fetch.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import type { Language } from "@/misc/langmap";
|
||||
import * as deepl from "deepl-node";
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import perform from "@/remote/activitypub/perform.js";
|
|||
import Logger from "@/services/logger.js";
|
||||
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
||||
import { Instances } from "@/models/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { toPuny, extractHost } from "backend-rs";
|
||||
import { getApId } from "@/remote/activitypub/type.js";
|
||||
import { fetchInstanceMetadata } from "@/services/fetch-instance-metadata.js";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { URL } from "url";
|
||||
import httpSignature, { IParsedSignature } from "@peertube/http-signature";
|
||||
import config from "@/config/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { toPuny } from "backend-rs";
|
||||
import DbResolver from "@/remote/activitypub/db-resolver.js";
|
||||
import { getApId } from "@/remote/activitypub/type.js";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { uploadFromUrl } from "@/services/drive/upload-from-url.js";
|
||||
import type { CacheableRemoteUser } from "@/models/entities/user.js";
|
||||
import Resolver from "../resolver.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { apLogger } from "../logger.js";
|
||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||
import { DriveFiles } from "@/models/index.js";
|
||||
|
|
|
@ -4,7 +4,6 @@ import type { NoteReaction } from "@/models/entities/note-reaction.js";
|
|||
import type { Note } from "@/models/entities/note.js";
|
||||
import { Emojis } from "@/models/index.js";
|
||||
import renderEmoji from "./emoji.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
|
||||
export const renderLike = async (noteReaction: NoteReaction, note: Note) => {
|
||||
const reaction = noteReaction.reaction;
|
||||
|
|
|
@ -2,7 +2,7 @@ import config from "@/config/index.js";
|
|||
import { getJson } from "@/misc/fetch.js";
|
||||
import type { ILocalUser } from "@/models/entities/user.js";
|
||||
import { getInstanceActor } from "@/services/instance-actor.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { extractHost } from "backend-rs";
|
||||
import { isSelfHost } from "@/misc/backend-rs.js";
|
||||
import { signedGet } from "./request.js";
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
getSignatureUser,
|
||||
} from "@/remote/activitypub/check-fetch.js";
|
||||
import { getInstanceActor } from "@/services/instance-actor.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import renderFollow from "@/remote/activitypub/renderer/follow.js";
|
||||
import Featured from "./activitypub/featured.js";
|
||||
import Following from "./activitypub/following.js";
|
||||
|
|
|
@ -5,7 +5,7 @@ import renderOrderedCollection from "@/remote/activitypub/renderer/ordered-colle
|
|||
import renderNote from "@/remote/activitypub/renderer/note.js";
|
||||
import { Users, Notes, UserNotePinings } from "@/models/index.js";
|
||||
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { setResponseType } from "../activitypub.js";
|
||||
import type Router from "@koa/router";
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import renderFollowUser from "@/remote/activitypub/renderer/follow-user.js";
|
|||
import { Users, Followings, UserProfiles } from "@/models/index.js";
|
||||
import type { Following } from "@/models/entities/following.js";
|
||||
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { setResponseType } from "../activitypub.js";
|
||||
import type { FindOptionsWhere } from "typeorm";
|
||||
import type Router from "@koa/router";
|
||||
|
|
|
@ -8,7 +8,7 @@ import renderFollowUser from "@/remote/activitypub/renderer/follow-user.js";
|
|||
import { Users, Followings, UserProfiles } from "@/models/index.js";
|
||||
import type { Following } from "@/models/entities/following.js";
|
||||
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { setResponseType } from "../activitypub.js";
|
||||
import type { FindOptionsWhere } from "typeorm";
|
||||
import type Router from "@koa/router";
|
||||
|
|
|
@ -11,7 +11,7 @@ import * as url from "@/prelude/url.js";
|
|||
import { Users, Notes } from "@/models/index.js";
|
||||
import type { Note } from "@/models/entities/note.js";
|
||||
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { makePaginationQuery } from "../api/common/make-pagination-query.js";
|
||||
import { setResponseType } from "../activitypub.js";
|
||||
import type Router from "@koa/router";
|
||||
|
|
|
@ -2,7 +2,7 @@ import type Koa from "koa";
|
|||
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
import { UserIps } from "@/models/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import type { IEndpoint } from "./endpoints.js";
|
||||
import authenticate, { AuthenticationError } from "./authenticate.js";
|
||||
import call from "./call.js";
|
||||
|
|
|
@ -9,7 +9,7 @@ import endpoints from "./endpoints.js";
|
|||
import compatibility from "./compatibility.js";
|
||||
import { ApiError } from "./error.js";
|
||||
import { apiLogger } from "./logger.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
|
||||
const accessDenied = {
|
||||
message: "Access denied.",
|
||||
|
|
|
@ -2,6 +2,7 @@ import config from "@/config/index.js";
|
|||
import { Meta } from "@/models/entities/meta.js";
|
||||
import { insertModerationLog } from "@/services/insert-moderation-log.js";
|
||||
import { db } from "@/db/postgre.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
||||
export const meta = {
|
||||
|
@ -120,6 +121,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
} else {
|
||||
await transactionalEntityManager.save(Meta, set);
|
||||
}
|
||||
// update meta cache
|
||||
fetchMeta(true);
|
||||
});
|
||||
insertModerationLog(me, "updateMeta");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import config from "@/config/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Meta } from "@/models/entities/meta.js";
|
||||
import { insertModerationLog } from "@/services/insert-moderation-log.js";
|
||||
import { db } from "@/db/postgre.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
||||
export const meta = {
|
||||
|
@ -571,6 +572,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
} else {
|
||||
await transactionalEntityManager.save(Meta, set);
|
||||
}
|
||||
// update meta cache
|
||||
fetchMeta(true);
|
||||
});
|
||||
|
||||
insertModerationLog(me, "updateMeta");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// import { IsNull } from 'typeorm';
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
||||
export const meta = {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// import { IsNull } from 'typeorm';
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
||||
export const meta = {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { DriveFiles } from "@/models/index.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { addFile } from "@/services/drive/add-file.js";
|
|||
import { DriveFiles } from "@/models/index.js";
|
||||
import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js";
|
||||
import { IdentifiableError } from "@/misc/identifiable-error.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { MINUTE } from "@/const.js";
|
||||
import define from "@/server/api/define.js";
|
||||
import { apiLogger } from "@/server/api/logger.js";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { Instances } from "@/models/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { sqlLikeEscape } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Brackets } from "typeorm";
|
||||
import define from "@/server/api/define.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { Notes } from "@/models/index.js";
|
||||
import type { Note } from "@/models/entities/note.js";
|
||||
import { safeForSql } from "backend-rs";
|
||||
|
|
|
@ -3,7 +3,7 @@ import { createImportPostsJob } from "@/queue/index.js";
|
|||
import { ApiError } from "@/server/api/error.js";
|
||||
import { DriveFiles } from "@/models/index.js";
|
||||
import { DAY } from "@/const.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
|
||||
export const meta = {
|
||||
secure: true,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import JSON5 from "json5";
|
||||
import { IsNull, MoreThan } from "typeorm";
|
||||
import config from "@/config/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { Ads, Emojis, Users } from "@/models/index.js";
|
||||
import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { Notes } from "@/models/index.js";
|
||||
import { activeUsersChart } from "@/services/chart/index.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Brackets } from "typeorm";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { Followings, Notes } from "@/models/index.js";
|
||||
import { activeUsersChart } from "@/services/chart/index.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Brackets } from "typeorm";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { Notes } from "@/models/index.js";
|
||||
import { activeUsersChart } from "@/services/chart/index.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Brackets } from "typeorm";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { Notes } from "@/models/index.js";
|
||||
import { activeUsersChart } from "@/services/chart/index.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { IsNull } from "typeorm";
|
||||
import { Users } from "@/models/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { stringToAcct } from "backend-rs";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// import { IsNull } from 'typeorm';
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
||||
export const meta = {
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as os from "node:os";
|
|||
import si from "systeminformation";
|
||||
import define from "@/server/api/define.js";
|
||||
// import meilisearch from "@/db/meilisearch.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
|
||||
export const meta = {
|
||||
requireCredential: false,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { genId } from "@/misc/gen-id.js";
|
||||
import { SwSubscriptions } from "@/models/index.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
|
|
@ -4,7 +4,7 @@ import { publishAdminStream } from "@/services/stream.js";
|
|||
import { AbuseUserReports, UserProfiles, Users } from "@/models/index.js";
|
||||
import { genId } from "@/misc/gen-id.js";
|
||||
import { sendEmail } from "@/services/send-email.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { getUser } from "@/server/api/common/getters.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Entity } from "megalodon";
|
||||
import config from "@/config/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { MAX_NOTE_TEXT_LENGTH, FILE_TYPE_BROWSERSAFE } from "@/const.js";
|
||||
|
||||
export async function getInstance(
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
convertPoll,
|
||||
convertStatus,
|
||||
} from "../converters.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
|
||||
function normalizeQuery(data: any) {
|
||||
const str = querystring.stringify(data);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type Koa from "koa";
|
||||
import rndstr from "rndstr";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { verifyHcaptcha, verifyRecaptcha } from "@/misc/captcha.js";
|
||||
import { Users, RegistrationTickets, UserPendings } from "@/models/index.js";
|
||||
import { signup } from "@/server/api/common/signup.js";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Channel from "../channel.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
||||
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Channel from "../channel.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
||||
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Channel from "../channel.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
||||
import type { Packed } from "@/misc/schema.js";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Channel from "../channel.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
||||
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
||||
|
|
|
@ -16,7 +16,7 @@ import { IsNull } from "typeorm";
|
|||
import config from "@/config/index.js";
|
||||
import Logger from "@/services/logger.js";
|
||||
import { Users } from "@/models/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { genIdenticon } from "@/misc/gen-identicon.js";
|
||||
import { createTemp } from "@/misc/create-temp.js";
|
||||
import { stringToAcct } from "backend-rs";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Router from "@koa/router";
|
||||
import config from "@/config/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { Users, Notes } from "@/models/index.js";
|
||||
import { IsNull, MoreThan } from "typeorm";
|
||||
import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js";
|
||||
|
|
|
@ -16,7 +16,8 @@ import { BullAdapter } from "@bull-board/api/bullAdapter.js";
|
|||
import { KoaAdapter } from "@bull-board/koa";
|
||||
|
||||
import { In, IsNull } from "typeorm";
|
||||
import { fetchMeta, metaToPugArgs } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { metaToPugArgs } from "backend-rs";
|
||||
import config from "@/config/index.js";
|
||||
import {
|
||||
Users,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type Koa from "koa";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import config from "@/config/index.js";
|
||||
import manifest from "./manifest.json" assert { type: "json" };
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type Koa from "koa";
|
||||
import summaly from "summaly";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import Logger from "@/services/logger.js";
|
||||
import config from "@/config/index.js";
|
||||
import { query } from "@/prelude/url.js";
|
||||
|
|
|
@ -72,8 +72,8 @@ html
|
|||
div#splash
|
||||
img#splashIcon(src= splashIcon || `/static-assets/splash.svg?${ timestamp }`)
|
||||
span#splashText
|
||||
block randomMOTD
|
||||
= randomMOTD
|
||||
block randomMotd
|
||||
= randomMotd
|
||||
div#splashSpinner
|
||||
<svg class="spinner bg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="matrix(1,0,0,1,12,12)">
|
||||
|
|
|
@ -6,7 +6,7 @@ import type S3 from "aws-sdk/clients/s3.js"; // TODO: migrate to SDK v3
|
|||
import sharp from "sharp";
|
||||
import { IsNull } from "typeorm";
|
||||
import { publishMainStream, publishDriveStream } from "@/services/stream.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { contentDisposition } from "@/misc/content-disposition.js";
|
||||
import { getFileInfo } from "@/misc/get-file-info.js";
|
||||
import {
|
||||
|
|
|
@ -2,7 +2,7 @@ import type { DriveFile } from "@/models/entities/drive-file.js";
|
|||
import { InternalStorage } from "./internal-storage.js";
|
||||
import { DriveFiles } from "@/models/index.js";
|
||||
import { createDeleteObjectStorageFileJob } from "@/queue/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import { getS3 } from "./s3.js";
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js
|
|||
import { checkHitAntenna } from "@/misc/check-hit-antenna.js";
|
||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
||||
import { addNoteToAntenna } from "@/services/add-note-to-antenna.js";
|
||||
import { countSameRenotes } from "@/misc/count-same-renotes.js";
|
||||
import { otherRenoteByUserExists } from "@/misc/backend-rs.js";
|
||||
import { deliverToRelays, getCachedRelays } from "../relay.js";
|
||||
import type { Channel } from "@/models/entities/channel.js";
|
||||
import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
||||
|
@ -412,7 +412,7 @@ export default async (
|
|||
if (
|
||||
data.renote &&
|
||||
!user.isBot &&
|
||||
(await countSameRenotes(user.id, data.renote.id, note.id)) === 0
|
||||
!(await otherRenoteByUserExists(user.id, data.renote.id, note.id))
|
||||
) {
|
||||
incRenoteCount(data.renote);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
deliverToFollowers,
|
||||
deliverToUser,
|
||||
} from "@/remote/activitypub/deliver-manager.js";
|
||||
import { countSameRenotes } from "@/misc/count-same-renotes.js";
|
||||
import { otherRenoteByUserExists } from "@/misc/backend-rs.js";
|
||||
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
||||
import { deliverToRelays } from "@/services/relay.js";
|
||||
// import meilisearch from "@/db/meilisearch.js";
|
||||
|
@ -34,7 +34,7 @@ export default async function (
|
|||
// この投稿を除く指定したユーザーによる指定したノートのリノートが存在しないとき
|
||||
if (
|
||||
note.renoteId &&
|
||||
(await countSameRenotes(user.id, note.renoteId, note.id)) === 0 &&
|
||||
!(await otherRenoteByUserExists(user.id, note.renoteId, note.id)) &&
|
||||
deleteFromDb
|
||||
) {
|
||||
Notes.decrement({ id: note.renoteId }, "renoteCount", 1);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import push from "web-push";
|
||||
import config from "@/config/index.js";
|
||||
import { SwSubscriptions } from "@/models/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import type { Packed } from "@/misc/schema.js";
|
||||
import { getNoteSummary } from "@/misc/get-note-summary.js";
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as nodemailer from "nodemailer";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
import Logger from "@/services/logger.js";
|
||||
import config from "@/config/index.js";
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { validate as validateEmail } from "deep-email-validator";
|
||||
import { UserProfiles } from "@/models/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta } from "@/misc/backend-rs.js";
|
||||
|
||||
export async function validateEmailForAccount(emailAddress: string): Promise<{
|
||||
available: boolean;
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
"city-timezones": "1.2.1",
|
||||
"compare-versions": "6.1.0",
|
||||
"cropperjs": "2.0.0-beta.4",
|
||||
"date-fns": "3.3.0",
|
||||
"date-fns": "3.3.1",
|
||||
"emojilib": "^3.0.11",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-plugin-file-progress": "1.3.0",
|
||||
|
@ -76,7 +76,7 @@
|
|||
"swiper": "11.0.5",
|
||||
"syuilo-password-strength": "0.0.1",
|
||||
"textarea-caret": "3.1.0",
|
||||
"three": "0.160.0",
|
||||
"three": "0.160.1",
|
||||
"throttle-debounce": "5.0.0",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tinyld": "^1.3.4",
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
import Prism from "prismjs";
|
||||
import { computed, ref } from "vue";
|
||||
import Prism, { loadLanguage } from "@/scripts/prism";
|
||||
import "prismjs/themes/prism-okaidia.css";
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -17,9 +17,24 @@ const props = defineProps<{
|
|||
inline?: boolean;
|
||||
}>();
|
||||
|
||||
const prismLang = computed(() =>
|
||||
Prism.languages[props.lang] ? props.lang : "plaintext",
|
||||
// fallback to "plaintext" if language not loaded
|
||||
const prismLang = ref(
|
||||
props.lang != null && props.lang in Prism.languages
|
||||
? props.lang
|
||||
: "plaintext",
|
||||
);
|
||||
|
||||
// try to load language asynchronously
|
||||
if (props.lang != null && !(props.lang in Prism.languages)) {
|
||||
const { lang } = props;
|
||||
loadLanguage(props.lang).then(
|
||||
// onLoaded
|
||||
() => (prismLang.value = lang),
|
||||
// onError
|
||||
() => {},
|
||||
);
|
||||
}
|
||||
|
||||
const html = computed(() =>
|
||||
Prism.highlight(
|
||||
props.code,
|
||||
|
|
|
@ -309,9 +309,9 @@
|
|||
}}</span></FormSwitch
|
||||
>
|
||||
<FormSwitch v-model="useEmojiCdn" class="_formBlock"
|
||||
>{{ i18n.ts.useEmojiCdn
|
||||
>{{ i18n.ts.useCdn
|
||||
}}<template #caption>{{
|
||||
i18n.ts.useEmojiCdnDescription
|
||||
i18n.ts.useCdnDescription
|
||||
}}</template></FormSwitch
|
||||
>
|
||||
<FormSwitch
|
||||
|
|
29
packages/client/src/scripts/prism.ts
Normal file
29
packages/client/src/scripts/prism.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import Prism from "prismjs";
|
||||
import "prismjs/plugins/autoloader/prism-autoloader.js";
|
||||
import { defaultStore } from "@/store";
|
||||
|
||||
// TODO
|
||||
Prism.plugins.autoloader.languages_path =
|
||||
"https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/";
|
||||
|
||||
const nonExistingLanguagesCache = new Set<string>();
|
||||
export const loadLanguage = (lang: string) =>
|
||||
new Promise<void>((resolve, reject) => {
|
||||
// for now
|
||||
if (!defaultStore.state.useEmojiCdn) return resolve();
|
||||
// cached non-existing language
|
||||
if (nonExistingLanguagesCache.has(lang)) return reject();
|
||||
// load language with autoloader
|
||||
Prism.plugins.autoloader.loadLanguages(
|
||||
lang,
|
||||
// loaded
|
||||
() => resolve(),
|
||||
// failed
|
||||
() => {
|
||||
nonExistingLanguagesCache.add(lang);
|
||||
reject();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
export default Prism;
|
|
@ -18,10 +18,10 @@
|
|||
"url": "https://code.naskya.net/naskya/firefish"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@swc/cli": "0.1.64",
|
||||
"@swc/cli": "0.1.65",
|
||||
"@swc/core": "1.3.105",
|
||||
"@swc/types": "0.1.5",
|
||||
"@types/node": "20.11.5",
|
||||
"@types/node": "20.11.6",
|
||||
"ts-node": "10.9.2",
|
||||
"tsd": "0.30.4",
|
||||
"typescript": "5.3.3"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"format": "pnpm biome format * --write"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@swc/cli": "0.1.64",
|
||||
"@swc/cli": "0.1.65",
|
||||
"@swc/core": "1.3.105",
|
||||
"@swc/core-android-arm64": "1.3.11",
|
||||
"firefish-js": "workspace:*",
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
"isolatedModules": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"],
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"typeRoots": [
|
||||
"node_modules/@types",
|
||||
|
|
361
pnpm-lock.yaml
361
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue