
    SJj]                       U d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlmZ ddlmZ ddlmZ  ee      j%                         j&                  j&                  Z ee      ej,                  vr"ej,                  j/                  d ee             ddlmZmZmZmZmZ ddlmZ dd	l m!Z!m"Z"m#Z# dd
l$m%Z% ddl&m'Z' ddl(m)Z)m*Z*m+Z+m,Z, ddl-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZR ddlSmTZTmUZUmVZVmWZWmXZXmYZYmZZZm[Z[m\Z\m]Z]m^Z^m_Z_m`Z`maZambZbmcZc ddldmeZf ddlgmhZhmiZimjZj ddlkmlZmmnZompZpmqZqmrZrmsZsmtZt edz  ZudZveYe\eZe]dZw ed      Zxexj                  edgdgdg        ed      Zzi Z{de|d<    e}       Z~de|d<   i Zde|d <    e	j                          Ze
j                  Z e	j                         Z ed!"      Zd#e|d$<   dad%ad&Zdad'e|d(<   dd)Zdd*Z G d+ d,      Z eej                  e      s eej                        e_         eej                   e      s eej                         e_        dd-Zdd.Zee
_         ece       dd/Zdd0Zdd1Zi Zd2e|d3<   h d4Zd5Z G d6 d7e      Z G d8 d9      Zdd:Zdd;Zddd<Zdd=Zdd>Zdd?Zdd@ZddAZdddBZdCddDddEZdFZddGZddHZddIZddJZddKZddLZddMZddNZddOZddPZddQZddRZddSZddTZ ejj                  dU      ZdVZddWZexjs                  dX      ddY       Zezjw                  dZ      dd[       Zezjw                  d\      dd]       Zdd^Zezjw                  d_      dd`       Zezj                  da      ddb       ZdddcZdddZezjw                  de      ddf       Zezj                  dg      ddh       Zezj                  di      ddj       Zezjw                  dk      ddl       Zezj                  dk      ddm       Zezj                  dn      ddo       ZddpZezjw                  dq      ddr       Zezj                  ds      ddt       Zezj                  du      ddv       Zezj                  dw      ddx       Zezj                  dy      ddz       Zezj                  d{      dd|       Zdd}Zezjw                  d~      dd       Zezj                  d~      dd       Zezjw                  d      dd       Zezjw                  d      dd       Zezj                  d      dd       Zezj                  d      dd       Zezjw                  d      dd       Zezj                  d      dd       Zezj                  d      dd       Zezj                  d      dd       Zezj                  d      dd       Zezj                  d      dd       ZddddZezj                  d      dd       ZddZezj                  d      dd       Zezj                  d      dd       Zezjw                  d      dd       Zezj                  d      dd       Zezj                  d      dd       Zezj                  d      dd       ZddZezj                  d      dd       Zezj                  d      dd       Zezjw                  d      dd       Zezjw                  d      ddd       Zezj                  d      dd       Zezj                  d      dd       ZddZezj                  d      dd       Zezj                  d      dd       Zezj                  d      dd       Zexj                  ez       ddZddZexj                  d      dd       Zexj                  d      dd       Zexjw                  dZ      dd       Zexjw                  d      dd       Zexj                  d e%eu      d¬ë       edk(  rvddlZdevdCdƜZe+r ee+      ndZe,r ee,      ndZ er=e r:ej                         r)e j                         r ee      ed<    ee       ed<    ej                  di e yy)uO  Панель OZPAY: API девайсов + статика мини-аппа.

Отдельный процесс от notify_server.py.
Проверки (check_balance / check_turnover / check_cards / full_check) и выпуск карты (add_card) идут в thread pool,
чтобы не блокировать event loop на ADB.
    )annotationsN)deque)Path)Optional)	APIRouterFastAPIHTTPExceptionQueryRequest)CORSMiddleware)FileResponseJSONResponseResponse)StaticFiles)current_user_from_request)ADMIN_TG_IDSDEVICE_CHAT_MAPSSL_CERTFILESSL_KEYFILE)%
add_ip_banadd_panel_workeradjust_usd_balancebind_device_ownerclaim_free_devicecount_free_slotscreate_devicedelete_deviceensure_client_leasefind_device_by_ip_portget_app_user
get_deviceget_slot_priceget_sms_chat_idget_watch_settingsip_covers_clientis_ip_bannedlist_app_userslist_deviceslist_devices_by_tglist_ip_banslist_lock_logout_duelist_panel_workersparse_ip_ban_inputsparse_sms_chat_idrefund_client_leaserelease_device_ownerremove_ip_banremove_panel_workerrename_devicesave_watch_settingsset_slot_priceset_sms_chat_idstart_client_leaseupdate_card_flagsupdate_deviceupdate_password)ActionCancelledadd_card
add_devicecancel_logincapture_screencheck_balancecheck_cardscheck_login_statecheck_turnover
full_check	logout_lkpress_device_back	probe_adbreboot_devicescreencap_pngset_action_cancel_hook)runtime)SMS_CHAT_ERRORSMS_TEST_TEXTsend_bot_message)DEFAULT_PORTDEFAULT_USERdelete_hostget_hostrename_hostrun_ssh_commandsupsert_hostappi  )balanceturnovercardsallzOZPAY Panel)title*)allow_originsallow_methodsallow_headersz/api)prefixzdict[str, asyncio.Lock]_device_lockszset[str]	_checkingzdict[str, threading.Event]_cancel_flagsi  )maxlenzdeque[dict]
_log_lines ip  zOptional[asyncio.Task]_lock_logout_taskc                     d| v ryd| v rd| v ryy)Nz
 /api/logsT/screenz /api/devices/F )lines    5/var/www/oz-panel.ru/ozpay-pub/server/panel_server.py_skip_captured_logrm   x   s#    tD-5    c                   | sy t         | z   }|j                  d      }|j                         a |sy t        5  |D ]3  }t	        |      rt
        dz  at        j                  t
        |d       5 	 d d d        y # 1 sw Y   y xY w)N
   )idtext)_log_partialsplitpop	_log_lockrm   _log_seqre   append)rs   chunkpartsrk   s       rl   _ingest_logr|      s    4EKKE99;L	 > 	>D!$'MHXt<=		>> > >s   9A::Bc                  *    e Zd Zd Zd Zd Zd Zd Zy)_StdTeec                    || _         y N)	_original)selforiginals     rl   __init__z_StdTee.__init__   s	    !rn   c                @   |yt        |t              r	 |j                  dd      }nt        |      }	 | j                  j                  |       t        |       t        |t              st        |      S |S # t        $ r t	        |      }Y Zw xY w# t        $ r Y Mw xY w)Nr   zutf-8replace)
isinstancebytesdecode	Exceptionreprstrr   writer|   intlen)r   datars   s      rl   r   z_StdTee.write   s    <dE""{{7I6 t9D	NN  & 	D *4 5s4y?4?  "Dz"  		s"   A7 B 7BB	BBc                X    	 | j                   j                          y # t        $ r Y y w xY wr   )r   flushr   r   s    rl   r   z_StdTee.flush   s)    	NN  " 		s    	))c                V    	 | j                   j                         S # t        $ r Y yw xY wNF)r   isattyr   r   s    rl   r   z_StdTee.isatty   s,    	>>((** 		s    	((c                .    t        | j                  |      S r   )getattrr   )r   names     rl   __getattr__z_StdTee.__getattr__   s    t~~t,,rn   N)__name__
__module____qualname__r   r   r   r   r   rj   rn   rl   r~   r~      s    "@"-rn   r~   c                     t        t        dd       } | sy t        j                  |       }||j	                         sy t        t        dd      sdt        _        t        d|  d       t        d      )N	device_idcancel_loggedFTu#   действие отменено ()u!   Действие отменено)r   _tlsrc   getis_setr   printr;   )r   flags     rl   _action_cancel_hookr      sh    k40IY'D|4;;=4%0!3I;a@A
=
>>rn   c                   t        t        dd       }|st        |        y t        j                         t        dt        | xs d            z   }	 t                |t        j                         z
  }|dk  ry t        t        d|             =)Nr           r   g?)	r   r   _orig_sleeptime	monotonicmaxfloatr   min)secondsr   end	remainings       rl   _interruptible_sleepr      sw    k40IG
..
SeGLq&9:
:C
$..**	>CY'( rn   c                d    t         j                  |        t        j                         t        | <   y r   )rb   add	threadingEventrc   r   s    rl   _begin_actionr      s    MM)(0M)rn   c                Z    t         j                  |        t        j                  | d        y r   )rb   discardrc   rv   r   s    rl   _end_actionr      s     i i&rn   c                p    | t         _        dt         _        	  || d t         _        S # d t         _        w xY wr   )r   r   r   )r   fnargss      rl   _call_device_actionr      s,    DND4ys   ( 5zdict[str, 'LoginSession']_login_sessions>   running	verifying
cancellingawaiting_code     r@c                      e Zd ZdZy)LoginCancelleduC   Пользователь отменил вход из панели.N)r   r   r   __doc__rj   rn   rl   r   r      s    Mrn   r   c                  B    e Zd ZdZd
ddZd Zd Zd
dZddZd Z	d	 Z
y)LoginSessionu  Интерактивная сессия входа: add_device выполняется в отдельном потоке и на
    шаге ввода кода блокируется, ожидая действие из мини-аппа (код или повторную
    отправку). Пока ждём код, поток сам опрашивает состояние кнопки 'Получить новый
    код' на устройстве и кладёт его в `resend_available`, чтобы кнопка в панели
    была активна ровно тогда же, когда она активна в Ozon.Nc                    || _         || _        || _        || _        d| _        d | _        d | _        d | _        d | _        d| _	        d| _
        d | _        t        j                         | _        d | _        y )Nr   F)r   numberpassworduser_idstatusmethodtargeterrordeviceresend_availablecancel_requested_devicequeueQueue	_action_qthread)r   r   r   r   r   s        rl   r   zLoginSession.__init__   sl    " %)%)$(
&* % %/4{{}26rn   c                    | j                   y 	 ddlm}  || j                         }|t        |      | _        y y # t
        $ r Y y w xY w)Nr   )_get_new_code_button_enabled)r   server.mainr   boolr   r   )r   r   states      rl   _update_resend_availablez%LoginSession._update_resend_available  sN    <<	@0>E (,U% ! 		s   *; 	AAc                Z   | j                   y 	 ddlm}m}m} d| _         || j                   d        || j                          t        j                  d        || j                         xs i }|j                  d      | _	        |j                  d      | _
        y # t        $ r Y y w xY w)	Nr   )detect_code_screendismiss_permission_dialogwait_and_tap_get_new_codeFg      $@timeoutg      ?r   r   )r   r   r   r   r   r   r   sleepr   r   r   r   )r   r   r   r   hints        rl   _perform_resendzLoginSession._perform_resend  s    <<
	ll$)D!%dllDA%dll3JJsO%dll39rD((8,DK((8,DK 		s   BB 	B*)B*c                   |xs i }|j                  d      | _        |j                  d      }|
d|v sd|v r|}|xs i }|j                  d      | _        |j                  d      | _        | j                  r
t               d| _        t        j                         t        z   }t        j                         |k  r| j                          	 | j                  j                  d      \  }}|dk(  r
t               |d	k(  r	d
| _        |S |dk(  r+| j                          t        j                         t        z   }t        j                         |k  rt        d      # t        j                  $ r Y w xY w)Nr   r   r   r   r   g       @r   cancelcoder   resendu.   Код не был введён вовремя)r   r   r   r   r   r   r   r   CODE_WAIT_TIMEOUTr   r   r   Emptyr   RuntimeError)r   ctxr   deadlineactionpayloads         rl   code_providerzLoginSession.code_provider)  sM   iRwwx(wwv<X_CDzrhhx(hhx(   ""%99;!22iikH$))+"&.."4"4S"4"A !$&&)!$$&99;):: iikH$ KLL ;; s   E E10E1c                >    | j                   j                  d|f       y )Nr   r   put)r   r   s     rl   submit_codezLoginSession.submit_codeG  s    FD>*rn   c                :    | j                   j                  d       y )N)r   Nr   r   s    rl   request_resendzLoginSession.request_resendJ  s    +,rn   c                V    d| _         d| _        | j                  j                  d       y)up   Пометить сессию как отменяемую и разбудить поток, ждущий код.Tr   )r   NN)r   r   r   r   r   s    rl   request_cancelzLoginSession.request_cancelM  s$     $"+,rn   r   )r   r   r   r   r   r   r   Optional[int])r   r   )r   r   r   r   r   r   r   r   r   r   r   rj   rn   rl   r   r      s,    e7 	M<+--rn   r   c                p    | j                   rt        | j                         t        | j                         y r   )r   r/   r   r0   )sessions    rl   _end_failed_loginr  T  s%    G--.**+rn   c                j   	 t        | j                  | j                  | j                  | j                  d       t        t        | j                        d      | _        d| _        t"        j%                  | j                         y # t        $ rd d| _        	 t        | j                         n1# t        $ r%}t        d| j                   d|        Y d }~nd }~ww xY wd| _        t        |        Y t        $ r}| j                  r[	 t        | j                         n1# t        $ r%}t        d| j                   d|        Y d }~nd }~ww xY wd| _        t        |        n"t        |      | _        d	| _        t        |        Y d }~#d }~ww xY w# t"        j%                  | j                         w xY w)
NF)r   press_get_new_codeis_admindoner   zcancel_login(
) failed: 	cancelledr   )r=   r   r   r   r   serialize_device_require_devicer   r   r   r>   r   r   r  r   r   r   rb   r   )r  excnav_excs      rl   
_run_loginr  Z  sq   -NN!//$	
 */':K:K*LW\], 	'++,+  #%	F**+ 	FM'"3"3!4JseDEE	F$'" '##NW../ Ng&7&7%8
7)LMMN(GNg&HGM$GNg&' 	'++,s   A$B FB-,F-	C6CFCF0F 2F:F	DF		E&EF	E8F	F 	FF !F2c                n   t         j                  |       }|r|j                  t        v rt	        dd      | t
        v rt	        dd      t        | |||      }|t         | <   t
        j                  |        t        j                  t        |fd      |_        |j                  j                          |S )N  u&   Вход уже выполняетсяstatus_codedetailu*   Девайс занят проверкойr   T)r   r   daemon)r   r   r   _ACTIVE_LOGIN_STATESr	   rb   r   r   r   Threadr  r   start)r   r   r   r   existingr  s         rl   _start_login_sessionr  }  s    ""9-HHOO';;4\]]I4`aa9fhHG!(OIMM)%%ZwjQUVGNNNNrn   c                n    t         j                  |       }|t        j                         }|t         | <   |S r   )ra   r   asyncioLock)r   locks     rl   	_lock_forr    s1    Y'D|||~#'i Krn   c                6   | | dk(  ryt        | t        t        f      rt        |       S t        |       j	                  dd      j	                  dd      j	                  dd      }t        j                  dd|      }	 |rt        |      S dS # t        $ r Y yw xY w)Nrf   r        ,.z[^\d.])r   r   r   r   r   resub
