@whiteslove/parsing-lexicon 0.6.1 → 0.6.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whiteslove/parsing-lexicon",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Shared deterministic multilingual parsing lexicon for WhitesLove housing and hiring services",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,85 @@
1
+ // Time-sensitive curated data consumed by hiring-safety.js's classification
2
+ // logic. Kept in its own file so updating a blacklist/allowlist never means
3
+ // touching the (stable) regex classification code, and vice versa.
4
+
5
+ export const SCAM_CONTACTS = [
6
+ ['telegram:valery_hr_36', /(?:^|[^a-z0-9_])@?valery_hr_36(?:$|[^a-z0-9_])/i],
7
+ ['telegram:kris_mogelevich7', /(?:^|[^a-z0-9_])@?kris_mogelevich7(?:$|[^a-z0-9_])/i],
8
+ ['telegram:gasgazz_07', /(?:^|[^a-z0-9_])@?gasgazz_07(?:$|[^a-z0-9_])/i],
9
+ ['phone:+998992993435', /(?:\+?998[\s()-]*)99[\s()-]*299[\s()-]*34[\s()-]*35/],
10
+ ['phone:+998992600344', /(?:\+?998[\s()-]*)99[\s()-]*260[\s()-]*03[\s()-]*44/],
11
+ ['phone:+998931244802', /(?:\+?998[\s()-]*)93[\s()-]*124[\s()-]*48[\s()-]*02/],
12
+ ];
13
+
14
+ // Exact Telegram handles from reviewed external blacklists. User comments / "please
15
+ // check" submissions are deliberately excluded; only the editorial/list body is used.
16
+ export const REPORTED_TELEGRAM_BY_SOURCE = {
17
+ moshelovka: [
18
+ 'pitupishka', 'obnalmanua1', 'p2p_lab_processing', 'hoodmoneyp2p', 'p2prvt',
19
+ 'protsessing', 'protsessing0', 'dropovod01k_chat', 'processing_skupka', 'mamonts',
20
+ 'brown_bear0', 'mediap2p', 'proseccina', 'amanatniy', 'pitupitradersrf',
21
+ 'russiantradersclubs', 'vvaybit',
22
+ ],
23
+ vklader: [
24
+ 'dobro_ot_yana', 'senpaj_help', 'shinobi_help', 'daime_helper', 'ninja_inform',
25
+ 'ninja_invest', 'assistent_ninja', 'alex_resolution', 'alex_crypto_way',
26
+ 'joecopytrade_bot', 'kirill_onchain', 'cryptolnspect', 'ghostl1', 'slashl1',
27
+ 'alexandrzenin', 'seriy_crypt', 'airolejon', 'olekitka', 'poizonrider',
28
+ 'poizonriderrobot', 'riderfeedback', 'poizonridersupport', 'poizondaniel',
29
+ 'poizonfenix', 'poizonsector', 'poizonlevel', 'poizonline', 'poizongo',
30
+ 'poizonoffice', 'poizonnation', 'poizonstorm', 'poizonsystem', 'poizonaura',
31
+ 'islyam_t', 'ethio_adam', 'vitalikadminn', 'ilya_vias', 'taddypedy', 'happyroman',
32
+ 'maxhappyict', 'rrrrviprr_bot', 'artem1991v', 'samuray_new', 'gen_zemtsov',
33
+ 'shortist_owner', 'arbitrage_capital', 'vladimir_arbitrage', 'mkwaydq',
34
+ 'poslednii_chance', 'romantradee', 'white_voronbtc', 'white_crow_btc',
35
+ 'unilive_network', 'potokcash', 'cashflowfund', 'potokpoint', 'cash_potok',
36
+ 'cashflowtime', 'kate_559', 'capitalforward', 'allocation_ay', 'andraicrypto',
37
+ 'andraicrypto_manager', 'vladbelokrylov', 'mersedes1_1', 'vadim_hub', 'david_gg7',
38
+ 'konstantinpravda', 'marafondeadinrich_bot', 'maratwhale', 'marat_whale',
39
+ 'fadeev_trade', 'andreysrbrv', 'speculant_g', 'sniperusdt', 'ratner_official',
40
+ 'arthurratner', 'markglavnyy', 'savivoin', 'l1r1q', 'arturomega', 'rodioncrypt0',
41
+ 'vipbyrodion_bot', 'magistr_tr', 'maxcrypto_adm', 'snipervip0001_bot', 'denis_longist',
42
+ 'alexeyaltador', 'anton_manag', 'twotradeowner', 'alexey_maker', 'alex_profitmaker',
43
+ 'hivetrader', 'robert_crypto98', 'neesmshnyi_bot', 'crypto_compass_btc', 'ska1pgod',
44
+ 'ternov_alexi', 'ternovhellobot', 'rafael_markov', 'cap_scalperr', 'dmitrukotov',
45
+ 'dmitrukot', 'crypto_partners_bot', 'learnarb_crypto', 'alinnainvest', 'speculyantt',
46
+ 'alex1trader', 'alexodessa_invest', 'alexodessa', 'maxbrotrd', 'mbro_pocket',
47
+ 'sergosnova', 'seedwalletshop_bot', 'seedpkultrasbot', 'arbitrageeproc', 'lebed_off',
48
+ 'cryptobotarbitrage_bot', 'youmentor_anna', 'kowalrenata', 'lunosupportstradebot',
49
+ 'nikicrypto_stre', 'exmonftmarket_bot', 'pr1vatee_roman', 'roman_pr1vat', 'rich_dmitry',
50
+ 'rudi_dmitry', 'sd_0986_bot', 'igor_richman', 'alex_wise_trade', 'alex_wiseman',
51
+ 'brokertribunai', 'tradelab_bot', 'tradelab_channel', 'tradelab_community',
52
+ 'superrare_thebot', 'traderr_server', 'trader_serverr', 'trader_servers',
53
+ 'traderer_stock', 'tanyamikheeva_pro_dengi', 'tanyamikheeva', 'veraastroguide',
54
+ 'daryu_money', 'mur_anastasi_official', 'dengisvoim_bot', 'minaevosnova',
55
+ 'pumpdumpcrypto_bot', 'trader_servver', 'traderr_serverl', 'maximonchain',
56
+ 'crypro_objectt', 'litvinov_teach', 'andrey_onchain', 'bank_tbx_bot', 'crypto_objectt',
57
+ ],
58
+ };
59
+
60
+ export const REPORTED_TELEGRAM_INVITES = [
61
+ ['moshelovka:invite-hqnj', 't.me/+-hqnjkgsgha2zwm0'],
62
+ ['moshelovka:invite-adhp', 't.me/+adhpbvvjddk2njfi'],
63
+ ['vklader:penguin-protocol', 't.me/+jqffw2xgl04wytux'],
64
+ ['vklader:velvethaze', 't.me/joinchat/57q3oqqv_ea2njhi'],
65
+ ['vklader:pump', 't.me/+6ddntu5hsuo3ntmy'],
66
+ ['vklader:bullvault', 't.me/joinchat/5ll_t_cthgbhytri'],
67
+ ['vklader:lumencap', 't.me/joinchat/dbmlm5ieytezmwji'],
68
+ ['vklader:cryptoosnova', 't.me/joinchat/zylzt2q8gmc1mjyy'],
69
+ ];
70
+
71
+ // Current licensed private employment agencies in Uzbekistan.
72
+ // Snapshot of the official Migration Agency register, updated there on 2026-08-08.
73
+ // Absence is a SOFT signal only; direct foreign employers are not intermediaries.
74
+ export const UZ_LICENSED_FOREIGN_EMPLOYMENT_AGENCIES = [
75
+ 'reiwa', 'migo overseas consulting', 'turon world cooperation', 'specialist group',
76
+ 'naimix', 'common sense', 'dhaef global', 'job maker', 'the best-staff', 'mir power',
77
+ 'horizon work', 'world wide immigration', 'the kasb', 'best globalize',
78
+ 'gotalent international', 'globalhr', 'international migration line', 'work expert',
79
+ 'viza master', 'diamor', 'fairness japan', 'getwork', 'garant immigration',
80
+ 'youth globe', 'jobbridge', 'aimjob', 'worknet', 'gilen jobs', 'interwork', 'oukaway',
81
+ 'bestwill', 'world bridge', 'gate', 'immigration service', 'visacentrum',
82
+ 'resurs export group', 'imkon', 'trust migration', 'united careers', 'talantum group',
83
+ 'skd man power', 'qadam global', 'workline', 'meros job', 'hr job start',
84
+ 'mora work group', 'jobex',
85
+ ];
@@ -1,6 +1,13 @@
1
1
  // Vacancy risk + vagueness classification.
