@mathrunet/masamune_workflow_sales 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +361 -0
- package/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/clients/app_store_scraper_client.d.ts +93 -0
- package/dist/clients/app_store_scraper_client.js +252 -0
- package/dist/clients/app_store_scraper_client.js.map +1 -0
- package/dist/clients/google_play_scraper_client.d.ts +92 -0
- package/dist/clients/google_play_scraper_client.js +240 -0
- package/dist/clients/google_play_scraper_client.js.map +1 -0
- package/dist/clients/website_contact_client.d.ts +77 -0
- package/dist/clients/website_contact_client.js +262 -0
- package/dist/clients/website_contact_client.js.map +1 -0
- package/dist/functions/collect_app_store_developers.d.ts +29 -0
- package/dist/functions/collect_app_store_developers.js +231 -0
- package/dist/functions/collect_app_store_developers.js.map +1 -0
- package/dist/functions/collect_google_play_developers.d.ts +38 -0
- package/dist/functions/collect_google_play_developers.js +239 -0
- package/dist/functions/collect_google_play_developers.js.map +1 -0
- package/dist/functions.d.ts +20 -0
- package/dist/functions.js +65 -0
- package/dist/functions.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/models/app_store_developer_data.d.ts +176 -0
- package/dist/models/app_store_developer_data.js +3 -0
- package/dist/models/app_store_developer_data.js.map +1 -0
- package/dist/models/google_play_developer_data.d.ts +165 -0
- package/dist/models/google_play_developer_data.js +3 -0
- package/dist/models/google_play_developer_data.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.WebsiteContactClient = void 0;
|
|
7
|
+
const puppeteer_core_1 = __importDefault(require("puppeteer-core"));
|
|
8
|
+
const chromium_1 = __importDefault(require("@sparticuz/chromium"));
|
|
9
|
+
/**
|
|
10
|
+
* Client for extracting contact information from websites using Puppeteer.
|
|
11
|
+
*
|
|
12
|
+
* Puppeteerを使用してWebサイトからコンタクト情報を抽出するクライアント。
|
|
13
|
+
*/
|
|
14
|
+
class WebsiteContactClient {
|
|
15
|
+
config;
|
|
16
|
+
browser = null;
|
|
17
|
+
/** Email regex pattern / メールアドレスの正規表現パターン */
|
|
18
|
+
emailRegex = /[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/g;
|
|
19
|
+
/** Contact page URL patterns / コンタクトページのURLパターン */
|
|
20
|
+
contactPatterns = [
|
|
21
|
+
/contact/i,
|
|
22
|
+
/support/i,
|
|
23
|
+
/about/i,
|
|
24
|
+
/inquiry/i,
|
|
25
|
+
/enquiry/i,
|
|
26
|
+
/お問い合わせ/,
|
|
27
|
+
/お問合せ/,
|
|
28
|
+
/連絡先/,
|
|
29
|
+
/お問合/,
|
|
30
|
+
/問い合わせ/
|
|
31
|
+
];
|
|
32
|
+
/** Email addresses to exclude (common false positives) / 除外するメールアドレス */
|
|
33
|
+
excludeEmails = [
|
|
34
|
+
/example\.com$/i,
|
|
35
|
+
/test\.com$/i,
|
|
36
|
+
/localhost$/i,
|
|
37
|
+
/your-?domain/i,
|
|
38
|
+
/domain\.com$/i,
|
|
39
|
+
/email\.com$/i,
|
|
40
|
+
/@2x\./i,
|
|
41
|
+
/@3x\./i,
|
|
42
|
+
/\.png$/i,
|
|
43
|
+
/\.jpg$/i,
|
|
44
|
+
/\.svg$/i
|
|
45
|
+
];
|
|
46
|
+
constructor(config = {}) {
|
|
47
|
+
this.config = {
|
|
48
|
+
pageTimeout: config.pageTimeout ?? 10000,
|
|
49
|
+
maxContactPages: config.maxContactPages ?? 2
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get or create browser instance.
|
|
54
|
+
*
|
|
55
|
+
* ブラウザインスタンスを取得または作成。
|
|
56
|
+
*/
|
|
57
|
+
async getBrowser() {
|
|
58
|
+
if (this.browser) {
|
|
59
|
+
return this.browser;
|
|
60
|
+
}
|
|
61
|
+
// Configure chromium for Cloud Functions environment
|
|
62
|
+
chromium_1.default.setGraphicsMode = false;
|
|
63
|
+
this.browser = await puppeteer_core_1.default.launch({
|
|
64
|
+
args: chromium_1.default.args,
|
|
65
|
+
defaultViewport: chromium_1.default.defaultViewport,
|
|
66
|
+
executablePath: await chromium_1.default.executablePath(),
|
|
67
|
+
headless: true
|
|
68
|
+
});
|
|
69
|
+
return this.browser;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Extract contact information from a website.
|
|
73
|
+
*
|
|
74
|
+
* Webサイトからコンタクト情報を抽出。
|
|
75
|
+
*
|
|
76
|
+
* @param websiteUrl Website URL / WebサイトURL
|
|
77
|
+
* @returns Contact information / コンタクト情報
|
|
78
|
+
*/
|
|
79
|
+
async extractContactInfo(websiteUrl) {
|
|
80
|
+
const result = {
|
|
81
|
+
emails: [],
|
|
82
|
+
contactPageUrls: []
|
|
83
|
+
};
|
|
84
|
+
let page = null;
|
|
85
|
+
try {
|
|
86
|
+
const browser = await this.getBrowser();
|
|
87
|
+
page = await browser.newPage();
|
|
88
|
+
// Set timeout and user agent
|
|
89
|
+
await page.setDefaultNavigationTimeout(this.config.pageTimeout);
|
|
90
|
+
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
|
|
91
|
+
// Navigate to the main page
|
|
92
|
+
console.log(`Navigating to: ${websiteUrl}`);
|
|
93
|
+
await page.goto(websiteUrl, { waitUntil: "networkidle2" });
|
|
94
|
+
// Extract emails from main page
|
|
95
|
+
const mainPageEmails = await this.extractEmailsFromPage(page);
|
|
96
|
+
result.emails.push(...mainPageEmails);
|
|
97
|
+
// Find contact page URLs
|
|
98
|
+
const contactPageUrls = await this.findContactPageUrls(page, websiteUrl);
|
|
99
|
+
result.contactPageUrls = contactPageUrls;
|
|
100
|
+
// Visit contact pages to find more emails
|
|
101
|
+
const pagesToVisit = contactPageUrls.slice(0, this.config.maxContactPages);
|
|
102
|
+
for (const contactUrl of pagesToVisit) {
|
|
103
|
+
try {
|
|
104
|
+
console.log(`Visiting contact page: ${contactUrl}`);
|
|
105
|
+
await page.goto(contactUrl, { waitUntil: "networkidle2" });
|
|
106
|
+
const contactPageEmails = await this.extractEmailsFromPage(page);
|
|
107
|
+
result.emails.push(...contactPageEmails);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
console.warn(`Failed to visit contact page: ${contactUrl}`, err);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Remove duplicates and filter invalid emails
|
|
114
|
+
result.emails = this.filterEmails([...new Set(result.emails)]);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.warn(`Failed to extract contact info from: ${websiteUrl}`, error);
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
if (page) {
|
|
121
|
+
await page.close();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Extract email addresses from a page (after JS rendering).
|
|
128
|
+
*
|
|
129
|
+
* ページからメールアドレスを抽出(JSレンダリング後)。
|
|
130
|
+
*
|
|
131
|
+
* @param page Puppeteer page / Puppeteerページ
|
|
132
|
+
* @returns List of email addresses / メールアドレス一覧
|
|
133
|
+
*/
|
|
134
|
+
async extractEmailsFromPage(page) {
|
|
135
|
+
const emails = [];
|
|
136
|
+
try {
|
|
137
|
+
// Method 1: Extract from mailto: links
|
|
138
|
+
const mailtoEmails = await page.evaluate(() => {
|
|
139
|
+
const links = document.querySelectorAll('a[href^="mailto:"]');
|
|
140
|
+
return Array.from(links).map(link => {
|
|
141
|
+
const href = link.getAttribute("href") || "";
|
|
142
|
+
const email = href.replace(/^mailto:/i, "").split("?")[0];
|
|
143
|
+
return email.trim();
|
|
144
|
+
}).filter(e => e.length > 0);
|
|
145
|
+
});
|
|
146
|
+
emails.push(...mailtoEmails);
|
|
147
|
+
// Method 2: Extract from page content using regex
|
|
148
|
+
const pageContent = await page.evaluate(() => {
|
|
149
|
+
return document.body.innerText || "";
|
|
150
|
+
});
|
|
151
|
+
const contentEmails = pageContent.match(this.emailRegex) || [];
|
|
152
|
+
emails.push(...contentEmails);
|
|
153
|
+
// Method 3: Check common email display elements
|
|
154
|
+
const elementEmails = await page.evaluate(() => {
|
|
155
|
+
const selectors = [
|
|
156
|
+
'[class*="email"]',
|
|
157
|
+
'[class*="contact"]',
|
|
158
|
+
'[id*="email"]',
|
|
159
|
+
'[id*="contact"]',
|
|
160
|
+
'address',
|
|
161
|
+
'.footer',
|
|
162
|
+
'#footer'
|
|
163
|
+
];
|
|
164
|
+
const found = [];
|
|
165
|
+
for (const selector of selectors) {
|
|
166
|
+
const elements = document.querySelectorAll(selector);
|
|
167
|
+
elements.forEach(el => {
|
|
168
|
+
const text = el.textContent || "";
|
|
169
|
+
found.push(text);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return found;
|
|
173
|
+
});
|
|
174
|
+
for (const text of elementEmails) {
|
|
175
|
+
const matches = text.match(this.emailRegex) || [];
|
|
176
|
+
emails.push(...matches);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
console.warn("Failed to extract emails from page", error);
|
|
181
|
+
}
|
|
182
|
+
return emails;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Find contact page URLs on the current page.
|
|
186
|
+
*
|
|
187
|
+
* 現在のページからコンタクトページのURLを探索。
|
|
188
|
+
*
|
|
189
|
+
* @param page Puppeteer page / Puppeteerページ
|
|
190
|
+
* @param baseUrl Base URL for resolving relative URLs / 相対URLを解決するためのベースURL
|
|
191
|
+
* @returns List of contact page URLs / コンタクトページURL一覧
|
|
192
|
+
*/
|
|
193
|
+
async findContactPageUrls(page, baseUrl) {
|
|
194
|
+
try {
|
|
195
|
+
const allLinks = await page.evaluate(() => {
|
|
196
|
+
const links = document.querySelectorAll("a[href]");
|
|
197
|
+
return Array.from(links).map(link => ({
|
|
198
|
+
href: link.getAttribute("href") || "",
|
|
199
|
+
text: link.textContent?.trim() || ""
|
|
200
|
+
}));
|
|
201
|
+
});
|
|
202
|
+
const contactUrls = [];
|
|
203
|
+
const baseUrlObj = new URL(baseUrl);
|
|
204
|
+
for (const link of allLinks) {
|
|
205
|
+
// Check if link text or href matches contact patterns
|
|
206
|
+
const isContactLink = this.contactPatterns.some(pattern => pattern.test(link.href) || pattern.test(link.text));
|
|
207
|
+
if (isContactLink && link.href) {
|
|
208
|
+
try {
|
|
209
|
+
// Resolve relative URL
|
|
210
|
+
const fullUrl = new URL(link.href, baseUrl);
|
|
211
|
+
// Only include URLs from the same domain
|
|
212
|
+
if (fullUrl.hostname === baseUrlObj.hostname) {
|
|
213
|
+
contactUrls.push(fullUrl.href);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// Invalid URL, skip
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// Remove duplicates
|
|
222
|
+
return [...new Set(contactUrls)];
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
console.warn("Failed to find contact page URLs", error);
|
|
226
|
+
return [];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Filter out invalid or unwanted email addresses.
|
|
231
|
+
*
|
|
232
|
+
* 無効または不要なメールアドレスを除外。
|
|
233
|
+
*
|
|
234
|
+
* @param emails List of emails / メールアドレス一覧
|
|
235
|
+
* @returns Filtered emails / フィルタリングされたメールアドレス一覧
|
|
236
|
+
*/
|
|
237
|
+
filterEmails(emails) {
|
|
238
|
+
return emails.filter(email => {
|
|
239
|
+
// Check if email matches any exclude pattern
|
|
240
|
+
const isExcluded = this.excludeEmails.some(pattern => pattern.test(email));
|
|
241
|
+
if (isExcluded) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
// Basic email validation
|
|
245
|
+
const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
246
|
+
return isValid;
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Close the browser instance.
|
|
251
|
+
*
|
|
252
|
+
* ブラウザインスタンスを閉じる。
|
|
253
|
+
*/
|
|
254
|
+
async close() {
|
|
255
|
+
if (this.browser) {
|
|
256
|
+
await this.browser.close();
|
|
257
|
+
this.browser = null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
exports.WebsiteContactClient = WebsiteContactClient;
|
|
262
|
+
//# sourceMappingURL=website_contact_client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"website_contact_client.js","sourceRoot":"","sources":["../../src/clients/website_contact_client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Action, WorkflowProcessFunctionBase, WorkflowContext } from "@mathrunet/masamune_firebase_workflow";
|
|
2
|
+
/**
|
|
3
|
+
* A function for collecting developer information from App Store.
|
|
4
|
+
*
|
|
5
|
+
* App Storeからデベロッパー情報を収集するためのFunction。
|
|
6
|
+
*/
|
|
7
|
+
export declare class CollectAppStoreDevelopers extends WorkflowProcessFunctionBase {
|
|
8
|
+
/**
|
|
9
|
+
* The ID of the function.
|
|
10
|
+
*
|
|
11
|
+
* 関数のID。
|
|
12
|
+
*/
|
|
13
|
+
id: string;
|
|
14
|
+
/**
|
|
15
|
+
* The process of the function.
|
|
16
|
+
*
|
|
17
|
+
* @param context The context of the function.
|
|
18
|
+
* @returns The action of the function.
|
|
19
|
+
*/
|
|
20
|
+
process(context: WorkflowContext): Promise<Action>;
|
|
21
|
+
/**
|
|
22
|
+
* Save developer info to Firestore.
|
|
23
|
+
*
|
|
24
|
+
* デベロッパー情報をFirestoreに保存。
|
|
25
|
+
*
|
|
26
|
+
* @param devInfo Developer information / デベロッパー情報
|
|
27
|
+
*/
|
|
28
|
+
private saveToFirestore;
|
|
29
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CollectAppStoreDevelopers = void 0;
|
|
37
|
+
const admin = __importStar(require("firebase-admin"));
|
|
38
|
+
const masamune_firebase_workflow_1 = require("@mathrunet/masamune_firebase_workflow");
|
|
39
|
+
const app_store_scraper_client_1 = require("../clients/app_store_scraper_client");
|
|
40
|
+
/**
|
|
41
|
+
* A function for collecting developer information from App Store.
|
|
42
|
+
*
|
|
43
|
+
* App Storeからデベロッパー情報を収集するためのFunction。
|
|
44
|
+
*/
|
|
45
|
+
class CollectAppStoreDevelopers extends masamune_firebase_workflow_1.WorkflowProcessFunctionBase {
|
|
46
|
+
/**
|
|
47
|
+
* The ID of the function.
|
|
48
|
+
*
|
|
49
|
+
* 関数のID。
|
|
50
|
+
*/
|
|
51
|
+
id = "collect_app_store_developers";
|
|
52
|
+
/**
|
|
53
|
+
* The process of the function.
|
|
54
|
+
*
|
|
55
|
+
* @param context The context of the function.
|
|
56
|
+
* @returns The action of the function.
|
|
57
|
+
*/
|
|
58
|
+
async process(context) {
|
|
59
|
+
const action = context.action;
|
|
60
|
+
const params = action.command?.data;
|
|
61
|
+
// 1. Validate parameters
|
|
62
|
+
if (!params?.mode) {
|
|
63
|
+
console.warn("CollectAppStoreDevelopers: No mode specified");
|
|
64
|
+
return {
|
|
65
|
+
...action,
|
|
66
|
+
results: {
|
|
67
|
+
appStoreDevelopers: {
|
|
68
|
+
stats: {
|
|
69
|
+
mode: "developer_ids",
|
|
70
|
+
targetCount: 0,
|
|
71
|
+
collectedCount: 0,
|
|
72
|
+
withEmailCount: 0,
|
|
73
|
+
savedCount: 0
|
|
74
|
+
},
|
|
75
|
+
developers: [],
|
|
76
|
+
error: "No mode specified in command parameters"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// 2. Initialize client
|
|
82
|
+
const client = new app_store_scraper_client_1.AppStoreScraperClient({
|
|
83
|
+
lang: params.lang ?? "ja",
|
|
84
|
+
country: params.country ?? "jp",
|
|
85
|
+
enableWebsiteScraping: true
|
|
86
|
+
});
|
|
87
|
+
const maxCount = params.maxCount ?? 100;
|
|
88
|
+
const collectedDevelopers = [];
|
|
89
|
+
const processedDevIds = new Set();
|
|
90
|
+
let savedCount = 0;
|
|
91
|
+
try {
|
|
92
|
+
// 3. Get target developer IDs based on mode
|
|
93
|
+
let targetDevIds = [];
|
|
94
|
+
switch (params.mode) {
|
|
95
|
+
case "developer_ids":
|
|
96
|
+
targetDevIds = params.developerIds ?? [];
|
|
97
|
+
break;
|
|
98
|
+
case "category_ranking":
|
|
99
|
+
if (!params.categoryConfig) {
|
|
100
|
+
throw new Error("categoryConfig is required for category_ranking mode");
|
|
101
|
+
}
|
|
102
|
+
const listApps = await client.getListApps(params.categoryConfig);
|
|
103
|
+
targetDevIds = client.extractDeveloperIds(listApps);
|
|
104
|
+
break;
|
|
105
|
+
case "search_keyword":
|
|
106
|
+
if (!params.searchConfig) {
|
|
107
|
+
throw new Error("searchConfig is required for search_keyword mode");
|
|
108
|
+
}
|
|
109
|
+
const searchApps = await client.searchApps(params.searchConfig);
|
|
110
|
+
targetDevIds = client.extractDeveloperIds(searchApps);
|
|
111
|
+
break;
|
|
112
|
+
default:
|
|
113
|
+
throw new Error(`Unknown mode: ${params.mode}`);
|
|
114
|
+
}
|
|
115
|
+
console.log(`CollectAppStoreDevelopers: Found ${targetDevIds.length} target developers`);
|
|
116
|
+
// 4. Collect developer information
|
|
117
|
+
for (const devId of targetDevIds) {
|
|
118
|
+
if (collectedDevelopers.length >= maxCount) {
|
|
119
|
+
console.log(`CollectAppStoreDevelopers: Reached maxCount limit (${maxCount})`);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
if (processedDevIds.has(devId)) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
processedDevIds.add(devId);
|
|
126
|
+
try {
|
|
127
|
+
const devInfo = await client.getDeveloperInfo(devId);
|
|
128
|
+
if (devInfo) {
|
|
129
|
+
collectedDevelopers.push(devInfo);
|
|
130
|
+
// 5. Save to Firestore
|
|
131
|
+
await this.saveToFirestore(devInfo);
|
|
132
|
+
savedCount++;
|
|
133
|
+
console.log(`CollectAppStoreDevelopers: Collected ${devInfo.developerName} (email: ${devInfo.email ?? "none"})`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
console.warn(`CollectAppStoreDevelopers: Failed to collect developer: ${devId}`, err.message);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// 6. Create statistics
|
|
141
|
+
const stats = {
|
|
142
|
+
mode: params.mode,
|
|
143
|
+
targetCount: targetDevIds.length,
|
|
144
|
+
collectedCount: collectedDevelopers.length,
|
|
145
|
+
withEmailCount: collectedDevelopers.filter(d => d.email).length,
|
|
146
|
+
savedCount: savedCount
|
|
147
|
+
};
|
|
148
|
+
const result = {
|
|
149
|
+
stats: stats,
|
|
150
|
+
developers: collectedDevelopers
|
|
151
|
+
};
|
|
152
|
+
console.log(`CollectAppStoreDevelopers: Completed - ${stats.collectedCount} collected, ${stats.withEmailCount} with email`);
|
|
153
|
+
// 7. Return results
|
|
154
|
+
return {
|
|
155
|
+
...action,
|
|
156
|
+
results: {
|
|
157
|
+
appStoreDevelopers: result
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
console.error("CollectAppStoreDevelopers: Failed to collect data", error);
|
|
163
|
+
return {
|
|
164
|
+
...action,
|
|
165
|
+
results: {
|
|
166
|
+
appStoreDevelopers: {
|
|
167
|
+
stats: {
|
|
168
|
+
mode: params.mode,
|
|
169
|
+
targetCount: 0,
|
|
170
|
+
collectedCount: collectedDevelopers.length,
|
|
171
|
+
withEmailCount: collectedDevelopers.filter(d => d.email).length,
|
|
172
|
+
savedCount: savedCount
|
|
173
|
+
},
|
|
174
|
+
developers: collectedDevelopers,
|
|
175
|
+
error: error.message
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
// 8. Cleanup browser resources
|
|
182
|
+
await client.close();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Save developer info to Firestore.
|
|
187
|
+
*
|
|
188
|
+
* デベロッパー情報をFirestoreに保存。
|
|
189
|
+
*
|
|
190
|
+
* @param devInfo Developer information / デベロッパー情報
|
|
191
|
+
*/
|
|
192
|
+
async saveToFirestore(devInfo) {
|
|
193
|
+
const firestore = admin.firestore();
|
|
194
|
+
const docId = `appStore_${devInfo.developerId}`;
|
|
195
|
+
const docPath = `plugins/workflow/address/${docId}`;
|
|
196
|
+
const now = admin.firestore.Timestamp.now();
|
|
197
|
+
// Convert ModelTimestamp to Firestore Timestamp
|
|
198
|
+
const collectedTimestamp = devInfo.collectedTime
|
|
199
|
+
? admin.firestore.Timestamp.fromDate(devInfo.collectedTime.value())
|
|
200
|
+
: now;
|
|
201
|
+
// Build document, omitting undefined values
|
|
202
|
+
const addressDoc = {
|
|
203
|
+
source: "appStore",
|
|
204
|
+
developerId: devInfo.developerId,
|
|
205
|
+
developerName: devInfo.developerName,
|
|
206
|
+
appNames: devInfo.apps.slice(0, 5).map(a => a.title),
|
|
207
|
+
appDescriptions: devInfo.apps.slice(0, 3).map(a => a.description ?? ""),
|
|
208
|
+
appCount: devInfo.apps.length,
|
|
209
|
+
collectedTime: collectedTimestamp,
|
|
210
|
+
updatedTime: now
|
|
211
|
+
};
|
|
212
|
+
// Add optional fields only if they have values
|
|
213
|
+
if (devInfo.companyName)
|
|
214
|
+
addressDoc.companyName = devInfo.companyName;
|
|
215
|
+
if (devInfo.email)
|
|
216
|
+
addressDoc.email = devInfo.email;
|
|
217
|
+
if (devInfo.website)
|
|
218
|
+
addressDoc.website = devInfo.website;
|
|
219
|
+
if (devInfo.developerUrl)
|
|
220
|
+
addressDoc.developerUrl = devInfo.developerUrl;
|
|
221
|
+
if (devInfo.contactPageUrls && devInfo.contactPageUrls.length > 0) {
|
|
222
|
+
addressDoc.contactPageUrls = devInfo.contactPageUrls;
|
|
223
|
+
}
|
|
224
|
+
await firestore.doc(docPath).set(addressDoc, { merge: true });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
exports.CollectAppStoreDevelopers = CollectAppStoreDevelopers;
|
|
228
|
+
module.exports = (regions, options, data) => new CollectAppStoreDevelopers(options).build(regions);
|
|
229
|
+
// Export class for testing
|
|
230
|
+
module.exports.CollectAppStoreDevelopers = CollectAppStoreDevelopers;
|
|
231
|
+
//# sourceMappingURL=collect_app_store_developers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect_app_store_developers.js","sourceRoot":"","sources":["../../src/functions/collect_app_store_developers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Action, WorkflowProcessFunctionBase, WorkflowContext } from "@mathrunet/masamune_firebase_workflow";
|
|
2
|
+
/**
|
|
3
|
+
* A function for collecting developer information from Google Play.
|
|
4
|
+
*
|
|
5
|
+
* Google Playからデベロッパー情報を収集するためのFunction。
|
|
6
|
+
*/
|
|
7
|
+
export declare class CollectGooglePlayDevelopers extends WorkflowProcessFunctionBase {
|
|
8
|
+
/**
|
|
9
|
+
* The ID of the function.
|
|
10
|
+
*
|
|
11
|
+
* 関数のID。
|
|
12
|
+
*/
|
|
13
|
+
id: string;
|
|
14
|
+
/**
|
|
15
|
+
* The process of the function.
|
|
16
|
+
*
|
|
17
|
+
* @param context The context of the function.
|
|
18
|
+
* @returns The action of the function.
|
|
19
|
+
*/
|
|
20
|
+
process(context: WorkflowContext): Promise<Action>;
|
|
21
|
+
/**
|
|
22
|
+
* Save developer info to Firestore.
|
|
23
|
+
*
|
|
24
|
+
* デベロッパー情報をFirestoreに保存。
|
|
25
|
+
*
|
|
26
|
+
* @param devInfo Developer information / デベロッパー情報
|
|
27
|
+
*/
|
|
28
|
+
private saveToFirestore;
|
|
29
|
+
/**
|
|
30
|
+
* Sanitize developer ID for Firestore document ID.
|
|
31
|
+
*
|
|
32
|
+
* FirestoreドキュメントID用にデベロッパーIDをサニタイズ。
|
|
33
|
+
*
|
|
34
|
+
* @param id Developer ID / デベロッパーID
|
|
35
|
+
* @returns Sanitized ID / サニタイズされたID
|
|
36
|
+
*/
|
|
37
|
+
private sanitizeId;
|
|
38
|
+
}
|