ValueError)valuers   s     rl   
_to_numberr)    s    }%#u&U|u:fc*223;CCCMD66)R&D"uT{++ s   =B 
B 	BBc           	         t        j                  dd| xs d      s| xs dS dj                  fdt        dt	              d      D              S )N\Drf   r"  c              3  .   K   | ]  }||d z      yw)   Nrj   ).0idigitss     rl   	<genexpr>z&_format_card_number.<locals>.<genexpr>  s     FF1QUOFs   r   r-  )r%  r&  joinranger   )r   r0  s    @rl   _format_card_numberr4    sH    VVE2v|,F|88FU1c&k1-EFFFrn   c                N   | xs dj                         }|syt        j                  d|      rt        |      dkD  r|d d S |S t        j                  dd|      }t        |      dk(  r>|d d j                         rt        |d d       nd}d|cxk  rd	k  rn y|d d  d
|dd   S y)Nrf   z(0[1-9]|1[0-2])/\d{2}(?:\d{2})?   r+  r-     r   rq      /)stripr%  	fullmatchr   r&  isdigitr   )rawrs   r0  months       rl   _format_expiryr?    s    I2D	||6=t9q=tBQx2d2VVE2t$F
6{a#)"1:#5#5#7F2AJQ Raj\6!":,//rn   c                   | si S t        | t              r| }n	 t        j                  |       }t        |t              si S i }|j                         D ]  \  }}t        j                  ddt        |            }|rt        |t              s9t        |j                  d            t        |j                  d            t        |j                  d            d||<    |S # t        t
        t        j                  f$ r i cY S w xY w)Nr+  rf   beelineyapaymtsrA  rB  rC  )r   dictjsonloads	TypeErrorr'  JSONDecodeErroritemsr%  r&  r   r   r   )r=  r   flagskeyr(  r0  s         rl   parse_card_flagsrM    s    	#t	::c?D dD!	Ejjl 

Ur3s8,Zt4EIIi01%))G,-		%()
f	
 L :t';';< 	I	s   C    DDc                   t        |      }| sg S g }t        |       j                  d      D ]  }|j                         }|s|j                  d      }|r|d   nd}t	        |      dkD  r|d   nd}t	        |      dkD  r|d   nd}t        j                  dd|      }	t        j                  dd|      }
