refactor: move misc/check-word-mute.ts to backend-rs
Co-authored-by: sup39 <dev@sup39.dev>
This commit is contained in:
parent
45a65d156e
commit
1f37c0c5a3
29 changed files with 416 additions and 415 deletions
|
@ -1413,6 +1413,7 @@ _menuDisplay:
|
||||||
hide: "Hide"
|
hide: "Hide"
|
||||||
_wordMute:
|
_wordMute:
|
||||||
muteWords: "Muted words"
|
muteWords: "Muted words"
|
||||||
|
mutePatterns: "Muted patterns"
|
||||||
muteLangs: "Muted Languages"
|
muteLangs: "Muted Languages"
|
||||||
muteWordsDescription: "Separate with spaces for an AND condition or with line breaks
|
muteWordsDescription: "Separate with spaces for an AND condition or with line breaks
|
||||||
for an OR condition."
|
for an OR condition."
|
||||||
|
|
|
@ -1221,6 +1221,7 @@ _menuDisplay:
|
||||||
hide: "隠す"
|
hide: "隠す"
|
||||||
_wordMute:
|
_wordMute:
|
||||||
muteWords: "ミュートするワード"
|
muteWords: "ミュートするワード"
|
||||||
|
mutePatterns: "ミュートするパターン"
|
||||||
muteLangs: "ミュートされた言語"
|
muteLangs: "ミュートされた言語"
|
||||||
muteWordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります。"
|
muteWordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります。"
|
||||||
muteWordsDescription2: "キーワードをスラッシュで囲むと正規表現になります。"
|
muteWordsDescription2: "キーワードをスラッシュで囲むと正規表現になります。"
|
||||||
|
|
|
@ -295,7 +295,7 @@ if (!nativeBinding) {
|
||||||
throw new Error(`Failed to load native binding`)
|
throw new Error(`Failed to load native binding`)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, hasOtherRenoteOfThisNote, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, genString, IdConvertType, convertId } = nativeBinding
|
const { EnvConfig, readEnvironmentConfig, readServerConfig, JsDbConn, connectToDatabase, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, extractHost, toPuny, toPunyOptional, convertToHiddenPost, sqlLikeEscape, safeForSql, formatMilliseconds, nativeInitIdGenerator, nativeCreateId, nativeGetTimestamp, fetchMeta, metaToPugArgs, hasOtherRenoteOfThisNote, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, genString, IdConvertType, convertId } = nativeBinding
|
||||||
|
|
||||||
module.exports.EnvConfig = EnvConfig
|
module.exports.EnvConfig = EnvConfig
|
||||||
module.exports.readEnvironmentConfig = readEnvironmentConfig
|
module.exports.readEnvironmentConfig = readEnvironmentConfig
|
||||||
|
@ -314,6 +314,7 @@ module.exports.UserProfileFfvisibilityEnum = UserProfileFfvisibilityEnum
|
||||||
module.exports.UserProfileMutingnotificationtypesEnum = UserProfileMutingnotificationtypesEnum
|
module.exports.UserProfileMutingnotificationtypesEnum = UserProfileMutingnotificationtypesEnum
|
||||||
module.exports.stringToAcct = stringToAcct
|
module.exports.stringToAcct = stringToAcct
|
||||||
module.exports.acctToString = acctToString
|
module.exports.acctToString = acctToString
|
||||||
|
module.exports.checkWordMute = checkWordMute
|
||||||
module.exports.getFullApAccount = getFullApAccount
|
module.exports.getFullApAccount = getFullApAccount
|
||||||
module.exports.isSelfHost = isSelfHost
|
module.exports.isSelfHost = isSelfHost
|
||||||
module.exports.extractHost = extractHost
|
module.exports.extractHost = extractHost
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
DELETE FROM "migrations" WHERE name IN (
|
DELETE FROM "migrations" WHERE name IN (
|
||||||
|
'SeparateHardMuteWordsAndPatterns1706413792769',
|
||||||
'RenameMetaColumns1705944717480',
|
'RenameMetaColumns1705944717480',
|
||||||
'RemoveNativeUtilsMigration1705877093218',
|
'RemoveNativeUtilsMigration1705877093218',
|
||||||
'DropTimeZone1705691683091',
|
'DropTimeZone1705691683091',
|
||||||
|
@ -12,6 +13,10 @@ DELETE FROM "migrations" WHERE name IN (
|
||||||
'EmojiModerator1692825433698'
|
'EmojiModerator1692825433698'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- separate-hard-mute-words-and-patterns
|
||||||
|
UPDATE "user_profile" SET "mutedWords" = "mutedWords" || array_to_json("mutedPatterns")::jsonb;
|
||||||
|
ALTER TABLE "user_profile" DROP "mutedPatterns";
|
||||||
|
|
||||||
-- rename-meta-columns
|
-- rename-meta-columns
|
||||||
ALTER TABLE "meta" RENAME COLUMN "tosUrl" TO "ToSUrl";
|
ALTER TABLE "meta" RENAME COLUMN "tosUrl" TO "ToSUrl";
|
||||||
ALTER TABLE "meta" RENAME COLUMN "objectStorageUseSsl" TO "objectStorageUseSSL";
|
ALTER TABLE "meta" RENAME COLUMN "objectStorageUseSsl" TO "objectStorageUseSSL";
|
||||||
|
|
20
packages/backend-rs/Cargo.lock
generated
20
packages/backend-rs/Cargo.lock
generated
|
@ -94,9 +94,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle"
|
name = "anstyle"
|
||||||
version = "1.0.4"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
|
checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-parse"
|
name = "anstyle-parse"
|
||||||
|
@ -1118,9 +1118,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.1.0"
|
version = "2.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.14.3",
|
"hashbrown 0.14.3",
|
||||||
|
@ -1163,9 +1163,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.12.0"
|
version = "0.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
@ -2221,9 +2221,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.112"
|
version = "1.0.113"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d1bd37ce2324cf3bf85e5a25f96eb4baf0d5aa6eba43e7ae8958870c4ec48ed"
|
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
|
@ -2244,9 +2244,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_yaml"
|
name = "serde_yaml"
|
||||||
version = "0.9.30"
|
version = "0.9.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38"
|
checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"itoa",
|
"itoa",
|
||||||
|
|
|
@ -73,6 +73,8 @@ pub struct Model {
|
||||||
pub prevent_ai_learning: bool,
|
pub prevent_ai_learning: bool,
|
||||||
#[sea_orm(column_name = "isIndexable")]
|
#[sea_orm(column_name = "isIndexable")]
|
||||||
pub is_indexable: bool,
|
pub is_indexable: bool,
|
||||||
|
#[sea_orm(column_name = "mutedPatterns")]
|
||||||
|
pub muted_patterns: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
|
114
packages/backend-rs/src/util/check_word_mute.rs
Normal file
114
packages/backend-rs/src/util/check_word_mute.rs
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
use crate::database::JsDbConn;
|
||||||
|
use crate::model::entity::{drive_file, note};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use regex::Regex;
|
||||||
|
use sea_orm::prelude::*;
|
||||||
|
|
||||||
|
// FIXME: remove this type
|
||||||
|
#[napi_derive::napi(object)]
|
||||||
|
pub struct NoteLike {
|
||||||
|
pub file_ids: Vec<String>,
|
||||||
|
pub user_id: Option<String>,
|
||||||
|
pub text: Option<String>,
|
||||||
|
pub cw: Option<String>,
|
||||||
|
pub renote_id: Option<String>,
|
||||||
|
pub reply_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn full_text(conn: &JsDbConn, note: NoteLike) -> String {
|
||||||
|
let mut to_return = format!(
|
||||||
|
"{}\n{}\n",
|
||||||
|
note.text.unwrap_or_default(),
|
||||||
|
note.cw.unwrap_or_default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
for file_id in note.file_ids {
|
||||||
|
if let Some(alt_text) = drive_file::Entity::find_by_id(file_id)
|
||||||
|
.one(conn.inner())
|
||||||
|
.await
|
||||||
|
.expect("Failed to connect to the database")
|
||||||
|
.expect("file_id is invalid")
|
||||||
|
.comment
|
||||||
|
{
|
||||||
|
to_return.push_str(alt_text.as_str());
|
||||||
|
to_return.push('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if note.renote_id.is_some() {
|
||||||
|
to_return.push_str(
|
||||||
|
note::Entity::find_by_id(note.renote_id.unwrap())
|
||||||
|
.one(conn.inner())
|
||||||
|
.await
|
||||||
|
.expect("Failed to connect to the database")
|
||||||
|
.expect("renote_id is invalid")
|
||||||
|
.text
|
||||||
|
.unwrap_or_default()
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
|
to_return.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
if note.reply_id.is_some() {
|
||||||
|
to_return.push_str(
|
||||||
|
note::Entity::find_by_id(note.reply_id.unwrap())
|
||||||
|
.one(conn.inner())
|
||||||
|
.await
|
||||||
|
.expect("Failed to connect to the database")
|
||||||
|
.expect("reply_id is invalid")
|
||||||
|
.text
|
||||||
|
.unwrap_or_default()
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
to_return.trim().to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: remove this funtion
|
||||||
|
fn convert_regex(js_regex: String) -> String {
|
||||||
|
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"^/(.+)/(.*)$").unwrap());
|
||||||
|
RE.replace(&js_regex, "(?$2)$1").to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn check_word_mute_impl(
|
||||||
|
text: String,
|
||||||
|
muted_word_lists: Vec<Vec<String>>,
|
||||||
|
muted_patterns: Vec<String>,
|
||||||
|
) -> bool {
|
||||||
|
if text.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let text_lowercase = text.to_lowercase();
|
||||||
|
|
||||||
|
muted_word_lists.into_iter().any(|muted_word_list| {
|
||||||
|
muted_word_list
|
||||||
|
.into_iter()
|
||||||
|
.all(|muted_word| text_lowercase.contains(&muted_word.to_lowercase()))
|
||||||
|
}) || muted_patterns.into_iter().any(|muted_patten| {
|
||||||
|
match Regex::new(convert_regex(muted_patten).as_str()) {
|
||||||
|
Ok(re) => re.is_match(&text),
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[napi_derive::napi]
|
||||||
|
pub async fn check_word_mute(
|
||||||
|
conn: &JsDbConn,
|
||||||
|
note: NoteLike,
|
||||||
|
muted_word_lists: Vec<Vec<String>>,
|
||||||
|
muted_patterns: Vec<String>,
|
||||||
|
) -> bool {
|
||||||
|
if muted_word_lists.is_empty() && muted_patterns.is_empty() {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
check_word_mute_impl(
|
||||||
|
full_text(conn, note).await,
|
||||||
|
muted_word_lists,
|
||||||
|
muted_patterns,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod acct;
|
pub mod acct;
|
||||||
|
pub mod check_word_mute;
|
||||||
pub mod convert_host;
|
pub mod convert_host;
|
||||||
pub mod convert_to_hidden_post;
|
pub mod convert_to_hidden_post;
|
||||||
pub mod escape_sql;
|
pub mod escape_sql;
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
export class SeparateHardMuteWordsAndPatterns1706413792769 {
|
||||||
|
name = "SeparateHardMuteWordsAndPatterns1706413792769";
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "user_profile" ADD "mutedPatterns" text[] DEFAULT '{}'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`
|
||||||
|
UPDATE "user_profile" SET
|
||||||
|
"mutedPatterns" = ARRAY(
|
||||||
|
SELECT jsonb_array_elements_text(jsonb_path_query_array(
|
||||||
|
"mutedWords",
|
||||||
|
'$ ? (@.type() == "string")'
|
||||||
|
))
|
||||||
|
),
|
||||||
|
"mutedWords" = jsonb_path_query_array(
|
||||||
|
"mutedWords",
|
||||||
|
'$ ? (@.type() == "array")'
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "user_profile" ALTER "mutedPatterns" SET NOT NULL`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(
|
||||||
|
`UPDATE "user_profile" SET "mutedWords" = "mutedWords" || array_to_json("mutedPatterns")::jsonb`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP "mutedPatterns"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
import RE2 from "re2";
|
|
||||||
|
|
||||||
export class convertHardMutes1644010796173 {
|
export class convertHardMutes1644010796173 {
|
||||||
name = "convertHardMutes1644010796173";
|
name = "convertHardMutes1644010796173";
|
||||||
|
|
||||||
|
@ -15,7 +13,7 @@ export class convertHardMutes1644010796173 {
|
||||||
if (regexp) {
|
if (regexp) {
|
||||||
// convert regexp's
|
// convert regexp's
|
||||||
try {
|
try {
|
||||||
new RE2(regexp[1], regexp[2]);
|
new RegExp(regexp[1], regexp[2]);
|
||||||
return `/${regexp[1]}/${regexp[2]}`;
|
return `/${regexp[1]}/${regexp[2]}`;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// invalid regex, ignore it
|
// invalid regex, ignore it
|
||||||
|
|
|
@ -98,7 +98,6 @@
|
||||||
"qs": "6.11.2",
|
"qs": "6.11.2",
|
||||||
"random-seed": "0.3.0",
|
"random-seed": "0.3.0",
|
||||||
"ratelimiter": "3.4.1",
|
"ratelimiter": "3.4.1",
|
||||||
"re2": "1.20.9",
|
|
||||||
"redis-semaphore": "5.5.0",
|
"redis-semaphore": "5.5.0",
|
||||||
"reflect-metadata": "0.2.1",
|
"reflect-metadata": "0.2.1",
|
||||||
"rename": "1.0.4",
|
"rename": "1.0.4",
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {
|
||||||
readServerConfig,
|
readServerConfig,
|
||||||
readEnvironmentConfig,
|
readEnvironmentConfig,
|
||||||
connectToDatabase,
|
connectToDatabase,
|
||||||
|
checkWordMute as checkWordMuteImpl,
|
||||||
fetchMeta as fetchMetaImpl,
|
fetchMeta as fetchMetaImpl,
|
||||||
hasOtherRenoteOfThisNote as hasOtherRenoteOfThisNoteImpl,
|
hasOtherRenoteOfThisNote as hasOtherRenoteOfThisNoteImpl,
|
||||||
JsDbConn,
|
JsDbConn,
|
||||||
|
@ -20,3 +21,4 @@ const curryDb =
|
||||||
|
|
||||||
export const fetchMeta = curryDb(fetchMetaImpl);
|
export const fetchMeta = curryDb(fetchMetaImpl);
|
||||||
export const hasOtherRenoteOfThisNote = curryDb(hasOtherRenoteOfThisNoteImpl);
|
export const hasOtherRenoteOfThisNote = curryDb(hasOtherRenoteOfThisNoteImpl);
|
||||||
|
export const checkWordMute = curryDb(checkWordMuteImpl);
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
import type { Antenna } from "@/models/entities/antenna.js";
|
import type { Antenna } from "@/models/entities/antenna.js";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type { Note } from "@/models/entities/note.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
|
import type { UserProfile } from "@/models/entities/user-profile.js";
|
||||||
import { Blockings, Followings, UserProfiles } from "@/models/index.js";
|
import { Blockings, Followings, UserProfiles } from "@/models/index.js";
|
||||||
import { getFullApAccount, stringToAcct } from "backend-rs";
|
import { getFullApAccount, stringToAcct } from "backend-rs";
|
||||||
|
import { checkWordMute } from "@/misc/backend-rs.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type { Packed } from "@/misc/schema.js";
|
||||||
import { Cache } from "@/misc/cache.js";
|
import { Cache } from "@/misc/cache.js";
|
||||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
|
||||||
|
|
||||||
const blockingCache = new Cache<User["id"][]>("blocking", 60 * 5);
|
const blockingCache = new Cache<User["id"][]>("blocking", 60 * 5);
|
||||||
const mutedWordsCache = new Cache<string[][] | undefined>("mutedWords", 60 * 5);
|
const hardMutesCache = new Cache<{
|
||||||
|
userId: UserProfile["userId"];
|
||||||
|
mutedWords: UserProfile["mutedWords"];
|
||||||
|
mutedPatterns: UserProfile["mutedPatterns"];
|
||||||
|
}>("hardMutes", 60 * 5);
|
||||||
const followingCache = new Cache<User["id"][]>("following", 60 * 5);
|
const followingCache = new Cache<User["id"][]>("following", 60 * 5);
|
||||||
|
|
||||||
export async function checkHitAntenna(
|
export async function checkHitAntenna(
|
||||||
|
@ -103,12 +108,24 @@ export async function checkHitAntenna(
|
||||||
if (!following.includes(note.userId)) return false;
|
if (!following.includes(note.userId)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mutedWords = await mutedWordsCache.fetch(antenna.userId, () =>
|
const mutes = await hardMutesCache.fetch(antenna.userId, () =>
|
||||||
UserProfiles.findOneBy({ userId: antenna.userId }).then(
|
UserProfiles.findOneByOrFail({
|
||||||
(profile) => profile?.mutedWords,
|
userId: antenna.userId,
|
||||||
),
|
}).then((profile) => {
|
||||||
|
return {
|
||||||
|
userId: antenna.userId,
|
||||||
|
mutedWords: profile.mutedWords,
|
||||||
|
mutedPatterns: profile.mutedPatterns,
|
||||||
|
};
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
if (await getWordHardMute(note, antenna.userId, mutedWords)) return false;
|
if (
|
||||||
|
mutes.mutedWords != null &&
|
||||||
|
mutes.mutedPatterns != null &&
|
||||||
|
antenna.userId !== note.userId &&
|
||||||
|
(await checkWordMute(note, mutes.mutedWords, mutes.mutedPatterns))
|
||||||
|
)
|
||||||
|
return false;
|
||||||
|
|
||||||
// TODO: eval expression
|
// TODO: eval expression
|
||||||
|
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
import RE2 from "re2";
|
|
||||||
import type { Note } from "@/models/entities/note.js";
|
|
||||||
|
|
||||||
type NoteLike = {
|
|
||||||
userId: Note["userId"];
|
|
||||||
text: Note["text"];
|
|
||||||
files?: Note["files"];
|
|
||||||
cw?: Note["cw"];
|
|
||||||
};
|
|
||||||
|
|
||||||
function checkWordMute(
|
|
||||||
note: NoteLike,
|
|
||||||
mutedWords: Array<string | string[]>,
|
|
||||||
): boolean {
|
|
||||||
if (note == null) return false;
|
|
||||||
|
|
||||||
let text = `${note.cw ?? ""} ${note.text ?? ""}`;
|
|
||||||
if (note.files != null)
|
|
||||||
text += ` ${note.files.map((f) => f.comment ?? "").join(" ")}`;
|
|
||||||
text = text.trim();
|
|
||||||
|
|
||||||
if (text === "") return false;
|
|
||||||
|
|
||||||
for (const mutePattern of mutedWords) {
|
|
||||||
if (Array.isArray(mutePattern)) {
|
|
||||||
// Clean up
|
|
||||||
const keywords = mutePattern.filter((keyword) => keyword !== "");
|
|
||||||
|
|
||||||
if (
|
|
||||||
keywords.length > 0 &&
|
|
||||||
keywords.every((keyword) =>
|
|
||||||
text.toLowerCase().includes(keyword.toLowerCase()),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// represents RegExp
|
|
||||||
const regexp = mutePattern.match(/^\/(.+)\/(.*)$/);
|
|
||||||
|
|
||||||
// This should never happen due to input sanitisation.
|
|
||||||
if (!regexp) {
|
|
||||||
console.warn(`Found invalid regex in word mutes: ${mutePattern}`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (new RE2(regexp[1], regexp[2]).test(text)) return true;
|
|
||||||
} catch (err) {
|
|
||||||
// This should never happen due to input sanitisation.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getWordHardMute(
|
|
||||||
note: NoteLike,
|
|
||||||
meId: string | null | undefined,
|
|
||||||
mutedWords?: Array<string | string[]>,
|
|
||||||
): Promise<boolean> {
|
|
||||||
if (note.userId === meId || mutedWords == null) return false;
|
|
||||||
|
|
||||||
if (mutedWords.length > 0) {
|
|
||||||
return (
|
|
||||||
checkWordMute(note, mutedWords) ||
|
|
||||||
checkWordMute(note.reply, mutedWords) ||
|
|
||||||
checkWordMute(note.renote, mutedWords)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
|
@ -223,6 +223,12 @@ export class UserProfile {
|
||||||
})
|
})
|
||||||
public mutedWords: string[][];
|
public mutedWords: string[][];
|
||||||
|
|
||||||
|
@Column("text", {
|
||||||
|
array: true,
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public mutedPatterns: string[];
|
||||||
|
|
||||||
@Column("jsonb", {
|
@Column("jsonb", {
|
||||||
default: [],
|
default: [],
|
||||||
comment: "List of instances muted by the user.",
|
comment: "List of instances muted by the user.",
|
||||||
|
|
|
@ -573,6 +573,7 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
hasPendingReceivedFollowRequest:
|
hasPendingReceivedFollowRequest:
|
||||||
this.getHasPendingReceivedFollowRequest(user.id),
|
this.getHasPendingReceivedFollowRequest(user.id),
|
||||||
mutedWords: profile?.mutedWords,
|
mutedWords: profile?.mutedWords,
|
||||||
|
mutedPatterns: profile?.mutedPatterns,
|
||||||
mutedInstances: profile?.mutedInstances,
|
mutedInstances: profile?.mutedInstances,
|
||||||
mutingNotificationTypes: profile?.mutingNotificationTypes,
|
mutingNotificationTypes: profile?.mutingNotificationTypes,
|
||||||
emailNotificationTypes: profile?.emailNotificationTypes,
|
emailNotificationTypes: profile?.emailNotificationTypes,
|
||||||
|
|
|
@ -474,6 +474,16 @@ export const packedMeDetailedOnlySchema = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mutedPatterns: {
|
||||||
|
type: "array",
|
||||||
|
nullable: false,
|
||||||
|
optional: false,
|
||||||
|
items: {
|
||||||
|
type: "string",
|
||||||
|
nullable: false,
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
mutedInstances: {
|
mutedInstances: {
|
||||||
type: "array",
|
type: "array",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
|
|
|
@ -61,6 +61,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
injectFeaturedNote: profile.injectFeaturedNote,
|
injectFeaturedNote: profile.injectFeaturedNote,
|
||||||
receiveAnnouncementEmail: profile.receiveAnnouncementEmail,
|
receiveAnnouncementEmail: profile.receiveAnnouncementEmail,
|
||||||
mutedWords: profile.mutedWords,
|
mutedWords: profile.mutedWords,
|
||||||
|
mutedPatterns: profile.mutedPatterns,
|
||||||
mutedInstances: profile.mutedInstances,
|
mutedInstances: profile.mutedInstances,
|
||||||
mutingNotificationTypes: profile.mutingNotificationTypes,
|
mutingNotificationTypes: profile.mutingNotificationTypes,
|
||||||
isModerator: user.isModerator,
|
isModerator: user.isModerator,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import RE2 from "re2";
|
|
||||||
import * as mfm from "mfm-js";
|
import * as mfm from "mfm-js";
|
||||||
import { publishMainStream, publishUserEvent } from "@/services/stream.js";
|
import { publishMainStream, publishUserEvent } from "@/services/stream.js";
|
||||||
import acceptAllFollowRequests from "@/services/following/requests/accept-all.js";
|
import acceptAllFollowRequests from "@/services/following/requests/accept-all.js";
|
||||||
|
@ -126,6 +125,7 @@ export const paramDef = {
|
||||||
ffVisibility: { type: "string", enum: ["public", "followers", "private"] },
|
ffVisibility: { type: "string", enum: ["public", "followers", "private"] },
|
||||||
pinnedPageId: { type: "string", format: "misskey:id", nullable: true },
|
pinnedPageId: { type: "string", format: "misskey:id", nullable: true },
|
||||||
mutedWords: { type: "array" },
|
mutedWords: { type: "array" },
|
||||||
|
mutedPatterns: { type: "array", items: { type: "string" } },
|
||||||
mutedInstances: {
|
mutedInstances: {
|
||||||
type: "array",
|
type: "array",
|
||||||
items: {
|
items: {
|
||||||
|
@ -166,23 +166,52 @@ export default define(meta, paramDef, async (ps, _user, token) => {
|
||||||
profileUpdates.ffVisibility = ps.ffVisibility;
|
profileUpdates.ffVisibility = ps.ffVisibility;
|
||||||
if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId;
|
if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId;
|
||||||
if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId;
|
if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId;
|
||||||
if (ps.mutedWords !== undefined) {
|
if (ps.mutedPatterns !== undefined) {
|
||||||
// validate regular expression syntax
|
for (const item of ps.mutedPatterns) {
|
||||||
ps.mutedWords
|
const regexp = item.match(/^\/(.+)\/(.*)$/);
|
||||||
.filter((x) => !Array.isArray(x))
|
|
||||||
.forEach((x) => {
|
|
||||||
const regexp = x.match(/^\/(.+)\/(.*)$/);
|
|
||||||
if (!regexp) throw new ApiError(meta.errors.invalidRegexp);
|
if (!regexp) throw new ApiError(meta.errors.invalidRegexp);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new RE2(regexp[1], regexp[2]);
|
new RegExp(regexp[1], regexp[2]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new ApiError(meta.errors.invalidRegexp);
|
throw new ApiError(meta.errors.invalidRegexp);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
profileUpdates.mutedWords = ps.mutedWords;
|
profileUpdates.mutedPatterns = profileUpdates.mutedPatterns ?? [];
|
||||||
profileUpdates.enableWordMute = ps.mutedWords.length > 0;
|
profileUpdates.mutedPatterns.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ps.mutedWords !== undefined) {
|
||||||
|
// for compatibility with the upstream Firefish API
|
||||||
|
for (const item of ps.mutedWords) {
|
||||||
|
if (Array.isArray(item)) continue;
|
||||||
|
|
||||||
|
const regexp = item.match(/^\/(.+)\/(.*)$/);
|
||||||
|
if (!regexp) throw new ApiError(meta.errors.invalidRegexp);
|
||||||
|
|
||||||
|
try {
|
||||||
|
new RegExp(regexp[1], regexp[2]);
|
||||||
|
} catch (err) {
|
||||||
|
throw new ApiError(meta.errors.invalidRegexp);
|
||||||
|
}
|
||||||
|
|
||||||
|
profileUpdates.mutedPatterns = profileUpdates.mutedPatterns ?? [];
|
||||||
|
profileUpdates.mutedPatterns.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
profileUpdates.mutedWords = ps.mutedWords.filter((item) =>
|
||||||
|
Array.isArray(item),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
profileUpdates.mutedWords !== undefined ||
|
||||||
|
profileUpdates.mutedPatterns !== undefined
|
||||||
|
) {
|
||||||
|
profileUpdates.enableWordMute =
|
||||||
|
(profileUpdates.mutedWords != null &&
|
||||||
|
profileUpdates.mutedWords.length > 0) ||
|
||||||
|
(profileUpdates.mutedPatterns != null &&
|
||||||
|
profileUpdates.mutedPatterns.length > 0);
|
||||||
}
|
}
|
||||||
if (ps.mutedInstances !== undefined)
|
if (ps.mutedInstances !== undefined)
|
||||||
profileUpdates.mutedInstances = ps.mutedInstances;
|
profileUpdates.mutedInstances = ps.mutedInstances;
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { fileURLToPath } from "node:url";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import translate from "@/misc/translate.js";
|
import translate from "@/misc/translate.js";
|
||||||
import type { Language } from "@/misc/langmap.js";
|
import type { Language } from "@/misc/langmap.js";
|
||||||
import RE2 from "re2";
|
|
||||||
|
|
||||||
const _filename = fileURLToPath(import.meta.url);
|
const _filename = fileURLToPath(import.meta.url);
|
||||||
const _dirname = dirname(_filename);
|
const _dirname = dirname(_filename);
|
||||||
|
@ -37,8 +36,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
async function translateCommitMsg(msg: string, targetLang: Language) {
|
async function translateCommitMsg(msg: string, targetLang: Language) {
|
||||||
const regex = new RE2(/^(.*) (\(by .*\))$/);
|
const matches = msg.match(/^(.*) (\(by .*\))$/);
|
||||||
const matches = regex.match(msg);
|
|
||||||
|
|
||||||
if (matches == null) return msg;
|
if (matches == null) return msg;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import Channel from "../channel.js";
|
import Channel from "../channel.js";
|
||||||
import { fetchMeta } from "@/misc/backend-rs.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 { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
||||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
import { isUserRelated } from "@/misc/is-user-related.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type { Packed } from "@/misc/schema.js";
|
||||||
|
import { checkWordMute } from "@/misc/backend-rs.js";
|
||||||
|
|
||||||
export default class extends Channel {
|
export default class extends Channel {
|
||||||
public readonly chName = "globalTimeline";
|
public readonly chName = "globalTimeline";
|
||||||
|
@ -68,10 +68,15 @@ export default class extends Channel {
|
||||||
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)
|
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)
|
||||||
// 現状では、ワードミュートにおけるMutedNoteレコードの追加処理はストリーミングに流す処理と並列で行われるため、
|
// 現状では、ワードミュートにおけるMutedNoteレコードの追加処理はストリーミングに流す処理と並列で行われるため、
|
||||||
// レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。
|
// レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。
|
||||||
// そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる
|
// そのためレコードが存在するかのチェックでは不十分なので、改めてcheckWordMuteを呼んでいる
|
||||||
if (
|
if (
|
||||||
this.userProfile &&
|
this.userProfile &&
|
||||||
(await getWordHardMute(note, this.user?.id, this.userProfile.mutedWords))
|
this.user?.id !== note.userId &&
|
||||||
|
(await checkWordMute(
|
||||||
|
note,
|
||||||
|
this.userProfile.mutedWords,
|
||||||
|
this.userProfile.mutedPatterns,
|
||||||
|
))
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import Channel from "../channel.js";
|
import Channel from "../channel.js";
|
||||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
|
||||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
import { isUserRelated } from "@/misc/is-user-related.js";
|
||||||
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type { Packed } from "@/misc/schema.js";
|
||||||
|
import { checkWordMute } from "@/misc/backend-rs.js";
|
||||||
|
|
||||||
export default class extends Channel {
|
export default class extends Channel {
|
||||||
public readonly chName = "homeTimeline";
|
public readonly chName = "homeTimeline";
|
||||||
|
@ -65,10 +65,15 @@ export default class extends Channel {
|
||||||
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)
|
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)
|
||||||
// 現状では、ワードミュートにおけるMutedNoteレコードの追加処理はストリーミングに流す処理と並列で行われるため、
|
// 現状では、ワードミュートにおけるMutedNoteレコードの追加処理はストリーミングに流す処理と並列で行われるため、
|
||||||
// レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。
|
// レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。
|
||||||
// そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる
|
// そのためレコードが存在するかのチェックでは不十分なので、改めてcheckWordMuteを呼んでいる
|
||||||
if (
|
if (
|
||||||
this.userProfile &&
|
this.userProfile &&
|
||||||
(await getWordHardMute(note, this.user?.id, this.userProfile.mutedWords))
|
this.user?.id !== note.userId &&
|
||||||
|
(await checkWordMute(
|
||||||
|
note,
|
||||||
|
this.userProfile.mutedWords,
|
||||||
|
this.userProfile.mutedPatterns,
|
||||||
|
))
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import Channel from "../channel.js";
|
import Channel from "../channel.js";
|
||||||
import { fetchMeta } from "@/misc/backend-rs.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 { isUserRelated } from "@/misc/is-user-related.js";
|
||||||
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type { Packed } from "@/misc/schema.js";
|
||||||
|
import { checkWordMute } from "@/misc/backend-rs.js";
|
||||||
|
|
||||||
export default class extends Channel {
|
export default class extends Channel {
|
||||||
public readonly chName = "hybridTimeline";
|
public readonly chName = "hybridTimeline";
|
||||||
|
@ -82,10 +82,15 @@ export default class extends Channel {
|
||||||
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)
|
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)
|
||||||
// 現状では、ワードミュートにおけるMutedNoteレコードの追加処理はストリーミングに流す処理と並列で行われるため、
|
// 現状では、ワードミュートにおけるMutedNoteレコードの追加処理はストリーミングに流す処理と並列で行われるため、
|
||||||
// レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。
|
// レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。
|
||||||
// そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる
|
// そのためレコードが存在するかのチェックでは不十分なので、改めてcheckWordMuteを呼んでいる
|
||||||
if (
|
if (
|
||||||
this.userProfile &&
|
this.userProfile &&
|
||||||
(await getWordHardMute(note, this.user?.id, this.userProfile.mutedWords))
|
this.user?.id !== note.userId &&
|
||||||
|
(await checkWordMute(
|
||||||
|
note,
|
||||||
|
this.userProfile.mutedWords,
|
||||||
|
this.userProfile.mutedPatterns,
|
||||||
|
))
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import Channel from "../channel.js";
|
import Channel from "../channel.js";
|
||||||
import { fetchMeta } from "@/misc/backend-rs.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 { isUserRelated } from "@/misc/is-user-related.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type { Packed } from "@/misc/schema.js";
|
||||||
|
import { checkWordMute } from "@/misc/backend-rs.js";
|
||||||
|
|
||||||
export default class extends Channel {
|
export default class extends Channel {
|
||||||
public readonly chName = "localTimeline";
|
public readonly chName = "localTimeline";
|
||||||
|
@ -60,10 +60,15 @@ export default class extends Channel {
|
||||||
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)
|
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)
|
||||||
// 現状では、ワードミュートにおけるMutedNoteレコードの追加処理はストリーミングに流す処理と並列で行われるため、
|
// 現状では、ワードミュートにおけるMutedNoteレコードの追加処理はストリーミングに流す処理と並列で行われるため、
|
||||||
// レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。
|
// レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。
|
||||||
// そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる
|
// そのためレコードが存在するかのチェックでは不十分なので、改めてcheckWordMuteを呼んでいる
|
||||||
if (
|
if (
|
||||||
this.userProfile &&
|
this.userProfile &&
|
||||||
(await getWordHardMute(note, this.user?.id, this.userProfile.mutedWords))
|
this.user?.id !== note.userId &&
|
||||||
|
(await checkWordMute(
|
||||||
|
note,
|
||||||
|
this.userProfile.mutedWords,
|
||||||
|
this.userProfile.mutedPatterns,
|
||||||
|
))
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import Channel from "../channel.js";
|
import Channel from "../channel.js";
|
||||||
import { fetchMeta } from "@/misc/backend-rs.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 { isUserRelated } from "@/misc/is-user-related.js";
|
||||||
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type { Packed } from "@/misc/schema.js";
|
||||||
|
import { checkWordMute } from "@/misc/backend-rs.js";
|
||||||
|
|
||||||
export default class extends Channel {
|
export default class extends Channel {
|
||||||
public readonly chName = "recommendedTimeline";
|
public readonly chName = "recommendedTimeline";
|
||||||
|
@ -80,10 +80,15 @@ export default class extends Channel {
|
||||||
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)
|
// TODO: 将来的には、単にMutedNoteテーブルにレコードがあるかどうかで判定したい(以下の理由により難しそうではある)
|
||||||
// 現状では、ワードミュートにおけるMutedNoteレコードの追加処理はストリーミングに流す処理と並列で行われるため、
|
// 現状では、ワードミュートにおけるMutedNoteレコードの追加処理はストリーミングに流す処理と並列で行われるため、
|
||||||
// レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。
|
// レコードが追加されるNoteでも追加されるより先にここのストリーミングの処理に到達することが起こる。
|
||||||
// そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる
|
// そのためレコードが存在するかのチェックでは不十分なので、改めてcheckWordMuteを呼んでいる
|
||||||
if (
|
if (
|
||||||
this.userProfile &&
|
this.userProfile &&
|
||||||
(await getWordHardMute(note, this.user?.id, this.userProfile.mutedWords))
|
this.user?.id !== note.userId &&
|
||||||
|
(await checkWordMute(
|
||||||
|
note,
|
||||||
|
this.userProfile.mutedWords,
|
||||||
|
this.userProfile.mutedPatterns,
|
||||||
|
))
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,8 @@ import { Poll } from "@/models/entities/poll.js";
|
||||||
import { createNotification } from "@/services/create-notification.js";
|
import { createNotification } from "@/services/create-notification.js";
|
||||||
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
||||||
import { checkHitAntenna } from "@/misc/check-hit-antenna.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 { addNoteToAntenna } from "@/services/add-note-to-antenna.js";
|
||||||
import { hasOtherRenoteOfThisNote } from "@/misc/backend-rs.js";
|
import { checkWordMute, hasOtherRenoteOfThisNote } from "@/misc/backend-rs.js";
|
||||||
import { deliverToRelays, getCachedRelays } from "../relay.js";
|
import { deliverToRelays, getCachedRelays } from "../relay.js";
|
||||||
import type { Channel } from "@/models/entities/channel.js";
|
import type { Channel } from "@/models/entities/channel.js";
|
||||||
import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
||||||
|
@ -64,9 +63,13 @@ import { redisClient } from "@/db/redis.js";
|
||||||
import { Mutex } from "redis-semaphore";
|
import { Mutex } from "redis-semaphore";
|
||||||
import { langmap } from "@/misc/langmap.js";
|
import { langmap } from "@/misc/langmap.js";
|
||||||
|
|
||||||
const mutedWordsCache = new Cache<
|
const hardMutesCache = new Cache<
|
||||||
{ userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[]
|
{
|
||||||
>("mutedWords", 60 * 5);
|
userId: UserProfile["userId"];
|
||||||
|
mutedWords: UserProfile["mutedWords"];
|
||||||
|
mutedPatterns: UserProfile["mutedPatterns"];
|
||||||
|
}[]
|
||||||
|
>("hardMutes", 60 * 5);
|
||||||
|
|
||||||
type NotificationType = "reply" | "renote" | "quote" | "mention";
|
type NotificationType = "reply" | "renote" | "quote" | "mention";
|
||||||
|
|
||||||
|
@ -357,18 +360,20 @@ export default async (
|
||||||
incNotesCountOfUser(user);
|
incNotesCountOfUser(user);
|
||||||
|
|
||||||
// Word mute
|
// Word mute
|
||||||
mutedWordsCache
|
hardMutesCache
|
||||||
.fetch(null, () =>
|
.fetch(null, () =>
|
||||||
UserProfiles.find({
|
UserProfiles.find({
|
||||||
where: {
|
where: {
|
||||||
enableWordMute: true,
|
enableWordMute: true,
|
||||||
},
|
},
|
||||||
select: ["userId", "mutedWords"],
|
select: ["userId", "mutedWords", "mutedPatterns"],
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.then((us) => {
|
.then((us) => {
|
||||||
for (const u of us) {
|
for (const u of us) {
|
||||||
getWordHardMute(data, u.userId, u.mutedWords).then((shouldMute) => {
|
if (u.userId === user.id) return;
|
||||||
|
checkWordMute(note, u.mutedWords, u.mutedPatterns).then(
|
||||||
|
(shouldMute: boolean) => {
|
||||||
if (shouldMute) {
|
if (shouldMute) {
|
||||||
MutedNotes.insert({
|
MutedNotes.insert({
|
||||||
id: genId(),
|
id: genId(),
|
||||||
|
@ -377,7 +382,8 @@ export default async (
|
||||||
reason: "word",
|
reason: "word",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,15 @@
|
||||||
>
|
>
|
||||||
<FormTextarea v-model="hardMutedWords" class="_formBlock">
|
<FormTextarea v-model="hardMutedWords" class="_formBlock">
|
||||||
<span>{{ i18n.ts._wordMute.muteWords }}</span>
|
<span>{{ i18n.ts._wordMute.muteWords }}</span>
|
||||||
<template #caption
|
<template #caption>{{
|
||||||
>{{ i18n.ts._wordMute.muteWordsDescription }}<br />{{
|
i18n.ts._wordMute.muteWordsDescription
|
||||||
|
}}</template>
|
||||||
|
</FormTextarea>
|
||||||
|
<FormTextarea v-model="hardMutedPatterns" class="_formBlock">
|
||||||
|
<span>{{ i18n.ts._wordMute.mutePatterns }}</span>
|
||||||
|
<template #caption>{{
|
||||||
i18n.ts._wordMute.muteWordsDescription2
|
i18n.ts._wordMute.muteWordsDescription2
|
||||||
}}</template
|
}}</template>
|
||||||
>
|
|
||||||
</FormTextarea>
|
</FormTextarea>
|
||||||
<MkKeyValue
|
<MkKeyValue
|
||||||
v-if="hardWordMutedNotesCount != null"
|
v-if="hardWordMutedNotesCount != null"
|
||||||
|
@ -90,6 +94,7 @@ const tab = ref("soft");
|
||||||
const softMutedWords = ref(render(defaultStore.state.mutedWords));
|
const softMutedWords = ref(render(defaultStore.state.mutedWords));
|
||||||
const softMutedLangs = ref(render(defaultStore.state.mutedLangs));
|
const softMutedLangs = ref(render(defaultStore.state.mutedLangs));
|
||||||
const hardMutedWords = ref(render($i!.mutedWords));
|
const hardMutedWords = ref(render($i!.mutedWords));
|
||||||
|
const hardMutedPatterns = ref($i!.mutedPatterns.join("\n"));
|
||||||
const hardWordMutedNotesCount = ref(null);
|
const hardWordMutedNotesCount = ref(null);
|
||||||
const changed = ref(false);
|
const changed = ref(false);
|
||||||
|
|
||||||
|
@ -109,8 +114,12 @@ watch(hardMutedWords, () => {
|
||||||
changed.value = true;
|
changed.value = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(hardMutedPatterns, () => {
|
||||||
|
changed.value = true;
|
||||||
|
});
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
const parseMutes = (mutes, tab) => {
|
const parseSoftMutes = (mutes, tab) => {
|
||||||
// split into lines, remove empty lines and unnecessary whitespace
|
// split into lines, remove empty lines and unnecessary whitespace
|
||||||
const lines = mutes
|
const lines = mutes
|
||||||
.trim()
|
.trim()
|
||||||
|
@ -151,11 +160,80 @@ async function save() {
|
||||||
return lines;
|
return lines;
|
||||||
};
|
};
|
||||||
|
|
||||||
let softMutes, softMLangs, hardMutes;
|
const parseMutedWords = (mutes) => {
|
||||||
|
// split into lines, remove empty lines and unnecessary whitespace
|
||||||
|
return mutes
|
||||||
|
.trim()
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => line.trim())
|
||||||
|
.filter((line) => line !== "")
|
||||||
|
.map((line) => line.split(" "))
|
||||||
|
.filter((line) => line.length > 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseMutedPatterns = (mutes, tab) => {
|
||||||
|
// split into lines, remove empty lines and unnecessary whitespace
|
||||||
|
const lines = mutes
|
||||||
|
.trim()
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => line.trim())
|
||||||
|
.filter((line) => line !== "");
|
||||||
|
|
||||||
|
// check each line if it is a RegExp or not
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
const line = lines[i];
|
||||||
|
const regexp = line.match(/^\/(.+)\/(.*)$/);
|
||||||
|
if (regexp) {
|
||||||
|
// check that the RegExp is valid
|
||||||
try {
|
try {
|
||||||
softMutes = parseMutes(softMutedWords.value, i18n.ts._wordMute.soft);
|
new RegExp(regexp[1], regexp[2]);
|
||||||
softMLangs = parseMutes(softMutedLangs.value, i18n.ts._wordMute.lang);
|
// note that regex lines will not be split by spaces!
|
||||||
hardMutes = parseMutes(hardMutedWords.value, i18n.ts._wordMute.hard);
|
} catch (err: any) {
|
||||||
|
// invalid syntax: do not save, do not reset changed flag
|
||||||
|
os.alert({
|
||||||
|
type: "error",
|
||||||
|
title: i18n.ts.regexpError,
|
||||||
|
text:
|
||||||
|
i18n.t("regexpErrorDescription", {
|
||||||
|
tab,
|
||||||
|
line: i + 1,
|
||||||
|
}) +
|
||||||
|
"\n" +
|
||||||
|
err.toString(),
|
||||||
|
});
|
||||||
|
// re-throw error so these invalid settings are not saved
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// invalid syntax: do not save, do not reset changed flag
|
||||||
|
os.alert({
|
||||||
|
type: "error",
|
||||||
|
title: i18n.ts.regexpError,
|
||||||
|
text: i18n.t("regexpErrorDescription", {
|
||||||
|
tab,
|
||||||
|
line: i + 1,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
// re-throw error so these invalid settings are not saved
|
||||||
|
throw new Error("Invalid regular expression");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
};
|
||||||
|
|
||||||
|
let softMutes, softMLangs, hardMWords, hardMPatterns;
|
||||||
|
try {
|
||||||
|
softMutes = parseSoftMutes(
|
||||||
|
softMutedWords.value,
|
||||||
|
i18n.ts._wordMute.soft,
|
||||||
|
);
|
||||||
|
softMLangs = parseMutedWords(softMutedLangs.value);
|
||||||
|
hardMWords = parseMutedWords(hardMutedWords.value);
|
||||||
|
hardMPatterns = parseMutedPatterns(
|
||||||
|
hardMutedPatterns.value,
|
||||||
|
i18n.ts._wordMute.hard,
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// already displayed error message in parseMutes
|
// already displayed error message in parseMutes
|
||||||
return;
|
return;
|
||||||
|
@ -164,7 +242,8 @@ async function save() {
|
||||||
defaultStore.set("mutedWords", softMutes);
|
defaultStore.set("mutedWords", softMutes);
|
||||||
defaultStore.set("mutedLangs", softMLangs);
|
defaultStore.set("mutedLangs", softMLangs);
|
||||||
await os.api("i/update", {
|
await os.api("i/update", {
|
||||||
mutedWords: hardMutes,
|
mutedWords: hardMWords,
|
||||||
|
mutedPatterns: hardMPatterns,
|
||||||
});
|
});
|
||||||
|
|
||||||
changed.value = false;
|
changed.value = false;
|
||||||
|
|
|
@ -107,6 +107,7 @@ export type MeDetailed = UserDetailed & {
|
||||||
isDeleted: boolean;
|
isDeleted: boolean;
|
||||||
isExplorable: boolean;
|
isExplorable: boolean;
|
||||||
mutedWords: string[][];
|
mutedWords: string[][];
|
||||||
|
mutedPatterns: string[];
|
||||||
mutingNotificationTypes: string[];
|
mutingNotificationTypes: string[];
|
||||||
noCrawle: boolean;
|
noCrawle: boolean;
|
||||||
preventAiLearning: boolean;
|
preventAiLearning: boolean;
|
||||||
|
|
263
pnpm-lock.yaml
263
pnpm-lock.yaml
|
@ -300,9 +300,6 @@ importers:
|
||||||
ratelimiter:
|
ratelimiter:
|
||||||
specifier: 3.4.1
|
specifier: 3.4.1
|
||||||
version: 3.4.1
|
version: 3.4.1
|
||||||
re2:
|
|
||||||
specifier: 1.20.9
|
|
||||||
version: 1.20.9
|
|
||||||
redis-semaphore:
|
redis-semaphore:
|
||||||
specifier: 5.5.0
|
specifier: 5.5.0
|
||||||
version: 5.5.0(ioredis@5.3.2)
|
version: 5.5.0(ioredis@5.3.2)
|
||||||
|
@ -3017,26 +3014,6 @@ packages:
|
||||||
fastq: 1.15.0
|
fastq: 1.15.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@npmcli/agent@2.2.0:
|
|
||||||
resolution: {integrity: sha512-2yThA1Es98orMkpSLVqlDZAMPK3jHJhifP2gnNUdk1754uZ8yI5c+ulCoVG+WlntQA6MzhrURMXjSd9Z7dJ2/Q==}
|
|
||||||
engines: {node: ^16.14.0 || >=18.0.0}
|
|
||||||
dependencies:
|
|
||||||
agent-base: 7.1.0
|
|
||||||
http-proxy-agent: 7.0.0
|
|
||||||
https-proxy-agent: 7.0.2
|
|
||||||
lru-cache: 10.0.2
|
|
||||||
socks-proxy-agent: 8.0.2
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@npmcli/fs@3.1.0:
|
|
||||||
resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==}
|
|
||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
|
||||||
dependencies:
|
|
||||||
semver: 7.5.4
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@one-ini/wasm@0.1.1:
|
/@one-ini/wasm@0.1.1:
|
||||||
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
|
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -4757,14 +4734,6 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/aggregate-error@3.1.0:
|
|
||||||
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
clean-stack: 2.2.0
|
|
||||||
indent-string: 4.0.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/ajv-keywords@3.5.2(ajv@6.12.6):
|
/ajv-keywords@3.5.2(ajv@6.12.6):
|
||||||
resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==}
|
resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -5708,24 +5677,6 @@ packages:
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/cacache@18.0.0:
|
|
||||||
resolution: {integrity: sha512-I7mVOPl3PUCeRub1U8YoGz2Lqv9WOBpobZ8RyWFXmReuILz+3OAyTa5oH3QPdtKZD7N0Yk00aLfzn0qvp8dZ1w==}
|
|
||||||
engines: {node: ^16.14.0 || >=18.0.0}
|
|
||||||
dependencies:
|
|
||||||
'@npmcli/fs': 3.1.0
|
|
||||||
fs-minipass: 3.0.3
|
|
||||||
glob: 10.3.10
|
|
||||||
lru-cache: 10.0.2
|
|
||||||
minipass: 7.0.4
|
|
||||||
minipass-collect: 1.0.2
|
|
||||||
minipass-flush: 1.0.5
|
|
||||||
minipass-pipeline: 1.2.4
|
|
||||||
p-map: 4.0.0
|
|
||||||
ssri: 10.0.5
|
|
||||||
tar: 6.2.0
|
|
||||||
unique-filename: 3.0.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/cache-base@1.0.1:
|
/cache-base@1.0.1:
|
||||||
resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==}
|
resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -6092,11 +6043,6 @@ packages:
|
||||||
escape-string-regexp: 1.0.5
|
escape-string-regexp: 1.0.5
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/clean-stack@2.2.0:
|
|
||||||
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/cli-cursor@3.1.0:
|
/cli-cursor@3.1.0:
|
||||||
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
|
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -7338,14 +7284,6 @@ packages:
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/encoding@0.1.13:
|
|
||||||
resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
|
|
||||||
requiresBuild: true
|
|
||||||
dependencies:
|
|
||||||
iconv-lite: 0.6.3
|
|
||||||
dev: false
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/end-of-stream@1.4.4:
|
/end-of-stream@1.4.4:
|
||||||
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
|
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7371,15 +7309,6 @@ packages:
|
||||||
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||||
engines: {node: '>=0.12'}
|
engines: {node: '>=0.12'}
|
||||||
|
|
||||||
/env-paths@2.2.1:
|
|
||||||
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/err-code@2.0.3:
|
|
||||||
resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/error-ex@1.3.2:
|
/error-ex@1.3.2:
|
||||||
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
|
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -8560,10 +8489,6 @@ packages:
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/exponential-backoff@3.1.1:
|
|
||||||
resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/ext-list@2.2.2:
|
/ext-list@2.2.2:
|
||||||
resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==}
|
resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -9059,13 +8984,6 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
minipass: 3.3.6
|
minipass: 3.3.6
|
||||||
|
|
||||||
/fs-minipass@3.0.3:
|
|
||||||
resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==}
|
|
||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
|
||||||
dependencies:
|
|
||||||
minipass: 7.0.4
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/fs-mkdirp-stream@1.0.0:
|
/fs-mkdirp-stream@1.0.0:
|
||||||
resolution: {integrity: sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==}
|
resolution: {integrity: sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
|
@ -9769,16 +9687,6 @@ packages:
|
||||||
toidentifier: 1.0.1
|
toidentifier: 1.0.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/http-proxy-agent@7.0.0:
|
|
||||||
resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==}
|
|
||||||
engines: {node: '>= 14'}
|
|
||||||
dependencies:
|
|
||||||
agent-base: 7.1.0
|
|
||||||
debug: 4.3.4
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/http2-wrapper@1.0.3:
|
/http2-wrapper@1.0.3:
|
||||||
resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==}
|
resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==}
|
||||||
engines: {node: '>=10.19.0'}
|
engines: {node: '>=10.19.0'}
|
||||||
|
@ -9890,10 +9798,12 @@ packages:
|
||||||
/imurmurhash@0.1.4:
|
/imurmurhash@0.1.4:
|
||||||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||||
engines: {node: '>=0.8.19'}
|
engines: {node: '>=0.8.19'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/indent-string@4.0.0:
|
/indent-string@4.0.0:
|
||||||
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
|
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/indent-string@5.0.0:
|
/indent-string@5.0.0:
|
||||||
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
|
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
|
||||||
|
@ -9930,11 +9840,6 @@ packages:
|
||||||
resolution: {integrity: sha512-/nPtyeX9xPUvxZf+r0518B7uqNKlP+LqNJqSiXFEaa2T71rWIwTVXGH7hB9xO/EVdwa5/pWlFCPwShOW81XIxQ==}
|
resolution: {integrity: sha512-/nPtyeX9xPUvxZf+r0518B7uqNKlP+LqNJqSiXFEaa2T71rWIwTVXGH7hB9xO/EVdwa5/pWlFCPwShOW81XIxQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/install-artifact-from-github@1.3.5:
|
|
||||||
resolution: {integrity: sha512-gZHC7f/cJgXz7MXlHFBxPVMsvIbev1OQN1uKQYKVJDydGNm9oYf9JstbU4Atnh/eSvk41WtEovoRm+8IF686xg==}
|
|
||||||
hasBin: true
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/internal-slot@1.0.6:
|
/internal-slot@1.0.6:
|
||||||
resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==}
|
resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
@ -10238,10 +10143,6 @@ packages:
|
||||||
ip-regex: 4.3.0
|
ip-regex: 4.3.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/is-lambda@1.0.1:
|
|
||||||
resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/is-natural-number@4.0.1:
|
/is-natural-number@4.0.1:
|
||||||
resolution: {integrity: sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==}
|
resolution: {integrity: sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -10436,11 +10337,6 @@ packages:
|
||||||
/isexe@2.0.0:
|
/isexe@2.0.0:
|
||||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||||
|
|
||||||
/isexe@3.1.1:
|
|
||||||
resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==}
|
|
||||||
engines: {node: '>=16'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/isobject@2.1.0:
|
/isobject@2.1.0:
|
||||||
resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==}
|
resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -11815,25 +11711,6 @@ packages:
|
||||||
/make-error@1.3.6:
|
/make-error@1.3.6:
|
||||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||||
|
|
||||||
/make-fetch-happen@13.0.0:
|
|
||||||
resolution: {integrity: sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==}
|
|
||||||
engines: {node: ^16.14.0 || >=18.0.0}
|
|
||||||
dependencies:
|
|
||||||
'@npmcli/agent': 2.2.0
|
|
||||||
cacache: 18.0.0
|
|
||||||
http-cache-semantics: 4.1.1
|
|
||||||
is-lambda: 1.0.1
|
|
||||||
minipass: 7.0.4
|
|
||||||
minipass-fetch: 3.0.4
|
|
||||||
minipass-flush: 1.0.5
|
|
||||||
minipass-pipeline: 1.2.4
|
|
||||||
negotiator: 0.6.3
|
|
||||||
promise-retry: 2.0.1
|
|
||||||
ssri: 10.0.5
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/make-iterator@1.0.1:
|
/make-iterator@1.0.1:
|
||||||
resolution: {integrity: sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==}
|
resolution: {integrity: sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -12103,45 +11980,6 @@ packages:
|
||||||
/minimist@1.2.8:
|
/minimist@1.2.8:
|
||||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
||||||
|
|
||||||
/minipass-collect@1.0.2:
|
|
||||||
resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
|
|
||||||
engines: {node: '>= 8'}
|
|
||||||
dependencies:
|
|
||||||
minipass: 3.3.6
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/minipass-fetch@3.0.4:
|
|
||||||
resolution: {integrity: sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==}
|
|
||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
|
||||||
dependencies:
|
|
||||||
minipass: 7.0.4
|
|
||||||
minipass-sized: 1.0.3
|
|
||||||
minizlib: 2.1.2
|
|
||||||
optionalDependencies:
|
|
||||||
encoding: 0.1.13
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/minipass-flush@1.0.5:
|
|
||||||
resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==}
|
|
||||||
engines: {node: '>= 8'}
|
|
||||||
dependencies:
|
|
||||||
minipass: 3.3.6
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/minipass-pipeline@1.2.4:
|
|
||||||
resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
minipass: 3.3.6
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/minipass-sized@1.0.3:
|
|
||||||
resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
minipass: 3.3.6
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/minipass@3.3.6:
|
/minipass@3.3.6:
|
||||||
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
|
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -12264,7 +12102,9 @@ packages:
|
||||||
|
|
||||||
/nan@2.18.0:
|
/nan@2.18.0:
|
||||||
resolution: {integrity: sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==}
|
resolution: {integrity: sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
/nanoid@3.3.7:
|
/nanoid@3.3.7:
|
||||||
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
|
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
|
||||||
|
@ -12377,25 +12217,6 @@ packages:
|
||||||
resolution: {integrity: sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==}
|
resolution: {integrity: sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
/node-gyp@10.0.1:
|
|
||||||
resolution: {integrity: sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==}
|
|
||||||
engines: {node: ^16.14.0 || >=18.0.0}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
env-paths: 2.2.1
|
|
||||||
exponential-backoff: 3.1.1
|
|
||||||
glob: 10.3.10
|
|
||||||
graceful-fs: 4.2.11
|
|
||||||
make-fetch-happen: 13.0.0
|
|
||||||
nopt: 7.2.0
|
|
||||||
proc-log: 3.0.0
|
|
||||||
semver: 7.5.4
|
|
||||||
tar: 6.2.0
|
|
||||||
which: 4.0.0
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/node-int64@0.4.0:
|
/node-int64@0.4.0:
|
||||||
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
|
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -12795,13 +12616,6 @@ packages:
|
||||||
p-limit: 3.1.0
|
p-limit: 3.1.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/p-map@4.0.0:
|
|
||||||
resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
aggregate-error: 3.1.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/p-map@6.0.0:
|
/p-map@6.0.0:
|
||||||
resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==}
|
resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
@ -13655,11 +13469,6 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/proc-log@3.0.0:
|
|
||||||
resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==}
|
|
||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/process-nextick-args@2.0.1:
|
/process-nextick-args@2.0.1:
|
||||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||||
|
|
||||||
|
@ -13667,14 +13476,6 @@ packages:
|
||||||
resolution: {integrity: sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==}
|
resolution: {integrity: sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/promise-retry@2.0.1:
|
|
||||||
resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
err-code: 2.0.3
|
|
||||||
retry: 0.12.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/promise@7.3.1:
|
/promise@7.3.1:
|
||||||
resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
|
resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -13922,17 +13723,6 @@ packages:
|
||||||
setimmediate: 1.0.5
|
setimmediate: 1.0.5
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/re2@1.20.9:
|
|
||||||
resolution: {integrity: sha512-ZYcPTFr5ha2xq3WQjBDTF9CWPSDK1z28MLh5UFRxc//7X8BNQ3A7yR7ITnP0jO346661ertdKVFqw1qoL3FMEQ==}
|
|
||||||
requiresBuild: true
|
|
||||||
dependencies:
|
|
||||||
install-artifact-from-github: 1.3.5
|
|
||||||
nan: 2.18.0
|
|
||||||
node-gyp: 10.0.1
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/react-is@18.2.0:
|
/react-is@18.2.0:
|
||||||
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
|
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -14316,11 +14106,6 @@ packages:
|
||||||
engines: {node: '>=0.12'}
|
engines: {node: '>=0.12'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/retry@0.12.0:
|
|
||||||
resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
|
|
||||||
engines: {node: '>= 4'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/reusify@1.0.4:
|
/reusify@1.0.4:
|
||||||
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
|
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
|
||||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||||
|
@ -14730,17 +14515,6 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/socks-proxy-agent@8.0.2:
|
|
||||||
resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==}
|
|
||||||
engines: {node: '>= 14'}
|
|
||||||
dependencies:
|
|
||||||
agent-base: 7.1.0
|
|
||||||
debug: 4.3.4
|
|
||||||
socks: 2.7.1
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/socks@2.7.1:
|
/socks@2.7.1:
|
||||||
resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==}
|
resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==}
|
||||||
engines: {node: '>= 10.13.0', npm: '>= 3.0.0'}
|
engines: {node: '>= 10.13.0', npm: '>= 3.0.0'}
|
||||||
|
@ -14882,13 +14656,6 @@ packages:
|
||||||
tweetnacl: 0.14.5
|
tweetnacl: 0.14.5
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/ssri@10.0.5:
|
|
||||||
resolution: {integrity: sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==}
|
|
||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
|
||||||
dependencies:
|
|
||||||
minipass: 7.0.4
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/stack-trace@0.0.10:
|
/stack-trace@0.0.10:
|
||||||
resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
|
resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -16042,20 +15809,6 @@ packages:
|
||||||
resolution: {integrity: sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ==}
|
resolution: {integrity: sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/unique-filename@3.0.0:
|
|
||||||
resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==}
|
|
||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
|
||||||
dependencies:
|
|
||||||
unique-slug: 4.0.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/unique-slug@4.0.0:
|
|
||||||
resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==}
|
|
||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
|
||||||
dependencies:
|
|
||||||
imurmurhash: 0.1.4
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/unique-stream@2.3.1:
|
/unique-stream@2.3.1:
|
||||||
resolution: {integrity: sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==}
|
resolution: {integrity: sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -16578,14 +16331,6 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe: 2.0.0
|
isexe: 2.0.0
|
||||||
|
|
||||||
/which@4.0.0:
|
|
||||||
resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==}
|
|
||||||
engines: {node: ^16.13.0 || >=18.0.0}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
isexe: 3.1.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/wide-align@1.1.5:
|
/wide-align@1.1.5:
|
||||||
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
|
|
Loading…
Reference in a new issue