Merge branch 'develop' into swn

This commit is contained in:
tamaina 2021-08-20 00:30:52 +09:00
commit 1cc5d3e386
752 changed files with 5003 additions and 3570 deletions

View File

@ -1,13 +0,0 @@
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": {
"version": 3,
"proposals": true
}
}
]
]
}

7
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,7 @@
contact_links:
- name: 👪 Misskey Forum
url: https://forum.misskey.io/
about: Ask questions and share knowledge
- name: 💬 Misskey official Discord
url: https://discord.gg/Wp8gVStHW3
about: Chat freely about Misskey

View File

@ -1,21 +1,29 @@
<!-- お読みください
PRありがとうございます PRを作成する前に、以下をご確認ください:
可能であればタイトルに、以下で示すようなPRの種類が分かるキーワードをプリフィクスしてください。
fix / refactor / feat / enhance / perf / chore
また、PRの粒度が適切であることを確認してください。ひとつのPRに複数の種類の変更や関心を含めることは避けてください。
このPRによって解決されるIssueがある場合は、そのIssue IDを本文内に記入してください。
CHANGELOG.mdに変更点を追記してください。リファクタリングなど、利用者に影響を与えない変更についてはこの限りではありません。
機能追加やバグ修正をした場合は、可能であればテストケースを追加してください。
- 可能であればタイトルに、以下で示すようなPRの種類が分かるキーワードをプリフィクスしてください。
- fix / refactor / feat / enhance / perf / chore
- また、PRの粒度が適切であることを確認してください。ひとつのPRに複数の種類の変更や関心を含めることは避けてください。
- このPRによって解決されるIssueがある場合は、そのIssueへの参照を本文内に含めてください。
- CHANGELOG.mdに変更点を追記してください。リファクタリングなど、利用者に影響を与えない変更についてはこの限りではありません。
- この変更により新たに作成、もしくは更新すべきドキュメントがないか確認してください。
- 機能追加やバグ修正をした場合は、可能であればテストケースを追加してください。
- テスト、Lintが通っていることを予め確認してください。
- `npm run test`、`npm run lint`でぞれぞれ実施可能です
- UIに変更がある場合はスクリーンショットを本文内に添付してください。
ご協力ありがとうございます🤗
-->
<!-- README
Thank you for your PR! Before creating a PR, please check the following:
If possible, prefix the title with a keyword that identifies the type of this PR, as shown below.
fix / refactor / feat / enhance / perf / chore
Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR.
If there is an issue to be resolved by this PR, please include the Issue ID in the text.
Please add the summary of the changes to CHANGELOG.md. However, this is not necessary for changes that do not affect the users, such as refactoring.
If you have added a feature or fixed a bug, please add a test case if possible.
- If possible, prefix the title with a keyword that identifies the type of this PR, as shown below.
- fix / refactor / feat / enhance / perf / chore
- Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR.
- If there is an Issue which will be resolved by this PR, please include a reference to the Issue in the text.
- Please add the summary of the changes to CHANGELOG.md. However, this is not necessary for changes that do not affect the users, such as refactoring.
- Check if there are any documents that need to be created or updated due to this change.
- If you have added a feature or fixed a bug, please add a test case if possible.
- Please make sure that tests and Lint are passed in advance.
- You can run it with `npm run test` and `npm run lint`.
- If this PR includes UI changes, please attach a screenshot in the text.
Thanks for your cooperation 🤗
-->

11
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

View File