|	r|
|	dd	 k(  rd}nt        |      }|j                  |	      xs i }|j                  t        |      ||t        |j                  d
            t        |j                  d            t        |j                  d            d       ! |S )ui   cards в БД: number/expiry/cvv, карты через ':'. Старый формат: number/last4/cvv.:r9  r   rf   rq   r7  r+  NrA  rB  rC  )r   expirycvvrA  rB  rC  )rM  r   ru   r:  r   r%  r&  r?  r   ry   r4  r   )r=  	flags_raw	flags_maprY   rz   r{   r   middlerR  number_digitsmiddle_digitsrQ  rK  s                rl   parse_cardsrX    s;    +I	ES$ C "q Z!^qe*q.eAhbub&1ub&1]mBC.@@F#F+Fm,2)&1EIIi01%))G,-		%()
 	. Lrn   Fr  ownersc               z   | j                  d      xs d}| j                  d      }| j                  d      }t        | j                  d            }t        | j                  d            }| j                  d      }	 |dvrt        |      nd }|t
        v rd	}	n|sd
}	n|rd}	n	|r|rd}	nd}	t        |      xs i }
t        |
j                  d      xs d      j                         xs t        }	 t        |
j                  d      xs t              }i d|d| j                  d      xs dj                         d| j                  d      xs dd|xs dd|dvr|ndd|	d|d|d|t
        v dt        | j                  d            dt        | j                  d            dt        | j                  d            dt        | j                  d      | j                  d            d|d| xr |d u d|d|t        | j                  d            d d d}	 | j                  d      dvrt        | j                  d            nd }||d<   |r|r| j                  d      r|t        z   |d<   t        j                  |      }||j                   nd }|t"        v r|nd |d <   |r-|r+|
t%               }|j                  |      xs	 |ddd!d!d"d#|d$<   |sd|d<   d|d<   d|d<   d|d<   |S # t        t        f$ r d }Y ww xY w# t        t        f$ r
 t        }Y w xY w# t        t        f$ r d }Y w xY w)%Nr   rf   ipportr   blockedtg_idNrf   r   0busynewonlineofflineusernamerr   r   Nrf   r   linkedcheckingrW   incomeoutcomerY   
card_flagsfreessh_userssh_port	leased_at)leased
blocked_atlock_logout_atrr  rs  login_statusFr   rr   rf  
first_namer  	is_workerbalance_usdowner)r   r   r   rH  r'  rb   rR   r   r:  SSH_DEFAULT_USERSSH_DEFAULT_PORTr)  rX  r   LOCK_LOGOUT_SECONDSr   r   r  _owners_by_id)rowr  rZ  r   r\  r]  rh  r^  r_  r   hostrn  ro  r   rr  loginrt  s                    rl   r
  r
    s   !'RI	B776?D#''(#$F3779%&GGGGE#+==E
4 I		I$"D488J'-2.446J:JH$txx';+;<i&B--/ 	#''(#)r 	bhB	
 	J.B 	& 	& 	7 	I* 	:cggi01 	*SWWX./ 	:cggi01 	SWWW-sww|/DE 	 	V.$  	H!" 	H#$ sww{+,)G,58WW\5JR\5\U377<01bf
 'GL:#''+"6$.1D$D !	*E#(#45<<$L.:>R.RlX\GNE>"_F!::e, 
1
  
 
NI z" " z" $#$6 z" 
s6   >K2 1"L
 "/L& 2LL
L#"L#&L:9L:z*Accept, Content-Type, X-Telegram-Init-Datac                r    t        | j                  d             xr t        | j                  d             S Nr  rw  r   r   users    rl   _pays_for_leaser  A  s/    DHHZ())M$txx7L2M.MMrn   c                R    t        | j                  dd       }|st        dd      |S )Nr  i  u+   Откройте панель из Telegramr  )r   r   r	   requestr  s     rl   _userr  E  s*    7==&$/D4abbKrn   c                X    t        |       }|j                  d      st        dd      |S )Nr    u'   Только администраторr  )r  r   r	   r  s     rl   _require_adminr  L  s*    >D88J4]^^Krn   c                    | j                   r| j                   j                  ndxs d}|j                         }|j                  d      r|dd  }|S )Nrf   z::ffff:   )clientr  r:  
startswith)r  r  s     rl   _request_ipr  S  sE    #*>>GNNr@bD::<Dy!ABxKrn   c                0    t               t        |       ddS )NT)bans	client_ipok)r*   r  r  s    rl   _ip_bans_payloadr  [  s     ) rn   c                \    t        | j                  d      xs | j                  d            S r  r  r  s    rl   	_is_staffr  c  s$    $=(=>>rn   c                    | j                  d      }	 |dvxr t        |      t        |d         k(  S # t        t        f$ r Y yw xY w)Nr_  r`  rr   F)r   r   rH  r'  )r~  r  tgs      rl   _ownsr  g  sN    		B++JB3tDz?0JJz" s   3 AAc                P    | j                  d       xr | j                  d      dv S )Nr   r_  r`  )r   )r~  s    rl   _is_free_slotr  o  s(    !!Mswww'7;M'MMrn   c                    t        |       }t        |      }|j                  d      s|j                  d      st        ||      r||fS t	        dd      )Nr  rw  r  2   Нет доступа к этому девайсуr  r  r  r   r  r	   r  r   r  r~  s       rl   _require_device_accessr  s  sM    >D
)
$Cxx
txx4c48HSy
C0d
eern   c                    t        |       }t        |      }|j                  d      st        ||      r||fS t	        dd      )Nr  r  r  r  r  r  s       rl   _require_owner_or_adminr  {  sB    >D
)
$Cxx
uS$/Sy
C0d
eern   c                    t        |       }t        j                  |      }|2|j                  r&t	        |j                        t	        |d         k(  r|S t        | |       |S )Nrr   )r  r   r   r   r   r  )r  r   r  r  s       rl   _require_login_accessr    sT    >D!!),Gw3w3G3tTXz?3ZGY/Krn   c                   t        |       }t        ||      s|j                  d      r't        |      rt	        | |d          t        |       }|S t        |      rt	        | |d          t        |       S t        dd      )Nr  rr   r  u   Слот уже занятr  )r  r  r   r  r   r	   )r   r  r~  s      rl   _bind_if_freer    su    
)
$CS$488J/id4!),C
S)T$Z0y))
C0L
MMrn   c                ^    t        | t        t        |      j                  d                  S )Nr  r  )r
  r   r  r   )r~  r  s     rl   _serr    s#    C$uW~/A/A*/M*NOOrn   c                X   t        | j                  d            }t        | j                  d            }|rdn|rdnd}| d   |||| j                  d      xs d| j                  d	      xs dt               t        t	        | d         xs i j                  d
            t               d	S )Nr  rw  adminworkerr  rr   rf  rf   rv  usd_balance)	rr   r  rw  rolerf  rv  
free_slotsrx  slot_price_usd)r   r   r   r)  r    r"   )r  r  r  r  s       rl   _me_payloadr    s    *%&E$((;'(F7f(&D4jHHZ(.Bhh|,2&(!<T
#;#Ar"F"F}"UV(*
 
rn   z ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$g      N@c                B    t        |       }|st        dd|  d      |S )N  u   Устройство 'u   ' не найденоr  )r!   r	   )r   r~  s     rl   r  r    s,    
Y
C6LYKWl4mnnJrn   httpc                  K   | j                   j                  d      xs d}|dt        ddd}| j                  dk(  rt	        d|	      S | j
                  j                  }t        |       }|d
k7  r|rt        |      rt        ddid|	      S |j                  d      r |d
k7  r	 t        |       | j                  _         ||        d {   }|j#                         D ]  \  }}	|	|j                   |<    |dk7  r8|j%                  d      s't'        | j                   d| d|j                           |S # t        $ r.}t        d|j                  i|j                   |	      cY d }~S d }~ww xY w7 w)Noriginr\   zGET, POST, DELETE, OPTIONS86400Origin)zAccess-Control-Allow-OriginzAccess-Control-Allow-MethodszAccess-Control-Allow-HeaderszAccess-Control-Max-AgeVaryOPTIONS   )r  headersz/api/healthr  u   Доступ запрещёнr  z/api/z	/api/logsri   r"  z -> )r  r   _CORS_HEADERSr   r   urlpathr  r&   r   r  r   r   r  r	   r  r  rJ  endswithr   )
r  	call_nextr  corsr  r  r  responserL  r(  s
             rl   log_requestsr    sf    __  *1cF'-(D(5")D ~~"C66;;DG$I}|I/FX'FGUXbfggwDM$9	c!:7!CGMM w''Hjjl &
U %&{4==#; $tH,@,@+ABCO  	c3:: 6COO]abb	c (sC   B!E0$D4 >E0	E.
A*E04	E+=#E& E+!E0&E++E0z/healthc                    K   ddiS wNr   r  rj   rj   rn   rl   healthr         d   z/mec                6   K   dt        t        |             iS w)Nme)r  r  r  s    rl   api_mer    s     +eGn-..s   c                L    t        | d         }t        |      }||||dS |dS )Nrr   )personal_idsms_chat_ideffective_chat_id)r   r#   )r  personalcustoms      rl   _sms_settings_payloadr    sB    4:HX&F'-'9V  @H rn   z	/settingsc                2   K   t        t        |             S wr   )r  r  r  s    rl   api_settingsr    s      w00s   z/settings/sms-chatc                  K   t        |       }t        |d         }	 | j                          d {   }t	        |t
              r|j                  d      nd }|dv r#t	        |t
              r|j                  d      nd }t        |xs d      j                         }|st        |d        ddit        |      S t        |      }|t        dd	
      ||k(  rt        |d        ddit        |      S 	 t        |t               t        ||       ddit        |      S 7 # t        $ r i }Y w xY w# t        $ r t        |d        t        dt         
      w xY ww)Nrr   r  rg  chat_idrf   r  T  u$   Некорректный ID чатаr  )r  r   rF  r   r   rE  r   r   r:  r6   r  r.   r	   rN   rM   r'  rL   )r  r  r  bodyr=  rs   parseds          rl   api_set_sms_chatr    s\    >D4:H\\^# &0d%;$((=
