From 96ea504b10d3784395f68e006ef81c4ebb3919b0 Mon Sep 17 00:00:00 2001 From: MoonDev Date: Wed, 21 May 2025 07:55:46 +0300 Subject: [PATCH] first commit --- __pycache__/callback.cpython-311.pyc | Bin 0 -> 2662 bytes callback.py | 51 +++++ callbacks/__pycache__/example.cpython-311.pyc | Bin 0 -> 523 bytes callbacks/__pycache__/lock.cpython-311.pyc | Bin 0 -> 1374 bytes callbacks/__pycache__/media.cpython-311.pyc | Bin 0 -> 4946 bytes callbacks/__pycache__/screen.cpython-311.pyc | Bin 0 -> 1802 bytes callbacks/__pycache__/system.cpython-311.pyc | Bin 0 -> 3731 bytes callbacks/__pycache__/v2ray.cpython-311.pyc | Bin 0 -> 8385 bytes callbacks/__pycache__/web.cpython-311.pyc | Bin 0 -> 1663 bytes callbacks/example.py | 5 + callbacks/lock.py | 21 ++ callbacks/media.py | 109 ++++++++++ callbacks/screen.py | 28 +++ callbacks/system.py | 86 ++++++++ callbacks/v2ray.py | 135 ++++++++++++ callbacks/web.py | 39 ++++ config/v2ray.yaml | 2 + main.py | 39 ++++ static/icons/cloud.png | Bin 0 -> 38038 bytes static/icons/steam-svgrepo-com.svg | 16 ++ static/icons/telegram-logo-svgrepo-com.svg | 2 + static/icons/vpn.png | Bin 0 -> 7794 bytes static/index.html | 196 ++++++++++++++++++ test.py | 104 ++++++++++ utils/__pycache__/config.cpython-311.pyc | Bin 0 -> 2334 bytes .../__pycache__/windows_toast.cpython-311.pyc | Bin 0 -> 2428 bytes utils/config.py | 41 ++++ utils/windows_toast.py | 45 ++++ 28 files changed, 919 insertions(+) create mode 100644 __pycache__/callback.cpython-311.pyc create mode 100644 callback.py create mode 100644 callbacks/__pycache__/example.cpython-311.pyc create mode 100644 callbacks/__pycache__/lock.cpython-311.pyc create mode 100644 callbacks/__pycache__/media.cpython-311.pyc create mode 100644 callbacks/__pycache__/screen.cpython-311.pyc create mode 100644 callbacks/__pycache__/system.cpython-311.pyc create mode 100644 callbacks/__pycache__/v2ray.cpython-311.pyc create mode 100644 callbacks/__pycache__/web.cpython-311.pyc create mode 100644 callbacks/example.py create mode 100644 callbacks/lock.py create mode 100644 callbacks/media.py create mode 100644 callbacks/screen.py create mode 100644 callbacks/system.py create mode 100644 callbacks/v2ray.py create mode 100644 callbacks/web.py create mode 100644 config/v2ray.yaml create mode 100644 main.py create mode 100644 static/icons/cloud.png create mode 100644 static/icons/steam-svgrepo-com.svg create mode 100644 static/icons/telegram-logo-svgrepo-com.svg create mode 100644 static/icons/vpn.png create mode 100644 static/index.html create mode 100644 test.py create mode 100644 utils/__pycache__/config.cpython-311.pyc create mode 100644 utils/__pycache__/windows_toast.cpython-311.pyc create mode 100644 utils/config.py create mode 100644 utils/windows_toast.py diff --git a/__pycache__/callback.cpython-311.pyc b/__pycache__/callback.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..978838f30360b5a4262f7ac8efa89eb1566034f8 GIT binary patch literal 2662 zcma)8eP|R%6rcULy^r-SN$+BNF>TiPaXHXv(Z(tw*&Fh&cMW2uC3qMVumY0!3Ujl3W)7cD+nZb2JVMPX)8o3he)t?>!oaI9G*YlvgjgsTq=91 zkW3fSoU@)HJ=cRmTG<<+Ue@-UkJN$oJ<3s8YTRLaRQ4h>7ghNqONneB$pk3{kdf#( zS+OWN+Kn{tEJANNLXpeTU!n{1qRcT`O@+7Hma~jjZOah7_3DX!5mx6?d4(YMrf$%3 zY|fE&XbWdYkhw%>mW3IajbN@^smf<_v!l>R_?6;WV9)eiJb_n>XQX!I#uB8}**FL- zMaqgCR~e`1vLbbBZ_avUxw#QTe(YQeh4#Y6&v8e&k$+14AT@{%Gkeh>HS#anHDS-r z4Bxye9!n$+#NvHw<~7guR7{jap={caVVcuJ89o}7ld=|#g7VWCscE$ zcC(_S6d?h_<>W!3KP3(%Bq2j@5W-a^ol;FU9n%h(oOD=LHPv*a6*;My&ID+pte7q- zDXN1qc(~>MbV|_@@&VIZ5~C$B(hg)s)EaRn!C@sv8O?21%nkZE6fBIp4&E-(*rAw zz{(=>Ikr+Ie%e*w{lD?`cli3T-8#R-;FlDU*S(dRa82&G)6|NaS_^fJ<7>v-#@Bqc z@^ojB=Dk~~nP8(4T#euEoazGxqzAVf!R@2m{ZO+JT0gb?*O1Y+OAqZfLc5EIsd?98 zXFnKye@wf#W!v4rvWZ1_c^lB=P^s4g?K6Sk*oU~T1!!V@sn-MRjKDf_8Dh^N=l$KiALTt8ib&llY2$ zT+mPG!+0A1q@Ti5`lo_^Ou$#+(T{LX<7sfbA>b)|178943Q;b@5PVb5gKbhjj;{#z zforx8sdc2FEkcUA83#QXQ6F|8pfRx8Sz^oRieq2A(Tngu9%Y8W8y9~ZD-|>h;t}4UXIKEbQHW^N+ z7mTB>P#YZGHMaC@GLQ5QpE z$+(;{Ic+Engn(W0mV za_6n9fU2=g1?0@^q1x9mswr{-iX8X~z8XsKZ2T9KGrkdvyAm|T*XpQn&ok(yjulA5xT=@xr# zYH@L5dg?8f#G>@#l?*Exi&%lC6obrH_@(S@6;n`Il98Vmlb@Jb5R;sklarK~oLwA~ z3NcZypz;7%mXCQ zU9akxmtT^RT7>R;h2qM*xELJWX85M&7p zNDU~wK#sFJ!E%Ay7lc@Ri$JmBr^y8NMiEFU#88kh*tlODHo5sJr8%i~MZ7>Uuun~a ej1SC=jEobS4U=eI2*fsz(j(BeX literal 0 HcmV?d00001 diff --git a/callbacks/__pycache__/lock.cpython-311.pyc b/callbacks/__pycache__/lock.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9cb454e6c40503400669020522ce8c2fcde9f78 GIT binary patch literal 1374 zcmaJ>O=uKJ6t3!?=}AVD&@n&g`cwWKYzR4+i;Qu?;1A@7+0`7x5RkUJCex;;yQ!*X zG9i)Rdf0pX zh)IMYolYd$JZ`mg8$Sj8May1Q+HhLxQ_x6v>3S25TV^pIKc{T1*8)_R~*%3v;!9C=p zL^(I-C^0<=2#J3`ssUs=oVMZoK7ENXpJm8+AtvPlDdGo|)j1VR$K}Ll@m}DXqTsU< zfh=X(jS|&?7t_Fkjhq>_U3c;LWrzb#!Y46cdqL}UTs+Y%aHFo$4g| zPo#3e3^hJYei}SEz89}X%}msD;v zFAeL3zy!Sf9*9ryte{$7DmjTi>Vx->JY3q)hc@-0clzjCeRM<5ZtB^;w5^{08p54p z+r0;?ht6;GW;c7Y)&1G6-^SkbReSPscI3Zo@9P6EKx&uU-Tl>p@z)3byRts;{{W~k zH@YV_yCb$mJNU@{|opn5O5a8Tc~R#ezwrz>d$5^q2o#X&|V#R ermmiS?A4I8*ZS71e@E7e{~WE`zm}{Yj{64wB5lk7 literal 0 HcmV?d00001 diff --git a/callbacks/__pycache__/media.cpython-311.pyc b/callbacks/__pycache__/media.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..20cd019258daf9c86fe6519a38ab3fc0b2f69d07 GIT binary patch literal 4946 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%0AO5#KvJ2cNQ69@5NX(ixM5drG23ErOVZX4 zqvpb+5i@cy8@_a|G1Sr;pKOd<&;aeGuNDlruqwvWvH$=zLp6~IFRe=2IFS&XBsr7S z4udjX<|S2Z@%ZZU1w~0K(_A#c!68G^NYZ5{Fu_Ynb5)5`2QD8eMbYOmO2^{qEU9S~ zJ0w_RDsErRX`%{o0VEAt5#yWKp(aH!17FU`o2evrl0GU+8uk%t4iX#}FNxZDVh#r^ zym=^`qrQy>esevH=)&C}3Z} z?1ejV5ms+n#%+yS!?da?kzNB{%r?`DnFbn8GrgE?<`y&cEMfu%S^j4BFjGeddm9@- zthw+po8s@p43IE;$aSc&h*j*W*Gyg9Apt%TB%~orNOE(~fL4$a3CuRj3%dma$a+>V zvu+@VT_o8JlrSZ#!Z;q%kCGC6HME#FG>Qs!2iPbOFS_-*x8y|TtKIqX}5 z%-4rdD)pkg02ay5C-osLkbl8-7u5#OIu@vJ14DY?M}N7fpE&cZyA)U|2bT1}QmN#k^BDN1@8yH*wjPg z<U~T19^2JQ-l?*8O7~8Iv3{=P^jCU%i!3M&9sAP#C-)ya zA9mJ|ogFi}vb(<+y_c;7LVDo%?sfg-OgS)9T&#EkpWXb%bF}0+TIoM_kFAWHEOiYX zJa_fi5X;Uy?;kF`J*D^mxVTjH`R||Hp~}8t-8Wovzu~S1I6d&rzP%J6w)MbF>C9C< z@P2WT_|MXzPRQkgf~$`fI(euJ#(LcWnE?cLC(? z1wWv|TKj5eZ|TVVKj8Im1LQhbHo}BH4!82$3{Av1`FEl?vKbvp>9buItU_|L7-3aN( zPfg5dxeOdu3i(Gv{sbXqoOEP`{29H39w~FseeZlPl@_u|@r)9MAvu!N-$Dl-Qd9+X z-ZicY>bPrMErjc?aaB-%=}mXdeubhIsGX@@dUtu(`S45)8H_z)|I`zD|J}dJ4aN_6 JDf8gb{{Tz0(xU(X literal 0 HcmV?d00001 diff --git a/callbacks/__pycache__/v2ray.cpython-311.pyc b/callbacks/__pycache__/v2ray.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d605c625c38e1286a07469067a3488b1db8421e GIT binary patch literal 8385 zcmeHMX>1$E6`tKC#hVlli8?HqvSnG66#1?lB~9v3kz>2CTgz|~!T`Z&R~8kTWM`L= ztxBnUBoP`T5dr}Y8oO45!bfAEZV(4*f?Sq=_(y;23JaK6z<|*rX!DPTZNTu4qHmVh zE=kEQnidGqaGKELx3E+vXP-=VmNka zNNZ4`cXxZC^fclS8TByDT3F^J6=qliXfY5w!bY|RXpO4f#F{~`RjEC&5l4@14*C3wXnZ8e3w;~cZ`i6BqwL{WVo3Y$h-UIu@BUQPJV8yM2ynS; zf`(l2O-wM5D_9C62D##VP;Ev$E#*{`ZC z;?W6a&Rnold)N2i1k$u*m@rgdU9eVQ1WGG-38}Jm4x^)bD572Pmuz4w)~W@pAU}OS zPtYaXU=3Ra^{rU7{r&)*rS&#a=&@S04WiX(1Jdf^4P*2X=4CWSQRrou3!vLTq=bf2 zAKDT2O&W#fQVDC<>pu?fXwvw)af}*6xz>V?^s^u@&PXSu4l-{M8K}J)0KqRoh-9yfTh~QXG4KP2Vu>JKT36tV45NH9vFE!R zphPjSQ6Y*Qz>Yf)Y}^OVBoIvtBZ0lU_ousw6~C3Hq3u5r-2qU)gh}FjUtnN-#XvL` z=h%RdR2$(E0`Y)cKwYOnr(%l6lEgnLj!--XwSzeifSsVIZ22pO6!9N5ybu-AJO-Q@4%T27ku{TEMAA5}*oH925>ujaUNK{i zPbCxJlY4h!d6=%TP0LdB|zcq`1Oxv;67;l&O4-?1KjnmX~^P--Bu!;Z<2Q zt_zYzcID zbgMA7d2}f1s)7zC6&;AP%U^kPa2N7mk5fMifDWcIba16tg1q=1c;wHecQoE#{7RZ4 z{$DyK&fgb^%vrz$@nh-j98>@*05Xt*H$d!@-hg-x?w^WR2#Sb*mW}~@Ts;Y+T(3KQukZMKOm1muST_0vlou=REr! zTnFZ+yNJ!_N}UJ*+8hJhuL1;pA$|#_X#1Qde*Uj#-Uz6$6-eRak)zPCQHTj~PB9$@ zY>6J?_NTXyR&^*w#tHCK*BW3Pfz*=nzQA~W3C_4g^p!Z5QxdeOAcR*y!#UJa@r!@~ zZX$%tFWf>%E09ZhL}CDpFzKQSJ-Cf4&r{Q; zjLSW3$QtZ=eDYp7^mV_AP&;M+&MYz!gj$Z=cu9v)D#8p%z8$h}hv?gJtEpSuG9dnZ zQtWvhlGOAox#?G;uSz0VWYHne3vX&nfM;y%yN)~*MQUj?f{C{64D7ou_RL*R?z{X075c_ z$q7A=2R*O$5d5_;(apus~?<7t9X<{@4q1VcFMk;qHm|__jdp!4N}`_xIOV)o&sVuhX`T;h4Q+`qu)0; zaN_=h@_s-D4wB>>mVLvbZ}^7^4x1#;X4$h@v~R8ehfi0BTG2O+n?p9{n!^qJwLk;m zw-J89W)0Pu7U~$nH&BFcRQXnG=xJu5(-qpvENnFbuLB2|o4F`i7?{eF3U1S$H|799 zDzA#@6IF2CaFT(Ts~UHu(`1t+o`#+3XVR4PHi?svD9AC`F&-nkU~zsAgg%IWQ;b9L zB+msYH9Ei(ow@TqCXQjezGBI#;!&vM2Y}?x_qT1XQ%`3RWm%i?)X(*PwzaD9myp`78oj_InxPUR&9gwJioYyvG_J@ZJ#p3>;b2=N>x-OPR-R>y z(347%Gl1yU%>&ZS6Y#(LF^qR*w6y$;3a2?#c*_tIrK-;i_$mOcm12ze?2?j9ndG!k zjI6>*%dq5gWg3>0D{KF zQ_DR=BK5irOTLA$??|s@$s21$qD2xr4tscyZO`wSQdqhjsIvQddas3Vpp_YS|^X?2;V2WykI*Yld;m49>nJ zGA)oY2GhwG-r9S7@60aAuu?Xx6b&n3gsF`p+MrDt)Gq2%wq}r`U}I37-cif%X=_L6 RS|VR0tBPEyjBx6p{0n`u14;k@ literal 0 HcmV?d00001 diff --git a/callbacks/__pycache__/web.cpython-311.pyc b/callbacks/__pycache__/web.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae2c7edcef0eb7d939fb7b18a4ec46fefd6b8a64 GIT binary patch literal 1663 zcmaJ>&1)M+6ra(ozP7gIDt02fPBM)Hsfvjyp>|PRJ9a)Gv^Zc>hZ;jz@2;#(rCl*I z8%3&YLK2D_3h6C|B;Zrpk`!EMA@u0KKmr}af}zk$dlQ(H;8WkMBwJ2OXGc%(?Y@uS z`@Nn0p}Si}u&(?*k`W3*e@dghLM>%?0hC9`KnBjD#pXX=#9#-qfgD*RIb~77$RH*$ zgQk)W474*KLwWmNS}}t6mBo;O=TS2BxAdJ&20Z1Gr3;Tt+eJ^&*b4VT%oHxOb-bSq zp)lz8;J2HByPqKpu%f7pHalDnR0BT)ujl*mtGJALOpp$bz+sQO;ISDvcz&Q6ylHc)(So_mEn!m2rXpif!%S;#R?ubU6u8N#W7F%FZGdrB z_2Z^tqA6dKS>$|ER1Vy7Y>gGE?$|=JY|CDuXIz#&LqFhxft93A+Aq+qCmiYkgjUu$ z{|)I#+>x?ii45gJ6E3GYlXGpwq?&C2;=C&)0yk&cqK$7(v$)xj=-T{c#vGQSSJQq$ ziA*-y#*x;nEX2xYJOYSILto5&PIE2?4osS7&MnI@Wih|kWS|tz2$4^Xj_yUI!a-wE z7|U#F@Cu{?*H&kpRZ5ZTEt*SxJ_>N-uC7BjX*ZiK!l?Oh+$r2DFJL3O<_zSK(s4>_dynz4ci9gId$b9d9>wM>|lX@)PKsfs8PJF0x z{CqV&QHxJhx+WSS)O+ON+Jm*qiI1zXv07|QdJWg(LmRvrKec}GRR|5xS|a)Lhc8B7 zo~tINYKf^z{LQ@{uE&nb$WM0S1C_zCYJ9vFAFp(cL;l3X=5XcM`R1~s zaI@wl8v;{)7Wpj@P!Z!g>bc`zb@Xnfz3XVG@?X25oWd9IM&E|Md2S=~#EaRc{r{4^2c`c7T<@zu literal 0 HcmV?d00001 diff --git a/callbacks/example.py b/callbacks/example.py new file mode 100644 index 0000000..4d1c0f9 --- /dev/null +++ b/callbacks/example.py @@ -0,0 +1,5 @@ +async def example_action(args): + return {"message": "Example action executed", "args": args} + +def another_action(args): + return {"message": "Another action executed synchronously", "args": args} \ No newline at end of file diff --git a/callbacks/lock.py b/callbacks/lock.py new file mode 100644 index 0000000..6a3b534 --- /dev/null +++ b/callbacks/lock.py @@ -0,0 +1,21 @@ +import ctypes +from typing import Dict, Any + +async def lock_computer(args: Dict[str, Any]) -> Dict[str, Any]: + """ + Locks the Windows computer screen using the LockWorkStation API. + Args: + args: Dictionary of arguments (not used in this implementation). + Returns: + Dictionary with status message and input arguments. + Raises: + OSError: If the lock operation fails or the platform is not Windows. + """ + try: + # Use Windows API to lock the screen + result = ctypes.WinDLL('user32.dll').LockWorkStation() + if not result: + raise OSError("Failed to lock the Windows screen") + return {"message": "Windows screen locked successfully", "args": args} + except Exception as e: + raise OSError(f"Error while locking the Windows screen: {str(e)}") \ No newline at end of file diff --git a/callbacks/media.py b/callbacks/media.py new file mode 100644 index 0000000..dc82a24 --- /dev/null +++ b/callbacks/media.py @@ -0,0 +1,109 @@ +import sys +import os +import asyncio +import comtypes +import ctypes +from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume +from ctypes import cast, POINTER +from typing import Dict, Any + +from winrt.windows.media.control import GlobalSystemMediaTransportControlsSessionManager as MediaManager + + +# Добавляем родительскую директорию в sys.path +parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +if parent_dir not in sys.path: + sys.path.append(parent_dir) + + + + +async def set_volume(args: Dict[str, Any]) -> Dict[str, Any]: + """ + Sets the Windows system volume using the Core Audio API. + + Args: + args: Dictionary containing 'level' (float from 0.0 to 1.0) for volume level. + + Returns: + Dictionary with status message and input arguments. + + Raises: + OSError: If volume setting fails or the platform is not Windows. + """ + try: + # Initialize COM + comtypes.CoInitialize() + + # Get volume level from args + level = args.get('level', 0.5) # Default to 50% if not specified + + # Validate input level + if not isinstance(level, (int, float)) or not 0.0 <= level <= 1.0: + raise ValueError("Volume level must be a float between 0.0 and 1.0") + + # Get audio endpoint interface + devices = AudioUtilities.GetSpeakers() + interface = devices.Activate(IAudioEndpointVolume._iid_, comtypes.CLSCTX_ALL, None) + volume = cast(interface, POINTER(IAudioEndpointVolume)) + + # Set volume level + volume.SetMasterVolumeLevelScalar(float(level), None) + + return { + "message": f"Volume set to {level*100:.0f}% successfully", + "args": args + } + + except Exception as e: + raise OSError(f"Error while setting volume: {str(e)}") + + finally: + # Release COM resources + comtypes.CoUninitialize() + +async def play(args): + # Получаем менеджер медиасессий + sessions = await MediaManager.request_async() + current_session = sessions.get_current_session() + + if current_session: + # Воспроизведение + await current_session.try_play_async() + else: + print("No media session is active.") + +async def pause(args): + #print(await read_config("media.yaml")) + # Получаем менеджер медиасессий + sessions = await MediaManager.request_async() + current_session = sessions.get_current_session() + + if current_session: + # пауза + await current_session.try_pause_async() + else: + print("No media session is active.") + +async def next(args): + # Получаем менеджер медиасессий + sessions = await MediaManager.request_async() + current_session = sessions.get_current_session() + + if current_session: + # вперед + await current_session.try_skip_next_async() + # await show_notification({"title":"Test","message":"test"}) + else: + print("No media session is active.") + +async def prev(args): + # Получаем менеджер медиасессий + sessions = await MediaManager.request_async() + current_session = sessions.get_current_session() + + if current_session: + # назад + await current_session.try_skip_previous_async() + else: + print("No media session is active.") \ No newline at end of file diff --git a/callbacks/screen.py b/callbacks/screen.py new file mode 100644 index 0000000..70cf0a8 --- /dev/null +++ b/callbacks/screen.py @@ -0,0 +1,28 @@ +import monitorcontrol + +def get_monitors(): + """Retrieve a list of connected monitors.""" + return monitorcontrol.get_monitors() + +def set_brightness(monitor, brightness): + """Set the brightness of a specific monitor.""" + if not 0 <= brightness <= 100: + raise ValueError("Brightness must be between 0 and 100") + with monitor: + monitor.set_luminance(brightness) + print(f"Set brightness to {brightness}%") + + +def chenge_brightness(args): + try: + level = args.get('level', 10) + monitors = get_monitors() + if not monitors: + raise OSError(f"No DDC/CI compatible monitors found.") + return + + for i, monitor in enumerate(monitors): + set_brightness(monitor, level) + + except Exception as e: + raise OSError(f"An error occurred: {e}") diff --git a/callbacks/system.py b/callbacks/system.py new file mode 100644 index 0000000..61a1bc3 --- /dev/null +++ b/callbacks/system.py @@ -0,0 +1,86 @@ +import asyncio +import psutil +import pynvml +import time +from typing import Dict, Any + +async def get_system_metrics(args: Dict[str, Any]) -> Dict[str, Any]: + """ + Retrieves system metrics including CPU usage, RAM usage, GPU usage (for NVIDIA GPUs), + system uptime, and network traffic of the primary network interface. + + Args: + args: Dictionary of arguments (not used in this implementation). + + Returns: + Dictionary with CPU usage (%), RAM used (GB), RAM total (GB), GPU usage (%), + system uptime (seconds), network traffic (Mbit/s), and input arguments. + + Raises: + OSError: If retrieving metrics fails. + """ + try: + # Get CPU usage (averaged over 0.1 seconds for responsiveness) + cpu_usage = await asyncio.to_thread(psutil.cpu_percent, interval=0.1) + + # Get RAM usage + memory = psutil.virtual_memory() + ram_used = memory.used / (1024 ** 3) # Convert bytes to GB + ram_total = memory.total / (1024 ** 3) # Convert bytes to GB + + # Get system uptime + uptime = time.time() - psutil.boot_time() # Time since system boot in seconds + + # Get network traffic for primary interface + network_traffic = 0.0 + net_io = psutil.net_io_counters(pernic=True) + primary_interface = None + max_bytes = 0 + + # Find primary network interface (with most bytes sent/received) + for interface, stats in net_io.items(): + total_bytes = stats.bytes_sent + stats.bytes_recv + if total_bytes > max_bytes: + max_bytes = total_bytes + primary_interface = interface + + if primary_interface: + # Measure traffic over 1 second + initial_stats = net_io[primary_interface] + await asyncio.sleep(1) + final_stats = psutil.net_io_counters(pernic=True)[primary_interface] + + # Calculate traffic in Mbit/s + bytes_diff = (final_stats.bytes_sent - initial_stats.bytes_sent + + final_stats.bytes_recv - initial_stats.bytes_recv) + network_traffic = (bytes_diff * 8) / (1024 ** 2) # Convert bytes to Mbit/s + + # Try to get GPU usage (NVIDIA only) + gpu_usage = 0.0 + try: + pynvml.nvmlInit() + device_count = pynvml.nvmlDeviceGetCount() + if device_count > 0: + handle = pynvml.nvmlDeviceGetHandleByIndex(0) # Use first GPU + utilization = pynvml.nvmlDeviceGetUtilizationRates(handle) + gpu_usage = utilization.gpu + pynvml.nvmlShutdown() + except pynvml.NVMLError: + gpu_usage = -1 # Indicate GPU metrics unavailable + + return { + "message": "System metrics retrieved successfully", + "metrics": { + "cpu_usage_percent": round(cpu_usage, 2), + "ram_used_gb": round(ram_used, 2), + "ram_total_gb": round(ram_total, 2), + "gpu_usage_percent": gpu_usage, + "uptime_seconds": round(uptime, 2), + "network_traffic_mbps": round(network_traffic, 2) + }, + "args": args + } + + except Exception as e: + raise OSError(f"Error while retrieving system metrics: {str(e)}") + diff --git a/callbacks/v2ray.py b/callbacks/v2ray.py new file mode 100644 index 0000000..6c00be2 --- /dev/null +++ b/callbacks/v2ray.py @@ -0,0 +1,135 @@ +import aiohttp +import sys +import os + + + +# Добавляем родительскую директорию в sys.path +parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +if parent_dir not in sys.path: + sys.path.append(parent_dir) + + +from utils.windows_toast import show_notification +from utils.config import read_config + + +class V2rayAController: + def __init__(self, host='http://localhost:2017', username='admin', password='admin'): + self.host = host + self.username = username + self.password = password + self.token = None + self.session = None + + async def authenticate(self): + """Аутентификация и получение токена""" + self.session = aiohttp.ClientSession() + auth_url = f"{self.host}/api/login" + credentials = { + 'username': self.username, + 'password': self.password + } + + try: + async with self.session.post(auth_url, json=credentials) as response: + if response.status == 200: + data = await response.json() + self.token = data.get('data').get('token') + print("V2RayA auth OK") + return True + else: + print(f"Ошибка аутентификации: {response.status}") + return False + except Exception as e: + raise OSError("Failed to authenticate v2ray") + print(f"Ошибка при аутентификации: {e}") + return False + + async def enable_proxy(self): + """Включение прокси""" + if not self.token: + print("Не выполнен вход. Пожалуйста, сначала выполните аутентификацию") + return False + + url = f"{self.host}/api/v2ray" + headers = {'Authorization': f"Bearer {self.token}"} + data = {} + + try: + async with self.session.post(url, headers=headers, json=data) as response: + if response.status == 200: + print("Прокси успешно включен") + await show_notification({"title":"✅ V2Ray proxy","message":"Прокси успешно включен"}) + return True + else: + print(f"Ошибка при включении прокси: {response.status}") + return False + except Exception as e: + raise OSError("Failed to enable proxy") + print(f"Ошибка при включении прокси: {e}") + return False + + async def disable_proxy(self): + """Выключение прокси""" + if not self.token: + print("Не выполнен вход. Пожалуйста, сначала выполните аутентификацию") + return False + + url = f"{self.host}/api/v2ray" + headers = {'Authorization': f"Bearer {self.token}"} + data = {'operation': 'stop'} + + try: + async with self.session.delete(url, headers=headers, json=data) as response: + if response.status == 200: + print("Прокси успешно выключен") + await show_notification({"title":"🔴 V2Ray proxy","message":"Прокси успешно выключен"}) + return True + else: + print(f"Ошибка при выключении прокси: {response.status}") + return False + except Exception as e: + raise OSError("Failed to disable proxy") + print(f"Ошибка при выключении прокси: {e}") + return False + + async def close(self): + """Закрытие сессии""" + if self.session: + await self.session.close() + +async def enable_vpn(args): + # Инициализация контроллера + config = await read_config("v2ray.yaml") + if config.get("username") and config.get("password"): + controller = V2rayAController( + host='http://localhost:2017', + username=config.get("username"), + password=config.get("password") + ) + # Аутентификация + if await controller.authenticate(): + await controller.enable_proxy() + + # Закрытие сессии + await controller.close() + else: + raise OSError("Config unset") +async def disable_vpn(args): + # Инициализация контроллера + config = await read_config("v2ray.yaml") + if config.get("username") and config.get("password"): + controller = V2rayAController( + host='http://localhost:2017', + username=config.get("username"), + password=config.get("password") + ) + # Аутентификация + if await controller.authenticate(): + await controller.disable_proxy() + + # Закрытие сессии + await controller.close() + else: + raise OSError("Config unset") diff --git a/callbacks/web.py b/callbacks/web.py new file mode 100644 index 0000000..63670e7 --- /dev/null +++ b/callbacks/web.py @@ -0,0 +1,39 @@ +import asyncio +import webbrowser +from typing import Dict, Any + +async def open_url(args: Dict[str, Any]) -> Dict[str, Any]: + """ + Opens a website in the default browser on Windows. + + Args: + args: Dictionary containing 'url' (string) of the website to open. + + Returns: + Dictionary with status message and input arguments. + + Raises: + OSError: If opening the website fails. + """ + try: + # Get URL from args + url = args.get('url') + if not url: + raise ValueError("URL must be provided in args") + + # Ensure URL has a scheme (http:// or https://) + if not url.startswith(('http://', 'https://')): + url = 'https://' + url + + # Open website in default browser + success = await asyncio.to_thread(webbrowser.open, url) + if not success: + raise OSError("Failed to open the website") + + return { + "message": f"Website {url} opened successfully", + "args": args + } + + except Exception as e: + raise OSError(f"Error while opening website: {str(e)}") \ No newline at end of file diff --git a/config/v2ray.yaml b/config/v2ray.yaml new file mode 100644 index 0000000..0cb0208 --- /dev/null +++ b/config/v2ray.yaml @@ -0,0 +1,2 @@ +username: admin123 +password: admin123 \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..6153638 --- /dev/null +++ b/main.py @@ -0,0 +1,39 @@ +from fastapi import FastAPI, HTTPException +from pydantic import BaseModel +from fastapi.staticfiles import StaticFiles +from fastapi.responses import HTMLResponse +from typing import Optional, Dict, Any +import json +from callback import call_action +from fastapi.responses import JSONResponse + +app = FastAPI() + +app.mount("/static", StaticFiles(directory="static"), name="static") + +class ActionArgs(BaseModel): + args: Optional[Dict[str, Any]] = None + + +@app.get("/") +async def read_index(): + with open("static/index.html", "r", encoding="utf-8") as f: + html_content = f.read() + return HTMLResponse(content=html_content, status_code=200) + +@app.post("/action/{name:path}") +async def handle_action(name: str, action_args: ActionArgs): + try: + # Вызываем функцию из callback.py, передавая имя действия и аргументы + result = await call_action(name, action_args.args or {}) + return JSONResponse(content={"status": "success", "result": result}) + except ValueError as e: + # Если функция не найдена, возвращаем 404 + raise HTTPException(status_code=404, detail=str(e)) + except Exception as e: + # Обработка остальных ошибок + raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}") + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8000) \ No newline at end of file diff --git a/static/icons/cloud.png b/static/icons/cloud.png new file mode 100644 index 0000000000000000000000000000000000000000..0029f83708f7033466b06b4d0729d922af8dd8c6 GIT binary patch literal 38038 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 bJC*+*tV9&$&9AX-00000NkvXXu0mjfiY6+C literal 0 HcmV?d00001 diff --git a/static/icons/steam-svgrepo-com.svg b/static/icons/steam-svgrepo-com.svg new file mode 100644 index 0000000..fd9d6f6 --- /dev/null +++ b/static/icons/steam-svgrepo-com.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/static/icons/telegram-logo-svgrepo-com.svg b/static/icons/telegram-logo-svgrepo-com.svg new file mode 100644 index 0000000..25999d5 --- /dev/null +++ b/static/icons/telegram-logo-svgrepo-com.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/static/icons/vpn.png b/static/icons/vpn.png new file mode 100644 index 0000000000000000000000000000000000000000..9336d45293bcb506bc5734df3097fa9cac76cf56 GIT binary patch literal 7794 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 Jt8UrF{tvSVKyd&7 literal 0 HcmV?d00001 diff --git a/static/index.html b/static/index.html new file mode 100644 index 0000000..8c72c01 --- /dev/null +++ b/static/index.html @@ -0,0 +1,196 @@ + + + + + + + Dynamic Glassmorphism Tile Panel + + + + + +
+
+
+ + + + \ No newline at end of file diff --git a/test.py b/test.py new file mode 100644 index 0000000..a71dc3e --- /dev/null +++ b/test.py @@ -0,0 +1,104 @@ +import aiohttp +import asyncio +import json + +class V2rayAController: + def __init__(self, host='http://localhost:2017', username='admin', password='admin'): + self.host = host + self.username = username + self.password = password + self.token = None + self.session = None + + async def authenticate(self): + """Аутентификация и получение токена""" + self.session = aiohttp.ClientSession() + auth_url = f"{self.host}/api/login" + credentials = { + 'username': self.username, + 'password': self.password + } + + try: + async with self.session.post(auth_url, json=credentials) as response: + if response.status == 200: + data = await response.json() + self.token = data.get('data').get('token') + print("V2RayA auth OK") + return True + else: + print(f"Ошибка аутентификации: {response.status}") + return False + except Exception as e: + print(f"Ошибка при аутентификации: {e}") + return False + + async def enable_proxy(self): + """Включение прокси""" + if not self.token: + print("Не выполнен вход. Пожалуйста, сначала выполните аутентификацию") + return False + + url = f"{self.host}/api/v2ray" + headers = {'Authorization': f"Bearer {self.token}"} + data = {} + + try: + async with self.session.post(url, headers=headers, json=data) as response: + if response.status == 200: + print("Прокси успешно включен") + return True + else: + print(f"Ошибка при включении прокси: {response.status}") + return False + except Exception as e: + print(f"Ошибка при включении прокси: {e}") + return False + + async def disable_proxy(self): + """Выключение прокси""" + if not self.token: + print("Не выполнен вход. Пожалуйста, сначала выполните аутентификацию") + return False + + url = f"{self.host}/api/v2ray" + headers = {'Authorization': f"Bearer {self.token}"} + data = {'operation': 'stop'} + + try: + async with self.session.delete(url, headers=headers, json=data) as response: + if response.status == 200: + print("Прокси успешно выключен") + return True + else: + print(f"Ошибка при выключении прокси: {response.status}") + return False + except Exception as e: + print(f"Ошибка при выключении прокси: {e}") + return False + + async def close(self): + """Закрытие сессии""" + if self.session: + await self.session.close() + +async def main(): + # Инициализация контроллера + controller = V2rayAController( + host='http://localhost:2017', + username='admin123', + password='admin123' + ) + + # Аутентификация + if await controller.authenticate(): + # Примеры использования + await controller.enable_proxy() + await asyncio.sleep(20) # Пауза для демонстрации + await controller.disable_proxy() + + # Закрытие сессии + await controller.close() + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/utils/__pycache__/config.cpython-311.pyc b/utils/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..48202f6580d18c2990a5cdd7ac57ef8d47dbab45 GIT binary patch literal 2334 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 Dict[str, Any]: + """ + Displays a system notification in the Windows system tray (bottom-right corner). + Args: + args: Dictionary containing 'title' (str), 'message' (str), and optional 'duration' (int, in seconds). + Returns: + Dictionary with status message and input arguments. + Raises: + ValueError: If required 'title' or 'message' arguments are missing. + OSError: If the notification fails to display. + """ + try: + # Check for required arguments + title = args.get('title') + message = args.get('message') + if not title or not message: + raise ValueError("Both 'title' and 'message' are required in args") + + # Optional duration (default to 5 seconds) + duration = args.get('duration', 5) + if not isinstance(duration, int) or duration < 1: + raise ValueError("'duration' must be a positive integer") + + # Initialize the notifier + toaster = ToastNotifier() + + # Show notification (run in a separate thread to avoid blocking) + await asyncio.get_event_loop().run_in_executor( + None, + lambda: toaster.show_toast( + title=title, + msg=message, + duration=duration, + threaded=True + ) + ) + + return {"message": "Notification displayed successfully", "args": args} + + except Exception as e: + raise OSError(f"Error displaying notification: {str(e)}") \ No newline at end of file