1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const env_1 = require("./env");
|
4 | const fs_1 = require("./fs");
|
5 | const util_1 = require("util");
|
6 | const apple = require('app-store-scraper');
|
7 | const google = require('google-play-scraper');
|
8 | const { parseString } = require('xml2js');
|
9 | const parseXml = util_1.promisify(parseString);
|
10 | const Analytics = require('analytics-node');
|
11 | async function scrapeApp(ionicConfig, packageJson, codeDir) {
|
12 | const segmentKey = env_1.env.require('SEGMENT_WRITE_KEY');
|
13 | const userId = env_1.env.require('IONIC_USER_ID');
|
14 | const appId = env_1.env.require('APP_ID');
|
15 | const analytics = new Analytics(segmentKey);
|
16 | const flush = util_1.promisify(analytics.flush.bind(analytics));
|
17 | const configXml = await readXml(`${codeDir}/config.xml`);
|
18 | const appData = { appId: appId };
|
19 | appData.ionic_type = ionicConfig.type;
|
20 | const deps = packageJson.dependencies;
|
21 | if (deps) {
|
22 | appData.pro_client_version = hardVersion(deps['@ionic/pro']);
|
23 | appData.ionic_angular_version = hardVersion(deps['ionic-angular']);
|
24 | appData.cordova_ionic_version = hardVersion(deps['cordova-plugin-ionic']);
|
25 | }
|
26 | let appStoreInfo;
|
27 | let playStoreInfo;
|
28 | if (configXml && configXml.widget) {
|
29 | if (configXml.widget.$ && configXml.widget.$) {
|
30 | appStoreInfo = await scrapeApple(configXml.widget.$);
|
31 | Object.assign(appData, appStoreInfo);
|
32 | playStoreInfo = await scrapeGoogle(configXml.widget.$);
|
33 | Object.assign(appData, playStoreInfo);
|
34 | }
|
35 | if (configXml.widget.plugin) {
|
36 | appData.plugins = configXml.widget.plugin.map((x) => x.$.name).join();
|
37 | }
|
38 | }
|
39 | analytics.track({
|
40 | userId: userId,
|
41 | event: 'Ionic App Info',
|
42 | properties: appData
|
43 | });
|
44 | await flush();
|
45 | }
|
46 | exports.scrapeApp = scrapeApp;
|
47 | function hardVersion(semver) {
|
48 | if (semver) {
|
49 | return semver.split('.').map((s) => s.replace(/\D/g, '')).join('.');
|
50 | }
|
51 | }
|
52 | function processApple(obj) {
|
53 | let info = { ios_store: false };
|
54 | if (!obj) {
|
55 | return info;
|
56 | }
|
57 | info.ios_store = true;
|
58 | info.ios_id = obj.id;
|
59 | info.ios_bundle_id = obj.appId;
|
60 | info.ios_title = obj.title;
|
61 | info.ios_url = obj.url;
|
62 | info.ios_description = obj.description;
|
63 | info.ios_genre = obj.primaryGenre;
|
64 | info.ios_required_os_version = obj.requiredOsVersion;
|
65 | info.ios_released = new Date(obj.released);
|
66 | info.ios_updated = new Date(obj.updated);
|
67 | info.ios_version = obj.version;
|
68 | info.ios_free = obj.free;
|
69 | info.ios_developer_website = obj.developerWebsite;
|
70 | info.ios_developer_url = obj.developerUrl;
|
71 | return info;
|
72 | }
|
73 | function processGoogle(obj) {
|
74 | let info = { play_store: false };
|
75 | if (!obj) {
|
76 | return info;
|
77 | }
|
78 | info.play_store = true;
|
79 | info.play_title = obj.title;
|
80 | info.play_url = obj.url;
|
81 | info.play_bundle_id = obj.appId;
|
82 | info.play_free = obj.free;
|
83 | info.play_summary = obj.summary;
|
84 | info.play_min_installs = obj.minInstalls;
|
85 | info.play_max_installs = obj.maxInstalls;
|
86 | info.play_score = obj.score;
|
87 | info.play_developer_website = obj.developerWebsite;
|
88 | info.play_developer_email = obj.developerEmail;
|
89 | info.play_developer = obj.developer;
|
90 | info.play_updated = new Date(obj.updated);
|
91 | info.play_version = obj.version;
|
92 | info.play_genre = obj.genre;
|
93 | info.play_required_android_version = obj.androidVersion;
|
94 | info.play_description = obj.description;
|
95 | return info;
|
96 | }
|
97 | async function scrapeApple(widget) {
|
98 | let bundleId = widget['ios-CFBundleIdentifier'] || widget['id'];
|
99 | if (!bundleId || bundleId === 'io.ionic.starter')
|
100 | return processApple();
|
101 | try {
|
102 | let appleInfo = await apple.app({ appId: bundleId });
|
103 | return processApple(appleInfo);
|
104 | }
|
105 | catch (e) {
|
106 | return processApple();
|
107 | }
|
108 | }
|
109 | async function scrapeGoogle(widget) {
|
110 | let bundleId = widget['android-packageName'] || widget['id'];
|
111 | if (!bundleId || bundleId === 'io.ionic.starter')
|
112 | return processApple();
|
113 | if (!bundleId)
|
114 | return processGoogle();
|
115 | try {
|
116 | let googleInfo = await google.app({ appId: bundleId });
|
117 | return processGoogle(googleInfo);
|
118 | }
|
119 | catch (e) {
|
120 | return processGoogle();
|
121 | }
|
122 | }
|
123 | async function readXml(path) {
|
124 | try {
|
125 | const f = await fs_1.fsReadFile(path, { encoding: 'utf-8' });
|
126 | const o = await parseXml(f);
|
127 | return o;
|
128 | }
|
129 | catch (e) {
|
130 | if (e instanceof SyntaxError) {
|
131 | console.log(`Invalid XML in ${path}`);
|
132 | return;
|
133 | }
|
134 | }
|
135 | }
|