diff --git a/.info/openapi.json b/.info/openapi.json index 0c5cbe7..2e38d7c 100644 --- a/.info/openapi.json +++ b/.info/openapi.json @@ -1 +1 @@ -{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"paths":{"/auth/signup":{"post":{"summary":"Signup","operationId":"signup_auth_signup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRegistration"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/login":{"post":{"summary":"Login","operationId":"login_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserLoginData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserLogin"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/refresh":{"post":{"summary":"Refresh","operationId":"refresh_auth_refresh_post","parameters":[{"name":"refresh_token","in":"query","required":true,"schema":{"type":"string","title":"Refresh Token"}},{"name":"iss","in":"query","required":true,"schema":{"enum":["credentials","telegram","api"],"type":"string","title":"Iss"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserTokens"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/plans/":{"get":{"summary":"Get Plans","operationId":"get_plans_plans__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingPlans"}}}}}}},"/orders/checkout":{"post":{"summary":"Checkout","operationId":"checkout_orders_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderDetails"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/me":{"get":{"summary":"Get Me","operationId":"get_me_users_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfo"}}}}}}},"/users/subscription":{"get":{"summary":"Get Subscription","operationId":"get_subscription_users_subscription_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/users/subscription/hwid":{"get":{"summary":"Get Hwid","operationId":"get_hwid_users_subscription_hwid_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Device"},"title":"Response Get Hwid Users Subscription Hwid Get"}}}}}},"delete":{"summary":"Delete Hwid Endpoint","operationId":"delete_hwid_endpoint_users_subscription_hwid_delete","parameters":[{"name":"hwid","in":"query","required":true,"schema":{"type":"string","title":"Hwid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/payments/pally/result":{"post":{"summary":"Pally Callback","operationId":"pally_callback_payments_pally_result_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_pally_callback_payments_pally_result_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AddonData":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"price":{"type":"number","title":"Price"},"free_threshold":{"type":"integer","title":"Free Threshold"}},"type":"object","required":["id","name","price","free_threshold"],"title":"AddonData"},"Body_pally_callback_payments_pally_result_post":{"properties":{"InvId":{"type":"string","title":"Invid"},"OutSum":{"type":"string","title":"Outsum"},"Commission":{"type":"string","title":"Commission"},"TrsId":{"type":"string","title":"Trsid"},"Status":{"type":"string","title":"Status"},"CurrencyIn":{"type":"string","title":"Currencyin"},"custom":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom"},"SignatureValue":{"type":"string","title":"Signaturevalue"},"AccountType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accounttype"},"AccountNumber":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accountnumber"},"BalanceAmount":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Balanceamount"},"BalanceCurrency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Balancecurrency"},"PayerPhone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payerphone"},"PayerEmail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payeremail"},"PayerName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payername"},"PayerComment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payercomment"},"ErrorCode":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Errorcode"},"ErrorMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Errormessage"}},"type":"object","required":["InvId","OutSum","Commission","TrsId","Status","CurrencyIn","SignatureValue"],"title":"Body_pally_callback_payments_pally_result_post"},"CheckoutResponse":{"properties":{"order_id":{"type":"string","title":"Order Id"},"total_amount":{"type":"number","title":"Total Amount"},"bonus_paid":{"type":"number","title":"Bonus Paid"},"amount_to_pay":{"type":"number","title":"Amount To Pay"},"payment_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Link"}},"type":"object","required":["order_id","total_amount","bonus_paid","amount_to_pay"],"title":"CheckoutResponse"},"Device":{"properties":{"os":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"client":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client"},"hwid":{"type":"string","title":"Hwid"}},"type":"object","required":["hwid"],"title":"Device"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"OrderDetails":{"properties":{"devices":{"type":"integer","title":"Devices"},"addons":{"items":{"type":"string"},"type":"array","title":"Addons","description":"List of addons ids"},"duration_days":{"type":"integer","title":"Duration Days"}},"type":"object","required":["devices","addons","duration_days"],"title":"OrderDetails"},"PricingPlans":{"properties":{"device_price":{"type":"integer","title":"Device Price"},"addons":{"items":{"$ref":"#/components/schemas/AddonData"},"type":"array","title":"Addons"}},"type":"object","required":["device_price","addons"],"title":"PricingPlans"},"TelegramData":{"properties":{},"type":"object","title":"TelegramData"},"UserInfo":{"properties":{"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"telegram_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Telegram Id"},"referal_code":{"type":"string","title":"Referal Code"}},"type":"object","required":["referal_code"],"title":"UserInfo"},"UserLogin":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"expires_at":{"type":"number","title":"Expires At"},"user":{"$ref":"#/components/schemas/UserInfo"}},"type":"object","required":["access_token","refresh_token","expires_at","user"],"title":"UserLogin"},"UserLoginData":{"properties":{"provider":{"type":"string","enum":["credentials","telegram","api"],"title":"Provider"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password"},"telegram":{"anyOf":[{"$ref":"#/components/schemas/TelegramData"},{"type":"null"}]}},"type":"object","required":["provider"],"title":"UserLoginData"},"UserRegistration":{"properties":{"telegram_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Telegram Id"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password"},"referal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Referal Code"},"provider":{"type":"string","enum":["credentials","telegram","api"],"title":"Provider"}},"type":"object","required":["provider"],"title":"UserRegistration"},"UserTokens":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"expires_at":{"type":"number","title":"Expires At"}},"type":"object","required":["access_token","refresh_token","expires_at"],"title":"UserTokens"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}} \ No newline at end of file +{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"paths":{"/auth/signup":{"post":{"summary":"Signup","operationId":"signup_auth_signup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRegistration"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/login":{"post":{"summary":"Login","operationId":"login_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserLoginData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserLogin"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/refresh":{"post":{"summary":"Refresh","operationId":"refresh_auth_refresh_post","parameters":[{"name":"refresh_token","in":"query","required":true,"schema":{"type":"string","title":"Refresh Token"}},{"name":"iss","in":"query","required":true,"schema":{"enum":["credentials","telegram","api"],"type":"string","title":"Iss"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserTokens"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/plans/":{"get":{"summary":"Get Plans","operationId":"get_plans_plans__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingPlans"}}}}}}},"/orders/checkout":{"post":{"summary":"Checkout","operationId":"checkout_orders_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderDetails"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/me":{"get":{"summary":"Get Me","operationId":"get_me_users_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfo"}}}}}}},"/users/subscription":{"get":{"summary":"Get Subscription","operationId":"get_subscription_users_subscription_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/users/subscription/hwid":{"get":{"summary":"Get Hwid","operationId":"get_hwid_users_subscription_hwid_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Device"},"title":"Response Get Hwid Users Subscription Hwid Get"}}}}}},"delete":{"summary":"Delete Hwid Endpoint","operationId":"delete_hwid_endpoint_users_subscription_hwid_delete","parameters":[{"name":"hwid","in":"query","required":true,"schema":{"type":"string","title":"Hwid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/payments/pally/result":{"post":{"summary":"Pally Callback","operationId":"pally_callback_payments_pally_result_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_pally_callback_payments_pally_result_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AddonData":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"price":{"type":"number","title":"Price"},"free_threshold":{"type":"integer","title":"Free Threshold"}},"type":"object","required":["id","name","price","free_threshold"],"title":"AddonData"},"Body_pally_callback_payments_pally_result_post":{"properties":{"InvId":{"type":"string","title":"Invid"},"OutSum":{"type":"string","title":"Outsum"},"Commission":{"type":"string","title":"Commission"},"TrsId":{"type":"string","title":"Trsid"},"Status":{"type":"string","title":"Status"},"CurrencyIn":{"type":"string","title":"Currencyin"},"custom":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom"},"SignatureValue":{"type":"string","title":"Signaturevalue"},"AccountType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accounttype"},"AccountNumber":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accountnumber"},"BalanceAmount":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Balanceamount"},"BalanceCurrency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Balancecurrency"},"PayerPhone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payerphone"},"PayerEmail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payeremail"},"PayerName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payername"},"PayerComment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payercomment"},"ErrorCode":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Errorcode"},"ErrorMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Errormessage"}},"type":"object","required":["InvId","OutSum","Commission","TrsId","Status","CurrencyIn","SignatureValue"],"title":"Body_pally_callback_payments_pally_result_post"},"CheckoutResponse":{"properties":{"order_id":{"type":"string","title":"Order Id"},"total_amount":{"type":"number","title":"Total Amount"},"bonus_paid":{"type":"number","title":"Bonus Paid"},"amount_to_pay":{"type":"number","title":"Amount To Pay"},"payment_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Link"}},"type":"object","required":["order_id","total_amount","bonus_paid","amount_to_pay"],"title":"CheckoutResponse"},"Device":{"properties":{"os":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"client":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client"},"hwid":{"type":"string","title":"Hwid"}},"type":"object","required":["hwid"],"title":"Device"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"OrderDetails":{"properties":{"devices":{"type":"integer","title":"Devices"},"addons":{"items":{"type":"string"},"type":"array","title":"Addons","description":"List of addons ids"},"duration_days":{"type":"integer","title":"Duration Days"}},"type":"object","required":["devices","addons","duration_days"],"title":"OrderDetails"},"PricingPlans":{"properties":{"device_price":{"type":"integer","title":"Device Price"},"addons":{"items":{"$ref":"#/components/schemas/AddonData"},"type":"array","title":"Addons"}},"type":"object","required":["device_price","addons"],"title":"PricingPlans"},"TelegramData":{"properties":{},"type":"object","title":"TelegramData"},"UserInfo":{"properties":{"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"telegram_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Telegram Id"},"referal_code":{"type":"string","title":"Referal Code"},"bonus_balance":{"type":"number","title":"Bonus Balance"}},"type":"object","required":["referal_code","bonus_balance"],"title":"UserInfo"},"UserLogin":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"expires_at":{"type":"number","title":"Expires At"},"user":{"$ref":"#/components/schemas/UserInfo"}},"type":"object","required":["access_token","refresh_token","expires_at","user"],"title":"UserLogin"},"UserLoginData":{"properties":{"provider":{"type":"string","enum":["credentials","telegram","api"],"title":"Provider"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password"},"telegram":{"anyOf":[{"$ref":"#/components/schemas/TelegramData"},{"type":"null"}]}},"type":"object","required":["provider"],"title":"UserLoginData"},"UserRegistration":{"properties":{"telegram_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Telegram Id"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password"},"referal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Referal Code"},"provider":{"type":"string","enum":["credentials","telegram","api"],"title":"Provider"}},"type":"object","required":["provider"],"title":"UserRegistration"},"UserTokens":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"expires_at":{"type":"number","title":"Expires At"}},"type":"object","required":["access_token","refresh_token","expires_at"],"title":"UserTokens"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}} \ No newline at end of file diff --git a/src/api/client.test.ts b/src/api/client.test.ts index f7021a9..64dfadd 100644 --- a/src/api/client.test.ts +++ b/src/api/client.test.ts @@ -68,7 +68,7 @@ describe('api client', () => { access_token: 'a', refresh_token: 'r', expires_at: 1, - user: { username: 'u', telegram_id: null, referal_code: 'x' }, + user: { username: 'u', telegram_id: null, referal_code: 'x', bonus_balance: 0 }, }); }); await api.login({ provider: 'credentials', username: 'u', password: 'p' }); @@ -102,7 +102,7 @@ describe('api client', () => { return jsonResponse({ access_token: 'new', refresh_token: 'new-r', expires_at: 9999999999 }); } if (calls === 1) return jsonResponse({ detail: 'expired' }, 401); - return jsonResponse({ username: 'u', telegram_id: null, referal_code: 'x' }); + return jsonResponse({ username: 'u', telegram_id: null, referal_code: 'x', bonus_balance: 0 }); }); const me = await api.getMe(); expect(me.username).toBe('u'); diff --git a/src/components/ClientLinksModal.tsx b/src/components/ClientLinksModal.tsx new file mode 100644 index 0000000..f50068e --- /dev/null +++ b/src/components/ClientLinksModal.tsx @@ -0,0 +1,111 @@ +import { useEffect } from 'react'; +import { createPortal } from 'react-dom'; + +interface Client { + name: string; + href: string; + note?: string; +} + +interface Platform { + name: string; + clients: Client[]; +} + +const PLATFORMS: Platform[] = [ + { + name: 'iOS', + clients: [ + { name: 'Incy Client', href: 'https://apps.apple.com/us/app/incy/id6756943388', note: 'Приложение может быть недоступно в РФ, смените регион.' }, + ], + }, + { + name: 'Windows', + clients: [ + { name: 'Happ', href: 'https://github.com/Happ-proxy/happ-desktop/releases/latest/download/setup-Happ.x64.exe' }, + { + name: 'Throne', + href: 'https://github.com/throneproj/Throne/releases/latest', + note: 'При первом запуске: Настройки -> Подписка -> Разрешить отправку HWID.', + }, + ], + }, + { + name: 'Android', + clients: [ + { name: 'Happ (Google Play)', href: 'https://play.google.com/store/apps/details?id=com.happproxy&pli=1' }, + { name: 'Happ (APK)', href: 'https://github.com/Happ-proxy/happ-android/releases/latest/download/Happ.apk' }, + { name: 'v2raytun', href: 'https://play.google.com/store/apps/details?id=com.v2raytun.android&hl=ru' }, + ], + }, + { + name: 'Linux', + clients: [ + { + name: 'Throne', + href: 'https://github.com/throneproj/Throne/releases/latest', + note: 'При первом запуске: Настройки -> Подписка -> Разрешить отправку HWID.', + }, + ], + }, +]; + +interface ClientLinksModalProps { + open: boolean; + onClose: () => void; +} + +export function ClientLinksModal({ open, onClose }: ClientLinksModalProps) { + useEffect(() => { + if (!open) return; + const onKey = (event: KeyboardEvent) => { + if (event.key === 'Escape') onClose(); + }; + document.addEventListener('keydown', onKey); + document.body.style.overflow = 'hidden'; + return () => { + document.removeEventListener('keydown', onKey); + document.body.style.overflow = ''; + }; + }, [onClose, open]); + + if (!open) return null; + + return createPortal( +
{client.note}
: null} +Отсканируйте код камерой или приложением Malenia.
+