Various Fixes

This commit is contained in:
Laura Hausmann 2023-07-02 00:11:36 +02:00
parent 17f57c3ed1
commit 554e02dd31
Signed by: zotan
GPG key ID: D044E84C5BE01605
8 changed files with 204 additions and 21 deletions

View file

@ -1005,6 +1005,14 @@ export default class Mastodon implements MegalodonInterface {
})
}
public async getAccountFeaturedTags(id :string): Promise<Response<Array<Entity.FeaturedTag>>> {
return this.client.get<Array<MastodonAPI.Entity.FeaturedTag>>(`/api/v1/accounts/${id}/featured_tags`).then(res => {
return Object.assign(res, {
data: res.data.map(f => MastodonAPI.Converter.featured_tag(f))
})
})
}
public async createFeaturedTag(name: string): Promise<Response<Entity.FeaturedTag>> {
return this.client
.post<MastodonAPI.Entity.FeaturedTag>('/api/v1/featured_tags', {

View file

@ -229,6 +229,17 @@ export interface MegalodonInterface {
sleep_ms?: number
}
): Promise<Response<Array<Entity.Account>>>
/**
* GET /api/v1/accounts/:id/featured_tags
*
* @param id The account ID.
* @return The array of accounts.
*/
getAccountFeaturedTags(
id: string
): Promise<Response<Array<Entity.FeaturedTag>>>
/**
* GET /api/v1/accounts/:id/following
*

View file

@ -948,10 +948,19 @@ export default class Misskey implements MegalodonInterface {
// accounts/featured_tags
// ======================================
public async getFeaturedTags(): Promise<Response<Array<Entity.FeaturedTag>>> {
return new Promise((_, reject) => {
const err = new NoImplementedError('misskey does not support')
reject(err)
})
return this.getAccountFeaturedTags();
}
public async getAccountFeaturedTags(): Promise<Response<Array<Entity.FeaturedTag>>> {
console.log("getting featured tags");
const tags : Entity.FeaturedTag[] = [];
const res : Response = {
headers: undefined,
statusText: "",
status: 200,
data: tags
};
return new Promise(resolve => resolve(res))
}
public async createFeaturedTag(_name: string): Promise<Response<Entity.FeaturedTag>> {
@ -979,10 +988,23 @@ export default class Misskey implements MegalodonInterface {
// accounts/preferences
// ======================================
public async getPreferences(): Promise<Response<Entity.Preferences>> {
return new Promise((_, reject) => {
const err = new NoImplementedError('misskey does not support')
reject(err)
})
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: MisskeyAPI.Converter.userPreferences(res.data, ga.data)
})
})
*/
// TODO:
// FIXME: get this from api
return Object.assign(res, {
data: MisskeyAPI.Converter.userPreferences(res.data, {defaultNoteVisibility: "followers", tutorial: -1})
})
})
}
// ======================================
@ -1148,7 +1170,14 @@ export default class Misskey implements MegalodonInterface {
if (options) {
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
limit: options.limit,
depth: 12
})
}
else {
params = Object.assign(params, {
limit: 30,
depth: 12
})
}
if (options.max_id) {
@ -1162,10 +1191,31 @@ export default class Misskey implements MegalodonInterface {
})
}
}
else {
params = Object.assign(params, {
limit: 30,
depth: 12
})
}
return this.client.post<Array<MisskeyAPI.Entity.Note>>('/api/notes/children', params).then(res => {
console.log(JSON.stringify(res, null, 2));
const parent : Entity.Status[] = [];
this.getStatus(params.noteId).then(res => {
console.log("getting status");
if (res.data.in_reply_to_id != null){
console.log("replyid not null");
this.getStatus(res.data.in_reply_to_id).then(res => {
console.log("setting parent to " + res.data.id);
parent.push(res.data);
});
}
});
const context: Entity.Context = {
ancestors: [],
descendants: res.data.map(n => MisskeyAPI.Converter.note(n, this.baseUrlToHost(this.baseUrl)))
ancestors: parent,
descendants: this.dfs(res.data.map(n => MisskeyAPI.Converter.note(n, this.baseUrlToHost(this.baseUrl))))
}
return {
...res,
@ -1174,6 +1224,46 @@ export default class Misskey implements MegalodonInterface {
})
}
private dfs(graph: Entity.Status[]) {
// we don't need to run dfs if we have zero or one elements
if (graph.length <= 1) {
return graph;
}
// sort the graph first, so we can grab the correct starting point
graph = graph.sort((a, b) => {
if (a.id < b.id) return -1;
if (a.id > b.id) return 1;
return 0;
});
const initialPostId = graph[0].in_reply_to_id;
// populate stack with all top level replies
const stack = graph.filter(reply => reply.in_reply_to_id === initialPostId).reverse();
const visited = new Set();
const result = [];
while (stack.length) {
const currentPost = stack.pop();
if (currentPost === undefined)
return result;
if (!visited.has(currentPost)) {
visited.add(currentPost);
result.push(currentPost);
for (const reply of graph.filter(reply => reply.in_reply_to_id === currentPost.id).reverse()) {
stack.push(reply);
}
}
}
return result;
}
/**
* POST /api/notes/renotes
*/
@ -1196,16 +1286,20 @@ export default class Misskey implements MegalodonInterface {
}
public async favouriteStatus(id: string): Promise<Response<Entity.Status>> {
return this.createEmojiReaction(id, await this.getDefaultFavoriteEmoji());
}
private async getDefaultFavoriteEmoji(): Promise<string> {
// 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.
const reaction = await this.client
.post<Array<string>>('/api/i/registry/get-unsecure', {
key: 'reactions',
scope: ['client', 'base'],
})
.then(res => res.data[0] ?? '⭐');
return this.createEmojiReaction(id, reaction);
return await this.client
.post<Array<string>>('/api/i/registry/get-unsecure', {
key: 'reactions',
scope: ['client', 'base'],
})
.then(res => res.data[0] ?? '⭐');
}
public async unfavouriteStatus(id: string): Promise<Response<Entity.Status>> {

View file

@ -36,6 +36,8 @@ namespace MisskeyAPI {
export type Relation = MisskeyEntity.Relation
export type User = MisskeyEntity.User
export type UserDetail = MisskeyEntity.UserDetail
export type UserDetailMe = MisskeyEntity.UserDetailMe
export type GetAll = MisskeyEntity.GetAll
export type UserKey = MisskeyEntity.UserKey
export type Session = MisskeyEntity.Session
export type Stats = MisskeyEntity.Stats
@ -90,8 +92,8 @@ namespace MisskeyAPI {
url: acctUrl,
avatar: u.avatarUrl,
avatar_static: u.avatarColor,
header: '',
header_static: '',
header: 'https://http.cat/404', // FIXME
header_static: 'https://http.cat/404', // FIXME
emojis: u.emojis.map(e => emoji(e)),
moved: null,
fields: [],
@ -130,6 +132,16 @@ namespace MisskeyAPI {
}
}
export const userPreferences = (u: MisskeyAPI.Entity.UserDetailMe, g: MisskeyAPI.Entity.GetAll): MegalodonEntity.Preferences => {
return {
"reading:expand:media": "default",
"reading:expand:spoilers": false,
"posting:default:language": u.lang,
"posting:default:sensitive": u.alwaysMarkNsfw,
"posting:default:visibility": visibility(g.defaultNoteVisibility)
}
}
export const visibility = (v: 'public' | 'home' | 'followers' | 'specified'): 'public' | 'unlisted' | 'private' | 'direct' => {
switch (v) {
case 'public':
@ -252,7 +264,7 @@ namespace MisskeyAPI {
emojis: n.emojis.map(e => emoji(e)),
replies_count: n.repliesCount,
reblogs_count: n.renoteCount,
favourites_count: 0,
favourites_count: getTotalReactions(n.reactions), // FIXME: instead get # of default reaction emoji reactions
reblogged: false,
favourited: !!n.myReaction,
muted: false,
@ -290,6 +302,10 @@ namespace MisskeyAPI {
})
}
export const getTotalReactions = (r: { [key: string]: number }): number => {
return Object.values(r).length > 0 ? Object.values(r).reduce((previousValue, currentValue) => previousValue + currentValue) : 0
}
export const reactions = (r: Array<Entity.Reaction>): Array<MegalodonEntity.Reaction> => {
const result: Array<MegalodonEntity.Reaction> = []
for (const e of r) {
@ -553,6 +569,9 @@ namespace MisskeyAPI {
})
}
}
console.log(JSON.stringify(bodyParams, null, 2));
return axios.post<T>(this.baseUrl + path, bodyParams, options).then((resp: AxiosResponse<T>) => {
const res: Response<T> = {
data: resp.data,

View file

@ -0,0 +1,6 @@
namespace MisskeyEntity {
export type GetAll = {
tutorial: number
defaultNoteVisibility: 'public' | 'home' | 'followers' | 'specified'
}
}

View file

@ -0,0 +1,36 @@
/// <reference path="emoji.ts" />
/// <reference path="field.ts" />
/// <reference path="note.ts" />
namespace MisskeyEntity {
export type UserDetailMe = {
id: string
name: string
username: string
host: string | null
avatarUrl: string
avatarColor: string
isAdmin: boolean
isModerator: boolean
isBot: boolean
isCat: boolean
emojis: Array<Emoji>
createdAt: string
bannerUrl: string
bannerColor: string
isLocked: boolean
isSilenced: boolean
isSuspended: boolean
description: string
followersCount: number
followingCount: number
notesCount: number
avatarId: string
bannerId: string
pinnedNoteIds?: Array<string>
pinnedNotes?: Array<Note>
fields: Array<Field>
alwaysMarkNsfw: boolean
lang: string | null
}
}

View file

@ -20,6 +20,7 @@
/// <reference path="entities/relation.ts" />
/// <reference path="entities/user.ts" />
/// <reference path="entities/userDetail.ts" />
/// <reference path="entities/userDetailMe.ts" />
/// <reference path="entities/userkey.ts" />
/// <reference path="entities/session.ts" />
/// <reference path="entities/stats.ts" />

View file

@ -997,6 +997,14 @@ export default class Pleroma implements MegalodonInterface {
})
}
public async getAccountFeaturedTags(id: string): Promise<Response<Array<Entity.FeaturedTag>>> {
return this.client.get<Array<PleromaAPI.Entity.FeaturedTag>>(`/api/v1/accounts/${id}/featured_tags`).then(res => {
return Object.assign(res, {
data: res.data.map(f => PleromaAPI.Converter.featured_tag(f))
})
})
}
public async createFeaturedTag(name: string): Promise<Response<Entity.FeaturedTag>> {
return this.client
.post<PleromaAPI.Entity.FeaturedTag>('/api/v1/featured_tags', {