!C
j%/d%;dhhy!syb>!D$'d:3D9::t$F~4Z[[$'d:3D9::D/
 Hf%$6/5665 $ (  D$'NCCDsP   ED! DD! B>E4D2 ED! !D/,E.D//E2'EEc           
     *   t        | j                  d      xs d      }|xs
 t               }t        | j                  d            }|| j                  d      xs d| j                  d      xs d|| xr ||v t	        | j                  d            dS )	Nr_  r   r  rf  rf   rv  r  ru  )r   r   setr   r)  )r~  
worker_idsr_  workersr  s        rl   _rent_user_payloadr    s     %A&E!CEGCGGJ'(HGGJ'-2ggl+1r"l8(8!#''-"89 rn   c                     t               D  ch c]  } t        |        }} i }t               D ]3  }	 t        |j                  d      xs d      }|s%t        ||      ||<   5 |S c c} w # t        t
        f$ r Y Nw xY w)Nr_  r   )r,   r   r'   r   rH  r'  r  )itemr  rZ  r~  r_  s        rl   r}  r}  "  s    (:(<=#d)=J= F @	(-A.E .sJ?F5M@ M >
 :& 		s   A%A**A<;A<z/rentc                N  K   t        |       }t               t        t        |d         xs i j	                  d            d}|j	                  d      rEt               D ch c]  }t        |       }}t               D cg c]  }t        ||       c}|d<   |S c c}w c c}w w)Nrr   r  )r  rx  r  users)	r  r"   r)  r    r   r,   r   r'   r  )r  r  r   r  r  r~  s         rl   api_rent_settingsr  /  s     >D!/!1*l[_`d[eNfNljlMqMqr  NA  CB  CGxx
,>,@ADc$iA
AKYK[\C.sJ?\N B\s   AB% B2B% B B%z/rent/pricec                (  K   t        |        	 | j                          d {   }t        |t              r|j                  d      nd }|dv r#t        |t              r|j                  d      nd }	 t        t        |      j                  dd      j                  dd            }	 t        |      }d|dS 7 # t        $ r i }Y w xY w# t        t        f$ r t        dd	
      w xY w# t        $ r}t        dt        |      
      |d }~ww xY ww)Nr  rg  pricer#  r$  r"  rf   r  u"   Укажите цену слотаr  T)r  r  )r  rF  r   r   rE  r   r   r   r   rH  r'  r	   r5   )r  r  r=  r  savedr  s         rl   api_set_rent_pricer  9  s    7\\^# )34(>$((#
$DC
j#-dD#9dhhwtZc#h&&sC088bABGu% %00 $  z" Z4XYYZ  GCH=3FGsn   DB9 B7B9 A
D24C
 'C* 2D7B9 9CDCD
C''D*	D3D

DDz/rent/topupc           	     v  K   t        |       }	 | j                          d {   }t        |t              r|j                  d      nd }|dv r#t        |t              r|j                  d      nd }	 t        |      }|dk  rt        dd      t        |t              r|j                  d      nd }	 t        t        t        |      j                  d	d
      j                  dd            d      }|dk  rt        dd      t        ||dt        |d               }t               D ch c]  }t        |       }	}d||t!        t#        |      xs ||d|	      dS 7 =# t        $ r i }Y Iw xY w# t        t        f$ r t        dd      w xY w# t        t        f$ r t        dd      w xY wc c}w w)Nr_  rg  rr   r     Укажите Telegram IDr  r   amountr#  r$  r"  rf   r7  u.   Укажите сумму пополненияu6   Сумма должна быть больше нуляtopup)reasonadmin_idT)r_  r  )r  r_  rx  r  )r  rF  r   r   rE  r   r   rH  r'  r	   roundr   r   r   r   r,   r  r    )
r  r  r  raw_idr_  
raw_amountr  new_balancer  r  s
             rl   api_rent_topupr  N  s    7#E\\^# #-T4"8TXXgdF#-dD#9$tRF z4PQQ'1$'=(#4JfuS_44S#>FFsBOPRST {4lmm$UF7SQVW[Q\M]^K(:(<=#d)=J=""<#6#fEZe:fhrs	 + $  z" R4PQQR z" f4deef
 >st   F9E" EE" A
F92E4 =5F93>F 19F9*F4<#F9E" "E1-F90E11F94FF9F11F9z/workersc                8   K   t        |        dt               iS w)Nr  )r  r,   r  s    rl   api_list_workersr  o  s     7)+,,s   c                  K   t        |        | j                          d {   }t        |t              r|j	                  d      nd }|dv r#t        |t              r|j	                  d      nd }	 t        |      }|dk  rt        dd      |t        t        xs d      v rt        dd	      t        |      st        dd
      t               ddS 7 # t        t        f$ r t        dd      w xY ww)Nr_  rg  rr   r  r  r  r   rj   u,   Админ и так имеет доступu$   Некорректный Telegram IDTr  r  )r  rF  r   rE  r   r   rH  r'  r	   r  r   r   r,   )r  r  r=  r_  s       rl   api_add_workerr  u  s     7D)$5$((7
4C
j *4 6dhhtnDRC z4PQQL&B''4bccE"4Z[[)+488   z" R4PQQRs)   C7CAC71C <AC7C44C7z/workers/{tg_id}c                j   K   t        |       t        |       st        dd      t               ddS w)Nr  u"   Работник не найденr  Tr  )r  r2   r	   r,   )r_  r  s     rl   api_delete_workerr    s2     7u%4XYY)+488s   13c                    t        | t              rt        dt        |             S t        dt        |       xs d      S )Nr  r  u   Ошибка userbot)r   r'  r	   r   )r  s    rl   _userbot_http_errorr     s4    #z"SX>>SS1S=STTrn   z/userbotc                H   K   t        |        t        j                         S wr   )r  userbot_runtimesnapshotr  s    rl   api_userbot_statusr    s     7##%%s    "z/userbot/loginc                  K   t        |        | j                          d {   }	 t        j                  t	        |j                  d      xs d             d {   S 7 >7 # t        t        f$ r}t        |      |d }~ww xY ww)Nphonerf   )	r  rF  r  request_coder   r   r'  r   r   r  r  r  s      rl   api_userbot_loginr	    sr     7D0$11#dhhw6G6M22NOOO  O% 0!#&C/0D   BA B4A$ A"A$ B"A$ $B3A??BBz/userbot/codec                  K   t        |        | j                          d {   }	 t        j                  t	        |j                  d      xs d             d {   S 7 >7 # t        t        f$ r}t        |      |d }~ww xY ww)Nr   rf   )	r  rF  r  r   r   r   r'  r   r   r  s      rl   api_userbot_coder    sr     7D0$00TXXf5E5K1LMMM  M% 0!#&C/0r
  z/userbot/passwordc                  K   t        |        | j                          d {   }	 t        j                  t	        |j                  d      xs d             d {   S 7 >7 # t        t        f$ r}t        |      |d }~ww xY ww)Nr   rf   )	r  rF  r  submit_passwordr   r   r'  r   r   r  s      rl   api_userbot_passwordr    ss     7D0$44S*9M9SQS5TUUU  U% 0!#&C/0r
  z/userbot/cancelc                \   K   t        |        t        j                          d {   S 7 wr   )r  r  r>   r  s    rl   api_userbot_cancelr    s#     7 --////s   #,*,z/userbot/logoutc                   K   t        |        	 t        j                          d {   S 7 # t        $ r}t	        |      |d }~ww xY wwr   )r  r  logoutr   r   )r  r  s     rl   api_userbot_logoutr    sD     70$++---- 0!#&C/0s0   A
- +- A
- 	AAAA
c                     t               } | j                  d      -t        j                         D ]  }|	 t	        |      | d<    | S  | S # t
        t        f$ r Y ,w xY w)Nalert_chat_id)r$   r   r   valuesr   rH  r'  )r   r(  s     rl   _watch_payloadr    st    Dxx ($++- 	E ,/JD) K	 K ":. s   AAAz/userbot/watchc                4   K   t        |        t               S wr   )r  r  r  s    rl   api_userbot_watchr    s     7s   c                   K   t        |        | j                          d {   }t        |t              st	        dd      t        |       t               S 7 6w)Nr  u+   Некорректные настройкиr  )r  rF  r   rE  r	   r4   r  )r  r  s     rl   api_userbot_watch_saver    sJ     7DdD!4abb	  s   AA7Az/userbot/dialogsc                   K   t        |        	 t        j                          d {   }d|iS 7 # t        $ r}t	        |      |d }~ww xY ww)Ndialogs)r  r  list_dialogsr   r   )r  r  r  s      rl   api_userbot_dialogsr     sR     70'4466 w 7 0!#&C/0s0   A1 /1 A1 	AAAAz/devicesc           	     ^  K   t        |       }	 t        |      r
