mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
Implement WebFinger, rework TS
This commit is contained in:
parent
29f63dfcb7
commit
c573052450
35
database/entities/Application.ts
Normal file
35
database/entities/Application.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
import { APIApplication } from "~types/entities/application";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applications from clients
|
||||||
|
*/
|
||||||
|
@Entity({
|
||||||
|
name: "applications",
|
||||||
|
})
|
||||||
|
export class Application extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn("uuid")
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column("varchar")
|
||||||
|
name!: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
website!: string | null;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
vapid_key!: string | null;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/require-await
|
||||||
|
async toAPI(): Promise<APIApplication> {
|
||||||
|
return {
|
||||||
|
name: "",
|
||||||
|
website: null,
|
||||||
|
vapid_key: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
import { getConfig } from "@config";
|
|
||||||
import {
|
|
||||||
BaseEntity,
|
|
||||||
Column,
|
|
||||||
CreateDateColumn,
|
|
||||||
Entity,
|
|
||||||
ManyToOne,
|
|
||||||
PrimaryGeneratedColumn,
|
|
||||||
UpdateDateColumn,
|
|
||||||
} from "typeorm";
|
|
||||||
import { Status } from "~types/entities/status";
|
|
||||||
import { DBUser } from "./DBUser";
|
|
||||||
|
|
||||||
const config = getConfig();
|
|
||||||
|
|
||||||
@Entity({
|
|
||||||
name: "statuses",
|
|
||||||
})
|
|
||||||
export class DBStatus extends BaseEntity {
|
|
||||||
@PrimaryGeneratedColumn("uuid")
|
|
||||||
id!: string;
|
|
||||||
|
|
||||||
@ManyToOne(() => DBUser, (user) => user.id)
|
|
||||||
account!: DBUser;
|
|
||||||
|
|
||||||
@CreateDateColumn()
|
|
||||||
created_at!: Date;
|
|
||||||
|
|
||||||
@UpdateDateColumn()
|
|
||||||
updated_at!: Date;
|
|
||||||
|
|
||||||
@ManyToOne(() => DBStatus, (status) => status.id, {
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
reblog?: DBStatus;
|
|
||||||
|
|
||||||
@Column("boolean")
|
|
||||||
isReblog!: boolean;
|
|
||||||
|
|
||||||
toAPI(): Status {
|
|
||||||
return {
|
|
||||||
account: this.account.toAPI(),
|
|
||||||
application: null,
|
|
||||||
bookmarked: false,
|
|
||||||
created_at: this.created_at.toISOString(),
|
|
||||||
emojis: [],
|
|
||||||
favourited: false,
|
|
||||||
favourites_count: 0,
|
|
||||||
id: this.id,
|
|
||||||
in_reply_to_account_id: null,
|
|
||||||
in_reply_to_id: null,
|
|
||||||
language: null,
|
|
||||||
media_attachments: [],
|
|
||||||
mentions: [],
|
|
||||||
muted: false,
|
|
||||||
pinned: false,
|
|
||||||
poll: null,
|
|
||||||
reblog: this.isReblog ? this.reblog?.toAPI() ?? null : null,
|
|
||||||
reblogged: false,
|
|
||||||
reblogs_count: 0,
|
|
||||||
replies_count: 0,
|
|
||||||
sensitive: false,
|
|
||||||
spoiler_text: "",
|
|
||||||
tags: [],
|
|
||||||
card: null,
|
|
||||||
content: "",
|
|
||||||
uri: `${config.http.base_url}/@${this.account.username}/${this.id}`,
|
|
||||||
url: `${config.http.base_url}/@${this.account.username}/${this.id}`,
|
|
||||||
visibility: "public",
|
|
||||||
quote: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
30
database/entities/Emoji.ts
Normal file
30
database/entities/Emoji.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
import { APIEmoji } from "~types/entities/emoji";
|
||||||
|
|
||||||
|
@Entity({
|
||||||
|
name: "emojis",
|
||||||
|
})
|
||||||
|
export class Emoji extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn("uuid")
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column("varchar")
|
||||||
|
shortcode!: string;
|
||||||
|
|
||||||
|
@Column("varchar")
|
||||||
|
url!: string;
|
||||||
|
|
||||||
|
@Column("boolean")
|
||||||
|
visible_in_picker!: boolean;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/require-await
|
||||||
|
async toAPI(): Promise<APIEmoji> {
|
||||||
|
return {
|
||||||
|
shortcode: this.shortcode,
|
||||||
|
static_url: "",
|
||||||
|
url: "",
|
||||||
|
visible_in_picker: false,
|
||||||
|
category: undefined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
database/entities/Favourite.ts
Normal file
23
database/entities/Favourite.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { BaseEntity, Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
import { User } from "./User";
|
||||||
|
import { Status } from "./Status";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores an ActivityPub Like event
|
||||||
|
*/
|
||||||
|
@Entity({
|
||||||
|
name: "favourites",
|
||||||
|
})
|
||||||
|
export class Favourite extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn("uuid")
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => User, (user) => user.id)
|
||||||
|
actor!: User;
|
||||||
|
|
||||||
|
@ManyToOne(() => Status, (status) => status.id)
|
||||||
|
object!: Status;
|
||||||
|
|
||||||
|
@Column("datetime")
|
||||||
|
published!: Date;
|
||||||
|
}
|
||||||
66
database/entities/Instance.ts
Normal file
66
database/entities/Instance.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { BaseEntity, Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
import { APIInstance } from "~types/entities/instance";
|
||||||
|
import { User } from "./User";
|
||||||
|
|
||||||
|
@Entity({
|
||||||
|
name: "instances",
|
||||||
|
})
|
||||||
|
export class Instance extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn("uuid")
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => User, (user) => user.id)
|
||||||
|
contact_account!: User;
|
||||||
|
|
||||||
|
@Column("jsonb", {
|
||||||
|
default: {
|
||||||
|
media_attachments: {
|
||||||
|
image_matrix_limit: 0,
|
||||||
|
image_size_limit: 0,
|
||||||
|
supported_mime_types: [],
|
||||||
|
video_frame_limit: 0,
|
||||||
|
video_matrix_limit: 0,
|
||||||
|
video_size_limit: 0,
|
||||||
|
},
|
||||||
|
polls: {
|
||||||
|
max_options: 0,
|
||||||
|
max_characters_per_option: 0,
|
||||||
|
max_expiration: 0,
|
||||||
|
min_expiration: 0,
|
||||||
|
},
|
||||||
|
statuses: {
|
||||||
|
characters_reserved_per_url: 0,
|
||||||
|
max_characters: 0,
|
||||||
|
max_media_attachments: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
configuration!: APIInstance["configuration"];
|
||||||
|
|
||||||
|
async toAPI(): Promise<APIInstance> {
|
||||||
|
return {
|
||||||
|
uri: "",
|
||||||
|
approval_required: false,
|
||||||
|
email: "",
|
||||||
|
thumbnail: "",
|
||||||
|
title: "",
|
||||||
|
version: "",
|
||||||
|
configuration: this.configuration,
|
||||||
|
contact_account: await this.contact_account.toAPI(),
|
||||||
|
description: "",
|
||||||
|
invites_enabled: false,
|
||||||
|
languages: [],
|
||||||
|
registrations: false,
|
||||||
|
rules: [],
|
||||||
|
stats: {
|
||||||
|
domain_count: 0,
|
||||||
|
status_count: 0,
|
||||||
|
user_count: 0,
|
||||||
|
},
|
||||||
|
urls: {
|
||||||
|
streaming_api: "",
|
||||||
|
},
|
||||||
|
max_toot_chars: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
18
database/entities/RawObject.ts
Normal file
18
database/entities/RawObject.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
import {
|
||||||
|
APObject,
|
||||||
|
} from "activitypub-types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores an ActivityPub object as raw JSON-LD data
|
||||||
|
*/
|
||||||
|
@Entity({
|
||||||
|
name: "objects",
|
||||||
|
})
|
||||||
|
export class RawObject extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn("uuid")
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column("json")
|
||||||
|
data!: APObject;
|
||||||
|
}
|
||||||
29
database/entities/Renote.ts
Normal file
29
database/entities/Renote.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import {
|
||||||
|
BaseEntity,
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
ManyToOne,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
} from "typeorm";
|
||||||
|
import { User } from "./User";
|
||||||
|
import { Status } from "./Status";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores an ActivityPub Renote event
|
||||||
|
*/
|
||||||
|
@Entity({
|
||||||
|
name: "renotes",
|
||||||
|
})
|
||||||
|
export class Renote extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn("uuid")
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => User, (user) => user.id)
|
||||||
|
actor!: User;
|
||||||
|
|
||||||
|
@ManyToOne(() => Status, (status) => status.id)
|
||||||
|
object!: Status;
|
||||||
|
|
||||||
|
@Column("datetime")
|
||||||
|
published!: Date;
|
||||||
|
}
|
||||||
114
database/entities/Status.ts
Normal file
114
database/entities/Status.ts
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import { getConfig } from "@config";
|
||||||
|
import {
|
||||||
|
BaseEntity,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
Entity,
|
||||||
|
ManyToMany,
|
||||||
|
ManyToOne,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from "typeorm";
|
||||||
|
import { APIStatus } from "~types/entities/status";
|
||||||
|
import { User } from "./User";
|
||||||
|
import { Application } from "./Application";
|
||||||
|
import { Emoji } from "./Emoji";
|
||||||
|
import { Favourite } from "./Favourite";
|
||||||
|
|
||||||
|
const config = getConfig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores ActivityPub notes
|
||||||
|
*/
|
||||||
|
@Entity({
|
||||||
|
name: "statuses",
|
||||||
|
})
|
||||||
|
export class Status extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn("uuid")
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => User, (user) => user.id)
|
||||||
|
account!: User;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
created_at!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updated_at!: Date;
|
||||||
|
|
||||||
|
@ManyToOne(() => Status, (status) => status.id, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
reblog?: Status;
|
||||||
|
|
||||||
|
@Column("boolean")
|
||||||
|
isReblog!: boolean;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
content!: string;
|
||||||
|
|
||||||
|
@Column("varchar")
|
||||||
|
visibility!: APIStatus["visibility"];
|
||||||
|
|
||||||
|
@Column("boolean")
|
||||||
|
sensitive!: boolean;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
spoiler_text!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => Application, (app) => app.id, {
|
||||||
|
nullable: true
|
||||||
|
})
|
||||||
|
application!: Application | null;
|
||||||
|
|
||||||
|
@ManyToMany(() => Emoji, (emoji) => emoji.id)
|
||||||
|
emojis!: Emoji[];
|
||||||
|
|
||||||
|
async getFavourites(): Promise<Favourite[]> {
|
||||||
|
return Favourite.find({
|
||||||
|
where: {
|
||||||
|
object: {
|
||||||
|
id: this.id
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async toAPI(): Promise<APIStatus> {
|
||||||
|
return {
|
||||||
|
account: await this.account.toAPI(),
|
||||||
|
application: await this.application?.toAPI() ?? null,
|
||||||
|
bookmarked: false,
|
||||||
|
created_at: this.created_at.toISOString(),
|
||||||
|
emojis: await Promise.all(this.emojis.map(async (emoji) => await emoji.toAPI())),
|
||||||
|
favourited: false,
|
||||||
|
favourites_count: (await this.getFavourites()).length,
|
||||||
|
id: this.id,
|
||||||
|
in_reply_to_account_id: null,
|
||||||
|
in_reply_to_id: null,
|
||||||
|
language: null,
|
||||||
|
media_attachments: [],
|
||||||
|
mentions: [],
|
||||||
|
muted: false,
|
||||||
|
pinned: false,
|
||||||
|
poll: null,
|
||||||
|
reblog: this.isReblog ? await this.reblog?.toAPI() ?? null : null,
|
||||||
|
reblogged: false,
|
||||||
|
reblogs_count: 0,
|
||||||
|
replies_count: 0,
|
||||||
|
sensitive: false,
|
||||||
|
spoiler_text: "",
|
||||||
|
tags: [],
|
||||||
|
card: null,
|
||||||
|
content: "",
|
||||||
|
uri: `${config.http.base_url}/@${this.account.username}/${this.id}`,
|
||||||
|
url: `${config.http.base_url}/@${this.account.username}/${this.id}`,
|
||||||
|
visibility: "public",
|
||||||
|
quote: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
import { getConfig, getHost } from "@config";
|
import { getConfig, getHost } from "@config";
|
||||||
import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
|
import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
|
||||||
import { Account } from "~types/entities/account";
|
import { APIAccount } from "~types/entities/account";
|
||||||
|
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores local and remote users
|
||||||
|
*/
|
||||||
@Entity({
|
@Entity({
|
||||||
name: "users",
|
name: "users",
|
||||||
})
|
})
|
||||||
export class DBUser extends BaseEntity {
|
export class User extends BaseEntity {
|
||||||
@PrimaryGeneratedColumn("uuid")
|
@PrimaryGeneratedColumn("uuid")
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
|
|
@ -16,8 +19,10 @@ export class DBUser extends BaseEntity {
|
||||||
})
|
})
|
||||||
username!: string;
|
username!: string;
|
||||||
|
|
||||||
@Column("varchar")
|
@Column("varchar", {
|
||||||
password!: string;
|
nullable: true,
|
||||||
|
})
|
||||||
|
password!: string | null;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
unique: true,
|
unique: true,
|
||||||
|
|
@ -35,7 +40,11 @@ export class DBUser extends BaseEntity {
|
||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
updated_at!: Date;
|
updated_at!: Date;
|
||||||
|
|
||||||
toAPI(): Account {
|
@Column("boolean")
|
||||||
|
isRemote!: boolean;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/require-await
|
||||||
|
async toAPI(): Promise<APIAccount> {
|
||||||
return {
|
return {
|
||||||
acct: `@${this.username}@${getHost()}`,
|
acct: `@${this.username}@${getHost()}`,
|
||||||
avatar: "",
|
avatar: "",
|
||||||
1
index.ts
1
index.ts
|
|
@ -1,4 +1,5 @@
|
||||||
import { getConfig } from "@config";
|
import { getConfig } from "@config";
|
||||||
|
import "reflect-metadata";
|
||||||
|
|
||||||
const router = new Bun.FileSystemRouter({
|
const router = new Bun.FileSystemRouter({
|
||||||
style: "nextjs",
|
style: "nextjs",
|
||||||
|
|
|
||||||
37
package.json
37
package.json
|
|
@ -1,19 +1,22 @@
|
||||||
{
|
{
|
||||||
"name": "fedi-project",
|
"name": "fedi-project",
|
||||||
"module": "index.ts",
|
"module": "index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^6.6.0",
|
"@typescript-eslint/eslint-plugin": "^6.6.0",
|
||||||
"@typescript-eslint/parser": "^6.6.0",
|
"@typescript-eslint/parser": "^6.6.0",
|
||||||
"bun-types": "latest",
|
"activitypub-types": "^1.0.3",
|
||||||
"eslint": "^8.49.0",
|
"bun-types": "latest",
|
||||||
"typescript": "^5.2.2"
|
"eslint": "^8.49.0",
|
||||||
},
|
"typescript": "^5.2.2"
|
||||||
"peerDependencies": {
|
},
|
||||||
"typescript": "^5.0.0"
|
"peerDependencies": {
|
||||||
},
|
"typescript": "^5.0.0"
|
||||||
"dependencies": {
|
},
|
||||||
"pg": "^8.11.3",
|
"dependencies": {
|
||||||
"typeorm": "^0.3.17"
|
"jsonld": "^8.3.1",
|
||||||
}
|
"pg": "^8.11.3",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"typeorm": "^0.3.17"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
server/api/.well-known/webfinger/index.ts
Normal file
39
server/api/.well-known/webfinger/index.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { errorResponse, jsonResponse } from "@response";
|
||||||
|
import { MatchedRoute } from "bun";
|
||||||
|
import { User } from "~database/entities/User";
|
||||||
|
import { getHost } from "@config";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ActivityPub WebFinger endpoint
|
||||||
|
*/
|
||||||
|
export default async (
|
||||||
|
req: Request,
|
||||||
|
matchedRoute: MatchedRoute
|
||||||
|
): Promise<Response> => {
|
||||||
|
// In the format acct:name@example.com
|
||||||
|
const resource = matchedRoute.query.resource;
|
||||||
|
const requestedUser = resource.split("acct:")[1];
|
||||||
|
|
||||||
|
// Check if user is a local user
|
||||||
|
if (requestedUser.split("@")[1] !== getHost()) {
|
||||||
|
return errorResponse("User is a remote user", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await User.findOneBy({ username: requestedUser.split("@")[0] });
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return errorResponse("User not found", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonResponse({
|
||||||
|
subject: `acct:${user.username}@${getHost()}`,
|
||||||
|
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
rel: "self",
|
||||||
|
type: "application/activity+json",
|
||||||
|
href: `${getHost()}/@${user.username}/actor`
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
};
|
||||||
19
server/api/object/[uuid]/index.ts
Normal file
19
server/api/object/[uuid]/index.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { errorResponse, jsonResponse } from "@response";
|
||||||
|
import { MatchedRoute } from "bun";
|
||||||
|
import { RawObject } from "~database/entities/RawObject";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a user
|
||||||
|
*/
|
||||||
|
export default async (
|
||||||
|
req: Request,
|
||||||
|
matchedRoute: MatchedRoute
|
||||||
|
): Promise<Response> => {
|
||||||
|
const object = await RawObject.findOneBy({
|
||||||
|
id: matchedRoute.params.id
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!object) return errorResponse("Object not found", 404)
|
||||||
|
|
||||||
|
return jsonResponse(object);
|
||||||
|
};
|
||||||
|
|
@ -1,24 +1,22 @@
|
||||||
import { jsonResponse } from "@response";
|
import { errorResponse, jsonResponse } from "@response";
|
||||||
import { MatchedRoute } from "bun";
|
import { MatchedRoute } from "bun";
|
||||||
import { DBUser } from "~database/entities/DBUser";
|
import { User } from "~database/entities/User";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a user
|
||||||
|
*/
|
||||||
export default async (
|
export default async (
|
||||||
req: Request,
|
req: Request,
|
||||||
matchedRoute: MatchedRoute
|
matchedRoute: MatchedRoute
|
||||||
): Promise<Response> => {
|
): Promise<Response> => {
|
||||||
const id = matchedRoute.params.id;
|
const id = matchedRoute.params.id;
|
||||||
|
|
||||||
const user = await DBUser.findOneBy({
|
const user = await User.findOneBy({
|
||||||
id,
|
id,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user)
|
if (!user)
|
||||||
return jsonResponse(
|
return errorResponse("User not found", 404)
|
||||||
{
|
|
||||||
error: "User not found",
|
|
||||||
},
|
|
||||||
404
|
|
||||||
);
|
|
||||||
|
|
||||||
return jsonResponse(user.toAPI());
|
return jsonResponse(user.toAPI());
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import { jsonResponse } from "@response";
|
import { errorResponse, jsonResponse } from "@response";
|
||||||
import { MatchedRoute } from "bun";
|
import { MatchedRoute } from "bun";
|
||||||
import { DBStatus } from "~database/entities/DBStatus";
|
import { Status } from "~database/entities/Status";
|
||||||
import { DBUser } from "~database/entities/DBUser";
|
import { User } from "~database/entities/User";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch all statuses for a user
|
||||||
|
*/
|
||||||
export default async (
|
export default async (
|
||||||
req: Request,
|
req: Request,
|
||||||
matchedRoute: MatchedRoute
|
matchedRoute: MatchedRoute
|
||||||
|
|
@ -24,19 +27,14 @@ export default async (
|
||||||
tagged?: string;
|
tagged?: string;
|
||||||
} = matchedRoute.query;
|
} = matchedRoute.query;
|
||||||
|
|
||||||
const user = await DBUser.findOneBy({
|
const user = await User.findOneBy({
|
||||||
id,
|
id,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user)
|
if (!user)
|
||||||
return jsonResponse(
|
return errorResponse("User not found", 404)
|
||||||
{
|
|
||||||
error: "User not found",
|
|
||||||
},
|
|
||||||
404
|
|
||||||
);
|
|
||||||
|
|
||||||
const statuses = await DBStatus.find({
|
const statuses = await Status.find({
|
||||||
where: {
|
where: {
|
||||||
account: {
|
account: {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
"strictFunctionTypes": true,
|
"strictFunctionTypes": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"types": [
|
"types": [
|
||||||
"bun-types" // add Bun global
|
"bun-types" // add Bun global
|
||||||
|
|
@ -25,6 +26,11 @@
|
||||||
"paths": {
|
"paths": {
|
||||||
"@*": ["./utils/*"],
|
"@*": ["./utils/*"],
|
||||||
"~*": ["./*"]
|
"~*": ["./*"]
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
"include": [
|
||||||
|
"*.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"server/api/.well-known/**/*.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Emoji } from "./emoji";
|
import { APIEmoji } from "./emoji";
|
||||||
import { Field } from "./field";
|
import { APIField } from "./field";
|
||||||
import { Role } from "./role";
|
import { APIRole } from "./role";
|
||||||
import { Source } from "./source";
|
import { APISource } from "./source";
|
||||||
|
|
||||||
export interface Account {
|
export interface APIAccount {
|
||||||
id: string;
|
id: string;
|
||||||
username: string;
|
username: string;
|
||||||
acct: string;
|
acct: string;
|
||||||
|
|
@ -24,11 +24,11 @@ export interface Account {
|
||||||
avatar_static: string;
|
avatar_static: string;
|
||||||
header: string;
|
header: string;
|
||||||
header_static: string;
|
header_static: string;
|
||||||
emojis: Emoji[];
|
emojis: APIEmoji[];
|
||||||
moved: Account | null;
|
moved: APIAccount | null;
|
||||||
fields: Field[];
|
fields: APIField[];
|
||||||
bot: boolean;
|
bot: boolean;
|
||||||
source?: Source;
|
source?: APISource;
|
||||||
role?: Role;
|
role?: APIRole;
|
||||||
mute_expires_at?: string;
|
mute_expires_at?: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Activity {
|
export interface APIActivity {
|
||||||
week: string;
|
week: string;
|
||||||
statuses: string;
|
statuses: string;
|
||||||
logins: string;
|
logins: string;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Emoji } from "./emoji";
|
import { APIEmoji } from "./emoji";
|
||||||
import { StatusTag } from "./status";
|
import { APIStatusTag } from "./status";
|
||||||
|
|
||||||
export interface Announcement {
|
export interface APIAnnouncement {
|
||||||
id: string;
|
id: string;
|
||||||
content: string;
|
content: string;
|
||||||
starts_at: string | null;
|
starts_at: string | null;
|
||||||
|
|
@ -13,8 +13,8 @@ export interface Announcement {
|
||||||
read: boolean | null;
|
read: boolean | null;
|
||||||
mentions: AnnouncementAccount[];
|
mentions: AnnouncementAccount[];
|
||||||
statuses: AnnouncementStatus[];
|
statuses: AnnouncementStatus[];
|
||||||
tags: StatusTag[];
|
tags: APIStatusTag[];
|
||||||
emojis: Emoji[];
|
emojis: APIEmoji[];
|
||||||
reactions: AnnouncementReaction[];
|
reactions: AnnouncementReaction[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Application {
|
export interface APIApplication {
|
||||||
name: string;
|
name: string;
|
||||||
website?: string | null;
|
website?: string | null;
|
||||||
vapid_key?: string | null;
|
vapid_key?: string | null;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import { Meta } from "./attachment";
|
import { APIMeta } from "./attachment";
|
||||||
|
|
||||||
export interface AsyncAttachment {
|
export interface APIAsyncAttachment {
|
||||||
id: string;
|
id: string;
|
||||||
type: "unknown" | "image" | "gifv" | "video" | "audio";
|
type: "unknown" | "image" | "gifv" | "video" | "audio";
|
||||||
url: string | null;
|
url: string | null;
|
||||||
remote_url: string | null;
|
remote_url: string | null;
|
||||||
preview_url: string;
|
preview_url: string;
|
||||||
text_url: string | null;
|
text_url: string | null;
|
||||||
meta: Meta | null;
|
meta: APIMeta | null;
|
||||||
description: string | null;
|
description: string | null;
|
||||||
blurhash: string | null;
|
blurhash: string | null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Sub {
|
export interface APISub {
|
||||||
// For Image, Gifv, and Video
|
// For Image, Gifv, and Video
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
|
|
@ -13,15 +13,15 @@ export interface Sub {
|
||||||
bitrate?: number;
|
bitrate?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Focus {
|
export interface APIFocus {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Meta {
|
export interface APIMeta {
|
||||||
original?: Sub;
|
original?: APISub;
|
||||||
small?: Sub;
|
small?: APISub;
|
||||||
focus?: Focus;
|
focus?: APIFocus;
|
||||||
length?: string;
|
length?: string;
|
||||||
duration?: number;
|
duration?: number;
|
||||||
fps?: number;
|
fps?: number;
|
||||||
|
|
@ -34,14 +34,14 @@ export interface Meta {
|
||||||
audio_channel?: string;
|
audio_channel?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Attachment {
|
export interface APIAttachment {
|
||||||
id: string;
|
id: string;
|
||||||
type: "unknown" | "image" | "gifv" | "video" | "audio";
|
type: "unknown" | "image" | "gifv" | "video" | "audio";
|
||||||
url: string;
|
url: string;
|
||||||
remote_url: string | null;
|
remote_url: string | null;
|
||||||
preview_url: string | null;
|
preview_url: string | null;
|
||||||
text_url: string | null;
|
text_url: string | null;
|
||||||
meta: Meta | null;
|
meta: APIMeta | null;
|
||||||
description: string | null;
|
description: string | null;
|
||||||
blurhash: string | null;
|
blurhash: string | null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Card {
|
export interface APICard {
|
||||||
url: string;
|
url: string;
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Status } from "./status";
|
import { APIStatus } from "./status";
|
||||||
|
|
||||||
export interface Context {
|
export interface APIContext {
|
||||||
ancestors: Status[];
|
ancestors: APIStatus[];
|
||||||
descendants: Status[];
|
descendants: APIStatus[];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Account } from "./account";
|
import { APIAccount } from "./account";
|
||||||
import { Status } from "./status";
|
import { APIStatus } from "./status";
|
||||||
|
|
||||||
export interface Conversation {
|
export interface APIConversation {
|
||||||
id: string;
|
id: string;
|
||||||
accounts: Account[];
|
accounts: APIAccount[];
|
||||||
last_status: Status | null;
|
last_status: APIStatus | null;
|
||||||
unread: boolean;
|
unread: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Emoji {
|
export interface APIEmoji {
|
||||||
shortcode: string;
|
shortcode: string;
|
||||||
static_url: string;
|
static_url: string;
|
||||||
url: string;
|
url: string;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface FeaturedTag {
|
export interface APIFeaturedTag {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
statuses_count: number;
|
statuses_count: number;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Field {
|
export interface APIField {
|
||||||
name: string;
|
name: string;
|
||||||
value: string;
|
value: string;
|
||||||
verified_at: string | null;
|
verified_at: string | null;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Filter {
|
export interface APIFilter {
|
||||||
id: string;
|
id: string;
|
||||||
phrase: string;
|
phrase: string;
|
||||||
context: FilterContext[];
|
context: FilterContext[];
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface History {
|
export interface APIHistory {
|
||||||
day: string;
|
day: string;
|
||||||
uses: number;
|
uses: number;
|
||||||
accounts: number;
|
accounts: number;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface IdentityProof {
|
export interface APIIdentityProof {
|
||||||
provider: string;
|
provider: string;
|
||||||
provider_username: string;
|
provider_username: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
import { Account } from "./account";
|
import { APIAccount } from "./account";
|
||||||
import { Stats } from "./stats";
|
import { APIStats } from "./stats";
|
||||||
import { URLs } from "./urls";
|
import { APIURLs } from "./urls";
|
||||||
|
|
||||||
export interface Instance {
|
export interface APIInstance {
|
||||||
uri: string;
|
uri: string;
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
email: string;
|
email: string;
|
||||||
version: string;
|
version: string;
|
||||||
thumbnail: string | null;
|
thumbnail: string | null;
|
||||||
urls: URLs;
|
urls: APIURLs;
|
||||||
stats: Stats;
|
stats: APIStats;
|
||||||
languages: string[];
|
languages: string[];
|
||||||
registrations: boolean;
|
registrations: boolean;
|
||||||
approval_required: boolean;
|
approval_required: boolean;
|
||||||
|
|
@ -37,11 +37,11 @@ export interface Instance {
|
||||||
max_expiration: number;
|
max_expiration: number;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
contact_account: Account;
|
contact_account: APIAccount;
|
||||||
rules: InstanceRule[];
|
rules: APIInstanceRule[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InstanceRule {
|
export interface APIInstanceRule {
|
||||||
id: string;
|
id: string;
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
export interface List {
|
export interface APIList {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
replies_policy: RepliesPolicy;
|
replies_policy: APIRepliesPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RepliesPolicy = "followed" | "list" | "none";
|
export type APIRepliesPolicy = "followed" | "list" | "none";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Marker {
|
export interface APIMarker {
|
||||||
home: {
|
home: {
|
||||||
last_read_id: string;
|
last_read_id: string;
|
||||||
version: number;
|
version: number;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Mention {
|
export interface APIMention {
|
||||||
id: string;
|
id: string;
|
||||||
username: string;
|
username: string;
|
||||||
url: string;
|
url: string;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import { Account } from "./account";
|
import { APIAccount } from "./account";
|
||||||
import { Status } from "./status";
|
import { APIStatus } from "./status";
|
||||||
|
|
||||||
export interface Notification {
|
export interface APINotification {
|
||||||
account: Account;
|
account: APIAccount;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
id: string;
|
id: string;
|
||||||
status?: Status;
|
status?: APIStatus;
|
||||||
type: NotificationType;
|
type: APINotificationType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type NotificationType = string;
|
export type APINotificationType = string;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { PollOption } from "./poll_option";
|
import { APIPollOption } from "./poll_option";
|
||||||
|
|
||||||
export interface Poll {
|
export interface APIPoll {
|
||||||
id: string;
|
id: string;
|
||||||
expires_at: string | null;
|
expires_at: string | null;
|
||||||
expired: boolean;
|
expired: boolean;
|
||||||
multiple: boolean;
|
multiple: boolean;
|
||||||
votes_count: number;
|
votes_count: number;
|
||||||
options: PollOption[];
|
options: APIPollOption[];
|
||||||
voted: boolean;
|
voted: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface PollOption {
|
export interface APIPollOption {
|
||||||
title: string;
|
title: string;
|
||||||
votes_count: number | null;
|
votes_count: number | null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Preferences {
|
export interface APIPreferences {
|
||||||
"posting:default:visibility": "public" | "unlisted" | "private" | "direct";
|
"posting:default:visibility": "public" | "unlisted" | "private" | "direct";
|
||||||
"posting:default:sensitive": boolean;
|
"posting:default:sensitive": boolean;
|
||||||
"posting:default:language": string | null;
|
"posting:default:language": string | null;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Alerts {
|
export interface APIAlerts {
|
||||||
follow: boolean;
|
follow: boolean;
|
||||||
favourite: boolean;
|
favourite: boolean;
|
||||||
mention: boolean;
|
mention: boolean;
|
||||||
|
|
@ -6,9 +6,9 @@ export interface Alerts {
|
||||||
poll: boolean;
|
poll: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PushSubscription {
|
export interface APIPushSubscription {
|
||||||
id: string;
|
id: string;
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
server_key: string;
|
server_key: string;
|
||||||
alerts: Alerts;
|
alerts: APIAlerts;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Relationship {
|
export interface APIRelationship {
|
||||||
id: string;
|
id: string;
|
||||||
following: boolean;
|
following: boolean;
|
||||||
followed_by: boolean;
|
followed_by: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
import { Account } from "./account";
|
import { APIAccount } from "./account";
|
||||||
|
|
||||||
export interface Report {
|
export interface APIReport {
|
||||||
id: string;
|
id: string;
|
||||||
action_taken: boolean;
|
action_taken: boolean;
|
||||||
action_taken_at: string | null;
|
action_taken_at: string | null;
|
||||||
category: Category;
|
category: APICategory;
|
||||||
comment: string;
|
comment: string;
|
||||||
forwarded: boolean;
|
forwarded: boolean;
|
||||||
status_ids: string[] | null;
|
status_ids: string[] | null;
|
||||||
rule_ids: string[] | null;
|
rule_ids: string[] | null;
|
||||||
target_account: Account;
|
target_account: APIAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Category = "spam" | "violation" | "other";
|
export type APICategory = "spam" | "violation" | "other";
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Account } from "./account";
|
import { APIAccount } from "./account";
|
||||||
import { Status } from "./status";
|
import { APIStatus } from "./status";
|
||||||
import { Tag } from "./tag";
|
import { APITag } from "./tag";
|
||||||
|
|
||||||
export interface Results {
|
export interface APIResults {
|
||||||
accounts: Account[];
|
accounts: APIAccount[];
|
||||||
statuses: Status[];
|
statuses: APIStatus[];
|
||||||
hashtags: Tag[];
|
hashtags: APITag[];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
export interface Role {
|
export interface APIRole {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Attachment } from "./attachment";
|
import { APIAttachment } from "./attachment";
|
||||||
import { StatusParams } from "./status_params";
|
import { APIStatusParams } from "./status_params";
|
||||||
|
|
||||||
export interface ScheduledStatus {
|
export interface APIScheduledStatus {
|
||||||
id: string;
|
id: string;
|
||||||
scheduled_at: string;
|
scheduled_at: string;
|
||||||
params: StatusParams;
|
params: APIStatusParams;
|
||||||
media_attachments: Attachment[];
|
media_attachments: APIAttachment[];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Field } from "./field";
|
import { APIField } from "./field";
|
||||||
|
|
||||||
export interface Source {
|
export interface APISource {
|
||||||
privacy: string | null;
|
privacy: string | null;
|
||||||
sensitive: boolean | null;
|
sensitive: boolean | null;
|
||||||
language: string | null;
|
language: string | null;
|
||||||
note: string;
|
note: string;
|
||||||
fields: Field[];
|
fields: APIField[];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Stats {
|
export interface APIStats {
|
||||||
user_count: number;
|
user_count: number;
|
||||||
status_count: number;
|
status_count: number;
|
||||||
domain_count: number;
|
domain_count: number;
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
import { Account } from "./account";
|
import { APIAccount } from "./account";
|
||||||
import { Application } from "./application";
|
import { APIApplication } from "./application";
|
||||||
import { Attachment } from "./attachment";
|
import { APIAttachment } from "./attachment";
|
||||||
import { Card } from "./card";
|
import { APICard } from "./card";
|
||||||
import { Emoji } from "./emoji";
|
import { APIEmoji } from "./emoji";
|
||||||
import { Mention } from "./mention";
|
import { APIMention } from "./mention";
|
||||||
import { Poll } from "./poll";
|
import { APIPoll } from "./poll";
|
||||||
|
|
||||||
export interface Status {
|
export interface APIStatus {
|
||||||
id: string;
|
id: string;
|
||||||
uri: string;
|
uri: string;
|
||||||
url: string;
|
url: string;
|
||||||
account: Account;
|
account: APIAccount;
|
||||||
in_reply_to_id: string | null;
|
in_reply_to_id: string | null;
|
||||||
in_reply_to_account_id: string | null;
|
in_reply_to_account_id: string | null;
|
||||||
reblog: Status | null;
|
reblog: APIStatus | null;
|
||||||
content: string;
|
content: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
emojis: Emoji[];
|
emojis: APIEmoji[];
|
||||||
replies_count: number;
|
replies_count: number;
|
||||||
reblogs_count: number;
|
reblogs_count: number;
|
||||||
favourites_count: number;
|
favourites_count: number;
|
||||||
|
|
@ -26,21 +26,21 @@ export interface Status {
|
||||||
sensitive: boolean;
|
sensitive: boolean;
|
||||||
spoiler_text: string;
|
spoiler_text: string;
|
||||||
visibility: "public" | "unlisted" | "private" | "direct";
|
visibility: "public" | "unlisted" | "private" | "direct";
|
||||||
media_attachments: Attachment[];
|
media_attachments: APIAttachment[];
|
||||||
mentions: Mention[];
|
mentions: APIMention[];
|
||||||
tags: StatusTag[];
|
tags: APIStatusTag[];
|
||||||
card: Card | null;
|
card: APICard | null;
|
||||||
poll: Poll | null;
|
poll: APIPoll | null;
|
||||||
application: Application | null;
|
application: APIApplication | null;
|
||||||
language: string | null;
|
language: string | null;
|
||||||
pinned: boolean | null;
|
pinned: boolean | null;
|
||||||
bookmarked?: boolean;
|
bookmarked?: boolean;
|
||||||
// These parameters are unique parameters in fedibird.com for quote.
|
// These parameters are unique parameters in fedibird.com for quote.
|
||||||
quote_id?: string;
|
quote_id?: string;
|
||||||
quote?: Status | null;
|
quote?: APIStatus | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StatusTag {
|
export interface APIStatusTag {
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface StatusParams {
|
export interface APIStatusParams {
|
||||||
text: string;
|
text: string;
|
||||||
in_reply_to_id: string | null;
|
in_reply_to_id: string | null;
|
||||||
media_ids: string[] | null;
|
media_ids: string[] | null;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface StatusSource {
|
export interface APIStatusSource {
|
||||||
id: string;
|
id: string;
|
||||||
text: string;
|
text: string;
|
||||||
spoiler_text: string;
|
spoiler_text: string;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { History } from "./history";
|
import { APIHistory } from "./history";
|
||||||
|
|
||||||
export interface Tag {
|
export interface APITag {
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url: string;
|
||||||
history: History[];
|
history: APIHistory[];
|
||||||
following?: boolean;
|
following?: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export interface Token {
|
export interface APIToken {
|
||||||
access_token: string;
|
access_token: string;
|
||||||
token_type: string;
|
token_type: string;
|
||||||
scope: string;
|
scope: string;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
export interface URLs {
|
export interface APIURLs {
|
||||||
streaming_api: string;
|
streaming_api: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
0
types/entity.ts
Normal file
0
types/entity.ts
Normal file
|
|
@ -5,4 +5,10 @@ export const jsonResponse = (data: object, status = 200) => {
|
||||||
},
|
},
|
||||||
status,
|
status,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const errorResponse = (error: string, status = 500) => {
|
||||||
|
return jsonResponse({
|
||||||
|
error: error
|
||||||
|
}, status);
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue