Compare commits

...

16 Commits

Author SHA1 Message Date
Puniko 3fc984ad2d Merge branch 'refactor-deliver-actor' into mk.absturztau.be 2023-05-06 19:59:36 +02:00
Puniko c3a6dcd6f0 Revert "Merge branch 'refactor-deliver-actor' into mk.absturztau.be"
This reverts commit 76b4e4ee08, reversing
changes made to 22f2ac427f.
2023-05-06 19:59:18 +02:00
Puniko 3d1a991051 Merge branch 'main' into mk.absturztau.be 2023-05-06 19:54:28 +02:00
Chloe Kudryavtsev 0ad0ab7589 Translated using Weblate (Russian)
Currently translated at 96.1% (1161 of 1208 strings)

Co-authored-by: Chloe Kudryavtsev <code@toast.bunkerlabs.net>
Translate-URL: http://translate.akkoma.dev/projects/foundkey/foundkey/ru/
Translation: Foundkey/foundkey
2023-05-05 10:11:46 +00:00
ogur4ik 7972540e3a Translated using Weblate (Russian)
Currently translated at 96.1% (1161 of 1208 strings)

Translated using Weblate (Russian)

Currently translated at 90.5% (1094 of 1208 strings)

Co-authored-by: ogur4ik <abrew1330@gmail.com>
Translate-URL: http://translate.akkoma.dev/projects/foundkey/foundkey/ru/
Translation: Foundkey/foundkey
2023-05-05 10:11:46 +00:00
Johann150 ba77a81cc0
fix: require async for deliver queue 2023-05-04 21:43:09 +02:00
Johann150 b04ef21b6e
fix missing parameter name 2023-05-01 20:45:47 +02:00
Johann150 965ee4b041
fix for delivering multiple activities at once 2023-05-01 12:41:39 +02:00
Johann150 34d55e2dda
server: better matching for MFM mentions
When rendering the HTML for outgoing activities, the mentions are now
matched case insensitive and should also work properly for IDNs. The
username is also compared case insensitive. Mentions of local users
are also handled properly independed of whether the hostname was given
or omitted.

The query to get mentions is now also only executed once instead of
for each mention individually.

Changelog: Fixed
2023-04-28 23:47:48 +02:00
kazari 1d99657a45 Translated using Weblate (Japanese)
Currently translated at 99.8% (1206 of 1208 strings)

Co-authored-by: kazari <6c577a54-aac9-482a-955e-745c858445e3@simplelogin.com>
Translate-URL: http://translate.akkoma.dev/projects/foundkey/foundkey/ja/
Translation: Foundkey/foundkey
2023-04-27 17:57:55 +00:00
mondstern bd598cd9ba Translated using Weblate (Indonesian)
Currently translated at 92.1% (1113 of 1208 strings)

Co-authored-by: mondstern <mondstern@monocles.de>
Translate-URL: http://translate.akkoma.dev/projects/foundkey/foundkey/id/
Translation: Foundkey/foundkey
2023-04-27 17:57:55 +00:00
Johann150 b374a79eb1
activitypub: no longer deliver chat read
Prospectively, the messaging messages will be removed as objects so
it does not make sense to refactor this to match the remainder of
refactoring away the user from deliver. It is just easier to remove
this use of delivering something that is not an activity.

Changelog: Removed
2023-04-24 22:55:38 +02:00
Johann150 c978a687e9
remove unused user parameter from deliver 2023-04-24 22:55:36 +02:00
Johann150 4dc8822d05
remove unnecesary intermediate variables 2023-04-24 22:54:23 +02:00
Johann150 ff4b6d932e
refactor deliver to extract actor from activity 2023-04-24 22:54:12 +02:00
Johann150 a786fd99fc
make delivery manager author agnostic 2023-04-24 22:07:05 +02:00
18 changed files with 200 additions and 92 deletions

View File