t               nt        |d         }|j                  d      r
t               nd }|D cg c]  }t        ||j                  d      |      ! c}t        |      dS # t        $ r}t        dd|       |d }~ww xY wc c}w w)Nrr     u   Ошибка БД: r  r  rY  )devicesr  )
r  r  r(   r)   r   r	   r   r}  r
  r  )r  r  rowsr  rZ  r~  s         rl   api_list_devicesr%    s     >DZ!*4|~6Hd6T !% 4]_$Fcgh\_$S488J3GPVWh$   Z6I#4OPVYYZ is3   B-#B !B-$B(7B-	B%B  B%%B-c                :  K   t        |        | j                          d {   }|j                  d      xs( |j                  d      xs |j                  d      xs dj                         }|st	        dd      t        j                  d|      st	        dd	      t        |j                  d
      xs d      j                  dd      j                         }|st	        dd      |j                  d      }|dv rt	        dd      	 t        t        |      j                               }|j                  d      }||j                  d      }|t        |      dk(  rt	        dd      t        |      }t        |j                  d      xs |j                  d      xs d      j                         xs t        }|j                  d|j                  d            }|dv rt        }	n#	 t        t        |      j                               }	d|	cxk  rdk  sn t	        dd      t        ||      }
|
r&t	        dd| d| d |
j                  d       d!      	 t        j                   t"        ||       d {    	 t'        |||"       	 t-        |||||	'       dt1        t3        |      |       iS 7 # t        t        f$ r t	        dd      w xY w# t        t        f$ r t	        dd      w xY w7 ~# t$        $ r}t	        dt        |            |d }~ww xY w# t(        j*                  $ r t	        dd#| d$      t$        $ r}t	        d%d&|       |d }~ww xY w# t$        $ r!}t/        |       t	        d%d(|       |d }~ww xY ww))Nrr   r   r   rf   r  $   Укажите имя девайсаr  [A-Za-z0-9][A-Za-z0-9._-]{0,63}:   Имя девайса: латиница, цифры, . _ -r\  r#  r$     Укажите IPr]  rg  &   Укажите порт девайса:   Порт девайса должен быть числомr   ssh_passwordu*   Укажите пароль сервераserver_loginrn  server_portro  :   Порт сервера должен быть числомrq     "   Порт сервера: 1–65535r  IP rO  %    уже занят девайсом ''r\  r]     Девайс '   ' уже естьr"  u1   Не удалось создать девайс: rf  r]  ,   Не удалось сохранить SSH: )r  rF  r   r:  r	   r%  r;  r   r   r   rH  r'  rz  r{  r   r  	to_threadrG   r   r   sqlite3IntegrityErrorrU   r   r  r  )r  r  r   r\  port_rawr]  r   r.  server_port_rawr/  	duplicater  s               rl   api_create_devicerA    s    7D$O488H#5O&9IORVVXI4Z[[<<:IF4pqq
dhhtn"
#	,	,S#	6	<	<	>B4GHHxxH:4\]]r3x=&&() xx
#H88N+3x=B.4`aa8}H0NDHHZ4HNBOVVXl\lLhh}dhhz.BCO*$&	vc/288:;K $u$4XYY&r40IAdV#HW_I`Haabc
 	

G	2t444xiBT2sIr8lU
 d?95w?@@A    z" r4pqqr$ :& 	vC8tuu	v 	5 GCH=3FG
 !! cnYKO`4abb x6ghkgl4mntwwx
  si 6bcfbg4hiorrss   NJ<C,N"J? 1B?N1"K AN"L  K?L L) M. %N?KNK<<N?L 	L&
L!!L&&N),M+M&&M++N.	N7NNNz/devices/{device_id}/updatec                  K   t        |       t        |       }| t        v rt        dd      |j	                          d {   }t        |j                  d      xs |j                  d      xs |       j                         }|st        dd      t        j                  d|      st        dd	      t        d
|v r|j                  d
      n|j                  d
      xs d      j                  dd      j                         }|st        dd      d|v r|j                  d      nd }|dv r	 t        |j                  d            }n#	 t        t        |      j                               }|j                  d      }||j                  d      }|dn
t        |      }t        |       }	t        |j                  d      xs |j                  d      xs d      j                         }
|
s8t        |	xs i j                  d      xs d      j                         xs t        }
|j                  d|j                  d            }|dv r(	 t        |	xs i j                  d      xs t               }n#	 t        t        |      j                               }d|cxk  rdk  sn t        dd      || k7  rt#        |      rt        dd| d      t%        ||      }|r;|j                  d      | |hvr&t        dd | d!| d"|j                  d       d#      t        |j                  d
      xs d      }	 t        |j                  d            }||k7  s||k7  r$	 t'        j(                  t*        ||       d {    | }|| k7  rt/        | |      st        d$d%      	 t1        | |       | t2        v rt2        j5                  |       t2        |<   | t        v r*t        j7                  |        t        j9                  |       | t:        v rt:        j5                  |       t:        |<   |}t        |      xs |	}	t=        |||d'       t#        |      st        d$d(      |	s|r	 t?        |||r|nd |
|)       dtA        t        |      |      iS 7 Q# t        t        f$ r t        dd      w xY w# t        t        f$ r t        dd      w xY w# t        t        f$ r
 t         }Y Uw xY w# t        t        f$ r t        dd      w xY w# t        t        f$ r d }Y w xY w7 # t,        $ r}t        dt        |            |d }~ww xY w# t        $ r(}t/        ||        t        dt        |            |d }~wt,        $ r"}t/        ||        t        d$d&|       |d }~ww xY w# t,        $ r}t        d$d*|       |d }~ww xY ww)+Nr  6   Дождитесь окончания проверкиr  rr   r   r  r'  r(  r)  r\  rf   r#  r$  r*  r]  rg  r+  r,  r   r-  r.  rn  rf  r/  ro  r0  rq   r1  r2  r7  r8  r3  rO  r4  r5  r"  u;   Не удалось переименовать девайсu4   Не удалось переименовать SSH: r6  u3   Не удалось сохранить девайсr9  r:  )!r  r  rb   r	   rF  r   r   r:  r%  r;  r   r   rH  r'  rR   rz  r{  r!   r   r  r;  rG   r   r3   rS   ra   rv   r   r   rc   r9   rU   r  )r   r  r~  r  new_idr\  r>  r]  r   r  r.  r?  r/  r@  old_ipold_portr  
current_ids                     rl   api_update_devicerH  E  s    7
)
$CI4lmmD$B488H#5BCIIKF4Z[[<<:FC4pqq
dhhtn#''$-2E2
F	O	OPSUX	Y	_	_	aB4GHH#)T>txxtH:	bswwv'D	vs8}**,-D xx
#H88N+%r3x=HID0NDHHZ4HNBOVVXLDJB++J7=2>DDFZJZhh}dhhz.BCO*$	+tzr..v6J:JKK	vc/288:;K $u$4XYYz&1nVHL]4^__&r40IY]]8,Y4GGAdV#HW_I`Haabc
 	

 $"%Fswwv' |x4'	K##Ir4888 JY/C8uvv		6* %$1$5$5i$@M&!	!i(MM&!%$1$5$5i$@M&!

#+t*R67j!4ijjx		w$$%  d?:6@AAS   :& 	bC8`aa	b
 :& 	vC8tuu	v  :& 	+*K	+
 :& 	vC8tuu	v$ z"  9 	KCCAsJ	K  	K&),CCAsJ 	&),C:norns8tu{~~	4  	wC:fgjfk8lmsvv	ws/  ?WRC0W3R W"R5 1CW&S 4W6"S1 B"W;T 
