feat(billmanager): профили ihor, cloudrix, servhost, landvps, datacheap
Docker / build (push) Failing after 19s
Docker / build (push) Failing after 19s
Гео из datacentername, specs через vds.order/vds.edit; парсер ДЦ/городов РФ. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -207,7 +207,28 @@ export function parseDatacenterName(dcName: unknown): { country: string; locatio
|
||||
}
|
||||
}
|
||||
|
||||
if (/ММТС|Adman|Москва/i.test(s)) {
|
||||
// «Москва DC3», «ДЦ Москва», «Новосибирск Xeon» — город РФ (+ опц. префикс ДЦ / суффикс)
|
||||
// Без \b: в JS word-boundary не срабатывает на кириллице без флага u.
|
||||
const RU_CITY_CANON: Record<string, string> = {
|
||||
москва: 'Москва',
|
||||
'санкт-петербург': 'Санкт-Петербург',
|
||||
спб: 'Санкт-Петербург',
|
||||
новосибирск: 'Новосибирск',
|
||||
екатеринбург: 'Екатеринбург',
|
||||
казань: 'Казань',
|
||||
самара: 'Самара',
|
||||
краснодар: 'Краснодар',
|
||||
}
|
||||
const cityHaystack = s.replace(/^ДЦ\s+/i, '').trim()
|
||||
const ruCityMatch = cityHaystack.match(
|
||||
/^(Москва|Санкт-Петербург|СПб|Новосибирск|Екатеринбург|Казань|Самара|Краснодар)(?:\s|$)/i,
|
||||
)
|
||||
if (ruCityMatch) {
|
||||
const key = ruCityMatch[1]!.toLowerCase()
|
||||
return { country: 'Россия', location: RU_CITY_CANON[key] || ruCityMatch[1]! }
|
||||
}
|
||||
|
||||
if (/ММТС|Adman/i.test(s)) {
|
||||
return { country: 'Россия', location: s }
|
||||
}
|
||||
if (/Европа/i.test(s)) {
|
||||
|
||||
@@ -95,6 +95,138 @@ const FIRSTBYTE_VDS_FIXTURE = {
|
||||
],
|
||||
}
|
||||
|
||||
/** Minimal ihor-style bjson (`datacentername`: «Москва DC3»). */
|
||||
const IHOR_VDS_FIXTURE = {
|
||||
func: 'vds',
|
||||
elem: [
|
||||
{
|
||||
id: '2927366',
|
||||
ip: '185.105.116.43',
|
||||
domain: 'vds2927366.my-ihor.ru',
|
||||
expiredate: '2026-08-08',
|
||||
real_expiredate: '2026-08-08',
|
||||
datacenter: '1',
|
||||
datacentername: 'Москва DC3',
|
||||
ostempl: 'Ubuntu-26.04-amd64',
|
||||
pricelist: 'KVM SSD Start (1 СPU/768 MB RAM/7 GB SSD)',
|
||||
pricelist_id: '7818',
|
||||
intname: 'SSD_Start',
|
||||
cost: '100.00 RUB / Месяц',
|
||||
item_cost: '100.0000',
|
||||
currency_str: 'RUB',
|
||||
createdate: '2026-03-08',
|
||||
item_status_orig: '2',
|
||||
item_status: 'Активен',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
/** Minimal Cloudrix-style bjson — promo plan without CPU/RAM in pricelist name. */
|
||||
const CLOUDRIX_VDS_FIXTURE = {
|
||||
func: 'vds',
|
||||
elem: [
|
||||
{
|
||||
id: '8226',
|
||||
ip: '95.85.240.37',
|
||||
domain: 'msk.shz.su',
|
||||
expiredate: '2026-08-18',
|
||||
real_expiredate: '2026-08-18',
|
||||
datacenter: '1',
|
||||
datacentername: 'Россия, Москва',
|
||||
ipv6_subnet: '2a12:bec4:1280:7e::/64',
|
||||
ostempl: 'Alma Linux 10',
|
||||
pricelist: 'SPROMO-1',
|
||||
pricelist_id: '1',
|
||||
intname: 'spromo',
|
||||
cost: '160.00 RUB / Месяц',
|
||||
item_cost: '160.0000',
|
||||
currency_str: 'RUB',
|
||||
createdate: '2026-05-18',
|
||||
item_status_orig: '2',
|
||||
item_status: 'Активен',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
/** Minimal serv.host bjson — named Xeon plan, city+CPU line in datacentername. */
|
||||
const SERVHOST_VDS_FIXTURE = {
|
||||
func: 'vds',
|
||||
elem: [
|
||||
{
|
||||
id: '621601',
|
||||
ip: '178.250.186.111',
|
||||
domain: 'shatskiy.denis.serv.host',
|
||||
expiredate: '2027-06-16',
|
||||
real_expiredate: '2027-06-16',
|
||||
datacenter: '5',
|
||||
datacentername: 'Новосибирск Xeon',
|
||||
ostempl: 'Ubuntu 24.04',
|
||||
pricelist: 'Тариф «Xeon 2667V2-1»',
|
||||
pricelist_id: '502',
|
||||
intname: 'Тариф «Xeon 2667V2-1»',
|
||||
cost: '127.50 RUB / Месяц',
|
||||
item_cost: '1530.0000',
|
||||
currency_str: 'RUB',
|
||||
createdate: '2026-02-16',
|
||||
item_status_orig: '2',
|
||||
item_status: 'Активен',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
/** Minimal LandVPS bjson — `ДЦ Москва`, tariff code MSK-0, ipv6_subnet. */
|
||||
const LANDVPS_VDS_FIXTURE = {
|
||||
func: 'vds',
|
||||
elem: [
|
||||
{
|
||||
id: '196380',
|
||||
ip: '77.105.133.124',
|
||||
domain: '196380.landvps.online',
|
||||
expiredate: '2026-08-21',
|
||||
real_expiredate: '2026-08-21',
|
||||
datacenter: '3',
|
||||
datacentername: 'ДЦ Москва',
|
||||
ipv6_subnet: '2a12:b3c0:1:b6::/64',
|
||||
ostempl: 'Ubuntu 24.04',
|
||||
pricelist: 'MSK-0',
|
||||
pricelist_id: '19',
|
||||
intname: 'RUS-0',
|
||||
cost: '90.00 RUB / Месяц',
|
||||
item_cost: '270.0000',
|
||||
currency_str: 'RUB',
|
||||
createdate: '2026-04-21',
|
||||
item_status_orig: '2',
|
||||
item_status: 'Активен',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
/** Minimal Datacheap bjson — country-only DC, NVMe plan without CPU/RAM in name. */
|
||||
const DATACHEAP_VDS_FIXTURE = {
|
||||
func: 'vds',
|
||||
elem: [
|
||||
{
|
||||
id: '189678',
|
||||
ip: '84.252.100.102',
|
||||
domain: 'dc.msk.rt.shx.su',
|
||||
expiredate: '2026-08-21',
|
||||
real_expiredate: '2026-08-21',
|
||||
datacenter: '8',
|
||||
datacentername: 'Россия',
|
||||
ostempl: 'Ubuntu 24.04',
|
||||
pricelist: 'VPS Start NVMe unlimited (RU)',
|
||||
pricelist_id: '2489',
|
||||
intname: 'NVMe unlim',
|
||||
cost: '203.70 RUB / Месяц',
|
||||
item_cost: '611.1000',
|
||||
currency_str: 'RUB',
|
||||
createdate: '2026-01-21',
|
||||
item_status_orig: '2',
|
||||
item_status: 'Активен',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
describe('billmanager profiles', () => {
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals()
|
||||
@@ -122,6 +254,13 @@ describe('billmanager profiles', () => {
|
||||
expect(p.map.enrichVds).toBeTypeOf('function')
|
||||
})
|
||||
|
||||
it('resolve: ihor hostname → ihor profile', () => {
|
||||
const p = resolveBillmanagerProfile('https://bill.my-ihor.ru/')
|
||||
expect(p.id).toBe('ihor')
|
||||
expect(p.funcs.listVds).toBe('vds')
|
||||
expect(p.map.enrichVds).toBeTypeOf('function')
|
||||
})
|
||||
|
||||
it('resolve: unknown hoster → default', () => {
|
||||
const p = resolveBillmanagerProfile('https://bill.hoster.ru/')
|
||||
expect(p.id).toBe('default')
|
||||
@@ -143,6 +282,218 @@ describe('billmanager profiles', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('parseDatacenterName: ihor «Москва DC3»', () => {
|
||||
expect(parseDatacenterName('Москва DC3')).toEqual({
|
||||
country: 'Россия',
|
||||
location: 'Москва',
|
||||
})
|
||||
})
|
||||
|
||||
it('ihor fixture → country/city from datacentername', () => {
|
||||
const profile = resolveBillmanagerProfile('https://my-ihor.ru/')
|
||||
const elems = extractList(IHOR_VDS_FIXTURE, profile.extract.listVdsKey)
|
||||
expect(elems).toHaveLength(1)
|
||||
const vps = mapVdsWithProfile(
|
||||
profile,
|
||||
elemToObject(elems[0]!),
|
||||
'prov-ihor',
|
||||
'acc-ihor',
|
||||
)
|
||||
expect(vps.externalId).toBe('2927366')
|
||||
expect(vps.ip).toBe('185.105.116.43')
|
||||
expect(vps.country).toBe('Россия')
|
||||
expect(vps.city).toBe('Москва')
|
||||
expect(vps.datacenter).toBe('Москва DC3')
|
||||
expect(vps.os).toBe('Ubuntu-26.04-amd64')
|
||||
expect(vps.paidUntil).toBe('2026-08-08')
|
||||
expect(vps.status).toBe('active')
|
||||
})
|
||||
|
||||
it('resolve: cloudrix hostname → cloudrix profile', () => {
|
||||
const p = resolveBillmanagerProfile('https://bill.cloudrix.ru/')
|
||||
expect(p.id).toBe('cloudrix')
|
||||
expect(p.funcs.listVds).toBe('vds')
|
||||
expect(p.map.enrichVds).toBeTypeOf('function')
|
||||
expect(p.options?.fetchVdsEditForSpecs).toBe(true)
|
||||
})
|
||||
|
||||
it('Cloudrix fixture → geo, ipv6; specs from vds.order by pricelist_id', () => {
|
||||
const profile = resolveBillmanagerProfile('https://cloudrix.ru/')
|
||||
const elems = extractList(CLOUDRIX_VDS_FIXTURE, profile.extract.listVdsKey)
|
||||
expect(elems).toHaveLength(1)
|
||||
const item = elemToObject(elems[0]!)
|
||||
let vps = mapVdsWithProfile(profile, item, 'prov-cr', 'acc-cr')
|
||||
expect(vps.externalId).toBe('8226')
|
||||
expect(vps.country).toBe('Россия')
|
||||
expect(vps.city).toBe('Москва')
|
||||
expect(vps.datacenter).toBe('Россия, Москва')
|
||||
expect(vps.ipv6).toBe('2a12:bec4:1280:7e::/64')
|
||||
expect(vps.os).toBe('Alma Linux 10')
|
||||
expect(vps.vcpu).toBe(0)
|
||||
expect(vps.ramGb).toBe(0)
|
||||
expect(vps.diskGb).toBe(0)
|
||||
|
||||
vps = enrichMappedVpsFromTariffs(item, vps, [
|
||||
{
|
||||
externalId: '1',
|
||||
name: 'SPROMO-1',
|
||||
desc: '1 CPU / 1 GB RAM / 15 GB NVMe',
|
||||
vcpu: 1,
|
||||
ramGb: 1,
|
||||
diskGb: 15,
|
||||
diskType: 'NVMe',
|
||||
virtualization: 'KVM',
|
||||
},
|
||||
])
|
||||
expect(vps.vcpu).toBe(1)
|
||||
expect(vps.ramGb).toBe(1)
|
||||
expect(vps.diskGb).toBe(15)
|
||||
expect(vps.diskType).toBe('NVMe')
|
||||
expect(vps.virtualization).toBe('KVM')
|
||||
})
|
||||
|
||||
it('resolve: serv.host → servhost profile', () => {
|
||||
const p = resolveBillmanagerProfile('https://bill.serv.host/')
|
||||
expect(p.id).toBe('servhost')
|
||||
expect(p.funcs.listVds).toBe('vds')
|
||||
expect(p.options?.fetchVdsEditForSpecs).toBe(true)
|
||||
})
|
||||
|
||||
it('parseDatacenterName: serv.host «Новосибирск Xeon»', () => {
|
||||
expect(parseDatacenterName('Новосибирск Xeon')).toEqual({
|
||||
country: 'Россия',
|
||||
location: 'Новосибирск',
|
||||
})
|
||||
})
|
||||
|
||||
it('serv.host fixture → geo; specs from vds.order by pricelist_id', () => {
|
||||
const profile = resolveBillmanagerProfile('https://my.serv.host/')
|
||||
const elems = extractList(SERVHOST_VDS_FIXTURE, profile.extract.listVdsKey)
|
||||
expect(elems).toHaveLength(1)
|
||||
const item = elemToObject(elems[0]!)
|
||||
let vps = mapVdsWithProfile(profile, item, 'prov-sh', 'acc-sh')
|
||||
expect(vps.externalId).toBe('621601')
|
||||
expect(vps.country).toBe('Россия')
|
||||
expect(vps.city).toBe('Новосибирск')
|
||||
expect(vps.datacenter).toBe('Новосибирск Xeon')
|
||||
expect(vps.os).toBe('Ubuntu 24.04')
|
||||
expect(vps.vcpu).toBe(0)
|
||||
expect(vps.diskGb).toBe(0)
|
||||
|
||||
vps = enrichMappedVpsFromTariffs(item, vps, [
|
||||
{
|
||||
externalId: '502',
|
||||
name: 'Тариф «Xeon 2667V2-1»',
|
||||
desc: '2 CPU / 2 GB RAM / 40 GB NVMe',
|
||||
vcpu: 2,
|
||||
ramGb: 2,
|
||||
diskGb: 40,
|
||||
diskType: 'NVMe',
|
||||
virtualization: 'KVM',
|
||||
},
|
||||
])
|
||||
expect(vps.vcpu).toBe(2)
|
||||
expect(vps.ramGb).toBe(2)
|
||||
expect(vps.diskGb).toBe(40)
|
||||
expect(vps.virtualization).toBe('KVM')
|
||||
})
|
||||
|
||||
it('resolve: landvps.online → landvps profile', () => {
|
||||
const p = resolveBillmanagerProfile('https://bill.landvps.online/')
|
||||
expect(p.id).toBe('landvps')
|
||||
expect(p.funcs.listVds).toBe('vds')
|
||||
expect(p.options?.fetchVdsEditForSpecs).toBe(true)
|
||||
})
|
||||
|
||||
it('parseDatacenterName: LandVPS «ДЦ Москва»', () => {
|
||||
expect(parseDatacenterName('ДЦ Москва')).toEqual({
|
||||
country: 'Россия',
|
||||
location: 'Москва',
|
||||
})
|
||||
})
|
||||
|
||||
it('LandVPS fixture → geo, ipv6; specs from vds.order by pricelist_id', () => {
|
||||
const profile = resolveBillmanagerProfile('https://my.landvps.online/')
|
||||
const elems = extractList(LANDVPS_VDS_FIXTURE, profile.extract.listVdsKey)
|
||||
expect(elems).toHaveLength(1)
|
||||
const item = elemToObject(elems[0]!)
|
||||
let vps = mapVdsWithProfile(profile, item, 'prov-lv', 'acc-lv')
|
||||
expect(vps.externalId).toBe('196380')
|
||||
expect(vps.country).toBe('Россия')
|
||||
expect(vps.city).toBe('Москва')
|
||||
expect(vps.datacenter).toBe('ДЦ Москва')
|
||||
expect(vps.ipv6).toBe('2a12:b3c0:1:b6::/64')
|
||||
expect(vps.os).toBe('Ubuntu 24.04')
|
||||
expect(vps.paidUntil).toBe('2026-08-21')
|
||||
expect(vps.vcpu).toBe(0)
|
||||
expect(vps.diskGb).toBe(0)
|
||||
|
||||
vps = enrichMappedVpsFromTariffs(item, vps, [
|
||||
{
|
||||
externalId: '19',
|
||||
name: 'MSK-0',
|
||||
desc: '1 CPU / 1 GB RAM / 20 GB NVMe',
|
||||
vcpu: 1,
|
||||
ramGb: 1,
|
||||
diskGb: 20,
|
||||
diskType: 'NVMe',
|
||||
virtualization: 'KVM',
|
||||
},
|
||||
])
|
||||
expect(vps.vcpu).toBe(1)
|
||||
expect(vps.ramGb).toBe(1)
|
||||
expect(vps.diskGb).toBe(20)
|
||||
expect(vps.virtualization).toBe('KVM')
|
||||
})
|
||||
|
||||
it('resolve: datacheap.ru → datacheap profile', () => {
|
||||
const p = resolveBillmanagerProfile('https://bill.datacheap.ru/')
|
||||
expect(p.id).toBe('datacheap')
|
||||
expect(p.funcs.listVds).toBe('vds')
|
||||
expect(p.options?.fetchVdsEditForSpecs).toBe(true)
|
||||
})
|
||||
|
||||
it('parseDatacenterName: Datacheap «Россия»', () => {
|
||||
expect(parseDatacenterName('Россия')).toEqual({
|
||||
country: 'Россия',
|
||||
location: '',
|
||||
})
|
||||
})
|
||||
|
||||
it('Datacheap fixture → country; specs from vds.order by pricelist_id', () => {
|
||||
const profile = resolveBillmanagerProfile('https://my.datacheap.ru/')
|
||||
const elems = extractList(DATACHEAP_VDS_FIXTURE, profile.extract.listVdsKey)
|
||||
expect(elems).toHaveLength(1)
|
||||
const item = elemToObject(elems[0]!)
|
||||
let vps = mapVdsWithProfile(profile, item, 'prov-dc', 'acc-dc')
|
||||
expect(vps.externalId).toBe('189678')
|
||||
expect(vps.country).toBe('Россия')
|
||||
expect(vps.city).toBe('')
|
||||
expect(vps.datacenter).toBe('Россия')
|
||||
expect(vps.os).toBe('Ubuntu 24.04')
|
||||
expect(vps.paidUntil).toBe('2026-08-21')
|
||||
expect(vps.vcpu).toBe(0)
|
||||
expect(vps.diskGb).toBe(0)
|
||||
|
||||
vps = enrichMappedVpsFromTariffs(item, vps, [
|
||||
{
|
||||
externalId: '2489',
|
||||
name: 'VPS Start NVMe unlimited (RU)',
|
||||
desc: '1 CPU / 1 GB RAM / 15 GB NVMe',
|
||||
vcpu: 1,
|
||||
ramGb: 1,
|
||||
diskGb: 15,
|
||||
diskType: 'NVMe',
|
||||
virtualization: 'KVM',
|
||||
},
|
||||
])
|
||||
expect(vps.vcpu).toBe(1)
|
||||
expect(vps.ramGb).toBe(1)
|
||||
expect(vps.diskGb).toBe(15)
|
||||
expect(vps.diskType).toBe('NVMe')
|
||||
expect(vps.virtualization).toBe('KVM')
|
||||
})
|
||||
|
||||
it('Waicore fixture elem → MappedVps fields + geo from datacentername', () => {
|
||||
const profile = resolveBillmanagerProfile('https://my.waicore.com/')
|
||||
const elems = extractList(WAICORE_VDS_FIXTURE, profile.extract.listVdsKey)
|
||||
|
||||
@@ -51,3 +51,8 @@ Sync и operations **не** содержат `if (hoster)` — только пр
|
||||
|----|-------|-------------------|
|
||||
| `waicore` | `waicore.com` / keyword | `funcs.listVds = vds.vps`; geo из `datacentername` (`[DE] Город \| …` / `Страна, Город`) |
|
||||
| `firstbyte` | `firstbyte.ru`, `firstbyte.club`, `1byte.ru` | `enrichVds`: страна/город, daily из `billdaily`/`Ежедневное списание`, `dailyRate=cost/30`; `enrichVdsBatch`: общий баланс ÷ сумма daily → один `paidUntil`; specs из `vds.order` / `vds.edit` |
|
||||
| `ihor` | `my-ihor.ru`, `ihor.ru` / keyword | `enrichVds`: geo из `datacentername` (`Москва DC3` → Россия / Москва) |
|
||||
| `cloudrix` | `cloudrix.ru` / keyword | `enrichVds`: geo (`Россия, Москва`) + `ipv6_subnet`; specs через `vds.order` / `vds.edit` (`fetchVdsEditForSpecs`) |
|
||||
| `servhost` | `serv.host` | `enrichVds`: geo (`Новосибирск Xeon` → Россия / Новосибирск); specs через `vds.order` / `vds.edit` |
|
||||
| `landvps` | `landvps.online` / keyword | `enrichVds`: geo (`ДЦ Москва` → Россия / Москва) + `ipv6_subnet`; specs через `vds.order` / `vds.edit` |
|
||||
| `datacheap` | `datacheap.ru` / keyword | `enrichVds`: geo (`Россия`); specs через `vds.order` / `vds.edit` |
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { parseDatacenterName } from '../parsers.js'
|
||||
import type { MappedVps } from '../mappers.js'
|
||||
import type {
|
||||
BillmanagerMapOverrides,
|
||||
BillmanagerProfileOverrides,
|
||||
} from './types.js'
|
||||
|
||||
/**
|
||||
* Geo + IPv6 from Cloudrix list row.
|
||||
* - `datacentername`: `Россия, Москва` → Россия / Москва
|
||||
* - `ipv6_subnet`: `2a12:…::/64`
|
||||
*
|
||||
* Hardware (vcpu/ram/disk): list has only `pricelist` like SPROMO-1 —
|
||||
* filled in sync via vds.order match and `vds.edit` (fetchVdsEditForSpecs).
|
||||
*/
|
||||
export function enrichCloudrixVds(
|
||||
item: Record<string, string>,
|
||||
mapped: MappedVps,
|
||||
): MappedVps {
|
||||
const dcRaw = (item.datacentername || item.datacenter || mapped.datacenter || '').trim()
|
||||
const { country, location } = dcRaw
|
||||
? parseDatacenterName(dcRaw)
|
||||
: { country: '', location: '' }
|
||||
|
||||
const ipv6 = (item.ipv6_subnet || item.ipv6 || mapped.ipv6 || '').trim()
|
||||
|
||||
return {
|
||||
...mapped,
|
||||
country: country || mapped.country,
|
||||
city: location || mapped.city,
|
||||
datacenter: dcRaw || mapped.datacenter,
|
||||
ipv6: ipv6 || mapped.ipv6,
|
||||
// Promo / named plans rarely encode disk type — prefer NVMe when unknown
|
||||
diskType: mapped.diskGb ? mapped.diskType : mapped.diskType || 'NVMe',
|
||||
virtualization: mapped.virtualization || 'KVM',
|
||||
}
|
||||
}
|
||||
|
||||
const cloudrixMap: BillmanagerMapOverrides = {
|
||||
enrichVds: enrichCloudrixVds,
|
||||
}
|
||||
|
||||
/**
|
||||
* Cloudrix — standard func=vds; geo from datacentername;
|
||||
* specs via vds.order + vds.edit (no CPU/RAM in list pricelist name).
|
||||
*/
|
||||
export const cloudrixOverrides: BillmanagerProfileOverrides = {
|
||||
id: 'cloudrix',
|
||||
match: {
|
||||
hostnames: ['cloudrix.ru', 'cloudrix.space'],
|
||||
keywords: ['cloudrix'],
|
||||
},
|
||||
map: cloudrixMap,
|
||||
options: {
|
||||
fetchVdsEditForSpecs: true,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import { parseDatacenterName } from '../parsers.js'
|
||||
import type { MappedVps } from '../mappers.js'
|
||||
import type {
|
||||
BillmanagerMapOverrides,
|
||||
BillmanagerProfileOverrides,
|
||||
} from './types.js'
|
||||
|
||||
/**
|
||||
* Geo from Datacheap list row.
|
||||
* - `datacentername`: `Россия` (country only; city empty)
|
||||
* - `ipv6_subnet` when present
|
||||
*
|
||||
* Hardware: `pricelist` like `VPS Start NVMe unlimited (RU)` has no CPU/RAM —
|
||||
* filled via vds.order + vds.edit (fetchVdsEditForSpecs).
|
||||
*/
|
||||
export function enrichDatacheapVds(
|
||||
item: Record<string, string>,
|
||||
mapped: MappedVps,
|
||||
): MappedVps {
|
||||
const dcRaw = (item.datacentername || item.datacenter || mapped.datacenter || '').trim()
|
||||
const { country, location } = dcRaw
|
||||
? parseDatacenterName(dcRaw)
|
||||
: { country: '', location: '' }
|
||||
|
||||
const ipv6 = (item.ipv6_subnet || item.ipv6 || mapped.ipv6 || '').trim()
|
||||
|
||||
return {
|
||||
...mapped,
|
||||
country: country || mapped.country,
|
||||
city: location || mapped.city,
|
||||
datacenter: dcRaw || mapped.datacenter,
|
||||
ipv6: ipv6 || mapped.ipv6,
|
||||
diskType: mapped.diskGb ? mapped.diskType : mapped.diskType || 'NVMe',
|
||||
virtualization: mapped.virtualization || 'KVM',
|
||||
}
|
||||
}
|
||||
|
||||
const datacheapMap: BillmanagerMapOverrides = {
|
||||
enrichVds: enrichDatacheapVds,
|
||||
}
|
||||
|
||||
/**
|
||||
* Datacheap — standard func=vds; geo from datacentername;
|
||||
* specs via vds.order + vds.edit.
|
||||
*/
|
||||
export const datacheapOverrides: BillmanagerProfileOverrides = {
|
||||
id: 'datacheap',
|
||||
match: {
|
||||
hostnames: ['datacheap.ru', 'datacheap.com'],
|
||||
keywords: ['datacheap'],
|
||||
},
|
||||
map: datacheapMap,
|
||||
options: {
|
||||
fetchVdsEditForSpecs: true,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { parseDatacenterName } from '../parsers.js'
|
||||
import type { MappedVps } from '../mappers.js'
|
||||
import type {
|
||||
BillmanagerMapOverrides,
|
||||
BillmanagerProfileOverrides,
|
||||
} from './types.js'
|
||||
|
||||
/**
|
||||
* Geo from ihor `datacentername`, e.g. `Москва DC3` → Россия / Москва.
|
||||
*/
|
||||
export function enrichIhorVds(
|
||||
item: Record<string, string>,
|
||||
mapped: MappedVps,
|
||||
): MappedVps {
|
||||
const dcRaw = (item.datacentername || item.datacenter || mapped.datacenter || '').trim()
|
||||
if (!dcRaw) return mapped
|
||||
|
||||
const { country, location } = parseDatacenterName(dcRaw)
|
||||
return {
|
||||
...mapped,
|
||||
country: country || mapped.country,
|
||||
city: location || mapped.city,
|
||||
datacenter: dcRaw || mapped.datacenter,
|
||||
}
|
||||
}
|
||||
|
||||
const ihorMap: BillmanagerMapOverrides = {
|
||||
enrichVds: enrichIhorVds,
|
||||
}
|
||||
|
||||
/**
|
||||
* ihor (my-ihor.ru) — standard func=vds.
|
||||
* Geo from datacentername via enrichVds.
|
||||
*/
|
||||
export const ihorOverrides: BillmanagerProfileOverrides = {
|
||||
id: 'ihor',
|
||||
match: {
|
||||
hostnames: ['my-ihor.ru', 'ihor.ru'],
|
||||
keywords: ['ihor'],
|
||||
},
|
||||
map: ihorMap,
|
||||
}
|
||||
@@ -11,4 +11,9 @@ export type {
|
||||
BillmanagerProfileOverrides,
|
||||
BillmanagerRequestParams,
|
||||
} from './types.js'
|
||||
export { enrichCloudrixVds, cloudrixOverrides } from './cloudrix.js'
|
||||
export { enrichDatacheapVds, datacheapOverrides } from './datacheap.js'
|
||||
export { enrichIhorVds, ihorOverrides } from './ihor.js'
|
||||
export { enrichLandvpsVds, landvpsOverrides } from './landvps.js'
|
||||
export { enrichServhostVds, servhostOverrides } from './servhost.js'
|
||||
export { waicoreOverrides } from './waicore.js'
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { parseDatacenterName } from '../parsers.js'
|
||||
import type { MappedVps } from '../mappers.js'
|
||||
import type {
|
||||
BillmanagerMapOverrides,
|
||||
BillmanagerProfileOverrides,
|
||||
} from './types.js'
|
||||
|
||||
/**
|
||||
* Geo + IPv6 from LandVPS list row.
|
||||
* - `datacentername`: `ДЦ Москва` → Россия / Москва
|
||||
* - `ipv6_subnet`
|
||||
*
|
||||
* Hardware: `pricelist` like `MSK-0` has no CPU/RAM —
|
||||
* filled via vds.order + vds.edit (fetchVdsEditForSpecs).
|
||||
*/
|
||||
export function enrichLandvpsVds(
|
||||
item: Record<string, string>,
|
||||
mapped: MappedVps,
|
||||
): MappedVps {
|
||||
const dcRaw = (item.datacentername || item.datacenter || mapped.datacenter || '').trim()
|
||||
const { country, location } = dcRaw
|
||||
? parseDatacenterName(dcRaw)
|
||||
: { country: '', location: '' }
|
||||
|
||||
const ipv6 = (item.ipv6_subnet || item.ipv6 || mapped.ipv6 || '').trim()
|
||||
|
||||
return {
|
||||
...mapped,
|
||||
country: country || mapped.country,
|
||||
city: location || mapped.city,
|
||||
datacenter: dcRaw || mapped.datacenter,
|
||||
ipv6: ipv6 || mapped.ipv6,
|
||||
diskType: mapped.diskGb ? mapped.diskType : mapped.diskType || 'NVMe',
|
||||
virtualization: mapped.virtualization || 'KVM',
|
||||
}
|
||||
}
|
||||
|
||||
const landvpsMap: BillmanagerMapOverrides = {
|
||||
enrichVds: enrichLandvpsVds,
|
||||
}
|
||||
|
||||
/**
|
||||
* LandVPS — standard func=vds; geo from datacentername;
|
||||
* specs via vds.order + vds.edit.
|
||||
*/
|
||||
export const landvpsOverrides: BillmanagerProfileOverrides = {
|
||||
id: 'landvps',
|
||||
match: {
|
||||
hostnames: ['landvps.online', 'landvps.ru', 'landvps.com'],
|
||||
keywords: ['landvps'],
|
||||
},
|
||||
map: landvpsMap,
|
||||
options: {
|
||||
fetchVdsEditForSpecs: true,
|
||||
},
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
import { DEFAULT_PROFILE } from './default.js'
|
||||
import { cloudrixOverrides } from './cloudrix.js'
|
||||
import { datacheapOverrides } from './datacheap.js'
|
||||
import { firstbyteOverrides } from './firstbyte.js'
|
||||
import { ihorOverrides } from './ihor.js'
|
||||
import { landvpsOverrides } from './landvps.js'
|
||||
import { mergeProfile } from './merge.js'
|
||||
import { servhostOverrides } from './servhost.js'
|
||||
import type { BillmanagerProfile, BillmanagerProfileOverrides } from './types.js'
|
||||
import { waicoreOverrides } from './waicore.js'
|
||||
|
||||
@@ -11,6 +16,11 @@ import { waicoreOverrides } from './waicore.js'
|
||||
export const PROFILE_OVERRIDES: BillmanagerProfileOverrides[] = [
|
||||
waicoreOverrides,
|
||||
firstbyteOverrides,
|
||||
ihorOverrides,
|
||||
cloudrixOverrides,
|
||||
servhostOverrides,
|
||||
landvpsOverrides,
|
||||
datacheapOverrides,
|
||||
]
|
||||
|
||||
function matchesUrl(url: string, override: BillmanagerProfileOverrides): boolean {
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { parseDatacenterName } from '../parsers.js'
|
||||
import type { MappedVps } from '../mappers.js'
|
||||
import type {
|
||||
BillmanagerMapOverrides,
|
||||
BillmanagerProfileOverrides,
|
||||
} from './types.js'
|
||||
|
||||
/**
|
||||
* Geo from serv.host `datacentername`, e.g. `Новосибирск Xeon` → Россия / Новосибирск.
|
||||
*
|
||||
* Hardware: list `pricelist` like `Тариф «Xeon 2667V2-1»` has no CPU/RAM/disk —
|
||||
* filled via vds.order + vds.edit (fetchVdsEditForSpecs).
|
||||
*/
|
||||
export function enrichServhostVds(
|
||||
item: Record<string, string>,
|
||||
mapped: MappedVps,
|
||||
): MappedVps {
|
||||
const dcRaw = (item.datacentername || item.datacenter || mapped.datacenter || '').trim()
|
||||
const { country, location } = dcRaw
|
||||
? parseDatacenterName(dcRaw)
|
||||
: { country: '', location: '' }
|
||||
|
||||
const ipv6 = (item.ipv6_subnet || item.ipv6 || mapped.ipv6 || '').trim()
|
||||
|
||||
return {
|
||||
...mapped,
|
||||
country: country || mapped.country,
|
||||
city: location || mapped.city,
|
||||
datacenter: dcRaw || mapped.datacenter,
|
||||
ipv6: ipv6 || mapped.ipv6,
|
||||
diskType: mapped.diskGb ? mapped.diskType : mapped.diskType || 'NVMe',
|
||||
virtualization: mapped.virtualization || 'KVM',
|
||||
}
|
||||
}
|
||||
|
||||
const servhostMap: BillmanagerMapOverrides = {
|
||||
enrichVds: enrichServhostVds,
|
||||
}
|
||||
|
||||
/**
|
||||
* serv.host — standard func=vds; geo from datacentername;
|
||||
* specs via vds.order + vds.edit.
|
||||
*/
|
||||
export const servhostOverrides: BillmanagerProfileOverrides = {
|
||||
id: 'servhost',
|
||||
match: {
|
||||
hostnames: ['serv.host'],
|
||||
keywords: ['serv.host'],
|
||||
},
|
||||
map: servhostMap,
|
||||
options: {
|
||||
fetchVdsEditForSpecs: true,
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user