@ -35,6 +35,8 @@ jobs:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: yarn install
- name: Check yarn.lock
run: git diff --exit-code yarn.lock
- name: Copy Configure
run: cp .circleci/misskey/*.yml .config
- name: Build

View File

@ -1 +1 @@
v16.2.0
v16.6.2

View File

@ -1,3 +1,56 @@
<!--
## 12.x.x (unreleased)
### Improvements
### Bugfixes
-->
## 12.x.x (unreleased)
### Improvements
- 依存関係の更新
### Bugfixes
- チャンネルを作成しているとアカウントを削除できないのを修正
## 12.88.0 (2021/08/17)
### Features
- ノートの翻訳機能を追加
- 有効にするには、サーバー管理者がDeepLの無料アカウントを登録し、取得した認証キーを「インスタンス設定 > その他 > DeepL Auth Key」に設定する必要があります。
- Misskey更新時にダイアログを表示するように
- ジョブキューウィジェットに警報音を鳴らす設定を追加
### Improvements
- ブロックの挙動を改修
- ブロックされたユーザーがブロックしたユーザーに対してアクション出来ないようになりました。詳細はドキュメントをご確認ください。
- UIデザインの調整
- データベースのインデックスを最適化
- Proxy使用時にKeep-Aliveをサポート
- DNSキャッシュでネガティブキャッシュをサポート
- 依存関係の更新
### Bugfixes
- タッチ操作でウィンドウを閉じることができない問題を修正
- Renoteされた時刻が投稿された時刻のように表示される問題を修正
- コントロールパネルでファイルを削除した際の表示を修正
- ActivityPub: 長いユーザーの名前や自己紹介の対応
## 12.87.0 (2021/08/12)
### Improvements
- 絵文字オートコンプリートで一文字目は最近使った絵文字をサジェストするように
- 絵文字オートコンプリートのパフォーマンスを改善
- about-misskeyページにドキュメントへのリンクを追加
- Docker: Node.jsを16.6.2に
- 依存関係の更新
- 翻訳の更新
### Bugfixes
- Misskey更新時、テーマキャッシュの影響でスタイルがおかしくなる問題を修正
## 12.86.0 (2021/08/11)
### Improvements

View File

@ -35,6 +35,11 @@ If your language is not listed in Crowdin, please open an issue.
## Test
* Test codes are located in [`/test`](/test).
### Run specify test
```
npx cross-env TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT="./test/tsconfig.json" npx mocha test/foo.ts --require ts-node/register
```
## Continuous integration
Misskey uses GitHub Actions for executing automated tests.
Configuration files are located in [`/.github/workflows`](/.github/workflows).

View File

@ -1,4 +1,4 @@
FROM node:16.2.0-alpine3.13 AS base
FROM node:16.6.2-alpine3.13 AS base
ENV NODE_ENV=production
@ -18,9 +18,7 @@ RUN apk add --no-cache \
nasm \
pkgconfig \
python3 \
zlib-dev \
vips-dev \
vips
zlib-dev
COPY package.json yarn.lock .yarnrc ./
RUN yarn install
@ -31,8 +29,7 @@ FROM base AS runner
RUN apk add --no-cache \
ffmpeg \
tini \
vips
tini
ENTRYPOINT ["/sbin/tini", "--"]

Binary file not shown.

3
cypress.json Normal file
View File

@ -0,0 +1,3 @@
{
"baseUrl": "http://localhost"
}

View File

@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@ -0,0 +1,69 @@
describe('Basic', () => {
before(() => {
cy.request('POST', '/api/reset-db');
});
beforeEach(() => {
cy.reload(true);
});
it('successfully loads', () => {
cy.visit('/');
});
it('setup instance', () => {
cy.visit('/');
cy.get('[data-cy-admin-username] input').type('admin');
cy.get('[data-cy-admin-password] input').type('admin1234');
cy.get('[data-cy-admin-ok]').click();
});
it('signup', () => {
cy.visit('/');
cy.get('[data-cy-signup]').click();
cy.get('[data-cy-signup-username] input').type('alice');
cy.get('[data-cy-signup-password] input').type('alice1234');
cy.get('[data-cy-signup-password-retype] input').type('alice1234');
cy.get('[data-cy-signup-submit]').click();
});
it('signin', () => {
cy.visit('/');
cy.get('[data-cy-signin]').click();
cy.get('[data-cy-signin-username] input').type('alice');
// Enterキーでサインインできるかの確認も兼ねる
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
});
it('note', () => {
cy.visit('/');
//#region TODO: この辺はUI操作ではなくAPI操作でログインする
cy.get('[data-cy-signin]').click();
cy.get('[data-cy-signin-username] input').type('alice');
// Enterキーでサインインできるかの確認も兼ねる
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
//#endregion
cy.get('[data-cy-open-post-form]').click();
cy.get('[data-cy-post-form-text]').type('Hello, Misskey!');
cy.get('[data-cy-open-post-form-submit]').click();
// TODO: 投稿した文字列が画面内にあるか(=タイムラインに流れてきたか)のテスト
});
});

22
cypress/plugins/index.js Normal file
View File

@ -0,0 +1,22 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}

View File

@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })

20
cypress/support/index.js Normal file
View File

@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@ -1,3 +1,13 @@
/*
import * as fs from 'fs';
if (fs.existsSync('./built')) {
import('./built/index.js').then(built => built());
} else {
console.log('Built code is not found. Probably an error occurred during a build or you just forgot to build.');
}
*/
const fs = require('fs');
if (fs.existsSync('./built')) {

View File

@ -1,14 +1,14 @@
---
_lang_: "Deutsch"
headlineMisskey: "Ein durch Notizen verbundenes Netzwerk"
introMisskey: "Willkommen! Misskey ist eine dezentralisierte Open-Source Microblogging-Platform.\nVerfasse \"Notizen\" um mitzuteilen, was gerade passiert oder um Ereignisse mit Anderen zu teilen. 📡\nMit \"Reaktionen\" kannst du außerdem schnell deine Gefühle über Notizen anderer Benutzer zum Ausdruck bringen. 👍\nErforsche eine neue Welt! 🚀"
monthAndDay: "{day}/{month}"
introMisskey: "Willkommen! Misskey ist eine dezentralisierte Open-Source Microblogging-Platform.\nVerfasse „Notizen“ um mitzuteilen, was gerade passiert oder um Ereignisse mit anderen zu teilen. 📡\nMit „Reaktionen“ kannst du außerdem schnell deine Gefühle über Notizen anderer Benutzer zum Ausdruck bringen. 👍\nEine neue Welt wartet auf dich! 🚀"
monthAndDay: "{day}.{month}."
search: "Suchen"
notifications: "Benachrichtigungen"
username: "Benutzername"
password: "Passwort"
forgotPassword: "Passwort vergessen"
fetchingAsApObject: "Wird aus dem Fediverse angefragt..."
fetchingAsApObject: "Wird aus dem Fediverse angefragt"
ok: "OK"
gotIt: "Verstanden!"
cancel: "Abbrechen"
@ -25,10 +25,10 @@ profile: "Profil"
timeline: "Chronik"
noAccountDescription: "Dieser Nutzer hat seine Profilbeschreibung noch nicht ausgefüllt."
login: "Anmelden"
loggingIn: "Du wirst angemeldet..."
loggingIn: "Du wirst angemeldet"
logout: "Abmelden"
signup: "Registrieren"
uploading: "Wird hochgeladen..."
uploading: "Wird hochgeladen"
save: "Speichern"
users: "Benutzer"
addUser: "Benutzer hinzufügen"
@ -63,7 +63,7 @@ import: "Import"
export: "Export"
files: "Dateien"
download: "Herunterladen"
driveFileDeleteConfirm: "Möchtest du die Datei \"{name}\" wirklich löschen? Die zugehörige Notiz wird ebenso verschwinden."
driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Die zugehörige Notiz wird ebenso verschwinden."
unfollowConfirm: "Möchtest du {name} nicht mehr folgen?"
exportRequested: "Du hast einen Export angefragt. Dies kann etwas Zeit in Anspruch nehmen. Sobald der Export abgeschlossen ist, wird er deiner Drive hinzugefügt."
importRequested: "Du hast einen Import angefragt. Dies kann etwas Zeit in Anspruch nehmen."
@ -80,7 +80,7 @@ error: "Fehler"
somethingHappened: "Ein Fehler ist aufgetreten"
retry: "Wiederholen"
pageLoadError: "Laden der Seite fehlgeschlagen."
pageLoadErrorDescription: "Dieser Fehler wird meist durch Netzwerkfehler oder den Browser-Cache verursacht. Versuche bitte den Browser-Cache zu leeren und es nach kurzer Zeit noch einmal zu probieren."
pageLoadErrorDescription: "Dieser Fehler wird meist durch Netzwerkfehler oder den Browser-Cache verursacht. Bitte leere den Cache oder versuche es nach einiger Zeit erneut."
enterListName: "Name der Liste eingeben"
privacy: "Privatsphäre"
makeFollowManuallyApprove: "Follow-Anfragen benötigen Bestätigung"
@ -105,7 +105,7 @@ sensitive: "NSFW"
add: "Hinzufügen"
reaction: "Reaktionen"
reactionSettingDescription: "Wähle die Reaktionen aus, die in der Reaktionsauswahl angezeigt werden sollen."
reactionSettingDescription2: "Ziehe zum Anordnen, Klicke zum Löschen, Drücke \"+\" zum Hinzufügen"
reactionSettingDescription2: "Ziehe zum Anordnen, klicke zum Löschen, drücke + zum Hinzufügen"
rememberNoteVisibility: "Notizsichtbarkeit merken"
attachCancel: "Anhang entfernen"
markAsSensitive: "Als NSFW markieren"
@ -129,14 +129,14 @@ editWidgetsExit: "Fertig"
customEmojis: "Benutzerdefinierte Emojis"
emoji: "Emojis"
emojis: "Emojis"
emojiName: "Emojiname"
emojiName: "Emoji-Name"
emojiUrl: "Emoji-URL"
addEmoji: "Emoji hinzufügen"
settingGuide: "Empfohlene Einstellung"
cacheRemoteFiles: "Dateien von fremden Instanzen im Cache speichern"
cacheRemoteFilesDescription: "Ist diese Einstellung deaktiviert, so werden Dateien fremder Instanzen direkt von dort geladen. Hierdurch wird Speicherplatz auf dem Server gespart, aber durch fehlende Generierung von Vorschaubildern mehr Bandbreite verwendet."
flagAsBot: "Als Bot markieren"
flagAsBotDescription: "Aktiviere diese Option, falls dieses Benutzerkonto durch ein Programm gesteuert wird. Falls aktiviert, agiert es als Flag für andere Entwickler zur Verhinderung von endlosen Kettenreaktionen mit anderen Bots und lässt Misskey's interne Systeme dieses Benutzerkonto als Bot behandeln."
flagAsBotDescription: "Aktiviere diese Option, falls dieses Benutzerkonto durch ein Programm gesteuert wird. Falls aktiviert, agiert es als Flag für andere Entwickler zur Verhinderung von endlosen Kettenreaktionen mit anderen Bots und lässt Misskeys interne Systeme dieses Benutzerkonto als Bot behandeln."
flagAsCat: "Als Katze markieren"
flagAsCatDescription: "Aktiviere diese Option, um dieses Benutzerkonto als Katze zu markieren."
autoAcceptFollowed: "Follow-Anfragen von Benutzern, denen du folgst, automatisch akzeptieren"
@ -196,7 +196,7 @@ noteDeleteConfirm: "Möchtest du diese Notiz wirklich löschen?"
pinLimitExceeded: "Es können nicht noch mehr Notizen angeheftet werden"
intro: "Misskey Installation abgeschlossen! Lass uns nun ein Administratorkonto erstellen."
done: "Fertig"
processing: "In Bearbeitung..."
processing: "In Bearbeitung"
preview: "Vorschau"
default: "Standard"
noCustomEmojis: "Keine benutzerdefinierten Emojis vorhanden"
@ -227,8 +227,8 @@ announcements: "Ankündigungen"
imageUrl: "Bild-URL"
remove: "Löschen"
removed: "Erfolgreich gelöscht"
removeAreYouSure: "Möchtest du \"{x}\" wirklich entfernen?"
deleteAreYouSure: "Möchtest du \"{x}\" wirklich löschen?"
removeAreYouSure: "Möchtest du „{x}“ wirklich entfernen?"
deleteAreYouSure: "Möchtest du „{x}“ wirklich löschen?"
resetAreYouSure: "Wirklich zurücksetzen?"
saved: "Gespeichert"
messaging: "Chat"
@ -240,7 +240,7 @@ uploadFromUrlDescription: "URL der hochzuladenden Datei"
uploadFromUrlRequested: "Upload angefordert"
uploadFromUrlMayTakeTime: "Es kann eine Weile dauern, bis das Hochladen abgeschlossen ist."
explore: "Erkunden"
games: "Misskey Spiele"
games: "Misskey-Spiele"
messageRead: "Gelesen"
noMoreHistory: "Kein weiterer Verlauf vorhanden"
startMessaging: "Neuen Chat erstellen"
@ -256,14 +256,14 @@ birthday: "Geburtstag"
yearsOld: "{age} Jahre alt"
registeredDate: "Registrationsdatum"
location: "Ort"
theme: "Farbthemen"
themeForLightMode: "Farbthema, das im Hellmodus genutzt wird"
themeForDarkMode: "Farbthema, das im Dunkelmodus genutzt wird"
theme: "Farbschema"
themeForLightMode: "Helles Farbschema"
themeForDarkMode: "Dunkles Farbschema"
light: "Hell"
dark: "Dunkel"
lightThemes: "Helle Farbthemen"
darkThemes: "Dunkle Farbthemen"
syncDeviceDarkMode: "Dunkelmodus mit den Einstellungen deines Gerätes synchronisieren"
lightThemes: "Helle Farbschemata"
darkThemes: "Dunkle Farbschemata"
syncDeviceDarkMode: "Einstellung deines Geräts übernehmen"
drive: "Drive"
fileName: "Dateiname"
selectFile: "Datei auswählen"
@ -293,7 +293,7 @@ whenServerDisconnected: "Bei Verbindungsverlust zum Server"
disconnectedFromServer: "Verbindung zum Server wurde getrennt"
reload: "Aktualisieren"
doNothing: "Ignorieren"
reloadConfirm: "Möchtest du die Chronik aktualisieren?"
reloadConfirm: "Seite neu laden?"
watch: "Beobachten"
unwatch: "Nicht mehr beobachten"
accept: "Akzeptieren"
@ -302,10 +302,10 @@ normal: "Normal"
instanceName: "Name der Instanz"
instanceDescription: "Beschreibung der Instanz"
maintainerName: "Betreiber"
maintainerEmail: "Betreiber-Email"
maintainerEmail: "Betreiber-E-Mail"
tosUrl: "URL der Nutzungsbedingungen"
thisYear: "Dieses Jahr"
thisMonth: "Dieser Monat"
thisYear: "Jahr"
thisMonth: "Monat"
today: "Heute"
dayX: "{day}"
monthX: "{month}"
@ -522,7 +522,7 @@ scratchpadDescription: "Die Testumgebung bietet eine Umgebung für AiScript-Expe
output: "Ausgabe"
script: "Skript"
disablePagesScript: "AiScript auf Seiten deaktivieren"
updateRemoteUser: "Informationen über Benutzer fremder Instanzen aktualisieren"
updateRemoteUser: "Benutzerinformationen aktualisieren"
deleteAllFiles: "Alle Dateien löschen"
deleteAllFilesConfirm: "Möchtest du wirklich alle Dateien löschen?"
removeAllFollowing: "Allen gefolgten Benutzern entfolgen"
@ -715,7 +715,7 @@ inChannelSearch: "In Kanal suchen"
useReactionPickerForContextMenu: "Reaktionsauswahl durch Rechtsklick öffnen"
typingUsers: "{users} ist/sind am schreiben..."
jumpToSpecifiedDate: "Zu bestimmtem Datum springen"
showingPastTimeline: "Momentan wird eine alte Chronik angezeigt"
showingPastTimeline: "Es wird eine alte Chronik angezeigt"
clear: "Zurückkehren"
markAllAsRead: "Alle als gelesen markieren"
goBack: "Zurück"
@ -771,6 +771,12 @@ received: "Erhalten"
searchResult: "Suchergebnisse"
hashtags: "Hashtags"
troubleshooting: "Problembehandlung"
useBlurEffect: "Weichzeichnungseffekt in der Benutzeroberfläche verwenden"
learnMore: "Mehr erfahren"
misskeyUpdated: "Misskey wurde aktualisiert!"
whatIsNew: "Änderungen anzeigen"
translate: "Übersetzen"
translatedFrom: "Aus {x} übersetzt"
_docs:
continueReading: "Mehr lesen"
features: "Funktionen"
@ -792,7 +798,7 @@ _gallery:
unlike: "\"Gefällt mir\" entfernen"
_email:
_follow:
title: "ist dir gefolgt"
title: "Du hast einen neuen Follower"
_receiveFollowRequest:
title: "Du hast eine Follow-Anfrage erhalten"
_plugin:
@ -1046,7 +1052,7 @@ _time:
_tutorial:
title: "Wie du Misskey verwendest"
step1_1: "Willkommen!"
step1_2: "Diese Seite ist die \"Chronik\". Sie zeigt dir deine geschrieben \"Notizen\" sowie die aller Benutzer, denen du \"folgst\", in chronologischer Reihenfolge."
step1_2: "Diese Seite ist die „Chronik“. Sie zeigt dir deine geschrieben „Notizen“ sowie die aller Benutzer, denen du „folgst“, in chronologischer Reihenfolge."
step1_3: "Deine Chronik sollte momentan leer sein, da du bis jetzt noch keine Notizen geschrieben hast und auch noch keinen Benutzern folgst."
step2_1: "Lass uns zuerst dein Profil vervollständigen, bevor du Notizen schreibst oder jemandem folgst."
step2_2: "Informationen darüber, was für eine Person du bist, macht es anderen leichter zu wissen, ob sie deine Notizen sehen wollen und ob sie dir folgen möchten."
@ -1055,7 +1061,7 @@ _tutorial:
step3_3: "Fülle das Fenster aus und drücke auf den Knopf oben rechts zum Senden."
step3_4: "Fällt dir nichts ein, das du schreiben möchtest? Versuch's mit \"Hallo Misskey!\""
step4_1: "Fertig mit dem Senden deiner ersten Notiz?"
step4_2: "Falls deine Notiz nun auf deiner Chronik auftaucht, hast du alles richtig gemacht."
step4_2: "Falls deine Notiz nun in deiner Chronik auftaucht, hast du alles richtig gemacht."
step5_1: "Lass uns nun deiner Chronik etwas mehr Leben einhauchen, indem du einigen anderen Benutzern folgst."
step5_2: "{featured} zeigt dir beliebte Notizen dieser Instanz. In {explore} kannst du beliebte Benutzer finden. Schau dort, ob du Benutzer findest, die dich interessieren."
step5_3: "Klicke zum Anzeigen des Profils eines Benutzers auf dessen Profilbild und dann auf den \"Folgen\"-Knopf, um diesem zu folgen."

View File

@ -249,7 +249,7 @@ agreeTo: "I agree to {0}"
tos: "Terms of Service"
start: "Begin"
home: "Home"
remoteUserCaution: "As this user is from a renote instance, the shown information may be incomplete."
remoteUserCaution: "As this user is from a remote instance, the shown information may be incomplete."
activity: "Activity"
images: "Images"
birthday: "Birthday"
@ -771,6 +771,12 @@ received: "Received"
searchResult: "Search results"
hashtags: "Hashtags"
troubleshooting: "Troubleshooting"
useBlurEffect: "Use blur effects in the UI"
learnMore: "Learn more"
misskeyUpdated: "Misskey has been updated!"
whatIsNew: "Show changes"
translate: "Translate"
translatedFrom: "Translated from {x}"
_docs:
continueReading: "Read more"
features: "Features"

View File

@ -1,7 +1,7 @@
---
_lang_: "Esperanto"
headlineMisskey: "Reto liganta per notoj"
introMisskey: "Bonvenon! Misskey estas malfermitkoda malcentriza mikrobloga servo.\nKreu \"noto\"n por kunhavu tion ke nun okazas, aŭ por dissendu pri vi📡\nPer la funkcio \"reago\" vi ankaŭ povas rapide esprimi vian senton pri ĉies noto👍\nVolu esplori nova mondo🚀"
headlineMisskey: "Reto ligata per notoj"
introMisskey: "Bonvenon! Misskey estas malfermitkoda malcentraliza mikrobloga servo.\nKreu \"noto\"n por diskonigi tion ke nun okazas, aŭ por dissendu pri vi📡\nPer la funkcio \"reago\" vi ankaŭ povas rapide esprimi vian senton pri ĉies noto👍\nVolu esplori nova mondo🚀"
monthAndDay: "{day}-a/{month}"
search: "Serĉi"
notifications: "Sciigoj"
@ -10,10 +10,10 @@ password: "Pasvorto"
forgotPassword: "Ĉu vi forgesis pasvorton?"
fetchingAsApObject: "Informpetado de Fediverso..."
ok: "Akcepteble"
gotIt: "Mi konprenas!"
gotIt: "Mi komprenas"
cancel: "Nuligi"
enterUsername: "Entajpu uzantnomon"
renotedBy: "Renoton faras {user}"
renotedBy: "Renoto farita de {user}"
noNotes: "Neniu noto!"
noNotifications: "Vi ne havas sciigojn."
instance: "Ekzemplo"
@ -44,7 +44,7 @@ copyContent: "Kopii enhavon"
copyLink: "Kopii ligilon"
delete: "Forviŝi"
deleteAndEdit: "Forigi kaj redakti"
deleteAndEditConfirm: "Ĉu vi certas, ke vi volas forigi kaj redakti la noton? Ĉiuj reagoj, renotoj, kaj respondoj ankaŭ foriĝos."
deleteAndEditConfirm: "Ĉu vi certas, ke vi volas forigi kaj redakti la noton? Ankaŭ ĉiuj reagoj, renotoj, kaj respondoj al ĝi foriĝos."
addToList: "Aldoni al la listo"
sendMessage: "Sendi mesaĝon"
copyUsername: "Kopii uzantnomon"
@ -52,12 +52,13 @@ searchUser: "Serĉi uzanton"
reply: "Respondi"
loadMore: "Vidu pli"
showMore: "Vidi pli"
youGotNewFollower: "Vin eksekvis"
receiveFollowRequest: "Eksekvopeton riceviĝis."
followRequestAccepted: "La eksekvopeto akceptiĝis."
youGotNewFollower: "sksekvis vin"
receiveFollowRequest: "Peto de sekvado estas ricevita"
followRequestAccepted: "La peto de sekvado akceptita"
mention: "Mencioj"
mentions: "Al vi"
importAndExport: "Importaĵo / Eksportaĵo"
directNotes: "Rektaj notoj"
importAndExport: "Importi/eksporti"
import: "Importi"
export: "Eksporti"
files: "Dosieroj"
@ -70,7 +71,7 @@ note: "Elsendi noto"
notes: "Notoj"
following: "Sekvatoj"
followers: "Sekvantoj"
followsYou: "Vin sekvas "
followsYou: "Sekvas vin"
createList: "Kreii liston"
error: "Eraro"
somethingHappened: "Problemo okazis."
@ -78,9 +79,9 @@ retry: "Reprovi"
enterListName: "Entajpu nomon de la listo"
privacy: "Privateco"
follow: "Sekvi"
followRequest: "Peti akcepti de vi eksekvi"
followRequests: "Eksekvopetoj"
unfollow: "Ne plu sekvi"
followRequest: "Peti de sekvado"
followRequests: "Petoj de sekvado"
unfollow: "Malsekvi"
enterEmoji: "Entajpu emoĵion"
renote: "Fari renoton"
unrenote: "Malfari renoton"
@ -95,7 +96,7 @@ clickToShow: "Klaku por malkaŝu"
sensitive: "Enhavo ne estas deca por laborejo (NSFW)"
add: "Aldoni"
reaction: "Reagoj"
enterFileName: "Entajpu dosiernomon"
enterFileName: "Entajpu nomon de dosiero"
mute: "Silentigi"
unmute: "Malsilentigi"
block: "Bloki"
@ -115,7 +116,7 @@ customEmojis: "Personecigitaj emoĵioj"
emoji: "Emoĵio"
emojis: "Emoĵio"
emojiName: "Nomo de emoĵio"
emojiUrl: "URL de la bildo de emoĵio"
emojiUrl: "URL de la emoĵio"
addEmoji: "Aldoni emoĵion"
settingGuide: "Rekomendaj agordoj"
cacheRemoteFiles: "Havi staplon por transaj dosieroj"
@ -124,16 +125,20 @@ flagAsCat: "Tiu uzanto estas kato"
addAccount: "Aldoni konton"
showOnRemote: "Vidi sur la fora ekzemplo"
general: "Ĝenerala"
wallpaper: "Ekranfonoj"
setWallpaper: "Apliki ekranfonon"
removeWallpaper: "Forviŝi ekranfonon. "
searchWith: "Serĉi: {q}"
youHaveNoLists: "Vi ne havas listojn."
followConfirm: "Ĉu vi certas ke vi volas sekvi {name}'(o)n?"
selectUser: "Elekti uzanton"
annotation: "Komentarioj"
federation: "Konfederacio"
federation: "Kunfederaĵo"
instances: "Ekzemplo"
perHour: "Po horo"
perDay: "Po tago"
blockThisInstance: "Bloki tiu ekzemplo"
version: "Versio"
withNFiles: "{n} dosiero(j)"
disk: "Diskilo"
instanceInfo: "Informo pri la ekzemplo"
@ -147,61 +152,86 @@ noUsers: "Sen uzantoj"
editProfile: "Redakti profilon"
noteDeleteConfirm: "Ĉu vi certas ke vi volas forviŝi la noton?"
pinLimitExceeded: "Vi ne plu povas alpingli noton."
processing: "Traktado..."
noCustomEmojis: "Neniu emoĵio"
federating: "Konfederado"
federating: "Kunfederado"
blocked: "Blokata"
all: "Ĉiuj"
subscribing: "Abonita"
publishing: "Dissendado"
notResponding: "Alvokato ne disponeblas"
instanceFollowing: "Sekvatoj sur la ekzemplo"
instanceFollowing: "Sekvatoj el la ekzemplo"
instanceFollowers: "Sekvantoj el la ekzemplo"
instanceUsers: "Uzantoj de la ekzemplo"
changePassword: "Ŝanĝi pasvorton"
security: "Sekureco"
currentPassword: "Aktuala pasvorto"
newPassword: "Nova pasvorto"
newPasswordRetype: "Reentajpu la novan pasvorton"
attachFile: "Aldoni dosieron"
more: "Plu!"
featured: "Maksimumi"
usernameOrUserId: "Uzantnomo aŭ identigilo de uzanto"
noSuchUser: "Neniuj uzantoj trovitaj."
lookup: "Informpeti"
announcements: "Novaĵoj"
imageUrl: "URL de bildo"
remove: "Forigi"
removed: "Forviŝis"
removeAreYouSure: "Ĉu vi certas ke vi volas forigi \"{x}\"'(o)n?"
deleteAreYouSure: "Ĉu vi certas ke vi volas forviŝi \"{x}\"'(o)n?"
saved: "Konservita"
messaging: "Retbabili"
upload: "Alŝuti"
fromDrive: "De la diskingo"
fromDrive: "De la disko"
fromUrl: "De URL"
uploadFromUrl: "Alŝuti de URL"
uploadFromUrlDescription: "URL de la dosiero kiun vi volu alŝuti"
uploadFromUrlDescription: "URL de la dosiero kiun vi volas alŝuti"
explore: "Esplori"
games: "Ludoj sur Misskey"
messageRead: "Legita"
startMessaging: "Komenci babiladon"
nUsersRead: "Legita de {n} homoj"
tos: "Kondiĉoj de uzado"
start: "Komenciĝi"
home: "Hejmo"
remoteUserCaution: "Ĉi tiu Infomoj estas ne tute ekzakta pro distanca uzanto."
activity: "Aktiveco"
images: "Bildoj"
birthday: "Naskiĝtago"
birthday: "Naskiĝdato"
registeredDate: "Registriĝdato"
drive: "Diskingo"
location: "Loko"
theme: "Koloraro"
light: "Luma"
dark: "Malluma"
drive: "Disko"
fileName: "Dosiernomo"
selectFile: "Elekti dosieron"
selectFiles: "Elekti dosieron"
selectFolder: "Elekti dosierujon"
selectFolders: "Elekti dosierujon"
renameFile: "Alinomi la dosieron"
folderName: "Nomo de la dosierujo"
createFolder: "Krei dosierujon"
renameFolder: "Alinomi la dosierujon"
deleteFolder: "Forviŝi dosierujon"
addFile: "Aldoni dosieron"
emptyDrive: "La diskingo malplenas."
emptyDrive: "La disko malplenas"
emptyFolder: "La dosierujo malplenas"
unableToDelete: "Ne forigebla"
inputNewFileName: "Entajpu nova dosiernomon"
inputNewFileName: "Entajpu nova nomon de la dosiero"
inputNewFolderName: "Entajpu nova nomon de la dosierujo"
hasChildFilesOrFolders: "La dosierujo ne estas forviŝebla, ĉar ĝi ne malplenas."
copyUrl: "Kopii URL"
rename: "Alinomi"
avatar: "Ikono"
banner: "Standardo"
nsfw: "Enhavo ne estas deca por laborejo (NSFW)"
reload: "Reŝargi"
watch: "Observi"
unwatch: "Malobservi"
accept: "Permesi"
normal: "Normala"
instanceName: "Nomo de la ekzemplo"
maintainerName: "Nomo de la administranto"
maintainerEmail: "Retpoŝto de la administranto"
@ -212,15 +242,24 @@ today: "Hodiaŭ"
dayX: "{day}-a"
monthX: "{month}"
yearX: "La jaro {year}"
pages: "Paĝoj"
connectService: "Konekti"
disconnectService: "Farkonektiĝi"
driveCapacityPerLocalAccount: "Volumo de miskej-diskingo po unu loka uzanto"
driveCapacityPerRemoteAccount: "Volumo de miskej-diskingo po unu transa uzanto"
iconUrl: "URL de la ikono (retpaĝsimbolo, ktp.)"
enableGlobalTimeline: "Ebligi mallokan templinion"
registration: "Registri"
driveCapacityPerLocalAccount: "Volumo de disko po unu loka uzanto"
driveCapacityPerRemoteAccount: "Volumo de disko po unu transa uzanto"
iconUrl: "URL de la ikono (retpaĝsimbolo, ktp)"
bannerUrl: "URL de standardo"
backgroundImageUrl: "URL de fona bildo"
basicInfo: "Baza informo"
pinnedUsers: "Alpinglita uzanto"
pinnedPages: "Alpinglitaj paĝoj"
pinnedNotes: "Pinglita noto"
antennas: "Antenoj"
name: "Nomo"
withFileAntenna: "Nur kun aldonaĵo"
withReplies: "Inkluzive respondoj"
notesAndReplies: "Kun respondoj"
withFiles: "Kun aldonaĵo"
silence: "Mutigi"
@ -231,53 +270,98 @@ recentlyUpdatedUsers: "Uzantoj kiu lastatempe faris noton"
recentlyRegisteredUsers: "Nove aniĝintaj uzantoj"
popularTags: "Popularaj kradvortoj"
userList: "Listoj"
about: "Informoj"
aboutMisskey: "Pri Misskey"
administrator: "Administranto"
moderator: "Moderigisto"
securityKey: "Sekureca ŝlosilo"
securityKeyName: "Nomo de la ŝlosilo"
lastUsed: "Plej malnove uzita"
passwordLessLogin: "Ensaluti sen pasvorto"
resetPassword: "Restarigi pasvorton"
newPasswordIs: "La nova pasvorto estas {password}."
share: "Diskonigi"
notFound: "Ne trovita"
cacheClear: "Malplenigi staplon"
help: "Manlibro de uzado"
inputMessageHere: "Entajpu masaĝo tie ĉi"
close: "Fermi"
group: "Grupo"
groups: "Grupoj"
createGroup: "Krei grupon"
groupName: "Grupa nomo"
members: "Membroj"
messagingWithUser: "Mesaĝado kun uzanto"
messagingWithGroup: "Mesaĝi kun grupo"
messagingWithGroup: "Mesaĝado kun grupo"
title: "Titolo"
text: "Teksto"
enable: "Ebligi"
next: "Sekve"
noteOf: "Noto de {user}"
noMessagesYet: "Neniu mesaĝo"
newMessageExists: "Vi ricevis novan mesaĝon."
onlyOneFileCanBeAttached: "Vi povas aldoni nur unu dosieron po unu mesaĝo."
invitationCode: "Kodo de invito"
uiLanguage: "Lingvo de la interfaco"
or: "Aŭ"
language: "Lingvo"
uiLanguage: "Lingvo de la fasado"
aboutX: "Pri {x}"
useOsNativeEmojis: "Oni uzas la emoĵioj de la denaska sistemo"
youHaveNoGroups: "Neniuj grupoj"
category: "Kategorio"
tags: "Etikedoj"
createAccount: "Krei konton"
existingAccount: "Ekzista konto"
noFollowRequests: "Vi ne havas eksekvopetojn."
fontSize: "Tipara grando"
noFollowRequests: "Vi ne havas peto de sekvado"
openImageInNewTab: "Fermi la bildon en nova tablo"
dashboard: "Stirpanelo"
local: "Loka"
remote: "Transa"
total: "Entute"
clientSettings: "Agordoj de kliento"
accountSettings: "Agordoj de Konto"
numberOfDays: "Nombro de tagoj"
hideThisNote: "Kaŝi tiun noton"
objectStorageBaseUrl: "Baza URL"
objectStorageRegion: "Regiono"
objectStorageUseSSL: "Oni uzas SSL"
serverLogs: "Servila protokolo"
deleteAll: "Forviŝi ĉiujn"
sounds: "Sonoj"
listen: "Aŭdi"
none: "Neniu"
showInPage: "Vidi en paĝo"
deleteAllFiles: "Forviŝi ĉiujn dosierojn"
deleteAllFilesConfirm: "Ĉu vi certas, ke vi volas forviŝi ĉiujn viajn dosierojn?"
userSilenced: "Tiu uzanto estas mutigata."
menu: "Menuo"
deletedNote: "Forviŝita noto"
invisibleNote: "Malpublika noto"
poll: "Balotujo"
useCw: "Kaŝi enhavo"
themeEditor: "Redaktilo de koloraroj"
author: "Aŭtoro"
plugins: "Kromaĵoj"
deck: "Kartaro"
medium: "Meza"
small: "Malgranda"
edit: "Redakti"
emailServer: "Retpoŝta servilo"
email: "Retpoŝto"
emailAddress: "Retpoŝta adreso"
smtpConfig: "Agordoj de la servilo SMTP"
smtpUser: "Uzantnomo"
smtpPass: "Pasvorto"
wordMute: "Silentigo de vortoj"
userSaysSomething: "{name} parolis ion"
display: "Vidi"
copy: "Kopii"
database: "Datumbazo"
channel: "Kanalo"
create: "Krei"
notificationSetting: "Agordoj de sciigoj"
useGlobalSetting: "Oni uzas malloka agordo"
fileIdOrUrl: "Dosiera identigilo aŭ URL"
abuseReports: "Signali"
reportAbuse: "Signali"
@ -285,45 +369,89 @@ reportAbuseOf: "Signali {name}'(o)n"
send: "Sendi"
openInNewTab: "Malfermi en nova langeto"
editTheseSettingsMayBreakAccount: "Redakti tiujn agordojn estas eble damaĝi konton."
public: "Publika"
i18nInfo: "Misskey estas tradukata en diversaj lingvoj far volontuloj. Oni povas kontribui por la tradukado ĉe {link}."
accountInfo: "Kontaj Informoj"
notesCount: "Numero de notoj"
repliesCount: "Numero de respondoj senditaj"
renotesCount: "Numero de renotoj kiun vi sendis"
repliedCount: "Numero de respondoj ricevitaj"
renotedCount: "Numero de renotoj kiun vi ricevis"
followingCount: "Numero de sekvatoj"
followersCount: "Numero de sekvantoj"
sentReactionsCount: "Numero de sentitaj reagoj"
receivedReactionsCount: "Numero de ricevitaj reagoj"
yes: "Jes"
no: "Ne"
driveFilesCount: "Numero de dosieroj en la diskingo"
driveFilesCount: "Numero de dosieroj sur la disko"
notSet: "Ne elektita"
noteFavoritesCount: "Numero de la preferataj notoj"
makeExplorable: "Igi videbla konto sur la paĝo \"Esplorado\""
showTitlebar: "Montri titolobredon"
contact: "Kontakto"
makeExplorable: "Videbligi konton sur la paĝo \"Esplori\""
duplicate: "Duobligi"
left: "Maldekstra"
center: "Centra"
showTitlebar: "Montri titola stango"
clearCache: "Malplenigi staplon"
onlineUsersCount: "{n} uzanto(j) estas surlinea"
nUsers: "{n} uzanto(j)"
nNotes: "{n} notoj"
myTheme: "Miaj koloraroj"
backgroundColor: "Fona koloro"
textColor: "Teksto"
saveAs: "Konservi kiel…"
value: "Valoro"
createdAt: "Kreita je"
updatedAt: "Laste ĝisdatigita"
deleteConfirm: "Ĉu certas forviŝi?"
closeAccount: "Forigi konton"
currentVersion: "Nuna versio"
latestVersion: "Plej nova versio"
youAreRunningUpToDateClient: "Vi uzas la plej novan version de via kliento."
newVersionOfClientAvailable: "Nova versio de via kliento estas disponebla."
inUse: "Uzata"
editCode: "Redakti kodon"
emailNotification: "Sciigoj per retpoŝto"
publish: "Publikigi"
inChannelSearch: "Serĉi en kanalo"
useReactionPickerForContextMenu: "Malfermu reago-elektilon per dekstro-kliki"
useReactionPickerForContextMenu: "Oni malfermas reago-elektilon per dekstro-kliki"
typingUsers: "{users} estas entajpanta(j)..."
info: "Informoj"
unknown: "Nekonata"
online: "Surkonektita"
offline: "Forkonektita"
instanceBlocking: "Blokado de ekzemplo"
selectAccount: "Elekti konton"
user: "Uzanto"
accounts: "Kontoj"
global: "Konfederacia"
high: "Alta"
middle: "Meza"
low: "Malalta"
customCss: "Uzantula CSS"
global: "Malloka"
sent: "Sendi"
received: "Ricevita"
searchResult: "Serĉorezultoj"
hashtags: "Kradvorto"
learnMore: "Lernu pli"
translate: "Traduki"
translatedFrom: "Tradukita el {x}"
_docs:
continueReading: "Legi plu"
features: "Funkcioj"
_gallery:
liked: "Ŝatitaj notoj"
like: "Ŝati"
_email:
_follow:
title: "Vin eksekvis"
title: "Vi estas eksekvita"
_receiveFollowRequest:
title: "Vi ricevis eksekvopeton."
title: "Vi ricevis peton de sekvado"
_registry:
key: "Ŝlosilo"
keys: "Ŝlosiloj"
domain: "Nomregno"
createKey: "Krei ŝlosilon"
_aboutMisskey:
about: "Misskey estas malfermitkoda programo evoluigata de syuilo ekde la 2014."
contributors: "Precipaj kontribuantoj"
@ -335,6 +463,10 @@ _mfm:
mention: "Mencioj"
hashtag: "Kradvorto"
url: "URL"
link: "Ligilo"
bold: "Grasa"
small: "Malgrande"
center: "Centrigi"
inlineCode: "Kodo (en linio)"
blockCode: "Kodo (bloko)"
inlineMath: "Formulo (en linio)"
@ -342,6 +474,12 @@ _mfm:
quote: "Citi"
emoji: "Personecigitaj emoĵioj"
search: "Serĉi"
flip: "Inversa"
x2: "Granda"
x3: "Grandega"
x4: "Pli grandega"
_reversi:
total: "Entute"
_instanceTicker:
none: "Ne montri"
remote: "Montri al transaj uzantoj"
@ -349,30 +487,39 @@ _instanceTicker:
_channel:
create: "Krei kanalon"
edit: "Redakti kanalon"
following: "Sekvata"
following: "Sekvante"
usersCount: "{n} partoprenanto(j)"
_menuDisplay:
hide: "Kaŝi"
_wordMute:
muteWords: "Silentigataj vortoj"
muteWords: "Kaŝigitaj vortoj"
mutedNotes: "Silentigataj notoj"
_theme:
code: "Kodo de koloraro"
darken: "Malbrileco"
lighten: "Brileco"
keys:
bg: "Fono"
navBg: "Fono de flanka stango"
hashtag: "Kradvorto"
mention: "Mencioj"
renote: "Fari renoton"
buttonBg: "Fono de butono"
driveFolderBg: "Fono de dosierujo de la disko"
_sfx:
note: "Nova noto"
noteMy: "Mia noto"
notification: "Sciigoj"
chat: "Retbabilejo"
chatBg: "Retbabilejo (BG)"
chat: "Retbabili"
chatBg: "Retbabili (BG)"
antenna: "Ricevo de anteno"
channel: "Sciigoj de kanalo"
_ago:
future: "Futuro"
justNow: "Ĵus"
secondsAgo: "Antaŭ {n} sekundoj"
minutesAgo: "Antaŭ {n} minutoj"
hoursAgo: "Antaŭ {n} horoj"
hoursAgo: "Antaŭ {n} horo(j)"
daysAgo: "Antaŭ {n} tagoj"
weeksAgo: "Antaŭ {n} semajnoj"
monthsAgo: "Antaŭ {n} monatoj"
@ -385,17 +532,17 @@ _time:
_tutorial:
title: "Uzado de Misskey"
step1_1: "Bonvenon."
step7_2: "Se vi volus scii pli pri Miskejon, volu rigardi la fakon {help}."
step7_3: "Do, bonvolu amuziĝi Miskejon🚀"
step7_2: "Se vi volas scii pli pri Misskey, rigardu la fakon {help}."
step7_3: "Do, bonvolu amuziĝi Misskey'on🚀"
_permissions:
"read:blocks": "Vidi la liston de uzantoj kiun vi blokas"
"write:blocks": "Redakti vian liston de blokataj uzantoj"
"read:drive": "Operacio por legi la informon de dosiero en via diskingo de Miskejo"
"write:drive": "Ĉia operacio por skribi, forviŝi, aŭ alimaniere ŝanĝi la informon de dosiero en via diskingo de Miskejo"
"read:drive": "Operacio por legi la informon de dosiero en via disko de Misskey"
"write:drive": "Ĉia operacio por skribi, forviŝi, aŭ alimaniere ŝanĝi la informon de dosiero en via disko de Misskey"
"read:favorites": "Vidi vian liston de preferatoj"
"read:following": "Vidi tion kion vi sekvas"
"write:following": "Sekvi kaj/aŭ malsekvi alian uzanton"
"read:messaging": "Vidi via retbabilado"
"read:following": "Vidi tiun kiun vi sekvas"
"write:following": "Sekvi aŭ malsekvi alian uzanton"
"read:messaging": "Vidi vian retbabiladon"
"read:mutes": "Vidi vian liston de silentigoj"
"write:mutes": "Redakti vian liston de silentigoj"
"write:notes": "Krei / Forviŝi noton"
@ -406,7 +553,8 @@ _permissions:
"read:page-likes": "Vidi ŝatojn de paĝo"
"read:channels": "Vidi kanalojn"
_antennaSources:
homeTimeline: "Notoj far uzantoj sekvataj de vi"
all: "Ĉiuj notoj"
homeTimeline: "Notoj far uzantoj, kiujn vi sekvas"
_weekday:
sunday: "dimanĉo"
monday: "lundo"
@ -419,15 +567,17 @@ _widgets:
notifications: "Sciigoj"
timeline: "Templinio"
clock: "Horloĝo"
federation: "Konfederacio"
activity: "Aktiveco"
federation: "Kunfederaĵo"
slideshow: "Bildoprezento"
button: "Butono"
onlineUsers: "Surkonektita uzanto"
_cw:
show: "Vidu pli"
files: "{count} dosiero(j)"
_poll:
choiceN: "Balotilo {n}"
noMore: "Oni ne plu povas aldoni."
noMore: "Oni ne povas aldoni pli."
infinite: "Neniam"
deadlineTime: "hor"
votesCount: "{n} balotiloj"
@ -438,11 +588,11 @@ _visibility:
home: "Hejmo"
homeDescription: "Elsendi nur sur la hejmtemplinio"
followers: "Sekvantoj"
followersDescription: "Elsendi nur al sekvantoj al mi"
followersDescription: "Nur al sekvantoj al mi"
localOnly: "Nur loka"
localOnlyDescription: "Ne montri al transaj uzantoj"
_postForm:
replyPlaceholder: "Respondado al tiu noto..."
replyPlaceholder: "Respondi al tiu noto..."
quotePlaceholder: "Citado tiun noton..."
channelPlaceholder: "Sendi sur la kanalo"
_profile:
@ -450,16 +600,21 @@ _profile:
username: "Uzantnomo"
metadataEdit: "Redakti kromaj informoj"
changeAvatar: "Ŝanĝi profilbildon"
changeBanner: "Ŝanĝi standardon"
_exportOrImport:
allNotes: "Ĉiuj notoj"
followingList: "Sekvataj"
muteList: "Silentigoj"
blockingList: "Blokado"
userLists: "Listoj"
_charts:
federationInstancesTotal: "Tuta numero de kunfederantaj ekzemploj"
filesTotal: "Tuta numero de dosieroj"
_timelines:
home: "Hejmo"
local: "Loka"
social: "Sociala"
global: "Konfederacia"
global: "Malloka"
_rooms:
translate: "Movi"
chooseImage: "Elekti bildon"
@ -472,18 +627,26 @@ _pages:
editThisPage: "Redakti la paĝon"
viewPage: "Vidi via paĝojn"
my: "Miaj paĝoj"
featured: "Ravaĵoj"
content: "Blokado de paĝo"
url: "URL de paĝo"
alignCenter: "Centrigi"
chooseBlock: "Aldoni blokon"
blocks:
image: "Bildoj"
image: "Bildo"
button: "Butono"
_post:
canvasId: "Kanvasa identigilo"
_numberInput:
text: "Titolo"
_canvas:
id: "Kanvasa identigilo"
_note:
id: "Identigilo de noto"
_counter:
text: "Titolo"
_button:
text: "Titolo"
_action:
_pushEvent:
event: "Nomo de la evento"
@ -511,21 +674,23 @@ _notification:
fileUploaded: "La dosiero sukcese alŝutiĝis."
youGotPoll: "{name} balotis"
youGotMessagingMessageFromUser: "{name} sentis mesaĝon al vi."
youWereFollowed: "Vin eksekvis"
youReceivedFollowRequest: "Vi ricevis eksekvopeton."
yourFollowRequestAccepted: "Via eksekvopeto estas akceptita."
youGotMessagingMessageFromGroup: "Retbabilan mesaĝon oni sendis al la grupo {name}"
youWereFollowed: "sksekvis vin"
youReceivedFollowRequest: "Vi ricevis peton de sekvado"
yourFollowRequestAccepted: "Via peto por eksekvu estas akceptita."
_types:
follow: "Sekvatoj"
mention: "Mencioj"
renote: "Fari renoton"
quote: "Citi"
reaction: "Reagoj"
receiveFollowRequest: "Eksekvopeto ricevita"
followRequestAccepted: "Eksekvopeto akceptiĝis."
receiveFollowRequest: "Ricevita peton de sekvado"
followRequestAccepted: "Peto por eksekvu akceptita"
_deck:
profile: "Agordaro"
_columns:
notifications: "Sciigoj"
tl: "Templinio"
antenna: "Antenoj"
list: "Listoj"
mentions: "Al vi"

View File

@ -91,11 +91,11 @@ followRequests: "Demandes dabonnement"
unfollow: "Se désabonner"
followRequestPending: "Demande d'abonnement en attente de confirmation"
enterEmoji: "Insérer un émoji"
renote: "Partager"
unrenote: "Annuler le partage"
renoted: "Republié !"
cantRenote: "Ce message ne peut pas être republié."
cantReRenote: "Impossible de repartager un partage."
renote: "Renoter"
unrenote: "Annuler la Renote"
renoted: "Renoté !"
cantRenote: "Ce message ne peut pas être renoté."
cantReRenote: "Impossible de renoter une Renote."
quote: "Citer"
pinnedNote: "Note épinglée"
pinned: "Épingler sur le profil"
@ -638,9 +638,9 @@ manageAccessTokens: "Gérer les jetons d'accès"
accountInfo: " Informations du compte "
notesCount: "Nombre de notes"
repliesCount: "Nombre de réponses envoyées"
renotesCount: "Nombre de notes repartagées"
renotesCount: "Nombre de notes que vous avez renotées"
repliedCount: "Nombre de réponses reçues"
renotedCount: "Nombre de Renotes"
renotedCount: "Nombre de vos notes renotées"
followingCount: "Nombre de comptes suivis"
followersCount: "Nombre d'abonnés"
sentReactionsCount: "Nombre de réactions envoyées"
@ -767,14 +767,22 @@ customCssWarn: "Utilisez cette fonctionnalité uniquement si vous savez exacteme
global: "Global"
squareAvatars: "Avatars carrés"
sent: "Envoyer"
searchResult: "Résultats de la recherche"
hashtags: "Hashtags"
troubleshooting: "Résolution de problèmes"
useBlurEffect: "Utiliser des effets de flou dans l'interface"
learnMore: "Plus d'informations"
misskeyUpdated: "Misskey a été mis à jour !"
whatIsNew: "Voir les derniers changements"
translate: "Traduire"
translatedFrom: "Traduit depuis {x}"
_docs:
continueReading: "Lire plus"
features: "Fonctionnalités"
generalTopics: "Sujets généraux"
advancedTopics: "Sujets avancés"
admin: "Gestion"
translateWarn: "Ceci est une traduction dont le contenu peut différer du texte original."
_ad:
back: "Retour"
reduceFrequencyOfThisAd: "Voir cette publicité moins souvent"
@ -988,7 +996,7 @@ _theme:
hashtag: "Hashtags"
mention: "Mentionner"
mentionMe: "Mentions (Moi)"
renote: "Partager"
renote: "Renoter"
modalBg: "Modal d'arrière-plan"
divider: "Séparateur"
scrollbarHandle: "Poignée de la barre de navigation"

View File

@ -767,9 +767,21 @@ customCssWarn: "Pengaturan ini seharusnya digunakan jika kamu tahu cara kerjanya
global: "Global"
squareAvatars: "Tampilkan avatar sebagai persegi"
sent: "Kirim"
received: "Diterima"
searchResult: "Hasil Penelusuran"
hashtags: "Tagar"
troubleshooting: "Penyelesaian Masalah"
useBlurEffect: "Gunakan efek blur pada antarmuka"
learnMore: "Pelajari lebih lanjut"
misskeyUpdated: "Misskey telah dimutakhirkan!"
whatIsNew: "Lihat perubahan pemutakhiran"
_docs:
continueReading: "Baca lebih lanjut"
features: "Fitur"
generalTopics: "Topik umum"
advancedTopics: "Topik tingkat lanjut"
admin: "Manajemen"
translateWarn: "Ini merupakan dokumen terjemahan. Konten di dalamnya kemungkinan dapat berbeda dari yang aslinya."
_ad:
back: "Kembali"
reduceFrequencyOfThisAd: "Tampilkan iklan ini lebih sedikit"
@ -868,6 +880,8 @@ _mfm:
blurDescription: "Konten dapat diburamkan dengan efek ini. Konten dapat ditampilkan dengan jelas dengan melayangkan kursor tetikus di atasnya."
font: "Font"
fontDescription: "Setel font yang ditampilkan untuk konten."
rainbow: "Pelangi"
rainbowDescription: "Membuat konten muncul dalam warna pelangi."
_reversi:
reversi: "Reversi"
gameSettings: "Pengaturan permainan"

View File

@ -772,6 +772,11 @@ searchResult: "検索結果"
hashtags: "ハッシュタグ"
troubleshooting: "トラブルシューティング"
useBlurEffect: "UIにぼかし効果を使用"
learnMore: "詳しく"
misskeyUpdated: "Misskeyが更新されました"
whatIsNew: "更新情報を見る"
translate: "翻訳"
translatedFrom: "{x}から翻訳"
_docs:
continueReading: "続きを読む"

View File

@ -7,6 +7,7 @@ search: "探す"
notifications: "通知"
username: "ユーザー名"
password: "パスワード"
forgotPassword: "パスワード忘れてん"
fetchingAsApObject: "今ちと連合に照会しとるで"
ok: "OKや"
gotIt: "ほい"
@ -139,6 +140,7 @@ flagAsBotDescription: "もしこのアカウントがプログラムによって
flagAsCat: "Catやで"
flagAsCatDescription: "ワレ、猫ちゃんならこのフラグをつけてみ?"
autoAcceptFollowed: "フォローしとるユーザーからのフォローリクエストを勝手に許可しとく"
addAccount: "アカウントを追加"
loginFailed: "ログインに失敗してしもうた…"
showOnRemote: "リモートで見る"
general: "全般"
@ -278,6 +280,7 @@ emptyDrive: "ドライブにはなんも残っとらん"
emptyFolder: "ふぉろだーにはなんも残っとらん"
unableToDelete: "消そうおもってんけどな、あかんかったわ"
inputNewFileName: "今度のファイル名は何にするん?"
inputNewDescription: "新しいキャプションを入力しましょ"
inputNewFolderName: "今度のフォルダ名は何にするん?"
circularReferenceFolder: "移動先のフォルダーは、移動するフォルダーのサブフォルダーや。"
hasChildFilesOrFolders: "このフォルダ、まだなんか入っとるから消されへん"

View File

@ -770,13 +770,20 @@ sent: "전송"
received: "수신"
searchResult: "검색 결과"
hashtags: "해시태그"
troubleshooting: "트러블 슈팅"
troubleshooting: "문제 해결"
useBlurEffect: "UI에 흐림 효과 사용"
learnMore: "자세히"
misskeyUpdated: "Misskey가 업데이트 되었습니다!"
whatIsNew: "패치 정보 보기"
translate: "번역"
translatedFrom: "{x}에서 번역"
_docs:
continueReading: "계속 읽기"
features: "기능"
generalTopics: "일반 주제"
advancedTopics: "심화 주제"
admin: "관리"
translateWarn: "이 문서는 번역되었기 때문에 원본과는 내용이 다를 수 있습니다."
_ad:
back: "뒤로"
reduceFrequencyOfThisAd: "이 광고의 표시 빈도 낮추기"

View File

@ -529,6 +529,7 @@ removeAllFollowing: "Удалить всех подписчиков"
removeAllFollowingDescription: "Отменить все подписки с домена {host}? Пожалуйста, применяйте это действие, если инстанс больше не существует."
userSuspended: "Эта учётная запись заморожена"
userSilenced: "Этот пользователь был заглушен"
menu: "Меню"
divider: "Линия-разделитель"
addItem: "Добавить элемент"
rooms: "Комната"
@ -761,15 +762,26 @@ middle: "Средне"
low: "Низкий"
emailNotConfiguredWarning: "Не указан адрес электронной почты"
ratio: "Соотношение"
customCss: "Индивидуальный CSS"
customCssWarn: "Используйте эту настройку только если знаете, что делаете. Ошибки здесь чреваты тем, что сайт перестанет нормально работать у вас."
global: "Всеобщая"
squareAvatars: "Квадратные аватарки"
sent: "Отправить"
received: "Получено"
searchResult: "Результаты поиска"
hashtags: "Хэштег"
troubleshooting: "Разрешение проблем"
useBlurEffect: "Размытие в интерфейсе"
learnMore: "Подробнее"
misskeyUpdated: "Misskey обновился!"
whatIsNew: "Что новенького?"
_docs:
continueReading: "Читать подробнее"
features: "Возможности"
generalTopics: "Основные темы"
advancedTopics: "Дополнительные темы"
admin: "Управление"
translateWarn: "Это перевод документа. Он может неточно отражать содержимое оригинала."
_ad:
back: "Выход"
reduceFrequencyOfThisAd: "Реже показывать эту рекламу"

View File

@ -771,6 +771,12 @@ received: "收取"
searchResult: "搜索结果"
hashtags: "话题标签"
troubleshooting: "故障排除"
useBlurEffect: "在UI上使用模糊效果"
learnMore: "更多信息"
misskeyUpdated: "Misskey更新完成"
whatIsNew: "显示更新信息"
translate: "翻译"
translatedFrom: "从 {x} 翻译"
_docs:
continueReading: "继续阅读"
features: "特性"

View File

@ -0,0 +1,182 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class chartReindex1629004542760 implements MigrationInterface {
name = 'chartReindex1629004542760'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DELETE FROM "__chart__active_users" a USING "__chart__active_users" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__drive" a USING "__chart__drive" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__federation" a USING "__chart__federation" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__hashtag" a USING "__chart__hashtag" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__instance" a USING "__chart__instance" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__network" a USING "__chart__network" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__notes" a USING "__chart__notes" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__per_user_drive" a USING "__chart__per_user_drive" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__per_user_following" a USING "__chart__per_user_following" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__per_user_notes" a USING "__chart__per_user_notes" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__per_user_reaction" a USING "__chart__per_user_reaction" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__test_grouped" a USING "__chart__test_grouped" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__test_unique" a USING "__chart__test_unique" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__users" a USING "__chart__users" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DROP INDEX "IDX_0ad37b7ef50f4ddc84363d7ccc"`);
await queryRunner.query(`DROP INDEX "IDX_00ed5f86db1f7efafb1978bf21"`);
await queryRunner.query(`DROP INDEX "IDX_9a3ed15a30ab7e3a37702e6e08"`);
await queryRunner.query(`DROP INDEX "IDX_13565815f618a1ff53886c5b28"`);
await queryRunner.query(`DROP INDEX "IDX_7a170f67425e62a8fabb76c872"`);
await queryRunner.query(`DROP INDEX "IDX_3313d7288855ec105b5bbf6c21"`);
await queryRunner.query(`DROP INDEX "IDX_36cb699c49580d4e6c2e6159f9"`);
await queryRunner.query(`DROP INDEX "IDX_76e87c7bfc5d925fcbba405d84"`);
await queryRunner.query(`DROP INDEX "IDX_dd907becf76104e4b656659e6b"`);
await queryRunner.query(`DROP INDEX "IDX_07747a1038c05f532a718fe1de"`);
await queryRunner.query(`DROP INDEX "IDX_99a7d2faaef84a6f728d714ad6"`);
await queryRunner.query(`DROP INDEX "IDX_25a97c02003338124b2b75fdbc"`);
await queryRunner.query(`DROP INDEX "IDX_6b8f34a1a64b06014b6fb66824"`);
await queryRunner.query(`DROP INDEX "IDX_da8a46ba84ca1d8bb5a29bfb63"`);
await queryRunner.query(`DROP INDEX "IDX_39ee857ab2f23493037c6b6631"`);
await queryRunner.query(`DROP INDEX "IDX_a1efd3e0048a5f2793a47360dc"`);
await queryRunner.query(`DROP INDEX "IDX_7b5da130992ec9df96712d4290"`);
await queryRunner.query(`DROP INDEX "IDX_0a905b992fecd2b5c3fb98759e"`);
await queryRunner.query(`DROP INDEX "IDX_42eb716a37d381cdf566192b2b"`);
await queryRunner.query(`DROP INDEX "IDX_7036f2957151588b813185c794"`);
await queryRunner.query(`DROP INDEX "IDX_f09d543e3acb16c5976bdb31fa"`);
await queryRunner.query(`DROP INDEX "IDX_5f86db6492274e07c1a3cdf286"`);
await queryRunner.query(`DROP INDEX "IDX_e496ca8096d28f6b9b509264dc"`);
await queryRunner.query(`DROP INDEX "IDX_30bf67687f483ace115c5ca642"`);
await queryRunner.query(`DROP INDEX "IDX_7af07790712aa3438ff6773f3b"`);
await queryRunner.query(`DROP INDEX "IDX_4b3593098b6edc9c5afe36b18b"`);
await queryRunner.query(`DROP INDEX "IDX_b77d4dd9562c3a899d9a286fcd"`);
await queryRunner.query(`DROP INDEX "IDX_84234bd1abb873f07329681c83"`);
await queryRunner.query(`DROP INDEX "IDX_55bf20f366979f2436de99206b"`);
await queryRunner.query(`DROP INDEX "IDX_5048e9daccbbbc6d567bb142d3"`);
await queryRunner.query(`DROP INDEX "IDX_f7bf4c62059764c2c2bb40fdab"`);
await queryRunner.query(`DROP INDEX "IDX_8cf3156fd7a6b15c43459c6e3b"`);
await queryRunner.query(`DROP INDEX "IDX_229a41ad465f9205f1f5703291"`);
await queryRunner.query(`DROP INDEX "IDX_0c641990ecf47d2545df4edb75"`);
await queryRunner.query(`DROP INDEX "IDX_234dff3c0b56a6150b95431ab9"`);
await queryRunner.query(`DROP INDEX "IDX_b14489029e4b3aaf4bba5fb524"`);
await queryRunner.query(`DROP INDEX "IDX_437bab3c6061d90f6bb65fd2cc"`);
await queryRunner.query(`DROP INDEX "IDX_bbfa573a8181018851ed0b6357"`);
await queryRunner.query(`DROP INDEX "IDX_a0cd75442dd10d0643a17c4a49"`);
await queryRunner.query(`DROP INDEX "IDX_b070a906db04b44c67c6c2144d"`);
await queryRunner.query(`DROP INDEX "IDX_d41cce6aee1a50bfc062038f9b"`);
await queryRunner.query(`DROP INDEX "IDX_a319e5dbf47e8a17497623beae"`);
await queryRunner.query(`DROP INDEX "IDX_845254b3eaf708ae8a6cac3026"`);
await queryRunner.query(`DROP INDEX "IDX_ed9b95919c672a13008e9487ee"`);
await queryRunner.query(`DROP INDEX "IDX_337e9599f278bd7537fe30876f"`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_9a3ed15a30ab7e3a37702e6e08" ON "__chart__active_users" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_60c5c6e7e538c09aa274ecd1cf" ON "__chart__active_users" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_3313d7288855ec105b5bbf6c21" ON "__chart__drive" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_ceab80a6729f8e2e6f5b8a1a3d" ON "__chart__drive" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_dd907becf76104e4b656659e6b" ON "__chart__federation" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_eddfed8fb40305a04c6f941050" ON "__chart__federation" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_25a97c02003338124b2b75fdbc" ON "__chart__hashtag" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_53a3604b939e2b479eb2cfaac8" ON "__chart__hashtag" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_39ee857ab2f23493037c6b6631" ON "__chart__instance" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_8111b817b9818c04d7eb8475b1" ON "__chart__instance" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0a905b992fecd2b5c3fb98759e" ON "__chart__network" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_2082327b2699ce924fa654afc5" ON "__chart__network" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_f09d543e3acb16c5976bdb31fa" ON "__chart__notes" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_e60c358aaced5aab8900a4af31" ON "__chart__notes" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_30bf67687f483ace115c5ca642" ON "__chart__per_user_drive" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a9a806d466b314f253a1a611c4" ON "__chart__per_user_drive" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_b77d4dd9562c3a899d9a286fcd" ON "__chart__per_user_following" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_dabbb38a51ab86ee3cab291326" ON "__chart__per_user_following" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_5048e9daccbbbc6d567bb142d3" ON "__chart__per_user_notes" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_583a157ed0cf0ed1b5ec2a833f" ON "__chart__per_user_notes" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_229a41ad465f9205f1f5703291" ON "__chart__per_user_reaction" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_3b7697a96f522d0478972e6d6f" ON "__chart__per_user_reaction" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_b14489029e4b3aaf4bba5fb524" ON "__chart__test_grouped" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_da522b4008a9f5d7743b87ad55" ON "__chart__test_grouped" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a0cd75442dd10d0643a17c4a49" ON "__chart__test_unique" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_16effb2e888f6763673b579f80" ON "__chart__test_unique" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a319e5dbf47e8a17497623beae" ON "__chart__test" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_dab383a36f3c9db4a0c9b02cf3" ON "__chart__test" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_337e9599f278bd7537fe30876f" ON "__chart__users" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_66feba81e1795d176d06c0b1e6" ON "__chart__users" ("date") WHERE "group" IS NULL`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX "IDX_66feba81e1795d176d06c0b1e6"`);
await queryRunner.query(`DROP INDEX "IDX_337e9599f278bd7537fe30876f"`);
await queryRunner.query(`DROP INDEX "IDX_dab383a36f3c9db4a0c9b02cf3"`);
await queryRunner.query(`DROP INDEX "IDX_a319e5dbf47e8a17497623beae"`);
await queryRunner.query(`DROP INDEX "IDX_16effb2e888f6763673b579f80"`);
await queryRunner.query(`DROP INDEX "IDX_a0cd75442dd10d0643a17c4a49"`);
await queryRunner.query(`DROP INDEX "IDX_da522b4008a9f5d7743b87ad55"`);
await queryRunner.query(`DROP INDEX "IDX_b14489029e4b3aaf4bba5fb524"`);
await queryRunner.query(`DROP INDEX "IDX_3b7697a96f522d0478972e6d6f"`);
await queryRunner.query(`DROP INDEX "IDX_229a41ad465f9205f1f5703291"`);
await queryRunner.query(`DROP INDEX "IDX_583a157ed0cf0ed1b5ec2a833f"`);
await queryRunner.query(`DROP INDEX "IDX_5048e9daccbbbc6d567bb142d3"`);
await queryRunner.query(`DROP INDEX "IDX_dabbb38a51ab86ee3cab291326"`);
await queryRunner.query(`DROP INDEX "IDX_b77d4dd9562c3a899d9a286fcd"`);
await queryRunner.query(`DROP INDEX "IDX_a9a806d466b314f253a1a611c4"`);
await queryRunner.query(`DROP INDEX "IDX_30bf67687f483ace115c5ca642"`);
await queryRunner.query(`DROP INDEX "IDX_e60c358aaced5aab8900a4af31"`);
await queryRunner.query(`DROP INDEX "IDX_f09d543e3acb16c5976bdb31fa"`);
await queryRunner.query(`DROP INDEX "IDX_2082327b2699ce924fa654afc5"`);
await queryRunner.query(`DROP INDEX "IDX_0a905b992fecd2b5c3fb98759e"`);
await queryRunner.query(`DROP INDEX "IDX_8111b817b9818c04d7eb8475b1"`);
await queryRunner.query(`DROP INDEX "IDX_39ee857ab2f23493037c6b6631"`);
await queryRunner.query(`DROP INDEX "IDX_53a3604b939e2b479eb2cfaac8"`);
await queryRunner.query(`DROP INDEX "IDX_25a97c02003338124b2b75fdbc"`);
await queryRunner.query(`DROP INDEX "IDX_eddfed8fb40305a04c6f941050"`);
await queryRunner.query(`DROP INDEX "IDX_dd907becf76104e4b656659e6b"`);
await queryRunner.query(`DROP INDEX "IDX_ceab80a6729f8e2e6f5b8a1a3d"`);
await queryRunner.query(`DROP INDEX "IDX_3313d7288855ec105b5bbf6c21"`);
await queryRunner.query(`DROP INDEX "IDX_60c5c6e7e538c09aa274ecd1cf"`);
await queryRunner.query(`DROP INDEX "IDX_9a3ed15a30ab7e3a37702e6e08"`);
await queryRunner.query(`DROP INDEX "IDX_a9021cc2e1feb5f72d3db6e9f5"`);
await queryRunner.query(`DROP INDEX "IDX_f22169eb10657bded6d875ac8f"`);
await queryRunner.query(`DROP INDEX "IDX_c8cc87bd0f2f4487d17c651fbf"`);
await queryRunner.query(`DROP INDEX "IDX_754499f9b2642336433769518d"`);
await queryRunner.query(`DROP INDEX "IDX_315c779174fe8247ab324f036e"`);
await queryRunner.query(`DROP INDEX "IDX_c5d46cbfda48b1c33ed852e21b"`);
await queryRunner.query(`CREATE INDEX "IDX_337e9599f278bd7537fe30876f" ON "__chart__users" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_ed9b95919c672a13008e9487ee" ON "__chart__users" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_845254b3eaf708ae8a6cac3026" ON "__chart__users" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_a319e5dbf47e8a17497623beae" ON "__chart__test" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_d41cce6aee1a50bfc062038f9b" ON "__chart__test" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_b070a906db04b44c67c6c2144d" ON "__chart__test" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_a0cd75442dd10d0643a17c4a49" ON "__chart__test_unique" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_bbfa573a8181018851ed0b6357" ON "__chart__test_unique" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_437bab3c6061d90f6bb65fd2cc" ON "__chart__test_unique" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_b14489029e4b3aaf4bba5fb524" ON "__chart__test_grouped" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_234dff3c0b56a6150b95431ab9" ON "__chart__test_grouped" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_0c641990ecf47d2545df4edb75" ON "__chart__test_grouped" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_229a41ad465f9205f1f5703291" ON "__chart__per_user_reaction" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_8cf3156fd7a6b15c43459c6e3b" ON "__chart__per_user_reaction" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_f7bf4c62059764c2c2bb40fdab" ON "__chart__per_user_reaction" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_5048e9daccbbbc6d567bb142d3" ON "__chart__per_user_notes" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_55bf20f366979f2436de99206b" ON "__chart__per_user_notes" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_84234bd1abb873f07329681c83" ON "__chart__per_user_notes" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_b77d4dd9562c3a899d9a286fcd" ON "__chart__per_user_following" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_4b3593098b6edc9c5afe36b18b" ON "__chart__per_user_following" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_7af07790712aa3438ff6773f3b" ON "__chart__per_user_following" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_30bf67687f483ace115c5ca642" ON "__chart__per_user_drive" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_e496ca8096d28f6b9b509264dc" ON "__chart__per_user_drive" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_5f86db6492274e07c1a3cdf286" ON "__chart__per_user_drive" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_f09d543e3acb16c5976bdb31fa" ON "__chart__notes" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_7036f2957151588b813185c794" ON "__chart__notes" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_42eb716a37d381cdf566192b2b" ON "__chart__notes" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_0a905b992fecd2b5c3fb98759e" ON "__chart__network" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_7b5da130992ec9df96712d4290" ON "__chart__network" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_a1efd3e0048a5f2793a47360dc" ON "__chart__network" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_39ee857ab2f23493037c6b6631" ON "__chart__instance" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_da8a46ba84ca1d8bb5a29bfb63" ON "__chart__instance" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_6b8f34a1a64b06014b6fb66824" ON "__chart__instance" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_25a97c02003338124b2b75fdbc" ON "__chart__hashtag" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_99a7d2faaef84a6f728d714ad6" ON "__chart__hashtag" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_07747a1038c05f532a718fe1de" ON "__chart__hashtag" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_dd907becf76104e4b656659e6b" ON "__chart__federation" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_76e87c7bfc5d925fcbba405d84" ON "__chart__federation" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_36cb699c49580d4e6c2e6159f9" ON "__chart__federation" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_3313d7288855ec105b5bbf6c21" ON "__chart__drive" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_7a170f67425e62a8fabb76c872" ON "__chart__drive" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_13565815f618a1ff53886c5b28" ON "__chart__drive" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_9a3ed15a30ab7e3a37702e6e08" ON "__chart__active_users" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_00ed5f86db1f7efafb1978bf21" ON "__chart__active_users" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_0ad37b7ef50f4ddc84363d7ccc" ON "__chart__active_users" ("date") `);
}
}