W T, >T)?T,  W$U 0B6W'V1 ;WR22W5SWS.*W-S..W1TWT&"W%T&&W)T, ,	U5UUW	V.#V  V.V))V..W1	W:WWWz/devices/{device_id}c                d   K   t        ||       \  }}dt        ||j                  d            iS w)Nr   r  r  )r  r
  r   )r   r  r  r~  s       rl   api_get_devicerJ    s2     &w	:ID#&sTXXj5IJKKs   .0c                   K   t        |       t        |        | t        v rt        dd      t	        |       st        dd      	 t        |        d| d	S # t        $ r}t        d|  d|        Y d }~$d }~ww xY ww)
Nr  rC  r  r"  u/   Не удалось удалить девайсzdelete_host(r  Tr  rr   )r  r  rb   r	   r   rQ   r   r   r   r  r  s      rl   api_delete_devicerN    s     7II4lmm#4eff9I i((  9YKz#7889s0   AA>A A>	A; A61A>6A;;A>z/devices/{device_id}/logoutc                  K   t        ||       \  }}| t        v rt        dd      |j                  d      st        dd      t	        |        t        |       }d}	 |4 d {    t        j                  t        | t        |        d {    d d d       d {    t        |        d
t        t        |       |j                  d            i}|rd|d<   |S 7 w7 Q7 C# 1 d {  7  sw Y   SxY w# t        $ r d}Y ct        $ r  t        $ r}t        d	t        |            |d }~ww xY w# t        |        w xY ww)Nr  *   Девайс уже проверяетсяr  r   r  u   ЛК не привязанFTr"  r   r  r  r	  )r  rb   r	   r   r   r  r  r;  r   rE   r;   r   r   r   r
  r  )r   r  r  r~  r  r	  r  r   s           rl   api_logout_devicerQ    s@    ';ID#I4`aa7784PQQ)YDI
 	Z 	Z##$7IyYYY	Z 	Z 	I)/)*DtxxXbOcdeG#N	ZY	Z 	Z 	Z 	Z 	  GCH=3FG 	Is   AEC7 $C%C7 ($C"CC"C7 C C7 !;EC7 C" C7 "C4(C+)C40C7 7D1D4 D1D,,D11D4 4EEz/devices/{device_id}/kickc                  K   t        |       t        |       }t               }t        j	                  |       }|=|j
                  t        v r+|j                          ddt        t        |       d|      dS |j	                  d      r| t        v rt        dd      t        |        t        |       }d	}	 |4 d {    t        j                  t        | t         |        d {    d d d       d {    t)        |        ddt        t        |       d|      d}|rd|d<   |S 	 t+        |j	                  d      xs d      }	|	r1t1        |        t3        |        ddt        t        |       d|      dS t        dd      7 7 7 # 1 d {  7  sw Y   xY w# t"        $ r d}Y t        $ r  t$        $ r}t        d
t'        |            |d }~ww xY w# t)        |        w xY w# t,        t.        f$ r d}	Y w xY ww)NTr   rY  )r  r   r   r   r  rP  r  Fr"  r  r	  r_  r   releaser  u$   Нет активной сессии)r  r  r}  r   r   r   r  r   r
  rb   r	   r   r  r  r;  r   rE   r;   r   r   r   r   rH  r'  r/   r0   )
r   r  r~  rZ  r  r  r	  r  r   owner_ids
             rl   api_kick_sessionrU    s    7
)
$C_F!!),Gw~~1EE &y'ADY_`
 	
 wwx	!C8deei #	
	# ^ ^''(;Y	S\]]]^ ^ 	"&y'ADY_`

 #'GK swww',1- I&Y'&y'ADY_`
 	

 C0V
WW?^]^ ^ ^ ^ 	I 	 	KCCAsJ	K 	" z" s   B3H6F" <F=F"  $F$F	%F)F" 4F5F" 9/H)G/ A HF" 	FF" FFFF" "G-G /G GGG G,,H/H HHHz/devices/{device_id}/cards/addc                  K   t        ||       \  }}| t        v rt        dd      t        |        t	        |       }d }d}	 |4 d {    t        j                  t        | t        |        d {   }d d d       d {    t        |        t        t        |       |j                  d            }|r|dd	S |r|j                  d
      s$t        d|xs i j                  d      xs d      ||j                  d      dS 7 7 7 # 1 d {  7  sw Y   xY w# t        $ r d}Y t        $ r  t        $ r}t        dt        |            |d }~ww xY w# t        |        w xY ww)Nr  rP  r  FTr"  r  r  )r   r	  successmessageu1   Не удалось выпустить карту)r   rX  )r  rb   r	   r   r  r  r;  r   r<   r;   r   r   r   r
  r  r   )	r   r  r  _rowr  resultr	  r  r   s	            rl   api_add_cardr[  !  sq    ()<JD$I4`aa)YDFI
 	b 	b",,-@)XW`aaF	b 	b 	Ioi8488JCWXF t44I.V\r4F4Fy4Q  5I  VI  J  	JI)>??%	ba	b 	b 	b 	b 	  GCH=3FG 	Is   ?E/D" D	D" $D0D	1D5D"  DD" BE/D" 	DD" DDDD" "E-E /E EEE E,,E/z /devices/{device_id}/cards/flagsc           	     l  K   t        ||       \  }}|j                          d {   }t        j                  ddt	        |j                  d      xs d            }|st        dd      t        |       }t        |r|j                  d      nd       }|j                  |      xs dddd	}d
|v rt        |j                  d
            |d
<   d|v rt        |j                  d            |d<   d|v rt        |j                  d            |d<   |j                  d
      s"|j                  d      s|j                  d      r|||<   n|j                  |d        t        | t        j                  |d            st        dd      dt        t        |       |j                  d            iS 7 w)Nr+  rf   r   r  u$   Укажите номер картыr  rl  FrD  rA  rB  rC  )ensure_asciir"  u<   Не удалось сохранить флаги картыr   r  r  )r  rF  r%  r&  r   r   r	   r!   rM  r   rv   r8   dumpsr
  r  )	r   r  r  rY  r  r   r~  rK  currents	            rl   api_update_card_flagsr`  A  st    ';JD$DVVE2s488H#5#;<=F4Z[[
Y
CcSWW\2tDEiiSuuU#SGD!$((9"56	$ 12}dhhuo.{{9W!5U9Kf		&$Y

5u(MN4rss&y'ADHHU_L`abb+  s   #F4F1FF4Tr  c               D  K   |t         vrt        dd      | t        v rt        dd      t        |        t	        |       }d}	 |4 d {    t        j                  t        | t         |   |        d {    d d d       d {    t        |        d	t        t        |       |
      i}|rd|d<   |S 7 k7 B7 4# 1 d {  7  sw Y   DxY w# t        $ r d}Y Tt        $ r  t        $ r}t        dt        |            |d }~ww xY w# t        |        w xY ww)Nr  u.   Неизвестный тип проверкиr  r  rP  FTr"  r   r  r	  )CHECKERSr	   rb   r   r  r  r;  r   r;   r   r   r   r
  r  )r   kindr  r  r	  r  r   s          rl   run_device_checkrd  \  s'    84deeI4`aa)YDI
 	_ 	_##$7HTNT]^^^	_ 	_ 	I)/)*DxXYG#N	_^	_ 	_ 	_ 	_ 	  GCH=3FG 	Is   AD C B8C 'B>7B:8B><C B<C ,D 8C :B><C >CCCC DD  D1DDD DD z!/devices/{device_id}/check/{kind}c           	        K   t        ||       \  }}|j                  d      r"|j                  d      s|dvrt        dd      t        | |t	        |j                  d                   d {   S 7 w)Nrw  r  >   rW   rX   r  !   Недостаточно правr  r  )r  r   r	   rd  r   )r   rc  r  r  rY  s        rl   api_check_devicerg  w  sf     ';JD$xxTXXj%9dJa>a4WXX!)TD*AU<VWWWWs   A,A5.A3/A5c           	        t        j                  ddt        | j                  d      xs d            }t        j                  ddt        | j                  d      xs d            }|st	        dd      |st	        dd      ||fS )	Nr+  rf   r   r   r  *   Укажите номер телефонаr  1   Укажите пароль (код-пароль))r%  r&  r   r   r	   )r  r   r   s      rl   _parse_login_credentialsrk    sy    VVE2s488H#5#;<=FvveRTXXj%9%?R!@AH4`aa4ghh8rn   z	/lk/loginc                  K   t        |       }|j                  d      r|j                  d      st        dd      | j                          d{   }t	        |      \  }}t        |      }|r	 t        |d         }nt        |d         }|st        d	d      |d   }		 t        |	|||d         }
