anticlone-sdk
Version:
SDK for generating app fingerprints and protecting against clone/fake apps
251 lines (199 loc) ⢠8.56 kB
JavaScript
const AntiCloneSDK = require('../index.js');
const fs = require('fs').promises;
const path = require('path');
class AntiCloneCLI {
constructor() {
this.sdk = new AntiCloneSDK();
this.configPath = path.join(process.cwd(), '.anticlone.json');
}
async run() {
const args = process.argv.slice(2);
const command = args[0];
try {
await this.loadConfig();
switch (command) {
case 'register':
await this.register();
break;
case 'config':
await this.configure();
break;
case 'fingerprint':
await this.generateFingerprint(args);
break;
case 'upload':
await this.uploadFingerprint(args);
break;
case 'profile':
await this.showProfile();
break;
case 'help':
default:
this.showHelp();
break;
}
} catch (error) {
console.error('ā Error:', error.message);
process.exit(1);
}
}
async loadConfig() {
try {
const config = await fs.readFile(this.configPath, 'utf8');
const { developerId, apiKey } = JSON.parse(config);
this.sdk.setCredentials(developerId, apiKey);
} catch (error) {
console.error('ā "Config file does not exist or is invalid":', error.message);
}
}
async saveConfig(developerId, apiKey) {
const config = { developerId, apiKey };
await fs.writeFile(this.configPath, JSON.stringify(config, null, 2));
console.log(`ā
Configuration saved to ${this.configPath}`);
}
async register() {
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
const question = (prompt) => new Promise(resolve => readline.question(prompt, resolve));
try {
console.log('š Developer Registration\n');
const developerName = await question('Developer Name: ');
const companyName = await question('Company Name (optional): ');
const email = await question('Email: ');
const phone = await question('Phone (optional): ');
const website = await question('Website (optional): ');
const developerInfo = {
developerName,
companyName: companyName || null,
email,
contactInfo: {
phone: phone || null,
website: website || null
}
};
const response = await this.sdk.registerDeveloper(developerInfo);
// Save credentials
await this.saveConfig(response.credentials.developerId, response.credentials.apiKey);
console.log('\nš Please save your passkey separately:');
console.log(`Passkey: ${response.credentials.passkey}\n`);
console.log('ā ļø Your account needs verification before you can upload fingerprints.');
} finally {
readline.close();
}
}
async configure() {
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
const question = (prompt) => new Promise(resolve => readline.question(prompt, resolve));
try {
console.log('āļø SDK Configuration\n');
const developerId = await question('Developer ID: ');
const apiKey = await question('API Key: ');
this.sdk.setCredentials(developerId, apiKey);
// Test credentials
await this.sdk.getDeveloperProfile();
await this.saveConfig(developerId, apiKey);
} finally {
readline.close();
}
}
async generateFingerprint(args) {
const inputPath = args[1];
const outputPath = args[2] || 'fingerprint.json';
if (!inputPath) {
throw new Error('Input path is required. Usage: anticlone fingerprint <path> [output]');
}
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
const question = (prompt) => new Promise(resolve => readline.question(prompt, resolve));
try {
console.log('š± App Information\n');
const appId = await question('App ID/Package Name: ');
const appName = await question('App Name: ');
const version = await question('Version: ');
const packageName = await question('Package Name (optional): ');
const appInfo = {
appId,
appName,
version,
packageName: packageName || appId
};
console.log('\nš Generating fingerprint...');
let fingerprint;
const stats = await fs.stat(inputPath);
if (stats.isDirectory()) {
fingerprint = await this.sdk.generateFingerprintFromProject(inputPath, appInfo);
} else {
fingerprint = await this.sdk.generateFingerprintFromFile(inputPath, appInfo);
}
await fs.writeFile(outputPath, JSON.stringify(fingerprint, null, 2));
console.log(`ā
Fingerprint generated and saved to ${outputPath}`);
console.log(`Overall Hash: ${fingerprint.overallHash}`);
console.log(`Files Analyzed: ${fingerprint.metadata.totalFiles || 'N/A'}`);
} finally {
readline.close();
}
}
async uploadFingerprint(args) {
const fingerprintPath = args[1] || 'fingerprint.json';
try {
const fingerprintData = await fs.readFile(fingerprintPath, 'utf8');
const fingerprint = JSON.parse(fingerprintData);
console.log('š¤ Uploading fingerprint...');
const response = await this.sdk.uploadFingerprint(fingerprint);
console.log(`ā
Upload successful! ID: ${response.id}`);
} catch (error) {
if (error.code === 'ENOENT') {
throw new Error(`Fingerprint file not found: ${fingerprintPath}`);
}
throw error;
}
}
async showProfile() {
const profile = await this.sdk.getDeveloperProfile();
if (profile.success) {
console.log('š¤ Developer Profile\n');
console.log(`Name: ${profile.profile.developer_name}`);
console.log(`Company: ${profile.profile.company_name || 'N/A'}`);
console.log(`Email: ${profile.profile.email}`);
console.log(`Status: ${profile.profile.verification_status}`);
console.log(`Registered: ${new Date(profile.profile.registration_date).toLocaleDateString()}`);
console.log(`Apps: ${profile.profile.app_count}`);
}
}
showHelp() {
console.log(`
š”ļø AntiClone SDK - App Fingerprinting Tool
USAGE:
anticlone <command> [options]
COMMANDS:
register Register as a new developer
config Configure SDK with your credentials
fingerprint <path> Generate fingerprint from project/APK/IPA
upload [file] Upload fingerprint to database
profile Show your developer profile
help Show this help message
EXAMPLES:
anticlone register
anticlone config
anticlone fingerprint ./my-app-project
anticlone fingerprint ./myapp.apk output.json
anticlone upload fingerprint.json
anticlone profile
For detailed documentation, visit: https://www.npmjs.com/package/anticlone-sdk?activeTab=readme
`);
}
}
// Run CLI
if (require.main === module) {
const cli = new AntiCloneCLI();
cli.run().catch(console.error);
}
module.exports = AntiCloneCLI;