Merge branch 'develop' of https://codeberg.org/calckey/calckey into upstream
This commit is contained in:
commit
567d94196a
|
@ -1601,6 +1601,8 @@ _aboutMisskey:
|
||||||
morePatrons: També agraïm el suport de molts altres ajudants que no figuren aquí.
|
morePatrons: També agraïm el suport de molts altres ajudants que no figuren aquí.
|
||||||
Gràcies! 🥰
|
Gràcies! 🥰
|
||||||
patrons: Mecenes de Calckey
|
patrons: Mecenes de Calckey
|
||||||
|
patronsList: Llistats cronològicament, no per la quantitat donada. Fes una donació
|
||||||
|
amb l'enllaç de dalt per veure el teu nom aquí!
|
||||||
unknown: Desconegut
|
unknown: Desconegut
|
||||||
pageLikesCount: Nombre de pàgines amb M'agrada
|
pageLikesCount: Nombre de pàgines amb M'agrada
|
||||||
youAreRunningUpToDateClient: Estás fent servir la versió del client més nova.
|
youAreRunningUpToDateClient: Estás fent servir la versió del client més nova.
|
||||||
|
@ -2082,11 +2084,7 @@ _experiments:
|
||||||
alpha: Alfa
|
alpha: Alfa
|
||||||
beta: Beta
|
beta: Beta
|
||||||
release: Publicà
|
release: Publicà
|
||||||
enablePostEditing: Activà l'edició de publicacions
|
|
||||||
title: Experiments
|
title: Experiments
|
||||||
postEditingCaption: Mostra l'opció perquè els usuaris editin les seves publicacions
|
|
||||||
mitjançant el menú d'opcions de publicació, i permet rebre publicacions editades
|
|
||||||
d'altres servidors.
|
|
||||||
enablePostImports: Activar l'importació de publicacions
|
enablePostImports: Activar l'importació de publicacions
|
||||||
postImportsCaption: Permet els usuaris importar publicacions desde comptes a Calckey,
|
postImportsCaption: Permet els usuaris importar publicacions desde comptes a Calckey,
|
||||||
Misskey, Mastodon, Akkoma i Pleroma. Pot fer que el servidor vagi més lent durant
|
Misskey, Mastodon, Akkoma i Pleroma. Pot fer que el servidor vagi més lent durant
|
||||||
|
|
|
@ -2095,10 +2095,7 @@ jumpToPrevious: Zum Vorherigen springen
|
||||||
silencedWarning: Diese Meldung wird angezeigt, weil diese Nutzer von Servern stammen,
|
silencedWarning: Diese Meldung wird angezeigt, weil diese Nutzer von Servern stammen,
|
||||||
die Ihr Administrator abgeschaltet hat, so dass es sich möglicherweise um Spam handelt.
|
die Ihr Administrator abgeschaltet hat, so dass es sich möglicherweise um Spam handelt.
|
||||||
_experiments:
|
_experiments:
|
||||||
enablePostEditing: Beitragsbearbeitung ermöglichen
|
|
||||||
title: Funktionstests
|
title: Funktionstests
|
||||||
postEditingCaption: Zeigt die Option für Nutzer an, ihre bestehenden Beiträge über
|
|
||||||
das Menü "Beitragsoptionen" zu bearbeiten
|
|
||||||
enablePostImports: Beitragsimporte aktivieren
|
enablePostImports: Beitragsimporte aktivieren
|
||||||
postImportsCaption: Erlaubt es Nutzer:innen ihre Posts von alten Calckey, Misskey,
|
postImportsCaption: Erlaubt es Nutzer:innen ihre Posts von alten Calckey, Misskey,
|
||||||
Mastodon, Akkoma und Pleroma Accounts zu importieren. Bei Engpässen in der Warteschlange
|
Mastodon, Akkoma und Pleroma Accounts zu importieren. Bei Engpässen in der Warteschlange
|
||||||
|
@ -2152,3 +2149,4 @@ clipsDesc: Clips sind wie teilbare, kategorisierte Lesezeichen. Du kannst Clips
|
||||||
Menü individueller Posts aus erstellen.
|
Menü individueller Posts aus erstellen.
|
||||||
channelFederationWarn: Kanäle föderieren noch nicht zu anderen Servern
|
channelFederationWarn: Kanäle föderieren noch nicht zu anderen Servern
|
||||||
reactionPickerSkinTone: Bevorzugte Emoji-Hautfarbe
|
reactionPickerSkinTone: Bevorzugte Emoji-Hautfarbe
|
||||||
|
swipeOnMobile: Wischen zwischen den Seiten erlauben
|
||||||
|
|
|
@ -1213,6 +1213,7 @@ _aboutMisskey:
|
||||||
morePatrons: "We also appreciate the support of many other helpers not listed here.
|
morePatrons: "We also appreciate the support of many other helpers not listed here.
|
||||||
Thank you! 🥰"
|
Thank you! 🥰"
|
||||||
patrons: "Calckey patrons"
|
patrons: "Calckey patrons"
|
||||||
|
patronsList: "Listed chronologically, not by donation size. Donate with the link above to get your name on here!"
|
||||||
_nsfw:
|
_nsfw:
|
||||||
respect: "Hide NSFW media"
|
respect: "Hide NSFW media"
|
||||||
ignore: "Don't hide NSFW media"
|
ignore: "Don't hide NSFW media"
|
||||||
|
@ -2069,9 +2070,6 @@ _deck:
|
||||||
direct: "Direct messages"
|
direct: "Direct messages"
|
||||||
_experiments:
|
_experiments:
|
||||||
title: "Experiments"
|
title: "Experiments"
|
||||||
enablePostEditing: "Enable post editing"
|
|
||||||
postEditingCaption: "Shows the option for users to edit their existing posts via\
|
|
||||||
\ the post options menu, and allows post edits from other instances to be recieved."
|
|
||||||
enablePostImports: "Enable post imports"
|
enablePostImports: "Enable post imports"
|
||||||
postImportsCaption: "Allows users to import their posts from past Calckey,\
|
postImportsCaption: "Allows users to import their posts from past Calckey,\
|
||||||
\ Misskey, Mastodon, Akkoma, and Pleroma accounts. It may cause slowdowns during\
|
\ Misskey, Mastodon, Akkoma, and Pleroma accounts. It may cause slowdowns during\
|
||||||
|
|
|
@ -2028,7 +2028,7 @@ flagShowTimelineRepliesDescription: Si activé, affiche dans le fil les réponse
|
||||||
_experiments:
|
_experiments:
|
||||||
alpha: Alpha
|
alpha: Alpha
|
||||||
beta: Beta
|
beta: Beta
|
||||||
enablePostEditing: Autoriser l'édition de note
|
enablePostImports: Autoriser l'importation de messages
|
||||||
title: Expérimentations
|
title: Expérimentations
|
||||||
findOtherInstance: Trouver un autre serveur
|
findOtherInstance: Trouver un autre serveur
|
||||||
userSaysSomethingReasonQuote: '{name} a cité une note contenant {reason}'
|
userSaysSomethingReasonQuote: '{name} a cité une note contenant {reason}'
|
||||||
|
|
|
@ -1887,9 +1887,7 @@ hiddenTagsDescription: 'トレンドと「みつける」から除外したい
|
||||||
hiddenTags: 非表示にするハッシュタグ
|
hiddenTags: 非表示にするハッシュタグ
|
||||||
apps: "アプリ"
|
apps: "アプリ"
|
||||||
_experiments:
|
_experiments:
|
||||||
enablePostEditing: 投稿の編集機能を有効にする
|
|
||||||
title: 試験的な機能
|
title: 試験的な機能
|
||||||
postEditingCaption: 投稿のメニューに既存の投稿を編集するボタンを表示し、他サーバーの編集も受信できるようにします。
|
|
||||||
postImportsCaption:
|
postImportsCaption:
|
||||||
ユーザーが過去の投稿をCalckey・Misskey・Mastodon・Akkoma・Pleromaからインポートすることを許可します。キューが溜まっているときにインポートするとサーバーに負荷がかかる可能性があります。
|
ユーザーが過去の投稿をCalckey・Misskey・Mastodon・Akkoma・Pleromaからインポートすることを許可します。キューが溜まっているときにインポートするとサーバーに負荷がかかる可能性があります。
|
||||||
enablePostImports: 投稿のインポートを有効にする
|
enablePostImports: 投稿のインポートを有効にする
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
|
||||||
_lang_: "简体中文"
|
_lang_: "简体中文"
|
||||||
headlineMisskey: "通过帖子连接在一起的网络"
|
headlineMisskey: "通过帖子连接在一起的网络"
|
||||||
introMisskey: "欢迎!Misskey是一个开源的、去中心化的“微博客”服务。\n通过编写「帖文」来和大家分享你的以及你周围的事情吧!📡\n通过「回应」功能,可以让你快速地对大家的帖文表达反馈👍\n来探索新的世界吧!🚀"
|
introMisskey: "欢迎!Misskey是一个开源的、去中心化的“微博客”服务。\n通过编写「帖文」来和大家分享你的以及你周围的事情吧!📡\n通过「回应」功能,可以让你快速地对大家的帖文表达反馈👍\n\
|
||||||
|
来探索新的世界吧!🚀"
|
||||||
monthAndDay: "{month}月 {day}日"
|
monthAndDay: "{month}月 {day}日"
|
||||||
search: "搜索"
|
search: "搜索"
|
||||||
notifications: "通知"
|
notifications: "通知"
|
||||||
|
@ -14,9 +14,9 @@ gotIt: "我明白了"
|
||||||
cancel: "取消"
|
cancel: "取消"
|
||||||
enterUsername: "输入用户名"
|
enterUsername: "输入用户名"
|
||||||
renotedBy: "由 {user} 转贴"
|
renotedBy: "由 {user} 转贴"
|
||||||
noNotes: "没有帖文"
|
noNotes: "没有帖子"
|
||||||
noNotifications: "无通知"
|
noNotifications: "无通知"
|
||||||
instance: "实例"
|
instance: "服务器"
|
||||||
settings: "设置"
|
settings: "设置"
|
||||||
basicSettings: "基本设置"
|
basicSettings: "基本设置"
|
||||||
otherSettings: "其他设置"
|
otherSettings: "其他设置"
|
||||||
|
@ -64,7 +64,7 @@ import: "导入"
|
||||||
export: "导出"
|
export: "导出"
|
||||||
files: "文件"
|
files: "文件"
|
||||||
download: "下载"
|
download: "下载"
|
||||||
driveFileDeleteConfirm: "要删除「{name}」文件吗?附加此文件的帖子也会被删除。"
|
driveFileDeleteConfirm: "要删除文件「{name}」吗?它将被所有作为附件包含它的帖子中删除。"
|
||||||
unfollowConfirm: "要取消对{name}的关注吗?"
|
unfollowConfirm: "要取消对{name}的关注吗?"
|
||||||
exportRequested: "导出请求已提交,这可能需要花一些时间,导出的文件将保存到网盘中。"
|
exportRequested: "导出请求已提交,这可能需要花一些时间,导出的文件将保存到网盘中。"
|
||||||
importRequested: "导入请求已提交,这可能需要花一点时间。"
|
importRequested: "导入请求已提交,这可能需要花一点时间。"
|
||||||
|
@ -166,7 +166,7 @@ selectUser: "选择用户"
|
||||||
recipient: "收件人"
|
recipient: "收件人"
|
||||||
annotation: "注解"
|
annotation: "注解"
|
||||||
federation: "联合"
|
federation: "联合"
|
||||||
instances: "实例"
|
instances: "服务器"
|
||||||
registeredAt: "初次观测"
|
registeredAt: "初次观测"
|
||||||
latestRequestSentAt: "上次发送的请求"
|
latestRequestSentAt: "上次发送的请求"
|
||||||
latestRequestReceivedAt: "上次收到的请求"
|
latestRequestReceivedAt: "上次收到的请求"
|
||||||
|
@ -186,14 +186,14 @@ jobQueue: "作业队列"
|
||||||
cpuAndMemory: "CPU和内存"
|
cpuAndMemory: "CPU和内存"
|
||||||
network: "网络"
|
network: "网络"
|
||||||
disk: "存储"
|
disk: "存储"
|
||||||
instanceInfo: "实例信息"
|
instanceInfo: "服务器信息"
|
||||||
statistics: "统计"
|
statistics: "统计"
|
||||||
clearQueue: "清除队列"
|
clearQueue: "清除队列"
|
||||||
clearQueueConfirmTitle: "确定清除队列?"
|
clearQueueConfirmTitle: "确定清除队列?"
|
||||||
clearQueueConfirmText: "未送达的帖子将不会送达。 通常,您不需要这样做。"
|
clearQueueConfirmText: "未送达的帖子将不会送达。 通常,您不需要这样做。"
|
||||||
clearCachedFiles: "清除缓存"
|
clearCachedFiles: "清除缓存"
|
||||||
clearCachedFilesConfirm: "确定要清除缓存文件?"
|
clearCachedFilesConfirm: "确定要清除缓存文件?"
|
||||||
blockedInstances: "被阻拦的实例"
|
blockedInstances: "已屏蔽的服务器"
|
||||||
blockedInstancesDescription: "设定要阻拦的实例,以换行来进行分割。被阻拦的实例将无法与本实例进行交换通讯。"
|
blockedInstancesDescription: "设定要阻拦的实例,以换行来进行分割。被阻拦的实例将无法与本实例进行交换通讯。"
|
||||||
muteAndBlock: "屏蔽/拉黑"
|
muteAndBlock: "屏蔽/拉黑"
|
||||||
mutedUsers: "已屏蔽用户"
|
mutedUsers: "已屏蔽用户"
|
||||||
|
@ -309,8 +309,8 @@ unwatch: "取消关注"
|
||||||
accept: "允许"
|
accept: "允许"
|
||||||
reject: "拒绝"
|
reject: "拒绝"
|
||||||
normal: "正常"
|
normal: "正常"
|
||||||
instanceName: "实例名称"
|
instanceName: "服务器名称"
|
||||||
instanceDescription: "实例介绍"
|
instanceDescription: "服务器简介"
|
||||||
maintainerName: "管理员名称"
|
maintainerName: "管理员名称"
|
||||||
maintainerEmail: "管理员电子邮箱"
|
maintainerEmail: "管理员电子邮箱"
|
||||||
tosUrl: "服务条款URL"
|
tosUrl: "服务条款URL"
|
||||||
|
@ -321,7 +321,7 @@ dayX: "{day}日"
|
||||||
monthX: "{month}月"
|
monthX: "{month}月"
|
||||||
yearX: "{year}年"
|
yearX: "{year}年"
|
||||||
pages: "页面"
|
pages: "页面"
|
||||||
integration: "关联"
|
integration: "整合"
|
||||||
connectService: "连接"
|
connectService: "连接"
|
||||||
disconnectService: "断开连接"
|
disconnectService: "断开连接"
|
||||||
enableLocalTimeline: "启用本地时间线功能"
|
enableLocalTimeline: "启用本地时间线功能"
|
||||||
|
@ -600,7 +600,7 @@ testEmail: "邮件发送测试"
|
||||||
wordMute: "文字屏蔽"
|
wordMute: "文字屏蔽"
|
||||||
regexpError: "正则表达式错误"
|
regexpError: "正则表达式错误"
|
||||||
regexpErrorDescription: "{tab} 屏蔽文字的第 {line} 行的正则表达式有错误:"
|
regexpErrorDescription: "{tab} 屏蔽文字的第 {line} 行的正则表达式有错误:"
|
||||||
instanceMute: "实例的屏蔽"
|
instanceMute: "服务器静音"
|
||||||
userSaysSomething: "{name}说了什么"
|
userSaysSomething: "{name}说了什么"
|
||||||
makeActive: "启用"
|
makeActive: "启用"
|
||||||
display: "显示"
|
display: "显示"
|
||||||
|
@ -643,7 +643,7 @@ instanceTicker: "帖子的实例信息"
|
||||||
waitingFor: "等待{x}"
|
waitingFor: "等待{x}"
|
||||||
random: "随机"
|
random: "随机"
|
||||||
system: "系统"
|
system: "系统"
|
||||||
switchUi: "切换界面"
|
switchUi: "界面"
|
||||||
desktop: "桌面"
|
desktop: "桌面"
|
||||||
clip: "便签"
|
clip: "便签"
|
||||||
createNew: "新建"
|
createNew: "新建"
|
||||||
|
@ -755,7 +755,7 @@ active: "活动"
|
||||||
offline: "离线"
|
offline: "离线"
|
||||||
notRecommended: "不推荐"
|
notRecommended: "不推荐"
|
||||||
botProtection: "Bot防御"
|
botProtection: "Bot防御"
|
||||||
instanceBlocking: "被阻拦的实例"
|
instanceBlocking: "联邦管理"
|
||||||
selectAccount: "选择账户"
|
selectAccount: "选择账户"
|
||||||
switchAccount: "切换账户"
|
switchAccount: "切换账户"
|
||||||
enabled: "已启用"
|
enabled: "已启用"
|
||||||
|
@ -816,7 +816,7 @@ controlPanel: "控制面板"
|
||||||
manageAccounts: "管理账户"
|
manageAccounts: "管理账户"
|
||||||
makeReactionsPublic: "将回应设置为公开"
|
makeReactionsPublic: "将回应设置为公开"
|
||||||
makeReactionsPublicDescription: "将您发表过的回应设置成公开可见。"
|
makeReactionsPublicDescription: "将您发表过的回应设置成公开可见。"
|
||||||
classic: "经典"
|
classic: "居中"
|
||||||
muteThread: "屏蔽帖子列表"
|
muteThread: "屏蔽帖子列表"
|
||||||
unmuteThread: "取消屏蔽帖子列表"
|
unmuteThread: "取消屏蔽帖子列表"
|
||||||
ffVisibility: "连接的可见范围"
|
ffVisibility: "连接的可见范围"
|
||||||
|
@ -896,7 +896,10 @@ shuffle: "随机"
|
||||||
account: "账户"
|
account: "账户"
|
||||||
move: "移动"
|
move: "移动"
|
||||||
customKaTeXMacro: "自定义 KaTeX 宏"
|
customKaTeXMacro: "自定义 KaTeX 宏"
|
||||||
customKaTeXMacroDescription: "使用宏来轻松的输入数学表达式吧!宏的用法与 LaTeX 中的命令定义相同。你可以使用 \\newcommand{\\name}{content} 或 \\newcommand{\\name}[number of arguments]{content} 来输入数学表达式。举个例子,\\newcommand{\\add}[2]{#1 + #2} 会将 \\add{3}{foo} 展开为 3 + foo。此外,宏名称外的花括号 {} 可以被替换为圆括号 () 和方括号 [],这会影响用于参数的括号。每行只能够定义一个宏,无法在中间换行,且无效的行将被忽略。只支持简单字符串替换功能,不支持高级语法,如条件分支等。"
|
customKaTeXMacroDescription: "使用宏来轻松的输入数学表达式吧!宏的用法与 LaTeX 中的命令定义相同。你可以使用 \\newcommand{\\
|
||||||
|
name}{content} 或 \\newcommand{\\name}[number of arguments]{content} 来输入数学表达式。举个例子,\\
|
||||||
|
newcommand{\\add}[2]{#1 + #2} 会将 \\add{3}{foo} 展开为 3 + foo。此外,宏名称外的花括号 {} 可以被替换为圆括号
|
||||||
|
() 和方括号 [],这会影响用于参数的括号。每行只能够定义一个宏,无法在中间换行,且无效的行将被忽略。只支持简单字符串替换功能,不支持高级语法,如条件分支等。"
|
||||||
enableCustomKaTeXMacro: "启用自定义 KaTeX 宏"
|
enableCustomKaTeXMacro: "启用自定义 KaTeX 宏"
|
||||||
_sensitiveMediaDetection:
|
_sensitiveMediaDetection:
|
||||||
description: "可以使用机器学习技术自动检测敏感媒体,以便进行审核。服务器负载将略微增加。"
|
description: "可以使用机器学习技术自动检测敏感媒体,以便进行审核。服务器负载将略微增加。"
|
||||||
|
@ -981,6 +984,7 @@ _aboutMisskey:
|
||||||
donate: "赞助Misskey"
|
donate: "赞助Misskey"
|
||||||
morePatrons: "还有很多其他的人也在支持我们,非常感谢🥰"
|
morePatrons: "还有很多其他的人也在支持我们,非常感谢🥰"
|
||||||
patrons: "支持者"
|
patrons: "支持者"
|
||||||
|
patronsList: 按时间顺序而不是捐赠金额排列。通过上面的链接捐款,让您的名字出现在这里!
|
||||||
_nsfw:
|
_nsfw:
|
||||||
respect: "隐藏敏感内容"
|
respect: "隐藏敏感内容"
|
||||||
ignore: "不隐藏敏感内容"
|
ignore: "不隐藏敏感内容"
|
||||||
|
@ -1051,6 +1055,24 @@ _mfm:
|
||||||
rotateDescription: "旋转指定的角度。"
|
rotateDescription: "旋转指定的角度。"
|
||||||
plain: "简洁"
|
plain: "简洁"
|
||||||
plainDescription: "禁用所有内部语法。"
|
plainDescription: "禁用所有内部语法。"
|
||||||
|
crop: 裁剪
|
||||||
|
scale: 缩放
|
||||||
|
position: 位置
|
||||||
|
fade: 渐淡
|
||||||
|
advanced: 高级 MFM
|
||||||
|
background: 背景色
|
||||||
|
fadeDescription: 内容淡入和淡出。
|
||||||
|
warn: MFM 可能包含快速移动或华丽的动画
|
||||||
|
advancedDescription: 如果禁用,则仅允许基本标记,除非正在播放动态 MFM
|
||||||
|
foreground: 前景色
|
||||||
|
backgroundDescription: 更改文本的背景色。
|
||||||
|
play: 播放 MFM
|
||||||
|
alwaysPlay: 始终自动播放所有动态的 MFM
|
||||||
|
stop: 停止播放 MFM
|
||||||
|
positionDescription: 将内容移动指定的量。
|
||||||
|
cropDescription: 裁剪内容。
|
||||||
|
scaleDescription: 按指定量缩放内容。
|
||||||
|
foregroundDescription: 更改文本的前景色。
|
||||||
_instanceTicker:
|
_instanceTicker:
|
||||||
none: "不显示"
|
none: "不显示"
|
||||||
remote: "仅远程用户"
|
remote: "仅远程用户"
|
||||||
|
@ -1059,6 +1081,7 @@ _serverDisconnectedBehavior:
|
||||||
reload: "自动重载"
|
reload: "自动重载"
|
||||||
dialog: "对话框警告"
|
dialog: "对话框警告"
|
||||||
quiet: "安静警告"
|
quiet: "安静警告"
|
||||||
|
nothing: 什么也不做
|
||||||
_channel:
|
_channel:
|
||||||
create: "创建频道"
|
create: "创建频道"
|
||||||
edit: "编辑频道"
|
edit: "编辑频道"
|
||||||
|
@ -1068,7 +1091,7 @@ _channel:
|
||||||
owned: "管理中"
|
owned: "管理中"
|
||||||
following: "正在关注"
|
following: "正在关注"
|
||||||
usersCount: "有{n}人参与"
|
usersCount: "有{n}人参与"
|
||||||
notesCount: "有{n}个帖子"
|
notesCount: "{n} 帖子"
|
||||||
nameAndDescription: "名称与描述"
|
nameAndDescription: "名称与描述"
|
||||||
nameOnly: "仅名称"
|
nameOnly: "仅名称"
|
||||||
_menuDisplay:
|
_menuDisplay:
|
||||||
|
@ -1084,7 +1107,7 @@ _wordMute:
|
||||||
hardDescription: "防止将具有指定条件的帖子添加到时间线。 即使您更改条件,未添加的帖文也会被排除在外。"
|
hardDescription: "防止将具有指定条件的帖子添加到时间线。 即使您更改条件,未添加的帖文也会被排除在外。"
|
||||||
soft: "软屏蔽"
|
soft: "软屏蔽"
|
||||||
hard: "硬屏蔽"
|
hard: "硬屏蔽"
|
||||||
mutedNotes: "被屏蔽的帖子"
|
mutedNotes: "已静音的帖子"
|
||||||
_instanceMute:
|
_instanceMute:
|
||||||
instanceMuteDescription: "屏蔽配置实例中的所有帖子和转帖,包括实例的用户回复。"
|
instanceMuteDescription: "屏蔽配置实例中的所有帖子和转帖,包括实例的用户回复。"
|
||||||
instanceMuteDescription2: "设置时用换行符来分隔"
|
instanceMuteDescription2: "设置时用换行符来分隔"
|
||||||
|
@ -1165,7 +1188,7 @@ _theme:
|
||||||
accentLighten: "强调色(浅)"
|
accentLighten: "强调色(浅)"
|
||||||
fgHighlighted: "高亮显示文本"
|
fgHighlighted: "高亮显示文本"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "帖子"
|
note: "新的帖子"
|
||||||
noteMy: "我的帖子"
|
noteMy: "我的帖子"
|
||||||
notification: "通知"
|
notification: "通知"
|
||||||
chat: "聊天"
|
chat: "聊天"
|
||||||
|
@ -1178,7 +1201,7 @@ _ago:
|
||||||
secondsAgo: "{n}秒前"
|
secondsAgo: "{n}秒前"
|
||||||
minutesAgo: "{n}分前"
|
minutesAgo: "{n}分前"
|
||||||
hoursAgo: "{n}小时前"
|
hoursAgo: "{n}小时前"
|
||||||
daysAgo: "{n}日前"
|
daysAgo: "{n}天前"
|
||||||
weeksAgo: "{n}周前"
|
weeksAgo: "{n}周前"
|
||||||
monthsAgo: "{n}月前"
|
monthsAgo: "{n}月前"
|
||||||
yearsAgo: "{n}年前"
|
yearsAgo: "{n}年前"
|
||||||
|
@ -1218,6 +1241,21 @@ _2fa:
|
||||||
step3: "输入您的应用提供的动态口令以完成设置。"
|
step3: "输入您的应用提供的动态口令以完成设置。"
|
||||||
step4: "从现在开始,任何登录操作都将要求您提供动态口令。"
|
step4: "从现在开始,任何登录操作都将要求您提供动态口令。"
|
||||||
securityKeyInfo: "您可以设置使用支持FIDO2的硬件安全密钥、设备上的指纹或PIN来保护您的登录过程。"
|
securityKeyInfo: "您可以设置使用支持FIDO2的硬件安全密钥、设备上的指纹或PIN来保护您的登录过程。"
|
||||||
|
renewTOTPOk: 重新配置
|
||||||
|
renewTOTPCancel: 取消
|
||||||
|
token: 2FA 令牌
|
||||||
|
renewTOTP: 重新配置身份验证器应用程序
|
||||||
|
registerTOTPBeforeKey: 请设置一个认证器应用来注册一个安全或通行密钥。
|
||||||
|
renewTOTPConfirm: 这将导致您之前的应用程序中的验证码停止工作
|
||||||
|
step3Title: 输入验证码
|
||||||
|
step2Click: 点击此二维码将允许您在安全密钥或手机验证器应用中注册 2FA。
|
||||||
|
securityKeyNotSupported: 您的浏览器不支持安全密钥。
|
||||||
|
securityKeyName: 输入密钥名称
|
||||||
|
chromePasskeyNotSupported: 目前不支持 Chrome passkeys。
|
||||||
|
tapSecurityKey: 请按照您的浏览器的指示注册安全或通行密钥
|
||||||
|
removeKey: 移除安全密钥
|
||||||
|
removeKeyConfirm: 真的要删除 {name} 密钥吗?
|
||||||
|
whyTOTPOnlyRenew: 只要注册了安全密钥,就无法删除身份验证器应用程序。
|
||||||
_permissions:
|
_permissions:
|
||||||
"read:account": "查看账户信息"
|
"read:account": "查看账户信息"
|
||||||
"write:account": "更改帐户信息"
|
"write:account": "更改帐户信息"
|
||||||
|
@ -1258,12 +1296,15 @@ _auth:
|
||||||
pleaseGoBack: "请返回到应用程序"
|
pleaseGoBack: "请返回到应用程序"
|
||||||
callback: "回到应用程序"
|
callback: "回到应用程序"
|
||||||
denied: "拒绝访问"
|
denied: "拒绝访问"
|
||||||
|
allPermissions: 完全的账户访问权限
|
||||||
|
copyAsk: 请将以下授权码粘贴到应用程序中:
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "所有帖子"
|
all: "所有帖子"
|
||||||
homeTimeline: "已关注用户的帖子"
|
homeTimeline: "已关注用户的帖子"
|
||||||
users: "来自指定用户的帖子"
|
users: "来自指定用户的帖子"
|
||||||
userList: "来自指定列表中的帖子"
|
userList: "来自指定列表中的帖子"
|
||||||
userGroup: "来自指定群组中用户的帖子"
|
userGroup: "来自指定群组中用户的帖子"
|
||||||
|
instances: 服务器上所有用户的帖子
|
||||||
_weekday:
|
_weekday:
|
||||||
sunday: "星期日"
|
sunday: "星期日"
|
||||||
monday: "星期一"
|
monday: "星期一"
|
||||||
|
@ -1280,21 +1321,26 @@ _widgets:
|
||||||
trends: "趋势"
|
trends: "趋势"
|
||||||
clock: "时钟"
|
clock: "时钟"
|
||||||
rss: "RSS阅读器"
|
rss: "RSS阅读器"
|
||||||
rssTicker: "RSS Ticker"
|
rssTicker: "RSS滚动条"
|
||||||
activity: "活动"
|
activity: "活动"
|
||||||
photos: "照片"
|
photos: "照片"
|
||||||
digitalClock: "数字时钟"
|
digitalClock: "数字时钟"
|
||||||
unixClock: "UNIX时钟"
|
unixClock: "UNIX时钟"
|
||||||
federation: "联邦宇宙"
|
federation: "联邦宇宙"
|
||||||
instanceCloud: "实例云"
|
instanceCloud: "服务器云端"
|
||||||
postForm: "投稿窗口"
|
postForm: "发布窗口"
|
||||||
slideshow: "幻灯片展示"
|
slideshow: "幻灯片展示"
|
||||||
button: "按钮"
|
button: "按钮"
|
||||||
onlineUsers: "在线用户"
|
onlineUsers: "在线用户"
|
||||||
jobQueue: "作业队列"
|
jobQueue: "作业队列"
|
||||||
serverMetric: "服务器监控"
|
serverMetric: "服务器指标"
|
||||||
aiscript: "AiScript控制台"
|
aiscript: "AiScript控制台"
|
||||||
aichan: "小蓝"
|
aichan: "小蓝"
|
||||||
|
userList: 用户列表
|
||||||
|
meiliStatus: 服务器状态
|
||||||
|
meiliIndexCount: 已索引的帖子
|
||||||
|
meiliSize: 索引大小
|
||||||
|
serverInfo: 服务器信息
|
||||||
_cw:
|
_cw:
|
||||||
hide: "隐藏"
|
hide: "隐藏"
|
||||||
show: "查看更多"
|
show: "查看更多"
|
||||||
|
@ -1325,7 +1371,7 @@ _poll:
|
||||||
_visibility:
|
_visibility:
|
||||||
public: "公开"
|
public: "公开"
|
||||||
publicDescription: "您的帖子将出现在全局时间线上"
|
publicDescription: "您的帖子将出现在全局时间线上"
|
||||||
home: "首页"
|
home: "不公开"
|
||||||
homeDescription: "仅发送至首页的时间线"
|
homeDescription: "仅发送至首页的时间线"
|
||||||
followers: "仅关注者"
|
followers: "仅关注者"
|
||||||
followersDescription: "仅发送至关注者"
|
followersDescription: "仅发送至关注者"
|
||||||
|
@ -1395,6 +1441,7 @@ _timelines:
|
||||||
local: "本地"
|
local: "本地"
|
||||||
social: "社交"
|
social: "社交"
|
||||||
global: "全局"
|
global: "全局"
|
||||||
|
recommended: 推荐
|
||||||
_pages:
|
_pages:
|
||||||
newPage: "创建页面"
|
newPage: "创建页面"
|
||||||
editPage: "编辑页面"
|
editPage: "编辑页面"
|
||||||
|
@ -1733,9 +1780,9 @@ _deck:
|
||||||
stackLeft: "向左折叠"
|
stackLeft: "向左折叠"
|
||||||
popRight: "向右弹出"
|
popRight: "向右弹出"
|
||||||
profile: "配置文件"
|
profile: "配置文件"
|
||||||
newProfile: "新建配置文件"
|
newProfile: "新建工作区"
|
||||||
renameProfile: "重命名配置文件"
|
renameProfile: "重命名配置文件"
|
||||||
deleteProfile: "删除配置文件"
|
deleteProfile: "删除工作区"
|
||||||
nameAlreadyExists: "该配置文件名已存在。"
|
nameAlreadyExists: "该配置文件名已存在。"
|
||||||
introduction: "将各列进行组合以创建您自己的界面!"
|
introduction: "将各列进行组合以创建您自己的界面!"
|
||||||
introduction2: "您可以随时通过屏幕右侧的 + 来添加列"
|
introduction2: "您可以随时通过屏幕右侧的 + 来添加列"
|
||||||
|
@ -1748,4 +1795,134 @@ _deck:
|
||||||
antenna: "天线"
|
antenna: "天线"
|
||||||
list: "列表"
|
list: "列表"
|
||||||
mentions: "提及"
|
mentions: "提及"
|
||||||
direct: "指定用户"
|
direct: "私信"
|
||||||
|
channel: 频道
|
||||||
|
apps: 应用
|
||||||
|
_messaging:
|
||||||
|
dms: 私信
|
||||||
|
groups: 群组
|
||||||
|
migration: 迁移
|
||||||
|
_experiments:
|
||||||
|
title: 实验性功能
|
||||||
|
license: 许可证
|
||||||
|
flagSpeakAsCatDescription: 在猫模式下你的帖子会喵化
|
||||||
|
allowedInstances: 白名单服务器
|
||||||
|
listsDesc: 列表可以让你创建含有指定用户的时间线,它们可以从时间线页面访问。
|
||||||
|
flagSpeakAsCat: 像猫一样说话
|
||||||
|
removeReaction: 移除你的回应
|
||||||
|
expandOnNoteClick: 点击打开帖子
|
||||||
|
expandOnNoteClickDesc: 如果禁用,你仍然可以在右键菜单中或通过点击时间戳打开帖子。
|
||||||
|
sendPushNotificationReadMessage: 删除已阅读的推送通知
|
||||||
|
customMOTD: 自定义 MOTD(闪屏消息)
|
||||||
|
sendPushNotificationReadMessageCaption: 短暂显示 "{emptyPushNotificationMessage}" 的通知,如果启用,可能会增加你的设备的耗电量。
|
||||||
|
adminCustomCssWarn: 仅当你知道此设置的作用时才应使用它。输入不正确的值可能会导致每个人的客户端停止正常运行。请在用户设置中进行测试来确保您的 CSS
|
||||||
|
正常工作。
|
||||||
|
customMOTDDescription: 自定义MOTD(闪屏)消息,一行一个,每次用户加载/刷新页面时都会随机显示。
|
||||||
|
customSplashIconsDescription: 用换行符隔开的自定义闪屏图标的URL,在用户每次加载/重新加载页面时随机显示。请确保图片是在一个静态的
|
||||||
|
URL 上,最好全部调整为 192x192 的大小。
|
||||||
|
recommendedInstancesDescription: 推荐的服务器以换行符分隔,它们将出现在推荐的时间线中。不要添加 "https://",仅添加域名。
|
||||||
|
splash: 启动画面
|
||||||
|
showUpdates: Calckey 更新后显示弹出窗口
|
||||||
|
selectInstance: 选择一个服务器
|
||||||
|
silencedInstances: 静默的服务器
|
||||||
|
antennaInstancesDescription: 每行列出一个服务器主机
|
||||||
|
pushNotification: 推送通知
|
||||||
|
subscribePushNotification: 启用推送通知
|
||||||
|
showAdminUpdates: 提示新的 Calckey 版本可用(仅对于管理员)
|
||||||
|
searchPlaceholder: 搜索 Calckey
|
||||||
|
addInstance: 添加一个服务器
|
||||||
|
jumpToPrevious: 跳转至上一个
|
||||||
|
silenceThisInstance: 使此服务器静音
|
||||||
|
manageGroups: 管理群组
|
||||||
|
antennasDesc: "天线会显示符合您设置条件的新帖子!\n可以从时间线页面访问它们。"
|
||||||
|
channelFederationWarn: 频道还没有与其他服务器联合
|
||||||
|
seperateRenoteQuote: 单独的推荐和引用按钮
|
||||||
|
customSplashIcons: 自定义闪屏图标(urls)
|
||||||
|
alt: 替代文字
|
||||||
|
pushNotificationNotSupported: 你的浏览器或者服务器不支持推送通知
|
||||||
|
showAds: 显示广告
|
||||||
|
enterSendsMessage: 按回车键发送信息(关闭则是 Ctrl + Retun)
|
||||||
|
recommendedInstances: 推荐服务器
|
||||||
|
updateAvailable: 可能有可用更新!
|
||||||
|
swipeOnMobile: 允许在页面之间滑动
|
||||||
|
swipeOnDesktop: 允许在桌面端以移动设备方式滑动
|
||||||
|
logoImageUrl: Logo 图像 URL
|
||||||
|
deleted: 已删除
|
||||||
|
editNote: 编辑帖子
|
||||||
|
edited: 于 {date} {time} 编辑
|
||||||
|
selectChannel: 选择一个频道
|
||||||
|
accountMoved: 用户已迁移至新账户:
|
||||||
|
silencedInstancesDescription: 列出你想静默的服务器的主机名。列出的服务器中的账户被视为 "静默",只能发出跟随请求,如果不被跟随,就不能提及本地账户。这不会影响被封锁的服务器。
|
||||||
|
hiddenTags: 隐藏的哈希标签
|
||||||
|
userSaysSomethingReason: '{name} 说 {reason}'
|
||||||
|
clipsDesc: 便签就像可共享的分类书签。您可以从各个帖子的菜单中创建便签。
|
||||||
|
privateModeInfo: 当启用时,只有白名单上的服务器可以与你的服务器联合,所有的帖子都会对公共时间线隐藏。
|
||||||
|
allowedInstancesDescription: 要列入联合白名单的服务器的主机名,一行一个(仅适用于私密模式)。
|
||||||
|
breakFollowConfirm: 你确定要移除关注者吗?
|
||||||
|
caption: 自动显示说明文字
|
||||||
|
newer: 更新的
|
||||||
|
older: 更老的
|
||||||
|
noInstances: 没有服务器
|
||||||
|
silenced: 静默的
|
||||||
|
accessibility: 无障碍
|
||||||
|
secureMode: 安全模式(仅允许授权的拉取)
|
||||||
|
replayTutorial: 重播教程
|
||||||
|
userSaysSomethingReasonReply: '{name} 回复了包含 {reason} 的帖子'
|
||||||
|
userSaysSomethingReasonQuote: '{name} 引用了一篇包含 {reason} 的帖子'
|
||||||
|
userSaysSomethingReasonRenote: '{name} 推荐了一个包含 {reason} 的帖子'
|
||||||
|
noThankYou: 不,谢谢
|
||||||
|
secureModeInfo: 当向其他服务器请求时,不要在没有验证的情况下发回。
|
||||||
|
privateMode: 私密模式
|
||||||
|
instanceSecurity: 服务器安全
|
||||||
|
image: 图像
|
||||||
|
video: 视频
|
||||||
|
audio: 音频
|
||||||
|
cannotUploadBecauseExceedsFileSizeLimit: 无法上传此文件,因为它超出了允许的最大大小。
|
||||||
|
unsubscribePushNotification: 禁用推送通知
|
||||||
|
pushNotificationAlreadySubscribed: 推送通知已启用
|
||||||
|
enableEmojiReactions: 启用 emoji 回应
|
||||||
|
cw: 内容警告
|
||||||
|
hiddenTagsDescription: 列出你想隐藏的话题标签(不带#)以避免在趋势和探索中显示。隐藏的标签仍然可以通过其他方式被发现。
|
||||||
|
enableRecommendedTimeline: 启用推荐时间线
|
||||||
|
_skinTones:
|
||||||
|
medium: 中等
|
||||||
|
light: 浅色
|
||||||
|
yellow: 黄色
|
||||||
|
dark: 深色
|
||||||
|
isModerator: 协作者
|
||||||
|
isAdmin: 管理员
|
||||||
|
findOtherInstance: 寻找其它服务器
|
||||||
|
moveFromDescription: 这将为您的旧帐户设置一个别名,以便您可以从该旧帐户转移到当前帐户。在从旧帐户转移之前执行此操作。请输入格式如@person@server.com
|
||||||
|
的帐户标签
|
||||||
|
indexPosts: 索引帖子
|
||||||
|
signupsDisabled: 该服务器目前关闭注册,但您随时可以在另一台服务器上注册!如果您有该服务器的邀请码,请在下面输入。
|
||||||
|
silencedWarning: 显示这个页面是因为这些用户来自你的管理员设置的静默服务器,所以他们有可能是垃圾信息。
|
||||||
|
isBot: 这个账户是一个机器人
|
||||||
|
moveAccountDescription: 这个过程是不可逆的。在移动之前,请确保您已在新帐户上为当前帐户设置了别名。请输入格式如 @person@server.com
|
||||||
|
帐户标签
|
||||||
|
moveFromLabel: 您要移出的旧帐户:
|
||||||
|
preventAiLearning: 阻止 AI 机器人抓取
|
||||||
|
preventAiLearningDescription: 请求第三方人工智能语言模型不要研究您上传的内容,例如帖子和图像。
|
||||||
|
noGraze: 请禁用 "Graze for Mastodon" 浏览器扩展,因为它会干扰 Calckey。
|
||||||
|
moveTo: 将当前帐户移至新帐户
|
||||||
|
moveToLabel: 你要迁移到的目标帐户:
|
||||||
|
moveAccount: 移动账户!
|
||||||
|
migrationConfirm: "你确实确定要将帐户迁移到 {account} 吗?此操作无法撤消,并且你将无法再次正常使用旧账户。\n另外,请确保你已将此当前帐户设置为要移出的帐户。"
|
||||||
|
indexFromDescription: 留空以索引每个帖子
|
||||||
|
noteId: 帖子 ID
|
||||||
|
moveFrom: 从旧帐户移至此帐户
|
||||||
|
defaultReaction: 发出和收到的帖子的默认表情符号反应
|
||||||
|
indexNotice: 现在开始索引。这可能需要一段时间,请至少一个小时内不要重新启动服务器。
|
||||||
|
indexFrom: 从帖子 ID 开始的索引
|
||||||
|
sendModMail: 发送审核通知
|
||||||
|
isLocked: 该帐户设置了关注请求
|
||||||
|
_filters:
|
||||||
|
notesBefore: 在之前的帖子
|
||||||
|
followingOnly: 仅关注中
|
||||||
|
notesAfter: 在之后的帖子
|
||||||
|
fromDomain: 来自域名
|
||||||
|
withFile: 带有文件
|
||||||
|
fromUser: 来自用户
|
||||||
|
followersOnly: 仅关注者
|
||||||
|
reactionPickerSkinTone: 首选的表情符号肤色
|
||||||
|
isPatron: Calckey 赞助
|
||||||
|
|
|
@ -1816,7 +1816,6 @@ silenceThisInstance: 靜音此伺服器
|
||||||
silencedInstances: 已靜音的伺服器
|
silencedInstances: 已靜音的伺服器
|
||||||
silenced: 已靜音
|
silenced: 已靜音
|
||||||
_experiments:
|
_experiments:
|
||||||
enablePostEditing: 啟用帖子編輯
|
|
||||||
title: 試驗功能
|
title: 試驗功能
|
||||||
findOtherInstance: 找找另一個伺服器
|
findOtherInstance: 找找另一個伺服器
|
||||||
noGraze: 瀏覽器擴展 "Graze for Mastodon" 會與Calckey發生衝突,請停用該擴展。
|
noGraze: 瀏覽器擴展 "Graze for Mastodon" 會與Calckey發生衝突,請停用該擴展。
|
||||||
|
|
|
@ -13,18 +13,19 @@ pub enum IdConvertType {
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn convert_id(in_id: String, id_convert_type: IdConvertType) -> napi::Result<String> {
|
pub fn convert_id(in_id: String, id_convert_type: IdConvertType) -> napi::Result<String> {
|
||||||
|
println!("converting id: {}", in_id);
|
||||||
use IdConvertType::*;
|
use IdConvertType::*;
|
||||||
match id_convert_type {
|
match id_convert_type {
|
||||||
MastodonId => {
|
MastodonId => {
|
||||||
let mut out: i64 = 0;
|
let mut out: i128 = 0;
|
||||||
for (i, c) in in_id.to_lowercase().chars().rev().enumerate() {
|
for (i, c) in in_id.to_lowercase().chars().rev().enumerate() {
|
||||||
out += num_from_char(c)? as i64 * 36_i64.pow(i as u32);
|
out += num_from_char(c)? as i128 * 36_i128.pow(i as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(out.to_string())
|
Ok(out.to_string())
|
||||||
}
|
}
|
||||||
CalckeyId => {
|
CalckeyId => {
|
||||||
let mut input: i64 = match in_id.parse() {
|
let mut input: i128 = match in_id.parse() {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
"ajv": "8.12.0",
|
"ajv": "8.12.0",
|
||||||
"archiver": "5.3.1",
|
"archiver": "5.3.1",
|
||||||
"argon2": "^0.30.3",
|
"argon2": "^0.30.3",
|
||||||
"async-mutex": "^0.4.0",
|
|
||||||
"autobind-decorator": "2.4.0",
|
"autobind-decorator": "2.4.0",
|
||||||
"autolinker": "4.0.0",
|
"autolinker": "4.0.0",
|
||||||
"autwh": "0.1.0",
|
"autwh": "0.1.0",
|
||||||
|
@ -112,6 +111,7 @@
|
||||||
"ratelimiter": "3.4.1",
|
"ratelimiter": "3.4.1",
|
||||||
"re2": "1.19.0",
|
"re2": "1.19.0",
|
||||||
"redis-lock": "0.1.4",
|
"redis-lock": "0.1.4",
|
||||||
|
"redis-semaphore": "5.3.1",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
"rename": "1.0.4",
|
"rename": "1.0.4",
|
||||||
"rndstr": "1.0.0",
|
"rndstr": "1.0.0",
|
||||||
|
|
|
@ -1,42 +1,48 @@
|
||||||
import probeImageSize from "probe-image-size";
|
import probeImageSize from "probe-image-size";
|
||||||
import { Mutex, withTimeout } from "async-mutex";
|
import { Mutex } from "redis-semaphore";
|
||||||
|
|
||||||
import { FILE_TYPE_BROWSERSAFE } from "@/const.js";
|
import { FILE_TYPE_BROWSERSAFE } from "@/const.js";
|
||||||
import Logger from "@/services/logger.js";
|
import Logger from "@/services/logger.js";
|
||||||
import { Cache } from "./cache.js";
|
import { redisClient } from "@/db/redis.js";
|
||||||
|
|
||||||
export type Size = {
|
export type Size = {
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const cache = new Cache<boolean>(1000 * 60 * 10); // once every 10 minutes for the same url
|
|
||||||
const mutex = withTimeout(new Mutex(), 1000);
|
|
||||||
|
|
||||||
export async function getEmojiSize(url: string): Promise<Size> {
|
|
||||||
const logger = new Logger("emoji");
|
const logger = new Logger("emoji");
|
||||||
|
|
||||||
await mutex.runExclusive(() => {
|
export async function getEmojiSize(url: string): Promise<Size> {
|
||||||
const attempted = cache.get(url);
|
let attempted = true;
|
||||||
|
|
||||||
|
const lock = new Mutex(redisClient, "getEmojiSize");
|
||||||
|
await lock.acquire();
|
||||||
|
try {
|
||||||
|
const key = `getEmojiSize:${url}`;
|
||||||
|
attempted = (await redisClient.get(key)) !== null;
|
||||||
if (!attempted) {
|
if (!attempted) {
|
||||||
cache.set(url, true);
|
await redisClient.set(key, "done", "EX", 60 * 10);
|
||||||
} else {
|
}
|
||||||
logger.warn(`Attempt limit exceeded: ${url}`);
|
} finally {
|
||||||
throw new Error("Too many attempts");
|
await lock.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attempted) {
|
||||||
|
logger.warn(`Attempt limit exceeded: ${url}`);
|
||||||
|
throw new Error("attempt limit exceeded");
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
logger.info(`Retrieving emoji size from ${url}`);
|
logger.debug(`Retrieving emoji size from ${url}`);
|
||||||
const { width, height, mime } = await probeImageSize(url, {
|
const { width, height, mime } = await probeImageSize(url, {
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
});
|
});
|
||||||
if (!(mime.startsWith("image/") && FILE_TYPE_BROWSERSAFE.includes(mime))) {
|
if (!(mime.startsWith("image/") && FILE_TYPE_BROWSERSAFE.includes(mime))) {
|
||||||
throw new Error("Unsupported image type");
|
throw new Error("unsupported image type");
|
||||||
}
|
}
|
||||||
return { width, height };
|
return { width, height };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(`Unable to retrieve metadata: ${e}`);
|
throw new Error(`unable to retrieve metadata: ${e}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -482,7 +482,8 @@ export function createCleanRemoteFilesJob() {
|
||||||
export function createIndexAllNotesJob(data = {}) {
|
export function createIndexAllNotesJob(data = {}) {
|
||||||
return backgroundQueue.add("indexAllNotes", data, {
|
return backgroundQueue.add("indexAllNotes", data, {
|
||||||
removeOnComplete: true,
|
removeOnComplete: true,
|
||||||
removeOnFail: true,
|
removeOnFail: false,
|
||||||
|
timeout: 1000 * 60 * 60 * 24,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default async function indexAllNotes(
|
||||||
let total: number = (job.data.total as number) ?? 0;
|
let total: number = (job.data.total as number) ?? 0;
|
||||||
|
|
||||||
let running = true;
|
let running = true;
|
||||||
const take = 50000;
|
const take = 100000;
|
||||||
const batch = 100;
|
const batch = 100;
|
||||||
while (running) {
|
while (running) {
|
||||||
logger.info(
|
logger.info(
|
||||||
|
|
|
@ -541,10 +541,6 @@ function notEmpty(partial: Partial<any>) {
|
||||||
export async function updateNote(value: string | IObject, resolver?: Resolver) {
|
export async function updateNote(value: string | IObject, resolver?: Resolver) {
|
||||||
const uri = typeof value === "string" ? value : value.id;
|
const uri = typeof value === "string" ? value : value.id;
|
||||||
if (!uri) throw new Error("Missing note uri");
|
if (!uri) throw new Error("Missing note uri");
|
||||||
const instanceMeta = await fetchMeta();
|
|
||||||
if (instanceMeta.experimentalFeatures?.postEdits === false) {
|
|
||||||
throw new Error("Post edits disabled.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip if URI points to this server
|
// Skip if URI points to this server
|
||||||
if (uri.startsWith(`${config.url}/`)) throw new Error("uri points local");
|
if (uri.startsWith(`${config.url}/`)) throw new Error("uri points local");
|
||||||
|
|
|
@ -476,9 +476,6 @@ export const meta = {
|
||||||
optional: true,
|
optional: true,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
properties: {
|
properties: {
|
||||||
postEditing: {
|
|
||||||
type: "boolean",
|
|
||||||
},
|
|
||||||
postImports: {
|
postImports: {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
},
|
},
|
||||||
|
|
|
@ -174,7 +174,6 @@ export const paramDef = {
|
||||||
type: "object",
|
type: "object",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
properties: {
|
properties: {
|
||||||
postEditing: { type: "boolean" },
|
|
||||||
postImports: { type: "boolean" },
|
postImports: { type: "boolean" },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -529,7 +529,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
github: instance.enableGithubIntegration,
|
github: instance.enableGithubIntegration,
|
||||||
discord: instance.enableDiscordIntegration,
|
discord: instance.enableDiscordIntegration,
|
||||||
serviceWorker: instance.enableServiceWorker,
|
serviceWorker: instance.enableServiceWorker,
|
||||||
postEditing: instance.experimentalFeatures?.postEditing || false,
|
postEditing: true,
|
||||||
postImports: instance.experimentalFeatures?.postImports || false,
|
postImports: instance.experimentalFeatures?.postImports || false,
|
||||||
miauth: true,
|
miauth: true,
|
||||||
};
|
};
|
||||||
|
|
|
@ -140,12 +140,6 @@ export const meta = {
|
||||||
code: "NOT_LOCAL_USER",
|
code: "NOT_LOCAL_USER",
|
||||||
id: "b907f407-2aa0-4283-800b-a2c56290b822",
|
id: "b907f407-2aa0-4283-800b-a2c56290b822",
|
||||||
},
|
},
|
||||||
|
|
||||||
editsDisabled: {
|
|
||||||
message: "Post edits are disabled.",
|
|
||||||
code: "EDITS_DISABLED",
|
|
||||||
id: "99306f00-fb81-11ed-be56-0242ac120002",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
@ -244,11 +238,6 @@ export const paramDef = {
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
if (user.movedToUri != null) throw new ApiError(meta.errors.accountLocked);
|
if (user.movedToUri != null) throw new ApiError(meta.errors.accountLocked);
|
||||||
|
|
||||||
const instanceMeta = await fetchMeta();
|
|
||||||
if (instanceMeta.experimentalFeatures?.postEdits === false) {
|
|
||||||
throw new ApiError(meta.errors.editsDisabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Users.isLocalUser(user)) {
|
if (!Users.isLocalUser(user)) {
|
||||||
throw new ApiError(meta.errors.notLocalUser);
|
throw new ApiError(meta.errors.notLocalUser);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,15 @@ export default define(meta, paramDef, async (ps) => {
|
||||||
if (!ps.forceUpdate && cachedPatrons) {
|
if (!ps.forceUpdate && cachedPatrons) {
|
||||||
patrons = JSON.parse(cachedPatrons);
|
patrons = JSON.parse(cachedPatrons);
|
||||||
} else {
|
} else {
|
||||||
|
AbortSignal.timeout ??= function timeout(ms) {
|
||||||
|
const ctrl = new AbortController()
|
||||||
|
setTimeout(() => ctrl.abort(), ms)
|
||||||
|
return ctrl.signal
|
||||||
|
}
|
||||||
|
|
||||||
patrons = await fetch(
|
patrons = await fetch(
|
||||||
"https://codeberg.org/calckey/calckey/raw/branch/develop/patrons.json",
|
"https://codeberg.org/calckey/calckey/raw/branch/develop/patrons.json",
|
||||||
|
{ signal: AbortSignal.timeout(2000) }
|
||||||
)
|
)
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|
|
@ -83,7 +83,7 @@ const nodeinfo2 = async () => {
|
||||||
disableGlobalTimeline: meta.disableGlobalTimeline,
|
disableGlobalTimeline: meta.disableGlobalTimeline,
|
||||||
emailRequiredForSignup: meta.emailRequiredForSignup,
|
emailRequiredForSignup: meta.emailRequiredForSignup,
|
||||||
searchFilters: config.meilisearch ? true : false,
|
searchFilters: config.meilisearch ? true : false,
|
||||||
postEditing: meta.experimentalFeatures?.postEditing || false,
|
postEditing: true,
|
||||||
postImports: meta.experimentalFeatures?.postImports || false,
|
postImports: meta.experimentalFeatures?.postImports || false,
|
||||||
enableHcaptcha: meta.enableHcaptcha,
|
enableHcaptcha: meta.enableHcaptcha,
|
||||||
enableRecaptcha: meta.enableRecaptcha,
|
enableRecaptcha: meta.enableRecaptcha,
|
||||||
|
|
|
@ -69,6 +69,7 @@ import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
||||||
import { shouldSilenceInstance } from "@/misc/should-block-instance.js";
|
import { shouldSilenceInstance } from "@/misc/should-block-instance.js";
|
||||||
import meilisearch from "../../db/meilisearch.js";
|
import meilisearch from "../../db/meilisearch.js";
|
||||||
import { redisClient } from "@/db/redis.js";
|
import { redisClient } from "@/db/redis.js";
|
||||||
|
import { Mutex } from "redis-semaphore";
|
||||||
|
|
||||||
const mutedWordsCache = new Cache<
|
const mutedWordsCache = new Cache<
|
||||||
{ userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[]
|
{ userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[]
|
||||||
|
@ -461,58 +462,43 @@ export default async (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dontFederateInitially) {
|
if (!dontFederateInitially) {
|
||||||
|
let publishKey: string;
|
||||||
|
let noteToPublish: Note;
|
||||||
const relays = await getCachedRelays();
|
const relays = await getCachedRelays();
|
||||||
|
|
||||||
// Some relays (e.g., aode-relay) deliver posts by boosting them as
|
// Some relays (e.g., aode-relay) deliver posts by boosting them as
|
||||||
// Announce activities. In that case, user is the relay's actor.
|
// Announce activities. In that case, user is the relay's actor.
|
||||||
const boostedByRelay =
|
const boostedByRelay =
|
||||||
!!user.inbox &&
|
!!user.inbox &&
|
||||||
relays.map((relay) => relay.inbox).includes(user.inbox);
|
relays.map((relay) => relay.inbox).includes(user.inbox);
|
||||||
|
|
||||||
if (!note.uri) {
|
if (boostedByRelay && data.renote && data.renote.userHost) {
|
||||||
// Publish if the post is local
|
publishKey = `publishedNote:${data.renote.id}`;
|
||||||
publishNotesStream(note);
|
noteToPublish = data.renote;
|
||||||
} else if (boostedByRelay && data.renote?.uri) {
|
} else {
|
||||||
// Use Redis transaction for atomicity
|
publishKey = `publishedNote:${note.id}`;
|
||||||
await redisClient.watch(`publishedNote:${data.renote.uri}`);
|
noteToPublish = note;
|
||||||
const exists = await redisClient.exists(
|
}
|
||||||
`publishedNote:${data.renote.uri}`,
|
|
||||||
|
const lock = new Mutex(redisClient, "publishedNote");
|
||||||
|
await lock.acquire();
|
||||||
|
try {
|
||||||
|
const published = (await redisClient.get(publishKey)) !== null;
|
||||||
|
if (!published) {
|
||||||
|
await redisClient.set(publishKey, "done", "EX", 30);
|
||||||
|
if (noteToPublish.renoteId) {
|
||||||
|
// Prevents other threads from publishing the boosting post
|
||||||
|
await redisClient.set(
|
||||||
|
`publishedNote:${noteToPublish.renoteId}`,
|
||||||
|
"done",
|
||||||
|
"EX",
|
||||||
|
30,
|
||||||
);
|
);
|
||||||
if (exists === 0) {
|
|
||||||
// Start the transaction
|
|
||||||
const transaction = redisClient.multi();
|
|
||||||
const key = `publishedNote:${data.renote.uri}`;
|
|
||||||
transaction.set(key, 1, "EX", 30);
|
|
||||||
// Execute the transaction
|
|
||||||
transaction.exec((err, replies) => {
|
|
||||||
// Publish after setting the key in Redis
|
|
||||||
if (!err && data.renote) {
|
|
||||||
publishNotesStream(data.renote);
|
|
||||||
}
|
}
|
||||||
});
|
publishNotesStream(noteToPublish);
|
||||||
} else {
|
|
||||||
// Abort the transaction
|
|
||||||
redisClient.unwatch();
|
|
||||||
}
|
|
||||||
} else if (!boostedByRelay && note.uri) {
|
|
||||||
// Use Redis transaction for atomicity
|
|
||||||
await redisClient.watch(`publishedNote:${note.uri}`);
|
|
||||||
const exists = await redisClient.exists(`publishedNote:${note.uri}`);
|
|
||||||
if (exists === 0) {
|
|
||||||
// Start the transaction
|
|
||||||
const transaction = redisClient.multi();
|
|
||||||
const key = `publishedNote:${note.uri}`;
|
|
||||||
transaction.set(key, 1, "EX", 30);
|
|
||||||
// Execute the transaction
|
|
||||||
transaction.exec((err, replies) => {
|
|
||||||
// Publish after setting the key in Redis
|
|
||||||
if (!err) {
|
|
||||||
publishNotesStream(note);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Abort the transaction
|
|
||||||
redisClient.unwatch();
|
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
await lock.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (note.replyId != null) {
|
if (note.replyId != null) {
|
||||||
|
|
|
@ -67,9 +67,8 @@ function chosen(emoji: any) {
|
||||||
function opening() {
|
function opening() {
|
||||||
try {
|
try {
|
||||||
picker.value?.reset();
|
picker.value?.reset();
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
console.error(`Something's wrong with restting the emoji picker: ${e}`);
|
||||||
console.error(`Something's wrong with restting the emoji picker: ${e}`)
|
|
||||||
}
|
}
|
||||||
picker.value?.focus();
|
picker.value?.focus();
|
||||||
}
|
}
|
||||||
|
|
|
@ -337,9 +337,7 @@ let appearNote = $computed(() =>
|
||||||
const isMyRenote = $i && $i.id === note.userId;
|
const isMyRenote = $i && $i.id === note.userId;
|
||||||
const showContent = ref(false);
|
const showContent = ref(false);
|
||||||
const isDeleted = ref(false);
|
const isDeleted = ref(false);
|
||||||
const muted = ref(
|
const muted = ref(getWordSoftMute(note, $i, defaultStore.state.mutedWords));
|
||||||
getWordSoftMute(appearNote, $i, defaultStore.state.mutedWords)
|
|
||||||
);
|
|
||||||
const translation = ref(null);
|
const translation = ref(null);
|
||||||
const translating = ref(false);
|
const translating = ref(false);
|
||||||
const enableEmojiReactions = defaultStore.state.enableEmojiReactions;
|
const enableEmojiReactions = defaultStore.state.enableEmojiReactions;
|
||||||
|
|
|
@ -53,12 +53,12 @@ const props = defineProps<{
|
||||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||||
|
|
||||||
function scrollTop() {
|
function scrollTop() {
|
||||||
scroll(tlEl.value, { top: 0, behavior: 'smooth' })
|
scroll(tlEl.value, { top: 0, behavior: "smooth" });
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
pagingComponent,
|
pagingComponent,
|
||||||
scrollTop
|
scrollTop,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
ref="tlComponent"
|
ref="tlComponent"
|
||||||
:no-gap="!$store.state.showGapBetweenNotesInTimeline"
|
:no-gap="!$store.state.showGapBetweenNotesInTimeline"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
@queue="(x) => queue = x"
|
@queue="(x) => (queue = x)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -97,13 +97,16 @@
|
||||||
><Mfm
|
><Mfm
|
||||||
:text="'$[sparkle @kainoa@calckey.social] (Main developer)'"
|
:text="'$[sparkle @kainoa@calckey.social] (Main developer)'"
|
||||||
/></FormLink>
|
/></FormLink>
|
||||||
<FormLink to="/@april@calckey.social"
|
|
||||||
><Mfm :text="'@april@calckey.social (Backend)'"
|
|
||||||
/></FormLink>
|
|
||||||
<FormLink to="/@freeplay@calckey.social"
|
<FormLink to="/@freeplay@calckey.social"
|
||||||
><Mfm
|
><Mfm
|
||||||
:text="'@freeplay@calckey.social (UI/UX)'"
|
:text="'@freeplay@calckey.social (UI/UX)'"
|
||||||
/></FormLink>
|
/></FormLink>
|
||||||
|
<FormLink to="/@nmkj@calckey.jp"
|
||||||
|
><Mfm :text="'@nmkj@calckey.jp (Backend)'"
|
||||||
|
/></FormLink>
|
||||||
|
<FormLink to="/@dev@post.naskya.net"
|
||||||
|
><Mfm :text="'@dev@post.naskya.net (Backend)'"
|
||||||
|
/></FormLink>
|
||||||
<FormLink to="/@panos@calckey.social"
|
<FormLink to="/@panos@calckey.social"
|
||||||
><Mfm
|
><Mfm
|
||||||
:text="'@panos@calckey.social (Project Coordinator)'"
|
:text="'@panos@calckey.social (Project Coordinator)'"
|
||||||
|
@ -128,6 +131,9 @@
|
||||||
><Mfm text="$[jelly ❤]" />
|
><Mfm text="$[jelly ❤]" />
|
||||||
{{ i18n.ts._aboutMisskey.patrons }}</template
|
{{ i18n.ts._aboutMisskey.patrons }}</template
|
||||||
>
|
>
|
||||||
|
<p>
|
||||||
|
{{ i18n.ts._aboutMisskey.patronsList }}
|
||||||
|
</p>
|
||||||
<MkSparkle>
|
<MkSparkle>
|
||||||
<span
|
<span
|
||||||
v-for="patron in patrons"
|
v-for="patron in patrons"
|
||||||
|
@ -164,7 +170,12 @@ import { defaultStore } from "@/store";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||||
|
|
||||||
const patrons = await os.api("patrons", { forceUpdate: true });
|
let patrons = [];
|
||||||
|
try {
|
||||||
|
patrons = await os.api("patrons", { forceUpdate: true });
|
||||||
|
} catch {
|
||||||
|
console.error("Codeberg's down.")
|
||||||
|
}
|
||||||
|
|
||||||
let easterEggReady = false;
|
let easterEggReady = false;
|
||||||
let easterEggEmojis = $ref([]);
|
let easterEggEmojis = $ref([]);
|
||||||
|
|
|
@ -8,19 +8,6 @@
|
||||||
/></template>
|
/></template>
|
||||||
<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
|
<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
|
||||||
<FormSuspense :p="init">
|
<FormSuspense :p="init">
|
||||||
<FormSwitch
|
|
||||||
v-model="enablePostEditing"
|
|
||||||
@update:modelValue="save"
|
|
||||||
class="_formBlock"
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<i class="ph-pencil-line ph-bold ph-lg"></i>
|
|
||||||
{{ i18n.ts._experiments.enablePostEditing }}
|
|
||||||
</template>
|
|
||||||
<template #caption>{{
|
|
||||||
i18n.ts._experiments.postEditingCaption
|
|
||||||
}}</template>
|
|
||||||
</FormSwitch>
|
|
||||||
<FormSwitch
|
<FormSwitch
|
||||||
v-model="enablePostImports"
|
v-model="enablePostImports"
|
||||||
@update:modelValue="save"
|
@update:modelValue="save"
|
||||||
|
@ -49,13 +36,11 @@ import { fetchInstance } from "@/instance";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||||
|
|
||||||
let enablePostEditing = $ref(false);
|
|
||||||
let enablePostImports = $ref(false);
|
let enablePostImports = $ref(false);
|
||||||
let meta = $ref<MetaExperiments | null>(null);
|
let meta = $ref<MetaExperiments | null>(null);
|
||||||
|
|
||||||
type MetaExperiments = {
|
type MetaExperiments = {
|
||||||
experimentalFeatures?: {
|
experimentalFeatures?: {
|
||||||
postEditing?: boolean;
|
|
||||||
postImports?: boolean;
|
postImports?: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -64,14 +49,12 @@ async function init() {
|
||||||
meta = (await os.api("admin/meta")) as MetaExperiments;
|
meta = (await os.api("admin/meta")) as MetaExperiments;
|
||||||
if (!meta) return;
|
if (!meta) return;
|
||||||
|
|
||||||
enablePostEditing = meta.experimentalFeatures?.postEditing ?? false;
|
|
||||||
enablePostImports = meta.experimentalFeatures?.postImports ?? false;
|
enablePostImports = meta.experimentalFeatures?.postImports ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
const experiments: MetaExperiments = {
|
const experiments: MetaExperiments = {
|
||||||
experimentalFeatures: {
|
experimentalFeatures: {
|
||||||
postEditing: enablePostEditing,
|
|
||||||
postImports: enablePostImports,
|
postImports: enablePostImports,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
:value="usersComparedToThePrevDay"
|
:value="usersComparedToThePrevDay"
|
||||||
></MkNumberDiff>
|
></MkNumberDiff>
|
||||||
</div>
|
</div>
|
||||||
<div class="label">Users</div>
|
<div class="label">{{ i18n.ts.users }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item _panel notes">
|
<div class="item _panel notes">
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
:value="notesComparedToThePrevDay"
|
:value="notesComparedToThePrevDay"
|
||||||
></MkNumberDiff>
|
></MkNumberDiff>
|
||||||
</div>
|
</div>
|
||||||
<div class="label">Posts</div>
|
<div class="label">{{ i18n.ts.notes }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item _panel instances">
|
<div class="item _panel instances">
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
style="margin-right: 0.5em"
|
style="margin-right: 0.5em"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="label">Instances</div>
|
<div class="label">{{ i18n.ts.instances }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item _panel online">
|
<div class="item _panel online">
|
||||||
|
@ -69,10 +69,26 @@
|
||||||
style="margin-right: 0.5em"
|
style="margin-right: 0.5em"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="label">Online</div>
|
<div class="label">{{ i18n.ts.online }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item _panel emojis">
|
||||||
|
<div class="icon">
|
||||||
|
<i class="ph-smiley ph-bold ph-xl"></i>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<div class="value">
|
||||||
|
<MkNumber
|
||||||
|
:value="emojiCount"
|
||||||
|
style="margin-right: 0.5em"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="label">{{ i18n.ts.emojis }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- TODO: Drive -->
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -90,6 +106,7 @@ let stats: any = $ref(null);
|
||||||
let usersComparedToThePrevDay = $ref<number>();
|
let usersComparedToThePrevDay = $ref<number>();
|
||||||
let notesComparedToThePrevDay = $ref<number>();
|
let notesComparedToThePrevDay = $ref<number>();
|
||||||
let onlineUsersCount = $ref(0);
|
let onlineUsersCount = $ref(0);
|
||||||
|
let emojiCount = $ref(0);
|
||||||
let fetching = $ref(true);
|
let fetching = $ref(true);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
@ -110,6 +127,10 @@ onMounted(async () => {
|
||||||
stats.originalNotesCount - chart.local.total[1];
|
stats.originalNotesCount - chart.local.total[1];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
os.api("meta", { detail: false }).then((meta) => {
|
||||||
|
emojiCount = meta.emojis.length;
|
||||||
|
});
|
||||||
|
|
||||||
fetching = false;
|
fetching = false;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -172,6 +193,13 @@ onMounted(async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.drive {
|
||||||
|
> .icon {
|
||||||
|
background: #b4637a22;
|
||||||
|
color: #eb6f92;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
> .body {
|
> .body {
|
||||||
padding: 2px 0;
|
padding: 2px 0;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,9 @@
|
||||||
<div
|
<div
|
||||||
ref="bannerEl"
|
ref="bannerEl"
|
||||||
class="banner"
|
class="banner"
|
||||||
:style="{ backgroundImage: `url('${user.bannerUrl}')` }"
|
:style="{
|
||||||
|
backgroundImage: `url('${user.bannerUrl}')`,
|
||||||
|
}"
|
||||||
></div>
|
></div>
|
||||||
<div class="fade"></div>
|
<div class="fade"></div>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
|
@ -449,7 +451,12 @@ const timeForThem = $computed(() => {
|
||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
const patrons = await os.api("patrons");
|
let patrons = [];
|
||||||
|
try {
|
||||||
|
patrons = await os.api("patrons");
|
||||||
|
} catch {
|
||||||
|
console.error("Codeberg's down.")
|
||||||
|
}
|
||||||
|
|
||||||
function parallaxLoop() {
|
function parallaxLoop() {
|
||||||
parallaxAnimationId = window.requestAnimationFrame(parallaxLoop);
|
parallaxAnimationId = window.requestAnimationFrame(parallaxLoop);
|
||||||
|
@ -510,7 +517,7 @@ onUnmounted(() => {
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
filter: blur(12px) opacity(.1);
|
filter: blur(12px) opacity(0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -408,7 +408,7 @@ export function getNoteMenu(props: {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
instance.features.postEditing && isAppearAuthor
|
isAppearAuthor
|
||||||
? {
|
? {
|
||||||
icon: "ph-pencil-line ph-bold ph-lg",
|
icon: "ph-pencil-line ph-bold ph-lg",
|
||||||
text: i18n.ts.edit,
|
text: i18n.ts.edit,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<span class="year">{{ i18n.t("yearX", { year }) }}</span>
|
<span class="year">{{ i18n.t("yearX", { year }) }}</span>
|
||||||
<span class="month">{{ i18n.t("monthX", { month }) }}</span>
|
<span class="month">{{ i18n.t("monthX", { month }) }}</span>
|
||||||
</p>
|
</p>
|
||||||
<p v-if="month === 1 && day === 1" class="day">
|
<p v-if="(month === 1 && day === 1) || isBirthday" class="day">
|
||||||
🎉{{ i18n.t("dayX", { day })
|
🎉{{ i18n.t("dayX", { day })
|
||||||
}}<span style="display: inline-block; transform: scaleX(-1)"
|
}}<span style="display: inline-block; transform: scaleX(-1)"
|
||||||
>🎉</span
|
>🎉</span
|
||||||
|
@ -55,6 +55,7 @@ import {
|
||||||
import { GetFormResultType } from "@/scripts/form";
|
import { GetFormResultType } from "@/scripts/form";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
import { useInterval } from "@/scripts/use-interval";
|
import { useInterval } from "@/scripts/use-interval";
|
||||||
|
import { $i } from "@/account";
|
||||||
|
|
||||||
const name = "calendar";
|
const name = "calendar";
|
||||||
|
|
||||||
|
@ -80,6 +81,8 @@ const { widgetProps, configure } = useWidgetPropsManager(
|
||||||
emit
|
emit
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const hasBirthday = Boolean($i?.birthday);
|
||||||
|
|
||||||
const year = ref(0);
|
const year = ref(0);
|
||||||
const month = ref(0);
|
const month = ref(0);
|
||||||
const day = ref(0);
|
const day = ref(0);
|
||||||
|
@ -88,6 +91,8 @@ const yearP = ref(0);
|
||||||
const monthP = ref(0);
|
const monthP = ref(0);
|
||||||
const dayP = ref(0);
|
const dayP = ref(0);
|
||||||
const isHoliday = ref(false);
|
const isHoliday = ref(false);
|
||||||
|
const isBirthday = ref(false);
|
||||||
|
|
||||||
const tick = () => {
|
const tick = () => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const nd = now.getDate();
|
const nd = now.getDate();
|
||||||
|
@ -121,6 +126,13 @@ const tick = () => {
|
||||||
yearP.value = (yearNumer / yearDenom) * 100;
|
yearP.value = (yearNumer / yearDenom) * 100;
|
||||||
|
|
||||||
isHoliday.value = now.getDay() === 0 || now.getDay() === 6;
|
isHoliday.value = now.getDay() === 0 || now.getDay() === 6;
|
||||||
|
|
||||||
|
if (hasBirthday) {
|
||||||
|
const [bdayYear, bdayMonth, bdayDay] = $i.birthday.split("-");
|
||||||
|
if (month.value === +bdayMonth && day.value == +bdayDay) {
|
||||||
|
isBirthday.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useInterval(tick, 1000, {
|
useInterval(tick, 1000, {
|
||||||
|
|
13
patrons.json
13
patrons.json
|
@ -10,17 +10,15 @@
|
||||||
"@griff@stop.voring.me",
|
"@griff@stop.voring.me",
|
||||||
"@cafkafk@ck.cafkafk.com",
|
"@cafkafk@ck.cafkafk.com",
|
||||||
"@privateger@plasmatrap.com",
|
"@privateger@plasmatrap.com",
|
||||||
"@self@neo.voidworks.cc",
|
"@effye@toot.thoughtworks.com",
|
||||||
"@effy@social.effy.space",
|
|
||||||
"@Kio@kitsunes.club",
|
"@Kio@kitsunes.club",
|
||||||
"@twann@tech.lgbt",
|
"@twann@tech.lgbt",
|
||||||
"@surfbum@calckey.nz",
|
"@surfbum@calckey.nz",
|
||||||
"@topher@mastodon.online",
|
"@topher@mastodon.online",
|
||||||
"@hanicef@stop.voring.me",
|
"@hanicef@stop.voring.me",
|
||||||
"@nmkj@calckey.jp",
|
"@nmkj@calckey.jp",
|
||||||
"@trapezial@calckey.jp",
|
|
||||||
"@unattributed@calckey.social",
|
"@unattributed@calckey.social",
|
||||||
"@cody@mk.codingneko.com",
|
"@cody@misskey.codingneko.com",
|
||||||
"@kate@blahaj.zone",
|
"@kate@blahaj.zone",
|
||||||
"@emtk@mkkey.net",
|
"@emtk@mkkey.net",
|
||||||
"@jovikowi@calckey.social",
|
"@jovikowi@calckey.social",
|
||||||
|
@ -35,13 +33,12 @@
|
||||||
"@box464@calckey.social",
|
"@box464@calckey.social",
|
||||||
"@MariaTheMartian@calckey.social",
|
"@MariaTheMartian@calckey.social",
|
||||||
"@nisemikol@calckey.social",
|
"@nisemikol@calckey.social",
|
||||||
"@smallpatatas@calckey.patatas.ca",
|
"@smallpatatas@blahaj.zone",
|
||||||
"@bayra@stop.voring.me",
|
"@bayra@stop.voring.me",
|
||||||
"@frost@wolfdo.gg",
|
"@frost@wolfdo.gg",
|
||||||
"@joebiden@fuckgov.org",
|
"@joebiden@fuckgov.org",
|
||||||
"@nyaa@calckey.social",
|
"@nyaa@calckey.social",
|
||||||
"@Dan@calckey.social",
|
"@Dan@calckey.social",
|
||||||
"@testing@stop.voring.me",
|
|
||||||
"@dana@calckey.social",
|
"@dana@calckey.social",
|
||||||
"@Jdreben@calckey.social",
|
"@Jdreben@calckey.social",
|
||||||
"@natalie@prismst.one",
|
"@natalie@prismst.one",
|
||||||
|
@ -77,6 +74,10 @@
|
||||||
"@jtbennett@noc.social",
|
"@jtbennett@noc.social",
|
||||||
"@renere@distance.blue",
|
"@renere@distance.blue",
|
||||||
"@theking@kitsunes.club",
|
"@theking@kitsunes.club",
|
||||||
|
"@toof@fedi.toofie.net",
|
||||||
|
"@Punko@calckey.social",
|
||||||
|
"@joesbrat67@calckey.social",
|
||||||
|
"@arth@calckey.social",
|
||||||
"\nInterkosmos Link"
|
"\nInterkosmos Link"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
111
pnpm-lock.yaml
111
pnpm-lock.yaml
|
@ -132,9 +132,6 @@ importers:
|
||||||
argon2:
|
argon2:
|
||||||
specifier: ^0.30.3
|
specifier: ^0.30.3
|
||||||
version: 0.30.3
|
version: 0.30.3
|
||||||
async-mutex:
|
|
||||||
specifier: ^0.4.0
|
|
||||||
version: 0.4.0
|
|
||||||
autobind-decorator:
|
autobind-decorator:
|
||||||
specifier: 2.4.0
|
specifier: 2.4.0
|
||||||
version: 2.4.0
|
version: 2.4.0
|
||||||
|
@ -339,6 +336,9 @@ importers:
|
||||||
redis-lock:
|
redis-lock:
|
||||||
specifier: 0.1.4
|
specifier: 0.1.4
|
||||||
version: 0.1.4
|
version: 0.1.4
|
||||||
|
redis-semaphore:
|
||||||
|
specifier: 5.3.1
|
||||||
|
version: 5.3.1(ioredis@5.3.2)
|
||||||
reflect-metadata:
|
reflect-metadata:
|
||||||
specifier: 0.1.13
|
specifier: 0.1.13
|
||||||
version: 0.1.13
|
version: 0.1.13
|
||||||
|
@ -598,7 +598,7 @@ importers:
|
||||||
version: 5.1.3
|
version: 5.1.3
|
||||||
webpack:
|
webpack:
|
||||||
specifier: ^5.85.1
|
specifier: ^5.85.1
|
||||||
version: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3)
|
version: 5.85.1(@swc/core@1.3.62)
|
||||||
ws:
|
ws:
|
||||||
specifier: 8.13.0
|
specifier: 8.13.0
|
||||||
version: 8.13.0
|
version: 8.13.0
|
||||||
|
@ -2666,6 +2666,7 @@ packages:
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@swc/wasm': 1.2.130
|
'@swc/wasm': 1.2.130
|
||||||
|
|
||||||
|
@ -2772,6 +2773,7 @@ packages:
|
||||||
|
|
||||||
/@swc/wasm@1.2.130:
|
/@swc/wasm@1.2.130:
|
||||||
resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==}
|
resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==}
|
||||||
|
requiresBuild: true
|
||||||
|
|
||||||
/@syuilo/aiscript@0.11.1:
|
/@syuilo/aiscript@0.11.1:
|
||||||
resolution: {integrity: sha512-chwOIA3yLUKvOB0G611hjLArKTeOWNmTm3lHERSaDW1d+dS6do56naX6Lkwy2UpnwWC0qzeNSgg35elk6t2gZg==}
|
resolution: {integrity: sha512-chwOIA3yLUKvOB0G611hjLArKTeOWNmTm3lHERSaDW1d+dS6do56naX6Lkwy2UpnwWC0qzeNSgg35elk6t2gZg==}
|
||||||
|
@ -4491,12 +4493,6 @@ packages:
|
||||||
stream-exhaust: 1.0.2
|
stream-exhaust: 1.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/async-mutex@0.4.0:
|
|
||||||
resolution: {integrity: sha512-eJFZ1YhRR8UN8eBLoNzcDPcy/jqjsg6I1AP+KvWQX80BqOSW1oJPJXDylPUEeMr2ZQvHgnQ//Lp6f3RQ1zI7HA==}
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.6.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/async-settle@1.0.0:
|
/async-settle@1.0.0:
|
||||||
resolution: {integrity: sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==}
|
resolution: {integrity: sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
|
@ -4641,7 +4637,7 @@ packages:
|
||||||
/axios@0.24.0:
|
/axios@0.24.0:
|
||||||
resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==}
|
resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects: 1.15.2(debug@4.3.4)
|
follow-redirects: 1.15.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- debug
|
- debug
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -4657,7 +4653,7 @@ packages:
|
||||||
/axios@1.2.2:
|
/axios@1.2.2:
|
||||||
resolution: {integrity: sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==}
|
resolution: {integrity: sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects: 1.15.2(debug@4.3.4)
|
follow-redirects: 1.15.2
|
||||||
form-data: 4.0.0
|
form-data: 4.0.0
|
||||||
proxy-from-env: 1.1.0
|
proxy-from-env: 1.1.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -4667,7 +4663,7 @@ packages:
|
||||||
/axios@1.4.0:
|
/axios@1.4.0:
|
||||||
resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==}
|
resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects: 1.15.2(debug@4.3.4)
|
follow-redirects: 1.15.2
|
||||||
form-data: 4.0.0
|
form-data: 4.0.0
|
||||||
proxy-from-env: 1.1.0
|
proxy-from-env: 1.1.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -6283,6 +6279,17 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.0.0
|
ms: 2.0.0
|
||||||
|
|
||||||
|
/debug@3.2.7:
|
||||||
|
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
|
||||||
|
peerDependencies:
|
||||||
|
supports-color: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
supports-color:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
ms: 2.1.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/debug@3.2.7(supports-color@8.1.1):
|
/debug@3.2.7(supports-color@8.1.1):
|
||||||
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
|
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -6293,6 +6300,7 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
supports-color: 8.1.1
|
supports-color: 8.1.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/debug@4.3.3:
|
/debug@4.3.3:
|
||||||
resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==}
|
resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==}
|
||||||
|
@ -7530,6 +7538,16 @@ packages:
|
||||||
tabbable: 6.2.0
|
tabbable: 6.2.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/follow-redirects@1.15.2:
|
||||||
|
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
||||||
|
engines: {node: '>=4.0'}
|
||||||
|
peerDependencies:
|
||||||
|
debug: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
debug:
|
||||||
|
optional: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/follow-redirects@1.15.2(debug@4.3.4):
|
/follow-redirects@1.15.2(debug@4.3.4):
|
||||||
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
|
@ -7540,6 +7558,7 @@ packages:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.3.4(supports-color@8.1.1)
|
debug: 4.3.4(supports-color@8.1.1)
|
||||||
|
dev: true
|
||||||
|
|
||||||
/for-each@0.3.3:
|
/for-each@0.3.3:
|
||||||
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
|
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
|
||||||
|
@ -8450,7 +8469,7 @@ packages:
|
||||||
engines: {node: '>= 4.5.0'}
|
engines: {node: '>= 4.5.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 4.3.0
|
agent-base: 4.3.0
|
||||||
debug: 3.2.7(supports-color@8.1.1)
|
debug: 3.2.7
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -9849,7 +9868,7 @@ packages:
|
||||||
json5: 2.2.3
|
json5: 2.2.3
|
||||||
loader-utils: 2.0.4
|
loader-utils: 2.0.4
|
||||||
schema-utils: 3.3.0
|
schema-utils: 3.3.0
|
||||||
webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3)
|
webpack: 5.85.1(@swc/core@1.3.62)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/json5@2.2.3:
|
/json5@2.2.3:
|
||||||
|
@ -10092,7 +10111,7 @@ packages:
|
||||||
resolution: {integrity: sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==}
|
resolution: {integrity: sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==}
|
||||||
engines: {node: '>= 7.6.0'}
|
engines: {node: '>= 7.6.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7(supports-color@8.1.1)
|
debug: 3.2.7
|
||||||
koa-send: 5.0.1
|
koa-send: 5.0.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
@ -11086,7 +11105,7 @@ packages:
|
||||||
engines: {node: '>= 4.4.x'}
|
engines: {node: '>= 4.4.x'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7(supports-color@8.1.1)
|
debug: 3.2.7
|
||||||
iconv-lite: 0.4.24
|
iconv-lite: 0.4.24
|
||||||
sax: 1.2.4
|
sax: 1.2.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -12831,6 +12850,18 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
redis-errors: 1.2.0
|
redis-errors: 1.2.0
|
||||||
|
|
||||||
|
/redis-semaphore@5.3.1(ioredis@5.3.2):
|
||||||
|
resolution: {integrity: sha512-oUpxxfxSbh5eT0mvVpz2d4Qlg2CsaoQkeo80/v6CU2l97zO0u6NPgc9/zQZa9KGR3/93b0igtSct3hEFh8Ei8w==}
|
||||||
|
engines: {node: '>= 14.17.0'}
|
||||||
|
peerDependencies:
|
||||||
|
ioredis: ^4.1.0 || ^5
|
||||||
|
dependencies:
|
||||||
|
debug: 4.3.4(supports-color@8.1.1)
|
||||||
|
ioredis: 5.3.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
/redis@4.6.7:
|
/redis@4.6.7:
|
||||||
resolution: {integrity: sha512-KrkuNJNpCwRm5vFJh0tteMxW8SaUzkm5fBH7eL5hd/D0fAkzvapxbfGPP/r+4JAXdQuX7nebsBkBqA2RHB7Usw==}
|
resolution: {integrity: sha512-KrkuNJNpCwRm5vFJh0tteMxW8SaUzkm5fBH7eL5hd/D0fAkzvapxbfGPP/r+4JAXdQuX7nebsBkBqA2RHB7Usw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -13980,7 +14011,7 @@ packages:
|
||||||
webpack: '>=2'
|
webpack: '>=2'
|
||||||
dependencies:
|
dependencies:
|
||||||
'@swc/core': 1.3.62
|
'@swc/core': 1.3.62
|
||||||
webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3)
|
webpack: 5.85.1(@swc/core@1.3.62)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/swiper@9.3.2:
|
/swiper@9.3.2:
|
||||||
|
@ -14101,7 +14132,7 @@ packages:
|
||||||
schema-utils: 3.3.0
|
schema-utils: 3.3.0
|
||||||
serialize-javascript: 6.0.1
|
serialize-javascript: 6.0.1
|
||||||
terser: 5.18.2
|
terser: 5.18.2
|
||||||
webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3)
|
webpack: 5.85.1(@swc/core@1.3.62)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/terser@5.18.2:
|
/terser@5.18.2:
|
||||||
|
@ -14401,7 +14432,7 @@ packages:
|
||||||
micromatch: 4.0.5
|
micromatch: 4.0.5
|
||||||
semver: 7.5.1
|
semver: 7.5.1
|
||||||
typescript: 5.1.3
|
typescript: 5.1.3
|
||||||
webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3)
|
webpack: 5.85.1(@swc/core@1.3.62)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/ts-node@10.4.0(@swc/core@1.3.62)(@types/node@20.3.1)(typescript@5.1.3):
|
/ts-node@10.4.0(@swc/core@1.3.62)(@types/node@20.3.1)(typescript@5.1.3):
|
||||||
|
@ -15235,6 +15266,46 @@ packages:
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/webpack@5.85.1(@swc/core@1.3.62):
|
||||||
|
resolution: {integrity: sha512-xTb7MRf4LY8Z5rzn7aIx4TDrwYJrjcHnIfU1TqtyZOoObyuGSpAUwIvVuqq5wPnv7WEgQr8UvO1q/dgoGG4HjA==}
|
||||||
|
engines: {node: '>=10.13.0'}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
webpack-cli: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
webpack-cli:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@types/eslint-scope': 3.7.4
|
||||||
|
'@types/estree': 1.0.1
|
||||||
|
'@webassemblyjs/ast': 1.11.6
|
||||||
|
'@webassemblyjs/wasm-edit': 1.11.6
|
||||||
|
'@webassemblyjs/wasm-parser': 1.11.6
|
||||||
|
acorn: 8.9.0
|
||||||
|
acorn-import-assertions: 1.9.0(acorn@8.9.0)
|
||||||
|
browserslist: 4.21.9
|
||||||
|
chrome-trace-event: 1.0.3
|
||||||
|
enhanced-resolve: 5.15.0
|
||||||
|
es-module-lexer: 1.3.0
|
||||||
|
eslint-scope: 5.1.1
|
||||||
|
events: 3.3.0
|
||||||
|
glob-to-regexp: 0.4.1
|
||||||
|
graceful-fs: 4.2.11
|
||||||
|
json-parse-even-better-errors: 2.3.1
|
||||||
|
loader-runner: 4.3.0
|
||||||
|
mime-types: 2.1.35
|
||||||
|
neo-async: 2.6.2
|
||||||
|
schema-utils: 3.3.0
|
||||||
|
tapable: 2.2.1
|
||||||
|
terser-webpack-plugin: 5.3.9(@swc/core@1.3.62)(webpack@5.85.1)
|
||||||
|
watchpack: 2.4.0
|
||||||
|
webpack-sources: 3.2.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@swc/core'
|
||||||
|
- esbuild
|
||||||
|
- uglify-js
|
||||||
|
dev: true
|
||||||
|
|
||||||
/webpack@5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3):
|
/webpack@5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3):
|
||||||
resolution: {integrity: sha512-xTb7MRf4LY8Z5rzn7aIx4TDrwYJrjcHnIfU1TqtyZOoObyuGSpAUwIvVuqq5wPnv7WEgQr8UvO1q/dgoGG4HjA==}
|
resolution: {integrity: sha512-xTb7MRf4LY8Z5rzn7aIx4TDrwYJrjcHnIfU1TqtyZOoObyuGSpAUwIvVuqq5wPnv7WEgQr8UvO1q/dgoGG4HjA==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
|
|
Loading…
Reference in New Issue