mirror of
https://github.com/modrinth/code.git
synced 2026-08-31 03:55:59 +00:00
Merge remote-tracking branch 'origin/main' into cal/hosting-server-instances
# Conflicts: # apps/app-frontend/src/pages/Browse.vue # apps/app-frontend/src/pages/hosting/manage/Index.vue # apps/app-frontend/src/pages/instance/Index.vue # apps/app-frontend/src/pages/project/Index.vue # apps/app-frontend/src/routes.js # apps/frontend/src/locales/en-US/index.json # apps/frontend/src/middleware/project.global.ts # apps/frontend/src/pages/[type]/[project].vue # apps/frontend/src/pages/discover/[type]/index.vue # apps/frontend/src/pages/organization/[organization].vue # apps/frontend/src/pages/user/[user].vue # packages/ui/src/components/base/FloatingActionBar.vue # packages/ui/src/components/base/PageHeader.vue # packages/ui/src/components/base/StackedAdmonitions.vue # packages/ui/src/components/base/TeleportOverflowMenu.vue # packages/ui/src/components/base/index.ts # packages/ui/src/components/project/ProjectHeader.vue # packages/ui/src/components/servers/server-header/ServerManageHeader.vue # packages/ui/src/components/servers/server-header/index.ts # packages/ui/src/composables/index.ts # packages/ui/src/layouts/shared/browse-tab/composables/use-browse-search.ts # packages/ui/src/layouts/shared/browse-tab/header.vue # packages/ui/src/layouts/shared/browse-tab/layout.vue # packages/ui/src/layouts/shared/content-tab/components/ContentModpackCard.vue # packages/ui/src/layouts/shared/content-tab/layout.vue # packages/ui/src/layouts/shared/installation-settings/components/ContentDiffModal.vue # packages/ui/src/layouts/shared/installation-settings/providers/installation-settings.ts # packages/ui/src/layouts/wrapped/hosting/manage/[id]/index.vue # packages/ui/src/locales/cs-CZ/index.json # packages/ui/src/locales/de-CH/index.json # packages/ui/src/locales/de-DE/index.json # packages/ui/src/locales/es-419/index.json # packages/ui/src/locales/es-ES/index.json # packages/ui/src/locales/fr-FR/index.json # packages/ui/src/locales/hu-HU/index.json # packages/ui/src/locales/id-ID/index.json # packages/ui/src/locales/it-IT/index.json # packages/ui/src/locales/ja-JP/index.json # packages/ui/src/locales/ko-KR/index.json # packages/ui/src/locales/ms-MY/index.json # packages/ui/src/locales/nl-NL/index.json # packages/ui/src/locales/pl-PL/index.json # packages/ui/src/locales/pt-BR/index.json # packages/ui/src/locales/ru-RU/index.json # packages/ui/src/locales/sv-SE/index.json # packages/ui/src/locales/tr-TR/index.json # packages/ui/src/locales/uk-UA/index.json # packages/ui/src/locales/vi-VN/index.json # packages/ui/src/locales/zh-CN/index.json # packages/ui/src/locales/zh-TW/index.json # packages/ui/src/stories/base/PageHeader.stories.ts # packages/ui/src/utils/file-extensions.ts
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import { build } from 'esbuild'
|
||||
import dts from 'unplugin-dts/esbuild'
|
||||
|
||||
await build({
|
||||
entryPoints: ['src/index.ts'],
|
||||
outdir: 'dist',
|
||||
entryNames: '[name]',
|
||||
bundle: true,
|
||||
format: 'esm',
|
||||
platform: 'neutral',
|
||||
target: 'es2020',
|
||||
minify: true,
|
||||
sourcemap: true,
|
||||
legalComments: 'none',
|
||||
external: ['ofetch', 'mitt', '@tauri-apps/plugin-http'],
|
||||
plugins: [
|
||||
dts({
|
||||
bundleTypes: true,
|
||||
outDirs: 'dist',
|
||||
processor: 'ts',
|
||||
tsconfigPath: './tsconfig.build.json',
|
||||
}),
|
||||
],
|
||||
})
|
||||
@@ -34,7 +34,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "node --eval \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
||||
"build": "pnpm run clean && esbuild src/index.ts --bundle --format=esm --platform=neutral --target=es2020 --minify --legal-comments=none --outfile=dist/index.js --external:ofetch --external:mitt --external:@tauri-apps/plugin-http && tsc -p tsconfig.build.json",
|
||||
"build": "pnpm run clean && node esbuild.config.mjs",
|
||||
"prepare": "pnpm run build",
|
||||
"lint": "eslint . && prettier --check .",
|
||||
"fix": "eslint . --fix && prettier --write ."
|
||||
@@ -44,10 +44,12 @@
|
||||
"ofetch": "^1.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/api-extractor": "^7.58.9",
|
||||
"@modrinth/tooling-config": "workspace:*",
|
||||
"@tauri-apps/plugin-http": "^2.0.0",
|
||||
"esbuild": "0.27.2",
|
||||
"typescript": "^5.9.3"
|
||||
"typescript": "^5.9.3",
|
||||
"unplugin-dts": "^1.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tauri-apps/plugin-http": "^2.0.0"
|
||||
|
||||
@@ -43,6 +43,7 @@ export abstract class AbstractModrinthClient extends AbstractUploadClient {
|
||||
public readonly launchermeta!: InferredClientModules['launchermeta']
|
||||
public readonly paper!: InferredClientModules['paper']
|
||||
public readonly purpur!: InferredClientModules['purpur']
|
||||
public readonly sharedinstances!: InferredClientModules['sharedinstances']
|
||||
|
||||
constructor(config: ClientConfig) {
|
||||
super()
|
||||
@@ -50,6 +51,7 @@ export abstract class AbstractModrinthClient extends AbstractUploadClient {
|
||||
timeout: 10000,
|
||||
labrinthBaseUrl: 'https://api.modrinth.com',
|
||||
archonBaseUrl: 'https://archon.modrinth.com',
|
||||
sharedInstancesBaseUrl: 'https://shared-instances.modrinth.com',
|
||||
...config,
|
||||
}
|
||||
this.features = config.features ?? []
|
||||
@@ -123,6 +125,8 @@ export abstract class AbstractModrinthClient extends AbstractUploadClient {
|
||||
baseUrl = this.resolveBaseUrl(this.config.labrinthBaseUrl!)
|
||||
} else if (options.api === 'archon') {
|
||||
baseUrl = this.resolveBaseUrl(this.config.archonBaseUrl!)
|
||||
} else if (options.api === 'sharedinstances') {
|
||||
baseUrl = this.resolveBaseUrl(this.config.sharedInstancesBaseUrl!)
|
||||
} else {
|
||||
baseUrl = options.api
|
||||
}
|
||||
@@ -170,6 +174,8 @@ export abstract class AbstractModrinthClient extends AbstractUploadClient {
|
||||
baseUrl = this.resolveBaseUrl(this.config.labrinthBaseUrl!)
|
||||
} else if (options.api === 'archon') {
|
||||
baseUrl = this.resolveBaseUrl(this.config.archonBaseUrl!)
|
||||
} else if (options.api === 'sharedinstances') {
|
||||
baseUrl = this.resolveBaseUrl(this.config.sharedInstancesBaseUrl!)
|
||||
} else {
|
||||
baseUrl = options.api
|
||||
}
|
||||
|
||||
@@ -19,11 +19,14 @@ import { KyrosLogsV1Module } from './kyros/logs/v1'
|
||||
import { KyrosUploadSessionsV1Module } from './kyros/upload-sessions/v1'
|
||||
import { LabrinthVersionsV2Module, LabrinthVersionsV3Module } from './labrinth'
|
||||
import { LabrinthAffiliateInternalModule } from './labrinth/affiliate/internal'
|
||||
import { LabrinthAnalyticsInternalModule } from './labrinth/analytics/internal'
|
||||
import { LabrinthAnalyticsV3Module } from './labrinth/analytics/v3'
|
||||
import { LabrinthAttributionInternalModule } from './labrinth/attribution/internal'
|
||||
import { LabrinthAuthInternalModule } from './labrinth/auth/internal'
|
||||
import { LabrinthAuthV2Module } from './labrinth/auth/v2'
|
||||
import { LabrinthBillingInternalModule } from './labrinth/billing/internal'
|
||||
import { LabrinthBlockedUsersInternalModule } from './labrinth/blocked-users/internal'
|
||||
import { LabrinthBlockedUsersV3Module } from './labrinth/blocked-users/v3'
|
||||
import { LabrinthCampaignInternalModule } from './labrinth/campaign/internal'
|
||||
import { LabrinthCollectionsModule } from './labrinth/collections'
|
||||
import { LabrinthContentV3Module } from './labrinth/content/v3'
|
||||
@@ -57,6 +60,10 @@ import { MclogsInsightsV1Module } from './mclogs/insights/v1'
|
||||
import { MclogsLogsV1Module } from './mclogs/logs/v1'
|
||||
import { PaperVersionsV3Module } from './paper/v3'
|
||||
import { PurpurVersionsV2Module } from './purpur/v2'
|
||||
import { SharedInstancesInstancesV1Module } from './shared-instances/instances/v1'
|
||||
import { SharedInstancesInvitesV1Module } from './shared-instances/invites/v1'
|
||||
import { SharedInstancesModerationV1Module } from './shared-instances/moderation/v1'
|
||||
import { SharedInstancesUsersV1Module } from './shared-instances/users/v1'
|
||||
|
||||
type ModuleConstructor = new (client: AbstractModrinthClient) => AbstractModule
|
||||
|
||||
@@ -91,11 +98,14 @@ export const MODULE_REGISTRY = {
|
||||
kyros_logs_v1: KyrosLogsV1Module,
|
||||
kyros_upload_sessions_v1: KyrosUploadSessionsV1Module,
|
||||
labrinth_affiliate_internal: LabrinthAffiliateInternalModule,
|
||||
labrinth_analytics_internal: LabrinthAnalyticsInternalModule,
|
||||
labrinth_analytics_v3: LabrinthAnalyticsV3Module,
|
||||
labrinth_auth_internal: LabrinthAuthInternalModule,
|
||||
labrinth_auth_v2: LabrinthAuthV2Module,
|
||||
labrinth_attribution_internal: LabrinthAttributionInternalModule,
|
||||
labrinth_billing_internal: LabrinthBillingInternalModule,
|
||||
labrinth_blocked_users_internal: LabrinthBlockedUsersInternalModule,
|
||||
labrinth_blocked_users_v3: LabrinthBlockedUsersV3Module,
|
||||
labrinth_campaign_internal: LabrinthCampaignInternalModule,
|
||||
labrinth_collections: LabrinthCollectionsModule,
|
||||
labrinth_content_v3: LabrinthContentV3Module,
|
||||
@@ -128,6 +138,10 @@ export const MODULE_REGISTRY = {
|
||||
labrinth_versions_v3: LabrinthVersionsV3Module,
|
||||
paper_versions_v3: PaperVersionsV3Module,
|
||||
purpur_versions_v2: PurpurVersionsV2Module,
|
||||
sharedinstances_invites_v1: SharedInstancesInvitesV1Module,
|
||||
sharedinstances_instances_v1: SharedInstancesInstancesV1Module,
|
||||
sharedinstances_moderation_v1: SharedInstancesModerationV1Module,
|
||||
sharedinstances_users_v1: SharedInstancesUsersV1Module,
|
||||
} as const satisfies Record<string, ModuleConstructor>
|
||||
|
||||
export type ModuleID = keyof typeof MODULE_REGISTRY
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { AbstractModule } from '../../../core/abstract-module'
|
||||
import type { Labrinth } from '../types'
|
||||
|
||||
export class LabrinthAnalyticsInternalModule extends AbstractModule {
|
||||
public getModuleID(): string {
|
||||
return 'labrinth_analytics_internal'
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an analytics event.
|
||||
* POST /_internal/analytics-event
|
||||
*/
|
||||
public async createEvent(
|
||||
data: Labrinth.Analytics.Internal.AnalyticsEventUpsert,
|
||||
): Promise<Labrinth.Analytics.v3.AnalyticsEvent> {
|
||||
return this.client.request<Labrinth.Analytics.v3.AnalyticsEvent>('/analytics-event', {
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'POST',
|
||||
body: data,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit an analytics event.
|
||||
* PATCH /_internal/analytics-event/{id}
|
||||
*/
|
||||
public async editEvent(
|
||||
id: Labrinth.Analytics.v3.AnalyticsEventId,
|
||||
data: Labrinth.Analytics.Internal.AnalyticsEventUpsert,
|
||||
): Promise<Labrinth.Analytics.v3.AnalyticsEvent> {
|
||||
return this.client.request<Labrinth.Analytics.v3.AnalyticsEvent>(`/analytics-event/${id}`, {
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'PATCH',
|
||||
body: data,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an analytics event.
|
||||
* DELETE /_internal/analytics-event/{id}
|
||||
*/
|
||||
public async deleteEvent(id: Labrinth.Analytics.v3.AnalyticsEventId): Promise<void> {
|
||||
return this.client.request<void>(`/analytics-event/${id}`, {
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -70,47 +70,4 @@ export class LabrinthAnalyticsV3Module extends AbstractModule {
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an analytics event.
|
||||
* POST /v3/analytics-event
|
||||
*/
|
||||
public async createEvent(
|
||||
data: Labrinth.Analytics.v3.AnalyticsEventUpsert,
|
||||
): Promise<Labrinth.Analytics.v3.AnalyticsEvent> {
|
||||
return this.client.request<Labrinth.Analytics.v3.AnalyticsEvent>('/analytics-event', {
|
||||
api: 'labrinth',
|
||||
version: 3,
|
||||
method: 'POST',
|
||||
body: data,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit an analytics event.
|
||||
* PATCH /v3/analytics-event/{id}
|
||||
*/
|
||||
public async editEvent(
|
||||
id: Labrinth.Analytics.v3.AnalyticsEventId,
|
||||
data: Labrinth.Analytics.v3.AnalyticsEventUpsert,
|
||||
): Promise<Labrinth.Analytics.v3.AnalyticsEvent> {
|
||||
return this.client.request<Labrinth.Analytics.v3.AnalyticsEvent>(`/analytics-event/${id}`, {
|
||||
api: 'labrinth',
|
||||
version: 3,
|
||||
method: 'PATCH',
|
||||
body: data,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an analytics event.
|
||||
* DELETE /v3/analytics-event/{id}
|
||||
*/
|
||||
public async deleteEvent(id: Labrinth.Analytics.v3.AnalyticsEventId): Promise<void> {
|
||||
return this.client.request<void>(`/analytics-event/${id}`, {
|
||||
api: 'labrinth',
|
||||
version: 3,
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,38 @@ export class LabrinthAttributionInternalModule extends AbstractModule {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete attribution groups and all files inside them.
|
||||
* DELETE /_internal/attribution/group
|
||||
*
|
||||
* @param groupIds - The base62 attribution group ids (as returned from listProjectAttribution).
|
||||
*/
|
||||
public async deleteGroups(groupIds: string[]): Promise<void> {
|
||||
const body: Labrinth.Attribution.Internal.DeleteGroupsRequest = { groups: groupIds }
|
||||
return this.client.request<void>('/attribution/group', {
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'DELETE',
|
||||
body,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all attribution groups and files for a project.
|
||||
* DELETE /_internal/attribution/all-groups
|
||||
*/
|
||||
public async deleteAllGroups(projectId: string): Promise<void> {
|
||||
const body: Labrinth.Attribution.Internal.DeleteAllGroupsRequest = {
|
||||
project_id: projectId,
|
||||
}
|
||||
return this.client.request<void>('/attribution/all-groups', {
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'DELETE',
|
||||
body,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Reassign a file (by sha1) to another attribution group within the same project.
|
||||
* POST /_internal/attribution/assign
|
||||
@@ -100,4 +132,21 @@ export class LabrinthAttributionInternalModule extends AbstractModule {
|
||||
body,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan a file for attribution information.
|
||||
* POST /_internal/attribution/file/{file_id}/scan
|
||||
*
|
||||
* @param fileId - The file ID to scan.
|
||||
*/
|
||||
public async scanFile(fileId: string): Promise<Labrinth.Attribution.Internal.FileScanResponse> {
|
||||
return this.client.request<Labrinth.Attribution.Internal.FileScanResponse>(
|
||||
`/attribution/file/${fileId}/scan`,
|
||||
{
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'POST',
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { AbstractModule } from '../../../core/abstract-module'
|
||||
import type { Labrinth } from '../types'
|
||||
|
||||
export class LabrinthBlockedUsersInternalModule extends AbstractModule {
|
||||
public getModuleID(): string {
|
||||
return 'labrinth_blocked_users_internal'
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether one user has blocked another.
|
||||
*/
|
||||
public async getStatus(
|
||||
userId: string,
|
||||
targetId: string,
|
||||
): Promise<Labrinth.BlockedUsers.Internal.BlockStatus> {
|
||||
return this.client.request<Labrinth.BlockedUsers.Internal.BlockStatus>(
|
||||
`/block/${encodeURIComponent(userId)}/${encodeURIComponent(targetId)}`,
|
||||
{
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'GET',
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { AbstractModule } from '../../../core/abstract-module'
|
||||
import type { Labrinth } from '../types'
|
||||
|
||||
export class LabrinthBlockedUsersV3Module extends AbstractModule {
|
||||
public getModuleID(): string {
|
||||
return 'labrinth_blocked_users_v3'
|
||||
}
|
||||
|
||||
/**
|
||||
* List the users blocked by the authenticated user.
|
||||
*/
|
||||
public async list(): Promise<Labrinth.BlockedUsers.v3.BlockedUserId[]> {
|
||||
return this.client.request<Labrinth.BlockedUsers.v3.BlockedUserId[]>('/blocks', {
|
||||
api: 'labrinth',
|
||||
version: 3,
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Block a user.
|
||||
*
|
||||
* @param idOrUsername - The target user's ID or username
|
||||
*/
|
||||
public async block(idOrUsername: string): Promise<void> {
|
||||
return this.client.request(`/block/${encodeURIComponent(idOrUsername)}`, {
|
||||
api: 'labrinth',
|
||||
version: 3,
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblock a user.
|
||||
*
|
||||
* @param idOrUsername - The target user's ID or username
|
||||
*/
|
||||
public async unblock(idOrUsername: string): Promise<void> {
|
||||
return this.client.request(`/block/${encodeURIComponent(idOrUsername)}`, {
|
||||
api: 'labrinth',
|
||||
version: 3,
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ function buildImageQueryParams(
|
||||
params.thread_message_id = target.thread_message_id
|
||||
break
|
||||
case 'report':
|
||||
params.report_id = target.report_id
|
||||
if (target.report_id) params.report_id = target.report_id
|
||||
break
|
||||
}
|
||||
return params
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './analytics/internal'
|
||||
export * from './analytics/v3'
|
||||
export * from './attribution/internal'
|
||||
export * from './auth/internal'
|
||||
|
||||
@@ -6,6 +6,34 @@ export class LabrinthModerationInternalModule extends AbstractModule {
|
||||
return 'labrinth_moderation_internal'
|
||||
}
|
||||
|
||||
public async getProjects(
|
||||
params: Labrinth.Moderation.Internal.ProjectsRequest = {},
|
||||
): Promise<Labrinth.Moderation.Internal.ProjectsResponse> {
|
||||
return this.client.request<Labrinth.Moderation.Internal.ProjectsResponse>(
|
||||
'/moderation/projects',
|
||||
{
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'GET',
|
||||
params,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
public async getProjectIds(
|
||||
params: Omit<Labrinth.Moderation.Internal.ProjectsRequest, 'count' | 'offset'> = {},
|
||||
): Promise<Labrinth.Moderation.Internal.ProjectIdsResponse> {
|
||||
return this.client.request<Labrinth.Moderation.Internal.ProjectIdsResponse>(
|
||||
'/moderation/projects/ids',
|
||||
{
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'GET',
|
||||
params,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
public async acquireLock(
|
||||
projectId: string,
|
||||
): Promise<Labrinth.Moderation.Internal.LockAcquireResponse> {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { AbstractModule } from '../../../core/abstract-module'
|
||||
import type { UploadHandle } from '../../../types/upload'
|
||||
import type { Labrinth } from '../types'
|
||||
|
||||
export class LabrinthOAuthInternalModule extends AbstractModule {
|
||||
@@ -45,14 +44,15 @@ export class LabrinthOAuthInternalModule extends AbstractModule {
|
||||
* @returns Promise resolving to an array of OAuth clients
|
||||
*/
|
||||
public async getApps(ids: string[]): Promise<Labrinth.OAuth.Internal.OAuthClient[]> {
|
||||
return this.client.request<Labrinth.OAuth.Internal.OAuthClient[]>(
|
||||
`/oauth/apps?ids=${encodeURIComponent(JSON.stringify(ids))}`,
|
||||
{
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'GET',
|
||||
},
|
||||
)
|
||||
if (ids.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
// bulk `/oauth/apps` is broken on backend, fetch by id instead
|
||||
// TODO: Remove this once the backend is fixed
|
||||
const results = await Promise.all(ids.map((id) => this.getApp(id).catch(() => null)))
|
||||
|
||||
return results.filter((app): app is Labrinth.OAuth.Internal.OAuthClient => app !== null)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,14 +109,14 @@ export class LabrinthOAuthInternalModule extends AbstractModule {
|
||||
* @param id - The OAuth client ID
|
||||
* @param file - The icon file
|
||||
* @param ext - The file extension (e.g. 'png', 'jpeg')
|
||||
* @returns UploadHandle for progress tracking and cancellation
|
||||
*/
|
||||
public uploadAppIcon(id: string, file: File | Blob, ext: string): UploadHandle<void> {
|
||||
return this.client.upload<void>(`/oauth/app/${id}/icon`, {
|
||||
public async uploadAppIcon(id: string, file: File | Blob, ext: string): Promise<void> {
|
||||
return this.client.request(`/oauth/app/${id}/icon`, {
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
file,
|
||||
method: 'PATCH',
|
||||
params: { ext },
|
||||
body: file,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,30 @@ export class LabrinthProjectsV3Module extends AbstractModule {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Search projects (v3)
|
||||
*
|
||||
* @param params - Search parameters
|
||||
* @returns Promise resolving to v3 search results
|
||||
*/
|
||||
public async search(
|
||||
params: Labrinth.Search.SearchParams,
|
||||
options?: {
|
||||
headers?: Record<string, string>
|
||||
},
|
||||
): Promise<Labrinth.Search.v3.SearchResults> {
|
||||
return this.client.request<Labrinth.Search.v3.SearchResults>(`/search`, {
|
||||
api: 'labrinth',
|
||||
version: 3,
|
||||
method: 'GET',
|
||||
headers: options?.headers,
|
||||
params: {
|
||||
...params,
|
||||
facets: params.facets ? JSON.stringify(params.facets) : undefined,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a project (v3)
|
||||
*
|
||||
|
||||
@@ -100,9 +100,15 @@ export class LabrinthTechReviewInternalModule extends AbstractModule {
|
||||
*/
|
||||
public async updateIssueDetail(
|
||||
detailId: string,
|
||||
data: Labrinth.TechReview.Internal.UpdateIssueRequest,
|
||||
data: Labrinth.TechReview.Internal.UpdateIssueDetailRequest,
|
||||
): Promise<void> {
|
||||
return this.client.request<void>(`/moderation/tech-review/issue-detail/${detailId}`, {
|
||||
return this.updateIssueDetails([{ detail_id: detailId, verdict: data.verdict }])
|
||||
}
|
||||
|
||||
public async updateIssueDetails(
|
||||
data: Labrinth.TechReview.Internal.UpdateIssueRequest[],
|
||||
): Promise<void> {
|
||||
return this.client.request<void>('/moderation/tech-review/issue-detail', {
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'PATCH',
|
||||
@@ -110,6 +116,45 @@ export class LabrinthTechReviewInternalModule extends AbstractModule {
|
||||
})
|
||||
}
|
||||
|
||||
public async updateGlobalIssueDetails(
|
||||
data: Labrinth.TechReview.Internal.UpdateGlobalIssueRequest[],
|
||||
): Promise<void> {
|
||||
return this.client.request<void>('/moderation/tech-review/global-issue-detail', {
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'POST',
|
||||
body: data,
|
||||
})
|
||||
}
|
||||
|
||||
public async searchGlobalIssueDetails(
|
||||
params: Labrinth.TechReview.Internal.SearchGlobalIssueDetailsRequest,
|
||||
): Promise<Labrinth.TechReview.Internal.SearchGlobalIssueDetailsResponse> {
|
||||
return this.client.request<Labrinth.TechReview.Internal.SearchGlobalIssueDetailsResponse>(
|
||||
'/moderation/tech-review/global-issue-detail/search',
|
||||
{
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'POST',
|
||||
body: params,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
public async getGlobalIssueDetail(
|
||||
params: Labrinth.TechReview.Internal.GetGlobalIssueDetailRequest,
|
||||
): Promise<Labrinth.TechReview.Internal.GetGlobalIssueDetailResponse> {
|
||||
return this.client.request<Labrinth.TechReview.Internal.GetGlobalIssueDetailResponse>(
|
||||
'/moderation/tech-review/global-issue-detail/local-traces',
|
||||
{
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'POST',
|
||||
body: params,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
public async submitProject(
|
||||
projectId: string,
|
||||
data: Labrinth.TechReview.Internal.SubmitProjectRequest,
|
||||
|
||||
@@ -77,6 +77,7 @@ export namespace Labrinth {
|
||||
status: SubscriptionStatus
|
||||
created: string
|
||||
metadata?: SubscriptionMetadata
|
||||
next_charge_tax_amount?: number | null
|
||||
}
|
||||
|
||||
export type SubscriptionMetadata =
|
||||
@@ -373,6 +374,14 @@ export namespace Labrinth {
|
||||
date_created: string
|
||||
}
|
||||
|
||||
export type OverrideFileOnPlatform = {
|
||||
file_path: string
|
||||
sha1: string
|
||||
version_id: string
|
||||
platform_version_id: string
|
||||
platform_project_id: string
|
||||
}
|
||||
|
||||
export type AttributionGroup = {
|
||||
id: string
|
||||
flame_project: FlameProject | null
|
||||
@@ -381,12 +390,21 @@ export namespace Labrinth {
|
||||
attributed_by: string | null
|
||||
files: AttributionFile[]
|
||||
versions: AttributionVersionInfo[]
|
||||
override_files_on_platform: OverrideFileOnPlatform[]
|
||||
}
|
||||
|
||||
export type UpdateGroupRequest = {
|
||||
attribution: AttributionResolution
|
||||
}
|
||||
|
||||
export type DeleteGroupsRequest = {
|
||||
groups: string[]
|
||||
}
|
||||
|
||||
export type DeleteAllGroupsRequest = {
|
||||
project_id: string
|
||||
}
|
||||
|
||||
export type AssignRequest = {
|
||||
sha1: string
|
||||
target_group_id: number
|
||||
@@ -397,6 +415,12 @@ export namespace Labrinth {
|
||||
sha1: string
|
||||
project_id: string
|
||||
}
|
||||
|
||||
export type FileScanResponse = {
|
||||
new_attribution_groups: number
|
||||
new_attribution_files: number
|
||||
scanned_file_names: string[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,7 +442,7 @@ export namespace Labrinth {
|
||||
| { context: 'project'; project_id: string }
|
||||
| { context: 'version'; version_id: string }
|
||||
| { context: 'thread_message'; thread_message_id: string }
|
||||
| { context: 'report'; report_id: string }
|
||||
| { context: 'report'; report_id: string | null }
|
||||
)
|
||||
|
||||
export type UploadedImageFor<C extends ImageUploadContext> = Extract<
|
||||
@@ -434,11 +458,21 @@ export namespace Labrinth {
|
||||
| { context: 'project'; project_id: string }
|
||||
| { context: 'version'; version_id: string }
|
||||
| { context: 'thread_message'; thread_message_id: string }
|
||||
| { context: 'report'; report_id: string }
|
||||
| { context: 'report'; report_id?: string }
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Analytics {
|
||||
export namespace Internal {
|
||||
export type AnalyticsEventUpsert = {
|
||||
announcement_url: string | null
|
||||
for_metric_kind: v3.AnalyticsEventMetricKind[] | null
|
||||
title: string
|
||||
ends: string
|
||||
starts: string
|
||||
}
|
||||
}
|
||||
|
||||
export namespace v3 {
|
||||
export type AnalyticsEventId = number
|
||||
export type AnalyticsEventMetricKind = 'views' | 'revenue' | 'downloads' | 'playtime'
|
||||
@@ -452,14 +486,6 @@ export namespace Labrinth {
|
||||
starts: string
|
||||
}
|
||||
|
||||
export type AnalyticsEventUpsert = {
|
||||
announcement_url: string | null
|
||||
for_metric_kind: AnalyticsEventMetricKind[] | null
|
||||
title: string
|
||||
ends: string
|
||||
starts: string
|
||||
}
|
||||
|
||||
export type FetchRequest = {
|
||||
time_range: TimeRange
|
||||
return_metrics: ReturnMetrics
|
||||
@@ -740,6 +766,7 @@ export namespace Labrinth {
|
||||
email: string
|
||||
challenge: string
|
||||
sign_up_newsletter?: boolean
|
||||
account_consent?: boolean
|
||||
}
|
||||
|
||||
export type CreateAccountResponse = {
|
||||
@@ -757,6 +784,7 @@ export namespace Labrinth {
|
||||
state: string
|
||||
challenge: string
|
||||
sign_up_newsletter: boolean
|
||||
account_consent?: boolean
|
||||
}
|
||||
|
||||
export type CreateOAuthAccountResponse = {
|
||||
@@ -1333,6 +1361,7 @@ export namespace Labrinth {
|
||||
}
|
||||
|
||||
export type VersionFile = {
|
||||
id?: string
|
||||
hashes: VersionFileHash
|
||||
url: string
|
||||
filename: string
|
||||
@@ -1454,6 +1483,7 @@ export namespace Labrinth {
|
||||
}
|
||||
|
||||
export interface VersionFile {
|
||||
id?: string
|
||||
hashes: VersionFileHash
|
||||
url: string
|
||||
filename: string
|
||||
@@ -1635,6 +1665,8 @@ export namespace Labrinth {
|
||||
allow_friend_requests?: boolean
|
||||
moderation_notes?: Common.ModerationNote | null
|
||||
github_id?: number
|
||||
discord_id?: string
|
||||
steam_id?: string
|
||||
}
|
||||
|
||||
export type SearchUser = {
|
||||
@@ -1661,6 +1693,18 @@ export namespace Labrinth {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace BlockedUsers {
|
||||
export namespace Internal {
|
||||
export type BlockStatus = {
|
||||
blocked: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export namespace v3 {
|
||||
export type BlockedUserId = string
|
||||
}
|
||||
}
|
||||
|
||||
export namespace ServerPing {
|
||||
export namespace Internal {
|
||||
export type MinecraftJavaPingRequest = {
|
||||
@@ -1730,10 +1774,22 @@ export namespace Labrinth {
|
||||
}
|
||||
|
||||
export namespace Search {
|
||||
export type SearchParams = {
|
||||
query?: string
|
||||
offset?: string | number
|
||||
index?: string
|
||||
limit?: string | number
|
||||
new_filters?: string
|
||||
facets?: string[][]
|
||||
filters?: string
|
||||
version?: string
|
||||
}
|
||||
|
||||
export namespace v2 {
|
||||
export interface ResultSearchProject {
|
||||
project_id: string
|
||||
project_type: string
|
||||
all_project_types: string[]
|
||||
slug: string | null
|
||||
author: string
|
||||
author_id: string | null
|
||||
@@ -1771,6 +1827,7 @@ export namespace Labrinth {
|
||||
version_id: string
|
||||
project_id: string
|
||||
project_types: string[]
|
||||
all_project_types: string[]
|
||||
slug: string | null
|
||||
author: string
|
||||
author_id: string | null
|
||||
@@ -1790,7 +1847,9 @@ export namespace Labrinth {
|
||||
featured_gallery: string | null
|
||||
color: number | null
|
||||
loaders: string[]
|
||||
project_loader_fields?: Record<string, unknown[]>
|
||||
project_loader_fields?: Record<string, unknown[]> & {
|
||||
environment?: Projects.v3.Environment[]
|
||||
}
|
||||
minecraft_server?: Projects.v3.MinecraftServer | null
|
||||
minecraft_java_server?: Projects.v3.MinecraftJavaServer | null
|
||||
minecraft_bedrock_server?: Projects.v3.MinecraftBedrockServer | null
|
||||
@@ -1823,6 +1882,19 @@ export namespace Labrinth {
|
||||
new_status: Projects.v2.ProjectStatus
|
||||
old_status: Projects.v2.ProjectStatus
|
||||
}
|
||||
| {
|
||||
type: 'tech_review'
|
||||
verdict: 'safe' | 'unsafe'
|
||||
}
|
||||
| {
|
||||
type: 'tech_review_entered'
|
||||
}
|
||||
| {
|
||||
type: 'tech_review_exited'
|
||||
}
|
||||
| {
|
||||
type: 'tech_review_exit_file_deleted'
|
||||
}
|
||||
| {
|
||||
type: 'thread_closure'
|
||||
}
|
||||
@@ -1869,13 +1941,14 @@ export namespace Labrinth {
|
||||
|
||||
export namespace Reports {
|
||||
export namespace v3 {
|
||||
export type ItemType = 'project' | 'version' | 'user' | 'unknown'
|
||||
export type ItemType = 'project' | 'version' | 'user' | 'shared-instance' | 'unknown'
|
||||
|
||||
export type Report = {
|
||||
id: string
|
||||
report_type: string
|
||||
item_id: string
|
||||
item_type: ItemType
|
||||
shared_instance_version_id?: number
|
||||
reporter: string
|
||||
body: string
|
||||
created: string
|
||||
@@ -1906,6 +1979,57 @@ export namespace Labrinth {
|
||||
|
||||
export namespace Moderation {
|
||||
export namespace Internal {
|
||||
export type Ownership =
|
||||
| {
|
||||
kind: 'user'
|
||||
id: string
|
||||
name: string
|
||||
icon_url: string | null
|
||||
}
|
||||
| {
|
||||
kind: 'organization'
|
||||
id: string
|
||||
name: string
|
||||
icon_url: string | null
|
||||
}
|
||||
|
||||
export type ProjectsSort = 'oldest' | 'newest' | 'most_external_deps' | 'least_external_deps'
|
||||
|
||||
export type ProjectsRequest = {
|
||||
count?: number
|
||||
offset?: number
|
||||
has_external_dependencies?: boolean
|
||||
exclude_technical_review?: boolean
|
||||
query?: string
|
||||
project_type?: string
|
||||
sort?: ProjectsSort
|
||||
}
|
||||
|
||||
export type QueueProject = {
|
||||
id: string
|
||||
slug: string | null
|
||||
name: string
|
||||
summary: string
|
||||
icon_url: string | null
|
||||
status: Projects.v2.ProjectStatus
|
||||
requested_status: Projects.v2.ProjectStatus | null
|
||||
queued: string | null
|
||||
published: string
|
||||
updated: string
|
||||
project_types: string[]
|
||||
ownership: Ownership
|
||||
external_dependencies_count: number
|
||||
}
|
||||
|
||||
export type ProjectsResponse = {
|
||||
total: number
|
||||
projects: QueueProject[]
|
||||
}
|
||||
|
||||
export type ProjectIdsResponse = {
|
||||
ids: string[]
|
||||
}
|
||||
|
||||
export type LockedByUser = {
|
||||
id: string
|
||||
username: string
|
||||
@@ -2163,7 +2287,64 @@ export namespace Labrinth {
|
||||
| 'severity_desc'
|
||||
|
||||
export type UpdateIssueRequest = {
|
||||
verdict: 'safe' | 'unsafe'
|
||||
detail_id: string
|
||||
verdict: DelphiReportIssueStatus
|
||||
}
|
||||
|
||||
export type UpdateIssueDetailRequest = {
|
||||
verdict: DelphiReportIssueStatus
|
||||
}
|
||||
|
||||
export type UpdateGlobalIssueRequest = {
|
||||
detail_key: string
|
||||
verdict: DelphiReportIssueStatus
|
||||
}
|
||||
|
||||
export type SearchGlobalIssueDetailsRequest = {
|
||||
limit?: number
|
||||
page?: number
|
||||
query?: string | null
|
||||
}
|
||||
|
||||
export type SearchGlobalIssueDetailsResponse = {
|
||||
total: number
|
||||
traces: GlobalIssueDetail[]
|
||||
}
|
||||
|
||||
export type GetGlobalIssueDetailRequest = {
|
||||
detail_key: string
|
||||
limit?: number
|
||||
after_detail_id?: string | null
|
||||
}
|
||||
|
||||
export type GetGlobalIssueDetailResponse = {
|
||||
trace: GlobalIssueDetail
|
||||
next_after_detail_id: string | null
|
||||
}
|
||||
|
||||
export type GlobalIssueDetail = {
|
||||
detail_key: string
|
||||
verdict: DelphiReportIssueStatus
|
||||
local_trace_count: number
|
||||
local_traces: GlobalIssueDetailTrace[]
|
||||
}
|
||||
|
||||
export type GlobalIssueDetailTrace = {
|
||||
detail_id: string
|
||||
issue_id: string
|
||||
issue_type: string
|
||||
project_id: string
|
||||
project_slug: string | null
|
||||
project_name: string
|
||||
version_id: string
|
||||
version_number: string
|
||||
file_id: string
|
||||
file_name: string
|
||||
jar: string | null
|
||||
file_path: string
|
||||
severity: DelphiSeverity
|
||||
local_status: DelphiReportIssueStatus
|
||||
effective_status: DelphiReportIssueStatus
|
||||
}
|
||||
|
||||
export type SubmitProjectRequest = {
|
||||
@@ -2225,6 +2406,8 @@ export namespace Labrinth {
|
||||
decompiled_source: string | null
|
||||
data: Record<string, unknown>
|
||||
severity: DelphiSeverity
|
||||
local_status: DelphiReportIssueStatus | null
|
||||
global_status: DelphiReportIssueStatus | null
|
||||
status: DelphiReportIssueStatus
|
||||
}
|
||||
|
||||
@@ -2273,6 +2456,19 @@ export namespace Labrinth {
|
||||
new_status: Projects.v2.ProjectStatus
|
||||
old_status: Projects.v2.ProjectStatus
|
||||
}
|
||||
| {
|
||||
type: 'tech_review'
|
||||
verdict: 'safe' | 'unsafe'
|
||||
}
|
||||
| {
|
||||
type: 'tech_review_entered'
|
||||
}
|
||||
| {
|
||||
type: 'tech_review_exited'
|
||||
}
|
||||
| {
|
||||
type: 'tech_review_exit_file_deleted'
|
||||
}
|
||||
| {
|
||||
type: 'thread_closure'
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ export class LabrinthUsersV2Module extends AbstractModule {
|
||||
*/
|
||||
public async patch(
|
||||
idOrUsername: string,
|
||||
data: Partial<Pick<Labrinth.Users.v2.User, 'badges' | 'role'>>,
|
||||
data: Partial<Pick<Labrinth.Users.v2.User, 'badges' | 'bio' | 'role' | 'username'>>,
|
||||
): Promise<void> {
|
||||
return this.client.request(`/user/${idOrUsername}`, {
|
||||
api: 'labrinth',
|
||||
@@ -177,4 +177,34 @@ export class LabrinthUsersV2Module extends AbstractModule {
|
||||
body: data,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a user's avatar.
|
||||
*
|
||||
* @param idOrUsername - The user's ID or username
|
||||
* @param file - Image file to upload
|
||||
* @param ext - File extension (e.g., 'png', 'jpeg', 'gif', 'webp')
|
||||
*/
|
||||
public async changeIcon(idOrUsername: string, file: Blob, ext: string): Promise<void> {
|
||||
return this.client.request(`/user/${idOrUsername}/icon`, {
|
||||
api: 'labrinth',
|
||||
version: 2,
|
||||
method: 'PATCH',
|
||||
params: { ext },
|
||||
body: file,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a user's avatar.
|
||||
*
|
||||
* @param idOrUsername - The user's ID or username
|
||||
*/
|
||||
public async deleteIcon(idOrUsername: string): Promise<void> {
|
||||
return this.client.request(`/user/${idOrUsername}/icon`, {
|
||||
api: 'labrinth',
|
||||
version: 2,
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,18 @@ export class LabrinthVersionsV2Module extends AbstractModule {
|
||||
})
|
||||
}
|
||||
|
||||
public async getVersionFromFileHash(
|
||||
hash: string,
|
||||
algorithm: keyof Labrinth.Versions.v2.VersionFileHash,
|
||||
): Promise<Labrinth.Versions.v2.Version> {
|
||||
return this.client.request<Labrinth.Versions.v2.Version>(`/version_file/${hash}`, {
|
||||
api: 'labrinth',
|
||||
version: 2,
|
||||
method: 'GET',
|
||||
params: { algorithm },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get multiple versions by IDs (v2)
|
||||
*
|
||||
|
||||
@@ -3,16 +3,25 @@ export namespace LauncherMeta {
|
||||
export namespace v0 {
|
||||
export type LoaderVersion = {
|
||||
id: string
|
||||
url: string
|
||||
stable: boolean
|
||||
}
|
||||
|
||||
export type GameVersionEntry = {
|
||||
id: string
|
||||
stable: boolean
|
||||
versionGroup?: string
|
||||
loaders: LoaderVersion[]
|
||||
}
|
||||
|
||||
export type VersionGroup = {
|
||||
id: string
|
||||
loaders: LoaderVersion[]
|
||||
}
|
||||
|
||||
export type Manifest = {
|
||||
gameVersions: GameVersionEntry[]
|
||||
versionGroups?: VersionGroup[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ export class LauncherMetaManifestV0Module extends AbstractModule {
|
||||
*
|
||||
* @param loader - Loader platform (fabric, forge, quilt, neo)
|
||||
*/
|
||||
public async getManifest(loader: string): Promise<LauncherMeta.Manifest.v0.Manifest> {
|
||||
public async getManifest(
|
||||
loader: string,
|
||||
formatVersion = 0,
|
||||
): Promise<LauncherMeta.Manifest.v0.Manifest> {
|
||||
return this.client.request<LauncherMeta.Manifest.v0.Manifest>('/manifest.json', {
|
||||
api: LAUNCHER_META_BASE_URL,
|
||||
version: `${loader}/v0`,
|
||||
version: `${loader}/v${formatVersion}`,
|
||||
method: 'GET',
|
||||
skipAuth: true,
|
||||
headers: { 'Content-Type': '' },
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { AbstractModule } from '../../../core/abstract-module'
|
||||
import type { SharedInstances } from '../types'
|
||||
|
||||
export class SharedInstancesInstancesV1Module extends AbstractModule {
|
||||
public getModuleID(): string {
|
||||
return 'sharedinstances_instances_v1'
|
||||
}
|
||||
|
||||
public async get(instanceId: string): Promise<SharedInstances.Instances.v1.Instance> {
|
||||
return this.client.request<SharedInstances.Instances.v1.Instance>(
|
||||
`/instances/${encodeURIComponent(instanceId)}`,
|
||||
{
|
||||
api: 'sharedinstances',
|
||||
version: 1,
|
||||
method: 'GET',
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
public async getForUser(userId: string): Promise<string[]> {
|
||||
return this.client.request<string[]>('/instances', {
|
||||
api: 'sharedinstances',
|
||||
version: 1,
|
||||
method: 'GET',
|
||||
params: { user: userId },
|
||||
})
|
||||
}
|
||||
|
||||
public async getUsers(instanceId: string): Promise<SharedInstances.Instances.v1.InstanceUsers> {
|
||||
return this.client.request<SharedInstances.Instances.v1.InstanceUsers>(
|
||||
`/instances/${encodeURIComponent(instanceId)}/users`,
|
||||
{
|
||||
api: 'sharedinstances',
|
||||
version: 1,
|
||||
method: 'GET',
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
public async getLatestVersion(
|
||||
instanceId: string,
|
||||
): Promise<SharedInstances.Instances.v1.InstanceVersion> {
|
||||
return this.client.request<SharedInstances.Instances.v1.InstanceVersion>(
|
||||
`/instances/${encodeURIComponent(instanceId)}/versions`,
|
||||
{
|
||||
api: 'sharedinstances',
|
||||
version: 1,
|
||||
method: 'GET',
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
public async getVersion(
|
||||
instanceId: string,
|
||||
version: number,
|
||||
): Promise<SharedInstances.Instances.v1.InstanceVersion> {
|
||||
return this.client.request<SharedInstances.Instances.v1.InstanceVersion>(
|
||||
`/instances/${encodeURIComponent(instanceId)}/versions/${version}`,
|
||||
{
|
||||
api: 'sharedinstances',
|
||||
version: 1,
|
||||
method: 'GET',
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { AbstractModule } from '../../../core/abstract-module'
|
||||
import type { SharedInstances } from '../types'
|
||||
|
||||
export class SharedInstancesInvitesV1Module extends AbstractModule {
|
||||
public getModuleID(): string {
|
||||
return 'sharedinstances_invites_v1'
|
||||
}
|
||||
|
||||
public async get(inviteId: string): Promise<SharedInstances.Invites.v1.Invite> {
|
||||
return this.client.request<SharedInstances.Invites.v1.Invite>(
|
||||
`/invites/${encodeURIComponent(inviteId)}`,
|
||||
{
|
||||
api: 'sharedinstances',
|
||||
version: 1,
|
||||
method: 'GET',
|
||||
skipAuth: true,
|
||||
retry: false,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { AbstractModule } from '../../../core/abstract-module'
|
||||
import type { SharedInstances } from '../types'
|
||||
|
||||
export class SharedInstancesModerationV1Module extends AbstractModule {
|
||||
public getModuleID(): string {
|
||||
return 'sharedinstances_moderation_v1'
|
||||
}
|
||||
|
||||
public async blacklistUsers(
|
||||
request: SharedInstances.Moderation.v1.BlacklistUserRequest,
|
||||
): Promise<void> {
|
||||
return this.client.request('/moderation/blacklist', {
|
||||
api: 'sharedinstances',
|
||||
version: 1,
|
||||
method: 'POST',
|
||||
body: request,
|
||||
})
|
||||
}
|
||||
|
||||
public async unblacklistUsers(
|
||||
request: SharedInstances.Moderation.v1.BlacklistUserRequest,
|
||||
): Promise<void> {
|
||||
return this.client.request('/moderation/blacklist', {
|
||||
api: 'sharedinstances',
|
||||
version: 1,
|
||||
method: 'DELETE',
|
||||
body: request,
|
||||
})
|
||||
}
|
||||
|
||||
public async deleteFile(instanceId: string, version: number, fileName: string): Promise<void> {
|
||||
return this.client.request(
|
||||
`/moderation/instances/${encodeURIComponent(instanceId)}/versions/${version}/files/${encodeURIComponent(fileName)}`,
|
||||
{
|
||||
api: 'sharedinstances',
|
||||
version: 1,
|
||||
method: 'DELETE',
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
export namespace SharedInstances {
|
||||
export namespace Invites {
|
||||
export namespace v1 {
|
||||
export type UserManager = {
|
||||
id: string
|
||||
name: string
|
||||
type: 'user'
|
||||
avatar?: string | null
|
||||
}
|
||||
|
||||
export type ServerManager = {
|
||||
name: string
|
||||
type: 'server'
|
||||
icon?: string | null
|
||||
}
|
||||
|
||||
export type Manager = UserManager | ServerManager
|
||||
|
||||
export type InviteUser = {
|
||||
id: string
|
||||
name: string
|
||||
avatar?: string | null
|
||||
joined_at: string | null
|
||||
}
|
||||
|
||||
export type Invite = {
|
||||
instance_id: string
|
||||
instance_name: string
|
||||
instance_icon?: string | null
|
||||
game_version: string
|
||||
loader_version: string
|
||||
managers: Manager[]
|
||||
instance_users?: InviteUser[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Instances {
|
||||
export namespace v1 {
|
||||
export type Instance = {
|
||||
name: string
|
||||
icon: string | null
|
||||
quarantine: boolean
|
||||
}
|
||||
|
||||
export type JoinType = 'owner' | 'invite' | 'link'
|
||||
|
||||
export type InstanceUser = {
|
||||
id: string
|
||||
joined_at: string | null
|
||||
join_type: JoinType
|
||||
last_played: string | null
|
||||
}
|
||||
|
||||
export type InstanceUsers = {
|
||||
users: InstanceUser[]
|
||||
tokens: number
|
||||
}
|
||||
|
||||
export type FileMetadata = {
|
||||
path: string
|
||||
hash: string
|
||||
}
|
||||
|
||||
export type ExternalFile = {
|
||||
file_name: string
|
||||
file_type: string
|
||||
url: string
|
||||
file_size?: number
|
||||
metadata?: FileMetadata[]
|
||||
}
|
||||
|
||||
export type InstanceVersion = {
|
||||
version: number
|
||||
modrinth_ids?: string[]
|
||||
ready: boolean
|
||||
external_files: ExternalFile[]
|
||||
modpack_id: string | null
|
||||
game_version: string
|
||||
loader: string
|
||||
loader_version: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Moderation {
|
||||
export namespace v1 {
|
||||
export type BlacklistUserRequest = {
|
||||
user_ids: string[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Users {
|
||||
export namespace v1 {
|
||||
export type BlacklistStatus = {
|
||||
blacklisted: boolean
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { AbstractModule } from '../../../core/abstract-module'
|
||||
import type { SharedInstances } from '../types'
|
||||
|
||||
export class SharedInstancesUsersV1Module extends AbstractModule {
|
||||
public getModuleID(): string {
|
||||
return 'sharedinstances_users_v1'
|
||||
}
|
||||
|
||||
public async getBlacklistStatus(
|
||||
userId: string,
|
||||
): Promise<SharedInstances.Users.v1.BlacklistStatus> {
|
||||
return this.client.request<SharedInstances.Users.v1.BlacklistStatus>(
|
||||
`/blacklist/${encodeURIComponent(userId)}`,
|
||||
{
|
||||
api: 'sharedinstances',
|
||||
version: 1,
|
||||
method: 'GET',
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -6,3 +6,4 @@ export * from './launcher-meta/types'
|
||||
export * from './mclogs/types'
|
||||
export * from './paper/types'
|
||||
export * from './purpur/types'
|
||||
export * from './shared-instances/types'
|
||||
|
||||
@@ -21,6 +21,8 @@ export abstract class XHRUploadClient extends AbstractModrinthClient {
|
||||
baseUrl = this.resolveBaseUrl(this.config.labrinthBaseUrl!)
|
||||
} else if (options.api === 'archon') {
|
||||
baseUrl = this.resolveBaseUrl(this.config.archonBaseUrl!)
|
||||
} else if (options.api === 'sharedinstances') {
|
||||
baseUrl = this.resolveBaseUrl(this.config.sharedInstancesBaseUrl!)
|
||||
} else {
|
||||
baseUrl = options.api
|
||||
}
|
||||
|
||||
@@ -50,6 +50,12 @@ export interface ClientConfig {
|
||||
*/
|
||||
archonBaseUrl?: BaseUrlConfig
|
||||
|
||||
/**
|
||||
* Base URL for the Shared Instances API
|
||||
* @default 'https://shared-instances.modrinth.com'
|
||||
*/
|
||||
sharedInstancesBaseUrl?: BaseUrlConfig
|
||||
|
||||
/**
|
||||
* Default request timeout in milliseconds
|
||||
* @default 10000
|
||||
|
||||
@@ -11,6 +11,7 @@ export type RequestOptions = {
|
||||
* API to use for this request
|
||||
* - 'labrinth': Main Modrinth API (resolves to labrinthBaseUrl)
|
||||
* - 'archon': Modrinth Hosting API (resolves to archonBaseUrl)
|
||||
* - 'sharedinstances': Shared Instances API (resolves to sharedInstancesBaseUrl)
|
||||
* - string: Custom base URL (e.g., 'https://custom-api.com')
|
||||
*/
|
||||
api: 'labrinth' | 'archon' | string
|
||||
|
||||
Reference in New Issue
Block a user