2
2
  // Hard-block only high-confidence industry/scam patterns; ambiguous signals stay soft.
3
3
 
4
+ import {
5
+ SCAM_CONTACTS,
6
+ REPORTED_TELEGRAM_BY_SOURCE,
7
+ REPORTED_TELEGRAM_INVITES,
8
+ UZ_LICENSED_FOREIGN_EMPLOYMENT_AGENCIES,
9
+ } from './hiring-safety-blacklist.js';
10
+
4
11
  // ---- Hard-blocked: gambling / iGaming -------------------------------------
5
12
  const GAMBLING = [
6
13
  ['casino', /\bcasino\b|казино|казіно|kazino/i],
@@ -30,72 +37,6 @@ const SCAM = [
30
37
  ['crypto-bait', /гарантированн[а-яёіїєґ]*\s+(?:прибыл|профит)|трейдинг\s+с\s+гарант|инвестиц[а-яёіїєґ]*\s+с\s+гарант/i],
31
38
  ];
32
39
 
33
- const SCAM_CONTACTS = [
34
- ['telegram:valery_hr_36', /(?:^|[^a-z0-9_])@?valery_hr_36(?:$|[^a-z0-9_])/i],
35
- ['telegram:kris_mogelevich7', /(?:^|[^a-z0-9_])@?kris_mogelevich7(?:$|[^a-z0-9_])/i],
36
- ['telegram:gasgazz_07', /(?:^|[^a-z0-9_])@?gasgazz_07(?:$|[^a-z0-9_])/i],
37
- ['phone:+998992993435', /(?:\+?998[\s()-]*)99[\s()-]*299[\s()-]*34[\s()-]*35/],
38
- ['phone:+998992600344', /(?:\+?998[\s()-]*)99[\s()-]*260[\s()-]*03[\s()-]*44/],
39
- ['phone:+998931244802', /(?:\+?998[\s()-]*)93[\s()-]*124[\s()-]*48[\s()-]*02/],
40
- ];
41
-
42
- // Exact Telegram handles from reviewed external blacklists. User comments / "please
43
- // check" submissions are deliberately excluded; only the editorial/list body is used.
44
- const REPORTED_TELEGRAM_BY_SOURCE = {
45
- moshelovka: [
46
- 'pitupishka', 'obnalmanua1', 'p2p_lab_processing', 'hoodmoneyp2p', 'p2prvt',
47
- 'protsessing', 'protsessing0', 'dropovod01k_chat', 'processing_skupka', 'mamonts',
48
- 'brown_bear0', 'mediap2p', 'proseccina', 'amanatniy', 'pitupitradersrf',
49
- 'russiantradersclubs', 'vvaybit',
50
- ],
51
- vklader: [
52
- 'dobro_ot_yana', 'senpaj_help', 'shinobi_help', 'daime_helper', 'ninja_inform',
53
- 'ninja_invest', 'assistent_ninja', 'alex_resolution', 'alex_crypto_way',
54
- 'joecopytrade_bot', 'kirill_onchain', 'cryptolnspect', 'ghostl1', 'slashl1',
55
- 'alexandrzenin', 'seriy_crypt', 'airolejon', 'olekitka', 'poizonrider',
56
- 'poizonriderrobot', 'riderfeedback', 'poizonridersupport', 'poizondaniel',
57
- 'poizonfenix', 'poizonsector', 'poizonlevel', 'poizonline', 'poizongo',
58
- 'poizonoffice', 'poizonnation', 'poizonstorm', 'poizonsystem', 'poizonaura',
59
- 'islyam_t', 'ethio_adam', 'vitalikadminn', 'ilya_vias', 'taddypedy', 'happyroman',
60
- 'maxhappyict', 'rrrrviprr_bot', 'artem1991v', 'samuray_new', 'gen_zemtsov',
61
- 'shortist_owner', 'arbitrage_capital', 'vladimir_arbitrage', 'mkwaydq',
62
- 'poslednii_chance', 'romantradee', 'white_voronbtc', 'white_crow_btc',
63
- 'unilive_network', 'potokcash', 'cashflowfund', 'potokpoint', 'cash_potok',
64
- 'cashflowtime', 'kate_559', 'capitalforward', 'allocation_ay', 'andraicrypto',
65
- 'andraicrypto_manager', 'vladbelokrylov', 'mersedes1_1', 'vadim_hub', 'david_gg7',
66
- 'konstantinpravda', 'marafondeadinrich_bot', 'maratwhale', 'marat_whale',
67
- 'fadeev_trade', 'andreysrbrv', 'speculant_g', 'sniperusdt', 'ratner_official',
68
- 'arthurratner', 'markglavnyy', 'savivoin', 'l1r1q', 'arturomega', 'rodioncrypt0',
69
- 'vipbyrodion_bot', 'magistr_tr', 'maxcrypto_adm', 'snipervip0001_bot', 'denis_longist',
70
- 'alexeyaltador', 'anton_manag', 'twotradeowner', 'alexey_maker', 'alex_profitmaker',
71
- 'hivetrader', 'robert_crypto98', 'neesmshnyi_bot', 'crypto_compass_btc', 'ska1pgod',
72
- 'ternov_alexi', 'ternovhellobot', 'rafael_markov', 'cap_scalperr', 'dmitrukotov',
73
- 'dmitrukot', 'crypto_partners_bot', 'learnarb_crypto', 'alinnainvest', 'speculyantt',
74
- 'alex1trader', 'alexodessa_invest', 'alexodessa', 'maxbrotrd', 'mbro_pocket',
75
- 'sergosnova', 'seedwalletshop_bot', 'seedpkultrasbot', 'arbitrageeproc', 'lebed_off',
76
- 'cryptobotarbitrage_bot', 'youmentor_anna', 'kowalrenata', 'lunosupportstradebot',
77
- 'nikicrypto_stre', 'exmonftmarket_bot', 'pr1vatee_roman', 'roman_pr1vat', 'rich_dmitry',
78
- 'rudi_dmitry', 'sd_0986_bot', 'igor_richman', 'alex_wise_trade', 'alex_wiseman',
79
- 'brokertribunai', 'tradelab_bot', 'tradelab_channel', 'tradelab_community',
80
- 'superrare_thebot', 'traderr_server', 'trader_serverr', 'trader_servers',
81
- 'traderer_stock', 'tanyamikheeva_pro_dengi', 'tanyamikheeva', 'veraastroguide',
82
- 'daryu_money', 'mur_anastasi_official', 'dengisvoim_bot', 'minaevosnova',
83
- 'pumpdumpcrypto_bot', 'trader_servver', 'traderr_serverl', 'maximonchain',
84
- 'crypro_objectt', 'litvinov_teach', 'andrey_onchain', 'bank_tbx_bot', 'crypto_objectt',
85
- ],
86
- };
87
-
88
- const REPORTED_TELEGRAM_INVITES = [
89
- ['moshelovka:invite-hqnj', 't.me/+-hqnjkgsgha2zwm0'],
90
- ['moshelovka:invite-adhp', 't.me/+adhpbvvjddk2njfi'],
91
- ['vklader:penguin-protocol', 't.me/+jqffw2xgl04wytux'],
92
- ['vklader:velvethaze', 't.me/joinchat/57q3oqqv_ea2njhi'],
93
- ['vklader:pump', 't.me/+6ddntu5hsuo3ntmy'],
94
- ['vklader:bullvault', 't.me/joinchat/5ll_t_cthgbhytri'],
95
- ['vklader:lumencap', 't.me/joinchat/dbmlm5ieytezmwji'],
96
- ['vklader:cryptoosnova', 't.me/joinchat/zylzt2q8gmc1mjyy'],
97
- ];
98
-
99
40
  const REPORTED_TELEGRAM_INDEX = (() => {
100
41
  const index = new Map();
101
42
  for (const [source, handles] of Object.entries(REPORTED_TELEGRAM_BY_SOURCE)) {
@@ -163,22 +104,6 @@ const FOREIGN_JOB_SIGNAL = /работ[а-яёіїєґ]*\s+(?:за\s+грани
163
104
  const FOREIGN_EMPLOYMENT_INTERMEDIARY = /агентств[а-яёіїєґ]*\s+(?:по\s+)?(?:трудоустройств|занятост)|посредник[а-яёіїєґ]*\s+(?:по\s+)?трудоустройств|подбор\s+работ[а-яёіїєґ]*\s+за\s+(?:границ|рубеж)|помощ[а-яёіїєґ]*\s+(?:с\s+)?(?:трудоустройств|оформлени[а-яёіїєґ]*\s+(?:рабоч[а-яёіїєґ]*\s+)?виз)|employment\s+agency|recruitment\s+agency/i;
164
105
  const FOREIGN_JOB_UPFRONT_FEE = /(?:работ[а-яёіїєґ]*\s+(?:за\s+границ|за\s+кордон|за\s+рубеж)|трудоустройств[а-яёіїєґ]*\s+(?:за\s+границ|за\s+рубеж)|працевлаштуван[а-яёіїєґ]*\s+за\s+кордон)[\s\S]{0,600}(?:предоплат|внести|оплатить|перевести)[^.\n]{0,140}(?:виз|приглашени|запрошенн|документ|страхов|регистрац|бронь|гарантийн[а-яёіїєґ]*\s+взнос|услуг[а-яёіїєґ]*\s+агентств)/i;
165
106
 
166
- // Current licensed private employment agencies in Uzbekistan.
167
- // Snapshot of the official Migration Agency register, updated there on 2026-08-08.
168
- // Absence is a SOFT signal only; direct foreign employers are not intermediaries.
169
- const UZ_LICENSED_FOREIGN_EMPLOYMENT_AGENCIES = [
170
- 'reiwa', 'migo overseas consulting', 'turon world cooperation', 'specialist group',
171
- 'naimix', 'common sense', 'dhaef global', 'job maker', 'the best-staff', 'mir power',
172
- 'horizon work', 'world wide immigration', 'the kasb', 'best globalize',
173
- 'gotalent international', 'globalhr', 'international migration line', 'work expert',
174
- 'viza master', 'diamor', 'fairness japan', 'getwork', 'garant immigration',
175
- 'youth globe', 'jobbridge', 'aimjob', 'worknet', 'gilen jobs', 'interwork', 'oukaway',
176
- 'bestwill', 'world bridge', 'gate', 'immigration service', 'visacentrum',
177
- 'resurs export group', 'imkon', 'trust migration', 'united careers', 'talantum group',
178
- 'skd man power', 'qadam global', 'workline', 'meros job', 'hr job start',
179
- 'mora work group', 'jobex',
180
- ];
181
-
182
107
  function normalizeCompany(value) {
183
108
  return value
184
109
  .toLowerCase()
@@ -21,6 +21,15 @@ export function looksParkingOnly(value) {
21
21
  }
22
22
 
23
23
  // Cross-language "no agency" / "direct from owner" signals.
24
+ //
25
+ // This is a separate, deliberately broader/stricter pattern than
26
+ // SELLER_TERMS.owner (housing.js) / parseHousingSeller (housing-structured.js)
27
+ // — not an accidental duplicate. Consumers use isDirectOwner as a
28
+ // high-confidence override checked BEFORE falling back to
29
+ // parseHousingSeller's owner-vs-agency comparative scoring (see
30
+ // classifyTelegramAgency in whiteslove.me-backend-platform's
31
+ // apps/flats/src/scrapers/telegram.js). If you're tempted to merge these,
32
+ // check that call site's expectations first.
24
33
  const DIRECT_OWNER_RE = /(?:без\s+(?:макл(?:ер[а-яё]*)?|посредник[а-яё]*|ри[еэ]?лтор[а-яё]*|агент[а-яё]*)|от\s+(?:собственник[а-яё]*|хозяин[а-яё]*)|від\s+(?:власник[а-яіїґ]*|власниц[яії][а-яіїґ]*|господар[а-яіїґ]*)|без\s+(?:посередник[а-яіїґ]*|рі[єе]лтор[а-яіїґ]*|агент[а-яіїґ]*)|прямо\s+від\s+(?:власник[а-яіїґ]*|власниц[яії][а-яіїґ]*|господар[а-яіїґ]*)|(?:власник|власниця)\s+(?:зда[єе]|прода[єе])|no\s+(?:agency|broker|realtor|agent)|owner\s+direct|direct\s+from\s+(?:owner|landlord)|f(?:ă|a)r(?:ă|a)\s+(?:agen(?:ț|t)ie|intermediar\w*)|direct\s+(?:de\s+la\s+)?proprietar|makler\s*[- ]?siz|maklersiz|bez\s*makler(?:a|ov)?|bezmakler(?:a|ov)?|vositachi\s*[- ]?siz|vositachisiz|egasidan|uy\s+egasidan|делдалсыз|делдал\s*жоқ|иесінен|үй\s+иесінен)/iu;
25
34
 
26
35
  // Cross-language "no commission" signals. Direct-owner language implies zero