Add a mod manifest endpoint
This commit is contained in:
4 files changed
+244
-3
No files matched your search
@@ -13,6 +13,7 @@ import { handler as getVerifyCodeHandler } from './routes/get-verify-code'
|
||||
|
||||
import { handler as canLoadClientHandler } from './routes/can-load-client'
|
||||
|
||||
import { handler as launcherModsGetHandler } from './routes/launcher/mods/get'
|
||||
import { handler as launcherVersionsHandler } from './routes/launcher/versions/get'
|
||||
import { handler as launcherLatestHandler } from './routes/launcher/latest/get'
|
||||
import { handler as launcherDownloadHandler } from './routes/launcher/download/get'
|
||||
@@ -955,6 +956,24 @@ app.get('/can-load-client', context => canLoadClientHandler(context), {
|
||||
)
|
||||
})
|
||||
})
|
||||
app.get('/launcher/mods', context => launcherModsGetHandler(context), {
|
||||
detail: {
|
||||
description: 'The endpoint for getting mods for a version.',
|
||||
tags: ['Launcher']
|
||||
},
|
||||
query: t.Object({
|
||||
platform: t.String({ examples: ['windows', 'macos', 'linux'] }),
|
||||
arch: t.String({ examples: ['x86', 'x64', 'arm64'] }),
|
||||
version: t.String()
|
||||
}),
|
||||
headers: t.Object({
|
||||
'x-forwarded-for': t.Optional(
|
||||
t.String({
|
||||
hide: true
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
app.get('/launcher/versions', context => launcherVersionsHandler(context), {
|
||||
detail: {
|
||||
description:
|
||||
|
||||
@@ -103,6 +103,27 @@ export const cdnFiles = mysqlTable('cdnfiles', {
|
||||
mimeType: varchar('mimeType', { length: 255 })
|
||||
})
|
||||
|
||||
export const mods = mysqlTable('mods', {
|
||||
id: bigint('id', { mode: 'number' }).primaryKey().autoincrement().notNull(),
|
||||
name: text('name').notNull(),
|
||||
description: text('description').notNull(),
|
||||
downloadCount: bigint('downloadCount', { mode: 'number' })
|
||||
.notNull()
|
||||
.default(0),
|
||||
hidden: boolean('hidden').default(false).notNull()
|
||||
})
|
||||
|
||||
export const modVersions = mysqlTable('modversions', {
|
||||
id: text('id').primaryKey().notNull(),
|
||||
downloads: text('downloads').default('{}').notNull(),
|
||||
gameVersion: varchar('gameVersion', { length: 24 })
|
||||
.notNull()
|
||||
.references(() => launcherVersionManifest.id),
|
||||
releaseDate: bigint('releaseDate', { mode: 'number' }).notNull(),
|
||||
changelog: text('changelog'),
|
||||
hidden: boolean('hidden').default(false).notNull()
|
||||
})
|
||||
|
||||
// berrydashdatabase
|
||||
|
||||
export const berryDashUserData = mysqlTable('userdata', {
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
import {
|
||||
games,
|
||||
launcherVersionManifest,
|
||||
mods,
|
||||
modVersions
|
||||
} from '../../../lib/tables'
|
||||
import { and, asc, desc, eq } from 'drizzle-orm'
|
||||
import { getDatabaseConnection, jsonResponse } from '../../../lib/util'
|
||||
import { Context } from 'elysia'
|
||||
|
||||
export const handler = async (context: Context) => {
|
||||
const dbResult = getDatabaseConnection(0)
|
||||
if (!dbResult)
|
||||
return jsonResponse({ error: 'Failed to connect to database' }, 500)
|
||||
const { connection, db } = dbResult
|
||||
|
||||
const platform = context.query.platform
|
||||
const arch = context.query.arch
|
||||
const version = context.query.version
|
||||
|
||||
let platformsToShow: string[] | null = null
|
||||
if (platform == 'windows') {
|
||||
if (arch == 'x86') platformsToShow = ['windows-x86']
|
||||
else if (arch == 'x86_64' || arch == 'x64')
|
||||
platformsToShow = ['windows-x64', 'windows-x86']
|
||||
else if (arch == 'aarch64' || arch == 'arm64')
|
||||
platformsToShow = ['windows-arm64']
|
||||
else {
|
||||
connection.end()
|
||||
return jsonResponse(
|
||||
{
|
||||
message: 'Unsupported architecture for Windows',
|
||||
versions: null,
|
||||
games: null
|
||||
},
|
||||
400
|
||||
)
|
||||
}
|
||||
} else if (platform == 'linux') {
|
||||
if (arch == 'x86') platformsToShow = ['linux-x64']
|
||||
else if (arch == 'x86_64' || arch == 'x64')
|
||||
platformsToShow = ['linux-x64', 'linux-x86', 'windows-x64', 'windows-x86']
|
||||
else if (arch == 'aarch64' || arch == 'arm64')
|
||||
platformsToShow = ['linux-arm64']
|
||||
else {
|
||||
connection.end()
|
||||
return jsonResponse(
|
||||
{
|
||||
message: 'Unsupported architecture for Linux',
|
||||
versions: null,
|
||||
games: null
|
||||
},
|
||||
400
|
||||
)
|
||||
}
|
||||
} else if (platform == 'macos') {
|
||||
if (arch == 'x86_64' || arch == 'x64')
|
||||
platformsToShow = ['macos-x64', 'macos-universal']
|
||||
else if (arch == 'aarch64' || arch == 'arm64')
|
||||
platformsToShow = ['macos-arm64', 'macos-universal', 'macos-x64']
|
||||
else {
|
||||
connection.end()
|
||||
return jsonResponse(
|
||||
{
|
||||
message: 'Unsupported architecture for macOS',
|
||||
versions: null,
|
||||
games: null
|
||||
},
|
||||
400
|
||||
)
|
||||
}
|
||||
} else if (platform == 'android') platformsToShow = ['android']
|
||||
else if (platform == 'ios') platformsToShow = ['ios']
|
||||
else {
|
||||
connection.end()
|
||||
return jsonResponse(
|
||||
{ message: 'Unsupported platform', versions: null, games: null },
|
||||
400
|
||||
)
|
||||
}
|
||||
|
||||
const modsRaw = await db
|
||||
.select({
|
||||
id: mods.id,
|
||||
name: mods.name,
|
||||
description: mods.description,
|
||||
downloadCount: mods.downloadCount
|
||||
})
|
||||
.from(mods)
|
||||
.where(eq(mods.hidden, false))
|
||||
.orderBy(desc(mods.id))
|
||||
.execute()
|
||||
|
||||
const modsFinal = (
|
||||
await Promise.all(
|
||||
modsRaw.map(async v => {
|
||||
const vi = await db
|
||||
.select({
|
||||
id: modVersions.id,
|
||||
downloads: modVersions.downloads,
|
||||
gameVersion: modVersions.gameVersion,
|
||||
releaseDate: modVersions.releaseDate,
|
||||
changelog: modVersions.changelog
|
||||
})
|
||||
.from(modVersions)
|
||||
.where(
|
||||
and(
|
||||
eq(modVersions.hidden, false),
|
||||
eq(modVersions.gameVersion, version)
|
||||
)
|
||||
)
|
||||
.orderBy(desc(modVersions.releaseDate))
|
||||
.execute()
|
||||
|
||||
if (!vi || vi.length <= 1) return
|
||||
|
||||
const downloads: Record<string, number> = JSON.parse(vi[0].downloads)
|
||||
let download: string | undefined = undefined
|
||||
|
||||
for (const key of platformsToShow) {
|
||||
if (key in downloads) {
|
||||
download = key
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!download || !downloads[download]) return
|
||||
|
||||
return {
|
||||
id: v.id,
|
||||
name: v.name,
|
||||
description: v.description,
|
||||
downloads: v.downloadCount,
|
||||
released: vi[vi.length - 1].releaseDate,
|
||||
updated: vi[0].releaseDate,
|
||||
latestVersion: vi[0].id.substring(String(v.id).length + 1),
|
||||
latestDownload: downloads[download],
|
||||
changelog: vi[0].changelog
|
||||
}
|
||||
})
|
||||
)
|
||||
).filter(v => v != null)
|
||||
|
||||
connection.end()
|
||||
|
||||
return jsonResponse(modsFinal)
|
||||
}
|
||||
Reference in new issue
Block a user