From 436a79d99f7bdb252eecf75657dbcc0185983d33 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sun, 10 Sep 2023 17:31:08 -1000 Subject: [PATCH] Initial commit --- .eslintrc.js | 7 ++ .gitignore | 170 +++++++++++++++++++++++++++ README.md | 15 +++ bun.lockb | Bin 0 -> 71225 bytes database/datasource.ts | 17 +++ database/entities/User.ts | 21 ++++ index.ts | 23 ++++ package.json | 17 +++ server/api/v1/accounts/[id]/index.ts | 26 ++++ tsconfig.json | 30 +++++ types/entities/account.ts | 34 ++++++ types/entities/activity.ts | 6 + types/entities/announcement.ts | 39 ++++++ types/entities/application.ts | 5 + types/entities/async_attachment.ts | 13 ++ types/entities/attachment.ts | 47 ++++++++ types/entities/card.ts | 16 +++ types/entities/context.ts | 6 + types/entities/conversation.ts | 9 ++ types/entities/emoji.ts | 7 ++ types/entities/featured_tag.ts | 6 + types/entities/field.ts | 5 + types/entities/filter.ts | 10 ++ types/entities/history.ts | 5 + types/entities/identity_proof.ts | 7 ++ types/entities/instance.ts | 47 ++++++++ types/entities/list.ts | 7 ++ types/entities/marker.ts | 12 ++ types/entities/mention.ts | 6 + types/entities/notification.ts | 14 +++ types/entities/poll.ts | 11 ++ types/entities/poll_option.ts | 4 + types/entities/preferences.ts | 7 ++ types/entities/push_subscription.ts | 14 +++ types/entities/relationship.ts | 16 +++ types/entities/report.ts | 15 +++ types/entities/results.ts | 9 ++ types/entities/role.ts | 3 + types/entities/scheduled_status.ts | 9 ++ types/entities/source.ts | 9 ++ types/entities/stats.ts | 5 + types/entities/status.ts | 46 ++++++++ types/entities/status_params.ts | 10 ++ types/entities/status_source.ts | 5 + types/entities/tag.ts | 8 ++ types/entities/token.ts | 6 + types/entities/urls.ts | 3 + types/entity.ts | 39 ++++++ utils/config.ts | 16 +++ utils/response.ts | 8 ++ 50 files changed, 870 insertions(+) create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 README.md create mode 100755 bun.lockb create mode 100644 database/datasource.ts create mode 100644 database/entities/User.ts create mode 100644 index.ts create mode 100644 package.json create mode 100644 server/api/v1/accounts/[id]/index.ts create mode 100644 tsconfig.json create mode 100644 types/entities/account.ts create mode 100644 types/entities/activity.ts create mode 100644 types/entities/announcement.ts create mode 100644 types/entities/application.ts create mode 100644 types/entities/async_attachment.ts create mode 100644 types/entities/attachment.ts create mode 100644 types/entities/card.ts create mode 100644 types/entities/context.ts create mode 100644 types/entities/conversation.ts create mode 100644 types/entities/emoji.ts create mode 100644 types/entities/featured_tag.ts create mode 100644 types/entities/field.ts create mode 100644 types/entities/filter.ts create mode 100644 types/entities/history.ts create mode 100644 types/entities/identity_proof.ts create mode 100644 types/entities/instance.ts create mode 100644 types/entities/list.ts create mode 100644 types/entities/marker.ts create mode 100644 types/entities/mention.ts create mode 100644 types/entities/notification.ts create mode 100644 types/entities/poll.ts create mode 100644 types/entities/poll_option.ts create mode 100644 types/entities/preferences.ts create mode 100644 types/entities/push_subscription.ts create mode 100644 types/entities/relationship.ts create mode 100644 types/entities/report.ts create mode 100644 types/entities/results.ts create mode 100644 types/entities/role.ts create mode 100644 types/entities/scheduled_status.ts create mode 100644 types/entities/source.ts create mode 100644 types/entities/stats.ts create mode 100644 types/entities/status.ts create mode 100644 types/entities/status_params.ts create mode 100644 types/entities/status_source.ts create mode 100644 types/entities/tag.ts create mode 100644 types/entities/token.ts create mode 100644 types/entities/urls.ts create mode 100644 types/entity.ts create mode 100644 utils/config.ts create mode 100644 utils/response.ts diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..2eae3cbc --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: [ + "eslint:strict", + "plugin:@typescript-eslint/strict-type-checked", + "plugin:@typescript-eslint/stylistic", + ], +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..3cf3b5b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,170 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +\*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +\*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +\*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +\*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.cache +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +.cache/ + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp +.cache + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.\* +config/config.toml \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..e8ecc79b --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# fedi-project + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run index.ts +``` + +This project was created using `bun init` in bun v0.8.1. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..80d18dfd82ccea5c9e97288c0d2c9498372c1335 GIT binary patch literal 71225 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 literal 0 HcmV?d00001 diff --git a/database/datasource.ts b/database/datasource.ts new file mode 100644 index 00000000..3d075861 --- /dev/null +++ b/database/datasource.ts @@ -0,0 +1,17 @@ +import { DataSource } from "typeorm"; +import { getConfig } from "../utils/config"; + +const config = getConfig(); + +const AppDataSource = new DataSource({ + type: "postgres", + host: config.database.host, + port: config.database.port, + username: config.database.username, + password: config.database.password, + database: config.database.database, + synchronize: true, + entities: ["./entities/*.ts"], +}); + +export { AppDataSource }; diff --git a/database/entities/User.ts b/database/entities/User.ts new file mode 100644 index 00000000..9e013411 --- /dev/null +++ b/database/entities/User.ts @@ -0,0 +1,21 @@ +import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm"; + +@Entity({ + name: "users", +}) +export class User extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id!: string; + + @Column("varchar") + username!: string; + + @Column("varchar") + password!: string; + + @CreateDateColumn() + created_at!: Date; + + @UpdateDateColumn() + updated_at!: Date; +} \ No newline at end of file diff --git a/index.ts b/index.ts new file mode 100644 index 00000000..c073b0e5 --- /dev/null +++ b/index.ts @@ -0,0 +1,23 @@ +const router = new Bun.FileSystemRouter({ + style: "nextjs", + dir: process.cwd() + "/server/api", +}) + +Bun.serve({ + port: 8080, + hostname: "0.0.0.0", // defaults to "0.0.0.0" + async fetch(req) { + const url = new URL(req.url); + + const matchedRoute = router.match(req); + + if (matchedRoute) { + return (await import(matchedRoute.filePath)).default(req, matchedRoute); + } else { + const response = new Response(undefined, { + status: 404, + statusText: "Route not found", + }); + } + }, +}); diff --git a/package.json b/package.json new file mode 100644 index 00000000..27596bb7 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "fedi-project", + "module": "index.ts", + "type": "module", + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^6.6.0", + "bun-types": "latest", + "eslint": "^8.49.0" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "pg": "^8.11.3", + "typeorm": "^0.3.17" + } +} \ No newline at end of file diff --git a/server/api/v1/accounts/[id]/index.ts b/server/api/v1/accounts/[id]/index.ts new file mode 100644 index 00000000..630da01c --- /dev/null +++ b/server/api/v1/accounts/[id]/index.ts @@ -0,0 +1,26 @@ +import { jsonResponse } from "@response"; +import { MatchedRoute } from "bun"; +import { User } from "~database/entities/User"; + +export default async ( + req: Request, + matchedRoute: MatchedRoute +): Promise => { + const id = matchedRoute.params.id; + + const user = await User.findOneBy({ + id, + }); + + if (!user) + return jsonResponse( + { + statusText: "User not found", + }, + 404 + ); + + return jsonResponse({ + id, + }); +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..efa87a01 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "lib": ["ESNext"], + "module": "esnext", + "target": "esnext", + "moduleResolution": "bundler", + "moduleDetection": "force", + "allowImportingTsExtensions": true, + "noEmit": true, + "composite": true, + "strict": true, + "downlevelIteration": true, + "skipLibCheck": true, + "noImplicitAny": true, + "jsx": "preserve", + "allowSyntheticDefaultImports": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "forceConsistentCasingInFileNames": true, + "allowJs": true, + "experimentalDecorators": true, + "types": [ + "bun-types" // add Bun global + ], + "paths": { + "@*": ["./utils/*"], + "~*": ["./*"] + } + } +} diff --git a/types/entities/account.ts b/types/entities/account.ts new file mode 100644 index 00000000..cf663eda --- /dev/null +++ b/types/entities/account.ts @@ -0,0 +1,34 @@ +import { Emoji } from "./emoji"; +import { Field } from "./field"; +import { Role } from "./role"; +import { Source } from "./source"; + +export type Account = { + id: string; + username: string; + acct: string; + display_name: string; + locked: boolean; + discoverable?: boolean; + group: boolean | null; + noindex: boolean | null; + suspended: boolean | null; + limited: boolean | null; + created_at: string; + followers_count: number; + following_count: number; + statuses_count: number; + note: string; + url: string; + avatar: string; + avatar_static: string; + header: string; + header_static: string; + emojis: Array; + moved: Account | null; + fields: Array; + bot: boolean; + source?: Source; + role?: Role; + mute_expires_at?: string; +}; diff --git a/types/entities/activity.ts b/types/entities/activity.ts new file mode 100644 index 00000000..47647ffd --- /dev/null +++ b/types/entities/activity.ts @@ -0,0 +1,6 @@ +export type Activity = { + week: string; + statuses: string; + logins: string; + registrations: string; +}; diff --git a/types/entities/announcement.ts b/types/entities/announcement.ts new file mode 100644 index 00000000..d954ff82 --- /dev/null +++ b/types/entities/announcement.ts @@ -0,0 +1,39 @@ +import { Emoji } from "./emoji"; +import { StatusTag } from "./status"; + +export type Announcement = { + id: string; + content: string; + starts_at: string | null; + ends_at: string | null; + published: boolean; + all_day: boolean; + published_at: string; + updated_at: string; + read: boolean | null; + mentions: Array; + statuses: Array; + tags: Array; + emojis: Array; + reactions: Array; +}; + +export type AnnouncementAccount = { + id: string; + username: string; + url: string; + acct: string; +}; + +export type AnnouncementStatus = { + id: string; + url: string; +}; + +export type AnnouncementReaction = { + name: string; + count: number; + me: boolean | null; + url: string | null; + static_url: string | null; +}; diff --git a/types/entities/application.ts b/types/entities/application.ts new file mode 100644 index 00000000..0d17d205 --- /dev/null +++ b/types/entities/application.ts @@ -0,0 +1,5 @@ +export type Application = { + name: string; + website?: string | null; + vapid_key?: string | null; +}; diff --git a/types/entities/async_attachment.ts b/types/entities/async_attachment.ts new file mode 100644 index 00000000..f822ab08 --- /dev/null +++ b/types/entities/async_attachment.ts @@ -0,0 +1,13 @@ +import { Meta } from "./attachment"; + +export type AsyncAttachment = { + id: string; + type: "unknown" | "image" | "gifv" | "video" | "audio"; + url: string | null; + remote_url: string | null; + preview_url: string; + text_url: string | null; + meta: Meta | null; + description: string | null; + blurhash: string | null; +}; diff --git a/types/entities/attachment.ts b/types/entities/attachment.ts new file mode 100644 index 00000000..e7c40115 --- /dev/null +++ b/types/entities/attachment.ts @@ -0,0 +1,47 @@ +export type Sub = { + // For Image, Gifv, and Video + width?: number; + height?: number; + size?: string; + aspect?: number; + + // For Gifv and Video + frame_rate?: string; + + // For Audio, Gifv, and Video + duration?: number; + bitrate?: number; +}; + +export type Focus = { + x: number; + y: number; +}; + +export type Meta = { + original?: Sub; + small?: Sub; + focus?: Focus; + length?: string; + duration?: number; + fps?: number; + size?: string; + width?: number; + height?: number; + aspect?: number; + audio_encode?: string; + audio_bitrate?: string; + audio_channel?: string; +}; + +export type Attachment = { + id: string; + type: "unknown" | "image" | "gifv" | "video" | "audio"; + url: string; + remote_url: string | null; + preview_url: string | null; + text_url: string | null; + meta: Meta | null; + description: string | null; + blurhash: string | null; +}; diff --git a/types/entities/card.ts b/types/entities/card.ts new file mode 100644 index 00000000..f6513a71 --- /dev/null +++ b/types/entities/card.ts @@ -0,0 +1,16 @@ +export type Card = { + url: string; + title: string; + description: string; + type: "link" | "photo" | "video" | "rich"; + image: string | null; + author_name: string; + author_url: string; + provider_name: string; + provider_url: string; + html: string; + width: number; + height: number; + embed_url: string; + blurhash: string | null; +}; diff --git a/types/entities/context.ts b/types/entities/context.ts new file mode 100644 index 00000000..623a11e0 --- /dev/null +++ b/types/entities/context.ts @@ -0,0 +1,6 @@ +import { Status } from "./status"; + +export type Context = { + ancestors: Array; + descendants: Array; +}; diff --git a/types/entities/conversation.ts b/types/entities/conversation.ts new file mode 100644 index 00000000..fd372f43 --- /dev/null +++ b/types/entities/conversation.ts @@ -0,0 +1,9 @@ +import { Account } from "./account"; +import { Status } from "./status"; + +export type Conversation = { + id: string; + accounts: Array; + last_status: Status | null; + unread: boolean; +}; diff --git a/types/entities/emoji.ts b/types/entities/emoji.ts new file mode 100644 index 00000000..d41b2ab5 --- /dev/null +++ b/types/entities/emoji.ts @@ -0,0 +1,7 @@ +export type Emoji = { + shortcode: string; + static_url: string; + url: string; + visible_in_picker: boolean; + category?: string; +}; diff --git a/types/entities/featured_tag.ts b/types/entities/featured_tag.ts new file mode 100644 index 00000000..b3479069 --- /dev/null +++ b/types/entities/featured_tag.ts @@ -0,0 +1,6 @@ +export type FeaturedTag = { + id: string; + name: string; + statuses_count: number; + last_status_at: string; +}; diff --git a/types/entities/field.ts b/types/entities/field.ts new file mode 100644 index 00000000..44664c08 --- /dev/null +++ b/types/entities/field.ts @@ -0,0 +1,5 @@ +export type Field = { + name: string; + value: string; + verified_at: string | null; +}; diff --git a/types/entities/filter.ts b/types/entities/filter.ts new file mode 100644 index 00000000..8e68343c --- /dev/null +++ b/types/entities/filter.ts @@ -0,0 +1,10 @@ +export type Filter = { + id: string; + phrase: string; + context: Array; + expires_at: string | null; + irreversible: boolean; + whole_word: boolean; +}; + +export type FilterContext = string; diff --git a/types/entities/history.ts b/types/entities/history.ts new file mode 100644 index 00000000..442e6dc7 --- /dev/null +++ b/types/entities/history.ts @@ -0,0 +1,5 @@ +export type History = { + day: string; + uses: number; + accounts: number; +}; diff --git a/types/entities/identity_proof.ts b/types/entities/identity_proof.ts new file mode 100644 index 00000000..bdf601af --- /dev/null +++ b/types/entities/identity_proof.ts @@ -0,0 +1,7 @@ +export type IdentityProof = { + provider: string; + provider_username: string; + updated_at: string; + proof_url: string; + profile_url: string; +}; diff --git a/types/entities/instance.ts b/types/entities/instance.ts new file mode 100644 index 00000000..e3e91ef3 --- /dev/null +++ b/types/entities/instance.ts @@ -0,0 +1,47 @@ +import { Account } from "./account"; +import { Stats } from "./stats"; +import { URLs } from "./urls"; + +export type Instance = { + uri: string; + title: string; + description: string; + email: string; + version: string; + thumbnail: string | null; + urls: URLs; + stats: Stats; + languages: Array; + registrations: boolean; + approval_required: boolean; + invites_enabled: boolean; + max_toot_chars?: number; + configuration: { + statuses: { + max_characters: number; + max_media_attachments: number; + characters_reserved_per_url: number; + }; + media_attachments: { + supported_mime_types: Array; + image_size_limit: number; + image_matrix_limit: number; + video_size_limit: number; + video_frame_limit: number; + video_matrix_limit: number; + }; + polls: { + max_options: number; + max_characters_per_option: number; + min_expiration: number; + max_expiration: number; + }; + }; + contact_account: Account; + rules: Array; +}; + +export type InstanceRule = { + id: string; + text: string; +}; diff --git a/types/entities/list.ts b/types/entities/list.ts new file mode 100644 index 00000000..b3119da1 --- /dev/null +++ b/types/entities/list.ts @@ -0,0 +1,7 @@ +export type List = { + id: string; + title: string; + replies_policy: RepliesPolicy; +}; + +export type RepliesPolicy = "followed" | "list" | "none"; diff --git a/types/entities/marker.ts b/types/entities/marker.ts new file mode 100644 index 00000000..01c4118f --- /dev/null +++ b/types/entities/marker.ts @@ -0,0 +1,12 @@ +export type Marker = { + home: { + last_read_id: string; + version: number; + updated_at: string; + }; + notifications: { + last_read_id: string; + version: number; + updated_at: string; + }; +}; diff --git a/types/entities/mention.ts b/types/entities/mention.ts new file mode 100644 index 00000000..496e6d0d --- /dev/null +++ b/types/entities/mention.ts @@ -0,0 +1,6 @@ +export type Mention = { + id: string; + username: string; + url: string; + acct: string; +}; diff --git a/types/entities/notification.ts b/types/entities/notification.ts new file mode 100644 index 00000000..860acd24 --- /dev/null +++ b/types/entities/notification.ts @@ -0,0 +1,14 @@ +import { Account } from "./account" +import { Status } from "./status" + +namespace MastodonEntity { + export type Notification = { + account: Account + created_at: string + id: string + status?: Status + type: NotificationType + } + + export type NotificationType = string +} diff --git a/types/entities/poll.ts b/types/entities/poll.ts new file mode 100644 index 00000000..29e5f6e0 --- /dev/null +++ b/types/entities/poll.ts @@ -0,0 +1,11 @@ +import { PollOption } from "./poll_option"; + +export type Poll = { + id: string; + expires_at: string | null; + expired: boolean; + multiple: boolean; + votes_count: number; + options: Array; + voted: boolean; +}; diff --git a/types/entities/poll_option.ts b/types/entities/poll_option.ts new file mode 100644 index 00000000..36230998 --- /dev/null +++ b/types/entities/poll_option.ts @@ -0,0 +1,4 @@ +export type PollOption = { + title: string; + votes_count: number | null; +}; diff --git a/types/entities/preferences.ts b/types/entities/preferences.ts new file mode 100644 index 00000000..44b1f0a1 --- /dev/null +++ b/types/entities/preferences.ts @@ -0,0 +1,7 @@ +export type Preferences = { + "posting:default:visibility": "public" | "unlisted" | "private" | "direct"; + "posting:default:sensitive": boolean; + "posting:default:language": string | null; + "reading:expand:media": "default" | "show_all" | "hide_all"; + "reading:expand:spoilers": boolean; +}; diff --git a/types/entities/push_subscription.ts b/types/entities/push_subscription.ts new file mode 100644 index 00000000..e5df43c3 --- /dev/null +++ b/types/entities/push_subscription.ts @@ -0,0 +1,14 @@ +export type Alerts = { + follow: boolean; + favourite: boolean; + mention: boolean; + reblog: boolean; + poll: boolean; +}; + +export type PushSubscription = { + id: string; + endpoint: string; + server_key: string; + alerts: Alerts; +}; diff --git a/types/entities/relationship.ts b/types/entities/relationship.ts new file mode 100644 index 00000000..bcc6cf99 --- /dev/null +++ b/types/entities/relationship.ts @@ -0,0 +1,16 @@ +export type Relationship = { + id: string; + following: boolean; + followed_by: boolean; + blocking: boolean; + blocked_by: boolean; + muting: boolean; + muting_notifications: boolean; + requested: boolean; + domain_blocking: boolean; + showing_reblogs: boolean; + endorsed: boolean; + notifying: boolean; + note: string; + languages: Array; +}; diff --git a/types/entities/report.ts b/types/entities/report.ts new file mode 100644 index 00000000..e1ef7641 --- /dev/null +++ b/types/entities/report.ts @@ -0,0 +1,15 @@ +import { Account } from "./account"; + +export type Report = { + id: string; + action_taken: boolean; + action_taken_at: string | null; + category: Category; + comment: string; + forwarded: boolean; + status_ids: Array | null; + rule_ids: Array | null; + target_account: Account; +}; + +export type Category = "spam" | "violation" | "other"; diff --git a/types/entities/results.ts b/types/entities/results.ts new file mode 100644 index 00000000..42cd4c09 --- /dev/null +++ b/types/entities/results.ts @@ -0,0 +1,9 @@ +import { Account } from "./account"; +import { Status } from "./status"; +import { Tag } from "./tag"; + +export type Results = { + accounts: Array; + statuses: Array; + hashtags: Array; +}; diff --git a/types/entities/role.ts b/types/entities/role.ts new file mode 100644 index 00000000..85251115 --- /dev/null +++ b/types/entities/role.ts @@ -0,0 +1,3 @@ +export type Role = { + name: string; +}; diff --git a/types/entities/scheduled_status.ts b/types/entities/scheduled_status.ts new file mode 100644 index 00000000..1e4d9b7b --- /dev/null +++ b/types/entities/scheduled_status.ts @@ -0,0 +1,9 @@ +import { Attachment } from "./attachment"; +import { StatusParams } from "./status_params"; + +export type ScheduledStatus = { + id: string; + scheduled_at: string; + params: StatusParams; + media_attachments: Array; +}; diff --git a/types/entities/source.ts b/types/entities/source.ts new file mode 100644 index 00000000..e8352d65 --- /dev/null +++ b/types/entities/source.ts @@ -0,0 +1,9 @@ +import { Field } from "./field"; + +export type Source = { + privacy: string | null; + sensitive: boolean | null; + language: string | null; + note: string; + fields: Array; +}; diff --git a/types/entities/stats.ts b/types/entities/stats.ts new file mode 100644 index 00000000..3baf0639 --- /dev/null +++ b/types/entities/stats.ts @@ -0,0 +1,5 @@ +export type Stats = { + user_count: number; + status_count: number; + domain_count: number; +}; diff --git a/types/entities/status.ts b/types/entities/status.ts new file mode 100644 index 00000000..6c1e60d8 --- /dev/null +++ b/types/entities/status.ts @@ -0,0 +1,46 @@ +import { Account } from "./account"; +import { Application } from "./application"; +import { Attachment } from "./attachment"; +import { Card } from "./card"; +import { Emoji } from "./emoji"; +import { Mention } from "./mention"; +import { Poll } from "./poll"; + +export type Status = { + id: string; + uri: string; + url: string; + account: Account; + in_reply_to_id: string | null; + in_reply_to_account_id: string | null; + reblog: Status | null; + content: string; + created_at: string; + emojis: Emoji[]; + replies_count: number; + reblogs_count: number; + favourites_count: number; + reblogged: boolean | null; + favourited: boolean | null; + muted: boolean | null; + sensitive: boolean; + spoiler_text: string; + visibility: "public" | "unlisted" | "private" | "direct"; + media_attachments: Array; + mentions: Array; + tags: Array; + card: Card | null; + poll: Poll | null; + application: Application | null; + language: string | null; + pinned: boolean | null; + bookmarked?: boolean; + // These parameters are unique parameters in fedibird.com for quote. + quote_id?: string; + quote?: Status | null; +}; + +export type StatusTag = { + name: string; + url: string; +}; diff --git a/types/entities/status_params.ts b/types/entities/status_params.ts new file mode 100644 index 00000000..5b638efe --- /dev/null +++ b/types/entities/status_params.ts @@ -0,0 +1,10 @@ +export type StatusParams = { + text: string; + in_reply_to_id: string | null; + media_ids: Array | null; + sensitive: boolean | null; + spoiler_text: string | null; + visibility: "public" | "unlisted" | "private" | "direct" | null; + scheduled_at: string | null; + application_id: number; +}; diff --git a/types/entities/status_source.ts b/types/entities/status_source.ts new file mode 100644 index 00000000..82fea66d --- /dev/null +++ b/types/entities/status_source.ts @@ -0,0 +1,5 @@ +export type StatusSource = { + id: string; + text: string; + spoiler_text: string; +}; diff --git a/types/entities/tag.ts b/types/entities/tag.ts new file mode 100644 index 00000000..59db622f --- /dev/null +++ b/types/entities/tag.ts @@ -0,0 +1,8 @@ +import { History } from "./history"; + +export type Tag = { + name: string; + url: string; + history: Array; + following?: boolean; +}; diff --git a/types/entities/token.ts b/types/entities/token.ts new file mode 100644 index 00000000..cbe9e0a0 --- /dev/null +++ b/types/entities/token.ts @@ -0,0 +1,6 @@ +export type Token = { + access_token: string; + token_type: string; + scope: string; + created_at: number; +}; diff --git a/types/entities/urls.ts b/types/entities/urls.ts new file mode 100644 index 00000000..3c28faea --- /dev/null +++ b/types/entities/urls.ts @@ -0,0 +1,3 @@ +export type URLs = { + streaming_api: string; +}; diff --git a/types/entity.ts b/types/entity.ts new file mode 100644 index 00000000..dcafdfe7 --- /dev/null +++ b/types/entity.ts @@ -0,0 +1,39 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// + +export default MastodonEntity diff --git a/utils/config.ts b/utils/config.ts new file mode 100644 index 00000000..f8f13eac --- /dev/null +++ b/utils/config.ts @@ -0,0 +1,16 @@ +import data from "../config/config.toml"; + +export type ConfigType = { + database: { + host: string; + port: number; + username: string; + password: string; + database: string; + } + [ key: string ]: any; +} + +export const getConfig = () => { + return data as ConfigType; +} \ No newline at end of file diff --git a/utils/response.ts b/utils/response.ts new file mode 100644 index 00000000..1a961acf --- /dev/null +++ b/utils/response.ts @@ -0,0 +1,8 @@ +export const jsonResponse = (data: object, status: number = 200) => { + return new Response(JSON.stringify(data), { + headers: { + "Content-Type": "application/json" + }, + status, + }); +} \ No newline at end of file