@ -12,7 +12,7 @@ password: "Kata sandi"
forgotPassword: "Lupa Kata Sandi"
fetchingAsApObject: "Mengambil data dari Fediverse..."
ok: "OK"
gotIt: "Saya mengerti"
gotIt: "Saya mengerti!"
cancel: "Batalkan"
renotedBy: "direnote oleh {user}"
noNotes: "Tidak ada catatan"
@ -24,7 +24,7 @@ otherSettings: "Pengaturan lainnya"
openInWindow: "Buka di jendela"
profile: "Profil"
timeline: "Linimasa"
noAccountDescription: "Pengguna ini belum menulis bio"
noAccountDescription: "Pengguna ini belum menulis biodata mereka."
login: "Masuk"
loggingIn: "Sedang masuk"
logout: "Keluar"
@ -62,8 +62,8 @@ files: "Berkas"
download: "Unduh"
driveFileDeleteConfirm: "Hapus {name}? Catatan dengan berkas terkait juga akan terhapus."
unfollowConfirm: "Berhenti mengikuti {name}?"
exportRequested: "Kamu telah meminta ekspor. Ini akan memakan waktu sesaat. Setelah\
\ ekspor selesai, berkas yang dihasilkan akan ditambahkan ke Drive"
exportRequested: "Anda telah meminta ekspor. Ini mungkin memerlukan waktu beberapa\
\ saat. File ini akan ditambahkan ke Drive Anda setelah selesai."
importRequested: "Kamu telah meminta impor. Ini akan memakan waktu sesaat."
lists: "Daftar"
note: "Catat"
@ -100,8 +100,8 @@ clickToShow: "Klik untuk melihat"
sensitive: "Konten sensitif"
add: "Tambahkan"
reaction: "Reaksi"
reactionSettingDescription2: "Geser untuk memindah urutkan, klik untuk menghapus,\
\ tekan \"+\" untuk menambahkan"
reactionSettingDescription2: "Seret untuk menyusun ulang, klik untuk menghapus, tekan\
\ \"+\" untuk menambahkan."
attachCancel: "Hapus lampiran"
markAsSensitive: "Tandai sebagai konten sensitif"
unmarkAsSensitive: "Hapus tanda konten sensitif"
@ -193,10 +193,10 @@ blockedUsers: "Pengguna yang diblokir"
noUsers: "Tidak ada pengguna"
editProfile: "Sunting profil"
noteDeleteConfirm: "Apakah kamu yakin ingin menghapus catatan ini?"
pinLimitExceeded: "Kamu tidak dapat menyematkan catatan lagi"
pinLimitExceeded: "Anda tidak dapat menyematkan catatan lagi."
intro: "Instalasi FoundKey telah selesai! Mohon untuk membuat pengguna admin."
done: "Selesai"
processing: "Memproses"
processing: "Pemrosesan..."
preview: "Pratinjau"
default: "Bawaan"
noCustomEmojis: "Tidak ada emoji kustom"
@ -210,7 +210,7 @@ publishing: "Sedang menyiarkan langsung"
notResponding: "Tidak ada respon"
changePassword: "Ubah kata sandi"
security: "Keamanan"
retypedNotMatch: "Input tidak sama"
retypedNotMatch: "Input tidak cocok."
currentPassword: "Kata sandi saat ini"
newPassword: "Kata sandi baru"
newPasswordRetype: "Ulangi kata sandi baru"
@ -237,7 +237,7 @@ fromUrl: "Dari URL"
uploadFromUrl: "Unggah dari URL"
uploadFromUrlDescription: "URL berkas yang ingin kamu unggah"
uploadFromUrlRequested: "Pengunggahan telah diminta"
uploadFromUrlMayTakeTime: "Membutuhkan beberapa waktu hingga pengunggahan selesai"
uploadFromUrlMayTakeTime: "Mungkin diperlukan waktu hingga unggahan selesai."
explore: "Jelajahi"
messageRead: "Telah dibaca"
noMoreHistory: "Tidak ada sejarah lagi"
@ -403,7 +403,7 @@ newMessageExists: "Kamu mendapatkan pesan baru"
onlyOneFileCanBeAttached: "Kamu hanya dapat melampirkan satu berkas ke dalam pesan"
signinRequired: "Silahkan login"
invitationCode: "Kode undangan"
checking: "Memeriksa"
checking: "Memeriksa..."
available: "Tersedia"
unavailable: "Tidak tersedia"
usernameInvalidFormat: "Hanya dapat menerima karakter a-z, A-Z dan angka 0-9."
@ -445,11 +445,10 @@ showFeaturedNotesInTimeline: "Tampilkan catatan yang diunggulkan di linimasa"
objectStorage: "Object Storage"
useObjectStorage: "Gunakan object storage"
objectStorageBaseUrl: "Base URL"
objectStorageBaseUrlDesc: "Prefix URL digunakan untuk mengkonstruksi URL ke object\
\ (media) referencing. Tentukan URL jika kamu menggunakan CDN atau Proxy, jika tidak\
\ tentukan alamat yang dapat diakses secara publik sesuai dengan panduan dari layanan\
\ yang akan kamu gunakan, contohnya. 'https://<bucket>.s3.amazonaws.com' untuk AWS\
\ S3, dan 'https://storage.googleapis.com/<bucket>' untuk GCS."
objectStorageBaseUrlDesc: "URL yang digunakan sebagai referensi. Tentukan URL CDN\
\ atau Proksi Anda jika Anda menggunakan keduanya.\nUntuk S3 gunakan 'https://<bucket>.s3.amazonaws.com'\
\ dan untuk GCS atau layanan yang setara gunakan 'https://storage.googleapis.com/<bucket>',\
\ dst."
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "Mohon tentukan nama bucket yang digunakan pada layanan yang\
\ telah dikonfigurasi."
@ -647,8 +646,8 @@ contact: "Kontak"
useSystemFont: "Gunakan font bawaan sistem operasi"
clips: "Klip"
makeExplorable: "Buat akun tampil di \"Jelajahi\""
makeExplorableDescription: "Jika kamu mematikan ini, akun kamu tidak akan muncul di\
\ bagian \"Jelajahi:"
makeExplorableDescription: "Jika Anda menonaktifkannya, akun Anda tidak akan muncul\
\ di bagian \"Jelajahi\"."
showGapBetweenNotesInTimeline: "Tampilkan jarak diantara catatan pada linimasa"
duplicate: "Duplikat"
left: "Kiri"
@ -759,7 +758,7 @@ ffVisibility: "Visibilitas Mengikuti/Pengikut"
ffVisibilityDescription: "Mengatur siapa yang dapat melihat pengikutmu dan yang kamu\
\ ikuti."
continueThread: "Lihat lanjutan thread"
deleteAccountConfirm: "Akun akan dihapus. Apakah kamu yakin?"
deleteAccountConfirm: "Ini akan menghapuskan akun {handle} secara permanen. Lanjutkan?"
incorrectPassword: "Kata sandi salah."
voteConfirm: "Konfirmasi suara kamu untuk ({choice})"
hide: "Sembunyikan"
@ -1079,7 +1078,7 @@ _auth:
shareAccess: "Apakah kamu ingin mengijinkan \"{name}\" untuk mengakses akun ini?"
shareAccessAsk: "Apakah kamu ingin mengijinkan aplikasi ini untuk mengakses akun\
\ kamu?"
permissionAsk: "Aplikasi ini membutuhkan beberapa ijin, yaitu:"
permissionAsk: "Aplikasi ini meminta izin berikut ini"
pleaseGoBack: "Mohon kembali ke aplikasi kamu"
callback: "Mengembalikan kamu ke aplikasi"
denied: "Akses ditolak"
@ -1263,7 +1262,7 @@ _notification:
youWereFollowed: "Mengikuti kamu"
youReceivedFollowRequest: "Kamu menerima permintaan mengikuti"
yourFollowRequestAccepted: "Permintaan mengikuti kamu telah diterima"
youWereInvitedToGroup: "Telah diundang ke grup"
youWereInvitedToGroup: "{userName} mengundang Anda ke grup"
pollEnded: "Hasil Kuesioner telah keluar"
emptyPushNotificationMessage: "Pembaruan notifikasi dorong"
_types:

View File

@ -1295,7 +1295,7 @@ _remoteInteract:
description: 今すぐにこのアクションを実行することはできません。あなたのインスタンス上で、またはログインして行う必要があるかもしれません。
movedTo: このユーザーは {handle} に引っ越しました。
uploadFailedDescription: ファイルをアップロードできませんでした。
uploadFailedSize: このファイルは大きすぎるためアップロードできません。
uploadFailedSize: ファイルサイズが大きすぎるためアップロードできません。
uploadFailed: アップロード失敗
showAttachedNotes: 添付ノートを表示
attachedToNotes: このファイルが添付されたノート

View File

@ -181,14 +181,15 @@ clearCachedFiles: "Очистить кэш"
clearCachedFilesConfirm: "Удалить все закэшированные файлы с других сайтов?"
blockedInstances: "Заблокированные инстансы"
blockedInstancesDescription: "Введите список инстансов, которые хотите заблокировать.\
\ Они больше не смогут обмениваться с вашим инстансом."
\ Они больше не смогут обмениваться с вашим инстансом. Не-ASCII доменные имена должны\
\ быть переведены в punycode. Субдомены тоже будут заблокированы"
muteAndBlock: "Скрытие и блокировка"
mutedUsers: "Скрытые пользователи"
blockedUsers: "Заблокированные пользователи"
noUsers: "Нет ни одного пользователя"
editProfile: "Редактировать профиль"
noteDeleteConfirm: "Вы хотите удалить эту заметку?"
pinLimitExceeded: "Нельзя закрепить ещё больше заметок"
pinLimitExceeded: "Нельзя закрепить ещё больше заметок."
intro: "Установка FoundKey завершена! А теперь создайте учетную запись администратора."
done: "Готово"
processing: "Обработка"
@ -722,7 +723,7 @@ misskeyUpdated: "FoundKey обновился!"
whatIsNew: "Что новенького?"
translate: "Перевод"
translatedFrom: "Перевод. Язык оригинала — {x}"
accountDeletionInProgress: "В настоящее время выполняется удаление учетной записи"
accountDeletionInProgress: "В настоящее время выполняется удаление учетной записи."
usernameInfo: "Имя, которое отличает вашу учетную запись от других на этом сервере.\
\ Вы можете использовать алфавит (a~z, A~Z), цифры (0~9) или символы подчеркивания\
\ (_). Имена пользователей не могут быть изменены позже."
@ -749,7 +750,7 @@ ffVisibility: "Видимость подписок и подписчиков"
ffVisibilityDescription: "Здесь можно настроить, кто будет видеть ваши подписки и\
\ подписчиков."
continueThread: "Показать следующие ответы"
deleteAccountConfirm: "Учётная запись будет безвозвратно удалена. Подтверждаете?"
deleteAccountConfirm: "Учётная запись {handle} будет безвозвратно удалена. Подтверждаете?"
incorrectPassword: "Пароль неверен."
voteConfirm: "Отдать голос за «{choice}»?"
hide: "Спрятать"
@ -1268,3 +1269,81 @@ _deck:
mentions: "Упоминания"
direct: "Личное"
_services: {}
botFollowRequiresApproval: Запросы на подписку от аккаунтов помеченных как бот требуют
подтверждения
showLess: Показать меньше
exportAll: Экспортировать всё
exportSelected: Экспортировать выбранное
cannotAttachFileWhenAccountSwitched: Вы не можете прикрепить файл, перейдя в другую
учетную запись.
cannotSwitchAccountWhenFileAttached: Вы не можете переключать учетные записи, пока
файлы прикреплены.
deleteAccount: Удалить аккаунт
isSystemAccount: Учетная запись, созданная системой и автоматически управляемая ею.
oneDay: Один день
cropImage: Обрезать изображение
documentation: Документация
movedTo: Этот пользователь перешел на {handle}.
typeToConfirm: Пожалуйста введите {x} чтобы подтвердить
rateLimitExceeded: Лимит превышен
numberOfPageCache: Количество кэшированных страниц
numberOfPageCacheDescription: Увеличение этого числа повысит удобство для пользователей,
но приведет к увеличению нагрузки на сервер, а также к использованию большего объема
памяти.
file: Файл
unclip: Удалить из подборки
translationSettings: Настройки перевода
translationService: Служба перевода
threadMuteNotificationsDesc: Выберите уведомления, которые вы хотите просмотреть в
этом треде. Также применяются глобальные настройки уведомлений. Отключение имеет
приоритет.
reflectMayTakeTime: Это может занять некоторое время чтобы вступило в силу.
failedToFetchAccountInformation: Не удалось получить информацию о аккаунте
instanceDefaultThemeDescription: Введите код темы в формате объекта.
tenMinutes: 10 минут
oneHour: Один час
oneWeek: Одна неделя
cropImageAsk: Вы хотите обрезать это изображение?
recentNHours: Последние {n} часов
recentNDays: Последние {n} дней
confirmToUnclipAlreadyClippedNote: Эта заметка уже является частью подборки "{name}".
Вы хотите вместо этого удалить это из этой подборки?
noEmailServerWarning: Сервер электронной почты не настроен.
setTag: Установить метку
addTag: Добавить метку
removeTag: Удалить метку
externalCssSnippets: Несколько фрагментов CSS для вашего вдохновения (не управляются
FoundKey)
oauthErrorGoBack: Произошла ошибка при попытке аутентификации стороннего приложения.
Пожалуйста, вернитесь и попробуйте еще раз.
appAuthorization: Авторизация приложения
noPermissionsRequested: (Никаких разрешений не требуется.)
selectMode: Выберите несколько
selectAll: Выбрать все
setCategory: Установить категорию
thereIsUnresolvedAbuseReportWarning: Есть нерасмотренные жалобы.
recommended: Рекомендовано
check: Проверка
unlimited: Неограниченный
mutePeriod: Длительность глушения
uploadFailed: Загрузка не удалась
uploadFailedDescription: Файл не может быть загружен.
uploadFailedSize: Файл слишком большой для загрузки.
renoteUnmute: Показать репосты
stopActivityDeliveryDescription: Локальная активнось не будет отправлена на этот сервер.
Получение активностей работает как раньше.
renoteMute: Скрыть репосты
unrenoteAllConfirm: Вы уверены что хотите отменить все репосты данной замети?
unrenoteAll: Отменить все репосты
blockThisInstanceDescription: Локальная активность не будет отправлена на этот сервер.
Активность этого сервера будет выброшена.
attachedToNotes: Заметки с этим файлом
showAttachedNotes: Показать заметки с этим файлом
signinHistoryExpires: Данные о прошлых попытках войти будут автоматически удалены
после 60 дней для соблюдения правил конфиденциальности.
deleteAllFiles: Удалить все файлы
federateBlocks: Федерировать блоки
federateBlocksDescription: Если выключено, то активности типа "блок" не будут отправлены.
regexpErrorDescription: 'Произошла ошибка в регулярном выражении на строке {line}
ваших {tab} заглушенных слов:'
reporter: Подавший жалобу