|
j                  |	t        t!        |	      |j                  d            t#        |      dS 7 # t        $ r;}dt        |      j                         v rd	nd
}t        |t        |            |d}~ww xY w# t        $ r |rt        |	       t        |	        w xY ww)u   Пользователь оплачивает слот (если нужно), занимает его и начинает вход в ЛК.rw  r  r  rf  r  Nrr   u   слотr  r  u&   Нет свободных слотовr   r  r  )r   r   r   r  )r  r   r	   rF  rk  r  r7   r'  r   lowerr   r  r/   r0   r   r
  r  r  )r  r  r  r   r   paidr~  r  r   r   r  s              rl   api_lk_loginro    sY     >DxxTXXj%94WXXD/5FH4 D	N$T$Z0C
  T
+C8`aaHI&y&(DQUJW .."?9#=Q[H\]$	 +    	N&#c(..*::SFF3s8D#M	N  	*Y'	sN   AE!C2E!1C4 ?#E!#D; 5>E!4	D8=6D33D88E!;#EE!z/devices/{device_id}/loginc                  K   t        |      }|j                  d      r|j                  d      st        dd      t        |      r	 t	        |d   |        t        | |       |j                          d {   }t        |      \  }}	 t        | |||d         }|j                  | t        |      d	S # t
        $ r}t        dt        |            |d }~ww xY w7 f# t        $ r t        |      rt        |         w xY ww)
Nrw  r  r  rf  r  rr   r  r  )r   r   r  )r  r   r	   r  r   r'  r   r  rF  rk  r  r/   r   r  )r   r  r  r  r  r   r   r  s           rl   api_login_startrq    s     >DxxTXXj%94WXXt	KT
I6 )T"D/5FH&y&(DQUJW
 nn9KPTDUVV  	KCCAsJ	K    4 	*sN   AD	B6 D7C8DC  D6	C?CCD !DDc                L  K   t        ||        t        j                  |       }|sddiS |j                  |j                  |j
                  |j                  | d}|j                  dk(  r|j                  |d<   |j                  dk(  r|j                  r|j                  |d<   |S w)Nr   idle)r   r   r   r   r   r   r  r   )	r  r   r   r   r   r   r   r   r   )r   r  r  r   s       rl   api_login_statusrt    s     7I.!!),G&!!......#44G ~~ "==~~GNN#NNNs   B"B$z/devices/{device_id}/login/codec           	       K   t        ||        t        j                  |       }|r|j                  dk7  rt	        dd      |j                          d {   }t        j                  ddt        |j                  d      xs d            }t        |      dk7  rt	        d	d
      |j                  |       ddiS 7 gw)Nr   r  +   Сейчас код не ожидаетсяr  r+  rf   r      r  u4   Код должен состоять из 6 цифрr   r   )r  r   r   r   r	   rF  r%  r&  r   r   r   )r   r  r  r  r   s        rl   api_login_coderx    s     7I.!!),Ggnn74abbD66%S&!1!7R89D
4yA~4jkkk""  s   AB?B=A(B?z!/devices/{device_id}/login/resendc                   K   t        ||        t        j                  |       }|r|j                  dk7  rt	        dd      |j
                  st	        dd      |j                          ddiS w)Nr   r  rv  r  u'   Кнопка ещё не активнаr   )r  r   r   r   r	   r   r   r   r  r  s      rl   api_login_resendr{    sj     7I.!!),Ggnn74abb##4]^^o&&s   A-A/z!/devices/{device_id}/login/cancelc                   K   t        ||        t        j                  |       }|r|j                  t        vrddiS |j                          d|j                  iS w)Nr   rs  )r  r   r   r   r  r   rz  s      rl   api_login_cancelr}    sU     7I.!!),Ggnn,@@&!!gnn%%s   AAc                    t        j                  ddt        | xs d            }t        |      dk(  r|d   dv r|dd  }|S )Nr+  rf      r   )78rq   )r%  r&  r   r   )r=  r   s     rl   _normalize_lk_numberr    sC    VVE2s39"~.F
6{bVAY*4Mrn   z"/devices/{device_id}/login/refreshc                   K   t        ||        | t        v rt        dd      	 t        j                  t
        |        d {   }|S 7 # t        $ r}t        dt        |            |d }~ww xY ww)Nr     Девайс занятr  r"  )r  rb   r	   r  r;  rB   r   r   )r   r  r   r  s       rl   api_login_refreshr    ss     7I.I4MNNG''(99EE L F GCH=3FGs:   "A3A A	A A3	A 	A0A++A00A3z /devices/{device_id}/login/claimc           	     f  K   t        |      }t        | |      }|j                  d      rt        dd      | t        v rt        dd      |j                          d{   }t        |j                  d            }t        j                  ddt        |j                  d	      xs d            }t        |      d
k7  rt        dd      t        |      dk  rt        dd      t        | |||d   d      st        dd      dt        t        |       |j                  d            iS 7 έw)uz   Сохранить номер и код-пароль, если вход в ЛК на устройстве уже есть.r   r  u   ЛК уже привязанr  r  Nr+  rf   r   
   r  ri  r-  rj  rr   )r   r   r_  r"  u+   Не удалось сохранить ЛКr   r  r  )r  r  r   r	   rb   rF  r  r%  r&  r   r   r9   r
  r  )r   r  r  r~  r  r   r   s          rl   api_login_claimr    s     >D
	4
(C
wwx4RSSI4MNND!$((8"45FvveRTXXj%9%?R!@AH
6{b4`aa
8}q4ghhv8VZ[_V`$ab4abb&y'ADHHU_L`abb  s   AD1 D/!CD1z/devices/{device_id}/screenc                  K   t        ||        t        j                  |       }	 |K|j                  ?|j                  t
        v r-t        j                  t        |j                         d{   }n"t        j                  t        |        d{   }t        |dddi      S 7 77 # t        $ r}t        dd|       |d}~ww xY ww)	u  Снять PNG-скриншот текущего экрана устройства.

    Во время активного входа переиспользуем живое ADB-соединение из сессии
    (если оно уже получено на шаге ввода кода), иначе подключаемся заново.
    Эндпоинт не блокируется на `_checking`, чтобы экран можно было смотреть
    прямо во время входа и проверок.
    N  u+   Не удалось снять экран: r  z	image/pngzCache-Controlzno-store, max-age=0)content
