Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OBBs on multiple APKs #38

Merged
merged 7 commits into from
Oct 1, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"semi": false,
"singleQuote": true,
"trailingComma": "none"
}
106 changes: 56 additions & 50 deletions src/actions/Upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,22 @@ import { Edit, IEditParams } from '../Edit'
import { checkTrack } from '../helpers'

const debug = Debug('apkup:Upload')
export interface IUploadFile {
/** The APK or AAB file to upload. */
file: string
/** A paths to the deobfuscation file for this release. */
deobfuscation?: string
/** An array that specifies the paths to the expansion files (OBBs) for this release. */
obbs?: string[]
}

export interface IUploadParams {
// tslint:disable-next-line: max-line-length
/** Specify track for this release. Can be one of the [[tracks]]. Default: `internal` */
/** An array of objects that specifies the files to upload for this release. */
files: IUploadFile[]
/** Specify track for this release. Default: `internal` */
track?: string
/** An array of objects that specifies changes in this version. Each object has a `language` and `text`. */
releaseNotes?: IReleaseNotes[]
/** An array that specifies the paths to the expansion files (OBBs) for this release. */
obbs?: string[]
/** A paths to the deobfuscation file for this release. */
deobfuscation?: string
}

export interface IReleaseNotes {
Expand All @@ -32,125 +37,126 @@ export interface IReleaseNotes {
*/
export class Upload extends Edit {
private uploadParams: IUploadParams
private apk: string[]

private versionCodes: any[] = []

constructor (
client: JWT,
apk: string | string[],
uploadParams: IUploadParams = {},
uploadParams: IUploadParams,
nprail marked this conversation as resolved.
Show resolved Hide resolved
editParams: IEditParams
) {
super(client, editParams)

assert(apk, 'I require an APK file')
assert(
uploadParams.files.length > 0,
'I require at least one file to upload file'
)
if (uploadParams.track) {
uploadParams.track = uploadParams.track.toLowerCase()

assert(checkTrack(uploadParams.track), 'Unknown track')
}

this.apk = typeof apk === 'string' ? [apk] : apk

this.uploadParams = uploadParams
this.uploadParams.track = uploadParams.track || 'internal'
this.uploadParams.obbs = uploadParams.obbs || []
this.uploadParams.releaseNotes = uploadParams.releaseNotes || []
this.uploadParams.deobfuscation = uploadParams.deobfuscation
}

public async makeEdits () {
await this.uploadFiles()
await this.uploadOBBs()
await this.assignTrack()
await this.uploadDeobfuscation()
}

private async uploadFiles () {
debug('> Uploading release')
const uploads = this.apk.map(async (file) => {
const uploads = this.uploadParams.files.map(async (fileObject) => {
let uploadJob: any

const ext = extname(file)
const ext = extname(fileObject.file)
if (ext === '.apk') {
uploadJob = await this.publisher.edits.apks.upload({
editId: this.editId,
media: {
body: createReadStream(file),
body: createReadStream(fileObject.file),
mimeType: 'application/octet-stream'
},
packageName: this.editParams.packageName
})

debug(
`> Uploaded ${file} with version code ${
`> Uploaded ${fileObject.file} with version code ${
uploadJob.data.versionCode
} and SHA1 ${uploadJob.data.binary && uploadJob.data.binary.sha1}`
)
} else if (ext === '.aab') {
uploadJob = await this.publisher.edits.bundles.upload({
editId: this.editId,
media: {
body: createReadStream(file),
body: createReadStream(fileObject.file),
mimeType: 'application/octet-stream'
},
packageName: this.editParams.packageName
})

debug(
`> Uploaded ${file} with version code ${uploadJob.data.versionCode} and SHA1 ${uploadJob.data.sha1}`
`> Uploaded ${fileObject.file} with version code ${uploadJob.data.versionCode} and SHA1 ${uploadJob.data.sha1}`
)
}

this.versionCodes.push(uploadJob.data.versionCode)
const versionCode: number = uploadJob.data.versionCode
this.versionCodes.push(versionCode)

if (fileObject.obbs) {
await this.uploadOBBs(fileObject.obbs, versionCode)
}

if (fileObject.deobfuscation) {
await this.uploadDeobfuscation(fileObject.deobfuscation, versionCode)
}

return uploadJob
})
return Promise.all(uploads)
}

private async uploadDeobfuscation () {
debug('> Uploading deobfuscation')
if (this.uploadParams.deobfuscation) {
return this.publisher.edits.deobfuscationfiles.upload(
{
apkVersionCode: this.editParams.versionCode,
deobfuscationFileType: 'proguard',
editId: this.editId,
media: {
body: createReadStream(this.uploadParams.deobfuscation),
mimeType: 'application/octet-stream'
},
packageName: this.editParams.packageName
private async uploadDeobfuscation (
deobfuscation: string,
versionCode: number
) {
debug(`> Uploading deobfuscation for ${versionCode}`)
return this.publisher.edits.deobfuscationfiles.upload(
{
apkVersionCode: versionCode,
deobfuscationFileType: 'proguard',
editId: this.editId,
media: {
body: createReadStream(deobfuscation),
mimeType: 'application/octet-stream'
},
{}
)
}
packageName: this.editParams.packageName
},
{}
)
}

private async uploadOBBs () {
if (
!this.uploadParams.obbs ||
!Array.isArray(this.uploadParams.obbs) ||
!this.uploadParams.obbs.length
) {
private async uploadOBBs (obbs: string[], versionCode: number) {
if (!obbs || !Array.isArray(obbs) || !obbs.length) {
return
}

debug(`> Uploading ${this.uploadParams.obbs.length} expansion file(s)`)
debug(`> Uploading ${obbs.length} expansion file(s) for ${versionCode}`)

return Promise.all(
this.uploadParams.obbs.map(async (obb) => this.uploadOBB(obb))
obbs.map(async (obb) => this.uploadOBB(obb, versionCode))
)
}

private async uploadOBB (obb: string) {
debug(`> Uploading expansion file ${obb}`)
private async uploadOBB (obb: string, versionCode: number) {
debug(`> Uploading expansion file ${obb} for ${versionCode}`)

return this.publisher.edits.expansionfiles.upload(
{
apkVersionCode: this.editParams.versionCode,
apkVersionCode: versionCode,
editId: this.editId,
expansionFileType: 'main',
media: {
Expand Down
7 changes: 4 additions & 3 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ const argv = yargs
config: true,
demandOption: true
})
.option('apk', {
alias: 'a',
describe: 'Path to the APK file',
.option('file', {
alias: 'f',
describe:
'Paths to an APK or AAB. OBBs and deobfuscation files for the package can be included by adding a comma separated list after the main file.',
type: 'array'
})
.config(
Expand Down
15 changes: 2 additions & 13 deletions src/cli/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,13 @@ export const upload = {
describe: `A string with the format 'lang=changes'`,
type: 'array'
})
.option('deobfuscation', {
alias: 'd',
describe: 'Path to optional deobfuscation file',
type: 'string'
})
.option('obbs', {
alias: 'o',
describe: 'Path to optional expansion files (max 2)',
type: 'array'
})
.demandOption(['apk'])
},
command: 'upload [options]',
desc: 'Upload an APK',
handler: (argv) => {
const options: IUploadParams = {
deobfuscation: argv.deobfuscation,
obbs: argv.obbs,
files: [],
releaseNotes: [],
track: argv.track
}
Expand Down Expand Up @@ -68,7 +57,7 @@ export const upload = {
const spinner = ora('Uploading APK...').start()

apkup
.upload(argv.apk, options)
.upload(options)
.then((resp) => {
spinner.stop()

Expand Down
17 changes: 9 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,19 @@ export class Apkup {
* })
* ```
*/
public async upload (
apk: string | string[],
uploadParams?: IUploadParams
): Promise<IEditResponse> {
const apkPackage = await parseManifest(apk)
public async upload (uploadParams: IUploadParams): Promise<IEditResponse> {
const file = uploadParams.files[0]?.file

assert(file, 'At least one file is required')

const manifest = await parseManifest(file)

const editParams: IEditParams = {
packageName: apkPackage.packageName,
versionCode: apkPackage.versionCode
packageName: manifest.packageName,
versionCode: manifest.versionCode
}

const upload = new Upload(this.client, apk, uploadParams, editParams)
const upload = new Upload(this.client, uploadParams, editParams)
return upload.run()
}

Expand Down