chahinebrini b31066a04c feat(chat): native action sheet + Insta-style heart for DM messages
- ChatBubble: useActionSheet replaces custom Modal (native iOS popup, Android bottom sheet)
- DM mode (isDM prop): hides like-count, shows Insta-style heart badge under bubble when liked
- Group chat unchanged
- Cleanup: remove unused Modal/Platform imports, sheet styles, actionsOpen state
- deploy.sh: auto-detect ANDROID_HOME + auto-create local.properties for local Gradle
- NEXT_RELEASE.md: DM reactions release note
- Includes other staged work across binder-mac, marketing, ops/mdm, ios/
2026-05-30 09:14:32 +02:00

180 lines
6.1 KiB
JavaScript

#!/usr/bin/env node
/**
* play-submit.mjs — Google Play Console AAB/APK Upload
*
* Nutzt die Google Play Developer API (v3) via googleapis package.
* Lädt AAB/APK direkt in einen Track (internal/alpha/beta/production).
*
* Usage:
* node scripts/play-submit.mjs \
* --package org.rebreak.app \
* --aab android/app/build/outputs/bundle/release/app-release.aab \
* --track internal \
* --service-account ~/secrets/rebreak-play-service-account.json
*
* Env-Variablen (Fallback):
* PLAY_SERVICE_ACCOUNT_JSON — Pfad zum Service-Account-JSON
*
* Service-Account-Setup:
* 1. Google Cloud Console → IAM & Admin → Service Accounts
* 2. Create Service Account → JSON-Key downloaden
* 3. Play Console → Setup → API-Access → Service-Account verlinken
* 4. Permissions: "Releases" (Edit + Read)
*
* Exit-Codes:
* 0 — Upload erfolgreich
* 1 — Fehler (File nicht gefunden, Auth-Fehler, API-Fehler)
*/
import { readFile } from 'fs/promises';
import { createReadStream } from 'fs';
import { resolve } from 'path';
import { google } from 'googleapis';
// ─── CLI-Args ────────────────────────────────────────────────────────────────
const args = process.argv.slice(2);
const getArg = (flag) => {
const idx = args.indexOf(flag);
return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : null;
};
const packageName = getArg('--package');
const aabPath = getArg('--aab');
const track = getArg('--track') || 'internal';
const serviceAccountPath = getArg('--service-account') || process.env.PLAY_SERVICE_ACCOUNT_JSON || `${process.env.HOME}/secrets/rebreak-play-service-account.json`;
if (!packageName || !aabPath) {
console.error(`ERROR: Fehlende Args
Usage:
node scripts/play-submit.mjs \\
--package <package-name> \\
--aab <path-to-aab> \\
[--track <internal|alpha|beta|production>] \\
[--service-account <path-to-json>]
Env-Variablen (Fallback):
PLAY_SERVICE_ACCOUNT_JSON — Service-Account-JSON-Pfad
`);
process.exit(1);
}
// ─── Auth ────────────────────────────────────────────────────────────────────
const expandTilde = (p) => p.replace(/^~/, process.env.HOME);
const serviceAccountFullPath = resolve(expandTilde(serviceAccountPath));
const aabFullPath = resolve(expandTilde(aabPath));
let auth;
try {
const keyFile = await readFile(serviceAccountFullPath, 'utf-8');
const credentials = JSON.parse(keyFile);
auth = new google.auth.GoogleAuth({
credentials,
scopes: ['https://www.googleapis.com/auth/androidpublisher'],
});
console.log(`[play-submit] Auth: ${serviceAccountFullPath}`);
} catch (err) {
console.error(`ERROR: Service-Account-JSON konnte nicht geladen werden
Pfad: ${serviceAccountFullPath}
Fehler: ${err.message}
Setup:
1. Google Cloud Console → Service Accounts → Create → JSON-Key
2. Play Console → Setup → API-Access → Service-Account linken
3. Permissions: "Releases" (Edit + Read)
4. JSON-Key ablegen in ~/secrets/ (NICHT committen)
`);
process.exit(1);
}
// ─── Upload ─────────────────────────────────────────────────────────────────
const androidpublisher = google.androidpublisher({ version: 'v3', auth });
try {
console.log(`[play-submit] Package : ${packageName}`);
console.log(`[play-submit] AAB : ${aabFullPath}`);
console.log(`[play-submit] Track : ${track}`);
console.log('');
// 1. Edit erstellen (neue Transaction)
console.log('[play-submit] → Creating edit...');
const editRes = await androidpublisher.edits.insert({
packageName,
});
const editId = editRes.data.id;
console.log(`[play-submit] Edit-ID: ${editId}`);
// 2. AAB/APK hochladen
console.log('[play-submit] → Uploading AAB...');
const uploadRes = await androidpublisher.edits.bundles.upload({
packageName,
editId,
media: {
mimeType: 'application/octet-stream',
body: createReadStream(aabFullPath),
},
});
const versionCode = uploadRes.data.versionCode;
console.log(`[play-submit] Version-Code: ${versionCode}`);
// 3. Track-Assignment (Bundle in Track packen)
console.log(`[play-submit] → Assigning to track '${track}'...`);
await androidpublisher.edits.tracks.update({
packageName,
editId,
track,
requestBody: {
track,
releases: [
{
versionCodes: [String(versionCode)],
status: 'completed', // Draft = 'draft', Live = 'completed'
},
],
},
});
// 4. Edit committen (Transaction abschließen)
console.log('[play-submit] → Committing edit...');
await androidpublisher.edits.commit({
packageName,
editId,
});
console.log('');
console.log(`✓ Upload erfolgreich!`);
console.log(` Version-Code: ${versionCode}`);
console.log(` Track : ${track}`);
console.log(` Play-Console: https://play.google.com/console/u/0/developers/${packageName.split('.')[1]}/app/${packageName}/tracks/${track}`);
console.log('');
console.log('Status-Check:');
console.log(` Release erscheint in ~10-30min im Play-Console-Dashboard`);
} catch (err) {
console.error('');
console.error('ERROR: Upload fehlgeschlagen');
console.error('');
console.error(`Fehler: ${err.message}`);
if (err.response?.data) {
console.error('API-Response:', JSON.stringify(err.response.data, null, 2));
}
console.error('');
console.error('Mögliche Ursachen:');
console.error(' - Service-Account hat keine "Releases"-Permission im Play-Console');
console.error(' - Package-Name stimmt nicht mit dem im Play-Console überein');
console.error(' - Version-Code existiert bereits (muss unique + monoton steigend sein)');
console.error(' - AAB ist nicht korrekt signiert (Keystore-Hash muss in Play-Console registriert sein)');
console.error('');
process.exit(1);
}