View File

@ -0,0 +1,14 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class deeplIntegration1629024377804 implements MigrationInterface {
name = 'deeplIntegration1629024377804'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "meta" ADD "deeplAuthKey" character varying(128)`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deeplAuthKey"`);
}
}

View File

@ -0,0 +1,14 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class fixChannelUserId1629288472000 implements MigrationInterface {
name = 'fixChannelUserId1629288472000'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "channel" ALTER COLUMN "userId" DROP NOT NULL;`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "channel" ALTER COLUMN "userId" SET NOT NULL;`);
}
}

View File

@ -1,7 +1,7 @@
{
"name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>",
"version": "12.86.0",
"version": "12.88.0",
"codename": "indigo",
"repository": {
"type": "git",
@ -10,7 +10,8 @@
"main": "./index.js",
"private": true,
"scripts": {
"start": "node ./index.js",
"start": "node --experimental-json-modules ./index.js",
"start:test": "cross-env NODE_ENV=test node --experimental-json-modules ./index.js",
"init": "npm run migrate",
"ormconfig": "node ./built/ormconfig.js",
"migrate": "ts-node ./node_modules/typeorm/cli.js migration:run",
@ -26,6 +27,9 @@
"clean": "gulp clean",
"cleanall": "gulp cleanall",
"lint": "tslint 'src/**/*.ts'",
"cy:open": "cypress open",
"cy:run": "cypress run",
"e2e": "start-server-and-test start:test http://localhost cy:run",
"test": "cross-env TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha",
"format": "gulp format"
},
@ -34,7 +38,6 @@
"lodash": "^4.17.21"
},
"dependencies": {
"@babel/plugin-transform-runtime": "7.14.5",
"@elastic/elasticsearch": "7.11.0",
"@koa/cors": "3.1.0",
"@koa/multer": "3.0.0",
@ -44,7 +47,7 @@
"@sinonjs/fake-timers": "7.1.2",
"@syuilo/aiscript": "0.11.1",
"@types/bcryptjs": "2.4.2",
"@types/bull": "3.15.2",
"@types/bull": "3.15.3",
"@types/cbor": "6.0.0",
"@types/dateformat": "3.0.1",
"@types/escape-regexp": "0.0.0",
@ -57,8 +60,8 @@
"@types/jsonld": "1.5.6",
"@types/katex": "0.11.1",
"@types/koa": "2.13.4",
"@types/koa-bodyparser": "4.3.2",
"@types/koa-cors": "0.0.1",
"@types/koa-bodyparser": "4.3.3",
"@types/koa-cors": "0.0.2",
"@types/koa-favicon": "2.0.21",
"@types/koa-logger": "3.1.1",
"@types/koa-mount": "4.0.0",
@ -68,10 +71,10 @@
"@types/koa__multer": "2.0.3",
"@types/koa__router": "8.0.7",
"@types/markdown-it": "12.0.3",
"@types/matter-js": "0.17.3",
"@types/matter-js": "0.17.5",
"@types/mocha": "8.2.3",
"@types/node": "16.3.3",
"@types/node-fetch": "2.5.11",
"@types/node": "16.6.2",
"@types/node-fetch": "2.5.12",
"@types/nodemailer": "6.4.4",
"@types/nprogress": "0.2.0",
"@types/oauth": "0.9.1",
@ -86,9 +89,9 @@
"@types/redis": "2.8.31",
"@types/rename": "1.0.4",
"@types/request-stats": "3.0.0",
"@types/rimraf": "3.0.1",
"@types/rimraf": "3.0.2",
"@types/seedrandom": "2.4.28",
"@types/sharp": "0.28.4",
"@types/sharp": "0.28.5",
"@types/sinonjs__fake-timers": "6.0.3",
"@types/speakeasy": "2.0.6",
"@types/throttle-debounce": "2.1.0",
@ -98,40 +101,40 @@
"@types/web-push": "3.3.2",
"@types/webpack": "5.28.0",
"@types/webpack-stream": "3.2.12",
"@types/websocket": "1.0.3",
"@types/ws": "7.4.6",
"@typescript-eslint/parser": "4.28.3",
"@vue/compiler-sfc": "3.2.1",
"@types/websocket": "1.0.4",
"@types/ws": "7.4.7",
"@typescript-eslint/parser": "4.29.2",
"@vue/compiler-sfc": "3.2.4",
"abort-controller": "3.0.0",
"apexcharts": "3.27.2",
"apexcharts": "3.27.3",
"autobind-decorator": "2.4.0",
"autosize": "4.0.4",
"autwh": "0.1.0",
"aws-sdk": "2.948.0",
"aws-sdk": "2.966.0",
"bcryptjs": "2.4.3",
"blurhash": "1.1.3",
"broadcast-channel": "3.7.0",
"bull": "3.26.0",
"blurhash": "1.1.4",
"broadcast-channel": "4.2.0",
"bull": "3.28.1",
"cacheable-lookup": "6.0.0",
"cafy": "15.2.1",
"cbor": "7.0.6",
"chalk": "4.1.1",
"cbor": "8.0.0",
"chalk": "4.1.2",
"chart.js": "2.9.4",
"cli-highlight": "2.1.11",
"commander": "7.2.0",
"concurrently": "6.2.0",
"commander": "8.1.0",
"compare-versions": "3.6.0",
"concurrently": "6.2.1",
"content-disposition": "0.5.3",
"core-js": "3.15.2",
"crc-32": "1.2.0",
"css-loader": "6.0.0",
"cssnano": "5.0.6",
"css-loader": "6.2.0",
"cssnano": "5.0.8",
"dateformat": "4.5.1",
"diskusage": "1.1.3",
"escape-regexp": "0.0.1",
"eslint": "7.30.0",
"eslint-plugin-vue": "7.13.0",
"eslint": "7.32.0",
"eslint-plugin-vue": "7.16.0",
"eventemitter3": "4.0.7",
"feed": "4.2.2",
"file-type": "16.5.1",
"file-type": "16.5.3",
"fluent-ffmpeg": "2.1.2",
"glob": "7.1.7",
"got": "11.8.2",
@ -141,22 +144,18 @@
"gulp-replace": "1.1.3",
"gulp-terser": "2.0.1",
"gulp-tslint": "8.1.4",
"hard-source-webpack-plugin": "0.13.1",
"html-minifier": "4.0.0",
"http-proxy-agent": "4.0.1",
"hpagent": "0.1.2",
"http-signature": "1.3.5",
"https-proxy-agent": "5.0.0",
"idb-keyval": "5.1.3",
"insert-text-at-cursor": "0.3.0",
"is-root": "2.1.0",
"is-svg": "4.3.1",
"js-yaml": "4.1.0",
"jsdom": "16.6.0",
"jsdom": "16.7.0",
"json5": "2.2.0",
"json5-loader": "4.0.1",
"jsonld": "5.2.0",
"jsrsasign": "8.0.20",
"katex": "0.13.11",
"katex": "0.13.13",
"koa": "2.13.1",
"koa-bodyparser": "4.3.0",
"koa-favicon": "2.1.0",
@ -167,30 +166,26 @@
"koa-slow": "2.1.0",
"koa-views": "7.0.1",
"langmap": "0.0.16",
"lookup-dns-cache": "2.1.0",
"markdown-it": "12.1.0",
"markdown-it": "12.2.0",
"markdown-it-anchor": "7.1.0",
"matter-js": "0.17.1",
"mfm-js": "0.19.0",
"misskey-js": "0.0.6",
"mocha": "8.4.0",
"moji": "0.5.1",
"ms": "2.1.3",
"multer": "1.4.2",
"multer": "1.4.3",
"nested-property": "4.0.0",
"node-fetch": "2.6.1",
"nodemailer": "6.6.3",
"object-assign-deep": "0.4.0",
"os-utils": "0.0.14",
"parse5": "6.0.1",
"pg": "8.6.0",
"pg": "8.7.1",
"portscanner": "2.2.0",
"postcss": "8.3.5",
"postcss": "8.3.6",
"postcss-loader": "6.1.1",
"prismjs": "1.24.1",
"probe-image-size": "7.2.1",
"promise-limit": "2.7.0",
"promise-sequential": "1.1.1",
"pug": "3.0.2",
"punycode": "2.1.1",
"pureimage": "0.3.2",
@ -198,67 +193,62 @@
"random-seed": "0.3.0",
"ratelimiter": "3.4.1",
"re2": "1.16.0",
"reconnecting-websocket": "4.4.0",
"redis": "3.1.2",
"redis-lock": "0.1.4",
"reflect-metadata": "0.1.13",
"regenerator-runtime": "0.13.7",
"rename": "1.0.4",
"request-stats": "3.0.0",
"require-all": "3.0.0",
"rimraf": "3.0.2",
"rndstr": "1.0.0",
"s-age": "1.1.2",
"sass": "1.35.2",
"sass": "1.38.0",
"sass-loader": "12.1.0",
"seedrandom": "3.0.5",
"sharp": "0.28.3",
"sharp": "0.29.0",
"speakeasy": "2.0.0",
"stringz": "2.1.0",
"style-loader": "3.1.0",
"summaly": "2.4.0",
"style-loader": "3.2.1",
"summaly": "2.4.1",
"syslog-pro": "1.0.0",
"systeminformation": "5.7.7",
"systeminformation": "5.8.0",
"syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0",
"three": "0.117.1",
"throttle-debounce": "3.0.1",
"tinycolor2": "1.4.2",
"tmp": "0.2.1",
"ts-loader": "9.2.3",
"ts-node": "10.1.0",
"tsc-alias": "1.3.7",
"ts-loader": "9.2.5",
"ts-node": "10.2.1",
"tsc-alias": "1.3.9",
"tsconfig-paths": "3.10.1",
"tslint": "6.1.3",
"tslint-sonarts": "1.9.0",
"twemoji-parser": "13.1.0",
"typeorm": "0.2.32",
"typeorm": "0.2.37",
"typescript": "4.3.5",
"ulid": "2.3.0",
"uuid": "8.3.2",
"v-debounce": "0.1.2",
"vanilla-tilt": "1.7.0",
"vue": "3.2.1",
"vue-color": "2.8.1",
"vue-json-pretty": "1.8.1",
"vue-loader": "16.3.1",
"vue": "3.2.4",
"vue-loader": "16.5.0",
"vue-prism-editor": "2.0.0-alpha.2",
"vue-router": "4.0.5",
"vue-style-loader": "4.1.3",
"vue-svg-loader": "0.17.0-beta.2",
"vuedraggable": "4.0.1",
"web-push": "3.4.5",
"webpack": "5.45.1",
"webpack-cli": "4.7.2",
"webpack": "5.51.0",
"webpack-cli": "4.8.0",
"websocket": "1.0.34",
"ws": "7.5.3",
"ws": "8.2.0",
"xev": "2.0.1"
},
"devDependencies": {
"@redocly/openapi-core": "1.0.0-beta.44",
"@types/chai": "4.2.16",
"@types/fluent-ffmpeg": "2.1.17",
"chai": "4.3.4",
"cross-env": "7.0.3"
"cross-env": "7.0.3",
"cypress": "8.3.0",
"start-server-and-test": "1.13.1"
}
}

