Files
OpenVPN-Monitoring-Simple/APP/__pycache__/openvpn_api_v3.cpython-314.pyc

226 lines
32 KiB
Plaintext
Raw Normal View History

2026-01-09 01:05:50 +03:00
+
<00> ais<00><00>t<00>^RIt^RIt^RIHtHtHt^RIHtHtHt^RI H
2026-01-09 01:05:50 +03:00
t
^RI t ^RI t ^RI t ^RIHt^RIt^RIHt] P&!] P(RR7] P*!]4t]!]4t]
!]4!R R
4t]!4t]P7R R .R 7R4t]P7RR .R 7R4t]P7RR .R 7R4t]P7RR .R 7R4t]P7RR .R 7R4t ]P7RR .R 7R4t!]P7RR .R 7R4t"]R8Xdl]PFPIRRRR7t%R t&]PFPORR!R"R7t(]PSR#]% R$]& 24]PU]%]&](R%7R#R#)&<26>N)<03>datetime<6D> timedelta<74>timezone)<03>Flask<73>jsonify<66>request)<01>CORS)<01>Path)<01>DatabaseManagerz)%(asctime)s - %(levelname)s - %(message)s)<02>level<65>formatc<00>ha<00>]tRt^toR RltRtRtRtRtRt Rt
RR lt R
t RR lt R tVtR#)<10>
OpenVPNAPIc<08><><00>\V4Vn\P!4VnVPP V4VPP RRRR7VnVPP RRRR7VnVPP RRRR7PR4Vn /Vn
R#)<08> certificates<65>certificates_pathz/etc/openvpn/certs<74><01>fallback<63>certificate_extensionsz crt,pem,key<65>,N) r <00>
db_manager<EFBFBD> configparser<65> ConfigParser<65>config<69>read<61>getr<00>split<69>cert_extensions<6E> _cert_cache)<02>self<6C> config_files&&<26>APP/openvpn_api_v3.py<70>__init__<5F>OpenVPNAPI.__init__s<><00><00>)<29>+<2B>6<><04><0F>"<22>/<2F>/<2F>1<><04> <0B> <0C> <0B> <0B><18><18><1B>%<25>!%<25><1B><1B><1F><1F><1E>AT<41>_s<5F><1F>!t<><04><1E>!%<25><1B><1B><1F><1F><1E>AT<41>_s<5F><1F>!t<><04><1E>#<23>{<7B>{<7B><EFBFBD><EFBFBD>~<7E>?W<>bo<62><EFBFBD>p<>v<>v<>wz<77>{<7B><04><1C><1D><04><18>c <0C>6<00>VPP4#)zGet a database connection)r<00>get_connection)r s&r"<00>get_db_connection<6F>OpenVPNAPI.get_db_connection!s<00><00><13><EFBFBD><EFBFBD>-<2D>-<2D>/<2F>/r%c<08><><00>VP4p\V^,4^8XdRV^, 2V^&RPV4p\P!VR4# \
2026-01-09 01:05:50 +03:00
dW\P!TR4u# \
d.\ PRT 24\Puu#i;ii;i)<05><00> z%b %d %H:%M:%S %Y GMTz%b %d %H:%M:%S %Y %ZzCould not parse date: ) r<00>len<65>joinr<00>strptime<6D>
ValueError<EFBFBD>logger<65>warning<6E>min)r <00>date_str<74>parts<74>normalized_dates&& r"<00>parse_openssl_date<74>OpenVPNAPI.parse_openssl_date&s<><00><00> $<24><1C>N<EFBFBD>N<EFBFBD>$<24>E<EFBFBD><12>5<EFBFBD><11>8<EFBFBD>}<7D><01>!<21><1E>u<EFBFBD>Q<EFBFBD>x<EFBFBD>j<EFBFBD>><3E><05>a<EFBFBD><08>!<21>h<EFBFBD>h<EFBFBD>u<EFBFBD>o<EFBFBD>O<EFBFBD><1B>$<24>$<24>_<EFBFBD>6M<36>N<> N<><4E><19> $<24> $<24><1F>(<28>(<28><18>3I<33>J<>J<><4A><1D> $<24><16><0E><0E>!7<><08>z<EFBFBD>B<>C<><1F>|<7C>|<7C>#<23> $<24><> $<24>s0<00>AA <00> C<03>,B<02>C<03>3B=<05>8C<03><B=<05>=Cc<08> <00>VR8XdR#VPV4pV\P8XdR#V\P!4,
2026-01-09 01:05:50 +03:00
PpV^8dR\ V4 R2#V R2# \ dR#i;i)<04>N/Az Expired (z
days ago)z days)r7rr3<00>now<6F>days<79>abs<62> Exception)r <00> not_after_str<74>expiration_date<74>days_remainings&& r"<00>calculate_days_remaining<6E>#OpenVPNAPI.calculate_days_remaining4s|<00><00> <18>E<EFBFBD> !<21>%<25> '<27>"<22>5<>5<>m<EFBFBD>D<>O<EFBFBD><1E>(<28>,<2C>,<2C>.<2E>u<EFBFBD>-<2D><08> <0C> <0C><0E>><3E>D<>D<>N<EFBFBD><1D><01>!<21>I<EFBFBD>c<EFBFBD>.<2E>6I<36>5J<35>*<2A>*U<>#U<>*<2A>+<2B>5<EFBFBD>1<>1<><31><18>&<26><15>&<26>s<00>&A4<00>;A4<00>/A4<00>4 B<03>Bc
2026-01-09 01:05:50 +03:00
<08><><00>\P!RRRVRR.RRRR7pVPpR\PP V4RVR R
R R
R R
/pVP R 4F<>pVP4pVPR4'diVP R^4^,P4VR &\P!RVR ,4pV'dVP^4VR&K<>K<>RV9gK<>VP R^4^,P4VR &K<> VR ,R
8wd+VPVR ,4P4VR&M!\PP4VR&VP!VR ,4VR&RVR,9VR&V# \"d'p\$P'RT RT 24Rp?R#Rp?ii;i)<1A>openssl<73>x509z-inz-nooutz-textT)<03>capture_output<75>text<78>check<63>file<6C> file_path<74>subjectr:<00>issuer<65> not_after<65>
2026-01-09 01:05:50 +03:00
zSubject:z
CN=([^,]+)<29> common_namez Not After<65>:<3A> sort_daterA<00>Expired<65>
2026-01-09 01:05:50 +03:00
is_expiredzError processing z: N)<14>
subprocess<EFBFBD>run<75>stdout<75>os<6F>path<74>basenamer<00>strip<69>
startswith<EFBFBD>re<72>search<63>groupr7<00> isoformatrr3rBr>r1<00>error)r <00> cert_file<6C>result<6C>output<75>data<74>line<6E>cn_match<63>es&& r"<00>extract_cert_info<66>OpenVPNAPI.extract_cert_info>s<><00><00> <18><1F>^<5E>^<5E>Y<EFBFBD><06><05>y<EFBFBD>(<28>T[<5B>$\<5C>15<31>D<EFBFBD><04>N<01>F<EFBFBD><1B>]<5D>]<5D>F<EFBFBD><1A>B<EFBFBD>G<EFBFBD>G<EFBFBD>,<2C>,<2C>Y<EFBFBD>7<><1B>i<EFBFBD>QZ<51>\a<><1C>e<EFBFBD>[<5B>%<25>9<>D<EFBFBD><1F> <0C> <0C>T<EFBFBD>*<2A><04><1B>z<EFBFBD>z<EFBFBD>|<7C><04><17>?<3F>?<3F>:<3A>.<2E>.<2E>&*<2A>j<EFBFBD>j<EFBFBD><1A>Q<EFBFBD>&?<3F><01>&B<>&H<>&H<>&J<>D<EFBFBD><19>O<EFBFBD>!<21>y<EFBFBD>y<EFBFBD><1D><04>Y<EFBFBD><0F>H<>H<EFBFBD><1F>x<EFBFBD>~<7E>~<7E>a<EFBFBD>7H<37><14>m<EFBFBD>!4<>x<EFBFBD> <20>D<EFBFBD>(<28>(,<2C>
2026-01-09 01:05:50 +03:00
<EFBFBD>
<EFBFBD>3<EFBFBD><01>(:<3A>1<EFBFBD>(=<3D>(C<>(C<>(E<>D<EFBFBD><1B>%<25>+<2B><14>K<EFBFBD> <20>E<EFBFBD>)<29>$(<28>$;<3B>$;<3B>D<EFBFBD><1B><M<>$N<>$X<>$X<>$Z<><04>[<5B>!<21>$,<2C>L<EFBFBD>L<EFBFBD>$:<3A>$:<3A>$<<3C><04>[<5B>!<21>%)<29>%B<>%B<>4<EFBFBD> <0B>CT<43>%U<>D<EFBFBD>!<21> "<22>!*<2A>d<EFBFBD>3C<33>.D<>!D<>D<EFBFBD><1C> <1E><17>K<EFBFBD><4B><18> <18> <12>L<EFBFBD>L<EFBFBD>,<2C>Y<EFBFBD>K<EFBFBD>r<EFBFBD>!<21><13>=<3D> ><3E><17><> <18>s%<00>CF6<00>"F6<00>B2F6<00>6 G'<03>G"<03>"G'c<08>F<00>\VP4pVP4'g.#.pVPF4pVP VP RVP 4 244K6 \4p.pVF<>p\V4pVPV4\PPV4pVPPV4p V 'd)V R,V8XdVPV R,4K<>VP!V4p
V
'd'RVRV
/VPV&VPV
4K<>K<> \%VPP'44Fp W<>9gK VPV K V# \"dEKi;i)z*.<2E>mtimere)r
r<00>existsr<00>extend<6E>rglobr[<00>set<65>str<74>addrXrY<00>getmtimerr<00>appendri<00>OSError<6F>list<73>keys) r <00> cert_path<74>
cert_files<EFBFBD>ext<78>current_valid_files<65> cert_data<74>cert_file_pathrbrl<00>cached<65> parsed_data<74> cached_files & r"<00>get_certificates_info<66> OpenVPNAPI.get_certificates_info\sv<00><00><18><14>/<2F>/<2F>0<> <09><18><1F><1F>!<21>!<21>"<22>9<EFBFBD><17>
<EFBFBD><17>'<27>'<27>C<EFBFBD> <16> <1D> <1D>i<EFBFBD>o<EFBFBD>o<EFBFBD><02>3<EFBFBD>9<EFBFBD>9<EFBFBD>;<3B>-<2D>.@<40>A<> B<>(<28>"<22>e<EFBFBD><1B><16> <09>(<28>N<EFBFBD><1B>N<EFBFBD>+<2B>I<EFBFBD> <1F> #<23> #<23>I<EFBFBD> .<2E> <19><1A><07><07>(<28>(<28><19>3<><05><1E>)<29>)<29>-<2D>-<2D>i<EFBFBD>8<><06><19>f<EFBFBD>W<EFBFBD>o<EFBFBD><15>6<><1D>$<24>$<24>V<EFBFBD>F<EFBFBD>^<5E>4<>#'<27>"8<>"8<><19>"C<>K<EFBFBD>"<22>#<23>U<EFBFBD>"<22>K<EFBFBD>7<1A><04>(<28>(<28><19>3<>"<22>(<28>(<28><1B>5<> #<23>)<29>0 <20><04> 0<> 0<> 5<> 5<> 7<>8<>K<EFBFBD><1A>5<><18>$<24>$<24>[<5B>1<>9<><19><18><><1B> <19><18> <19>s<00>"A(F<02> F<02>%$F<02> F <05>F c  <0C><><00>VP4pVP4pVPR4VPUu.uF q3^,NK pp.pVP 4F&pVP \ \WF444K( VVP4#uupi \d5p\PRT 24.uRp?TP4#Rp?ii;i TP4i;i)<04>&Get current statistics for all clientsu<73>
2026-01-09 01:05:50 +03:00
SELECT
c.common_name,
c.real_address,
c.status,
CASE
WHEN c.status = 'Active' THEN 'N/A'
ELSE strftime('%Y-%m-%d %H:%M:%S', c.last_activity)
END as last_activity,
c.total_bytes_received,
c.total_bytes_sent,
-- Пиковая скорость Download за последние 2 минуты
(SELECT MAX(uh.bytes_received_rate_mbps)
FROM usage_history uh
WHERE uh.client_id = c.id
AND uh.timestamp >= datetime('now', '-30 seconds')) as current_recv_rate,
-- Пиковая скорость Upload за последние 2 минуты
(SELECT MAX(uh.bytes_sent_rate_mbps)
FROM usage_history uh
WHERE uh.client_id = c.id
AND uh.timestamp >= datetime('now', '-30 seconds')) as current_sent_rate,
strftime('%Y-%m-%d %H:%M:%S', c.updated_at) as last_updated
FROM clients c
ORDER BY c.status DESC, c.common_name
zError fetching data: N) r(<00>cursor<6F>execute<74> description<6F>fetchallrt<00>dict<63>zip<69>closer>r1ra)r <00>connr<6E><00>column<6D>columnsre<00>rowrhs& r"<00>get_current_stats<74>OpenVPNAPI.get_current_stats<74>s<><00><00><13>%<25>%<25>'<27><04><15><1B><1B><1D><06>- <19> <13>N<EFBFBD>N<EFBFBD><10> <11>406<30>/A<>/A<>B<>/A<>V<EFBFBD>a<EFBFBD>y<EFBFBD>y<EFBFBD>/A<>G<EFBFBD>B<><15>D<EFBFBD><1D><EFBFBD><EFBFBD>(<28><03><14> <0B> <0B>D<EFBFBD><13>W<EFBFBD>!2<>3<>4<>)<29><18> <11>J<EFBFBD>J<EFBFBD>L<EFBFBD><4C>C<01><><19> <16> <12>L<EFBFBD>L<EFBFBD>0<><11><03>4<> 5<><15>I<EFBFBD> <10>J<EFBFBD>J<EFBFBD>L<EFBFBD><4C>  <16><> <11>J<EFBFBD>J<EFBFBD>L<EFBFBD>sA<00>B'<00>B"<04>?B'<00>"B'<00>' C&<03>2C!<03> C&<03> C)<00>!C&<03>&C)<00>)C;Nc  <0C>$<00>VP4pVP4pV'g\P!4pV'gV\ ^R7,
2026-01-09 01:05:50 +03:00
p\ V\ 4'd\P!VR4p\ V\ 4'd\P!VR4pW2,
P4R, pRRRRRR R
R R R RR/pRp VR8Xd"V^8:dRp M%V^<5E>8:dR p MVR8:dR p MRp MWH9d W<>,p VPRV R24VP4'g\PRV R24Rp T R8gp
Rp ^p ^p T R8XdFTR8:dRp ^p ^xp M7TR8:dRp ^<p ^<5E>p M)TR8:dRp ^xp ^<5E>p MTR8:dRp Rp ^<5E>p M TR8:dRp Rp ^`p T 'dRT R T R!T R T R"2 pMT
'dR#T R$2pMR%pTPR4pTPR4pTPY<>TT34TPUu.uF pT^,NK ppTP4Uu.uFp\!\#TT44NK ppTpT 'd<>.pTUu/uF pTR&,TbK ppTP%4pTTT ,,
p\P&!T4pT\ Y<>,R'7,
pTp\)T 4FcpT\ T R'7, pTPR4pTT9dTP+TT,4KHTP+R&TR(^R)^R*^R+^/4Ke R,TR-R.Y<>'dR/MR0,R1\-T4R2TR3T//TP/4# EL;i EL<>;i EL?;iuupiuupiuupi \0dBp\P3R4T 24R,.R5\ T4/uR6p?TP/4#R6p?ii;i TP/4i;i)7u<37>
2026-01-09 01:05:50 +03:00
Получение истории с поддержкой агрегации (TSDB).
Автоматически выбирает таблицу (Raw, Hourly, Daily) в зависимости от периода.
<EFBFBD><01>hours<72>%Y-%m-%d %H:%M:%Si<00>raw<61> usage_history<72>5min<69>
stats_5min<EFBFBD>15min<69> stats_15min<69>hourly<6C> stats_hourly<6C>6h<36>stats_6h<36>daily<6C> stats_daily<6C>autoip<00><SELECT name FROM sqlite_master WHERE type='table' AND name='<27>'zTable z# missing, fallback to usage_historyFg<46><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?Tg<54><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD>@gffffff@g333333(@i,g<><67><EFBFBD><EFBFBD><EFBFBD>8@<40><>zV
SELECT
datetime((strftime('%s', uh.timestamp) / <20>) * a, 'unixepoch') as timestamp,
SUM(uh.bytes_received) as bytes_received,
SUM(uh.bytes_sent) as bytes_sent,
MAX(uh.bytes_received_rate_mbps) as bytes_received_rate_mbps,
MAX(uh.bytes_sent_rate_mbps) as bytes_sent_rate_mbps
FROM usage_history uh
JOIN clients c ON uh.client_id = c.id
WHERE c.common_name = ? AND uh.timestamp BETWEEN ? AND ?
GROUP BY datetime((strftime('%s', uh.timestamp) / zF, 'unixepoch')
ORDER BY timestamp ASC
z<>
2026-01-09 01:05:50 +03:00
SELECT
t.timestamp,
t.bytes_received,
t.bytes_sent,
0 as bytes_received_rate_mbps,
0 as bytes_sent_rate_mbps
FROM z<> t
JOIN clients c ON t.client_id = c.id
WHERE c.common_name = ? AND t.timestamp BETWEEN ? AND ?
ORDER BY t.timestamp ASC
a<>
SELECT
uh.timestamp,
uh.bytes_received,
uh.bytes_sent,
uh.bytes_received_rate_mbps,
uh.bytes_sent_rate_mbps
FROM usage_history uh
JOIN clients c ON uh.client_id = c.id
WHERE c.common_name = ? AND uh.timestamp BETWEEN ? AND ?
ORDER BY uh.timestamp ASC
<20> timestamp<6D><01>seconds<64>bytes_received<65>
bytes_sent<EFBFBD>bytes_received_rate_mbps<70>bytes_sent_rate_mbpsre<00>meta<74>resolution_used<65>_hires<65><00> record_count<6E>start<72>endzError fetching history: raN)r(r<>rr;r<00>
isinstancerqr/<00> total_secondsr<73><00>fetchoner1r2<00>strftimer<65>r<>r<>r<>r<><00>utcfromtimestamp<6D>rangertr-r<>r>ra)r rP<00>
2026-01-09 01:05:50 +03:00
start_date<EFBFBD>end_date<74>
resolutionr<EFBFBD>r<><00>duration_hours<72> table_map<61> target_table<6C> is_aggregated<65> is_high_res<65>interval<61> points_count<6E>query<72>s_str<74>e_strr<72>r<>r<><00> db_data_list<73>
final_data<EFBFBD> db_data_map<61>ts_end<6E>
ts_aligned<EFBFBD> aligned_end<6E>start_generated<65>current<6E>_<>ts_strrhs&&&&& r"<00>get_client_history<72>OpenVPNAPI.get_client_history<72>so<00><00>
2026-01-09 01:05:50 +03:00
<14>%<25>%<25>'<27><04><15><1B><1B><1D><06><18><1F>|<7C>|<7C>~<7E>H<EFBFBD><19>!<21>I<EFBFBD>B<EFBFBD>$7<>7<>J<EFBFBD> <16>j<EFBFBD>#<23> &<26> &<26>&<26>/<2F>/<2F>
<EFBFBD><O<>P<><1A> <15>h<EFBFBD><03> $<24> $<24>$<24>-<2D>-<2D>h<EFBFBD>8K<38>L<><18>#<23>/<2F>><3E>><3E>@<40>4<EFBFBD>G<><0E> <12>?<3F> <12>L<EFBFBD> <13>]<5D> <14>n<EFBFBD> <10>*<2A> <13>]<5D> 
<EFBFBD> <09>'<27> <0C> <16><16> <1F><1D><12>#<23>.<2E> <0C><1F>3<EFBFBD>&<26>-<2D> <0C><1F>4<EFBFBD>'<27>)<29> <0C>,<2C> <0C> <17> $<24>$<24>0<>L<EFBFBD> <11> <12>N<EFBFBD>N<EFBFBD>Y<>Zf<5A>Yg<59>gh<67>i<> j<><19>?<3F>?<3F>$<24>$<24><16><0E><0E><16> <0C>~<7E>5X<35>Y<>Z<>.<2E> <0C>} <19>(<28>O<EFBFBD>;<3B>M<EFBFBD> <20>K<EFBFBD><18>H<EFBFBD><1C>L<EFBFBD><1B><EFBFBD>.<2E>!<21>S<EFBFBD>(<28>"&<26>K<EFBFBD>!<21>H<EFBFBD>#&<26>L<EFBFBD>#<23>s<EFBFBD>*<2A>"&<26>K<EFBFBD>!<21>H<EFBFBD>#&<26>L<EFBFBD>#<23>s<EFBFBD>*<2A>"&<26>K<EFBFBD>"<22>H<EFBFBD>#&<26>L<EFBFBD>#<23>t<EFBFBD>+<2B>"&<26>K<EFBFBD>"<22>H<EFBFBD>#&<26>L<EFBFBD>#<23>t<EFBFBD>+<2B>"&<26>K<EFBFBD>"<22>H<EFBFBD>#%<25>L<EFBFBD><1A>><3E>>F<>Z<EFBFBD>t<EFBFBD>H<EFBFBD>:<3A>VC<01>DL<01>*<2A>D<EFBFBD>QY<51>PZ<50>[<11> <14><05><1F><16>#<23>^<5E>$<11> <14><05> <11><05><1F>'<27>'<27>(;<3B><<3C>E<EFBFBD><1C>%<25>%<25>&9<>:<3A>E<EFBFBD> <12>N<EFBFBD>N<EFBFBD>5<EFBFBD><05>u<EFBFBD>"=<3D> ><3E>/5<>/A<>/A<>B<>/A<>V<EFBFBD>v<EFBFBD>a<EFBFBD>y<EFBFBD>y<EFBFBD>/A<>G<EFBFBD>B<>?E<><EFBFBD><EFBFBD>?P<>Q<>?P<><03>D<EFBFBD><13>W<EFBFBD>c<EFBFBD>!2<>3<>?P<>L<EFBFBD>Q<>%<25>J<EFBFBD><1A><1F>
<EFBFBD>@L<>M<> <0C><13>s<EFBFBD>;<3B>/<2F><13>4<> <0C> <0B>M<>"<22>+<2B>+<2B>-<2D><06>#<23>v<EFBFBD><08>'8<>9<>
<EFBFBD>&<26>7<>7<>
<EFBFBD>C<> <0B>#.<2E> <09>,<2C>BY<42>0Z<30>"Z<><0F>)<29><07><1E>|<7C>,<2C>A<EFBFBD><1B>y<EFBFBD><18>:<3A>:<3A>G<EFBFBD>$<24>-<2D>-<2D>.A<>B<>F<EFBFBD><1D><1B>,<2C>"<22>)<29>)<29>+<2B>f<EFBFBD>*=<3D>><3E>"<22>)<29>)<29>'<27><16>,<2C>a<EFBFBD>(<28>!<21>6<><01>2<>A<EFBFBD> +<1A><1B>-<2D> <17>
<EFBFBD><16>%<25>|<7C>;<3B>x<EFBFBD>TV<54>'W<>"<22>C<EFBFBD>
<EFBFBD>O<EFBFBD><1B>U<EFBFBD><19>5<EFBFBD> <12><0E> <11>J<EFBFBD>J<EFBFBD>L<EFBFBD><4C>M <19>D<EFBFBD><44> <19>D<EFBFBD><44>F <11> <10><>^C<01><>Q<><51>N<01><>H<19> 1<> <12>L<EFBFBD>L<EFBFBD>3<>A<EFBFBD>3<EFBFBD>7<> 8<><1A>B<EFBFBD><07><13>Q<EFBFBD><16>0<> 0<> <10>J<EFBFBD>J<EFBFBD>L<EFBFBD><4C>  1<><31> <11>J<EFBFBD>J<EFBFBD>L<EFBFBD>s<EFBFBD><00>/N<00>N<00>*N<00>N<00>AN.<00>=N.<00>A N.<00>"N<04>4N.<00>N$<04>&N.<00>8N)<04> C+N.<00>N <03>N<03>N<03>N.<00>. O:<03>9&O5<03>O:<03> O=<00>5O:<03>:O=<00>=Pc <0C>t<00>VP4pVP4pVPR4VP4pVPUu.uF qD^,NK ppV'da\ \ WS44p\VR,R, ^4VR&\VR,R, ^4VR&VVP4#/VP4#uupi \d5p\PRT 24/uRp?TP4#Rp?ii;i TP4i;i) u3Общая статистика по системеaR
2026-01-09 01:05:50 +03:00
SELECT
COUNT(*) as total_clients,
SUM(CASE WHEN status = 'Active' THEN 1 ELSE 0 END) as active_clients,
COALESCE(SUM(total_bytes_received), 0) as total_bytes_received,
COALESCE(SUM(total_bytes_sent), 0) as total_bytes_sent
FROM clients
<20>total_bytes_received<65>total_received_gb<67>total_bytes_sent<6E> total_sent_gbzError system stats: Ni@) r(r<>r<>r<>r<>r<>r<><00>roundr<64>r>r1ra)r r<>r<>rcr<>r<><00>statsrhs& r"<00>get_system_stats<74>OpenVPNAPI.get_system_statsts<00><00><13>%<25>%<25>'<27><04><15><1B><1B><1D><06> <19> <12>N<EFBFBD>N<EFBFBD><10> <11><1C>_<EFBFBD>_<EFBFBD>&<26>F<EFBFBD>/5<>/A<>/A<>B<>/A<>V<EFBFBD>a<EFBFBD>y<EFBFBD>y<EFBFBD>/A<>G<EFBFBD>B<><15><1C>S<EFBFBD><17>1<>2<><05>-2<>5<EFBFBD>9O<39>3P<33>T[<5B>3\<5C>^_<>-`<60><05>)<29>*<2A>).<2E>u<EFBFBD>5G<35>/H<>G<EFBFBD>/T<>VW<56>)X<><05>o<EFBFBD>&<26><1C> <11>J<EFBFBD>J<EFBFBD>L<EFBFBD> <16>
<11>J<EFBFBD>J<EFBFBD>L<EFBFBD><4C>C<01><><19> <16> <12>L<EFBFBD>L<EFBFBD>/<2F><01>s<EFBFBD>3<> 4<><15>I<EFBFBD> <10>J<EFBFBD>J<EFBFBD>L<EFBFBD><4C>  <16><> <11>J<EFBFBD>J<EFBFBD>L<EFBFBD>sH<00>/C#<00>C<04>"AC#<00> C#<00>C#<00># D"<03>.D<03>D"<03>D%<00>D"<03>"D%<00>%D7c <0C><00>VP4pVP4pR^R.R.RR^R^//p^pRpRpVR 8Xd^<5E>pR
pR pM VR 8XdR pRpR pVPRV R24VP4'gRpTR8XdRpMRpRT RT RT RT RT RT RT R2p TPT 4TP 4p
TP
U u.uF q<>^,NK p p T
U u/uFq<>^,\ \Y<>44bK pp .TR&\P!4pTP4pTTT,,
p\P!T4pT\^`T,R7,
pTp\^`4FspT\TR7, pTPR4pTT9d"TR,PTT,4KOTR,PRTR^R^R^R ^R!^/4Ku ^pTR,F%p T P!R!^4T8<>gKT R!,pK' TTR&R"T R#T R$2pTPT4TP
U u.uF q<>^,NK pp TP 4U u.uFp \ \TT 44NK up TR&R%T R&T R'2pTPT4TP4pT'd,RT^,;'g^RT^,;'g^/TR&TTP#4# RpEL<>;iuup iuup iuup iuup i \$d5p\&P)R(T 24TuR)p?TP#4#R)p?ii;i TP#4i;i)*zQ
2026-01-09 01:05:50 +03:00
Get aggregated analytics with dynamic resolution.
range_arg: '24h', '7d', '30d'
<EFBFBD>max_concurrent_24h<34>top_clients_24h<34>global_history_24h<34>traffic_distribution<6F>rx<72>txr<78>r<><00>7di<64>r<><00>30di<64>ixir<>r<>z[SUM(bytes_received_rate_mbps) as total_rx_rate, SUM(bytes_sent_rate_mbps) as total_tx_rate,z'0 as total_rx_rate, 0 as total_tx_rate,zK
2026-01-09 01:05:50 +03:00
SELECT
datetime((strftime('%s', timestamp) / r<>a<>, 'unixepoch') as timestamp,
SUM(total_rx) as total_rx,
SUM(total_tx) as total_tx,
MAX(total_rx_rate) as total_rx_rate,
MAX(total_tx_rate) as total_tx_rate,
MAX(active_count) as active_count
FROM (
SELECT
timestamp,
SUM(bytes_received) as total_rx,
SUM(bytes_sent) as total_tx,
zT
COUNT(DISTINCT client_id) as active_count
FROM z6
WHERE timestamp >= datetime('now', '-zy hours')
GROUP BY timestamp
) sub
GROUP BY datetime((strftime('%s', timestamp) / z>, 'unixepoch')
2026-01-09 01:05:50 +03:00
ORDER BY timestamp ASC
r<>r<>r<><00>total_rx<72>total_tx<74> total_rx_rate<74> total_tx_rate<74> active_countz<74>
2026-01-09 01:05:50 +03:00
SELECT
c.common_name,
SUM(t.bytes_received) as rx,
SUM(t.bytes_sent) as tx,
(SUM(t.bytes_received) + SUM(t.bytes_sent)) as total_traffic
FROM zg t
JOIN clients c ON t.client_id = c.id
WHERE t.timestamp >= datetime('now', '-zk hours')
GROUP BY c.id
ORDER BY total_traffic DESC
LIMIT 3
zy
SELECT
SUM(bytes_received) as rx,
SUM(bytes_sent) as tx
FROM z3
WHERE timestamp >= datetime('now', '-z hours')
zAnalytics error: N)r(r<>r<>r<>r<>r<>r<>r<>r<00>utcnowr<77>r<>rr<>r<>rtrr<>r>r1ra)r <00> range_argr<67>r<><00> analyticsr<73><00>interval_secondsr<73><00> rate_cols<6C>
query_hist<EFBFBD>rows<77>colr<6C>r<><00>db_datar;<00>ts_nowr<77><00> now_aligned<65>
start_timer<EFBFBD>r<>r<><00> max_clients<74> query_top<6F>top_cols<6C>
query_dist<EFBFBD>dist_resrhs&& r"<00>get_analytics_data<74>OpenVPNAPI.get_analytics_data<74>s
<00><00>
2026-01-09 01:05:50 +03:00
<14>%<25>%<25>'<27><04><15><1B><1B><1D><06> !<21>!<21> <1D>r<EFBFBD> <20>"<22> "<22>T<EFBFBD>1<EFBFBD>d<EFBFBD>A<EFBFBD>$6<> 
<EFBFBD> <09><13><05><1E><18>&<26> <0C> <14><04> <1C><18>U<EFBFBD> $<24> <1D>*<2A>\<5C> <16>%<25> <1F><18>U<EFBFBD> %<25> <1D>*<2A>\<5C> ,<2C> <13>^<5E>^<5E>Z<>[g<>Zh<5A>hi<68>j<> k<><1A>O<EFBFBD>O<EFBFBD>%<25>%<25> /<2F><1C>p <19><1B><EFBFBD>.<2E>y<> <09>E<> <09>7<>7G<37>6H<36><04>M]<5D>L^<5E> _<15><1F>K<EFBFBD> <16>"<22>^<5E>$6<>6;<3B>W<EFBFBD>=<<3C>=M<01>;M<>T<EFBFBD>Rb<52>Qc<51>d <0A>'<10>J<EFBFBD>. <13>N<EFBFBD>N<EFBFBD>:<3A> &<26><19>?<3F>?<3F>$<24>D<EFBFBD>)/<2F>);<3B>);<3B><<3C>);<3B>#<23>1<EFBFBD>v<EFBFBD>v<EFBFBD>);<3B>G<EFBFBD><<3C>BF<42>G<>$<24>3<EFBFBD>1<EFBFBD>v<EFBFBD>t<EFBFBD>C<EFBFBD><07>$5<>6<>6<>$<24>G<EFBFBD>G<>/1<>I<EFBFBD>*<2A> +<2B><1A>/<2F>/<2F>#<23>C<EFBFBD><18>]<5D>]<5D>_<EFBFBD>F<EFBFBD><1F>6<EFBFBD>,<<3C>#<<3C>=<3D>J<EFBFBD>"<22>3<>3<>J<EFBFBD>?<3F>K<EFBFBD>%<25>y<EFBFBD><12>>N<>9N<39>'O<>O<>J<EFBFBD> <20>G<EFBFBD><1A>2<EFBFBD>Y<EFBFBD><01><17>9<EFBFBD>-=<3D>><3E>><3E><07> <20>)<29>)<29>*=<3D>><3E><06><19>W<EFBFBD>$<24><1D>2<>3<>:<3A>:<3A>7<EFBFBD>6<EFBFBD>?<3F>K<><1E>3<>4<>;<3B>;<3B>#<23>V<EFBFBD>"<22>A<EFBFBD>"<22>A<EFBFBD>'<27><11>'<27><11>&<26><01> =<16><17><1F>"<1C>K<EFBFBD> <20>!5<>6<>6<><03><16>7<EFBFBD>7<EFBFBD>><3E>1<EFBFBD>-<2D> <0B>;<3B>"%<25>n<EFBFBD>"5<>K<EFBFBD>7<>/:<3A>I<EFBFBD>*<2A> +<2B><12> <1F><1E> 4<>49<34>7<EFBFBD>; <0A> <10>I<EFBFBD> <13>N<EFBFBD>N<EFBFBD>9<EFBFBD> %<25>*0<>*<<3C>*<<3C>=<3D>*<<3C>3<EFBFBD>A<EFBFBD><06><06>*<<3C>H<EFBFBD>=<3D>PV<50>P_<50>P_<50>Pa<50>+b<>Pa<50><13>D<EFBFBD><13>X<EFBFBD>s<EFBFBD>1C<31>,D<>Pa<50>+b<>I<EFBFBD>'<27> (<28><12><1F><1E> 2<>27<32><17>9 <0A> <10>J<EFBFBD> <13>N<EFBFBD>N<EFBFBD>:<3A> &<26><1D><EFBFBD><EFBFBD>(<28>H<EFBFBD><17>59<35>8<EFBFBD>A<EFBFBD>;<3B>;K<>;K<>!<21>T<EFBFBD>S[<5B>\]<5D>S^<5E>Sc<53>Sc<53>bc<62>4d<34> <09>0<>1<><1C> <11>J<EFBFBD>J<EFBFBD>L<EFBFBD><4C>g ,<2C>+<2B>\<5C><>H=<3D><>G<><47>p><3E><>+b<><62> <19> <1D> <12>L<EFBFBD>L<EFBFBD>,<2C>Q<EFBFBD>C<EFBFBD>0<> 1<><1C> <1C> <10>J<EFBFBD>J<EFBFBD>L<EFBFBD><4C>  <1D><> <11>J<EFBFBD>J<EFBFBD>L<EFBFBD>s<EFBFBD><00>*L<00><L<00>?AL4<00>L <04>#L4<00>)$L%<04> DL4<00>$:L4<00>L*<04>/L4<00>L/<04>!7L4<00>L4<00>*L4<00>=L4<00>L<03> L4<00>4 M3<03>?M.<03>M3<03>M6<00>.M3<03>3M6<00>6N)rrrrr)z
config.ini)NNr<4E>)<01>24h)<10>__name__<5F>
__module__<EFBFBD> __qualname__<5F>__firstlineno__r#r(r7rBrir<>r<>r<>r<>r<><00>__static_attributes__<5F>__classdictcell__)<01> __classdict__s@r"rrsB<00><><00><00><1E>0<>
$<24>'<27><18><'<19>T2<19>hx<19>t<19>:U<19>Ur%rz /api/v1/stats<74>GET)<01>methodsc <04>8<00>\P4p.pVF<>p\VR,;'g^R, ^4VR&\VR,;'g^R, ^4VR&VR,;'g^VR&VR,;'g^VR&VPV4K<> \ R R
2026-01-09 01:05:50 +03:00
R \
P !4PR 4R VR\V4/4# \d%p\ R RR\T4/4R3uRp?#Rp?ii;i)r<>r<><00>total_received_mbr<62><00> total_sent_mb<6D>current_recv_rate<74>current_recv_rate_mbps<70>current_sent_rate<74>current_sent_rate_mbps<70>successTr<54>r<>re<00>countFra<00><>N<>) <0B>apir<69>r<>rtrrr;r<>r-r>rq)re<00>formatted_data<74>clientrhs r"<00> get_statsr-s#<00><00>A<01><12>$<24>$<24>&<26><04><1B><0E><1A>F<EFBFBD>*/<2F><16>8N<38>1O<31>1T<31>1T<31>ST<53>Yb<59>0c<30>ef<65>*g<>F<EFBFBD>&<26> '<27>&+<2B>V<EFBFBD>4F<34>-G<>-L<>-L<>1<EFBFBD>QZ<51>,[<5B>]^<5E>&_<>F<EFBFBD>?<3F> #<23>/5<>6I<36>/J<>/O<>/O<>a<EFBFBD>F<EFBFBD>+<2B> ,<2C>/5<>6I<36>/J<>/O<>/O<>a<EFBFBD>F<EFBFBD>+<2B> ,<2C> <1A> !<21> !<21>&<26> )<29> <1B><17> <15>t<EFBFBD> <17><18><1C><1C><1E>0<>0<>1D<31>E<> <12>N<EFBFBD> <13>S<EFBFBD><1E>(<28> 
2026-01-09 01:05:50 +03:00
<EFBFBD> <0B> <0B><> <15>A<01><16> <09>5<EFBFBD>'<27>3<EFBFBD>q<EFBFBD>6<EFBFBD>:<3A>;<3B>S<EFBFBD>@<40>@<40><>A<01>s0<00>/C*<00>AC*<00>;C*<00>AC*<00>* D<03>5D<03>D<03>Dz/api/v1/stats/systemc <04><><00>\P4p\RRR\P!4P R4RV/4# \ d%p\RRR\T4/4R3uR p?#R p?ii;i)
zGet system-wide statisticsrTr<54>r<>reFrarN)rr<>rrr;r<>r>rq)r<>rhs r"r<>r<>Dsz<00><00>A<01><13>$<24>$<24>&<26><05><16> <15>t<EFBFBD> <17><18><1C><1C><1E>0<>0<>1D<31>E<> <12>E<EFBFBD>
2026-01-09 01:05:50 +03:00
<EFBFBD> <0B> <0B><>
<15>A<01><16> <09>5<EFBFBD>'<27>3<EFBFBD>q<EFBFBD>6<EFBFBD>:<3A>;<3B>S<EFBFBD>@<40>@<40><>A<01>s<00>AA <00> A8<03>A3<03>-A8<03>3A8z"/api/v1/stats/<string:common_name>c<04><>a<00>\PPRRR7p\PPRRR7p\P!\
P 4pV\^R7,
pVPR4'd!V\\VRR*4R7,
pMtVPR 4'd!V\\VRR*4R
7,
pM=VPR 4'd'V\\VRR*4R ,R
7,
p\P4p\V3R lV4R4pV'g\RRRR/4R3#\PSVVVR7pRVR,RVR,RVR,RR\VR,;'g^R+, ^4R\VR,;'g^R+, ^4/RRVR,;'g^RVR ,;'g^/R!VR!,R"VPR#.4R$VPR$/4/p\RR%R&\P!\
P 4P!R'4R#V/4# \"d=p \$P'R(T 24\RRR\)T 4/4R)3uRp ? #Rp ? ii;i),z<>
Get detailed stats for a client.
Query Params:
- range: '24h' (default), '7d', '30d', '1y' OR custom dates
- resolution: 'auto' (default), 'raw', '5min', 'hourly', 'daily'
r<EFBFBD>r<><00><01>defaultr<74>r<>r<><00>hN<68>d)r<<00>yimc3<00>F<"<00>TFqR,S8XgKVx<00>K R#5i)rPN<>)<03>.0<EFBFBD>crPs& <20>r"<00> <genexpr><3E>#get_client_stats.<locals>.<genexpr>ms<00><><00><00>T<>y<EFBFBD>!<21>m<EFBFBD>4D<34> <0B>4S<34>A<EFBFBD>A<EFBFBD>y<EFBFBD>s<00>!<01>
!rFrazClient not foundi<64>)r<>r<>r<>rP<00> real_address<73>status<75>totals<6C> received_mbr<62><00>sent_mbr<62><00> current_rates<65> recv_mbpsr <00> sent_mbpsr <00> last_activity<74>historyrer<>Tr<54>r<>z API Error: r<00><><EFBFBD><EFBFBD><EFBFBD>r)r<00>argsrrr;r<00>utcr<00>endswith<74>intrr<><00>nextrr<>r<>r<>r>r1rarq)
rPr<>r<>r<>r<><00> all_stats<74> client_data<74>history_result<6C>responserhs
f r"<00>get_client_statsr8Qs<><00><><00><A<01><1B>L<EFBFBD>L<EFBFBD>$<24>$<24>W<EFBFBD>e<EFBFBD>$<24><<3C> <09><1C>\<5C>\<5C>%<25>%<25>l<EFBFBD>F<EFBFBD>%<25>C<>
2026-01-09 01:05:50 +03:00
<EFBFBD><1C><<3C><<3C><08> <0C> <0C>-<2D><08><1D> <09><02> 3<>3<>
<EFBFBD> <15> <1D> <1D>c<EFBFBD> "<22> "<22>!<21>I<EFBFBD>C<EFBFBD> <09>#<23>2<EFBFBD><0E>4G<34>$H<>H<>J<EFBFBD> <16> <1F> <1F><03> $<24> $<24>!<21>I<EFBFBD>3<EFBFBD>y<EFBFBD><13>"<22>~<7E>3F<33>$G<>G<>J<EFBFBD> <16> <1F> <1F><03> $<24> $<24>!<21>I<EFBFBD>3<EFBFBD>y<EFBFBD><13>"<22>~<7E>3F<33><13>3L<33>$M<>M<>J<EFBFBD><18>)<29>)<29>+<2B> <09><1A>T<>y<EFBFBD>T<>VZ<56>[<5B> <0B><1A><1A>I<EFBFBD>u<EFBFBD>g<EFBFBD>7I<37>J<>K<>S<EFBFBD>P<> P<><1D>/<2F>/<2F> <17>!<21><1D>!<21> 0<>
<EFBFBD><0E> <1A>;<3B>}<7D>5<> <1A>K<EFBFBD><0E>7<> <14>k<EFBFBD>(<28>+<2B> <14><1D>u<EFBFBD>k<EFBFBD>2H<32>&I<>&N<>&N<>Q<EFBFBD>S\<5C>%]<5D>_`<60>a<><19>5<EFBFBD>+<2B>.@<40>"A<>"F<>"F<>Q<EFBFBD>9<EFBFBD>!U<>WX<57>Y<><0E> <1C><1B>[<5B>)<<3C>=<3D>B<>B<><11><1B>[<5B>)<<3C>=<3D>B<>B<><11><0E> <1C>[<5B><1F>9<> <15>~<7E>)<29>)<29>&<26>"<22>5<> <12>N<EFBFBD>&<26>&<26>v<EFBFBD>r<EFBFBD>2<>
<EFBFBD><08>&<17> <15>t<EFBFBD> <17><18><1C><1C>h<EFBFBD>l<EFBFBD>l<EFBFBD>3<><<3C><<3C>=P<>Q<> <12>H<EFBFBD>
<EFBFBD> <0B> <0B><> <15>A<01><0E> <0C> <0C>{<7B>1<EFBFBD>#<23>&<26>'<27><16> <09>5<EFBFBD>'<27>3<EFBFBD>q<EFBFBD>6<EFBFBD>:<3A>;<3B>S<EFBFBD>@<40>@<40><>A<01>sL<00>BJ<00>6J<00>
6J<00>A(J<00>*A
J<00>5AJ<00>:J<00> A3J<00> K<03> 1K<03>=K<03>Kz/api/v1/certificatesc <00><><00>\P4p\RRRV/4# \d%p\RRR\ T4/4R3uRp?#Rp?ii;i)rTreFrarN)rr<>rr>rq)rerhs r"<00>get_certificatesr:<00>sY<00><00>A<01><12>(<28>(<28>*<2A><04><16> <09>4<EFBFBD><16><14>6<>7<>7<><37> <14>A<01><16> <09>5<EFBFBD>'<27>3<EFBFBD>q<EFBFBD>6<EFBFBD>:<3A>;<3B>S<EFBFBD>@<40>@<40><>A<01>s<00>"%<00> A<03>A<03> A<03>Az/api/v1/clientsc <00><><00>\P4pVUu.uFpRVR,RVR,/NK pp\RRRV/4#uupi \d%p\RRR\ T4/4R3uRp?#Rp?ii;i) rPr%rTreFrarN)rr<>rr>rq)rer!<00> simple_listrhs r"<00>get_clients_listr=<00>s<><00><00>A<01><12>$<24>$<24>&<26><04>Y]<5D>^<5E>Y]<5D>TU<54> <0A>q<EFBFBD><1D>'7<><18>1<EFBFBD>X<EFBFBD>;<3B>O<>Y]<5D> <0B>^<5E><16> <09>4<EFBFBD><16><1B>=<3D>><3E>><3E><>_<01><> <14>A<01><16> <09>5<EFBFBD>'<27>3<EFBFBD>q<EFBFBD>6<EFBFBD>:<3A>;<3B>S<EFBFBD>@<40>@<40><>A<01>s-<00>A <00>A<04>A <00>A <00> A<<03>A7<03>1A<<03>7A<z/api/v1/healthc <00><><00>\P4pVP4\RRRR/4# \d'p\RRRRR\ T4/4R3uRp?#Rp?ii;i) rTr%<00>healthyF<79> unhealthyrarN)rr(r<>rr>rq)r<>rhs r"<00> health_checkrA<00>sg<00><00>X<01><12>$<24>$<24>&<26><04> <0C>
2026-01-09 01:05:50 +03:00
<EFBFBD>
<EFBFBD> <0C><16> <09>4<EFBFBD><18>9<EFBFBD>=<3D>><3E>><3E><> <14>X<01><16> <09>5<EFBFBD>(<28>K<EFBFBD><17>#<23>a<EFBFBD>&<26>Q<>R<>TW<54>W<>W<><57>X<01>s<00>25<00> A&<03>A!<03>A&<03>!A&z/api/v1/analyticsc
<04><><00>\PPRRR7pRRRRRR/pVPVR4p\P V4p\ RRR\ P!\P4PR 4R
VRV/4# \d=p\PR T 24\ RR R \T4/4R3uRp?#Rp?ii;i)zGet dashboard analytics datar<61>r<>rr<>r<>rTr<54>r<>rezError in analytics endpoint: FrarN)rr/rrr<>rrr;rr0r<>r>r1rarq)r<><00> valid_ranges<65>selected_rangererhs r"<00> get_analyticsrE<00>s<><00><00>A<01><1B>L<EFBFBD>L<EFBFBD>$<24>$<24>W<EFBFBD>e<EFBFBD>$<24><<3C> <09><1E>u<EFBFBD>d<EFBFBD>D<EFBFBD>%<25><15>?<3F> <0C>%<25>)<29>)<29>)<29>U<EFBFBD>;<3B><0E><12>%<25>%<25>n<EFBFBD>5<><04><16> <15>t<EFBFBD> <17><18><1C><1C>h<EFBFBD>l<EFBFBD>l<EFBFBD>3<><<3C><<3C>=P<>Q<> <12>D<EFBFBD> <13>^<5E> 
<EFBFBD> <0B> <0B><> <15>A<01><0E> <0C> <0C>4<>Q<EFBFBD>C<EFBFBD>8<>9<><16> <09>5<EFBFBD>'<27>3<EFBFBD>q<EFBFBD>6<EFBFBD>:<3A>;<3B>S<EFBFBD>@<40>@<40><>A<01>s<00>BB<00> C<03>!1C<03>C<03>C<03>__main__r<00>hostz0.0.0.0ri<><00>debugFzStarting API on rQ)rG<00>portrH)+<2B>sqlite3rrrr<00>flaskrrr<00>
flask_corsr <00>loggingrUrX<00>pathlibr
r]<00>dbr <00> basicConfig<69>INFO<46> getLoggerr<72>r1<00>apprr<00>routerr<>r8r:r=rArErrrGrI<00>
getbooleanrH<00>inforVrr%r"<00><module>rWs<><00><01><0E><13>2<>2<>)<29>)<29><1B><0E><11> <09><18> <09><1E><08><13><13>
2026-01-09 01:05:50 +03:00
<11>,<2C>,<2C> 6<><02>
<11> <1A> <1A>8<EFBFBD> $<24><06> <0B>H<EFBFBD>o<EFBFBD><03><04>S<EFBFBD> <09>O<19>O<19>d<11>l<EFBFBD><03><05><19><19>?<3F>U<EFBFBD>G<EFBFBD><19>,<2C>A<01>-<2D>A<01>,<05><19><19> !<21>E<EFBFBD>7<EFBFBD><19>3<>
2026-01-09 01:05:50 +03:00
A<01>4<>
A<01><05><19><19> /<2F>%<25><17><19>A<>CA<01>B<01>CA<01>J<05><19><19> !<21>E<EFBFBD>7<EFBFBD><19>3<>A<01>4<>A<01><05><19><19> <1C>u<EFBFBD>g<EFBFBD><19>.<2E>A<01>/<2F>A<01><05><19><19> <1B>e<EFBFBD>W<EFBFBD><19>-<2D>X<01>.<2E>X<01><05><19><19> <1E><15><07><19>0<>A<01>1<>A<01>( <0C>z<EFBFBD><19> <0E>:<3A>:<3A>><3E>><3E>%<25><16>)<29>><3E> <<3C>D<EFBFBD> <0F>D<EFBFBD> <0F>J<EFBFBD>J<EFBFBD> !<21> !<21>%<25><17>5<EFBFBD> !<21> A<>E<EFBFBD>
<EFBFBD>K<EFBFBD>K<EFBFBD>"<22>4<EFBFBD>&<26><01>$<24><16>0<>1<><07>G<EFBFBD>G<EFBFBD><14>D<EFBFBD><05>G<EFBFBD>.<2E> r%