mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
refactor: migrate to eslint flat config and format codebase with prettier
- Remove legacy .eslintrc.cjs and .eslintignore - Add eslint.config.js with flat config, security rules (no-eval, no-implied-eval, no-new-func, no-script-url) - Add .prettierrc and .prettierignore - Format entire codebase with prettier
This commit is contained in:
@@ -1,218 +1,256 @@
|
||||
import apiClient from './client'
|
||||
import type { Subscription, RenewalOption, TrafficPackage, TrialInfo, PurchaseOptions, PurchaseSelection, PurchasePreview, AppConfig } from '../types'
|
||||
import apiClient from './client';
|
||||
import type {
|
||||
Subscription,
|
||||
RenewalOption,
|
||||
TrafficPackage,
|
||||
TrialInfo,
|
||||
PurchaseOptions,
|
||||
PurchaseSelection,
|
||||
PurchasePreview,
|
||||
AppConfig,
|
||||
} from '../types';
|
||||
|
||||
export const subscriptionApi = {
|
||||
// Get current subscription
|
||||
getSubscription: async (): Promise<Subscription> => {
|
||||
const response = await apiClient.get<Subscription>('/cabinet/subscription')
|
||||
return response.data
|
||||
const response = await apiClient.get<Subscription>('/cabinet/subscription');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Get renewal options
|
||||
getRenewalOptions: async (): Promise<RenewalOption[]> => {
|
||||
const response = await apiClient.get<RenewalOption[]>('/cabinet/subscription/renewal-options')
|
||||
return response.data
|
||||
const response = await apiClient.get<RenewalOption[]>('/cabinet/subscription/renewal-options');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Renew subscription
|
||||
renewSubscription: async (periodDays: number): Promise<{
|
||||
message: string
|
||||
new_end_date: string
|
||||
amount_paid_kopeks: number
|
||||
renewSubscription: async (
|
||||
periodDays: number,
|
||||
): Promise<{
|
||||
message: string;
|
||||
new_end_date: string;
|
||||
amount_paid_kopeks: number;
|
||||
}> => {
|
||||
const response = await apiClient.post('/cabinet/subscription/renew', {
|
||||
period_days: periodDays,
|
||||
})
|
||||
return response.data
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Get traffic packages
|
||||
getTrafficPackages: async (): Promise<TrafficPackage[]> => {
|
||||
const response = await apiClient.get<TrafficPackage[]>('/cabinet/subscription/traffic-packages')
|
||||
return response.data
|
||||
const response = await apiClient.get<TrafficPackage[]>(
|
||||
'/cabinet/subscription/traffic-packages',
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Purchase traffic
|
||||
purchaseTraffic: async (gb: number): Promise<{
|
||||
message: string
|
||||
gb_added: number
|
||||
amount_paid_kopeks: number
|
||||
purchaseTraffic: async (
|
||||
gb: number,
|
||||
): Promise<{
|
||||
message: string;
|
||||
gb_added: number;
|
||||
amount_paid_kopeks: number;
|
||||
}> => {
|
||||
const response = await apiClient.post('/cabinet/subscription/traffic', { gb })
|
||||
return response.data
|
||||
const response = await apiClient.post('/cabinet/subscription/traffic', { gb });
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Purchase devices
|
||||
purchaseDevices: async (devices: number): Promise<{
|
||||
success: boolean
|
||||
message: string
|
||||
devices_added: number
|
||||
new_device_limit: number
|
||||
price_kopeks: number
|
||||
price_label: string
|
||||
balance_kopeks: number
|
||||
balance_label: string
|
||||
purchaseDevices: async (
|
||||
devices: number,
|
||||
): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
devices_added: number;
|
||||
new_device_limit: number;
|
||||
price_kopeks: number;
|
||||
price_label: string;
|
||||
balance_kopeks: number;
|
||||
balance_label: string;
|
||||
}> => {
|
||||
const response = await apiClient.post('/cabinet/subscription/devices/purchase', { devices })
|
||||
return response.data
|
||||
const response = await apiClient.post('/cabinet/subscription/devices/purchase', { devices });
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Get device purchase price
|
||||
getDevicePrice: async (devices: number = 1): Promise<{
|
||||
available: boolean
|
||||
reason?: string
|
||||
devices?: number
|
||||
price_per_device_kopeks?: number
|
||||
price_per_device_label?: string
|
||||
total_price_kopeks?: number
|
||||
total_price_label?: string
|
||||
current_device_limit?: number
|
||||
days_left?: number
|
||||
base_device_price_kopeks?: number
|
||||
getDevicePrice: async (
|
||||
devices: number = 1,
|
||||
): Promise<{
|
||||
available: boolean;
|
||||
reason?: string;
|
||||
devices?: number;
|
||||
price_per_device_kopeks?: number;
|
||||
price_per_device_label?: string;
|
||||
total_price_kopeks?: number;
|
||||
total_price_label?: string;
|
||||
current_device_limit?: number;
|
||||
days_left?: number;
|
||||
base_device_price_kopeks?: number;
|
||||
}> => {
|
||||
const response = await apiClient.get('/cabinet/subscription/devices/price', { params: { devices } })
|
||||
return response.data
|
||||
const response = await apiClient.get('/cabinet/subscription/devices/price', {
|
||||
params: { devices },
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Update autopay settings
|
||||
updateAutopay: async (enabled: boolean, daysBefore?: number): Promise<{
|
||||
message: string
|
||||
autopay_enabled: boolean
|
||||
autopay_days_before: number
|
||||
updateAutopay: async (
|
||||
enabled: boolean,
|
||||
daysBefore?: number,
|
||||
): Promise<{
|
||||
message: string;
|
||||
autopay_enabled: boolean;
|
||||
autopay_days_before: number;
|
||||
}> => {
|
||||
const response = await apiClient.patch('/cabinet/subscription/autopay', {
|
||||
enabled,
|
||||
days_before: daysBefore,
|
||||
})
|
||||
return response.data
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Get trial info
|
||||
getTrialInfo: async (): Promise<TrialInfo> => {
|
||||
const response = await apiClient.get<TrialInfo>('/cabinet/subscription/trial')
|
||||
return response.data
|
||||
const response = await apiClient.get<TrialInfo>('/cabinet/subscription/trial');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Activate trial
|
||||
activateTrial: async (): Promise<Subscription> => {
|
||||
const response = await apiClient.post<Subscription>('/cabinet/subscription/trial')
|
||||
return response.data
|
||||
const response = await apiClient.post<Subscription>('/cabinet/subscription/trial');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Get purchase options (periods, servers, traffic, devices)
|
||||
getPurchaseOptions: async (): Promise<PurchaseOptions> => {
|
||||
const response = await apiClient.get<PurchaseOptions>('/cabinet/subscription/purchase-options')
|
||||
return response.data
|
||||
const response = await apiClient.get<PurchaseOptions>('/cabinet/subscription/purchase-options');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Preview purchase price
|
||||
previewPurchase: async (selection: PurchaseSelection): Promise<PurchasePreview> => {
|
||||
const response = await apiClient.post<PurchasePreview>('/cabinet/subscription/purchase-preview', {
|
||||
selection,
|
||||
})
|
||||
return response.data
|
||||
const response = await apiClient.post<PurchasePreview>(
|
||||
'/cabinet/subscription/purchase-preview',
|
||||
{
|
||||
selection,
|
||||
},
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Submit purchase
|
||||
submitPurchase: async (selection: PurchaseSelection): Promise<{
|
||||
success: boolean
|
||||
message: string
|
||||
subscription: Subscription
|
||||
was_trial_conversion: boolean
|
||||
submitPurchase: async (
|
||||
selection: PurchaseSelection,
|
||||
): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
subscription: Subscription;
|
||||
was_trial_conversion: boolean;
|
||||
}> => {
|
||||
const response = await apiClient.post('/cabinet/subscription/purchase', {
|
||||
selection,
|
||||
})
|
||||
return response.data
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Purchase tariff (for tariffs mode)
|
||||
purchaseTariff: async (tariffId: number, periodDays: number, trafficGb?: number): Promise<{
|
||||
success: boolean
|
||||
message: string
|
||||
subscription: Subscription
|
||||
tariff_id: number
|
||||
tariff_name: string
|
||||
balance_kopeks: number
|
||||
balance_label: string
|
||||
purchaseTariff: async (
|
||||
tariffId: number,
|
||||
periodDays: number,
|
||||
trafficGb?: number,
|
||||
): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
subscription: Subscription;
|
||||
tariff_id: number;
|
||||
tariff_name: string;
|
||||
balance_kopeks: number;
|
||||
balance_label: string;
|
||||
}> => {
|
||||
const response = await apiClient.post('/cabinet/subscription/purchase-tariff', {
|
||||
tariff_id: tariffId,
|
||||
period_days: periodDays,
|
||||
traffic_gb: trafficGb,
|
||||
})
|
||||
return response.data
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Get app config for connection
|
||||
getAppConfig: async (): Promise<AppConfig> => {
|
||||
const response = await apiClient.get<AppConfig>('/cabinet/subscription/app-config')
|
||||
return response.data
|
||||
const response = await apiClient.get<AppConfig>('/cabinet/subscription/app-config');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Get available countries/servers
|
||||
getCountries: async (): Promise<{
|
||||
countries: Array<{
|
||||
uuid: string
|
||||
name: string
|
||||
country_code: string | null
|
||||
base_price_kopeks: number
|
||||
price_kopeks: number
|
||||
price_per_month_kopeks: number
|
||||
price_rubles: number
|
||||
is_available: boolean
|
||||
is_connected: boolean
|
||||
has_discount: boolean
|
||||
discount_percent: number
|
||||
}>
|
||||
connected_count: number
|
||||
has_subscription: boolean
|
||||
days_left: number
|
||||
discount_percent: number
|
||||
uuid: string;
|
||||
name: string;
|
||||
country_code: string | null;
|
||||
base_price_kopeks: number;
|
||||
price_kopeks: number;
|
||||
price_per_month_kopeks: number;
|
||||
price_rubles: number;
|
||||
is_available: boolean;
|
||||
is_connected: boolean;
|
||||
has_discount: boolean;
|
||||
discount_percent: number;
|
||||
}>;
|
||||
connected_count: number;
|
||||
has_subscription: boolean;
|
||||
days_left: number;
|
||||
discount_percent: number;
|
||||
}> => {
|
||||
const response = await apiClient.get('/cabinet/subscription/countries')
|
||||
return response.data
|
||||
const response = await apiClient.get('/cabinet/subscription/countries');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Update countries/servers
|
||||
updateCountries: async (countries: string[]): Promise<{
|
||||
message: string
|
||||
added: string[]
|
||||
removed: string[]
|
||||
amount_paid_kopeks: number
|
||||
connected_squads: string[]
|
||||
updateCountries: async (
|
||||
countries: string[],
|
||||
): Promise<{
|
||||
message: string;
|
||||
added: string[];
|
||||
removed: string[];
|
||||
amount_paid_kopeks: number;
|
||||
connected_squads: string[];
|
||||
}> => {
|
||||
const response = await apiClient.post('/cabinet/subscription/countries', { countries })
|
||||
return response.data
|
||||
const response = await apiClient.post('/cabinet/subscription/countries', { countries });
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Get connection link and instructions
|
||||
getConnectionLink: async (): Promise<{
|
||||
subscription_url: string | null
|
||||
display_link: string | null
|
||||
happ_redirect_link: string | null
|
||||
happ_scheme_link: string | null
|
||||
connect_mode: string
|
||||
hide_link: boolean
|
||||
subscription_url: string | null;
|
||||
display_link: string | null;
|
||||
happ_redirect_link: string | null;
|
||||
happ_scheme_link: string | null;
|
||||
connect_mode: string;
|
||||
hide_link: boolean;
|
||||
instructions: {
|
||||
steps: string[]
|
||||
}
|
||||
steps: string[];
|
||||
};
|
||||
}> => {
|
||||
const response = await apiClient.get('/cabinet/subscription/connection-link')
|
||||
return response.data
|
||||
const response = await apiClient.get('/cabinet/subscription/connection-link');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Get hApp download links
|
||||
getHappDownloads: async (): Promise<{
|
||||
platforms: Record<string, {
|
||||
name: string
|
||||
icon: string
|
||||
link: string
|
||||
}>
|
||||
happ_enabled: boolean
|
||||
platforms: Record<
|
||||
string,
|
||||
{
|
||||
name: string;
|
||||
icon: string;
|
||||
link: string;
|
||||
}
|
||||
>;
|
||||
happ_enabled: boolean;
|
||||
}> => {
|
||||
const response = await apiClient.get('/cabinet/subscription/happ-downloads')
|
||||
return response.data
|
||||
const response = await apiClient.get('/cabinet/subscription/happ-downloads');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// ============ Device Management ============
|
||||
@@ -220,130 +258,140 @@ export const subscriptionApi = {
|
||||
// Get connected devices
|
||||
getDevices: async (): Promise<{
|
||||
devices: Array<{
|
||||
hwid: string
|
||||
platform: string
|
||||
device_model: string
|
||||
created_at: string | null
|
||||
}>
|
||||
total: number
|
||||
device_limit: number
|
||||
hwid: string;
|
||||
platform: string;
|
||||
device_model: string;
|
||||
created_at: string | null;
|
||||
}>;
|
||||
total: number;
|
||||
device_limit: number;
|
||||
}> => {
|
||||
const response = await apiClient.get('/cabinet/subscription/devices')
|
||||
return response.data
|
||||
const response = await apiClient.get('/cabinet/subscription/devices');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Delete a specific device
|
||||
deleteDevice: async (hwid: string): Promise<{
|
||||
success: boolean
|
||||
message: string
|
||||
deleted_hwid: string
|
||||
deleteDevice: async (
|
||||
hwid: string,
|
||||
): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
deleted_hwid: string;
|
||||
}> => {
|
||||
const response = await apiClient.delete(`/cabinet/subscription/devices/${encodeURIComponent(hwid)}`)
|
||||
return response.data
|
||||
const response = await apiClient.delete(
|
||||
`/cabinet/subscription/devices/${encodeURIComponent(hwid)}`,
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Delete all devices
|
||||
deleteAllDevices: async (): Promise<{
|
||||
success: boolean
|
||||
message: string
|
||||
deleted_count: number
|
||||
success: boolean;
|
||||
message: string;
|
||||
deleted_count: number;
|
||||
}> => {
|
||||
const response = await apiClient.delete('/cabinet/subscription/devices')
|
||||
return response.data
|
||||
const response = await apiClient.delete('/cabinet/subscription/devices');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// ============ Tariff Switch ============
|
||||
|
||||
// Preview tariff switch cost
|
||||
previewTariffSwitch: async (tariffId: number): Promise<{
|
||||
can_switch: boolean
|
||||
current_tariff_id: number | null
|
||||
current_tariff_name: string | null
|
||||
new_tariff_id: number
|
||||
new_tariff_name: string
|
||||
remaining_days: number
|
||||
upgrade_cost_kopeks: number
|
||||
upgrade_cost_label: string
|
||||
balance_kopeks: number
|
||||
balance_label: string
|
||||
has_enough_balance: boolean
|
||||
missing_amount_kopeks: number
|
||||
missing_amount_label: string
|
||||
is_upgrade: boolean
|
||||
previewTariffSwitch: async (
|
||||
tariffId: number,
|
||||
): Promise<{
|
||||
can_switch: boolean;
|
||||
current_tariff_id: number | null;
|
||||
current_tariff_name: string | null;
|
||||
new_tariff_id: number;
|
||||
new_tariff_name: string;
|
||||
remaining_days: number;
|
||||
upgrade_cost_kopeks: number;
|
||||
upgrade_cost_label: string;
|
||||
balance_kopeks: number;
|
||||
balance_label: string;
|
||||
has_enough_balance: boolean;
|
||||
missing_amount_kopeks: number;
|
||||
missing_amount_label: string;
|
||||
is_upgrade: boolean;
|
||||
}> => {
|
||||
const response = await apiClient.post('/cabinet/subscription/tariff/switch/preview', {
|
||||
tariff_id: tariffId,
|
||||
period_days: 30, // Default period for switch
|
||||
})
|
||||
return response.data
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Switch to a different tariff
|
||||
switchTariff: async (tariffId: number): Promise<{
|
||||
success: boolean
|
||||
message: string
|
||||
subscription: Subscription
|
||||
old_tariff_name: string
|
||||
new_tariff_id: number
|
||||
new_tariff_name: string
|
||||
charged_kopeks: number
|
||||
balance_kopeks: number
|
||||
balance_label: string
|
||||
switchTariff: async (
|
||||
tariffId: number,
|
||||
): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
subscription: Subscription;
|
||||
old_tariff_name: string;
|
||||
new_tariff_id: number;
|
||||
new_tariff_name: string;
|
||||
charged_kopeks: number;
|
||||
balance_kopeks: number;
|
||||
balance_label: string;
|
||||
}> => {
|
||||
const response = await apiClient.post('/cabinet/subscription/tariff/switch', {
|
||||
tariff_id: tariffId,
|
||||
period_days: 30,
|
||||
})
|
||||
return response.data
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// ============ Subscription Pause (Daily Tariffs) ============
|
||||
|
||||
// Toggle pause/resume for daily subscription
|
||||
togglePause: async (): Promise<{
|
||||
success: boolean
|
||||
message: string
|
||||
is_paused: boolean
|
||||
balance_kopeks: number
|
||||
balance_label: string
|
||||
success: boolean;
|
||||
message: string;
|
||||
is_paused: boolean;
|
||||
balance_kopeks: number;
|
||||
balance_label: string;
|
||||
}> => {
|
||||
const response = await apiClient.post('/cabinet/subscription/pause')
|
||||
return response.data
|
||||
const response = await apiClient.post('/cabinet/subscription/pause');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// ============ Traffic Switch ============
|
||||
|
||||
// Switch to a different traffic package
|
||||
switchTraffic: async (gb: number): Promise<{
|
||||
success: boolean
|
||||
message: string
|
||||
old_traffic_gb: number
|
||||
new_traffic_gb: number
|
||||
charged_kopeks: number
|
||||
balance_kopeks: number
|
||||
balance_label: string
|
||||
switchTraffic: async (
|
||||
gb: number,
|
||||
): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
old_traffic_gb: number;
|
||||
new_traffic_gb: number;
|
||||
charged_kopeks: number;
|
||||
balance_kopeks: number;
|
||||
balance_label: string;
|
||||
}> => {
|
||||
const response = await apiClient.put('/cabinet/subscription/traffic', { gb })
|
||||
return response.data
|
||||
const response = await apiClient.put('/cabinet/subscription/traffic', { gb });
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Refresh traffic usage from RemnaWave (rate limited: 1 per 60 seconds)
|
||||
refreshTraffic: async (): Promise<{
|
||||
success: boolean
|
||||
cached: boolean
|
||||
rate_limited?: boolean
|
||||
retry_after_seconds?: number
|
||||
source?: string
|
||||
traffic_used_bytes: number
|
||||
traffic_used_gb: number
|
||||
traffic_limit_bytes: number
|
||||
traffic_limit_gb: number
|
||||
traffic_used_percent: number
|
||||
is_unlimited: boolean
|
||||
lifetime_used_bytes?: number
|
||||
lifetime_used_gb?: number
|
||||
success: boolean;
|
||||
cached: boolean;
|
||||
rate_limited?: boolean;
|
||||
retry_after_seconds?: number;
|
||||
source?: string;
|
||||
traffic_used_bytes: number;
|
||||
traffic_used_gb: number;
|
||||
traffic_limit_bytes: number;
|
||||
traffic_limit_gb: number;
|
||||
traffic_used_percent: number;
|
||||
is_unlimited: boolean;
|
||||
lifetime_used_bytes?: number;
|
||||
lifetime_used_gb?: number;
|
||||
}> => {
|
||||
const response = await apiClient.post('/cabinet/subscription/refresh-traffic')
|
||||
return response.data
|
||||
const response = await apiClient.post('/cabinet/subscription/refresh-traffic');
|
||||
return response.data;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user