View File

@ -1,7 +0,0 @@
declare module 'is-root' {
function isRoot(): boolean;
namespace isRoot {} // Hack
export = isRoot;
}

View File

@ -1,9 +0,0 @@
declare module 'lookup-dns-cache' {
import { LookupOneOptions, LookupAllOptions, LookupOptions, LookupAddress } from 'dns';
function lookup(hostname: string, family: number, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void;
function lookup(hostname: string, options: LookupOneOptions, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void;
function lookup(hostname: string, options: LookupAllOptions, callback: (err: NodeJS.ErrnoException | null, addresses: LookupAddress[]) => void): void;
function lookup(hostname: string, options: LookupOptions, callback: (err: NodeJS.ErrnoException | null, address: string | LookupAddress[], family: number) => void): void;
function lookup(hostname: string, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void;
}

View File

@ -1,24 +1,23 @@
import { Command } from 'commander';
import config from '@/config';
import config from '@/config/index';
const program = new Command();
program
.version(config.version)
.option('--no-daemons', 'Disable daemon processes (for debbuging)')
.option('--disable-clustering', 'Disable clustering')
.option('--only-server', 'Run server only (without job queue processing)')
.option('--only-queue', 'Pocessing job queue only (without server)')
.option('--quiet', 'Suppress all logs')
.option('--verbose', 'Enable all logs')
.option('--with-log-time', 'Include timestamp for each logs')
.option('--slow', 'Delay all requests (for debbuging)')
.option('--color', 'This option is a dummy for some external program\'s (e.g. forever) issue.')
.parse(process.argv);
program.version(config.version);
program.option('--no-daemons', 'Disable daemon processes (for debbuging)');
program.option('--disable-clustering', 'Disable clustering');
program.option('--only-server', 'Run server only (without job queue processing)');
program.option('--only-queue', 'Pocessing job queue only (without server)');
program.option('--quiet', 'Suppress all logs');
program.option('--verbose', 'Enable all logs');
program.option('--with-log-time', 'Include timestamp for each logs');
program.option('--slow', 'Delay all requests (for debbuging)');
program.option('--color', 'This option is a dummy for some external program\'s (e.g. forever) issue.');
program.parse(process.argv);
if (process.env.MK_ONLY_QUEUE) program.onlyQueue = true;
if (process.env.NODE_ENV === 'test') program.disableClustering = true;
if (process.env.NODE_ENV === 'test') program.quiet = true;
//if (process.env.NODE_ENV === 'test') program.quiet = true;
if (process.env.NODE_ENV === 'test') program.noDaemons = true;
export { program };

View File

@ -2,7 +2,7 @@ import * as cluster from 'cluster';
import * as chalk from 'chalk';
import Xev from 'xev';
import Logger from '../services/logger';
import Logger from '@/services/logger';
import { program } from '../argv';
// for typeorm

View File

@ -2,17 +2,16 @@ import * as os from 'os';
import * as cluster from 'cluster';
import * as chalk from 'chalk';
import * as portscanner from 'portscanner';
import * as isRoot from 'is-root';
import { getConnection } from 'typeorm';
import Logger from '../services/logger';
import Logger from '@/services/logger';
import loadConfig from '@/config/load';
import { Config } from '@/config/types';
import { lessThan } from '../prelude/array';
import { lessThan } from '@/prelude/array';
import { program } from '../argv';
import { showMachineInfo } from '@/misc/show-machine-info';
import { initDb } from '../db/postgre';
const meta = require('../meta.json');
import * as meta from '../meta.json';
const logger = new Logger('core', 'cyan');
const bootLogger = logger.createSubLogger('boot', 'magenta', false);
@ -39,6 +38,11 @@ function greet() {
bootLogger.info(`Misskey v${meta.version}`, null, true);
}
function isRoot() {
// maybe process.getuid will be undefined under not POSIX environment (e.g. Windows)
return process.getuid != null && process.getuid() === 0;
}
/**
* Init master process
*/

View File

@ -35,6 +35,7 @@ import { twemojiSvgBase } from '@/misc/twemoji-base';
import { getStaticImageUrl } from '@client/scripts/get-static-image-url';
import { acct } from '@client/filters/user';
import * as os from '@client/os';
import { instance } from '@client/instance';
type EmojiDef = {
emoji: string;
@ -75,6 +76,36 @@ for (const x of lib) {
emjdb.sort((a, b) => a.name.length - b.name.length);
//#region Construct Emoji DB
const customEmojis = instance.emojis;
const emojiDefinitions: EmojiDef[] = [];
for (const x of customEmojis) {
emojiDefinitions.push({
name: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true
});
if (x.aliases) {
for (const alias of x.aliases) {
emojiDefinitions.push({
name: alias,
aliasOf: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true
});
}
}
}
emojiDefinitions.sort((a, b) => a.name.length - b.name.length);
const emojiDb = markRaw(emojiDefinitions.concat(emjdb));
//#endregion
export default defineComponent({
props: {
type: {
@ -124,7 +155,6 @@ export default defineComponent({
emojis: [],
items: [],
select: -1,
emojiDb: [] as EmojiDef[]
}
},
@ -144,36 +174,6 @@ export default defineComponent({
mounted() {
this.setPosition();
//#region Construct Emoji DB
const customEmojis = this.$instance.emojis;
const emojiDefinitions: EmojiDef[] = [];
for (const x of customEmojis) {
emojiDefinitions.push({
name: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true
});
if (x.aliases) {
for (const alias of x.aliases) {
emojiDefinitions.push({
name: alias,
aliasOf: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true
});
}
}
}
emojiDefinitions.sort((a, b) => a.name.length - b.name.length);
this.emojiDb = markRaw(emojiDefinitions.concat(emjdb));
//#endregion
this.textarea.addEventListener('keydown', this.onKeydown);
for (const el of Array.from(document.querySelectorAll('body *'))) {
@ -203,6 +203,13 @@ export default defineComponent({
complete(type, value) {
this.$emit('done', { type, value });
this.$emit('closed');
if (type === 'emoji') {
let recents = this.$store.state.recentlyUsedEmojis;
recents = recents.filter((e: any) => e !== value);
recents.unshift(value);
this.$store.set('recentlyUsedEmojis', recents.splice(0, 32));
}
},
setPosition() {
@ -281,29 +288,26 @@ export default defineComponent({
}
} else if (this.type == 'emoji') {
if (this.q == null || this.q == '') {
this.emojis = this.emojiDb.filter(x => x.isCustomEmoji && !x.aliasOf).sort((a, b) => {
var textA = a.name.toUpperCase();
var textB = b.name.toUpperCase();
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
});
// 使
this.emojis = this.$store.state.recentlyUsedEmojis.map(emoji => emojiDb.find(e => e.emoji == emoji)).filter(x => x != null);
return;
}
const matched = [];
const max = 30;
this.emojiDb.some(x => {
emojiDb.some(x => {
if (x.name.startsWith(this.q) && !x.aliasOf && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == max;
});
if (matched.length < max) {
this.emojiDb.some(x => {
emojiDb.some(x => {
if (x.name.startsWith(this.q) && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == max;
});
}
if (matched.length < max) {
this.emojiDb.some(x => {
emojiDb.some(x => {
if (x.name.includes(this.q) && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == max;
});

View File

@ -93,13 +93,13 @@ export default defineComponent({
});
return h(this.$store.state.animation ? TransitionGroup : 'div', this.$store.state.animation ? {
class: 'sqadhkmv' + (this.noGap ? ' noGap _block' : ''),
class: 'sqadhkmv' + (this.noGap ? ' noGap' : ''),
name: 'list',
tag: 'div',
'data-direction': this.direction,
'data-reversed': this.reversed ? 'true' : 'false',
} : {
class: 'sqadhkmv' + (this.noGap ? ' noGap _block' : ''),
class: 'sqadhkmv' + (this.noGap ? ' noGap' : ''),
}, {
default: renderChildren
});

View File

@ -1,5 +1,5 @@
<template>
<div class="yxspomdl" :class="{ inline, colored }">
<div class="yxspomdl" :class="{ inline, colored, mini }">
<div class="ring"></div>
</div>
</template>
@ -18,7 +18,12 @@ export default defineComponent({
type: Boolean,
required: false,
default: true
}
},
mini: {
type: Boolean,
required: false,
default: false
},
}
});
</script>
@ -38,6 +43,8 @@ export default defineComponent({
text-align: center;
cursor: wait;
--size: 48px;
&.colored {
color: var(--accent);
}
@ -45,19 +52,12 @@ export default defineComponent({
&.inline {
display: inline;
padding: 0;
> .ring:after {
width: 32px;
height: 32px;
--size: 32px;
}
> .ring {
&:before,
&:after {
width: 32px;
height: 32px;
}
}
&.mini {
padding: 16px;
--size: 32px;
}
> .ring {
@ -70,8 +70,8 @@ export default defineComponent({
content: " ";
display: block;
box-sizing: border-box;
width: 48px;
height: 48px;
width: var(--size);
height: var(--size);
border-radius: 50%;
border: solid 4px;
}

View File

@ -1,6 +1,6 @@
<template>
<div
class="note _block"
class="lxwezrsl _block"
v-if="!muted"
v-show="!isDeleted"
:tabindex="!isDeleted ? '-1' : null"
@ -67,6 +67,13 @@
<MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><i class="fas fa-reply"></i></MkA>
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
<a class="rp" v-if="appearNote.renote != null">RN:</a>
<div class="translation" v-if="translating || translation">
<MkLoading v-if="translating" mini/>
<div class="translated" v-else>
<b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}:</b>
{{ translation.text }}
</div>
</div>
</div>
<div class="files" v-if="appearNote.files.length > 0">
<XMediaList :media-list="appearNote.files"/>
@ -79,8 +86,8 @@
</div>
<footer class="footer">
<div class="info">
<span class="mobile" v-if="note.viaMobile"><i class="fas fa-mobile-alt"></i></span>
<MkTime class="created-at" :time="note.createdAt" mode="detail"/>
<span class="mobile" v-if="appearNote.viaMobile"><i class="fas fa-mobile-alt"></i></span>
<MkTime class="created-at" :time="appearNote.createdAt" mode="detail"/>
</div>
<XReactionsViewer :note="appearNote" ref="reactionsViewer"/>
<button @click="reply()" class="button _button">
@ -178,6 +185,8 @@ export default defineComponent({
showContent: false,
isDeleted: false,
muted: false,
translation: null,
translating: false,
};
},
@ -619,6 +628,11 @@ export default defineComponent({
text: this.$ts.share,
action: this.share
},
this.$instance.translatorAvailable ? {
icon: 'fas fa-language',
text: this.$ts.translate,
action: this.translate
} : undefined,
null,
statePromise.then(state => state.isFavorited ? {
icon: 'fas fa-star',
@ -852,6 +866,17 @@ export default defineComponent({
});
},
async translate() {
if (this.translation != null) return;
this.translating = true;
const res = await os.api('notes/translate', {
noteId: this.appearNote.id,
targetLang: localStorage.getItem('lang') || navigator.language,
});
this.translating = false;
this.translation = res;
},
focus() {
this.$el.focus();
},
@ -874,7 +899,7 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
.note {
.lxwezrsl {
position: relative;
transition: box-shadow 0.1s ease;
overflow: hidden;
@ -1050,6 +1075,13 @@ export default defineComponent({
font-style: oblique;
color: var(--renote);
}
> .translation {
border: solid 0.5px var(--divider);
border-radius: var(--radius);
padding: 12px;
margin-top: 8px;
}
}
> .url-preview {

View File

@ -51,6 +51,13 @@
<MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><i class="fas fa-reply"></i></MkA>
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
<a class="rp" v-if="appearNote.renote != null">RN:</a>
<div class="translation" v-if="translating || translation">
<MkLoading v-if="translating" mini/>
<div class="translated" v-else>
<b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}:</b>
{{ translation.text }}
</div>
</div>
</div>
<div class="files" v-if="appearNote.files.length > 0">
<XMediaList :media-list="appearNote.files"/>
@ -164,6 +171,8 @@ export default defineComponent({
collapsed: false,
isDeleted: false,
muted: false,
translation: null,
translating: false,
};
},
@ -594,6 +603,11 @@ export default defineComponent({
text: this.$ts.share,
action: this.share
},
this.$instance.translatorAvailable ? {
icon: 'fas fa-language',
text: this.$ts.translate,
action: this.translate
} : undefined,
null,
statePromise.then(state => state.isFavorited ? {
icon: 'fas fa-star',
@ -827,6 +841,17 @@ export default defineComponent({
});
},
async translate() {
if (this.translation != null) return;
this.translating = true;
const res = await os.api('notes/translate', {
noteId: this.appearNote.id,
targetLang: localStorage.getItem('lang') || navigator.language,
});
this.translating = false;
this.translation = res;
},
focus() {
this.$el.focus();
},
@ -1053,6 +1078,13 @@ export default defineComponent({
font-style: oblique;
color: var(--renote);
}
> .translation {
border: solid 0.5px var(--divider);
border-radius: var(--radius);
padding: 12px;
margin-top: 8px;
}
}
> .url-preview {

View File

@ -9,7 +9,7 @@
<div>{{ $ts.noNotes }}</div>
</div>
<div v-else>
<div v-else class="giivymft" :class="{ noGap }">
<div v-show="more && reversed" style="margin-bottom: var(--margin);">
<MkButton style="margin: 0 auto;" @click="fetchMoreFeature" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
<template v-if="!moreFetching">{{ $ts.loadMore }}</template>
@ -17,8 +17,8 @@
</MkButton>
</div>
<XList ref="notes" :items="notes" v-slot="{ item: note }" :direction="reversed ? 'up' : 'down'" :reversed="reversed" :no-gap="noGap" :ad="true">
<XNote :note="note" class="_block" @update:note="updated(note, $event)" :key="note._featuredId_ || note._prId_ || note.id"/>
<XList ref="notes" :items="notes" v-slot="{ item: note }" :direction="reversed ? 'up' : 'down'" :reversed="reversed" :no-gap="noGap" :ad="true" class="notes">
<XNote class="qtqtichx" :note="note" @update:note="updated(note, $event)" :key="note._featuredId_ || note._prId_ || note.id"/>
</XList>
<div v-show="more && !reversed" style="margin-top: var(--margin);">
@ -108,4 +108,21 @@ export default defineComponent({
.fade-leave-to {
opacity: 0;
}
.giivymft {
&.noGap {
> .notes {
background: var(--panel);
}
}
&:not(.noGap) {
> .notes {
.qtqtichx {
background: var(--panel);
border-radius: var(--radius);
}
}
}
}
</style>

View File

@ -17,7 +17,7 @@
<span v-if="visibility === 'followers'"><i class="fas fa-unlock"></i></span>
<span v-if="visibility === 'specified'"><i class="fas fa-envelope"></i></span>
</button>
<button class="submit _buttonPrimary" :disabled="!canPost" @click="post">{{ submitText }}<i :class="reply ? 'fas fa-reply' : renote ? 'fas fa-quote-right' : 'fas fa-paper-plane'"></i></button>
<button class="submit _buttonPrimary" :disabled="!canPost" @click="post" data-cy-open-post-form-submit>{{ submitText }}<i :class="reply ? 'fas fa-reply' : renote ? 'fas fa-quote-right' : 'fas fa-paper-plane'"></i></button>
</div>
</header>
<div class="form" :class="{ fixed }">
@ -36,7 +36,7 @@
</div>
<MkInfo warn v-if="hasNotSpecifiedMentions" class="hasNotSpecifiedMentions">{{ $ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ $ts.add }}</button></MkInfo>
<input v-show="useCw" ref="cw" class="cw" v-model="cw" :placeholder="$ts.annotation" @keydown="onKeydown">
<textarea v-model="text" class="text" :class="{ withCw: useCw }" ref="text" :disabled="posting" :placeholder="placeholder" @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd" />
<textarea v-model="text" class="text" :class="{ withCw: useCw }" ref="text" :disabled="posting" :placeholder="placeholder" @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd" data-cy-post-form-text/>
<input v-show="withHashtags" ref="hashtags" class="hashtags" v-model="hashtags" :placeholder="$ts.hashtags" list="hashtags">
<XPostFormAttaches class="attaches" :files="files" @updated="updateFiles" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/>
<XPollEditor v-if="poll" :poll="poll" @destroyed="poll = null" @updated="onPollUpdate"/>

View File

@ -3,11 +3,11 @@
<div class="auth _section">
<div class="avatar" :style="{ backgroundImage: user ? `url('${ user.avatarUrl }')` : null }" v-show="withAvatar"></div>
<div class="normal-signin" v-if="!totpLogin">
<MkInput v-model="username" :placeholder="$ts.username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required @update:modelValue="onUsernameChange">
<MkInput v-model="username" :placeholder="$ts.username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required @update:modelValue="onUsernameChange" data-cy-signin-username>
<template #prefix>@</template>
<template #suffix>@{{ host }}</template>
</MkInput>
<MkInput v-model="password" :placeholder="$ts.password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required>
<MkInput v-model="password" :placeholder="$ts.password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required data-cy-signin-password>
<template #prefix><i class="fas fa-lock"></i></template>
<template #caption><button class="_textButton" @click="resetPassword" type="button">{{ $ts.forgotPassword }}</button></template>
</MkInput>

View File

@ -5,7 +5,7 @@
<template #label>{{ $ts.invitationCode }}</template>
<template #prefix><i class="fas fa-key"></i></template>
</MkInput>
<MkInput v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @update:modelValue="onChangeUsername">
<MkInput v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @update:modelValue="onChangeUsername" data-cy-signup-username>
<template #label>{{ $ts.username }}</template>
<template #prefix>@</template>
<template #suffix>@{{ host }}</template>
@ -19,7 +19,7 @@
<span v-if="usernameState == 'max-range'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.tooLong }}</span>
</template>
</MkInput>
<MkInput v-model="password" type="password" :autocomplete="Math.random()" required @update:modelValue="onChangePassword">
<MkInput v-model="password" type="password" :autocomplete="Math.random()" required @update:modelValue="onChangePassword" data-cy-signup-password>
<template #label>{{ $ts.password }}</template>
<template #prefix><i class="fas fa-lock"></i></template>
<template #caption>
@ -28,7 +28,7 @@
<span v-if="passwordStrength == 'high'" style="color: var(--success)"><i class="fas fa-check fa-fw"></i> {{ $ts.strongPassword }}</span>
</template>
</MkInput>
<MkInput v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @update:modelValue="onChangePasswordRetype">
<MkInput v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @update:modelValue="onChangePasswordRetype" data-cy-signup-password-retype>
<template #label>{{ $ts.password }} ({{ $ts.retype }})</template>
<template #prefix><i class="fas fa-lock"></i></template>
<template #caption>
@ -46,7 +46,7 @@
</label>
<captcha v-if="meta.enableHcaptcha" class="captcha" provider="hcaptcha" ref="hcaptcha" v-model:value="hCaptchaResponse" :sitekey="meta.hcaptchaSiteKey"/>
<captcha v-if="meta.enableRecaptcha" class="captcha" provider="recaptcha" ref="recaptcha" v-model:value="reCaptchaResponse" :sitekey="meta.recaptchaSiteKey"/>
<MkButton type="submit" :disabled="shouldDisableSubmitting" primary>{{ $ts.start }}</MkButton>
<MkButton type="submit" :disabled="shouldDisableSubmitting" primary data-cy-signup-submit>{{ $ts.start }}</MkButton>
</template>
</form>
</template>

View File

@ -1,5 +1,5 @@
<template>
<transition :name="$store.state.animation ? 'popup-menu' : ''" :duration="$store.state.animation ? 300 : 0" appear @after-leave="onClosed" @enter="$emit('opening')" @after-enter="childRendered">
<transition :name="$store.state.animation ? 'popup-menu' : ''" appear @after-leave="onClosed" @enter="$emit('opening')" @after-enter="childRendered">
<div v-show="manualShowing != null ? manualShowing : showing" class="ccczpooj" :class="{ front, fixed, top: position === 'top' }" ref="content" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
<slot :point="point"></slot>
</div>

View File

@ -0,0 +1,58 @@
<template>
<MkModal ref="modal" @click="$refs.modal.close()" @closed="$emit('closed')">
<div class="ewlycnyt">
<div class="title">{{ $ts.misskeyUpdated }}</div>
<div class="version">{{ version }}🚀</div>
<MkButton full @click="whatIsNew">{{ $ts.whatIsNew }}</MkButton>
<MkButton primary full @click="$refs.modal.close()">{{ $ts.gotIt }}</MkButton>
</div>
</MkModal>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MkModal from '@client/components/ui/modal.vue';
import MkButton from '@client/components/ui/button.vue';
import { version } from '@client/config';
export default defineComponent({
components: {
MkModal,
MkButton,
},
data() {
return {
version: version,
};
},
methods: {
whatIsNew() {
this.$refs.modal.close();
this.$router.push('/docs/general/changelog');
}
}
});
</script>
<style lang="scss" scoped>
.ewlycnyt {
position: relative;
padding: 32px;
min-width: 320px;
max-width: 480px;
box-sizing: border-box;
text-align: center;
background: var(--panel);
border-radius: var(--radius);
> .title {
font-weight: bold;
}
> .version {
margin: 1em 0;
}
}
</style>

View File

@ -16,6 +16,7 @@ if (localStorage.getItem('accounts') != null) {
import * as Sentry from '@sentry/browser';
import { Integrations } from '@sentry/tracing';
import { computed, createApp, watch, markRaw } from 'vue';
import compareVersions from 'compare-versions';
import widgets from '@client/widgets';
import directives from '@client/directives';
@ -25,7 +26,7 @@ import { router } from '@client/router';
import { applyTheme } from '@client/scripts/theme';
import { isDeviceDarkmode } from '@client/scripts/is-device-darkmode';
import { i18n } from '@client/i18n';
import { stream, dialog, post } from '@client/os';
import { stream, dialog, post, popup } from '@client/os';
import * as sound from '@client/scripts/sound';
import { $i, refreshAccount, login, updateAccount, signout } from '@client/account';
import { defaultStore, ColdDeviceStorage } from '@client/store';
@ -227,6 +228,23 @@ if (splash) {
splash.style.pointerEvents = 'none';
}
// クライアントが更新されたか?
const lastVersion = localStorage.getItem('lastVersion');
if (lastVersion !== version) {
localStorage.setItem('lastVersion', version);
// テーマリビルドするため
localStorage.removeItem('theme');
try { // 変なバージョン文字列来るとcompareVersionsでエラーになるため
if (lastVersion != null && compareVersions(version, lastVersion) === 1) {
popup(import('@client/components/updated.vue'), {}, {}, 'closed');
}
} catch (e) {
}
}
// NOTE: この処理は必ず↑のクライアント更新時処理より後に来ること(テーマ再構築のため)
watch(defaultStore.reactiveState.darkMode, (darkMode) => {
applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'));
}, { immediate: localStorage.theme == null });

View File

@ -25,6 +25,7 @@ export async function fetchInstance() {
}
export const emojiCategories = computed(() => {
if (instance.emojis == null) return [];
const categories = new Set();
for (const emoji of instance.emojis) {
categories.add(emoji.category);
@ -33,6 +34,7 @@ export const emojiCategories = computed(() => {
});
export const emojiTags = computed(() => {
if (instance.emojis == null) return [];
const tags = new Set();
for (const emoji of instance.emojis) {
for (const tag of emoji.aliases) {

View File

@ -4,14 +4,14 @@
<div id="debug"></div>
<section class="_formItem about">
<div class="_formPanel panel" :class="{ playing: easterEggEngine != null }" ref="about">
<img src="/static-assets/client/about-icon.png" alt="" class="icon" ref="icon" @load="iconLoaded" draggable="false"/>
<img src="/static-assets/client/about-icon.png" alt="" class="icon" @load="iconLoaded" draggable="false" @click="gravity"/>
<div class="misskey">Misskey</div>
<div class="version">v{{ version }}</div>
<span class="emoji" v-for="emoji in easterEggEmojis" :key="emoji.id" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }"><MkEmoji class="emoji" :emoji="emoji.emoji" :custom-emojis="$instance.emojis" :is-reaction="false" :normal="true" :no-style="true"/></span>
</div>
</section>
<section class="_formItem" style="text-align: center; padding: 0 16px;" @click="gravity">
{{ $ts._aboutMisskey.about }}
<section class="_formItem" style="text-align: center; padding: 0 16px;">
{{ $ts._aboutMisskey.about }}<br><MkA class="_link" to="/docs/general/misskey">{{ $ts.learnMore }}</MkA>
</section>
<FormGroup>
<FormLink to="https://github.com/misskey-dev/misskey" external>
@ -54,7 +54,6 @@
<script lang="ts">
import { defineComponent } from 'vue';
import VanillaTilt from 'vanilla-tilt';
import { version } from '@client/config';
import FormLink from '@client/components/form/link.vue';
import FormBase from '@client/components/form/base.vue';
@ -62,7 +61,6 @@ import FormGroup from '@client/components/form/group.vue';
import FormKeyValueView from '@client/components/form/key-value-view.vue';
import MkLink from '@client/components/link.vue';
import { physics } from '@client/scripts/physics.ts';
import * as os from '@client/os';
import * as symbols from '@client/symbols';
const patrons = [
@ -145,15 +143,6 @@ export default defineComponent({
}
},
mounted() {
VanillaTilt.init(this.$refs.icon, {
max: 30,
perspective: 500,
scale: 1.125,
speed: 1000,
});
},
beforeUnmount() {
if (this.easterEggEngine) {
this.easterEggEngine.stop();
@ -181,7 +170,6 @@ export default defineComponent({
gravity() {
if (!this.easterEggReady) return;
this.easterEggReady = false;
this.$refs.icon.vanillaTilt.destroy();
this.easterEggEngine = physics(this.$refs.about);
}
}

View File

@ -1,7 +1,7 @@
<template>
<div class="_root">
<div class="_block" style="padding: 24px;">
<MkInput v-model="endpoint" :datalist="endpoints" @update:modelValue="onEndpointChange()">
<MkInput v-model="endpoint" :datalist="endpoints" @update:modelValue="onEndpointChange()" class="_inputNoTopMargin">
<template #label>Endpoint</template>
</MkInput>
<MkTextarea v-model="body" code>

View File

@ -1,10 +1,12 @@
<template>
<div class="vtaihdtm">
<div class="body">
<div class="search">
<MkInput v-model="query" :debounce="true" type="search" class="_inputNoTopMargin _inputNoBottomMargin" :placeholder="$ts.search">
<template #prefix><i class="fas fa-search"></i></template>
</MkInput>
</div>
<div class="list">
<MkFolder>
<template #header>{{ $ts._docs.generalTopics }}</template>
<div class="docs">
@ -45,6 +47,8 @@
</MkA>
</div>
</MkFolder>
</div>
</div>
</div>
</template>
@ -97,15 +101,22 @@ export default defineComponent({
.vtaihdtm {
background: var(--panel);
> .body {
max-width: 900px;
margin: 0 auto;
> .search {
padding: 16px;
}
> .list {
padding: 0 16px;
.docs {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
grid-gap: 12px;
margin: 0 16px 16px 16px;
margin: 0 0 16px 0;
> .doc {
display: inline-block;
@ -135,5 +146,7 @@ export default defineComponent({
}
}
}
}
}
}
</style>

View File

@ -1,6 +1,8 @@
<template>
<div class="_section">
<XNotes class="_content" :pagination="pagination" :detail="true" :prop="'note'" @before="before()" @after="after()"/>
<div class="jmelgwjh">
<div class="body">
<XNotes class="notes" :pagination="pagination" :detail="true" :prop="'note'" @before="before()" @after="after()"/>
</div>
</div>
</template>
@ -42,3 +44,16 @@ export default defineComponent({
}
});
</script>
<style lang="scss" scoped>
.jmelgwjh {
background: var(--bg);
> .body {
box-sizing: border-box;
max-width: 800px;
margin: 0 auto;
padding: 16px;
}
}
</style>

View File

@ -93,10 +93,8 @@ export default defineComponent({
});
if (canceled) return;
os.api('drive/files/delete', {
os.apiWithDialog('drive/files/delete', {
fileId: this.file.id
}).then(() => {
this.$refs.files.removeItem(x => x.id === this.file.id);
});
},

View File

@ -7,7 +7,12 @@
Summaly Proxy URL
</FormInput>
</FormGroup>
<FormGroup>
<FormInput v-model:value="deeplAuthKey">
<template #prefix><i class="fas fa-key"></i></template>
DeepL Auth Key
</FormInput>
</FormGroup>
<FormButton @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
</FormSuspense>
</FormBase>
@ -44,6 +49,7 @@ export default defineComponent({
icon: 'fas fa-cogs'
},
summalyProxy: '',
deeplAuthKey: '',
}
},
@ -55,10 +61,12 @@ export default defineComponent({
async init() {
const meta = await os.api('meta', { detail: true });
this.summalyProxy = meta.summalyProxy;
this.deeplAuthKey = meta.deeplAuthKey;
},
save() {
os.apiWithDialog('admin/update-meta', {
summalyProxy: this.summalyProxy,
deeplAuthKey: this.deeplAuthKey,
}).then(() => {
fetchInstance();
});

View File

@ -8,9 +8,9 @@
<div class="main _gap">
<MkButton v-if="!showNext && hasNext" class="load next" @click="showNext = true"><i class="fas fa-chevron-up"></i></MkButton>
<div class="_content _gap">
<MkRemoteCaution v-if="note.user.host != null" :href="note.url || note.uri" class="_gap"/>
<XNoteDetailed v-model:note="note" :key="note.id" class="_gap"/>
<div class="note _gap">
<MkRemoteCaution v-if="note.user.host != null" :href="note.url || note.uri" class="_isolated"/>
<XNoteDetailed v-model:note="note" :key="note.id" class="_isolated note"/>
</div>
<div class="_content clips _gap" v-if="clips && clips.length > 0">
<div class="title">{{ $ts.clip }}</div>
@ -108,6 +108,7 @@ export default defineComponent({
os.api('notes/show', {
noteId: this.noteId
}).then(note => {
this.note = note;
Promise.all([
os.api('notes/clips', {
noteId: note.id,
@ -126,7 +127,6 @@ export default defineComponent({
this.clips = clips;
this.hasPrev = prev.length !== 0;
this.hasNext = next.length !== 0;
this.note = note;
});
}).catch(e => {
this.error = e;
@ -147,6 +147,8 @@ export default defineComponent({
}
.fcuexfpr {
background: var(--bg);
> .note {
> .main {
> .load {
@ -163,6 +165,13 @@ export default defineComponent({
}
}
> .note {
> .note {
border-radius: var(--radius);
background: var(--panel);
}
}
> .clips {
> .title {
font-weight: bold;

View File

@ -1,5 +1,5 @@
<template>
<div class="_root">
<div class="">
<XNotifications class="_content" @before="before" @after="after" page/>
</div>
</template>

View File

@ -48,6 +48,7 @@ const soundsTypes = [
'syuilo/ryukyu',
'syuilo/kick',
'syuilo/snare',
'syuilo/queue-jammed',
'aisha/1',
'aisha/2',
'aisha/3',

View File

@ -1,5 +1,5 @@
<template>
<div class="cmuxhskf _root" v-hotkey.global="keymap">
<div class="cmuxhskf" v-hotkey.global="keymap">
<XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block _isolated"/>
<XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block _isolated" fixed/>
<div class="tabs">
@ -19,7 +19,7 @@
</div>
</div>
<div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
<XTimeline ref="tl"
<XTimeline ref="tl" class="tl"
:key="src === 'list' ? `list:${list.id}` : src === 'antenna' ? `antenna:${antenna.id}` : src === 'channel' ? `channel:${channel.id}` : src"
:src="src"
:list="list ? list.id : null"
@ -211,8 +211,6 @@ export default defineComponent({
<style lang="scss" scoped>
.cmuxhskf {
background: var(--bg);
> .new {
position: sticky;
top: calc(var(--stickyTop, 0px) + 16px);
@ -262,10 +260,9 @@ export default defineComponent({
left: 0;
right: 0;
margin: 0 auto;
width: calc(100% - 16px);
height: 4px;
width: 100%;
height: 2px;
background: var(--accent);
border-radius: 8px 8px 0 0;
}
}
@ -289,5 +286,9 @@ export default defineComponent({
}
}
}
> .tl {
border-top: solid 0.5px var(--divider);
}
}
</style>

View File

@ -27,8 +27,8 @@
<div class="desc" v-html="meta.description || $ts.headlineMisskey"></div>
</div>
<div class="action">
<MkButton @click="signup()" inline primary>{{ $ts.signup }}</MkButton>
<MkButton @click="signin()" inline>{{ $ts.login }}</MkButton>
<MkButton @click="signup()" inline primary data-cy-signup>{{ $ts.signup }}</MkButton>
<MkButton @click="signin()" inline data-cy-signin>{{ $ts.login }}</MkButton>
</div>
<div class="status" v-if="onlineUsersCount && stats">
<div>

View File

@ -3,17 +3,19 @@
<h1>Welcome to Misskey!</h1>
<div>
<p>{{ $ts.intro }}</p>
<MkInput v-model="username" pattern="^[a-zA-Z0-9_]{1,20}$" spellcheck="false" required>
<MkInput v-model="username" pattern="^[a-zA-Z0-9_]{1,20}$" spellcheck="false" required data-cy-admin-username>
<template #label>{{ $ts.username }}</template>
<template #prefix>@</template>
<template #suffix>@{{ host }}</template>
</MkInput>
<MkInput v-model="password" type="password">
<MkInput v-model="password" type="password" data-cy-admin-password>
<template #label>{{ $ts.password }}</template>
<template #prefix><i class="fas fa-lock"></i></template>
</MkInput>
<footer>
<MkButton primary type="submit" :disabled="submitting">{{ submitting ? $ts.processing : $ts.done }}<MkEllipsis v-if="submitting"/></MkButton>
<MkButton primary type="submit" :disabled="submitting" data-cy-admin-ok>
{{ submitting ? $ts.processing : $ts.done }}<MkEllipsis v-if="submitting"/>
</MkButton>
</footer>
</div>
</form>

View File

@ -2,6 +2,23 @@ import { ColdDeviceStorage } from '@client/store';
const cache = new Map<string, HTMLAudioElement>();
export function getAudio(file: string, useCache = true): HTMLAudioElement {
let audio: HTMLAudioElement;
if (useCache && cache.has(file)) {
audio = cache.get(file);
} else {
audio = new Audio(`/static-assets/client/sounds/${file}.mp3`);
if (useCache) cache.set(file, audio);
}
return audio;
}
export function setVolume(audio: HTMLAudioElement, volume: number): HTMLAudioElement {
const masterVolume = ColdDeviceStorage.get('sound_masterVolume');
audio.volume = masterVolume - ((1 - volume) * masterVolume);
return audio;
}
export function play(type: string) {
const sound = ColdDeviceStorage.get('sound_' + type as any);
if (sound.type == null) return;
@ -12,13 +29,6 @@ export function playFile(file: string, volume: number) {
const masterVolume = ColdDeviceStorage.get('sound_masterVolume');
if (masterVolume === 0) return;
let audio: HTMLAudioElement;
if (cache.has(file)) {
audio = cache.get(file);
} else {
audio = new Audio(`/static-assets/client/sounds/${file}.mp3`);
cache.set(file, audio);
}
audio.volume = masterVolume - ((1 - volume) * masterVolume);
const audio = setVolume(getAudio(file), volume);
audio.play();
}

View File

@ -330,6 +330,7 @@ hr {
contain: layout; // ふき出しがボックスから飛び出て表示されるようなデザインをする場合もあるので paint contain することができない
}
// TODO: 廃止
._root {
box-sizing: border-box;
margin: var(--root-margin, 32px) auto;

View File

@ -2,7 +2,7 @@
<div class="fdidabkb" :class="{ center }" :style="`--height:${height};`" :key="key">
<transition :name="$store.state.animation ? 'header' : ''" mode="out-in" appear>
<div class="buttons left" v-if="backButton">
<button class="_button button back" @click.stop="$emit('back')" v-tooltip="$ts.goBack"><i class="fas fa-chevron-left"></i></button>
<button class="_button button back" @click.stop="$emit('back')" @touchstart="preventDrag" v-tooltip="$ts.goBack"><i class="fas fa-chevron-left"></i></button>
</div>
</transition>
<template v-if="info">
@ -20,10 +20,10 @@
</div>
<div class="buttons right">
<template v-if="info.actions && showActions">
<button v-for="action in info.actions" class="_button button" :class="{ highlighted: action.highlighted }" @click.stop="action.handler" v-tooltip="action.text"><i :class="action.icon"></i></button>
<button v-for="action in info.actions" class="_button button" :class="{ highlighted: action.highlighted }" @click.stop="action.handler" @touchstart="preventDrag" v-tooltip="action.text"><i :class="action.icon"></i></button>
</template>
<button v-if="shouldShowMenu" class="_button button" @click.stop="showMenu" v-tooltip="$ts.menu"><i class="fas fa-ellipsis-h"></i></button>
<button v-if="closeButton" class="_button button" @click.stop="$emit('close')" v-tooltip="$ts.close"><i class="fas fa-times"></i></button>
<button v-if="shouldShowMenu" class="_button button" @click.stop="showMenu" @touchstart="preventDrag" v-tooltip="$ts.menu"><i class="fas fa-ellipsis-h"></i></button>
<button v-if="closeButton" class="_button button" @click.stop="$emit('close')" @touchstart="preventDrag" v-tooltip="$ts.close"><i class="fas fa-times"></i></button>
</div>
</template>
</div>
@ -122,6 +122,10 @@ export default defineComponent({
menu = menu.concat(this.menu);
}
popupMenu(menu, ev.currentTarget || ev.target);
},
preventDrag(ev) {
ev.stopPropagation();
}
}
});

View File

@ -3,7 +3,7 @@
<button class="item _button account" @click="openAccountMenu" v-click-anime>
<MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/>
</button>
<div class="post" @click="post">
<div class="post" @click="post" data-cy-open-post-form>
<MkButton class="button" primary full>
<i class="fas fa-pencil-alt fa-fw"></i><span class="text" v-if="!iconOnly">{{ $ts.note }}</span>
</MkButton>

View File

@ -4,7 +4,7 @@
<div class="contents" ref="contents" @contextmenu.stop="onContextmenu">
<header class="header" ref="header" @click="onHeaderClick">
<XHeader :info="pageInfo"/>
<XHeader :info="pageInfo" :back-button="true" @back="back()"/>
</header>
<main ref="main">
<div class="content">
@ -175,6 +175,10 @@ export default defineComponent({
window.scroll({ top: 0, behavior: 'smooth' });
},
back() {
history.back();
},
onTransition() {
if (window._scroll) window._scroll();
},
@ -253,11 +257,16 @@ export default defineComponent({
//backdrop-filter: var(--blur, blur(4px));
}
> .sidebar {
border-right: solid 0.5px var(--divider);
}
> .contents {
width: 100%;
min-width: 0;
--stickyTop: #{$header-height};
padding-top: $header-height;
background: var(--panel);
> .header {
position: fixed;
@ -272,7 +281,7 @@ export default defineComponent({
-webkit-backdrop-filter: var(--blur, blur(32px));
backdrop-filter: var(--blur, blur(32px));
background-color: var(--header);
//border-bottom: solid 0.5px var(--divider);
border-bottom: solid 0.5px var(--divider);
user-select: none;
}

View File

@ -50,6 +50,7 @@ import { defineComponent, markRaw } from 'vue';
import define from './define';
import * as os from '@client/os';
import number from '@client/filters/number';
import * as sound from '@client/scripts/sound';
const widget = define({
name: 'jobQueue',
@ -58,6 +59,10 @@ const widget = define({
type: 'boolean',
default: false,
},
sound: {
type: 'boolean',
default: false,
},
})
});
@ -79,6 +84,7 @@ export default defineComponent({
delayed: 0,
},
prev: {},
sound: sound.setVolume(sound.getAudio('syuilo/queue-jammed'), 1)
};
},
created() {
@ -107,6 +113,10 @@ export default defineComponent({
this[domain].active = stats[domain].active;
this[domain].waiting = stats[domain].waiting;
this[domain].delayed = stats[domain].delayed;
if (this[domain].waiting > 0 && this.props.sound && this.sound.paused) {
this.sound.play();
}
}
},

View File

@ -3,14 +3,20 @@
*/
import * as fs from 'fs';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import * as yaml from 'js-yaml';
import { Source, Mixin } from './types';
const meta = require('../meta.json');
import * as meta from '../meta.json';
//const _filename = fileURLToPath(import.meta.url);
const _filename = __filename;
const _dirname = dirname(_filename);
/**
* Path of configuration directory
*/
const dir = `${__dirname}/../../.config`;
const dir = `${_dirname}/../../.config`;
/**
* Path of configuration file

View File

@ -1,7 +1,7 @@
// TODO: 消したい
const interval = 30 * 60 * 1000;
import { AttestationChallenges } from '../models';
import { AttestationChallenges } from '@/models/index';
import { LessThan } from 'typeorm';
/**

View File

@ -1,5 +1,5 @@
import * as elasticsearch from '@elastic/elasticsearch';
import config from '@/config';
import config from '@/config/index';
const index = {
settings: {

View File

@ -1,3 +1,3 @@
import Logger from '../services/logger';
import Logger from '@/services/logger';
export const dbLogger = new Logger('db');

View File

@ -3,74 +3,74 @@ const types = require('pg').types;
types.setTypeParser(20, Number);
import { createConnection, Logger, getConnection } from 'typeorm';
import config from '@/config';
import { entities as charts } from '../services/chart/entities';
import config from '@/config/index';
import { entities as charts } from '@/services/chart/entities';
import { dbLogger } from './logger';
import * as highlight from 'cli-highlight';
import { Log } from '../models/entities/log';
import { User } from '../models/entities/user';
import { DriveFile } from '../models/entities/drive-file';
import { DriveFolder } from '../models/entities/drive-folder';
import { AccessToken } from '../models/entities/access-token';
import { App } from '../models/entities/app';
import { PollVote } from '../models/entities/poll-vote';
import { Note } from '../models/entities/note';
import { NoteReaction } from '../models/entities/note-reaction';
import { NoteWatching } from '../models/entities/note-watching';
import { NoteUnread } from '../models/entities/note-unread';
import { Notification } from '../models/entities/notification';
import { Meta } from '../models/entities/meta';
import { Following } from '../models/entities/following';
import { Instance } from '../models/entities/instance';
import { Muting } from '../models/entities/muting';
import { SwSubscription } from '../models/entities/sw-subscription';
import { Blocking } from '../models/entities/blocking';
import { UserList } from '../models/entities/user-list';
import { UserListJoining } from '../models/entities/user-list-joining';
import { UserGroup } from '../models/entities/user-group';
import { UserGroupJoining } from '../models/entities/user-group-joining';
import { UserGroupInvitation } from '../models/entities/user-group-invitation';
import { Hashtag } from '../models/entities/hashtag';
import { NoteFavorite } from '../models/entities/note-favorite';
import { AbuseUserReport } from '../models/entities/abuse-user-report';
import { RegistrationTicket } from '../models/entities/registration-tickets';
import { MessagingMessage } from '../models/entities/messaging-message';
import { Signin } from '../models/entities/signin';
import { AuthSession } from '../models/entities/auth-session';
import { FollowRequest } from '../models/entities/follow-request';
import { Emoji } from '../models/entities/emoji';
import { ReversiGame } from '../models/entities/games/reversi/game';
import { ReversiMatching } from '../models/entities/games/reversi/matching';
import { UserNotePining } from '../models/entities/user-note-pining';
import { Poll } from '../models/entities/poll';
import { UserKeypair } from '../models/entities/user-keypair';
import { UserPublickey } from '../models/entities/user-publickey';
import { UserProfile } from '../models/entities/user-profile';
import { UserSecurityKey } from '../models/entities/user-security-key';
import { AttestationChallenge } from '../models/entities/attestation-challenge';
import { Page } from '../models/entities/page';
import { PageLike } from '../models/entities/page-like';
import { GalleryPost } from '../models/entities/gallery-post';
import { GalleryLike } from '../models/entities/gallery-like';
import { ModerationLog } from '../models/entities/moderation-log';
import { UsedUsername } from '../models/entities/used-username';
import { Announcement } from '../models/entities/announcement';
import { AnnouncementRead } from '../models/entities/announcement-read';
import { Clip } from '../models/entities/clip';
import { ClipNote } from '../models/entities/clip-note';
import { Antenna } from '../models/entities/antenna';
import { AntennaNote } from '../models/entities/antenna-note';
import { PromoNote } from '../models/entities/promo-note';
import { PromoRead } from '../models/entities/promo-read';
import { Log } from '@/models/entities/log';
import { User } from '@/models/entities/user';
import { DriveFile } from '@/models/entities/drive-file';
import { DriveFolder } from '@/models/entities/drive-folder';
import { AccessToken } from '@/models/entities/access-token';
import { App } from '@/models/entities/app';
import { PollVote } from '@/models/entities/poll-vote';
import { Note } from '@/models/entities/note';
import { NoteReaction } from '@/models/entities/note-reaction';
import { NoteWatching } from '@/models/entities/note-watching';
import { NoteUnread } from '@/models/entities/note-unread';
import { Notification } from '@/models/entities/notification';
import { Meta } from '@/models/entities/meta';
import { Following } from '@/models/entities/following';
import { Instance } from '@/models/entities/instance';
import { Muting } from '@/models/entities/muting';
import { SwSubscription } from '@/models/entities/sw-subscription';
import { Blocking } from '@/models/entities/blocking';
import { UserList } from '@/models/entities/user-list';
import { UserListJoining } from '@/models/entities/user-list-joining';
import { UserGroup } from '@/models/entities/user-group';
import { UserGroupJoining } from '@/models/entities/user-group-joining';
import { UserGroupInvitation } from '@/models/entities/user-group-invitation';
import { Hashtag } from '@/models/entities/hashtag';
import { NoteFavorite } from '@/models/entities/note-favorite';
import { AbuseUserReport } from '@/models/entities/abuse-user-report';
import { RegistrationTicket } from '@/models/entities/registration-tickets';
import { MessagingMessage } from '@/models/entities/messaging-message';
import { Signin } from '@/models/entities/signin';
import { AuthSession } from '@/models/entities/auth-session';
import { FollowRequest } from '@/models/entities/follow-request';
import { Emoji } from '@/models/entities/emoji';
import { ReversiGame } from '@/models/entities/games/reversi/game';
import { ReversiMatching } from '@/models/entities/games/reversi/matching';
import { UserNotePining } from '@/models/entities/user-note-pining';
import { Poll } from '@/models/entities/poll';
import { UserKeypair } from '@/models/entities/user-keypair';
import { UserPublickey } from '@/models/entities/user-publickey';
import { UserProfile } from '@/models/entities/user-profile';
import { UserSecurityKey } from '@/models/entities/user-security-key';
import { AttestationChallenge } from '@/models/entities/attestation-challenge';
import { Page } from '@/models/entities/page';
import { PageLike } from '@/models/entities/page-like';
import { GalleryPost } from '@/models/entities/gallery-post';
import { GalleryLike } from '@/models/entities/gallery-like';
import { ModerationLog } from '@/models/entities/moderation-log';
import { UsedUsername } from '@/models/entities/used-username';
import { Announcement } from '@/models/entities/announcement';
import { AnnouncementRead } from '@/models/entities/announcement-read';
import { Clip } from '@/models/entities/clip';
import { ClipNote } from '@/models/entities/clip-note';
import { Antenna } from '@/models/entities/antenna';
import { AntennaNote } from '@/models/entities/antenna-note';
import { PromoNote } from '@/models/entities/promo-note';
import { PromoRead } from '@/models/entities/promo-read';
import { program } from '../argv';
import { Relay } from '../models/entities/relay';
import { MutedNote } from '../models/entities/muted-note';
import { Channel } from '../models/entities/channel';
import { ChannelFollowing } from '../models/entities/channel-following';
import { ChannelNotePining } from '../models/entities/channel-note-pining';
import { RegistryItem } from '../models/entities/registry-item';
import { Ad } from '../models/entities/ad';
import { Relay } from '@/models/entities/relay';
import { MutedNote } from '@/models/entities/muted-note';
import { Channel } from '@/models/entities/channel';
import { ChannelFollowing } from '@/models/entities/channel-following';
import { ChannelNotePining } from '@/models/entities/channel-note-pining';
import { RegistryItem } from '@/models/entities/registry-item';
import { Ad } from '@/models/entities/ad';
import { PasswordResetRequest } from '@/models/entities/password-reset-request';
const sqlLogger = dbLogger.createSubLogger('sql', 'white', false);
@ -211,3 +211,13 @@ export function initDb(justBorrow = false, sync = false, forceRecreate = false)
entities: entities
});
}
export async function resetDb() {
const conn = await getConnection();
const tables = await conn.query(`SELECT relname AS "table"
FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
AND C.relkind = 'r'
AND nspname !~ '^pg_toast';`);
await Promise.all(tables.map(t => t.table).map(x => conn.query(`DELETE FROM "${x}" CASCADE`)));
}

View File

@ -1,5 +1,5 @@
import * as redis from 'redis';
import config from '@/config';
import config from '@/config/index';
export function createConnection() {
return redis.createClient(

View File

@ -1,11 +1,14 @@
# よくある質問
ここでは利用上のよくある質問について掲載しています。 Misskeyのプロジェクト自体についてのよくある質問は[こちら](./misskey)に掲載されています。
### iOS/Androidのアプリはありますか
## iOS/Androidのアプリはありますか
公式にはそういったOSのネイティブアプリを開発していませんが、サードパーティ製のアプリがいくつかあります。 詳しくは[こちら](./apps)をご覧ください。
ただ、サードパーティ製アプリはどうしても機能への対応が遅れてしまうため、とくに拘りがなければ公式のWebクライアントの利用をおすすめします。 なお、MisskeyのWebクライアントはPWAに対応しているので、ネイティブアプリのように動作させることも可能です。 詳しくは[こちら](todo)をご覧ください。
## Mastodonクライアントでログインできないのですが
MisskeyはMastodonのAPIと互換性がないため、一部を除きMastodonクライアントでMisskeyを利用することはできません。
## 他のサーバーのユーザーをフォローするときは?
メニューから検索を選び、ユーザー名をホスト込みで入力します。例: `@syuilo@misskey.io`

View File

@ -1,7 +1,7 @@
# 用語集
Misskeyに関する用語集です。
## AcitivityPub
## ActivityPub
(読み: あくてぃびてぃぱぶ) 分散型を実現するために用いられるプロトコル(仕様)。このプロトコルに則ってサーバー同士通信を行うことで、連合が行われ、Fediverseを形成しています。
## AiScript

View File

@ -3,7 +3,7 @@
Misskeyはオープンソースの分散型マイクロブログプラットフォームプロジェクトです。 開発は日本でsyuiloによって2014年から開始されました。 ドライブ、リアクションなどの豊富な機能や、高いカスタマイズ性を備えたUIを持つことが特徴です。
## 歴史
開発当初は掲示板がメインのサービスでしたが、ユーザーが短文を投稿し、それを時系列で流れるタイムライン機能を追加したところ人気が高まり、徐々にそれがメインとして開発が進むようになりました。 当初は分散型ではありませんでしたが、2018年にAcitivityPubを実装し分散型になったことで、より多くの方に認知され利用されるサービスになり、現在に至ります。
開発当初は掲示板がメインのサービスでしたが、ユーザーが短文を投稿し、それを時系列で流れるタイムライン機能を追加したところ人気が高まり、徐々にそれがメインとして開発が進むようになりました。 当初は分散型ではありませんでしたが、2018年にActivityPubを実装し分散型になったことで、より多くの方に認知され利用されるサービスになり、現在に至ります。
<div class="info"> Misskeyという名前は、syuiloが当時聴いていたMay'nというアーティストの楽曲、Brain Diverの歌詞に由来します。</div>
誰でも開発に参加することができ、現在でも活発に開発が続いています。
@ -72,7 +72,7 @@ Misskeyは開発が進むにつれ使用する技術も大きく変わってき
また、MFMやAiScriptなどの、Misskeyから派生して独自の技術も開発しています。
### Mastodonのフォークですか
いいえ。MisskeyはMastodonやその他のプロジェクトとは全く別のプロジェクトです。 開発に関しても、Misskeyの方が昔から開発されています。ただし、分散型になったのはMastodonの登場より後です。 同じAcitivityPubという分散のためのプロトコルを実装しているという点以外、両者に特に関りがあるわけでもありません。
いいえ。MisskeyはMastodonやその他のプロジェクトとは全く別のプロジェクトです。 開発に関しても、Misskeyの方が昔から開発されています。ただし、分散型になったのはMastodonの登場より後です。 同じActivityPubという分散のためのプロトコルを実装しているという点以外、両者に特に関りがあるわけでもありません。
### iOS/Androidのアプリはありますか
公式にはそういったOSのネイティブアプリを開発していませんが、サードパーティ製のアプリがいくつかあります。 詳しくは[こちら](./apps)をご覧ください。

View File

@ -1,11 +1,14 @@
# よくある質問
ここでは利用上のよくある質問について掲載しています。 Misskeyのプロジェクト自体についてのよくある質問は[こちら](./misskey)に掲載されています。
### iOS/Androidのアプリはありますか
## iOS/Androidのアプリはありますか
公式にはそういったOSのネイティブアプリを開発していませんが、サードパーティ製のアプリがいくつかあります。 詳しくは[こちら](./apps)をご覧ください。
ただ、サードパーティ製アプリはどうしても機能への対応が遅れてしまうため、とくに拘りがなければ公式のWebクライアントの利用をおすすめします。 なお、MisskeyのWebクライアントはPWAに対応しているので、ネイティブアプリのように動作させることも可能です。 詳しくは[こちら](todo)をご覧ください。
## Mastodonクライアントでログインできないのですが
MisskeyはMastodonのAPIと互換性がないため、一部を除きMastodonクライアントでMisskeyを利用することはできません。
## 他のサーバーのユーザーをフォローするときは?
メニューから検索を選び、ユーザー名をホスト込みで入力します。例: `@syuilo@misskey.io`

View File

@ -1,7 +1,7 @@
# 用語集
Misskeyに関する用語集です。
## AcitivityPub
## ActivityPub
(読み: あくてぃびてぃぱぶ) 分散型を実現するために用いられるプロトコル(仕様)。このプロトコルに則ってサーバー同士通信を行うことで、連合が行われ、Fediverseを形成しています。
## AiScript

View File

@ -3,7 +3,7 @@
Misskeyはオープンソースの分散型マイクロブログプラットフォームプロジェクトです。 開発は日本でsyuiloによって2014年から開始されました。 ドライブ、リアクションなどの豊富な機能や、高いカスタマイズ性を備えたUIを持つことが特徴です。
## 歴史
開発当初は掲示板がメインのサービスでしたが、ユーザーが短文を投稿し、それを時系列で流れるタイムライン機能を追加したところ人気が高まり、徐々にそれがメインとして開発が進むようになりました。 当初は分散型ではありませんでしたが、2018年にAcitivityPubを実装し分散型になったことで、より多くの方に認知され利用されるサービスになり、現在に至ります。
開発当初は掲示板がメインのサービスでしたが、ユーザーが短文を投稿し、それを時系列で流れるタイムライン機能を追加したところ人気が高まり、徐々にそれがメインとして開発が進むようになりました。 当初は分散型ではありませんでしたが、2018年にActivityPubを実装し分散型になったことで、より多くの方に認知され利用されるサービスになり、現在に至ります。
<div class="info"> Misskeyという名前は、syuiloが当時聴いていたMay'nというアーティストの楽曲、Brain Diverの歌詞に由来します。</div>
誰でも開発に参加することができ、現在でも活発に開発が続いています。
@ -72,7 +72,7 @@ Misskeyは開発が進むにつれ使用する技術も大きく変わってき
また、MFMやAiScriptなどの、Misskeyから派生して独自の技術も開発しています。
### Mastodonのフォークですか
いいえ。MisskeyはMastodonやその他のプロジェクトとは全く別のプロジェクトです。 開発に関しても、Misskeyの方が昔から開発されています。ただし、分散型になったのはMastodonの登場より後です。 同じAcitivityPubという分散のためのプロトコルを実装しているという点以外、両者に特に関りがあるわけでもありません。
いいえ。MisskeyはMastodonやその他のプロジェクトとは全く別のプロジェクトです。 開発に関しても、Misskeyの方が昔から開発されています。ただし、分散型になったのはMastodonの登場より後です。 同じActivityPubという分散のためのプロトコルを実装しているという点以外、両者に特に関りがあるわけでもありません。
### iOS/Androidのアプリはありますか
公式にはそういったOSのネイティブアプリを開発していませんが、サードパーティ製のアプリがいくつかあります。 詳しくは[こちら](./apps)をご覧ください。

View File

@ -1,11 +1,14 @@
# よくある質問
ここでは利用上のよくある質問について掲載しています。 Misskeyのプロジェクト自体についてのよくある質問は[こちら](./misskey)に掲載されています。
### iOS/Androidのアプリはありますか
## iOS/Androidのアプリはありますか
公式にはそういったOSのネイティブアプリを開発していませんが、サードパーティ製のアプリがいくつかあります。 詳しくは[こちら](./apps)をご覧ください。
ただ、サードパーティ製アプリはどうしても機能への対応が遅れてしまうため、とくに拘りがなければ公式のWebクライアントの利用をおすすめします。 なお、MisskeyのWebクライアントはPWAに対応しているので、ネイティブアプリのように動作させることも可能です。 詳しくは[こちら](todo)をご覧ください。
## Mastodonクライアントでログインできないのですが
MisskeyはMastodonのAPIと互換性がないため、一部を除きMastodonクライアントでMisskeyを利用することはできません。
## 他のサーバーのユーザーをフォローするときは?
メニューから検索を選び、ユーザー名をホスト込みで入力します。例: `@syuilo@misskey.io`

View File

@ -1,7 +1,7 @@
# 用語集
Misskeyに関する用語集です。
## AcitivityPub
## ActivityPub
(読み: あくてぃびてぃぱぶ) 分散型を実現するために用いられるプロトコル(仕様)。このプロトコルに則ってサーバー同士通信を行うことで、連合が行われ、Fediverseを形成しています。
## AiScript

View File

@ -3,7 +3,7 @@
Misskeyはオープンソースの分散型マイクロブログプラットフォームプロジェクトです。 開発は日本でsyuiloによって2014年から開始されました。 ドライブ、リアクションなどの豊富な機能や、高いカスタマイズ性を備えたUIを持つことが特徴です。
## 歴史
開発当初は掲示板がメインのサービスでしたが、ユーザーが短文を投稿し、それを時系列で流れるタイムライン機能を追加したところ人気が高まり、徐々にそれがメインとして開発が進むようになりました。 当初は分散型ではありませんでしたが、2018年にAcitivityPubを実装し分散型になったことで、より多くの方に認知され利用されるサービスになり、現在に至ります。
開発当初は掲示板がメインのサービスでしたが、ユーザーが短文を投稿し、それを時系列で流れるタイムライン機能を追加したところ人気が高まり、徐々にそれがメインとして開発が進むようになりました。 当初は分散型ではありませんでしたが、2018年にActivityPubを実装し分散型になったことで、より多くの方に認知され利用されるサービスになり、現在に至ります。
<div class="info"> Misskeyという名前は、syuiloが当時聴いていたMay'nというアーティストの楽曲、Brain Diverの歌詞に由来します。</div>
誰でも開発に参加することができ、現在でも活発に開発が続いています。
@ -72,7 +72,7 @@ Misskeyは開発が進むにつれ使用する技術も大きく変わってき
また、MFMやAiScriptなどの、Misskeyから派生して独自の技術も開発しています。
### Mastodonのフォークですか
いいえ。MisskeyはMastodonやその他のプロジェクトとは全く別のプロジェクトです。 開発に関しても、Misskeyの方が昔から開発されています。ただし、分散型になったのはMastodonの登場より後です。 同じAcitivityPubという分散のためのプロトコルを実装しているという点以外、両者に特に関りがあるわけでもありません。
いいえ。MisskeyはMastodonやその他のプロジェクトとは全く別のプロジェクトです。 開発に関しても、Misskeyの方が昔から開発されています。ただし、分散型になったのはMastodonの登場より後です。 同じActivityPubという分散のためのプロトコルを実装しているという点以外、両者に特に関りがあるわけでもありません。
### iOS/Androidのアプリはありますか
公式にはそういったOSのネイティブアプリを開発していませんが、サードパーティ製のアプリがいくつかあります。 詳しくは[こちら](./apps)をご覧ください。

View File

@ -1,8 +1,8 @@
# LTL/STL/GTLの無効化
Misskeyでは、LTL/STL/GTLをそれぞれ無効化することができます。有効/無効を切り替えるには、インスタンスコントロールパネルで設定します。
# Lokale/soziale/globale Chronik deaktivieren
Misskey erlaubt es, die lokale, soziale und globale Chronik jeweils zu deaktivieren. Die Chroniken können in den Instanzeinstellungen aktiviert bzw. deaktiviert werden.
LTLやSTLは、そのインスタンス全員の投稿が見れるため、新規のユーザーにとってはユーザーを探す必要がなくなり、興味のあるユーザーを見つけやすいという利点があります。 しかし同時に、フォロー機能が活用されなくなったり、不適切な投稿が目につきやすくなったり、チャットのようになることで内輪感が生じて逆に新規ユーザーが参加しにくくなるといったデメリットも持ち合わせています。 サーバーによってメリット/デメリットどちらが優勢かは異なるので、オプションとして無効にできるようになっています。 もしデメリットの方が上回っていると感じたら、それらのタイムラインを無効化することも検討してください。
Dass alle Notizen auf deiner Instanz auf der lokalen und sozialen Chronik erscheinen, erleichtert es neuen Nutzern, andere zu finden, ohne dafür die Suche benutzen zu müssen. Es bedeutet jedoch auch, dass es nicht unbedingt nötig ist, Nutzern zu folgen, um ihre Posts zu sehen, und dass häufiger unangebrachte Inhalte zu sehen sein könnten. Die Nutzung gleicht zudem eher der eines Chatrooms, was es neuen Nutzern wiederum erschweren könnte, in Gespräche unter Langzeitnutzern einzusteigen. Diese Vor- und Nachteile wiegen je nach Instanz unterschiedlich schwer, weshalb die Wahl letztendlich den Betreibern überlassen ist. Falls die Nachteile also in deinem Fall überwiegen, kannst du die jeweiligen Chroniken auch deaktivieren.
<div class="warn">⚠️ 無効化を行うと、ユーザーが困惑し、短期的に見て利用者が減る可能性があります。そのため、無効化の際は影響を慎重に検討し、事前に説明してフォローを整える期間を一定程度設けることを推奨します。</div>
<div class="warn">⚠️ Das Deaktiveren von Chroniken kann Nutzer verwirren und kurzzeitig abschrecken. Daher solltest du diese Entscheidung gut begründen können und die Nutzer deiner Instanz im Vorfeld darüber aufklären, damit diese sich entsprechend vorbereiten können, beispielsweise indem sie Nutzern folgen, mit denen sie sich häufiger unterhalten.</div>
なお、管理者/モデレーターは、これらのタイムラインの無効化状態は適用されず、引き続き利用することが可能です。
Beachte, dass Aministratoren und Moderatoren diese Chroniken weiterhin sehen können, auch nachdem sie deaktiviert wurden.

View File

@ -1,5 +1,5 @@
# よくある質問
ここでは、サーバー管理者向けのよくある質問を掲載しています。
# Häufig gestellte Fragen
Dieses Dokument richtet sich an Administratoren und beantwortet besonders häufig gestellte Fragen.
## デフォルトテーマを設定したい
現在、デフォルトテーマ設定機能は実装されていません。
## Wie kann ich ein standardmäßiges Farbschema für meine Instanz festlegen?
Derzeit ist es noch nicht möglich, ein standardmäßiges Farbschema für eine Instanz festzulegen.

View File

@ -1,11 +1,14 @@
# よくある質問
# Häufig gestellte Fragen
ここでは利用上のよくある質問について掲載しています。 Misskeyのプロジェクト自体についてのよくある質問は[こちら](./misskey)に掲載されています。
### iOS/Androidのアプリはありますか
## iOS/Androidのアプリはありますか
公式にはそういったOSのネイティブアプリを開発していませんが、サードパーティ製のアプリがいくつかあります。 詳しくは[こちら](./apps)をご覧ください。
ただ、サードパーティ製アプリはどうしても機能への対応が遅れてしまうため、とくに拘りがなければ公式のWebクライアントの利用をおすすめします。 なお、MisskeyのWebクライアントはPWAに対応しているので、ネイティブアプリのように動作させることも可能です。 詳しくは[こちら](todo)をご覧ください。
## Mastodonクライアントでログインできないのですが
MisskeyはMastodonのAPIと互換性がないため、一部を除きMastodonクライアントでMisskeyを利用することはできません。
## 他のサーバーのユーザーをフォローするときは?
メニューから検索を選び、ユーザー名をホスト込みで入力します。例: `@syuilo@misskey.io`

View File

@ -1,7 +1,7 @@
# 用語集
Misskeyに関する用語集です。
## AcitivityPub
## ActivityPub
(読み: あくてぃびてぃぱぶ) 分散型を実現するために用いられるプロトコル(仕様)。このプロトコルに則ってサーバー同士通信を行うことで、連合が行われ、Fediverseを形成しています。
## AiScript

View File

@ -3,7 +3,7 @@
Misskeyはオープンソースの分散型マイクロブログプラットフォームプロジェクトです。 開発は日本でsyuiloによって2014年から開始されました。 ドライブ、リアクションなどの豊富な機能や、高いカスタマイズ性を備えたUIを持つことが特徴です。
## 歴史
開発当初は掲示板がメインのサービスでしたが、ユーザーが短文を投稿し、それを時系列で流れるタイムライン機能を追加したところ人気が高まり、徐々にそれがメインとして開発が進むようになりました。 当初は分散型ではありませんでしたが、2018年にAcitivityPubを実装し分散型になったことで、より多くの方に認知され利用されるサービスになり、現在に至ります。
開発当初は掲示板がメインのサービスでしたが、ユーザーが短文を投稿し、それを時系列で流れるタイムライン機能を追加したところ人気が高まり、徐々にそれがメインとして開発が進むようになりました。 当初は分散型ではありませんでしたが、2018年にActivityPubを実装し分散型になったことで、より多くの方に認知され利用されるサービスになり、現在に至ります。
<div class="info"> Misskeyという名前は、syuiloが当時聴いていたMay'nというアーティストの楽曲、Brain Diverの歌詞に由来します。</div>
誰でも開発に参加することができ、現在でも活発に開発が続いています。
@ -43,7 +43,7 @@ Misskeyはビジネスではなく、利用は無料であるため、収益は
## クレジット
Misskeyの開発者や、Misskeyに寄付をしてくださった方の一覧は[こちら](/about-misskey)で見ることができます。
## よくある質問
## Häufig gestellte Fragen
### プロジェクトは何を目指していますか?
強いて言うと、漠然的になりますが広く使われる汎用的なプラットフォームになることを目指しています。 Misskeyは他のプロジェクトとは違い、何らかの思想(例えば、反中央集権)やビジョンに基づいて開発が行われているわけではなく、その点ではフラットです。 それが逆に、特定の方向性に縛られないフレキシブルさを生み出すことに繋がっていると感じています。
<!-- TODO: ここにロードマップへのリンク -->
@ -72,7 +72,7 @@ Misskeyは開発が進むにつれ使用する技術も大きく変わってき
また、MFMやAiScriptなどの、Misskeyから派生して独自の技術も開発しています。
### Mastodonのフォークですか
いいえ。MisskeyはMastodonやその他のプロジェクトとは全く別のプロジェクトです。 開発に関しても、Misskeyの方が昔から開発されています。ただし、分散型になったのはMastodonの登場より後です。 同じAcitivityPubという分散のためのプロトコルを実装しているという点以外、両者に特に関りがあるわけでもありません。
いいえ。MisskeyはMastodonやその他のプロジェクトとは全く別のプロジェクトです。 開発に関しても、Misskeyの方が昔から開発されています。ただし、分散型になったのはMastodonの登場より後です。 同じActivityPubという分散のためのプロトコルを実装しているという点以外、両者に特に関りがあるわけでもありません。
### iOS/Androidのアプリはありますか
公式にはそういったOSのネイティブアプリを開発していませんが、サードパーティ製のアプリがいくつかあります。 詳しくは[こちら](./apps)をご覧ください。

View File

@ -51,4 +51,4 @@ If you enable this option, your note won't be federated to remote instances.
By pinning a note to your profile it will be constantly displayed on your profile page. To pin a note, open the note menu and press "Pin to profile". It's also possible to pin multiple notes to your profile.
## Watch
ノートをウォッチすると、自分以外のノートへのリアクションや返信などの通知を受け取ることができます。 ノートのメニューを開き、「ウォッチ」を選択してウォッチできます。
You can get notifications for replies, reactions etc. for a note that is not yours by watching it. To watch a note, select "Watch" from the respective note's menu.

View File

@ -1,22 +1,25 @@
# Frequently Asked Questions
This document will list answers to frequently asked questions regarding the usage of Misskey. Answers to frequently asked questions related to Misskey as a project can be found [here](./misskey).
### "Are there any apps for iOS / Android available?"
## "Are there any apps for iOS / Android available?"
While no official Misskey app for either OS exists, there are several third-party applications. For details, please check [here](./apps).
However, functionality of third-party applications will inevitably lag behind the official Web client, so unless you really want to use a native application, we recommend the official Web client instead. As the Misskey Web client supports PWA, it is possible to make it act as if it was a native application instead. For details regarding this, please check [here](todo).
However, functionality of third-party applications will inevitably lag behind the official Web client, so unless you really want to use a native application, we recommend the official Web client instead. As the Misskey Web client supports PWA, it is also possible to make it act as if it was a native application instead. For details regarding this, please check [here](todo).
## "Can't I log in through a Mastodon client?"
As Misskey is not compatible with the Mastodon API, barring some exceptions, using Mastodon clients to log into Misskey is not possible.
## "What do I do when I want to follow users from other servers?"
Select the search bar from the menu and enter their username including their host.E.g. `@syuilo@misskey.io`
Select the search bar from the menu and enter their username including their host server. E.g.: `@syuilo@misskey.io`
## "How do I take back a Renote?"
Press the three dots ("...") to the right of the renote timestamp and select "Take back Renote". To read more about Renotes, please check [here](../features/note).
Press the three dots ("...") displayed next to the renote timestamp and select "Take back Renote". To read more about Renotes, please check [here](../features/note).
## "I don't want the preview of an URL to be displayed."
You can disable an URL from being previewed using MFM.For details, please check the [MFM Cheatsheet](/mfm-cheat-sheet).
You can prevent an URL from being previewed using MFM. Please check the [MFM Cheatsheet](/mfm-cheat-sheet) for more details.
## "I want to add custom emoji."
Only administrators can add, edit or delete custom emoji.If you'd like to do either of these things, please ask your instance administrator.
Only administrators can add, edit or delete custom emoji. If you'd like to do either of these things, please ask your instance administrator.
## "I want to develop a Bot."
Anyone can develop a Misskey bot using the Misskey API.Please see [here](../advanced/develop-bot).
It is possible to develop a Bot using the Misskey API. Please, [see here](../advanced/develop-bot).

View File

@ -1,8 +1,8 @@
# A collection of links
## Websites
- [Official Discord](https://discord.gg/Wp8gVStHW3) - The official Discord server for Misskey
- [Misskey Forum](https://forum.misskey.io/) - A forum used for questions surrounding Misskey
- [Misskey Forum](https://forum.misskey.io/) - Misskeyに関する話題を扱うフォーラム
## Accounts
- [@repo@misskey.io](https://misskey.io/@repo) - A bot that publishes posts about updates to the Misskey repository

View File

@ -1,4 +1,4 @@
# LTL/STL/GTLの無効化
# Malebligo de loka/sociala/malloka templinio
Misskeyでは、LTL/STL/GTLをそれぞれ無効化することができます。有効/無効を切り替えるには、インスタンスコントロールパネルで設定します。
LTLやSTLは、そのインスタンス全員の投稿が見れるため、新規のユーザーにとってはユーザーを探す必要がなくなり、興味のあるユーザーを見つけやすいという利点があります。 しかし同時に、フォロー機能が活用されなくなったり、不適切な投稿が目につきやすくなったり、チャットのようになることで内輪感が生じて逆に新規ユーザーが参加しにくくなるといったデメリットも持ち合わせています。 サーバーによってメリット/デメリットどちらが優勢かは異なるので、オプションとして無効にできるようになっています。 もしデメリットの方が上回っていると感じたら、それらのタイムラインを無効化することも検討してください。

View File

@ -32,7 +32,7 @@ UUIDを生成する。以後これをセッションIDと呼びます。
表示する際、URLにクエリパラメータとしていくつかのオプションを設定できます:
* `name` ... アプリケーション名
* > 例: `MissDeck`
* `icon` ... アプリケーションのアイコン画像URL
* `icon` ... URL de ikono de la programo
* > 例: `https://missdeck.example.com/icon.png`
* `callback` ... 認証が終わった後にリダイレクトするURL
* > 例: `https://missdeck.example.com/callback`
@ -51,7 +51,7 @@ UUIDを生成する。以後これをセッションIDと呼びます。
[「APIの使い方」へ進む](#APIの使い方)
## APIの使い方
## Uzado de API
**APIはすべてPOSTで、リクエスト/レスポンスともにJSON形式です。RESTではありません。** アクセストークンは、`i`というパラメータ名でリクエストに含めます。
* [APIリファレンス](/api-doc)

View File

@ -1,4 +1,4 @@
# アンテナ
# Antenoj
アンテナは、自由に条件を設定して、合致するノートを自動で収集することができる機能です。
条件を設定したアンテナが作成された状態で、条件に合致するノートが投稿されると、リアルタイムでそのアンテナのタイムラインにノートが追加されます。

View File

@ -1,4 +1,4 @@
# デッキ
# Kartaro
デッキは利用可能なUIのひとつです。「カラム」と呼ばれるビューを複数並べて表示させることで、カスタマイズ性が高く、情報量の多いUIが構築できることが特徴です。

View File

@ -1,4 +1,4 @@
# Diskingo
# Disko
ドライブは、Misskey上でファイルを管理できる機能です。
[ドライブのページ](/my/drive)から任意のファイルをアップロードできるほか、アバターに設定した画像や、ノートに添付したファイルなどもすべてドライブにアップロードされます。

View File

@ -1,6 +1,6 @@
# キーボードショートカット
## Konfederacia
## Malloka
これらのショートカットは基本的にどこでも使えます。
<table>
<thead>

View File

@ -51,4 +51,4 @@ Contents Warningの略で、ートの内容を、閲覧者の操作なしに
ノートをピン留めすると、ユーザーページに常にそのノートを表示しておくことができます。 ノートのメニューを開き、「ピン留め」を選択してピン留めできます。 複数のノートをピン留めできます。
## Observi
ノートをウォッチすると、自分以外のノートへのリアクションや返信などの通知を受け取ることができます。 ノートのメニューを開き、「ウォッチ」を選択してウォッチできます。
Vi povas ricevi sciigojn pri reagoj, respondoj, ktp al noto, kiuj ne apartenas al vi. Por observu, malfermu respektivan menuon de noto, kaj elektu la "Observi" el ĝi.

View File

@ -10,13 +10,13 @@
## Sociala
自分のフォローしているユーザーの投稿と、全てのローカルユーザーの「ホーム」指定されていない投稿が流れます。STLと略されます。
## Konfederacia
## Malloka
全てのローカルユーザーの「ホーム」指定されていない投稿と、サーバーに届いた全てのリモートユーザーの「ホーム」指定されていない投稿が流れます。GTLと略されます。
## 比較
| ソース | | | Templinio | | |
| ------------ | --------- | ----- | --------- | ------- | ------------ |
| Uzanto | 公開範囲 | Hejmo | Loka | Sociala | Konfederacia |
| ------------ | --------- | ----- | --------- | ------- | ------- |
| Uzanto | 公開範囲 | Hejmo | Loka | Sociala | Malloka |
| ローカル (フォロー) | Publikigi | ✔ | ✔ | ✔ | ✔ |
| | Hejmo | ✔ | | ✔ | |
| | Sekvantoj | ✔ | ✔ | ✔ | ✔ |

View File

@ -1,5 +1,5 @@
# サードパーティアプリのリスト
## クライアント
## Klientoj
todo
## 連携サービス

View File

@ -1,11 +1,14 @@
# よくある質問
ここでは利用上のよくある質問について掲載しています。 Misskeyのプロジェクト自体についてのよくある質問は[こちら](./misskey)に掲載されています。
### iOS/Androidのアプリはありますか
## iOS/Androidのアプリはありますか
公式にはそういったOSのネイティブアプリを開発していませんが、サードパーティ製のアプリがいくつかあります。 詳しくは[こちら](./apps)をご覧ください。
ただ、サードパーティ製アプリはどうしても機能への対応が遅れてしまうため、とくに拘りがなければ公式のWebクライアントの利用をおすすめします。 なお、MisskeyのWebクライアントはPWAに対応しているので、ネイティブアプリのように動作させることも可能です。 詳しくは[こちら](todo)をご覧ください。
## Mastodonクライアントでログインできないのですが
MisskeyはMastodonのAPIと互換性がないため、一部を除きMastodonクライアントでMisskeyを利用することはできません。
## 他のサーバーのユーザーをフォローするときは?
メニューから検索を選び、ユーザー名をホスト込みで入力します。例: `@syuilo@misskey.io`

Some files were not shown because too many files have changed in this diff Show More