diff --git a/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts b/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts
index f98c6c929f..a9bcf69351 100644
--- a/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts
+++ b/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts
@@ -33,7 +33,7 @@ export const paramDef = {
} as const;
export default define(meta, paramDef, async (ps, user) => {
- if (ps.key !== "reactions") return;
+ if (ps.key !== "reactions" && ps.key !== "defaultNoteVisibility") return;
const query = RegistryItems.createQueryBuilder("item")
.where("item.domain IS NULL")
.andWhere("item.userId = :userId", { userId: user.id })
diff --git a/packages/backend/src/server/api/index.ts b/packages/backend/src/server/api/index.ts
index 29cfbf93c0..9e8c458868 100644
--- a/packages/backend/src/server/api/index.ts
+++ b/packages/backend/src/server/api/index.ts
@@ -112,7 +112,7 @@ mastoFileRouter.post("/v2/media", upload.single("file"), async (ctx) => {
ctx.status = 401;
return;
}
- const data = await client.uploadMedia(multipartData);
+ const data = await client.uploadMedia(multipartData, ctx.request.body);
ctx.body = convertAttachment(data.data as Entity.Attachment);
} catch (e: any) {
console.error(e);
diff --git a/packages/backend/src/server/api/mastodon/endpoints/account.ts b/packages/backend/src/server/api/mastodon/endpoints/account.ts
index 3fb1c9cbe4..5d0abdedd6 100644
--- a/packages/backend/src/server/api/mastodon/endpoints/account.ts
+++ b/packages/backend/src/server/api/mastodon/endpoints/account.ts
@@ -48,7 +48,7 @@ export function apiAccountMastodon(router: Router): void {
acct.source = {
note: acct.note,
fields: acct.fields,
- privacy: "public",
+ privacy: await client.getDefaultPostPrivacy(),
sensitive: false,
language: "",
};
diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts
index 3c58cf3a42..76057ef0a2 100644
--- a/packages/backend/src/server/api/mastodon/endpoints/status.ts
+++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts
@@ -123,27 +123,7 @@ export function apiStatusMastodon(router: Router): void {
id,
convertTimelinesArgsId(limitToInt(ctx.query as any)),
);
- const status = await client.getStatus(id);
- let reqInstance = axios.create({
- headers: {
- Authorization: ctx.headers.authorization,
- },
- });
- const reactionsAxios = await reqInstance.get(
- `${BASE_URL}/api/notes/reactions?noteId=${id}`,
- );
- const reactions: IReaction[] = reactionsAxios.data;
- const text = reactions
- .map((r) => `${r.type.replace("@.", "")} ${r.user.username}`)
- .join("
");
- data.data.descendants.unshift(
- statusModel(
- status.data.id,
- status.data.account.id,
- status.data.emojis,
- text,
- ),
- );
+
data.data.ancestors = data.data.ancestors.map((status) =>
convertStatus(status),
);
@@ -456,65 +436,3 @@ async function getFirstReaction(
return react;
}
}
-
-export function statusModel(
- id: string | null,
- acctId: string | null,
- emojis: MastodonEntity.Emoji[],
- content: string,
-) {
- const now = new Date().toISOString();
- return {
- id: "9atm5frjhb",
- uri: "/static-assets/transparent.png", // ""
- url: "/static-assets/transparent.png", // "",
- account: {
- id: "9arzuvv0sw",
- username: "Reactions",
- acct: "Reactions",
- display_name: "Reactions to this post",
- locked: false,
- created_at: now,
- followers_count: 0,
- following_count: 0,
- statuses_count: 0,
- note: "",
- url: "/static-assets/transparent.png",
- avatar: "/static-assets/badges/info.png",
- avatar_static: "/static-assets/badges/info.png",
- header: "/static-assets/transparent.png", // ""
- header_static: "/static-assets/transparent.png", // ""
- emojis: [],
- fields: [],
- moved: null,
- bot: false,
- },
- in_reply_to_id: id,
- in_reply_to_account_id: acctId,
- reblog: null,
- content: `
${content}
`,
- plain_content: null,
- created_at: now,
- emojis: emojis,
- replies_count: 0,
- reblogs_count: 0,
- favourites_count: 0,
- favourited: false,
- reblogged: false,
- muted: false,
- sensitive: false,
- spoiler_text: "",
- visibility: "public" as const,
- media_attachments: [],
- mentions: [],
- tags: [],
- card: null,
- poll: null,
- application: null,
- language: null,
- pinned: false,
- emoji_reactions: [],
- bookmarked: false,
- quote: null,
- };
-}
diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts
index f2befd31e3..e05a12eaad 100644
--- a/packages/megalodon/src/misskey.ts
+++ b/packages/megalodon/src/misskey.ts
@@ -460,7 +460,7 @@ export default class Misskey implements MegalodonInterface {
if (options) {
if (options.limit) {
params = Object.assign(params, {
- limit: options.limit
+ limit: options.limit <= 100 ? options.limit : 100
})
}
else {
@@ -474,11 +474,11 @@ export default class Misskey implements MegalodonInterface {
limit: 40
})
}
- return this.client.post>('/api/users/followers', params).then(res => {
- return Object.assign(res, {
- data: res.data.map(f => this.converter.follower(f))
- })
- })
+ return this.client.post>('/api/users/followers', params).then(async res => {
+ return Object.assign(res, {
+ data: (await Promise.all(res.data.map(async f => (this.getAccount(f.followerId)).then(p => p.data))))
+ })
+ })
}
/**
@@ -498,15 +498,15 @@ export default class Misskey implements MegalodonInterface {
if (options) {
if (options.limit) {
params = Object.assign(params, {
- limit: options.limit
+ limit: options.limit <= 100 ? options.limit : 100
})
}
}
- return this.client.post>('/api/users/following', params).then(res => {
- return Object.assign(res, {
- data: res.data.map(f => this.converter.following(f))
- })
- })
+ return this.client.post>('/api/users/following', params).then(async res => {
+ return Object.assign(res, {
+ data: (await Promise.all(res.data.map(async f => (this.getAccount(f.followeeId)).then(p => p.data))))
+ })
+ })
}
public async getAccountLists(_id: string): Promise>> {
@@ -1079,23 +1079,11 @@ export default class Misskey implements MegalodonInterface {
// accounts/preferences
// ======================================
public async getPreferences(): Promise> {
- return this.client.post('/api/i').then(res => {
- /*
- return this.client.post('/api/i/registry/get-all', {
- scope: ['client', 'base'],
- }).then(ga => {
- return Object.assign(res, {
- data: this.converter.userPreferences(res.data, ga.data)
- })
- })
- */
-
- // TODO:
- // FIXME: get this from api
- return Object.assign(res, {
- data: this.converter.userPreferences(res.data, {defaultNoteVisibility: "followers", tutorial: -1})
- })
- })
+ return this.client.post('/api/i').then(async res => {
+ return Object.assign(res, {
+ data: this.converter.userPreferences(res.data, await this.getDefaultPostPrivacy())
+ })
+ })
}
// ======================================
@@ -1529,6 +1517,23 @@ export default class Misskey implements MegalodonInterface {
.then(res => res.data[0] ?? '⭐');
}
+ private async getDefaultPostPrivacy(): Promise<'public' | 'unlisted' | 'private' | 'direct'> {
+ // NOTE: get-unsecure is calckey's extension.
+ // Misskey doesn't have this endpoint and regular `/i/registry/get` won't work
+ // unless you have a 'nativeToken', which is reserved for the frontend webapp.
+
+ return this.client
+ .post('/api/i/registry/get-unsecure', {
+ key: 'defaultNoteVisibility',
+ scope: ['client', 'base'],
+ })
+ .then(res => {
+ if (!res.data || (res.data != 'public' && res.data != 'home' && res.data != 'followers' && res.data != 'specified'))
+ return 'public';
+ return this.converter.visibility(res.data);
+ });
+ }
+
public async unfavouriteStatus(id: string): Promise> {
// NOTE: Misskey allows only one reaction per status, so we don't need to care what that emoji was.
return this.deleteEmojiReaction(id, '');
@@ -1638,20 +1643,26 @@ export default class Misskey implements MegalodonInterface {
/**
* POST /api/drive/files/create
*/
- public async uploadMedia(file: any, _options?: { description?: string; focus?: string }): Promise> {
+ public async uploadMedia(file: any, options?: { description?: string; focus?: string }): Promise> {
const formData = new FormData()
- formData.append('file', fs.createReadStream(file.path), {
- contentType: file.mimetype,
- filename: file.originalname,
- })
+ formData.append('file', fs.createReadStream(file.path), {
+ contentType: file.mimetype
+ })
+
+ if (file.originalname != null && file.originalname !== 'file')
+ formData.append('name', file.originalname);
+
+ if (options?.description != null)
+ formData.append('comment', options.description);
+
let headers: { [key: string]: string } = {}
if (typeof formData.getHeaders === 'function') {
headers = formData.getHeaders()
}
return this.client
.post('/api/drive/files/create', formData, headers)
- .then(res => ({ ...res, data: this.converter.file(res.data) }))
- }
+ .then(res => ({ ...res, data: this.converter.file(res.data) }))
+ }
public async getMedia(id: string): Promise> {
const res = await this.client.post('/api/drive/files/show', { fileId: id })
@@ -1679,6 +1690,12 @@ export default class Misskey implements MegalodonInterface {
isSensitive: options.is_sensitive
})
}
+
+ if (options.description !== undefined) {
+ params = Object.assign(params, {
+ comment: options.description
+ })
+ }
}
return this.client
.post('/api/drive/files/update', params)
diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts
index 7f1409c706..34e11784e0 100644
--- a/packages/megalodon/src/misskey/api_client.ts
+++ b/packages/megalodon/src/misskey/api_client.ts
@@ -134,8 +134,8 @@ namespace MisskeyAPI {
url: acctUrl,
avatar: u.avatarUrl,
avatar_static: u.avatarUrl,
- header: this.plcUrl, // FIXME
- header_static: this.plcUrl, // FIXME
+ header: this.plcUrl,
+ header_static: this.plcUrl,
emojis: u.emojis.map(e => this.emoji(e)),
moved: null,
fields: [],
@@ -174,13 +174,13 @@ namespace MisskeyAPI {
}
}
- userPreferences = (u: MisskeyAPI.Entity.UserDetailMe, g: MisskeyAPI.Entity.GetAll): MegalodonEntity.Preferences => {
+ userPreferences = (u: MisskeyAPI.Entity.UserDetailMe, v: 'public' | 'unlisted' | 'private' | 'direct'): MegalodonEntity.Preferences => {
return {
"reading:expand:media": "default",
"reading:expand:spoilers": false,
"posting:default:language": u.lang,
"posting:default:sensitive": u.alwaysMarkNsfw,
- "posting:default:visibility": this.visibility(g.defaultNoteVisibility)
+ "posting:default:visibility": v
}
}
@@ -308,7 +308,7 @@ namespace MisskeyAPI {
emojis: n.emojis.map(e => this.emoji(e)),
replies_count: n.repliesCount,
reblogs_count: n.renoteCount,
- favourites_count: this.getTotalReactions(n.reactions), // FIXME: instead get # of default reaction emoji reactions
+ favourites_count: this.getTotalReactions(n.reactions),
reblogged: false,
favourited: !!n.myReaction,
muted: false,