media_typer  )r  r   r   r   r   r  r  r;  rI   r?   r   r	   r   )r   r  r  pngr  s        rl   api_device_screenr  &  s      7I.!!),Gr7??#>7>>UiCi))-IIC)).)DDC  "78  JD r6abeaf4ghnqqrsM   "C
AB( ,B$-"B( B&B( C
$B( &B( (	C1CCC
z/logsc                   K   t        |        t        5  t        D cg c]  }|d   |kD  s| }}t        rt        d   d   n|}d d d        D cg c]  }|d   	 c}dS c c}w # 1 sw Y   $xY wc c}w w)Nrr   rs   )linesnext)r  rw   re   )r  afterr  rJ  nxts        rl   api_logsr  ?  s|     7	 <",C$T
U0BCC&0jnT"e< 055td6l5sCC D< < 6s=   A9	A(A#A#A(A9A4A9#A((A1-A9z/devices/{device_id}/backc                   K   t        ||        | t        v rt        dd      	 t        j                  t
        |        d {    ddiS 7 # t        $ r}t        dt        |            |d }~ww xY ww)Nr  u5   Недоступно во время действияr  r  r  T)r  rb   r	   r  r;  rF   r   r   rM  s      rl   api_device_backr  H  sx     7I.I4kllG 19=== $< 	> GCH=3FGs:   "A5A AA A5A 	A2A--A22A5z/devices/{device_id}/cancelc                  K   t        ||        t        j                  |       }|'|j                  t        v r|j                          dddS | t        vrt        dd      t        j                  |       }||j                          	 t        j                  t        |        d {    dddS 7 	# t        $ r}t        d|        Y d }~#d }~ww xY ww)	NTr  )r  rc  r  u*   Нет активного действияr  zcancel: press_back failed: r   )r  r   r   r   r  r   rb   r	   rc   r  r  r;  rF   r   r   )r   r  r  r   r  s        rl   api_cancel_actionr  T  s     7I.!!),Gw~~1EE G,,	!4`aaY'D
3 19=== )) 	> 3+C51223sB   BC
B3 'B1(B3 ,C1B3 3	C<C
CCCc                B   | j                  d      }|| j                  d      }t        |t              r|j                         }nt        |t              r|}ng }|D cg c]5  }t        |      j                         st        |      j                         7 c}S c c}w )Ncommandscommand)r   r   r   
splitlineslistr:  )r  r=  rJ  r  s       rl   _parse_ssh_commandsr  g  sy    
((:
C
{hhy!#s 	C	*/E$3t9??3DCIOOEEEs   B>Bz/devices/{device_id}/sshc           
       K   t        |       t        |        |j                          d {   }t        |      }|st	        dd      t        dt        t        dt        |            z        }	 t        j                  t        | ||d       d {   }d|i}t        |      dk(  rM|d	   j!                  d
      xs d|d
<   |d	   j!                  d      xs d|d<   |d	   j!                  d      |d<   |S 7 7 g# t        $ r}t	        dt        |            |d }~wt        $ r}t	        dt        |            |d }~wt        $ r}t	        dt        |            |d }~ww xY ww)Nr  u   Укажите командуr  r   rq   Fr  resultsr   stdoutrf   stderr	exit_code)r  r  rF  r  r	   r   SSH_COMMAND_TIMEOUTr   r   r  r;  rT   r'  r   r   r   r   )r   r  r  r  r   r  r  r   s           rl   api_ssh_commandr  t  s]    7ID"4(H4STT%,s1c(m/DDEGG))
 
 '"G
7|q#AJNN84:#AJNN84:&qz~~k:N5  
  GCH=3F GCH=3F GCH=3FGs_   *E*C8AE*2 C< C:C< A"E*:C< <	E'DE'(D??E'E""E''E*z/devices/{device_id}/rebootc                R  K   t        ||       \  }}| t        v rt        dd      t        |        t	        |       }d}	 |4 d {    t        j                  t        | t        |        d {    d d d       d {    t        |        t        t        |       |j                  d            dd	}|rd|d
<   |S 7 x7 R7 D# 1 d {  7  sw Y   TxY w# t        $ r d}Y dt        $ r  t        $ r}t        dt        |            |d }~ww xY w# t        |        w xY ww)Nr  rP  r  FTr"  r  r  )r   r  r	  )r  rb   r	   r   r  r  r;  r   rH   r;   r   r   r   r
  r  r   )r   r  r  rY  r  r	  r  r   s           rl   api_reboot_devicer    s'    ';JD$I4`aa)YDI
 	^ 	^##$7MS\]]]	^ 	^ 	I)/)*DtxxXbOcdlpqG#N	^]	^ 	^ 	^ 	^ 	  GCH=3FG 	Is   =D' C B?C 
$C.C/C3C >C?C <D'?C CC CCCC D%D 'D8DDD D$$D'z/devices/{device_id}/passwordc           	     .  K   t        ||        |j                          d {   }t        j                  ddt	        |j                  d      xs d            }t        |      dk  rt        dd      t        | |      st        dd	      d
| dS 7 pw)Nr+  rf   r   r-  r  u0   Код-пароль: минимум 4 цифрыr  r"  u3   Не удалось сохранить парольTrL  )	r  rF  r%  r&  r   r   r   r	   r:   )r   r  r  r   s       rl   api_update_passwordr    s     GY/DvveRTXXj%9%?R!@AH
8}q4fgg9h/4ijji((  s    BBA1Bc                  K   | r| t         v ry t        |        t        |       }	 |4 d {    t        j                  t
        | t        |        d {    d d d       d {    t        d|         t        |        y 7 V7 07 "# 1 d {  7  sw Y   2xY w# t        $ r}t        d|  d|        Y d }~Fd }~ww xY w# t        |        w xY ww)Nzauto lock-logout done: zauto lock-logout z: )
rb   r   r  r  r;  r   rE   r   r   r   )r   r  r  s      rl   _auto_lock_logoutr    s     	Y.)YD 	Z 	Z##$7IyYYY	Z 	Z'	{34 	I	ZY	Z 	Z 	Z 	Z  6!)Bse4556 	Is   "CB BB $BBBB #B$B 6CB BB BBBB 	C&B<7C <CC CCc                 ~  K   	 t        j                  d       d {    	 t        j                  t        t               d {   } | D ]1  }t        t        |j                  d      xs d             d {    3 	 |7 c7 >7 # t         j                  $ r  t        $ r}t        d|        Y d }~6d }~ww xY ww)N<   r   rf   zlock logout loop: )r  r   r;  r+   r|  r  r   r   CancelledErrorr   r   )duer~  r  s      rl   _lock_logout_loopr    s     
mmB	.))*>@STTC F'CGGH,=,C(DEEEF	 TE%% 	 	.&se,--	.s\   B=B B=!B B3B 7B8B >B=B B B:"B50B=5B::B=startupc                    K   t        j                          d {    t        j                  t	                     ay 7 "wr   )r  bootr  create_taskr  rg   rj   rn   rl   _userbot_startupr    s4      


   ++,=,?@ !s   ?=#?shutdownc                    K   t         } d a | r| j                          	 |  d {    t	        j
                          d {    y 7 !# t        j                  $ r Y 4w xY w7  wr   )rg   r   r  r  r  r  )tasks    rl   _userbot_shutdownr    s_      D	JJ 
"
"
$$$ %% 		$sB   A"A AA A"A  A"A AA"AA"c                    K   ddiS wr  rj   rj   rn   rl   root_healthr    r  r  r9  c                 .   K   t        t        dz        S w)Nz
index.html)r   
WEBAPP_DIRrj   rn   rl   indexr    s     
\122s   )	directorywebapp)r   __main__z0.0.0.0)r  r]  reloadssl_certfilessl_keyfile)rk   r   returnr   )rs   r   r  None)r  r  )r   r   r  r  )r   r   )r  'LoginSession'r  r  )r  r   r   )
r   r   r   r   r   r   r   r   r  r  )r   r   r  zasyncio.Lock)r  r   )r   r   r  r   )r=  r   r  r   )r  rE  )r=  zOptional[str]r  z
list[dict])r~  rE  r  r   rZ  zOptional[dict]r  rE  )r  rE  r  r   )r  r   r  rE  )r  r   r  r   )r~  rE  r  rE  r  r   )r~  rE  r  r   )r  r   r   r   )r  r   r   r   r  rE  )r   r   r  rE  r  rE  )r~  rE  r  r   r  rE  )r  rE  r  rE  )r   r   r  rE  )r  r   )r~  rE  r  zset[int] | Noner  rE  )r  zdict[int, dict])r_  r   r  r   r  rE  )r  BaseExceptionr  r	   )r   r   r  r   r  rE  )r   r   rc  r   r  r   r  rE  )r   r   rc  r   r  r   r  rE  )r  rE  r  ztuple[str, str])r  r   )r   r   r  r   r  r   )r   )r  r   r  r   r  rE  )r  rE  r  z	list[str])r  r   )zserver.panel_server:app(  r   
__future__r   r  rF  r   r%  r<  sysr   r   collectionsr   pathlibr   typingr   __file__resolveparent_ROOTr   r  insertfastapir   r   r	   r
   r   fastapi.middleware.corsr   fastapi.responsesr   r   r   fastapi.staticfilesr   server.authr   server.configr   r   r   r   
api.db_apir   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   server.userbot_servicerK   r  server.tg_sendrL   rM   rN   utils.ssh_cmdrO   r{  rP   rz  rQ   rR   rS   rT   rU   r  PORTrb  rV   add_middlewareapira   __annotations__r  rb   rc   localr   r   r   r  rw   re   rx   rt   r|  rg   rm   r|   r~   r   r  r  r   r   r   r   r   r   r  r   r   r   r   r  r  r  r  r)  r4  r?  rM  rX  r
  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  compile_DEVICE_ID_REr  r  
middlewarer  r   r  r  r  r  postr  r  r}  r  r  r  r  r  deleter  r   r  r	  r  r  r  r  r  r  r  r   r%  rA  rH  rJ  rN  rQ  rU  r[  r`  rd  rg  rk  ro  rq  rt  rx  r{  r}  r  r  r  r  r  r  r  r  r  r  r  include_routerr  r  on_eventr  r  r  r  mountr   uvicornkwargscertrL  existsrunrj   rn   rl   <module>r     s	   #    	  
     X ''..u:SXXHHOOAs5z" E E 2 B B + 1 R R& & & & & & & & & &N F  F  F  F  F = J J   U]
 	 M"   %%%	   v)+& +e	8 ,.) .yjjINN	t,
K , ,0 ) 0>""- "-J #**g&$CJ#**g&$CJ
?) "
 * +1
'
 .0* /N  NY NY- Y-x, -F
G2@ 5:TX M` =N?Nff
NP" 

>?   >   / / 1 1 
7  7B
   -1 1( - @ - -
 *9 9& 9  9U & &
 
0 0 /0 0 
0 0 
0 0
 
0 0
 	 
 
  	    
 
 *BA BAJ 
'(oB )oBd 	 L !L
 "#) $) 
'( )8 
%&3X '3Xl 
*+@ ,@> 
,-c .c4 KO 6 
-.X /X + D 
&'W (W* 	%& '& 
+,# -# 
-.' /' 
-.& /& 
./ 0 
,-c .c, 	&' (0 D D 
%& ' 
'(* )*$
F 
$% &@ 
'( )4 
)*) +)   3 
. iA A j
% 
%   3 3 		#{Z0x	 @ z?F!-44D*${
C#**,!$T~ #C}GKK4V4 rn   