View File

@ -4,6 +4,7 @@ import config from '@/config/index.js';
import { UserProfiles } from '@/models/index.js';
import { extractMentions } from '@/misc/extract-mentions.js';
import { intersperse } from '@/prelude/array.js';
import { toPunyNullable } from '@/misc/convert-host.js';
// Transforms MFM to HTML, given the MFM text and a list of user IDs that are
// mentioned in the text. If the list of mentions is not given, all mentions
@ -14,6 +15,19 @@ export async function toHtml(mfmText: string, mentions?: string[]): Promise<stri
return null;
}
let mentionedUsers = [];
const ids = mentions ?? extractMentions(nodes);
if (ids.length > 0) {
mentionedUsers = await UserProfiles.createQueryBuilder('user_profile')
.leftJoin('user_profile.user', 'user')
.select('user.usernameLower', 'username')
.addSelect('user.host', 'host')
// links should preferably use user friendly urls, only fall back to AP ids
.addSelect('COALESCE(user_profile.url, user.uri)', 'url')
.where('"userId" IN (:...ids)', { ids })
.getRawMany();
}
const doc = new JSDOM('').window.document;
const handlers: { [K in mfm.MfmNode['type']]: (node: mfm.NodeType<K>) => Promise<Node> } = {
@ -103,30 +117,28 @@ export async function toHtml(mfmText: string, mentions?: string[]): Promise<stri
},
async mention(node): Promise<HTMLElement | Text> {
const { username, host, acct } = node.props;
const ids = mentions ?? extractMentions(nodes);
if (ids.length > 0) {
const mentionedUsers = await UserProfiles.createQueryBuilder('user_profile')
.leftJoin('user_profile.user', 'user')
.select('user.username', 'username')
.addSelect('user.host', 'host')
// links should preferably use user friendly urls, only fall back to AP ids
.addSelect('COALESCE(user_profile.url, user.uri)', 'url')
.where('"userId" IN (:...ids)', { ids })
.getRawMany();
const userInfo = mentionedUsers.find(user => user.username === username && user.host === host);
if (userInfo != null) {
// Mastodon microformat: span.h-card > a.u-url.mention
const a = doc.createElement('a');
a.href = userInfo.url ?? `${config.url}/${acct}`;
a.className = 'u-url mention';
a.textContent = acct;
let { username, host, acct } = node.props;
// normalize username and host for searching the user
username = username.toLowerCase();
host = toPunyNullable(host);
// Discard host if it is the local host. Otherwise mentions of local users where the
// hostname is not omitted are not handled correctly.
if (host == config.hostname) {
host = null;
}
const userInfo = mentionedUsers.find(user => user.username === username && user.host === host);
if (userInfo != null) {
// Mastodon microformat: span.h-card > a.u-url.mention
const a = doc.createElement('a');
// The fallback will only be used for local users, so the host part can be discarded.
a.href = userInfo.url ?? `${config.url}/@${username}`;
a.className = 'u-url mention';
a.textContent = acct;
const card = doc.createElement('span');
card.className = 'h-card';
card.appendChild(a);
return card;
}
const card = doc.createElement('span');
card.className = 'h-card';
card.appendChild(a);
return card;
}
// this user does not actually exist
return doc.createTextNode(acct);

View File

@ -7,6 +7,7 @@ import { Webhook, webhookEventTypes } from '@/models/entities/webhook.js';
import { IActivity } from '@/remote/activitypub/type.js';
import { envOption } from '@/env.js';
import { MINUTE } from '@/const.js';
import { DbResolver } from '@/remote/activitypub/db-resolver.js';
import processDeliver from './processors/deliver.js';
import processInbox from './processors/inbox.js';
@ -83,24 +84,47 @@ webhookDeliverQueue
.on('error', (job: any, err: Error) => webhookLogger.error(`error ${err}`, { job, e: renderError(err) }))
.on('stalled', (job) => webhookLogger.warn(`stalled ${getJobInfo(job)} to=${job.data.to}`));
export function deliver(content: unknown, to: string | null) {
export async function deliver(content: IActivity|IActivity[], to: string | null) {
if (content == null) return null;
if (to == null) return null;
const data = {
content,
to,
};
// group activities by actor
const contentArray = Array.isArray(content) ? content : [content];
let byActor = contentArray.reduce((acc, activity) => {
if (activity.actor == null) throw new Error("Cannot deliver activity without actor.");
if (!(activity.actor in acc)) {
acc[activity.actor] = [];
}
acc[activity.actor].push(activity);
return acc;
}, []);
return deliverQueue.add(data, {
attempts: config.deliverJobMaxAttempts,
timeout: MINUTE,
backoff: {
type: 'apBackoff',
},
removeOnComplete: true,
removeOnFail: true,
});
// add groups to deliver queue
const dbResolver = new DbResolver();
for (const actor in byActor) {
// extract user from the Activity
const user = await dbResolver.getUserFromApId(actor);
if (!user) throw new Error("Actor not found, cannot deliver.");
if (user.host != null) throw new Error("Cannot deliver for remote actor.");
// add item to deliver queue
const data = {
user: {
id: user.id,
},
content: byActor[actor],
to,
};
deliverQueue.add(data, {
attempts: config.deliverJobMaxAttempts,
timeout: MINUTE,
backoff: {
type: 'apBackoff',
},
removeOnComplete: true,
removeOnFail: true,
});
}
}
export function inbox(activity: IActivity, signature: httpSignature.IParsedSignature) {

View File

@ -9,7 +9,6 @@ import { toPuny } from '@/misc/convert-host.js';
import { StatusError } from '@/misc/fetch.js';
import { shouldSkipInstance } from '@/misc/skipped-instances.js';
import { DeliverJobData } from '@/queue/types.js';
import { DbResolver } from '@/remote/activitypub/db-resolver.js';
const logger = new Logger('deliver');
@ -19,20 +18,13 @@ export default async (job: Bull.Job<DeliverJobData>) => {
if (await shouldSkipInstance(puny)) return 'skip';
// get user/actor for signing
const userUri = job.data.content.actor;
if (userUri == null) return 'error: missing actor';
const user = await new DbResolver().getUserFromApId(userUri);
if (user == null) return 'error: actor not found';
if (user.host != null) return 'error: actor not local';
try {
if (Array.isArray(job.data.content)) {
await Promise.all(
job.data.content.map(x => request(user, job.data.to, x))
job.data.content.map(x => request(job.data.user, job.data.to, x))
);
} else {
await request(user, job.data.to, job.data.content);
await request(job.data.user, job.data.to, job.data.content);
}
// Update stats

View File

@ -6,7 +6,9 @@ import { Webhook } from '@/models/entities/webhook.js';
import { IActivity } from '@/remote/activitypub/type.js';
export type DeliverJobData = {
/** Activity, containing the actor URI */
/** Actor */
user: ThinUser;
/** Activity */
content: IActivity;
/** inbox URL to deliver */
to: string;

View File

@ -156,7 +156,7 @@ export class DeliverManager {
// skip instances as indicated
if (instancesToSkip.includes(new URL(inbox).host)) continue;
deliver(this.activity, inbox);
await deliver(this.activity, inbox);
}
}
}

View File

@ -29,7 +29,7 @@ export default define(meta, paramDef, async (ps, me) => {
const actor = await getInstanceActor();
const targetUser = await Users.findOneByOrFail({ id: report.targetUserId });
deliver(renderActivity(renderFlag(actor, report)), targetUser.inbox);
await deliver(renderActivity(renderFlag(actor, report)), targetUser.inbox);
}
await AbuseUserReports.update(report.id, {

View File

@ -133,7 +133,7 @@ export default define(meta, paramDef, async (ps, user) => {
if (note.userHost != null) {
const pollOwner = await Users.findOneByOrFail({ id: note.userId }) as IRemoteUser;
deliver(renderActivity(await renderVote(user, vote, note, poll, pollOwner)), pollOwner.inbox);
await deliver(renderActivity(await renderVote(user, vote, note, poll, pollOwner)), pollOwner.inbox);
}
// リモートフォロワーにUpdate配信

View File

@ -29,6 +29,6 @@ export default async function(blocker: CacheableUser, blockee: CacheableUser) {
// deliver if remote bloking
if (Users.isLocalUser(blocker) && Users.isRemoteUser(blockee)) {
const content = renderActivity(renderUndo(renderBlock(blocking), blocker));
deliver(content, blockee.inbox);
await deliver(content, blockee.inbox);
}
}

View File

@ -27,7 +27,7 @@ export async function acceptFollowRequest(followee: User, follower: User): Promi
if (Users.isRemoteUser(follower) && Users.isLocalUser(followee)) {
const content = renderActivity(renderAccept(renderFollow(follower, followee, request.requestId!), followee));
deliver(content, follower.inbox);
await deliver(content, follower.inbox);
}
Users.pack(followee.id, followee, {

View File

@ -17,7 +17,7 @@ export async function cancelFollowRequest(followee: User, follower: User): Promi
const content = renderActivity(renderUndo(renderFollow(follower, followee), follower));
if (Users.isLocalUser(follower)) {
deliver(content, followee.inbox);
await deliver(content, followee.inbox);
}
}

View File

@ -64,6 +64,6 @@ export async function createFollowRequest(follower: User, followee: User, reques
if (Users.isLocalUser(follower) && Users.isRemoteUser(followee)) {
const content = renderActivity(renderFollow(follower, followee));
deliver(content, followee.inbox);
await deliver(content, followee.inbox);
}
}

View File

@ -97,7 +97,7 @@ export async function createMessage(user: { id: User['id']; host: User['host'];
const activity = renderActivity(renderCreate(await renderNote(note, false, true), note));
deliver(activity, recipientUser.inbox);
await deliver(activity, recipientUser.inbox);
}
return messageObj;
}

View File

@ -22,7 +22,7 @@ async function postDeleteMessage(message: MessagingMessage): Promise<void> {
if (Users.isLocalUser(user) && Users.isRemoteUser(recipient)) {
const activity = renderActivity(renderDelete(renderTombstone(`${config.url}/notes/${message.id}`), user));
deliver(activity, recipient.inbox);
await deliver(activity, recipient.inbox);
}
} else if (message.groupId) {
publishGroupMessagingStream(message.groupId, 'deleted', message.id);

View File

@ -37,7 +37,7 @@ export async function addRelay(inbox: string): Promise<Relay> {
const relayActor = await getRelayActor();
const activity = renderActivity(renderFollowRelay(relay, relayActor));
deliver(activity, relay.inbox);
await deliver(activity, relay.inbox);
return relay;
}
@ -53,7 +53,7 @@ export async function removeRelay(inbox: string): Promise<void> {
const relayActor = await getRelayActor();
const activity = renderActivity(renderUndo(renderFollowRelay(relay, relayActor), relayActor));
deliver(activity, relay.inbox);
await deliver(activity, relay.inbox);
await Relays.delete(relay.id);
}
@ -89,9 +89,9 @@ export async function deliverToRelays(user: { id: User['id']; host: null; }, act
const signed = await attachLdSignature(copy, user);
for (const relay of relays) {
deliver(signed, relay.inbox);
}
await Promise.all(relays.map(relay =>
deliver(signed, relay.inbox)
));
}
export async function deliverMultipleToRelays(user: User, activities: any[]): Promise<void> {
@ -107,7 +107,7 @@ export async function deliverMultipleToRelays(user: User, activities: any[]): Pr
return attachLdSignature(copy, user);
}));
for (const relay of relays) {
deliver(content, relay.inbox);
}
await Promise.all(relays.map(relay =>
deliver(content, relay.inbox)
));
}

View File

@ -32,7 +32,7 @@ export async function doPostUnsuspend(user: User): Promise<void> {
}
for (const inbox of queue) {
deliver(content, inbox);
await deliver(content, inbox);
}
}
}