Merge pull request '[PR]: Next batch of masto-client improvements' (#10440) from e2net/calckey:masto-client-improvements into develop
Reviewed-on: https://codeberg.org/calckey/calckey/pulls/10440
This commit is contained in:
commit
80b60af9f4
@ -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 })
|
||||
|
@ -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);
|
||||
|
@ -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: "",
|
||||
};
|
||||
|
@ -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("<br />");
|
||||
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: `<p>${content}</p>`,
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
@ -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<Array<MisskeyAPI.Entity.Follower>>('/api/users/followers', params).then(res => {
|
||||
return Object.assign(res, {
|
||||
data: res.data.map(f => this.converter.follower(f))
|
||||
})
|
||||
})
|
||||
return this.client.post<Array<MisskeyAPI.Entity.Follower>>('/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<Array<MisskeyAPI.Entity.Following>>('/api/users/following', params).then(res => {
|
||||
return Object.assign(res, {
|
||||
data: res.data.map(f => this.converter.following(f))
|
||||
})
|
||||
})
|
||||
return this.client.post<Array<MisskeyAPI.Entity.Following>>('/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<Response<Array<Entity.List>>> {
|
||||
@ -1079,23 +1079,11 @@ export default class Misskey implements MegalodonInterface {
|
||||
// accounts/preferences
|
||||
// ======================================
|
||||
public async getPreferences(): Promise<Response<Entity.Preferences>> {
|
||||
return this.client.post<MisskeyAPI.Entity.UserDetailMe>('/api/i').then(res => {
|
||||
/*
|
||||
return this.client.post<MisskeyAPI.Entity.GetAll>('/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<MisskeyAPI.Entity.UserDetailMe>('/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<string>('/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<Response<Entity.Status>> {
|
||||
// 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<Response<Entity.Attachment>> {
|
||||
public async uploadMedia(file: any, options?: { description?: string; focus?: string }): Promise<Response<Entity.Attachment>> {
|
||||
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<MisskeyAPI.Entity.File>('/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<Response<Entity.Attachment>> {
|
||||
const res = await this.client.post<MisskeyAPI.Entity.File>('/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<MisskeyAPI.Entity.File>('/api/drive/files/update', params)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user