Implement WebFinger, rework TS

This commit is contained in:
Jesse Wierzbinski 2023-09-12 10:48:10 -10:00
parent 29f63dfcb7
commit c573052450
No known key found for this signature in database
GPG key ID: F9A1E418934E40B0
56 changed files with 560 additions and 239 deletions

View 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,
}
}
}

View file

@ -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,
};
}
}

View 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,
}
}
}

View 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;
}

View 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,
};
}
}

View 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;
}

View 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
View 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,
};
}
}

View file

@ -1,13 +1,16 @@
import { getConfig, getHost } from "@config";
import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
import { Account } from "~types/entities/account";
import { APIAccount } from "~types/entities/account";
const config = getConfig();
/**
* Stores local and remote users
*/
@Entity({
name: "users",
})
export class DBUser extends BaseEntity {
export class User extends BaseEntity {
@PrimaryGeneratedColumn("uuid")
id!: string;
@ -16,8 +19,10 @@ export class DBUser extends BaseEntity {
})
username!: string;
@Column("varchar")
password!: string;
@Column("varchar", {
nullable: true,
})
password!: string | null;
@Column("varchar", {
unique: true,
@ -35,7 +40,11 @@ export class DBUser extends BaseEntity {
@UpdateDateColumn()
updated_at!: Date;
toAPI(): Account {
@Column("boolean")
isRemote!: boolean;
// eslint-disable-next-line @typescript-eslint/require-await
async toAPI(): Promise<APIAccount> {
return {
acct: `@${this.username}@${getHost()}`,
avatar: "",