domain-search-mcp 1.2.34 → 1.3.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/dist/server.d.ts +3 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +27 -1
- package/dist/server.js.map +1 -1
- package/dist/services/domain-hunter.d.ts +96 -0
- package/dist/services/domain-hunter.d.ts.map +1 -0
- package/dist/services/domain-hunter.js +477 -0
- package/dist/services/domain-hunter.js.map +1 -0
- package/dist/services/project-analyzer.d.ts +66 -0
- package/dist/services/project-analyzer.d.ts.map +1 -0
- package/dist/services/project-analyzer.js +419 -0
- package/dist/services/project-analyzer.js.map +1 -0
- package/dist/services/qwen-inference.d.ts +45 -2
- package/dist/services/qwen-inference.d.ts.map +1 -1
- package/dist/services/qwen-inference.js +223 -12
- package/dist/services/qwen-inference.js.map +1 -1
- package/dist/tools/analyze_project.d.ts +116 -0
- package/dist/tools/analyze_project.d.ts.map +1 -0
- package/dist/tools/analyze_project.js +214 -0
- package/dist/tools/analyze_project.js.map +1 -0
- package/dist/tools/hunt_domains.d.ts +155 -0
- package/dist/tools/hunt_domains.d.ts.map +1 -0
- package/dist/tools/hunt_domains.js +228 -0
- package/dist/tools/hunt_domains.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +9 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/suggest_domains_smart.d.ts +62 -0
- package/dist/tools/suggest_domains_smart.d.ts.map +1 -1
- package/dist/tools/suggest_domains_smart.js +33 -2
- package/dist/tools/suggest_domains_smart.js.map +1 -1
- package/package.json +1 -1
- package/src/server.ts +39 -1
- package/src/services/domain-hunter.ts +635 -0
- package/src/services/project-analyzer.ts +497 -0
- package/src/services/qwen-inference.ts +283 -11
- package/src/tools/analyze_project.ts +280 -0
- package/src/tools/hunt_domains.ts +287 -0
- package/src/tools/index.ts +14 -0
- package/src/tools/suggest_domains_smart.ts +37 -3
package/dist/server.d.ts
CHANGED
|
@@ -10,9 +10,11 @@
|
|
|
10
10
|
* - bulk_search: Check many domains at once
|
|
11
11
|
* - compare_registrars: Compare pricing across registrars
|
|
12
12
|
* - suggest_domains: Generate available name variations
|
|
13
|
-
* - suggest_domains_smart: AI-powered domain suggestions with
|
|
13
|
+
* - suggest_domains_smart: AI-powered domain suggestions with Qwen 2.5-7B
|
|
14
14
|
* - tld_info: Get TLD information and recommendations
|
|
15
15
|
* - check_socials: Check social handle availability
|
|
16
|
+
* - analyze_project: Extract context from projects for domain suggestions
|
|
17
|
+
* - hunt_domains: Find valuable domains for investment
|
|
16
18
|
*
|
|
17
19
|
* @see https://github.com/yourusername/domain-search-mcp
|
|
18
20
|
*/
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG"}
|
package/dist/server.js
CHANGED
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
* - bulk_search: Check many domains at once
|
|
12
12
|
* - compare_registrars: Compare pricing across registrars
|
|
13
13
|
* - suggest_domains: Generate available name variations
|
|
14
|
-
* - suggest_domains_smart: AI-powered domain suggestions with
|
|
14
|
+
* - suggest_domains_smart: AI-powered domain suggestions with Qwen 2.5-7B
|
|
15
15
|
* - tld_info: Get TLD information and recommendations
|
|
16
16
|
* - check_socials: Check social handle availability
|
|
17
|
+
* - analyze_project: Extract context from projects for domain suggestions
|
|
18
|
+
* - hunt_domains: Find valuable domains for investment
|
|
17
19
|
*
|
|
18
20
|
* @see https://github.com/yourusername/domain-search-mcp
|
|
19
21
|
*/
|
|
@@ -42,6 +44,8 @@ const TOOLS = [
|
|
|
42
44
|
index_js_2.suggestDomainsSmartTool,
|
|
43
45
|
index_js_2.tldInfoTool,
|
|
44
46
|
index_js_2.checkSocialsTool,
|
|
47
|
+
index_js_2.analyzeProjectTool,
|
|
48
|
+
index_js_2.huntDomainsTool,
|
|
45
49
|
];
|
|
46
50
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
47
51
|
// Server Implementation
|
|
@@ -151,6 +155,7 @@ async function executeToolCall(name, args) {
|
|
|
151
155
|
style: args.style || 'brandable',
|
|
152
156
|
max_suggestions: args.max_suggestions || 15,
|
|
153
157
|
include_premium: args.include_premium || false,
|
|
158
|
+
project_context: args.project_context,
|
|
154
159
|
});
|
|
155
160
|
case 'tld_info':
|
|
156
161
|
return (0, index_js_2.executeTldInfo)({
|
|
@@ -162,6 +167,27 @@ async function executeToolCall(name, args) {
|
|
|
162
167
|
name: args.name,
|
|
163
168
|
platforms: args.platforms,
|
|
164
169
|
});
|
|
170
|
+
case 'analyze_project':
|
|
171
|
+
return (0, index_js_2.executeAnalyzeProject)({
|
|
172
|
+
path: args.path,
|
|
173
|
+
include_source_files: args.include_source_files || false,
|
|
174
|
+
suggest_domains: args.suggest_domains !== false, // Default true
|
|
175
|
+
tld: args.tld || 'com',
|
|
176
|
+
max_suggestions: args.max_suggestions || 10,
|
|
177
|
+
style: args.style || 'brandable',
|
|
178
|
+
});
|
|
179
|
+
case 'hunt_domains':
|
|
180
|
+
return (0, index_js_2.executeHuntDomains)({
|
|
181
|
+
keywords: args.keywords,
|
|
182
|
+
tlds: args.tlds || ['com', 'io', 'co'],
|
|
183
|
+
min_length: args.min_length || 3,
|
|
184
|
+
max_length: args.max_length || 12,
|
|
185
|
+
include_aftermarket: args.include_aftermarket !== false, // Default true
|
|
186
|
+
max_aftermarket_price: args.max_aftermarket_price,
|
|
187
|
+
patterns: args.patterns || ['short', 'brandable'],
|
|
188
|
+
max_results: args.max_results || 20,
|
|
189
|
+
score_threshold: args.score_threshold || 40,
|
|
190
|
+
});
|
|
165
191
|
default:
|
|
166
192
|
throw new errors_js_1.DomainSearchError('UNKNOWN_TOOL', `Unknown tool: ${name}`, `The tool "${name}" is not available.`, {
|
|
167
193
|
retryable: false,
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;AACA
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain Hunter Service
|
|
3
|
+
*
|
|
4
|
+
* Finds valuable domains for investment opportunities:
|
|
5
|
+
* - Pattern-based generation (short, dictionary, brandable, acronym)
|
|
6
|
+
* - Sedo auction filtering
|
|
7
|
+
* - Investment scoring algorithm
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Pattern types for domain generation.
|
|
11
|
+
*/
|
|
12
|
+
export type HuntPattern = 'short' | 'dictionary' | 'numeric' | 'brandable' | 'acronym';
|
|
13
|
+
/**
|
|
14
|
+
* Criteria for hunting domains.
|
|
15
|
+
*/
|
|
16
|
+
export interface HuntCriteria {
|
|
17
|
+
/** Keywords to search for */
|
|
18
|
+
keywords?: string[];
|
|
19
|
+
/** TLDs to check */
|
|
20
|
+
tlds?: string[];
|
|
21
|
+
/** Minimum domain name length */
|
|
22
|
+
minLength?: number;
|
|
23
|
+
/** Maximum domain name length */
|
|
24
|
+
maxLength?: number;
|
|
25
|
+
/** Include Sedo auctions */
|
|
26
|
+
includeAftermarket?: boolean;
|
|
27
|
+
/** Maximum aftermarket price (USD) */
|
|
28
|
+
maxAftermarketPrice?: number;
|
|
29
|
+
/** Pattern types to generate */
|
|
30
|
+
patterns?: HuntPattern[];
|
|
31
|
+
/** Maximum results to return */
|
|
32
|
+
maxResults?: number;
|
|
33
|
+
/** Minimum investment score (0-100) */
|
|
34
|
+
scoreThreshold?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Investment score breakdown.
|
|
38
|
+
*/
|
|
39
|
+
export interface InvestmentScore {
|
|
40
|
+
/** Overall score (0-100) */
|
|
41
|
+
total: number;
|
|
42
|
+
/** Score factors */
|
|
43
|
+
factors: {
|
|
44
|
+
length: number;
|
|
45
|
+
tldValue: number;
|
|
46
|
+
keywordMatch: number;
|
|
47
|
+
pronounceability: number;
|
|
48
|
+
aftermarketPrice?: number;
|
|
49
|
+
pattern?: number;
|
|
50
|
+
};
|
|
51
|
+
/** Grade (A-F) */
|
|
52
|
+
grade: 'A' | 'B' | 'C' | 'D' | 'F';
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A hunted domain result.
|
|
56
|
+
*/
|
|
57
|
+
export interface HuntedDomain {
|
|
58
|
+
domain: string;
|
|
59
|
+
tld: string;
|
|
60
|
+
available: boolean;
|
|
61
|
+
/** Investment score details */
|
|
62
|
+
investment_score: InvestmentScore;
|
|
63
|
+
/** Source of the domain */
|
|
64
|
+
source: 'pattern_generated' | 'sedo_auction';
|
|
65
|
+
/** Aftermarket info if from Sedo */
|
|
66
|
+
aftermarket?: {
|
|
67
|
+
price: number | null;
|
|
68
|
+
currency: string | null;
|
|
69
|
+
auction_end?: string | null;
|
|
70
|
+
url: string;
|
|
71
|
+
};
|
|
72
|
+
/** Pattern used to generate (if applicable) */
|
|
73
|
+
pattern?: HuntPattern;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Hunt domains response.
|
|
77
|
+
*/
|
|
78
|
+
export interface HuntDomainsResponse {
|
|
79
|
+
results: HuntedDomain[];
|
|
80
|
+
total_scanned: number;
|
|
81
|
+
filters_applied: string[];
|
|
82
|
+
insights: string[];
|
|
83
|
+
sources: {
|
|
84
|
+
sedo_auctions: number;
|
|
85
|
+
pattern_generated: number;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Calculate investment score for a domain.
|
|
90
|
+
*/
|
|
91
|
+
export declare function calculateInvestmentScore(domain: string, tld: string, keywords?: string[], aftermarketPrice?: number, pattern?: HuntPattern): InvestmentScore;
|
|
92
|
+
/**
|
|
93
|
+
* Hunt for valuable domains.
|
|
94
|
+
*/
|
|
95
|
+
export declare function huntDomains(criteria: HuntCriteria): Promise<HuntDomainsResponse>;
|
|
96
|
+
//# sourceMappingURL=domain-hunter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-hunter.d.ts","sourceRoot":"","sources":["../../src/services/domain-hunter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB;IACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sCAAsC;IACtC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gCAAgC;IAChC,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,kBAAkB;IAClB,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,gBAAgB,EAAE,eAAe,CAAC;IAClC,2BAA2B;IAC3B,MAAM,EAAE,mBAAmB,GAAG,cAAc,CAAC;IAC7C,oCAAoC;IACpC,WAAW,CAAC,EAAE;QACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,+CAA+C;IAC/C,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE;QACP,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH;AAgLD;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,EAAO,EACvB,gBAAgB,CAAC,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,WAAW,GACpB,eAAe,CAyFjB;AAMD;;GAEG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA0PtF"}
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Domain Hunter Service
|
|
4
|
+
*
|
|
5
|
+
* Finds valuable domains for investment opportunities:
|
|
6
|
+
* - Pattern-based generation (short, dictionary, brandable, acronym)
|
|
7
|
+
* - Sedo auction filtering
|
|
8
|
+
* - Investment scoring algorithm
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.calculateInvestmentScore = calculateInvestmentScore;
|
|
12
|
+
exports.huntDomains = huntDomains;
|
|
13
|
+
const domain_search_js_1 = require("./domain-search.js");
|
|
14
|
+
const sedo_js_1 = require("../aftermarket/sedo.js");
|
|
15
|
+
const config_js_1 = require("../config.js");
|
|
16
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
17
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
18
|
+
// PATTERN GENERATION
|
|
19
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
20
|
+
/**
|
|
21
|
+
* Short domain patterns (3-5 letters).
|
|
22
|
+
*/
|
|
23
|
+
const SHORT_PATTERNS = [
|
|
24
|
+
// 3-letter patterns: consonant-vowel-consonant
|
|
25
|
+
...generateCVCPatterns(3),
|
|
26
|
+
// 4-letter patterns
|
|
27
|
+
...generateCVCPatterns(4),
|
|
28
|
+
// 5-letter memorable patterns
|
|
29
|
+
...generateCVCPatterns(5),
|
|
30
|
+
];
|
|
31
|
+
/**
|
|
32
|
+
* Generate consonant-vowel-consonant patterns.
|
|
33
|
+
*/
|
|
34
|
+
function generateCVCPatterns(length) {
|
|
35
|
+
const consonants = 'bcdfghjklmnprstvwxyz'.split('');
|
|
36
|
+
const vowels = 'aeiou'.split('');
|
|
37
|
+
const patterns = [];
|
|
38
|
+
if (length === 3) {
|
|
39
|
+
// CVC pattern
|
|
40
|
+
for (const c1 of consonants.slice(0, 10)) {
|
|
41
|
+
for (const v of vowels) {
|
|
42
|
+
for (const c2 of consonants.slice(0, 10)) {
|
|
43
|
+
patterns.push(c1 + v + c2);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (length === 4) {
|
|
49
|
+
// CVCV or CVCC patterns
|
|
50
|
+
for (const c1 of consonants.slice(0, 8)) {
|
|
51
|
+
for (const v1 of vowels) {
|
|
52
|
+
for (const c2 of consonants.slice(0, 8)) {
|
|
53
|
+
for (const v2 of vowels) {
|
|
54
|
+
patterns.push(c1 + v1 + c2 + v2);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (length === 5) {
|
|
61
|
+
// CVCVC patterns
|
|
62
|
+
for (const c1 of consonants.slice(0, 5)) {
|
|
63
|
+
for (const v1 of vowels.slice(0, 3)) {
|
|
64
|
+
for (const c2 of consonants.slice(0, 5)) {
|
|
65
|
+
for (const v2 of vowels.slice(0, 3)) {
|
|
66
|
+
for (const c3 of consonants.slice(0, 5)) {
|
|
67
|
+
patterns.push(c1 + v1 + c2 + v2 + c3);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return patterns.slice(0, 500); // Limit to prevent explosion
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Common dictionary words that make good domains.
|
|
78
|
+
*/
|
|
79
|
+
const DICTIONARY_WORDS = [
|
|
80
|
+
// Tech
|
|
81
|
+
'pixel', 'stack', 'cloud', 'spark', 'swift', 'logic', 'cipher', 'vector',
|
|
82
|
+
'nexus', 'prism', 'pulse', 'radar', 'signal', 'orbit', 'surge', 'core',
|
|
83
|
+
// Business
|
|
84
|
+
'prime', 'apex', 'elite', 'summit', 'vertex', 'titan', 'atlas', 'beacon',
|
|
85
|
+
'bridge', 'forge', 'vault', 'scale', 'lever', 'pivot', 'sprint', 'launch',
|
|
86
|
+
// Creative
|
|
87
|
+
'muse', 'dream', 'vivid', 'bloom', 'spark', 'flame', 'storm', 'wave',
|
|
88
|
+
'echo', 'nova', 'zen', 'flux', 'aura', 'halo', 'glow', 'blaze',
|
|
89
|
+
];
|
|
90
|
+
/**
|
|
91
|
+
* Generate brandable patterns from keywords.
|
|
92
|
+
*/
|
|
93
|
+
function generateBrandablePatterns(keywords) {
|
|
94
|
+
const patterns = [];
|
|
95
|
+
const suffixes = ['ly', 'ify', 'io', 'ai', 'eo', 'va', 'ra', 'co', 'go'];
|
|
96
|
+
const prefixes = ['go', 'my', 'get', 'try', 'hi', 'up', 'on', 'be'];
|
|
97
|
+
for (const keyword of keywords) {
|
|
98
|
+
if (keyword.length < 3)
|
|
99
|
+
continue;
|
|
100
|
+
// Add suffixes
|
|
101
|
+
for (const suffix of suffixes) {
|
|
102
|
+
patterns.push(keyword + suffix);
|
|
103
|
+
}
|
|
104
|
+
// Add prefixes
|
|
105
|
+
for (const prefix of prefixes) {
|
|
106
|
+
patterns.push(prefix + keyword);
|
|
107
|
+
}
|
|
108
|
+
// Truncate + suffix (like flickr, tumblr)
|
|
109
|
+
if (keyword.length > 4) {
|
|
110
|
+
const truncated = keyword.slice(0, -1);
|
|
111
|
+
patterns.push(truncated + 'r');
|
|
112
|
+
patterns.push(truncated + 'o');
|
|
113
|
+
}
|
|
114
|
+
// Remove vowels (flickr style)
|
|
115
|
+
const noVowels = keyword.replace(/[aeiou]/g, '');
|
|
116
|
+
if (noVowels.length >= 3 && noVowels !== keyword) {
|
|
117
|
+
patterns.push(noVowels);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return patterns;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Generate acronym patterns from keywords.
|
|
124
|
+
*/
|
|
125
|
+
function generateAcronymPatterns(keywords) {
|
|
126
|
+
const patterns = [];
|
|
127
|
+
if (keywords.length >= 2) {
|
|
128
|
+
// First letters of each keyword
|
|
129
|
+
const acronym = keywords.map(k => k[0]).join('');
|
|
130
|
+
if (acronym.length >= 2 && acronym.length <= 5) {
|
|
131
|
+
patterns.push(acronym);
|
|
132
|
+
patterns.push(acronym + 'hq');
|
|
133
|
+
patterns.push(acronym + 'io');
|
|
134
|
+
patterns.push(acronym + 'ai');
|
|
135
|
+
patterns.push('go' + acronym);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return patterns;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Generate numeric patterns (short + numbers).
|
|
142
|
+
*/
|
|
143
|
+
function generateNumericPatterns(keywords) {
|
|
144
|
+
const patterns = [];
|
|
145
|
+
const numbers = ['1', '2', '3', '4', '5', '7', '8', '9', '10', '24', '365'];
|
|
146
|
+
for (const keyword of keywords) {
|
|
147
|
+
if (keyword.length < 2 || keyword.length > 6)
|
|
148
|
+
continue;
|
|
149
|
+
for (const num of numbers) {
|
|
150
|
+
patterns.push(keyword + num);
|
|
151
|
+
patterns.push(num + keyword);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return patterns;
|
|
155
|
+
}
|
|
156
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
157
|
+
// INVESTMENT SCORING
|
|
158
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
159
|
+
/**
|
|
160
|
+
* TLD value scores.
|
|
161
|
+
*/
|
|
162
|
+
const TLD_VALUES = {
|
|
163
|
+
com: 25,
|
|
164
|
+
io: 15,
|
|
165
|
+
ai: 15,
|
|
166
|
+
co: 12,
|
|
167
|
+
net: 10,
|
|
168
|
+
org: 8,
|
|
169
|
+
dev: 8,
|
|
170
|
+
app: 8,
|
|
171
|
+
xyz: 5,
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Calculate investment score for a domain.
|
|
175
|
+
*/
|
|
176
|
+
function calculateInvestmentScore(domain, tld, keywords = [], aftermarketPrice, pattern) {
|
|
177
|
+
const factors = {
|
|
178
|
+
length: 0,
|
|
179
|
+
tldValue: 0,
|
|
180
|
+
keywordMatch: 0,
|
|
181
|
+
pronounceability: 0,
|
|
182
|
+
aftermarketPrice: undefined,
|
|
183
|
+
pattern: undefined,
|
|
184
|
+
};
|
|
185
|
+
// Length scoring (shorter = better)
|
|
186
|
+
const nameLength = domain.replace(`.${tld}`, '').length;
|
|
187
|
+
if (nameLength <= 3)
|
|
188
|
+
factors.length = 25;
|
|
189
|
+
else if (nameLength <= 4)
|
|
190
|
+
factors.length = 20;
|
|
191
|
+
else if (nameLength <= 5)
|
|
192
|
+
factors.length = 15;
|
|
193
|
+
else if (nameLength <= 6)
|
|
194
|
+
factors.length = 10;
|
|
195
|
+
else if (nameLength <= 8)
|
|
196
|
+
factors.length = 5;
|
|
197
|
+
else
|
|
198
|
+
factors.length = 0;
|
|
199
|
+
// TLD value
|
|
200
|
+
factors.tldValue = TLD_VALUES[tld] || 5;
|
|
201
|
+
// Keyword match
|
|
202
|
+
const name = domain.replace(`.${tld}`, '').toLowerCase();
|
|
203
|
+
for (const keyword of keywords) {
|
|
204
|
+
if (name.includes(keyword.toLowerCase())) {
|
|
205
|
+
factors.keywordMatch += 5;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
factors.keywordMatch = Math.min(factors.keywordMatch, 15);
|
|
209
|
+
// Pronounceability (vowel ratio check)
|
|
210
|
+
const vowels = (name.match(/[aeiou]/g) || []).length;
|
|
211
|
+
const vowelRatio = vowels / name.length;
|
|
212
|
+
if (vowelRatio >= 0.25 && vowelRatio <= 0.5) {
|
|
213
|
+
factors.pronounceability = 10;
|
|
214
|
+
}
|
|
215
|
+
else if (vowelRatio >= 0.2 && vowelRatio <= 0.6) {
|
|
216
|
+
factors.pronounceability = 5;
|
|
217
|
+
}
|
|
218
|
+
// Aftermarket price bonus (cheaper = better deal)
|
|
219
|
+
if (aftermarketPrice !== undefined) {
|
|
220
|
+
if (aftermarketPrice <= 50)
|
|
221
|
+
factors.aftermarketPrice = 15;
|
|
222
|
+
else if (aftermarketPrice <= 100)
|
|
223
|
+
factors.aftermarketPrice = 12;
|
|
224
|
+
else if (aftermarketPrice <= 250)
|
|
225
|
+
factors.aftermarketPrice = 8;
|
|
226
|
+
else if (aftermarketPrice <= 500)
|
|
227
|
+
factors.aftermarketPrice = 5;
|
|
228
|
+
else
|
|
229
|
+
factors.aftermarketPrice = 0;
|
|
230
|
+
}
|
|
231
|
+
// Pattern bonus
|
|
232
|
+
if (pattern) {
|
|
233
|
+
switch (pattern) {
|
|
234
|
+
case 'short':
|
|
235
|
+
factors.pattern = 10;
|
|
236
|
+
break;
|
|
237
|
+
case 'dictionary':
|
|
238
|
+
factors.pattern = 8;
|
|
239
|
+
break;
|
|
240
|
+
case 'brandable':
|
|
241
|
+
factors.pattern = 6;
|
|
242
|
+
break;
|
|
243
|
+
case 'acronym':
|
|
244
|
+
factors.pattern = 4;
|
|
245
|
+
break;
|
|
246
|
+
case 'numeric':
|
|
247
|
+
factors.pattern = 2;
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Calculate total
|
|
252
|
+
const total = Object.values(factors).reduce((sum, val) => sum + (val || 0), 0);
|
|
253
|
+
// Normalize to 0-100 scale
|
|
254
|
+
const normalizedTotal = Math.min(100, total);
|
|
255
|
+
// Calculate grade
|
|
256
|
+
let grade;
|
|
257
|
+
if (normalizedTotal >= 70)
|
|
258
|
+
grade = 'A';
|
|
259
|
+
else if (normalizedTotal >= 55)
|
|
260
|
+
grade = 'B';
|
|
261
|
+
else if (normalizedTotal >= 40)
|
|
262
|
+
grade = 'C';
|
|
263
|
+
else if (normalizedTotal >= 25)
|
|
264
|
+
grade = 'D';
|
|
265
|
+
else
|
|
266
|
+
grade = 'F';
|
|
267
|
+
return {
|
|
268
|
+
total: normalizedTotal,
|
|
269
|
+
factors,
|
|
270
|
+
grade,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
274
|
+
// MAIN HUNTING FUNCTION
|
|
275
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
276
|
+
/**
|
|
277
|
+
* Hunt for valuable domains.
|
|
278
|
+
*/
|
|
279
|
+
async function huntDomains(criteria) {
|
|
280
|
+
const { keywords = [], tlds = ['com', 'io', 'co'], minLength = 3, maxLength = 12, includeAftermarket = true, maxAftermarketPrice, patterns = ['short', 'brandable'], maxResults = 20, scoreThreshold = 40, } = criteria;
|
|
281
|
+
const results = [];
|
|
282
|
+
const filtersApplied = [];
|
|
283
|
+
const insights = [];
|
|
284
|
+
const sources = { sedo_auctions: 0, pattern_generated: 0 };
|
|
285
|
+
let totalScanned = 0;
|
|
286
|
+
// Build filter description
|
|
287
|
+
filtersApplied.push(`Length: ${minLength}-${maxLength} chars`);
|
|
288
|
+
filtersApplied.push(`TLDs: ${tlds.join(', ')}`);
|
|
289
|
+
filtersApplied.push(`Patterns: ${patterns.join(', ')}`);
|
|
290
|
+
if (maxAftermarketPrice) {
|
|
291
|
+
filtersApplied.push(`Max aftermarket price: $${maxAftermarketPrice}`);
|
|
292
|
+
}
|
|
293
|
+
filtersApplied.push(`Min score: ${scoreThreshold}`);
|
|
294
|
+
// ========================================
|
|
295
|
+
// Step 1: Fetch Sedo auctions if enabled
|
|
296
|
+
// ========================================
|
|
297
|
+
if (includeAftermarket && config_js_1.config.aftermarket.sedoEnabled) {
|
|
298
|
+
try {
|
|
299
|
+
const feedUrl = config_js_1.config.aftermarket.sedoFeedUrl || 'https://sedo.com/txt/auctions_us.txt';
|
|
300
|
+
const controller = new AbortController();
|
|
301
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
302
|
+
try {
|
|
303
|
+
const response = await fetch(feedUrl, { signal: controller.signal });
|
|
304
|
+
if (response.ok) {
|
|
305
|
+
const text = await response.text();
|
|
306
|
+
const sedoIndex = (0, sedo_js_1.parseSedoFeed)(text);
|
|
307
|
+
// Filter Sedo listings
|
|
308
|
+
for (const [domain, listing] of sedoIndex) {
|
|
309
|
+
const parts = domain.split('.');
|
|
310
|
+
if (parts.length < 2)
|
|
311
|
+
continue;
|
|
312
|
+
const name = parts.slice(0, -1).join('.');
|
|
313
|
+
const tld = parts[parts.length - 1];
|
|
314
|
+
// Apply filters
|
|
315
|
+
if (!tlds.includes(tld))
|
|
316
|
+
continue;
|
|
317
|
+
if (name.length < minLength || name.length > maxLength)
|
|
318
|
+
continue;
|
|
319
|
+
if (maxAftermarketPrice && listing.price && listing.price > maxAftermarketPrice)
|
|
320
|
+
continue;
|
|
321
|
+
// Check keyword match
|
|
322
|
+
const hasKeywordMatch = keywords.length === 0 ||
|
|
323
|
+
keywords.some(kw => name.toLowerCase().includes(kw.toLowerCase()));
|
|
324
|
+
if (!hasKeywordMatch && keywords.length > 0)
|
|
325
|
+
continue;
|
|
326
|
+
// Calculate score
|
|
327
|
+
const score = calculateInvestmentScore(domain, tld, keywords, listing.price || undefined);
|
|
328
|
+
if (score.total < scoreThreshold)
|
|
329
|
+
continue;
|
|
330
|
+
totalScanned++;
|
|
331
|
+
sources.sedo_auctions++;
|
|
332
|
+
results.push({
|
|
333
|
+
domain,
|
|
334
|
+
tld,
|
|
335
|
+
available: true, // Sedo auctions are available for purchase
|
|
336
|
+
investment_score: score,
|
|
337
|
+
source: 'sedo_auction',
|
|
338
|
+
aftermarket: {
|
|
339
|
+
price: listing.price,
|
|
340
|
+
currency: listing.currency,
|
|
341
|
+
auction_end: listing.auction_end || undefined,
|
|
342
|
+
url: listing.url,
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
insights.push(`Scanned ${sedoIndex.size} Sedo auctions`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
finally {
|
|
350
|
+
clearTimeout(timeout);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
logger_js_1.logger.warn('Failed to fetch Sedo auctions', {
|
|
355
|
+
error: error instanceof Error ? error.message : String(error),
|
|
356
|
+
});
|
|
357
|
+
insights.push('Sedo auction feed unavailable');
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// ========================================
|
|
361
|
+
// Step 2: Generate pattern candidates
|
|
362
|
+
// ========================================
|
|
363
|
+
const candidates = [];
|
|
364
|
+
// Generate based on patterns
|
|
365
|
+
if (patterns.includes('short')) {
|
|
366
|
+
const shortPatterns = SHORT_PATTERNS
|
|
367
|
+
.filter(p => p.length >= minLength && p.length <= maxLength)
|
|
368
|
+
.slice(0, 100); // Limit
|
|
369
|
+
for (const name of shortPatterns) {
|
|
370
|
+
candidates.push({ name, pattern: 'short' });
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (patterns.includes('dictionary')) {
|
|
374
|
+
const dictWords = DICTIONARY_WORDS.filter(w => w.length >= minLength && w.length <= maxLength);
|
|
375
|
+
for (const name of dictWords) {
|
|
376
|
+
candidates.push({ name, pattern: 'dictionary' });
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (patterns.includes('brandable') && keywords.length > 0) {
|
|
380
|
+
const brandablePatterns = generateBrandablePatterns(keywords)
|
|
381
|
+
.filter(p => p.length >= minLength && p.length <= maxLength)
|
|
382
|
+
.slice(0, 50);
|
|
383
|
+
for (const name of brandablePatterns) {
|
|
384
|
+
candidates.push({ name, pattern: 'brandable' });
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (patterns.includes('acronym') && keywords.length >= 2) {
|
|
388
|
+
const acronymPatterns = generateAcronymPatterns(keywords)
|
|
389
|
+
.filter(p => p.length >= minLength && p.length <= maxLength);
|
|
390
|
+
for (const name of acronymPatterns) {
|
|
391
|
+
candidates.push({ name, pattern: 'acronym' });
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (patterns.includes('numeric') && keywords.length > 0) {
|
|
395
|
+
const numericPatterns = generateNumericPatterns(keywords)
|
|
396
|
+
.filter(p => p.length >= minLength && p.length <= maxLength)
|
|
397
|
+
.slice(0, 30);
|
|
398
|
+
for (const name of numericPatterns) {
|
|
399
|
+
candidates.push({ name, pattern: 'numeric' });
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
insights.push(`Generated ${candidates.length} pattern candidates`);
|
|
403
|
+
// ========================================
|
|
404
|
+
// Step 3: Check availability for top candidates
|
|
405
|
+
// ========================================
|
|
406
|
+
// Pre-score candidates and pick best ones to check
|
|
407
|
+
const scoredCandidates = candidates.map(c => ({
|
|
408
|
+
...c,
|
|
409
|
+
preScore: calculateInvestmentScore(`${c.name}.${tlds[0]}`, tlds[0], keywords, undefined, c.pattern).total,
|
|
410
|
+
}));
|
|
411
|
+
scoredCandidates.sort((a, b) => b.preScore - a.preScore);
|
|
412
|
+
// Check top candidates (limit API calls)
|
|
413
|
+
const toCheck = scoredCandidates.slice(0, Math.min(50, maxResults * 3));
|
|
414
|
+
const BATCH_SIZE = 5;
|
|
415
|
+
for (let i = 0; i < toCheck.length && results.length < maxResults; i += BATCH_SIZE) {
|
|
416
|
+
const batch = toCheck.slice(i, i + BATCH_SIZE);
|
|
417
|
+
await Promise.all(batch.map(async ({ name, pattern }) => {
|
|
418
|
+
// Check across all TLDs
|
|
419
|
+
for (const tld of tlds) {
|
|
420
|
+
if (results.length >= maxResults)
|
|
421
|
+
return;
|
|
422
|
+
try {
|
|
423
|
+
const response = await (0, domain_search_js_1.searchDomain)(name, [tld], undefined, {
|
|
424
|
+
pricing: { enabled: false, maxQuotes: 0 },
|
|
425
|
+
includeGodaddySignals: false,
|
|
426
|
+
});
|
|
427
|
+
const result = response.results.find(r => r.domain === `${name}.${tld}`);
|
|
428
|
+
if (!result)
|
|
429
|
+
continue;
|
|
430
|
+
totalScanned++;
|
|
431
|
+
if (result.available) {
|
|
432
|
+
const score = calculateInvestmentScore(`${name}.${tld}`, tld, keywords, undefined, pattern);
|
|
433
|
+
if (score.total >= scoreThreshold) {
|
|
434
|
+
sources.pattern_generated++;
|
|
435
|
+
results.push({
|
|
436
|
+
domain: `${name}.${tld}`,
|
|
437
|
+
tld,
|
|
438
|
+
available: true,
|
|
439
|
+
investment_score: score,
|
|
440
|
+
source: 'pattern_generated',
|
|
441
|
+
pattern,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
catch {
|
|
447
|
+
// Ignore individual failures
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}));
|
|
451
|
+
}
|
|
452
|
+
// ========================================
|
|
453
|
+
// Step 4: Sort and finalize
|
|
454
|
+
// ========================================
|
|
455
|
+
results.sort((a, b) => b.investment_score.total - a.investment_score.total);
|
|
456
|
+
const finalResults = results.slice(0, maxResults);
|
|
457
|
+
// Generate insights
|
|
458
|
+
if (finalResults.length > 0) {
|
|
459
|
+
const bestDomain = finalResults[0];
|
|
460
|
+
insights.push(`Best find: ${bestDomain.domain} (Score: ${bestDomain.investment_score.total}, Grade: ${bestDomain.investment_score.grade})`);
|
|
461
|
+
const gradeA = finalResults.filter(r => r.investment_score.grade === 'A').length;
|
|
462
|
+
if (gradeA > 0) {
|
|
463
|
+
insights.push(`Found ${gradeA} Grade-A investment opportunities`);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
insights.push('No domains matched your criteria. Try adjusting filters.');
|
|
468
|
+
}
|
|
469
|
+
return {
|
|
470
|
+
results: finalResults,
|
|
471
|
+
total_scanned: totalScanned,
|
|
472
|
+
filters_applied: filtersApplied,
|
|
473
|
+
insights,
|
|
474
|
+
sources,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
//# sourceMappingURL=domain-hunter.js.map
|