hiddifypanel 3.0.0.dev64__cp39-cp39-manylinux2014_x86_64.whl → 3.0.0.dev65__cp39-cp39-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hiddifypanel/Events.py +27 -4
- hiddifypanel/VERSION +1 -1
- hiddifypanel/VERSION.py +1 -3
- hiddifypanel/__init__.py +7 -3
- hiddifypanel/__main__.py +13 -3
- hiddifypanel/base.py +88 -3
- hiddifypanel/base2.py +40 -3
- hiddifypanel/models/__init__.py +10 -3
- hiddifypanel/models/child.py +26 -4
- hiddifypanel/models/config.py +105 -4
- hiddifypanel/models/config_enum.py +207 -4
- hiddifypanel/models/domain.py +106 -4
- hiddifypanel/models/proxy.py +55 -3
- hiddifypanel/models/usage.py +58 -3
- hiddifypanel/models/user.py +171 -3
- hiddifypanel/panel/__init__.py +7 -4
- hiddifypanel/panel/admin/Actions.py +170 -3
- hiddifypanel/panel/admin/Backup.py +80 -4
- hiddifypanel/panel/admin/ChildAdmin.py +122 -3
- hiddifypanel/panel/admin/ConfigAdmin.py +54 -4
- hiddifypanel/panel/admin/Dashboard.py +70 -4
- hiddifypanel/panel/admin/DomainAdmin.py +195 -4
- hiddifypanel/panel/admin/ProxyAdmin.py +128 -3
- hiddifypanel/panel/admin/QuickSetup.py +127 -4
- hiddifypanel/panel/admin/SettingAdmin.py +224 -3
- hiddifypanel/panel/admin/Terminal.py +51 -4
- hiddifypanel/panel/admin/UserAdmin.py +277 -4
- hiddifypanel/panel/admin/__init__.py +82 -4
- hiddifypanel/panel/admin/adminlte.py +13 -4
- hiddifypanel/panel/admin/commercial_info.py +23 -3
- hiddifypanel/panel/admin/websocket.py +9 -3
- hiddifypanel/panel/admin_2.py +33 -3
- hiddifypanel/panel/asset.py +17 -3
- hiddifypanel/panel/cf_api.py +35 -4
- hiddifypanel/panel/clean_ip.py +125 -3
- hiddifypanel/panel/cli.py +172 -3
- hiddifypanel/panel/commercial/CommercialDashboard.py +59 -4
- hiddifypanel/panel/commercial/CommercialSettings.py +224 -3
- hiddifypanel/panel/commercial/ProxyDetailsAdmin.py +38 -4
- hiddifypanel/panel/commercial/__init__.py +50 -4
- hiddifypanel/panel/commercial/restapi/__init__.py +14 -3
- hiddifypanel/panel/commercial/restapi/tgbot.py +57 -3
- hiddifypanel/panel/commercial/telegrambot/DefaultResponse.py +11 -3
- hiddifypanel/panel/commercial/telegrambot/Usage.py +71 -3
- hiddifypanel/panel/commercial/telegrambot/__init__.py +6 -4
- hiddifypanel/panel/commercial/telegrambot/admin.py +120 -3
- hiddifypanel/panel/commercial/telegrambot/information.py +123 -3
- hiddifypanel/panel/common.py +98 -3
- hiddifypanel/panel/custom_widgets.py +71 -4
- hiddifypanel/panel/database.py +18 -3
- hiddifypanel/panel/hiddify.py +655 -4
- hiddifypanel/panel/hiddify_api.py +70 -3
- hiddifypanel/panel/init_db.py +393 -3
- hiddifypanel/panel/usage.py +85 -3
- hiddifypanel/panel/user/__init__.py +25 -4
- hiddifypanel/panel/user/link_maker.py +416 -3
- hiddifypanel/panel/user/templates/home/multi.html +1 -1
- hiddifypanel/panel/user/user.py +233 -3
- hiddifypanel/static/css/custom.css +6 -0
- hiddifypanel/templates/500.html +1 -1
- hiddifypanel/xray_api.py +109 -3
- {hiddifypanel-3.0.0.dev64.dist-info → hiddifypanel-3.0.0.dev65.dist-info}/METADATA +1 -1
- {hiddifypanel-3.0.0.dev64.dist-info → hiddifypanel-3.0.0.dev65.dist-info}/RECORD +67 -69
- hiddifypanel-3.0.0.dev65.dist-info/top_level.txt +1 -0
- hiddifypanel-3.0.0.dev64.dist-info/top_level.txt +0 -2
- pyarmor_runtime_000000/__init__.py +0 -4
- pyarmor_runtime_000000/pyarmor_runtime.so +0 -0
- {hiddifypanel-3.0.0.dev64.dist-info → hiddifypanel-3.0.0.dev65.dist-info}/LICENSE +0 -0
- {hiddifypanel-3.0.0.dev64.dist-info → hiddifypanel-3.0.0.dev65.dist-info}/WHEEL +0 -0
- {hiddifypanel-3.0.0.dev64.dist-info → hiddifypanel-3.0.0.dev65.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,278 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
__pyarmor__(__name__, __file__, b'PY000000\x00\x03\t\x00a\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00\xc81\x00\x00\x12\t\x04\x00B\xaao\xa3\x88\xf7\xfb\xde$\x8e\x1a2\xd0L\xcd\xf2\x00\x00\x00\x00\x00\x00\x00\x00\xda\xac\x8fR9\x8f\xfe\xfc\xfc\x16h0\x8f\x0b\x9a\xba]\x9c\xf2p8\x9e\xfc\xe6\x9a\x84\x81T\x89[\xeb\x8e\xbb]1|SU\x10#\xdbn\xa9\x05\xe8\xb0m \x8f\xa8\xf3\n\xa0l\xc0l\xdd\x1e\xe0l\xa2>N3\xb4s\x82eO\xdf\rG\x84\xbc\t\x99L\x93S\x12\x98 |\x96}4\x08\xf5\xe3\x1cdm\xf6\xd2U\xde\x87\x83\xb9E\x9c\xaa#C\'68\x06\xb7^J\x93JYiv_^L~\xdc\xabt\x10\xd5\x14?Z\xb1\xda\x17/o$\xc3\xc3\xcbuq\xc0>J\xa2]\xcf\xdb]\xcd\xd6\xc4COu\x8d\t+Iw\xd9\t\xff/7"\x9aMq\xe32\x7f>\xf4\x8e\xa5r&\x8aE\xb0\xd0BsZ\x00\xbe\xb5\x10\xe4\x17\xe4\xc5\xacO\xaa\xde\x0f\xe16\xd0\xcb02b*\x1f\xec\xa6q\x1f\x1f\x85V\x00\x1ck\xf0\x16|~\xaf\xa9\xfdU\xe4U\x01\\\xb3\x9d\xeb\x85\xb8@\x98\xf4i]\xddfFu\xe4\x7fJ}\x84\x0c\x7f\xe2\x0e+F\xdd\xea\\\xe9\xe8u:\x91\x898\xd8\xd2\xd4\xfdTa\xd4&t\xb4\xcaA\xeb\xcf7\x1fN\nK\xdd\xa4\xf9\xb0i6\xe0\x12\xa5\x1c\xb8\x91ntc\x9ft\xbb\xc5n\xbc\x0e\r\x8fE\xcd+\x04"8\xach\xfa\xc6^\xe64\xb8\x88I2\x12\x1c\xc5~gHY\x85\xd7\xe9K\x9e\x98\x9f\x93<t\xd9\xddC\xfc\xcf\xcd_\xd4\xa8v\xa2\x95\xc9\x01\x9c\t5\rQ\x81Q@\r8\xa6\x06h\xc5\xad\xfd*\x86\x01\t\x1f4\x81\x13Y\xee?(8\xef\xa7\x86\xc7\x18\xea\xd2\xa9K\\\xa0\xd1\x99\xd6\xe8\xa4E\n6"\xc2^\x15\xfe\x1a\xf3\xda\xcb\xcf|\xbc \xea\xe9\xba\x1a\xffb\x9a}@\x18\xa6[\x8dI\x01v\x9a#c4Q\x17\x12\xcd\x085\x12u\x13\xe0s\xeb\x13\x97\x81v\xc7\xc3\xa5\xbe.\xec\x86.&w=\xc9\xdf\x14\\\xfe\xfa\xca5\xe6m\x1a\x13N\xe5\xc1\x96\tMC\x0f(9\x8ct\xa8\xd1\x13\x9d\xb4K\xccb\xa3K\xcd\x1b\xcc;\xcd\xd8\x96D\xd9\x1a\xd3\x97rB1\xf4b\xc2e\x9a\xd3j\xf8\xf3A\xa5\x96\xf8\xc2\xba\xfd\xde{\x80\x15\xf1\xef\xab\xa8"/h\x12[\x02\xcaw\x8c-,\xe1\xf6k\xeb\xab:\x05\xf8\x05Q{x\xb9\x1d\xd3\x87\xedw\xb3Wh\x075\xa7\xee\xe1\x11\xec?Ke\x01(\xee\xa1\x03\xe7\x85\xdc*\xba\xbb@\x17Z\xcd1-6\x8a=m\xfa\x06\xe9\x93\xc2\xf8;\xe3\xaf=\xa5\xedh\x86.]\xaen\xb5>\xcc-o"\xa4-,\xf0U\xad\xfa\x08\xed\xdd\xee\x88<\xddx<\xddx\xd9\t~\xba\xac\xca\xff*&\xe7\xfb\xb3J\x14\x7f\xa5\x9b\x9b\xe4\'\xcc\xae]\xea\x14^`s\xc4\xdf\xc8\xce\xa5\x10[[\x95\xaah\xe8\xdb\xc9B\xf7P\x80:\xa2>w)Pn\xaf\xe1\xb7\x8e6\xde\xe4zP\xb45\x076\xb0\xcc\xd7\xe9\xc1\xae\x12L\xd6\x0b\xe6\xd83\x99\xe2d\x96\xbe\x7fz\x05pl\xf5\xe85\'O\x01\x1f\x04\xe1n\xb4\x91\xb2\x0cg"\x92;\x9d\xb11\xba\xf0\xef~\x17o\xa4\xda\x15m\xe0\x03\xa4\x02g\x00\xc2\xf7e\xfa<i\x86\x94\xc8\xf9\x9c\x9b\x88v\x8b\x86\x90I\xe0s\x08\x7f\x05n\xf9\xc4i\xae*\xdfJ\xa8\xf2\xf7.)\xca\xdb0t%\x0c%\'\x80\x13\xe1\xa4\x1f\x01\xb8\xd9$0\x9e\xf7d\xee~\xe0\xaf\xb5J\xdc-\xdd\xb7\xfd\xcc\x80\x0c@0e\xa4\xff\xb9y\xdc\xb5"\x8fLm7E\x18dM\x10\xcc\xe4\xde~\xda\xaf\xbd\xc3\xbfYq\x82p\xde\xf2\x87\n\xf4\xd6X5]\xcc$$\x16\x88p{\xc2"X>\xd5>\xd2\xfd\x8c\x80\xa7\xe8\xe4\xf5E\x91\xe3\t\x14\n\xc2h\xeb\xf6.\x8f\\\x05\xd3\xb0\xe3 \x0bn\xda\xc91Y\xbb\xf6\xf3\x130Y\x94\xbaf\x1cF|\xe3~\xa1\x89\x8b\xe2b\x05\r\xad\x12\x9d,J\xcf\xb4M\xe6\x1e\x8bxN\x824\x020\xa9\xe2\x94$\xe5\x92\xfc8\xb9\x05*Hh*qs\xdet\xa7\xc7\'\xed\xb7\x89C3\xc0pa\x84\xe7\xff\xc4\xa0\xa0\x08R\x87\xd9\r\xd9\xcf\x1d\x19\xaa\xb1\xee\xa4|_\xbf\x9c1\x8b\xfa\xe11\xe17\x8b\xa0\xbe\xa2zi\xbfUN\xc9\xedDm\nlVq\x90:\xb7\xf7/ d\x1cH\x1e5i\xb9\xc1`3\xe7\x80O\x0f\xb5\xc2\\c\xb8f\xfeF\x9e#\\\xca\xae6sv\xff\xc7bJ\x1a\xd1\x8d\xb2\xde\x15\x1a\xadB\xefI\xdc\xba\xd3\xf4\xc1rh\xbf\xae\x86\xa3\xc7`\nx\xe1\xf1&\x94\xff\xf8\xa6l\xe6\x01\r\x83%\x19Z,\xae\xfd\xdd\x1b\xeb\xcf\xd7(\x9cfI\xba\xd3\x9f\xb1I\xa6\xa3\x15\x02\x15+\xf5z\xda\xff_\xac\xb4\xe0\xfa%Q8\x032\xed\xc6Y\xc79\x86\xf6\xf7$\xbb\xdf\xff\x7fkZI)*d\xacA\x1cl\xf6\x8f\xa5\x0cN\xb0\xc57\x99ALBN\xd2\xf4au\x94u\x86\x1f.\x9e\xdbj\xa3\xa6v^\xf3{!\xc3\xa3\x97\x16z}\xe5\xb1\x07q\xe3l\xa4\xf3et\x90\x18|+\xb8\xbe\x1f\x0b\xc2};\x90\x81\xab\xd5\xf6C\x17e\x05\xc4\x17\x13Gf\xa2/\xa7T\x7fl\xb1upAG\x87\x9e\xe4rOh\xee\x98\x87\xb3\x8f\xeaGM\xaf\xc8F$l\xbfEYQ`\xe2\xe6%\xde\xcf\'\xd9\xd6\x9a\xc5\x86RKYN\xef\xc2\xb1\x8a\x1e\xe5$C\x9e\xa3!}\x04\xb2\x05\x88\x84S\xc7X\x95\x15\xd9\xe1:4\xec\x19/\xbdoy\xf20X*\xdc\x02\xd9z\x85<\x13\xca\xc1\xc1\xc4]\xc5\xf6\xce\xaa%\x02\x14\x92pAl\x89\xc9\xb9?\xcfx\xc8\t\x84\xd2\xe7?\xf6NP\xb1\x92\xc7C\x1c\xcax\xda\xd8\x18\xeb\r\x91\xc6\xf0i\xb2t\xd8\xad-\x88=\x8e(Z=vAD\xa4\xa6\xdf\xf1\xc4\x1bf\x9a\x18\xa6-\xb3u\x03\xa9-r\xee*\x96D=}\x17G\xb3.\xda\xbb[\x91\x14"f\\>\xd0G\xd3\xdd\xb9\xdb\x0bU\xe8\xa4\x1c\xc6aNI\xf7L\xfc\x82\rm\x99\xa4\x08\x96\x0c\xc0\xdd\x86\xcf*\xf6\x8a\xcfi,\xa8/\xf9cRC\xa0\x93p\xcca(Gb\xd1\x9e\xc7\x18!;h\x96\x816\x07\xd1d\x98\x19[w\xd3\xc1\x13A\x10\xae^\x07\xff\xa8\xbc\xff\xfd-Y\x94\x97Z\x85\xaaC\x96D@b\xba\xf2Mu5K\xd0\x0f>\x8fz\'F)\xf8\xe2\xba\x8a_\x13\x10\x86\xa4\x13\xfc\xa9\xd5R-\x81\xa2\xbe*\x98\xc4#\xdc3\xc4;\x80\xa2\x05j\x93\xe0=nI\xa7\x0b\x1b\xc77\x82\xcd\xd9\xfc44G\x10\x1e\x8b\xe4^)\xd7\xfc.Xe~A\x8e"\xa7\xebE\xa2\x95\x01Q\x0e"\xd0\xa7\xb1nd\x87\x93\xd3\x07d~\xa0\x95\nO\x84\xe7\xfb\xbe\xe2\x90\x84\xa0\xb4\xd3!\xf1\xf1\x87E\xfb\xa1\xf7\r\x1d\x82\x95?\xffq\xeb\x9f8:\x9d\xf2y\xed\xeb\xd3\xa0\x80\xed\xc5\x9c\xa4bV*\xf5\xf4\xea\xf3\xca\x817|\xa2h\xd1KUn\xa5Mw\xf7\x04\xc3\xa0\x8c\xcf@;\xeeE:\xf1p\xb2\x19aYv\x8c\xc8\xcd\xc5\xcb\xa0\xb4Z\xd1\xf1\xfe\xb1\xf5;N\x92\xc4\x15zt)\xf5\x9a\xa5]P\xfc\xe8\xee\x9a\x08\x02\x98\xef\x9e0\xa2\x9dR]}N1\xe6\x96\xb6\xde\x04\x15\xdf\xa7;qx<.fD\xd2\xa1\xec\x81\xf4u_\xa5u\x0c3z\x13\xad\x9c\xfc~\xb6\x05%\xabW\xc3\x15B\x8b*\xb6+k\x13\xcd-\x94\xd0`~\x9e\x80M\x04_\xe3]\xd6\x16\xad\x9f\xbf\x9a\xcfxh\xd1\xbfz>\x07\x80\r\xda\xc5\x8c\xd4\x0b\x12\x14"QO.\x12D\xbfq6\xff\x87Vh|\x80C\xe0\x1f\xf1\xe1N\x97\xe7\xc9\xe4\xdf\x06\xf7\xa2yg\xf8a\x1e\xa5\xab\xb6i\xa2\xef3\xaew\xad6\xf9\x98\x9f\x05\xc4W"\xba-%\x1a\xb7Gym\x88DVv\xdf\xd1\xc9<\xb4\x917\xafm\xf2\x84k\xe1\x9e ZA\x1cx\x11\x95?\xe5\xe9y<\x1fF\x91\xaa\xea\xf2f\x1dNz\x01\xfd\x00\xed+S\xb3YSN6\x83\x80\xce#\xcb\x9ei\x0b\xf5W\xc22\xd7+\xd2|\x98FjQ\xaf\xce\xc3i\x89\xfe\xa2\xd2\x804j\xc6\x04|Uk\x9d\x84j\xf5\x94wm\xa0EzU\xbd\xe6t\x0cnMe\xe0\x84\xa3z\xae\x8d\xb5\xfe:7k\xff\xcd\x90;\xb7D\xebi\x06 5~\xb5C\xdd\x87Q\x1e_vo\x82\xb1h\xfcL\xe8_\xcf\x8d\xa2\xac\xb3E\xea\xe1\xff\x06\xc8\x9f\x88\xbf\xca\xa2y\xc8\xa5\x87\x93\xc8\xfe\xedc\xf1|6b\x1c>dICU\xd9\x12\xce\xab\xea\xa7/\xe4\x85\x90\xf9H\x98$\x8dw\x9e\xefp$\xab\x94\\H\xc4\x94\xcd\xacJs\x9dF\xa1\xfc\x92\x8f\t\x15\xe8_l\xbe\xd9E\t\x8e\xce\x86\x9c\xf8i\x98P\x89\x8a\xcb\x97?\xa9\xe6\x90\xc9k\xaaWk\xbc\x9a\n\xd4\x11\xbbD\xe3\xda\x95\xa2,yvn\xfd\x189\xa0\x00\xf1hn{\xa9\xedtTP\xa8\x94\xed\xb8\xa2\x9bf\xe2{.\xee9\x19\xf6\xb9\x0f\xbf\x8a\xaa{\x95\x18\x9e/\x07\xf7v\xb6\x11n\xf8\x9c\xe1~!\x7f\x8bE\x08$\xef\xa7\xd4\xaa\x84\xeb\x0c\xfbP:6\x0fK\x06C"\xff\xdd5\x14\x18\xe2\xfe`\xbdC\x8aa!\xe2\x94\x92M\xed\x1al\xfc\x91\xa7=\x9f\x9b\xe2\xe9\x9d\x99\x18t\x9d@\xe7$d\xf8|\x02\xea\xdc\xeb5\xf1<\x97n\x10\x8e\xed\xa8*\xdcAq\x14\xcd\x03~\xd7\x95\x88\x92\xae\xa9\x97\x8f\r^\xda\x8d\xab8hH\xc1\x89\xdd{\xb3\xf39E\xdcj\x12\x7f\xbd\x8e\xe6\x0f\x99\xe8\xfd\xdc!\xbc\x84A=\xf8\x9c\'(H\xf8;\xd1F}\x03\xce\n\xba\r\xc9\x8cT\x1ac\x95\x95\x89\xc4V\x7f\xfa\xd6\x8a=Nj\x9d\xc4\xd6\xcd\xf4\xe5\n\xbf\xf1\xef\xf8\xc2\xdf?\x92\xa7\x95\xbd\xe7\x13!\xfe\x1ch\xc4\xcb\x15\xd0hC\xeb\xb8\xe0x\xac)I\xac\x8a\xd2G\xf8P\x98\xda7sE"\x11t\x1b\x11e\xb4\xea\xdc1\xba\x847\xec\x83\xc3\xba\xe3wm\x96\xff\x9d8\'\x97\x9c\xb9\x7f\xf9}$\xcf\x8e\xdc<\xc8\x17\xf9o>\xb8U7\xd6\x80\xfd{\x137$/2\x87W\xe2\xc2Y\xdc1\x1b\x00\xea\xcaML\xa0Y-uI)\x19\x95\x14\x82\x0e1.\xcfM\xa7\xb0\xd8\xa0\xce\xf4\x075\xec@S\xe8\xa8\xdd\xda/\x08\x93\xfa\xd5\xd0\xe1~\x10\xee#o\xd7t\x87&s\xfd\x8f\x1a\xe67\xad\xb4J\x06\x9d\xe5\\g\xf0+2\xaauH\xb7\xea\x94m\xf5F\xb3\xdb\xf8\x90R~\x99\xd5\x02\xd1\xb1\xe7\xde\xfd}g3\x13\xcdBy\xbd\x1a\xaf\x85\xcaX\x95\x931O\x1c\xb88i/\xcck\xe5\xd1\xe2\x0bJ#}F\x1a\xfa\xce\xd3\xa0\xf7\x8ad\xf6^,k\xd7\xc4\xf7\xf1\x9b\x94\n%\xac2f\x99\x9b1\xcd\xb5)\x8e\xc8\xbcS\x04\x1d\xfb,\x926\x1f\xb8i\x96\xd1\x13\xd1\x84\xa7H\xb4\xe4D\xa0}\x05\xf3C\xb6\xfb\x88DN%\x82\xb2\x11\nsL<\x0f\xd5<"\x08AA\x98\x19-\xea\xaeB{\xc3\x9b\xff\xb0\x8b\xd8\xbf\xd0\x0e\xc4\x7f\xe3|\x14_\x814`\xb7\n%\xd0yw\x10~L\xad\x87\x88\xce\xc8\xb8.d\x15\xf3\xab\xf85z$\x8ea\xc4\x12\xfcF<\xb7\x89\xe3_\x05\x94\x9c\x05m1\xaf\xfd\x01tk\xe2V\xb9\xf0\xeeJ]\x00\\\xb1\xe6;e\xf7\x97\xdc\xea\xffI\x97\xeb3\xc8\xd1\t\xee\xbbW\xa7:\xe6K1\xcb\x15\xc3l\x93\xe9\xdd`\x99\xe3&\xf2D\x1d\xd5\x06}Z\xb2k\x8f\x9d\x84\x8a\xd1\x1f\x8b\xf1\x12E\x02\x042\x87&Sj\x0e\x02\xba\x8c\xcf*!\xe7-\x81\x0e\xe8:\xfa;%\xcdh\xcc\x08\x98\xad\x08l\x99\x90\x984\xaf\xaaI e\xb3\xceIZ\xf6\xde\x06\xe4\xda:\xc6>\x1a\x1b\xca\x84\xcf\xf0\xda\xcb\xa6jyO\xcf[\xb9r\xf0\xe2\xec*\xf6\xb4\x12\xdf\xccJ\xb1\xfc(W\xd7\x18PL\xb1v\x01\xca\x14dRO\xadaN\xd0\x80\xb1\xb6$l\x01\xbcX\xf8\xa2\xd2\xf5\'\xc9\xa46\xcfc\xcb\x9e ?]Xm\x96\x80\xe6\x11\x05m\x8d}j\xb0\xf4]h\x06p{\x8f\x87\xe1\xfc\x9bY\xbaI\xefK<+r\x94\xb1\xf0o\xa3\x00\x8a,4\x13c@c/\xc4\xa5\x12\x0fgsG6\x98\xf7t:\xb3\xa0\xc2p\\\xaaY\x8a\xae\xa6\xac\xe8B\xf9H\x9fy\x86\xdem\xf7\x16\xb2\xe7`\xcc\x90\xd7s@bs\xbf\x03\xf5\xf1/\x80\xc2\xb2n<\xadL\xe73\xcc\x05R\xcczm\x1e_\x01\xdf\xdf\x9b\x9e_\xac\x0c\xc0z\x16`h\x9d\xc8\x16\x0f\nB\xee\x07\xc0\\f%><!\xa6\x8b\x92\x8f\x7f`\xb1Iu\\\xf5\\i\xa9q\xe4."[n1\xd2\xd5\x85\xce\xc8\xf3\xdbHA\xc4\x9e\x85\xaf\xeb\x02\xbb\xb7\xa58\xeb\x87\x05D\xd5\xd2\xe9d\xcb6D"1\xe7\xa4e\x1a\x1e\xda\xbc\x99!\xb8;\x15S\xce\xda\x10\x802\x86:\x8c\xb3\xdb\xb3Y\x87t0\xde&\xf7\xfd\xbc!\x866W\xa6As\xc7`\xda\xa0\xae^\xd4[RE\x16\xb6\x98\xd3f\xe6U\xdbI\xebm\x91\xc4f\x9d\x06\xc26\x1eQ\x94\xac\xcc\xff\x98M\xc5\x1c\xeeK?\x8d\xbb\x91W\xae\x9f\xde\xf7\xb7s\xfc\xee\xd7\xbe\xf8\xd5;*y\x05\xdb\xd8\x0f\xab\xfa"\xf410\xf1(Y\x95/\xc2--\xee\x9f\x7f\x11T`\x10V\x0c\xf2\xe7\xcd\x08\xf4\x9cz\xab\xffs_\xae]\xce\x84\x98]\x00\x06\xe2\x9a\x8e\xca\x12\xfb_;\xbd\xb3I\xad\xdb\xb2\xc5G"\xaby\xf6\xda\xd8\xa4`\x8ac\xed\xff\xc1\x92\x9e\xc2\xb5\xe5\x8d]\x19\xd6\xe3\xe4\xb5U\x9bS1\xc4,\xf8\x90\xdb\x81\xeb\xb5\xed\xd5B\xf6\xdc\x1fj>[]\xac\xc5&i\x92\xef\x05RCn\xa4Li\x94C\xdd\x0c\xc57\x9e\x90$\xc9\xd1\x0elJ`E\x0b\xcc\xc7\xb4\xd3z\xd4c\xb8\xa7\xccA\x07\x9e\x1bV\xa2?\xb2E\\\x82\xf9\xbd\\]\x12\x83o\xf1@A\xa5\xdd\x13\xe6\xb3\x15\x8f\xb1\x07\xb0+\x99\xc7\xf0)\xb7 q\x98\xee\x7fr_j\xd9%\x944\xbf\x1do>!\xfb\xb2\xf4\xe0v\xf0~n)\xce\x81\xc5)\x86\xa0\xbes\xb3/-lR\xf5\x16\x03&I\x1b\xebuK6%`=\xcf\x97\x85\xbf@\xee\x99\x17H\xf1\xeeG\x90/\xb7\xc9N\x14\x83Q\xc4m\xd4\x84\x05%1)\x95:f\x1f*0pWA\xe6\xb3\xcd\x90Q$\xf8\x95\xc0\xaa\x94\xb1\xc7RA\xc0\x80\xdc\xf8\xe1\xb3"\x03F*\x82suh \x1c\xb72yAH/\xbb\x9e\x92\xba\x9f\xb4\xa5\xba\x83fm\x11\xa8\xf5\xfdC\x80\xac\x00\x01\xf5M\x8e\xa6]\x1c\xfc\xa3\xc5\xcd0\r\xd7\xb9d\xc9 \xb8\x19\x84q\xab-VJ9\xd8u\xfe\x9alQ\x90\x00\tg\x8ce\x9a\x8f4H\xee\xa8499\\\x9et\xeft\r\xc5\x1e\xf6\xfeC\xf0\xbag\xe43m!\x1cg\x98e\x9d\xd3}\x03\xb5\xd1]*\x00\x87\xf4\xa7\xc0\xfe\xd0\xcdx\x0b\xd0\xb3\xfa\xd2\xb0\xefM\x80\x1f\xf4\x9d\x9b\x0fD\xb6\xe6i\xb9\xe5\xe1\xb9\xb4\xb3\xfe\xed%\xc3\xcc\x07\x92\xa8)\xae\x1dL\x81\xd1f\xb7\x13\x00\xea"\xa1"\xab32\xbd&\x84 O\xc6\xc8ZsB]\xd8\xfb\xb0\xb3\xee\xed\x9cJ\x13-&\x07\xef\x03M\xe4\x19\xec\x0c6l*\x8b\xc1Rt\xe8&#\xb2\xe9N\x19\x96\x01,\xf5;Oj]sG\x1b\x83\x17\xf0\xcbk\x86*h\x0f,\x10jR\xf2\xe3\xbe\xe7\xcb\x00G\xa4U[\xc97\xcc\xec\x92\xf46\x90Ub}#*\x94\x88n^+E|\x06*\xf3\x9f\x80f\xf9\x8f\x9ag3\x93\xcc\xd2\xda\x8c\x00\xdfz\xc9\xbc\x8dv\xeb\xe0\xe0\xd2\x96\xe7\r\x05\x8a(\x0f\xc2;\xd3\x1e7\xa2\xec\xb4\x1d\xb2\xdc\xefFr#x\xaf\xcb{\xe7\x076Vj%\xea8\x96\x16\xa2\x17\xbdn\x8eN\xe6{`\x06U- G\xc9\x9c\x18&\xd4\xe5\x0ecE\xf7\x8d\x8eJ\xc8w\x15[\xabd7b\xde\xc0"\xdd&.\xcc\xb67$\xeb%N\xdc\x8e$\xe2\xc54\xbb\xf4\xe3\x895M\xd8\xcd\x9d4\xc5\\S\xd7\xbc\n\xeb\xd5[\xba\x1d\xae\xaa\xa8?\x02\xc5\x8e\xbf\tc\xab\xcfHg\x9bzT`\xed\xcf\xfc\xa1OQ-]\x98\xde\xc5Yn\x1f\xb9\xa8\n\xf1W\x9d\xf94\x0c\x8bp\xc5\x1e\x8d,D\xd57\xc1P#\x1f.\x0f\x83\x10\\\x82}S\xe5\xcar\xfc\xce\'\x8cTYL\x06\xa9\xa2LBx\x82^\x9624\xa7\xcc\xa0\xd1\xbc\xebi\x7f\xfb\x0c\xc0\x0e{\xda\xb1\x1f\xb7\xe2e\x0e\xe0S\xb4\xaaQ\x86\xa2\x99\x96\x9c\x94\xeb\xfe\xf4\x97,\xe9@<\x04\x9b\xbb\xd8y-\xdc\xcatz\xc6{BT\xf1\xc0Hy2\x98\n{\xb2\x8fmH%\xadv\xb4\xa7\t\xc5r\xdd \x8dj\'\xb6I\xd8\xc9\xbe\xb9jr\t\xf8\x88\x91\x87\xbd\x94\xb3\x8c*J\xab\xbb\xc9\x8f&\x8c\xde\xf3\xec\xf8K\xc9\x08\\pF\x0e>\x08\xa0\xa3{\xfb\\\xaf\xe8/?\xf0\x84L-\xfd\x1f\x13*\x11\xa7\xd7^\n\x1c\xd2\x0f\xff\xe3\xf5\xee\x8d\xe0b\xb7\xe0\xf7\x88\xbd@~)\xd0\xd4\x91\x86*v\xbf\x1d\x0f\x0f\xd0\xbac\xad\x1d\x0f\x82\xd3B\xf9\x0b=\x81](\xfde\xc8#\xb29\xf3\x7f|@\xd0k\xe4\xb9\xc6\xf4\x97\x15D\xe1\xdbZEx\xbe{\xf2\x1a\x90=\xea\xb1\xa9\xdd\xf8\xb17G{8x\xb1\x1f\x1dGJcd\x05$\x15\xe2\x85\xa7\x05$\xfb5+{fB\t\xad\xbef\x94\xbb\xc1\xd9\xdd\xef\x1d\x1b5\xcfar\x12\xc1\x90\x0b\x14Sx\xd6\xea\x87n\x1fO\xfb\x0fz\x80\xc0\x00\x8aE\x07j\xe6\xdd\xc0\x8a/y\xaco;7Q-\xaf\x0f\xe8\xcd\xb5=\xdc\xe0\xccE\xde=\xc1(\xc2I*\xbb\x87\xaf\x9eB;\xb8\xbd\x0b\xcc\xf2\xd2\xf5\njG\xc2\xc7\xbc\xa5\xb0(\x14\xdb\xbc\x87\xb7\x03\xd2|\x99\xe8V\xce\x02\xf4\xab\x92a\xb8\xa0\xc6;8\x96\x8b\xe2\xc8\xe3\\#,L\x8f|\x1e\x81y.{\xc6\xa6\x07\xf9\xd2g\xec\xc8S\xaeHE\xb2%a\xac\x08\x88\x02o\xb0"\xb1\x12V\xd6\x06v\xe4$\xa0Uh\x89@\xdb\xde\xcc\xe7C!\x04\x8f}\xe4-\x99\t\xc2\xb7\xa4\xa1\x05\xces\x06\xb5G\xbcS\x88\x93g\xdc8\xeb\xd5\xaf\xba\xdd\x02\xc4\x82\x93\xfei`c\xfb\xbd/X\x1f\xfa\xf3r&E\x0e\x99<\xabcim\x12m\'>\xca?\xb7*\xa2v@L\x94yk\xc8\x81P\x81Ren\n\xc1\x96y\xf6Y\r\x9b\x87\xae\x02m\x13\xd8\x0c\xef\xfc_\xd6\xc4\xd8D\xcf)\x14\xa5\xa2\x9c\x17\x08\x9ey\x97V\xaaC\xd5\xb6t\xeeG&\x7f\xe1@7\xe1B\xefb\x00\x1a\xf3\xcd\'\xf9\x82\x17\xc8\xa9\x10\x10pIW\x82\x11\r\xe7\x8c\x10\x84J88\x11\xae\xe7X\xf2\xfd\xda+\xb0\x18\xf1\xab\xdc\xefN\x8b\xab\x0c\xfe\xe8\x1d\xbf\xe9~\x8c\x0bi0\xba\xd7\xd0?c\x9d\x00A\x80]\xd0(\t\xdf\x9d\x89X\x07\xd5\x0b\xc0\xe8\x1a\x87\xc1\x87\xf2\x10b\xc2\x7f\xde\xda8\xf0+\x97\xcd{\xa7\xdau\xc4\x97\x9f\xa1\xf5\xc9t%\xca\x82N\xce\xe7!\x10\xbc\x87y\x93/\xe3\x8b\x86\x06\xe6\x93\x8dN\xb4\xd5\xb3\xe3\x17\xb7YSI\x12G`vE\xf9\xe7p\x87\x07\n\xa3\x94\x18\xfa\xf4\xc7\x12\xa9\xa2\xdau{\x9e\xb2\xdc\xae|\xeaI\xb6\xeb\xe1\xac\xec\xcfDa5\x8e\x84\x9b\xd0>\x83\xe5e\x9a\xda\xbf\xc5M\xb7\xd2V\xe2\x0c*\xf1\x7f.\x1dVz\xcb\xca\xb0\xdb{#\x05|l\x1fS\xad\xfb\xdb5z\xbf\xb4\xc8hy\x00<\xda\xabc\xda\xc9\xfep\xf8\xc2\x1d\xd7\xec`\xdeL\x86S!9\xe6t\x1f\x07F]\x9a\x8e\xd3\x85\xfe\xb8\xa0\x0c?k\xd7\xd2\x02\xe9\xcc\xc0{{w8!\x8c\xbb\xf1\x8d\xd3u\x89L\xda\xef\xb9\xbc-\x9e\xf5(8\xdc\x10a\x94\xc4\xe2\xc0\xe2\x8651\xb7\x9fa\xfb\x19\xa2\xc2\x86bw\xfa[\x05\xaciYM\xf0\xa1A\x99f\xcau\x94q5\xcf\xa1\xe5\xfcp\x96\x96\xc6\x9c{G\x99[\x89\xae\x16I\x06U\xa4\xcfQ\x01\xfa\xa8\xe0\x02\x95\x04O\x1e\xbaU\x8c\xd2<\x12\xde\xe5\xe2\x0f1\x88G}\x0f\xd9s\xdd\x1a\x16\x1d\xf1\xf4`\xa7+O;\xa1l\xbf\xc0q\x10~j\xf5k\xf1\x0f\n:\xbe(\x94\x85E\x98h\x87\xbb?\xfa\x90\xd7\xe37DW\x96K\xd7\xfa2\xb1\xa1\x86P\xca\x18\xbc6eLfI\\\x96\xbf\x88\x02&D\x0e\n+\x81\xad\x92\xc6\x1f\x88\xd6V\xeaOb\xc7Pk\x90MAH\xf9\xdf\x83\x03F6*\x19\xef.*\n~\x1a\xda\x8b\xd6\xef\xa5 \n\x8f\x8a\xdc\xbc[opI\xd2\xd4\x9e\x91\x1fT\xb3\xb9\xe0\xb0O\xa4x\xf2UbF\xd8\xcf\xf2\xd8\xa4\xbd\x04\xff)$\xf8\x85u\xe4\x16\xf2\xb9\xe6lj\x85\xb6=\xec9|*>\xb0\xbe\xcd[\x90a\xfc\xe5S\xe4\xa6]2\xf8\xc4\x12\xb9\xe9\x1c\x80\xeb_Fq\xfe\x12\xb5rM\x0c2l\xa7\x07\xa5\x97\x02\xaa\xd0.\xe1\xa3\xedn\xab\xbe\xbaX\xc0\xf2\xdf\xc2|\xf2\xf2\x16W\xbf\xac\xaf\xc8G\x11\xa3\xadg\xb3C\xaf->\x1e>\xa0[\xcb\x9ce\xf8\x82\xe8l\xc7\xca\x04\xd01H\x08\x95\x1fv\xc2\x06\'\xf7z;\xf8\xa8\xa2\xddOHkZBC\x886{\xac\xf5F\xe3\xa6\xf2g\xc8\xd2\x0f\x0c+Q3\xf5\xb3\xf9S\x95!!\x9e\x17\x06\x0b\xd6\x0c\xa4\xe2EB\x88X\x18\xb3D\xc7\xd0&k\'\xa1X\x9b\xb0\xb7\xcfg\xecMX\xc10\xbe\x0b;=\xf9\xbey;r\x83\x98F\x97e\xc5\x9b0(\xd9\xd7J\r\xa3+\xeb\x08\xe8Q\r\x84M\xc0t\xb43\xf8\xd5\xad\xcef\xdahG\x1c\x03\xf2\xe9x\xee\x96!^\xd1\xbf^(\xf7\x81\n7\x8co\xd1!x\xa91\xf2+%\xe5v\xe8\xe2y\x1a\xff\x80\x19\xcd\xbc}\x82\xddY\x9b\xa9\x86\xa1\x1b\x9a\x86\xc3\x06\x84\xb7\xec\x98\x9ah\xe7OQ\xe1t\x16I\xbd\xf3\x9c\x04dW\x01\xdf\x15\xc2y\x8f3\xc0\x06qm6p7m~2\x14s\xbe\xbemc\x0f\xcaIx}\xd4\x90\x1e\xf6\x0e\xe8j\xc3,\xd7Y7.\x965p\xae\xe9\xb9@X\xd4h\xfb\xf4\xe1\xc7?\xad\x82\xa6\x19\x1d\x95\xa7,\x86\x96[\xf0\x96\xfd\xa0g\xfaM\x1d@\xc2\xfc\xde\x04\xe5\xde\xd7N\x9be\x81\x00\x81\x9b\xb7 RC\xd7\x12\x14\xba\x81\xdd\x06d\xb3\xa4<\x1b>\xb2H\xb0\xba\x04\xc1\xaf\xa8\xb9\x1c\x03\x1f\xd22/\x08G\x91\x9a\xd9+\xba\x9d\x14,fA\xf6\xc5q\x9a4\x93UV\'7\xb6<t.\xf6\xe6y\xc3\x01\x0c: \xb4\x0e\xe1\xd2!\xea\xd2A\x10\xf3\xef\xec{\x19\xf6\x1a\x0c9P\x18\xd3\xe1D(Pbz\t!u\x95sr\xed\xfas\x8c\xc7a4\xe8\xe1\xb1n\xc5R"\x80\x91\xf81\x8f\t\xdf\xcf0f@g\x95\xc5\xea5\xa2\xe2\x19\xbb\xbe\xa7oh\xe1\xa9K\xca2\xa3 \xca\xbc\xb8\x1b/E,\'\x8d\xf5)\x96\x9f\x8dYM:\x12\x16\xc5\xedl\xb1\x16\x88G\xbdtz\xed\x89\x15\x95\xb2\x0f\xf6R2\x02\x97\x1b]\xd2\xd1|.(\x1a\x84GI\xd1\xe4QG3qj^\x12Z\xdez\xe7b\x8f\xc2\x1c\xb8Q\x9b\xf03M\xb6\xa3rL\xcf\xe1\xac\xa7{\xd7\xd3\x9a\x01\xf6/\x1d\x951\r\xb2V\xb9@\xf5\xc2R\xc5p43\x07;y\xb5(\xce`-\xb6\xb8\xa70\t;\xce\xfa\xe6\xfaA\xd6\xeb7\xb4\x08Q\xed\x899L\xbal\x7fP\x9f\xc3\x06)\x9eC\x18\xaa\xb0\x82h\x05&c.\xa8\xd2\xbd \ta\xb4d\xbc\xfdl\xaa)\x13\x8f\xc8\xef;O\x05)\x10\x92\xc3\xd5\x95\x1f\xd1\x827\xb5oO\x8c\x9ff\x81\xbe\xa0\x96\x9f\xe6\xa8\x90\xcb\xa5>\xfb\x0f#\x1a1\xc6]jh\t!\xde\x12\x13\xff4\xf1!\xf3N~(\x88\xc5=\xe8\x06\xf3\x81\xfcv\x17\xd5\xa9\x7f\xa5.\xfe\x97B*y\x0c\xce\x1a\x18[\x96Q\t\xa7\xf9\xc3\xdc\xf1\x9d[\x87\x89\xd8\x8a.\x1co\x8eO\xe5\xa0\xc0\xcd0\rU^t\x82n\xa1\xa8\x0f=\xde:\xf2\xf5)\xa9\x86X\xcdn\xa1\xd8\xb3pOS9B\x94GY\xfd!\xac@<}`r\x11\xdd\r\xbex\x86\xa6f\xdb\x1b6w\xcf1uA\xe4$\xb5\x01\xb6*\xe9\xc3\x07\x91\x1c_\x95oG\x8d>5\xd0\xf0.\x1e\xcd\xb7\x1b\x910\xf6\xe3\xd7\xf5\x07\xd4T\x07\x9a,\xac_\xabkR\xf4\xcdd\xb0:t\xf9H!\xa3\xa8\xf5\xf6\xda\x92\xd2\x1ay\x9eBKZ\xd9\x81\xbb\x12\xb7H\xc5V\x9a\x97w\xaa\xf1\x8d$\x14J\xba\x99\xf5:O22G\xb67r|\x00\x7f\x97WK<\x8e\x10GB?\x8d+`\x0cs\xd8PI:\xd0\xf5\xd7\xfdx\xb9\xd3\xe5\xd7\xe2\xd8\x0e\x1b\x95~\x94\xe8\x0c\xd6)\xa9\xbf\x16\xb1\xdbu\xa1n\xca\xd2\x809T\xd3\xc5kp\x8470\xe3\t`\x8a\xf9/\'\xfc,=\xb7\x91H\xc1w\xe4\xb57>\xda\xdd\x1d*[$\xe6c\x18oJ\'a8\xe8\xea\x8e\xc1\x1a\x81\xd9\xbd1b\xf4\x82\x8b\x1aZ%D\xc6N\xe52\x9b\xe6\xc1\xb4H\xeb\xd1\x92\xdb\xe7\x00\x98 Fo4~\xbd\x18B\r\t\x15\xab\xe2\x1f\x02\x87\xdb\x08\xe6U\xd2\xf2\x94\xec\xcb2`#O\xd6\xedj\x7fhg)#\xa0O\xa3\xf2\x1c\x9d\xa04yl\x16\xd6\x80?\x87\x19\x1a\xc0\x02XF!O)\x9eM PB\x0f02oeF\x86\xb5\xed\xc5\xb7\xff\x10q\x9d\xcfe\x9f\x92Q\xb1\xe3-\xc7BM\xf07VQ~A\xa3w\xed\xd4\xcc\xe1\x11S\x83FT\xf8\xeb\x82\x89y*\x0f\xe6\x81lJsj\xce\xdb\xab%\xc74\xfdK\xe3\x9a\xe40+\xdc\xd2qL\xf8]\xd5(\xa7\x03>\xd3G\x9c5\x12\xf3u{\x92<\x93$x\xca!\x1f\x14\xc9vF\xed\xcd\x0f\x96\xfb\x16\x8d@\x1aV\x90\xc2&j\x86\xb8\x9d\xbc\x932+\xed\x08\xd1v\x05Le\xb1\xcb\xdc\xec\x96\x02k;\x19\xc0\x19Z\'3\x8a\xe9\xf1\xa3Y\xfc\xcbT\xe5@\n\x8a\xd4HC\xbaN\xdf\x1a\x9bk\x82|E|\xa3\x81\x1e\xd4\x15\rHC\xbar\xdc\xe6M\xf8\xb13\xfd\x01\xa9\xfd\xc1f\xeeX;7\x8e\xa8\x00\x84\xdc\xd1\xde\xd6\x99\xee\x0b\xa4/;|J!9U\x0f\x81\xad\x86\x1c\xe5%\xd5d\x0f0*0\xaed\xd6e\x85\xe4\x0eC\xa5\xee\xc6\x02\xd3t\x99\xc87\\\x91\x10\xc6\xf6\x17SO\xfe9qo\x8c\xe4RS\x9a?\x93\xb9\x02\x93\xf1I\xed\xe86\xe7\xb8\xc0\xfdK\x9eW\xac?=\x82\xf6\xe7^\xd5Xk\xba\x9f\xcb\xc0Ju>\xcd\x02\xeb\xe4f\xa4\xff-\x11d\x7f\x85\x1a\x1bt\\b\xedP\xcf\xf1\x0e\xb7\x18\xff\xdc\x84\xb1\xbc\x8a\xaf\x191-sS\x93\xa4\x1e\x90\x1b\xc2\xfb\x1e\xae\xf1\x88\xf1\xe9`4o\xb9\xec\x01~\x14DT\xec\x06t\xc8\xb7PNA\x01\xdf\x0f\x15\x8b\n7\xe1\x82\xd2\xe7\xcd\xb3p\xc4/n\xeaoO\\\xc8\x8d\x98\xa9yCJ\xf1\x04\xa9U\xad`\x04|\x90\xd1\x06\xca-QX\x9b\xcb\x07\xaa\xc2\x80t\xce\x0bh\xbd\x02u\x11\x1c\x08:M\x06\xf6\xeb\xd3n#\xc7x\xd2\x89\x1fX\x8d\xeb.%\x16/1\xda\x86\x8d\xf0\x8eOO.X\x96\x9e\tYZ\x9a3<\xaah\x1aR\xfd\xcc\xfd\xa2\xe2\xc9 \xafn\xe2\x1eQ\x08\xe1Q\x14\xfd\xd0\x8f\xc6Z\xca\x11*\xd1\xde\xebQ9\xe6\xb0\xf1\xd7x\xbdz\x13J\x7f[\x81\xf5o\xa5\xbdbr\xe9\xaf\xff\xf0M\xdc\xe2\x13%\xe8\xb6p\x1a\x86/$\xbd.\x94\xbd\xb9\x02\xa1\x82\xfc\xccu\xaf\x0fr*\x1c\x99\x12\x85\xc3Q\xec!\xa9K\xbbP\xe1\x8d\x9b\xc1\xee\xb2\xbf~\x1bp:\xc9/a\xd9\xb3y\x07\x1f\x07\rV\xe8;x\x19D4a\xbc\xb3\x86W\xc7\xe9\xd4\xdb\x9d[\x97D-o\xf2A\x10\x85\x8d\x81o\x8c\xf9\x1c\x00\xf9\xf6\xc4\xaa{>i\x9f_\x7f%8\xa0R\x83\r\xaf\xd4\x83|\x08\xe7\xa6\r\xba\xa7\xd2T\x18W\xf5\xda\xcb\x03\xd2(\x82\x02\xcb\xb3\xcd\xfdZ\r\xce\x8c.HJ\xf1=<\xdf\x04\xa5\xe7>\x17\x9dvp\xdfi\xfa\xc0\xe1x?p\xae\x07\xa7\xbf\x99\x02\x10\xeb\x10\xc9\xa4y\x1d\xb8\xe8\xcf\xfe\xf2Z\x1a_\xacCV\x1f\xe3\x9e\xeeD\xfd\x0b\xf7\xb2\x8de%B\xdd\x8aP\xec\x1d\x08\xd9Q\x7f\xb7\xbb\xf4\x1c0\x1c4\x89I\xf8\n\xc7\x1f\xd5\n\xa0\xf5\xec\x0fn\xa1\x94F\xbb\nF\xd2\x14Z\xe3\xf6\xf6\xa9}.c3\xab\xef\x9f\xf8\xf9\x15sV\xc4\x8d\x86\x1c\xf1\xe1M\x9b2\x96\xab\x05\xbc\x84\xf9\xa9\x95\x7f\xc6=\xf1w\xb8c\x9d\xdc\x81\x91\xc3\xc5i\xde\xa0\xd5\x96\x1b\xc3c\xbb\x1e\x16\x89\xc9\x1a\x05\xbf\xc6\x91\xb3\xc5\xe7\x16T\n<\x9a\x1f\x05E\xca`\x0c|\x06X\xa9\x17\xde\xb6\xed\x193\x193\x9a\xb0\xf8\xa9\x9e\x88w(\xa9%\x0b\xaa\xc6\xf4M\xb5\xa0\x9d\xb3G\xf7\x9262\x08\x8a|\xff\xc5!x|F\xb3l\xc7\x17n\xf5\xee8\xc5\xad\x1b\xc8\xbe\xda\xe9\xf1\x85\x84jd"B82c\xdd4\x92\xd2=\xe2^\xdf\x7fX\x97\xb9`\xb0\xf7Ao\xbc\xc4\xa0\x9d]V;\x82\xa3\x86\x836-\xb4\rrG8.\x06m\xf6\x14,\xd8>\xa9\x97\x81\xd8\xebj\x14;\x198\xb8\xeb\x1c\xc7\x13\xcf\xf1\xc2\xb3\x95\xca\t\xc1r\x1e\xc6\x19/<.\xeb\x85\xe7\xed\x87\xdeO\xf2\xf0/\x849\xf9\xf9\xd5\x90[\xf9\xe7ofq\x18\x9dcb\xd3\xe4\x85\xea\xf0\xb8X12\x9a\xf5}@\xab\xc2+hX}<\xf2E^T\xc5\xc7*\x98E\'\x16r\x00&\xbb\x14\xa0\xa2\xf8\xc0\xf6#/\xd3\xd3y\x93|\xd9\x13\xb7PaN\x12\x9b\xe0\x81\x0b6\xf8\xda7\xe5;\xae\xf5\xa0\n\xb36\xea9&7\x9a\xef\x95\xd7oU_,\x9db\xbfjcrmM\xef\xa1c\x87|j\xd4D\x99}1Zi6BY \xefT4J\x11T=\xfdz\x83\x86!f\x92\x9fq\xde\xc4N\x98\xa2\xf7\x9d\xb9\xceE\xd89\x1e<\x90\x98\x14z%\xe4\xe0MH\x17\x93\xe6\x96\xd4\xb6By\xa9\x81\xf1\xdd\x86\xa9S&:5;\nD+A:\x91s\xef\xdbnNv\xb5\xb8\xbcX+\xde\x8c\xd6\x90\xcf\x06\x18\xdc\xf5M\xb0\xf5\'\xd0$@\x1c\xdaj9\x04\x8b\xb2Z\x9d\xb8wx\x99\x9b\x8b\x01d{d\xff9P\xf4]\xdcD:\xd0fP\xfa\x81o)\x9cT\x81X1\x83\x14f6~q\xb1\'\xd4d\x93Y~\xcb\x8f>U8p\x9e\xbe}\xc3\xae\xd9\xe4p\x1e\x17\xd5[cP\x01\x8d\xf3\xd7!4\xec\\\xfd\xc1\xf6\xecy\xcc\xbc\x04\rV\xc6\xacP\xcb\x94d\xd2X\x04XL\xae\x7f\x06(}\xb5&\x9f}k\xcd\x89\x01\x9e\xfa\x8a\x80\xb5\xb5\x08\xb1\xa69\xaa\xf9|9\x87\x1f\xc1=hu\xe7ZD\x03 \xf7"Z\x87\x9e\x7fY\xaf\xb3\xba\xd4\xd9Z\xac\xd9\xb7S\'\x9f\x05Y\xa3f-\xec\x17\x7f_\x80\x10\xdaRAx\x0e\xc2P\xa7\x92\xeaSo\x05\x07\xbb\xe4@\xbbKu\xf2x\x95/"x\xe5m\x9c\x98\xf2z\xdc\xd5\xf0T\n\x10\x118\xcd\xcc\x92^\xcf\x13L*m\xf9\xa1\xd8\xb8q\x16[z\xa0U/ \xbe\xf6\xcaCTy\x06\x81xA\xcf\x8d\x06F_:\xed[N\xf9\xdb\xfc?F0Z\xc4"]\xd5?\xedt:l\xe7\xf3E\x18\x15\xb3(x\x98\xd7\x99\xa7\xa0\x0c4\xbb!\xef\xfe \x05\xb0\xa9`\xec\x9b\xcb\x06\x1e<\xaa\xe2\x05s\xc1=\xaa\xe8\xad\xe4u\xeb\x83\xd9^\xa4\x84\xab8\x89_\xe0\x12+\xb7\x89C\x8a\x9cf\x04\xabL\n\xa02\xccq\x10\xc0\xdb\x06\xe5\x92\x11\xfb\'\xbe\xc3\xa7[7\x16\x9e\x99=\xdcq\xf3\xbf?\x9bwkg\xe8\xe0_\x1d\x07\x93\x91\x1c\xe7b\'\xb7\x88\xb6\xa7#\xa0ue<\xab\xe2\xeb\xa6\xa4u\xacR\xb9n\x9a\xbb\x03^eb\xb17\x145\xbf\x83a4z\xb4\x9c\x11\xd6g\xb3T.\x9eQ\xfcp\xbb\xdb\x91&c\xad8\x99D:9\x96\x1bp\x91$\x18\xabJ\x9d\xef\xadG\xe0\xfdFl\xc1\x1c\xa9I,\xaa\x1e\x89|`\xb8\x95\x82\xfb\x0ea\x8a=\xa9\x1a\xa2\x86\xd9\x13\x87\x99\rL\xa0\xc1sI\xca\xa59\xdc\xf8|]\x06&\x82\x86\xb8\xd5\xf34\x18\xa6\xa0[6\xe1\xea&\xe4\x17\xa0\xee"\xe3\x9f+\x08\xfb|`\x9eBBd\xe1X\xfc\xc0\x1d6\xa9\x14\x18\xfa\xf7\xeb\xfaw_<\xf6v\x9a\xd5\xc0\x93\t\x8dq\x0b-\xaf\x94\x91\xdc8\xb3\x83\x8b\x9c\t\x17\xe5\xb7\xa6`E\xcc\x85B\xe3\x84\xd8<\xd9p\xa4\xcfw\x96\x02\x1a\xf6\x99\xf7t\x82\x07\xd4\xb97K_\xfc\x80\xfb\x02\x11\x04\xd9\xf0\x88\xf5\xe6\x81\xc5@\xb5\xe1\xb4\x82\xd0l\x85\xfd4\x02^\x1b9\x8c\x8d\xf5\xd5\xed\xf3B\x00w\xf7\'y\xd2)Um\xcb\xe4\xfc\x880\x18[\xf7\xd1\x9eV#\x92\xf1I\xad\x89R(IB\xc4\xde\xca\x18|h\x15\xa1\xe4\x99f\xa2%\x86r\x9d\xb7\xd0L\xcb\xed\xca\x98\xc8Da\x9d\xb5\xc0<\xa8\xa3\x9c)\x01A\xf3\xc4\xe5:\x83K\xb5\xa8\xde\xa3J\xd5\x9f\x8f\x08\xcc/\xcaN\xed\x90R\xcb\xae\xc0\xa5\x84\xfa\xc0\xc7\xba`[\xa8\xbd\x86\xd8\xac\xdc\xc76"\xcc\xcd\x9e*\x193Q\xd7\x13R\x15\'\x16W[\x1b\xf9\x1a\xb0p\xb6YP\xd64\x9f\xfc\xa2K\x8eK\x8dJ\xf5\xbf\x8d\xf7\xa5\xc5\xeeL\x0b\xe8u\x91\xde\xe3{\xed\xf2A\x08\x1dm\xa3\xb3h\x92E\xf7P~\xed\xea\xd8\x85c+\xcav\xd8Y\xd8\x9a8\xe5\xe1f\xb0&\xc3\xd1-X\x8b\xc4\xd8\xe2(\x18^\xed\x94\x16\xe4\xe9\xff4\xbc<\x9a\x0fr\x91K\xacu\xdbt\x1d\x96\x8d\xbd}|\xa2\xba\xfd\xde\x81\x93\x89\xc1\x0e6a\xbb\n0\xc5\xb5\x96\xf1\xd2\xd7\x0bW\t\xf4I\xc4W-\xab\n\xcb\xd0\xe5\x9b\xa8\xd1\xee\xa6\xe5\x96z\x98\xd7\x11\xb8\x80\x91?\x80S\x17\x92!\xd20\xc7\x96\x8f\x1b\xbb\x03]:\xcc\xf3E@U\x88V\xaaS8TO\xa7\x92\xf9\x85\xf6\x04#\x82q|\xc6^)JL\x8e,}\xfd\xd9Z\xc4"\xb3\xc2iC\nS\x8eR]\xa0&) /,\x01,\x14\xa8\xde/\x8d\x06\xdf\xe4G`\x11\\}\xe4\x7f\xa9\xbf{\xa03A\xf2\xab\xfd\xca\xd2\x9c\xbe\xb3MT\x1c]\n\xb7\x82\x8f\xc1\x82\xe4\x99\x93Vo\xc7\xb1\x93i\x99\x89\x19Zc\xe1\xedn\x81;\xa6h,J\x91$\x8f\x80q$@\xc0\xeb;\x86g\xc6Sm@J]\xf0yf\\a\xfa\xb4\n\x8d\xa3\xae\x89\x81)3y\x82\x03\xae,\xc4\x88\x0bM`X\xe6l\xfapO\r.\xe8#\xfb\xd04Z3?FnW\xf7\x11@$\xd5\x7f\nk\xfb\xd2\x91\xf9dI\xf0p\xe7AY\xd9\x8e\xcc,\x8f\xd8\x90\xa1:\xd1,C\xfd\x0c\x9f\x00\xce5\x15\xfd\xf1\x08\x9f\xb4\x0e\xda\x0e\x1f\x95V\xb4\x8d\xaa\xec\xff\xc1\x0e\x8c\xf9V\x8dz\xed\xcd\xfd\x90\x84\xc5\xc0w\x83-\x02{@&\x02(\xf2\x10\xf3\xa4\x82\x8d\x15\xf7ys\xb4cI\xa4\x8a\n\x18\xe8\xd3<\xca\'C7\x17D\xce2~L\xd0\xaa\x1f\xbe\xc1\xafG\xa3\xeb\x10(\x9c0;2\xef\xffo\x9d~\xae!\xfc\xd2\xef\x9bk\x9dFq\x93{\xc6!\x96\x0b"?\x84G`\x16\x9a\xed\xb3dZ8\xf7%\xce\xab/\x1akz\xb4\xeb?\xe5\x84Y{\xb9\xc2\xf4k\x9a~\xfc\x1e\x8f\xa3l\x95\xe3\xc0\xb2\x93\xe4\x11\x0f\x15=Q\xca7\x03\x94\t\xe6):\xab\xab\xf4V)\x0c\xa2$\xe1*\x9c\xea*\xaf\x85\xcc\x8e\x7f\xad,I \xed\x8fgN\x08\xfe)<LX6\x1e,f\x96\xef7s/6y\xa8\xecW\xecl\x18\xb4\x1bu\x1a\x8d\xcf\xf6,[E\xc8\xb9\x9ej.\xbf3oa}\x87\xcfY\xcfh\x99\xa3>\xb4 ;G\xf1\xff*a\xf0\xfc8\xc5WK(9\xd6\x12\xbb\xf7\x90\x0bU\r\x85\xbfia\xf3\xba\xbb\xf2"r\x80gq\xf5\xff\x00\x16\xfem\x92T\xcf\x17h`\xa9\x83\x1aN6\xc2\xc1\x97\xdf\xd6@~\xc4\x86G\xc8Oz\x9e\x017\x8fL\x1cF\x96e;\xa4\xccu\xfes\xc3\x15O\x11\x02\x17\xc1c\x85{\xb0\xed\xc7Y\x15\xfe\x9dOM\x97\xfc&T\xbd8\x0cj+h\xab+rNt\xd7\x95v\xfa\xb8\xbb\x86\x0e2g\x85X}\x08\xc9\xa4w\x01:\xc4T\xf0\xe7\xa7\xd1\xcb\xb0\xb5\xa98u\xb0p*;\xd7\x7f*TW\xafo\xb6/\xb3\xd12\x88\xb1I\xbcR\xed\xd1Nx\x8f\xd6)\x83\xd0?n\xf3\xfd\xa6)_\xb8\x84\x81\x8c\xa4\x81\x17\x14.\xab\xf8\xb1\xfc\xa3M\x07\xad\xc2&\xae\x17\xc5lnD1$\x82\xee\x8d4|I\xed\xad?\x82\x8f\xaa\xbe\xdf\xde\x109/\x03%\xbfL\xe1\xea\x05\x93\xc1\x05\x02\xc1\xe3\x84\x1e\xbf+\xa8\xac\x1eCcrE\xb1\xeb\xc2g\x94t+\xbf\x1c\x99\x8a*\\\xe3\xae\xe8\xda\xf6\xdc\x16h\x07\xa4\xb9\xa2L\xc4b&\xeb)\xce\xd8\x12\x8fi\xd16{\x08{\xca\xac\t1{\x18\xb8(\x10\xf1\xad\xc6\xa8l\x14\x1a\xcf\xa62+\xd9DrM\x17\x05MbSh\x8d\xab\xc0@!W(\x89\xb5Q\n\xc0\x97/k}\xcd\xdfo\xe4\x97\xa9\xd2\xa2)\x9c\xe7\xc2\x04\xff\xa3\x1d\xc0aV#tz/\x08\x8c\xe19\x8a\xbe\xfdq\x8b\xe6\xd1\xf6}\xaaTn\'\xf5\x89\x934\xc9\xfb\x1b\xc1\xc2j\xd2\xd5>\x91\x95\xaaTe\xae\\\xeeH?9K\x97\xa6\xbbi\xad\x9a\x8e\xcb\x8c9F\xacO\xa74\x98h\xbe\\3\xbaB\'a7{\xd7[\xe2>\xdd\xee\xc1^\xe1\x81\xe1\x9c\x8as\x9d\xac{-\x00b\xed\xf5\xa0`\xa2\xe2v\xadP\x19\x06X\x14\xbf_\r\x7f\xa9q)\xed[\xa5\xd3\xe3w\xc4b\x9cm4L\xc4\xa9YM{z\'\x8eo\x07\xdf<=\xb6\x9b@\xfb%2\x9bC\xbaa\xe5\xfb\x8ae\x96V7Z~\x89\xf7\xa74\x0f:"\xd4\x82\xe86\x89\xe9\xd0(!\x9b\xb21\x01a}\xa3\xe7Sv\'sFK\xfb\x967\rI\xf83fz\xfb-\xb4\xb2\x10\x1e\xd6\xbf\xc5(\xd7\xe8B\xe3\xf95U@Eq\xe7\xfe\x04,\x054\x11\x17\xf7O\t3\x99\xd8\x9bf\xe8\x9c\xd5\xa1\xe1\xb3\x90\xe9\x1e\x87i_\x90\xb2\x04\x8bm\xfaI\xcb&v\x04\r2\xa3\xb4\xf1\xef\x17\x11y6\xb0v\xa5U\xcdJ\x83\x9dM\x99\x1a&\x18\xaclI\x15v\xce)\xd1\xedl>wK?\xe2"\xc3i\x87k\xd8\xb7\xd2\xbb4\xd3dm\xc0\x97q}\xf4\xa0\x00\xb8\x0b\xfep!\xa1\x18\x81\xffR\x83?\xd9\xb6\xa3\xa6\xf7\xa8\x8f\xd3\xa0\xa1\xf2\xf2E\xeb\xb8Hw\x8d0u\xec\x17\x8a;I\xfd58\xc8\xad\xe9}\x85\x03\x03\x87\xf0i\xa8\xe3\xb7\x85\x14\x1e\x96\xa5\xb7]\x91\x03Y\xfat\xb2V\x87\xd2\xd9\xdfd\x00V\xc1j\xa7\xcfU\x12V\xcb\x88\x8b\xc3|)\xd4\xf4\x0cU\xd7.\x15\xe1\x9f\xb3\xf6\xa9\xb0?\xadY\x8e\xbb82\xe9\x84\xc1\xear\xc3\xfcA\xec\xdf[y:\xeb\xbf\x11\xdd\xae{\xc1\xe7\xd6\x95c\x90\xc0\x93O\xba\xb9\x1d\xf0\xbe\xd8\x9c\n\xd4\xe9\xf0\x0er\xfdh\x83\x96\xe5g\xe7\xbc\x9a\xe77<\xc3`\xe6?\x0b\xc0\x13\x07[\x88\x05\x7f\xe3\xbfm\xff\xda\x80\x84\x0e,\xea\x13]Y\xdaLS\xccM\x95\xf3\xf8\xea\xad\xdc\xdf66zZ\xdf\xdc\xe1@}\xbe\xf9\xa6Y\xfd\x15\xa7\xd6\x87\x11zR\x9e\xe46\x7fC\xb4\n\xfe\xa1\x9d\xdev\xe7(\xa7\xcc\xcdH\n\xb2\xb0\x1cx%\xc7\x0cy\xc1\xcf\xb4\\\x9f&\xd5h\xea\xf7\'=O$C\xa5Q\xa7mz\xd1>e\x04 \xc0\x13i\xf4}\xd3\xcd\xd7\xbf\xfaCXo\x0f\x1a\xcf\x02\xda\xbf\xde\x1bu\x0f\x85\x87\x8cA\x88\xebw\xe0P\x11Y\xa7#$(o\xa6\xef\x9c]Sb\xe3\xe6x\x849\xb3\xd7\x98\xcb-h\x1e\xb3\xfe\x1d\xf3\x7fF\xb0\x03\xd4\xee\xcdN\xd0V\t\xf1\x85\xa4\xa5<\xa6;1R\x8dO\xcd\xc3\xa2\x89W\x9dy%\xfe"\x02\xc3\xd3\x8ea\xc5Z\x0c\'j\x14\x935Q\xb2\xe0AzT\xe0V\x96\x0bn;/A\xf8[\xb6(\x0ey\x94\xc07:\xc8\xe1bWU\x08\xfd>\x1b\xe5\x17)\xdd\x80\x99Z\xdd\xf7\t\xf4\x88\x92\xd0\xaeR\xa8\x01\xb2\xd7\xdd\xd8\x16f8\xc3\x914t\x12\x0f\xcbs\xabY\xc7\xceG\xaa\xdc*\x08EA\xe8\xb8\x97$\x87\x9e\xd1\xf4?\xc0\x05>\xe4B\x80\xa7g\xcc\x91\xb30\xfag^]\x07\xf4Ck\x86-\t\xe8\xbbF?U\xaf\xb8\xcd\xdd\x0b\xddU\xe2|z\x8c\x84\x7f\x0ei\xbfh\x07Z\x93\x02\x0e\xbe\xd1;n\x0f\xa7\xeb\x7f\x94{\x8d\xf9:\xce\xd7g\xee\xef\xe5,H2P\xc6\xd2`\xad}\x05\xc3p\x16\x9a$\x1b\xef\xc5m\\\xd3\xdb\x89"\x82\x1a\xb1B\xfdq\xe5\xa1\xca\x96j\x11\xdb\x8fk;)I;p\x99\x9c\x89\x10\xee\xc1\xc5\xfd\x86[4\x9f\xc6\xbdI\xff\x0f\x1e\xf8\x9av\xed\xfd=\xaa\xda\x84E\x0eX\xd7e-\xb2\xa0\xec\xb8\x99\xa7\xe2\xd8`c\xa68\xb5]\'\xf8(\xf2\xf3\xa2\x9b\x87H%\xb0b\xb2\x84\xac\xc1\xd9\x9d\x8f\xb7\x83B\x97\x9f;!Y,\xa0P\xf5\xae\xf9\xef\xfb\x9a\x88.\xa5\xa2\xaa6`#4C\x07O-\xd6\xb9\x81p\x97\xd1u\x9f?9k\xa8\xa3\xa4\xaf\xda\x9c\xf0\xa5\x03:Lh\x91\xf28\x0c\'p\xbe\xf0\xbdQ\x02GBm\xcf\xa6H\xfd\x11\xe4\xee$\x93\xd4{\x8a\x8eahs^1\'\xe2+\xfc`\x19;\xe58\x0e\xc0\xac6q:\x1e\xd7%I9\x994kY\x0bwv\xbf\xe4\xff\xd2\\\xb2SI\x9b\x86;\xc9\x1b\xe4O\xe4\xff\x9e\x01SW\xa3\x8d\xa7&}Z\x10M=\x00\xe9(\xe3\x02\xe3}\x0b\xa9\xb4\xb7D\'J=o\x91n\xadQ\xf5\xeb\xdd\xb98~\xa6d\xbd*n\x94\x85\x80\xe0\x90C\xe3\xcf\xcbJ\x94b\xd2\xc4\xf8\x80\xa1\x15\x933\xae\x91\xbf\xf7\xa8\x82y\x1c\x9e`\x0eF\xf9\x1eX##\x85\xe5\xcc\x93\xd2\x06\xb5\r\x96\xf1\x9f\x93\x0e\xca \x01XA\xd4\xe2]\xfb\xec\xee\x9b\xc89HIVD\x9fowS\xf4D\xa9\xc4\xfd_\xcd\xca\xe4\xd3#T\xbd3\xdb\xa2$g3\x88\xde\xf7\xc7G\xacb39\x1d\xc8\xa8\x03\xac\xf0N\xb7v\xa9\x0f\xde\xa2\x88\xe7yt\xe4\xb6,\xd9\xacG\x0b\xb4\xc9Q\xfa\xde\x9d\x16d\\\xdb{6w\x84^\xedu@\x13+\xf8\xa3\x98\x948\xcf\x9c\xf5j\xd1\xbfO\xac\xd0\xe2\x8a\x03\x0c\xfe1*`\xd2\xd1~\xe5\x11f1\x8aEi\x01\xea\xca\xeeU\\\x8b\xd7\x99\xb4wE\xd6\xcd\xcd\xa8\x98,@\x1c\x11\xfc,\x04\xc4\x10\xa4\x82\xadf8>\xad\xc5%\x94n"D\x1axd\xac&\x88ZPs\xf4\x97q\x95\xb8\x13c\x0e\xa8dN\xc3\x96^\xe3<\x85\xf7WIw\xaf6\xb4\x7f\x85\x90\xcdw\xde\xad\n=\xb7\xc3\x80aX6\x02\x04\xb4g\xa5\x1b}\x8fu\x0f\xd7\xebb\xf1\x1a\x1e\xce\xe7k\xb3\x91\x81\x9e>\xb6\xbe\xfd\xad/bV\x96<v-\x97Y\xd8Q\x0e\x99\xa9\x93A\xd7L~\xcbk8W\x1e\xf9U\x0b1\xe2\xa9\xfea\x9c\x0b\xe1\x04C\xcf\xd9\x89\x01\xa7s\xef\xd71\x83\xf06\\\x1av\xce\x93HC\xa1m\x08\x12e\x1e\n\xaf\xb5\x1d\xa7\xb5\x80\x13\xe7(\xbbp\x11C\xb9\xc8f\x8e\xf2\xf2f\xf4\xfb\xa2\x08W\x85y#\xad\xc0(\x9e\xd3&\xc9\xf2\x14\xf2Y\xf2\xd9H\xc2\xb4\x1c\x97,\xebh\xa5\x1c\x9c\xc7\xe8\x8fF\xd0\x8b\xa4\xf1f\xe8\xdaj\x93\xae\xd3\xc9\xe8\xb2Qa.\xb6\xb0\xfeA\xe5\x02\xd9\xa9\xc6\t&T\x16\xc9\n\xbe\xa0\x8a\xf1M\xeez\xff\x15\xbd\xc9g\xe7\xcf\x90\x01\xdf9\xad\xa9\xe7 W\xcc\xb6Q\x1e5UJ\x98\xb5m\xdfxQ(\t\xb9\xb6\xedS\xa6\xc5\xea\xcb\xb9\xfa\xe8\xdb\xcf\x8f\xe3J\xa08\x85,\xcc\x9e@\xb5\x0e\xcb\xac\xa0E\xc57s\xc9\x902yC\x9b\x81\xef\xcbCC\xbbix9\x8e\xe2\xff~vi\xb9\x11~Bg\xfc\xe9\x18\x9e\x03\xfd\xaa\x85\xe0\xaf\xf1\xc9\x06#\xfe*\x98\xc3\x801-\x9e\x91*\x8d_\xa5\xe0Jwp\x0c0!\xd1\xdcv pK\x94df\x193t\xd3\xfc\xc5\xc2T!\xe7\xfe\xbe\xd5\xcan\xdd\xc8d\x95\xaf\x8cw\x89_C\xae\xdfb*\x90hT\x1e\x88\xc5S\xaaD\x01\xff\xdf\xf1\xc4GV\x03c$\x046?\x02\xa44c\x99`\xa2k\xd4\x86$nN\xf2\x00\x1a?D\x11!\xc1\xbb\xf9\xa2\xe1\x8f\x84\\\xba\r\xbe\xddU\xbc\x92\xb2\nq\x9c0T^\xa5H\xf4\xf3\x8d\xa9\xe6E\xa0\xc7\x1c\x1b4\x99I\xfe\xbe\xa6V\x9e\xd8\xfco\x97\x9a\xd2\x86\x07\xb9h\x16\xc2\x9eq}*\xfb\xd8\x90\xa9\xea\xdd\xd6-\xb6V\x85\x00<i<X1H\x05Tc\x12\xc7w\xc7\xf7E\x02d\x90\xb1y|\xf4#\xd4\xbe\xcb)|\xde\xbc\xc4\x89Y\x92\x9aq\xe9\x19\x1c\xb1\x13q\xf3\xb5\x1eH\xbda\xa2kx\xc8\x17\xbd\x89\xe7\xaf\x90\x10\xf1\xb6\\^\xda\xf4\x88\xde\xef\xc6WM\xff\xd3-(\xac0\x86\xab\xecg\xbb\x89T\t\x9f\xdb#h\x99\xa6\xeb\xa7\x9d-\xe2g\xfa\xed\x93\xca:w\xb7N\xcb\x91\xe5ka\x15\x9a\xc0g\xb4#g\x90\x10\xd3u\x93\xc0zY\x81\x12*\xd3h\x95?b\xb3\xc8\x87\xc1\x92\xe5\xd1\xf7\xb3\x82\x8d\xb4\x8dK\xe6\x81\x01@\x02/\x1a\xbar\x92\x83\xf4\xb3_\x9f.\x86\xdf\xfe\xe6\xe6\x81\xc0\xf1|\xea\x0b\x87\xff\xa2bMe\xdc\xee1b\xee\xfe&?x\xfa\x03H\xbae\x13\x0b,\x9f\x17\x190\xcb\xd7%y1\xa0\xf7-G\x9c}\np\xee\xb0\x92\xbd\xd0\x9b\xbf\x0fALw\xc2\x18E0\xcf-\x12\x01\x18\x0f\xa5;\x8d\x9b@v\xd3\xe1\x0cG+Zn\x95M\xda\x93\xd18\xa1\xaft\xd5\xe2Yc:1\x02bU\xbaf\xf3\xde\xa5\x03/\xdc\x9e`\x14\x96\xcc~\xb7\x86\xca\xc1I\xe9q"T\xb0\x92\xd5\xe7\xc0\x7f\xfe0|o\x1d\xd8\xf9\x87V5X\\\x1bq\x9d\xef\x00\x89y\x1d~4\xa9b\x13\xb1\xcd\xcc\xc7\xd2\xd5\x84\xbd5b\x85\xf3KK\x0e\xae$\x18R|>\xdap\xf3y6\xc3/\xc8Y\ng\x9a\xa8\xb3\x90\x03h\x81\x07\x88H\xc5\xd9\xe0\x9fn\x19\x11\r\x99BO\xbc\xd9K\x10l\xb4\x0f=\xec\xa3\xd5\x8f\xb7\xf0\xd7Qa\xe2\x84\xf4M&E\xe6C\xe1X\xe9\x8b\x00\xfa\xf5p\xa3\x15\x80Q\x002\x95\xe7u\xec\xcbFr\x14F\xb4\n~\xb5\xe0F<\x91N&B\'\xec\x9d00x\x96\x17\\J\r\xb9\xdb\xc2\xae;\xb5\x0e`\x19\x1e>\x7f;\xb1\xe36\xecV@/$\x9a\x04\xb9\x81gM]nS\xf7\x84bd\xf1\xfb\x1c\x8f#&\xbe\xb7UE\xf5\xb6\xcaL#\x87\xdb\xc5\xa1\x80\x02\xe7\xb3\xbf\x02w\xf6\xfaJ\xc9\x8f\xa6C\x14 5}\xd5\x17\xa3\xeb\xf5\x91\x8f\x16Q\xd4\xe3\xc4a2\x8f/l\xa3\xaa\xda\xe8w\x91*\xef;\x7f\xd1\xef\\J\xeb\xe2\x9dY\xf0\xd5\xd3\xbbZ\x1e\xca8\xb1\x9d\xfcx\xe7\xbc\x05\xf3\x98TR\xf5]#\xb8K\xb2\xf1w\xc5\xce\xe0\x93\x90\x8a\x9cT\xa0\x8d@6\xa0a\xafO5\x08+\x10\xce5\x99z\xb7\x9f\xa8\xdf\x12HF\x99\xfa\xe6\x0c;\xb4&5V\xb7\x94\xece\xfdaApL\x0e\x8cm\xaaF9d\x9d\x00\xe2\xd3\xe2P@\xea\x02\xe0\xfd\x92\xc9\\\xb8\xde\x00\x81+\xd9\xbcW\x0bZ\x10\xf0\x11@2\xc9F\xa0\x82u\xd0X\xfb\xddS\xa1\xd2\xab\x0f\xfd#\xab\xb8\x86\x9c)\xd7\xddx/\xc3\xf2]u\xc0\x05\xc1\xadt\xfb?\xfa\xb5\x11\x9a\'\x1d-\x14q\x9d=\xf0K\x82C\x94Z\tD\x9b\xb2\x9d\xe0\x86 \xe8\xf4\xaa\xd3\x17\xebD\x9e\x15\x84\xb9\xe7/f{~,r\xf1\x88\x85\xc3B\t\xb7yr\xe2\xdbj\xec\xfe\x06\x90\x8c\x02.}9\x01>\'\xefl&\xb5\xe6]\xa9\x94\x05\xd8\xeb\x19\xcd\x82\x91\x9d\r8\x1a\xde\xe0<{G\x9aw\x93\xf4\x03\xbb\xab\xc0+\x9a\x9b\xd1I\xf9\xc3\x1cFr\xb6\x0e\xc6d\xe0\xaf\x9c\xc6\xb8;\xf6\x8f\xaa\xff\xd3\x96\xac\x9b\x1a\xcf\xe9\xb6i2\xa8\xf3?\x99r*-\xb6\xf7\x8e\x1e\x0e%\xa6pU\x9d\xe1\xbc|d\xe9`\r*ulk\tPa\x0c\x93%w<\x01\x96\xd8\x03JVJ\x1a\xad\x0e\xcc\xf0\x1c\xebW\x11\x02\r\xff\xf9\xb6{x\xcc"\x12\xe1AX*\x94\xf8\x98\x81*\x80\xe96\xf8c=\xdcwkM\xdbK\xd1\x8a\xbe7\x98\x89P.\x80\x17\x81\xeb\x10g\xed\x02\x9a\xcf\x9c0\xa5M\xcc\xd0\xd0\x03\xb5[\xf07\x9c\xb5S\x1e\x88\xf4\xaf\xe7~\xdd\xfa\x8c1am\xcf\xbc\xc0\x13\xd45\xd8\xdd(\x04#`E\xb2d\xcf\xdb[\x1a\x80\x0c&j\xaa\x91\xdc\x8f\xb6\xac%}D\xad\xa7Dh6gs\xc0|\xf5X\xad\xc9\xc9\xae\xeb:h\xa0z\x00\x99\x04N\xce)\x02q\xf0\xe6T;\xf9j\xf0\x86\xa7\xc5;c&\x14\xa8\x1d\xc4\x98\xb1Y\n\xcc\xd5\x80b\xd8Dl\xfe:\x0f\xce~\xb4]\xde\xa1\xd6)iV\t0\xaa\x02\xdb\xc8\xb8\x03\x9f]\xec\xa9Q\x01\xb4\x0e%\xed\x1d\xf1\x04)\x0e\xd3\x1f\xffkx\xe0\xffHx/\x96\xbd\xcb\xe8\xe4$\x92\x97\x83h\xc5j$\xfe\xed5\xf7\xdey\x85f\xf0mIt\x82\xff\x84\xd4]\x80\xcc\xd4r\xe2\xd7\x86<\xd7\x86\x87\xa8\xb8\xbc\x14\xf1i\x08\xe9<\x00\x85\x1f\xd8\x1c\xd8\x04\x9bH\x0c5\x01\xe6\xa8\xa9)\\{K\x12\xb4fo[d\xb8\x92\xe8\xec^3br\xf4\xc14\xd3\xf7w\xf8\xc4V\xcd\xeb\x83\x0b\x17OD0\xa0\xd2\x1b\xa6\xb0h\xe0OqFss\xf1\x85\xfd\xfd\xa9|`\x8f\xefou`\xb52\xfd1l\xf8\x90W\xee\x06\xc7-\r-A^\x9b\x9d\x1a\x1a`\xcb\xe9l\xd9I\x904\xdc~5O\x80\xd6\xef\xa8\x7f\xe9U8\x99A!\xf9\xea2s\xff\x81\xca\x0f\xce\xae\xd7\x10\xc7\x85d7\x1cz>\x1au\x92\x05\x9b/E\x89b@\x04\xe4\xabbk\x10\xdc\x9d\x07\x0c.Y\x1e\xc2#\xce\x06\xfa\xa4\x86~\x11\xf0\xc1j\xc3\xf1"\x04J\xb0\xf9X\xe6\xe7\xaeE\xf7g\x83\x9f.\x1f\xedy5\x1d\xb7N*\xead\xe8\xe6\xca\xeb\x06\x8d\xd5Q\xc8"\xcc\x08\xfc\x9b\xbe\x0b\x1el\x0f\xc2\x1b9\x83\xd9\xd1R\xeb\x02J\x9bZQl5+\xa73\xe1\x8fG\x86\xfa{:\xa9Jy\xd6{%\\kLq\x06\xfa=\xcd:)5KW\xd69\x14F\x19V,,\ng\x10\xb0\x1fU\xd1\x9a\xec\xf2\xe7\xa2]\xacn\x1e\x19>\x14F\x81_\xc47\x90\x1c\xe6\x7f\xf9\x19\n\x1b6\xfc\xbb\x960\xada\xf4>*\r5\xdac\xc0\xeaA\x91\xf3\xecU\x18\x10m`\xefv\xcb"\x80\xb1qQ7X^9\x0b\x00y\xf6\xd0\xf4\xbd\xf2\xc1\xb0\xbdq1\xbe\x84\xf2\x04:\x9a\xe9\xb9\x9e\x1d\x1f\xcb\x9amh\xfa\xf7\x11\xe7pg\xc8]\xb0o\xd9\xf7\xbb\xf3\x02Y\x07WT,8 \x99\xe6\x7fmH\xb1f2\xfc\x0e[\xc0\x96\xf1\xbc\xfe:\tX]R\xb7\xca8nx\x04\xeeu\xe7\x95\xce\xa9\xf1\x9c[\x98\xb5\xfd\xdd_\xb6\xff\x0c\xb6S"R\xf2@Q\xe6\'\x93\'\x05\x08?\xd6?\x92\x19zs\xa1B\xe2\xc7\x0e\xd8\xa8\xa3\xd1\x8e@\xe7r\x1a\x00\xf7\xca\xb4\x8a\x87\xba%J\xd0\x81O\xd3\x0b\xa9\xe7@V\x16\x8d?8\xfa\xfbW\x88\x1d\xa2hA6\t\x07\xf8\xffT\xc4"\x13\x1e)~\xee\x15\x90\xfb\xb4\xc9q\xc3~\x9ah\xe5Ps\xf4\x9c\xd1\xdf\xea-\xd1w\x9dt\x15\x7f\xea\xa11O"*GT+P\xeb\xd6\x19BJ\'\x051\xb0@F\x1c\xbd\x97\xebK\xee\x17\xc3Pd$3\x18\x0f\x07\xe5g&U\x9f\x7fH\xf9\\G\xa4+Y`!c\xc4Q\x98\x9d_D\xc8\x8e\xfa\xcc\xd1\xaf=w\x1d\\5\x81\xcd\x18\xa0MewD%g\xa4\xf3\x18\x81\xf0hj\x84\xd1\x91\xa3Y\x1bm\xf50\xfe\xa0Sq\xa8\x1fb(\xbb\xdc\xab\xffb\'\x88\xae|r\xb4\x05f\xc9W2\x8a')
|
4
|
-
|
1
|
+
from flask_admin.contrib import sqla
|
2
|
+
from hiddifypanel.panel.database import db
|
3
|
+
import datetime
|
4
|
+
from hiddifypanel.models import *
|
5
|
+
from flask import Markup,g
|
6
|
+
from wtforms.validators import Regexp,ValidationError
|
7
|
+
import re,uuid
|
8
|
+
from hiddifypanel import xray_api
|
9
|
+
from .adminlte import AdminLTEModelView
|
10
|
+
# from gettext import gettext as _
|
11
|
+
from flask_babelex import gettext as __
|
12
|
+
from flask_babelex import lazy_gettext as _
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
from hiddifypanel.panel import hiddify,custom_widgets
|
17
|
+
from hiddifypanel.panel.hiddify import flash
|
18
|
+
from wtforms.fields import StringField
|
19
|
+
from flask_bootstrap import SwitchField
|
20
|
+
class UserAdmin(AdminLTEModelView):
|
21
|
+
column_sortable_list=["name","current_usage_GB",'mode',"remaining_days","comment",'last_online',"uuid",'remaining_days']
|
22
|
+
column_searchable_list=[("uuid"),"name"]
|
23
|
+
column_list = ["name","UserLinks","current_usage_GB","remaining_days","comment",'last_online','mode',"uuid"]
|
24
|
+
form_extra_fields = {
|
25
|
+
'reset_days': SwitchField(_("Reset package days")),
|
26
|
+
'reset_usage': SwitchField(_("Reset package usage")),
|
27
|
+
'disable_user': SwitchField(_("Disable User"))
|
28
|
+
}
|
29
|
+
list_template = 'model/user_list.html'
|
30
|
+
form_excluded_columns=['monthly','last_online','expiry_time','last_reset_time','current_usage_GB','start_date']
|
31
|
+
page_size=50
|
32
|
+
# edit_modal=True
|
33
|
+
# create_modal=True
|
34
|
+
# column_display_pk = True
|
35
|
+
# can_export = True
|
36
|
+
# form_overrides = dict(monthly=SwitchField)
|
37
|
+
form_overrides = dict(start_date=custom_widgets.DaysLeftField)
|
38
|
+
|
39
|
+
# form_overrides = dict(expiry_time=custom_widgets.DaysLeftField,last_reset_time=custom_widgets.LastResetField)
|
40
|
+
form_widget_args={
|
41
|
+
'current_usage_GB':{'min':'0'} ,
|
42
|
+
'usage_limit_GB':{'min':'0'} ,
|
43
|
+
|
44
|
+
}
|
45
|
+
form_args = {
|
46
|
+
'uuid': {
|
47
|
+
'validators': [Regexp(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',message=__("Should be a valid uuid"))]
|
48
|
+
# 'label': 'First Name',
|
49
|
+
# 'validators': [required()]
|
50
|
+
}
|
51
|
+
# ,
|
52
|
+
# 'expiry_time':{
|
53
|
+
# "":'%Y-%m-%d'
|
54
|
+
# }
|
55
|
+
}
|
56
|
+
# column_labels={'uuid':_("user.UUID")}
|
57
|
+
# column_filters=["uuid","name","usage_limit_GB",'monthly',"current_usage_GB","start_date"]
|
58
|
+
|
59
|
+
column_labels={
|
60
|
+
"Actions":_("actions"),
|
61
|
+
"name": _("user.name"),
|
62
|
+
"UserLinks":_("user.user_links"),
|
63
|
+
"usage_limit_GB":_("user.usage_limit_GB"),
|
64
|
+
"monthly":_("Reset every month"),
|
65
|
+
"mode":_("Mode"),
|
66
|
+
"current_usage_GB":_("user.current_usage_GB"),
|
67
|
+
"start_date":_("Start Date"),
|
68
|
+
"remaining_days":_("user.expiry_time"),
|
69
|
+
"last_reset_time":_("user.last_reset_time"),
|
70
|
+
"uuid":_("user.UUID"),
|
71
|
+
"comment":_("Note"),
|
72
|
+
'last_online':_('Last Online'),
|
73
|
+
"package_days":_('Package Days'),
|
74
|
+
|
75
|
+
}
|
76
|
+
# can_set_page_size=True
|
77
|
+
|
78
|
+
def search_placeholder(self):
|
79
|
+
return f"{_('search')} {_('user.UUID')} {_('user.name')}"
|
80
|
+
# def get_column_name(self,field):
|
81
|
+
# return "x"
|
82
|
+
# return column_labels[field]
|
83
|
+
column_descriptions = dict(
|
84
|
+
# name=_'just for remembering',
|
85
|
+
# usage_limit_GB="in GB",
|
86
|
+
# current_usage_GB="in GB"
|
87
|
+
comment=_("Add some text that is only visible to you."),
|
88
|
+
mode=_("Define the user mode. Should the usage reset every month?"),
|
89
|
+
last_reset_time=_("If monthly is enabled, the usage will be reset after 30 days from this date."),
|
90
|
+
start_date=_("From when the user package will be started? Empty for start from first connection"),
|
91
|
+
package_days=_("How many days this package should be available?")
|
92
|
+
)
|
93
|
+
# column_editable_list=["usage_limit_GB","current_usage_GB","expiry_time"]
|
94
|
+
# form_extra_fields={
|
95
|
+
# 'uuid': {'label_name':"D"}
|
96
|
+
|
97
|
+
# }
|
98
|
+
|
99
|
+
# can_edit = False
|
100
|
+
# def on_model_change(self, form, model, is_created):
|
101
|
+
# model.password = generate_password_hash(model.password)
|
102
|
+
|
103
|
+
|
104
|
+
def _name_formatter(view, context, model, name):
|
105
|
+
proxy_path=hconfig(ConfigEnum.proxy_path)
|
106
|
+
if hconfig(ConfigEnum.is_parent):
|
107
|
+
from hiddifypanel.panel.commercial import ParentDomain
|
108
|
+
d=ParentDomain.query.first()
|
109
|
+
else:
|
110
|
+
d=Domain.query.filter(Domain.mode!=DomainType.fake).first()
|
111
|
+
if d:
|
112
|
+
link=f"<a target='_blank' href='https://{d.domain}/{proxy_path}/{model.uuid}/#{model.name}'>{model.name} <i class='fa-solid fa-arrow-up-right-from-square'></i></a>"
|
113
|
+
if model.is_active:
|
114
|
+
link= '<i class="fa-solid fa-circle-check text-success"></i> '+link
|
115
|
+
else:
|
116
|
+
link= '<i class="fa-solid fa-circle-xmark text-danger"></i> '+link
|
117
|
+
return Markup(link)
|
118
|
+
else:
|
119
|
+
return model.name
|
120
|
+
def _ul_formatter(view, context, model, name):
|
121
|
+
if hconfig(ConfigEnum.is_parent):
|
122
|
+
from hiddifypanel.panel.commercial import ParentDomain
|
123
|
+
domains=ParentDomain.query.all()
|
124
|
+
else:
|
125
|
+
domains=Domain.query.filter(Domain.mode!=DomainType.fake).all()
|
126
|
+
return Markup(" ".join([hiddify.get_user_link(model.uuid,d,'new',model.name) for d in domains]))
|
127
|
+
|
128
|
+
def _uuid_formatter(view, context, model, name):
|
129
|
+
return Markup(f"<span>{model.uuid}</span>")
|
130
|
+
# def _usage_formatter(view, context, model, name):
|
131
|
+
# return round(model.current_usage_GB,3)
|
132
|
+
|
133
|
+
def _usage_formatter(view, context, model, name):
|
134
|
+
u= round(model.current_usage_GB,3)
|
135
|
+
t=round(model.usage_limit_GB,3)
|
136
|
+
rate=round(u*100/(t+0.000001))
|
137
|
+
state= "danger" if u>=t else ('warning' if rate>80 else 'success')
|
138
|
+
color= "#ff7e7e" if u>=t else ('#ffc107' if rate>80 else '#9ee150')
|
139
|
+
return Markup(f"""
|
140
|
+
<div class="progress progress-lg position-relative" style="min-width: 100px;">
|
141
|
+
<div class="progress-bar progress-bar-striped" role="progressbar" style="width: {rate}%;background-color: {color};" aria-valuenow="{rate}" aria-valuemin="0" aria-valuemax="100"></div>
|
142
|
+
<span class='badge position-absolute' style="left:auto;right:auto;width: 100%;font-size:1em">{u} {_('user.home.usage.from')} {t} GB</span>
|
143
|
+
|
144
|
+
</div>
|
145
|
+
""")
|
146
|
+
|
147
|
+
def _expire_formatter(view, context, model, name):
|
148
|
+
remaining=remaining_days(model)
|
149
|
+
|
150
|
+
diff=datetime.timedelta(days=remaining)
|
151
|
+
|
152
|
+
state='success' if diff.days>7 else ('warning' if diff.days>0 else 'danger')
|
153
|
+
formated=hiddify.format_timedelta(diff)
|
154
|
+
return Markup(f"<span class='badge badge-{state}'>{'*' if not model.start_date else ''} {formated} </span>")
|
155
|
+
# return Markup(f"<span class='badge ltr badge-}'>{days}</span> "+_('days'))
|
156
|
+
|
157
|
+
def _online_formatter(view, context, model, name):
|
158
|
+
if not model.last_online:
|
159
|
+
return Markup("-")
|
160
|
+
diff=model.last_online-datetime.datetime.now()
|
161
|
+
|
162
|
+
if diff.days<-1000:
|
163
|
+
return Markup("-")
|
164
|
+
|
165
|
+
state="danger" if diff.days<-3 else ("success" if diff.days>=-1 else "warning")
|
166
|
+
return Markup(f"<span class='badge badge-{state}'>{hiddify.format_timedelta(diff,granularity='min')}</span>")
|
167
|
+
|
168
|
+
|
169
|
+
# return Markup(f"<span class='badge ltr badge-{'success' if days>7 else ('warning' if days>0 else 'danger') }'>{days}</span> "+_('days'))
|
170
|
+
|
171
|
+
column_formatters = {
|
172
|
+
'name': _name_formatter,
|
173
|
+
'UserLinks': _ul_formatter,
|
174
|
+
'uuid': _uuid_formatter,
|
175
|
+
'current_usage_GB': _usage_formatter,
|
176
|
+
"remaining_days":_expire_formatter,
|
177
|
+
'last_online':_online_formatter
|
178
|
+
}
|
179
|
+
def on_model_delete(self, model):
|
180
|
+
if len(User.query.all())<=1:
|
181
|
+
raise ValidationError(f"at least one user should exist")
|
182
|
+
xray_api.remove_client(model.uuid)
|
183
|
+
# hiddify.flash_config_success()
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
# def is_accessible(self):
|
188
|
+
# return g.is_admin
|
189
|
+
def on_form_prefill(self, form, id=None):
|
190
|
+
print("================",form._obj.start_date)
|
191
|
+
if form._obj.start_date is None:
|
192
|
+
msg= _("Package not started yet.")
|
193
|
+
# form.reset['class']="d-none"
|
194
|
+
delattr(form,'reset_days')
|
195
|
+
delattr(form,'reset_usage')
|
196
|
+
# delattr(form,'disable_user')
|
197
|
+
else:
|
198
|
+
remaining=remaining_days(form._obj)
|
199
|
+
msg= _("Remaining: ")+ hiddify.format_timedelta(datetime.timedelta(days=remaining))
|
200
|
+
form.reset_days.label.text+=f" ({msg})"
|
201
|
+
usr_usage=f" ({_('user.home.usage.title')} {round(form._obj.current_usage_GB,3)}GB)"
|
202
|
+
form.reset_usage.label.text+=usr_usage
|
203
|
+
form.usage_limit_GB.label.text+=usr_usage
|
204
|
+
|
205
|
+
if form._obj.mode==UserMode.disable:
|
206
|
+
delattr(form,'disable_user')
|
207
|
+
# form.disable_user.data=form._obj.mode==UserMode.disable
|
208
|
+
form.package_days.label.text+=f" ({msg})"
|
209
|
+
|
210
|
+
def get_edit_form(self):
|
211
|
+
form = super().get_edit_form()
|
212
|
+
# print(form.__dict__)
|
213
|
+
# user=User.query.filter(User.uuid==form.uuid).first()
|
214
|
+
# if user and user.start_date:
|
215
|
+
# form.reset = SwitchField("Reset")
|
216
|
+
return form
|
217
|
+
def on_model_change(self, form, model, is_created):
|
218
|
+
if len(User.query.all())%4==0:
|
219
|
+
flash(('<div id="show-modal-donation"></div>'), ' d-none')
|
220
|
+
if not re.match("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", model.uuid):
|
221
|
+
raise ValidationError('Invalid UUID e.g.,'+ str(uuid.uuid4()))
|
222
|
+
|
223
|
+
if form.reset_usage.data:
|
224
|
+
model.current_usage_GB=0
|
225
|
+
if form.disable_user.data:
|
226
|
+
model.mode=UserMode.disable
|
227
|
+
if form.reset_days.data:
|
228
|
+
model.start_date=None
|
229
|
+
model.package_days=min(model.package_days,10000)
|
230
|
+
old_user=user_by_id(model.id)
|
231
|
+
if old_user and old_user.uuid!=model.uuid:
|
232
|
+
xray_api.remove_client(old_user.uuid)
|
233
|
+
|
234
|
+
# model.expiry_time=datetime.date.today()+datetime.timedelta(days=model.expiry_time)
|
235
|
+
|
236
|
+
|
237
|
+
# if model.current_usage_GB < model.usage_limit_GB:
|
238
|
+
# xray_api.add_client(model.uuid)
|
239
|
+
# else:
|
240
|
+
# xray_api.remove_client(model.uuid)
|
241
|
+
# hiddify.flash_config_success()
|
242
|
+
# def is_accessible(self):
|
243
|
+
# return is_valid()
|
244
|
+
|
245
|
+
def after_model_change(self,form, model, is_created):
|
246
|
+
hiddify.quick_apply_users()
|
247
|
+
def after_model_delete(self,model):
|
248
|
+
xray_api.remove_client(model.uuid)
|
249
|
+
hiddify.quick_apply_users()
|
250
|
+
|
251
|
+
def get_list(self, page, sort_column, sort_desc, search, filters,*args, **kwargs):
|
252
|
+
res=None
|
253
|
+
print('aaa',args, kwargs)
|
254
|
+
if 'remaining_days' == sort_column:
|
255
|
+
query = self.session.query(self.model)
|
256
|
+
count = query.count()
|
257
|
+
data = query.all()
|
258
|
+
data=sorted(data,key=lambda p: p.remaining_days,reverse=sort_desc)
|
259
|
+
res=count,data
|
260
|
+
else:
|
261
|
+
res=super().get_list(page, sort_column, sort_desc, search, filters,*args, **kwargs)
|
262
|
+
return res
|
263
|
+
|
264
|
+
# Override the default get_list method to use the custom sort function
|
265
|
+
query = self.session.query(self.model)
|
266
|
+
if self._sortable_columns:
|
267
|
+
print("sor",self._sortable_columns['remaining_days'])
|
268
|
+
for column, direction in self._get_default_order():
|
269
|
+
# if column == 'remaining_days':
|
270
|
+
# # Use the custom sort function for 'remaining_days'
|
271
|
+
# query = query.order_by(self.model.remaining_days.asc() if direction == 'asc' else self.model.remaining_days.desc())
|
272
|
+
# else:
|
273
|
+
# Use the default sort function for other columns
|
274
|
+
query = query.order_by(getattr(self.model, column).asc() if direction == 'asc' else getattr(self.model, column).desc())
|
275
|
+
count = query.count()
|
276
|
+
data = query.all()
|
277
|
+
return count, data#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
278
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
@@ -1,5 +1,83 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
|
4
|
-
|
1
|
+
from flask import Blueprint,url_for,request,jsonify,g,redirect
|
2
|
+
from flask_admin import Admin
|
3
|
+
from hiddifypanel import Events
|
4
|
+
# from flask_sockets import Sockets
|
5
|
+
|
6
|
+
from .SettingAdmin import SettingAdmin
|
7
|
+
from .DomainAdmin import DomainAdmin
|
8
|
+
from .ConfigAdmin import ConfigAdmin
|
9
|
+
from .commercial_info import CommercialInfo
|
10
|
+
from .ProxyAdmin import ProxyAdmin
|
11
|
+
|
12
|
+
from .Actions import Actions
|
13
|
+
from .Backup import Backup
|
14
|
+
from .QuickSetup import QuickSetup
|
15
|
+
from hiddifypanel.models import StrConfig,ConfigEnum
|
16
|
+
# from .resources import ProductItemResource, ProductResource
|
17
|
+
from hiddifypanel.panel.database import db
|
18
|
+
from hiddifypanel.models import *
|
19
|
+
from .Dashboard import Dashboard
|
20
|
+
|
21
|
+
from flask_admin.menu import MenuLink
|
22
|
+
|
23
|
+
import uuid
|
24
|
+
from flask_adminlte3 import AdminLTE3
|
25
|
+
flask_bp = Blueprint("flask", __name__, url_prefix=f"/<proxy_path>/<user_secret>/",template_folder="templates")
|
26
|
+
admin_bp = Blueprint("admin", __name__, url_prefix=f"/<proxy_path>/<user_secret>/admin/",template_folder="templates")
|
27
|
+
flaskadmin = Admin(endpoint="admin",base_template='flaskadmin-layout.html')
|
28
|
+
# from extensions import socketio
|
29
|
+
|
30
|
+
|
31
|
+
def init_app(app):
|
32
|
+
|
33
|
+
from .UserAdmin import UserAdmin
|
34
|
+
# admin_secret=StrConfig.query.filter(StrConfig.key==ConfigEnum.admin_secret).first()
|
35
|
+
#
|
36
|
+
# return
|
37
|
+
# admin = Admin(endpoint="admin",index_view=Dashboard(),base_template='lte-master.html',static_url_path="/static/")
|
38
|
+
flaskadmin.template_mode = "bootstrap4"
|
39
|
+
flaskadmin.init_app(flask_bp)
|
40
|
+
adminlte=AdminLTE3()
|
41
|
+
adminlte.init_app(app)
|
42
|
+
|
43
|
+
Events.admin_prehook.notify(flaskadmin=flaskadmin,admin_bp=admin_bp)
|
44
|
+
|
45
|
+
|
46
|
+
@app.route('/<proxy_path>/<user_secret>/admin')
|
47
|
+
def auto_route():
|
48
|
+
return redirect(request.url.replace("http://","https://")+"/")
|
49
|
+
|
50
|
+
|
51
|
+
# flaskadmin.init_app(app)
|
52
|
+
|
53
|
+
flaskadmin.add_view(UserAdmin(User, db.session))
|
54
|
+
flaskadmin.add_view(DomainAdmin(Domain, db.session))
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
SettingAdmin.register(admin_bp)
|
63
|
+
ProxyAdmin.register(admin_bp)
|
64
|
+
Actions.register(admin_bp)
|
65
|
+
CommercialInfo.register(admin_bp)
|
66
|
+
|
67
|
+
QuickSetup.register(admin_bp)
|
68
|
+
Backup.register(admin_bp)
|
69
|
+
Dashboard.register(admin_bp,route_base="/")
|
70
|
+
|
71
|
+
|
72
|
+
# admin_bp.add_url_rule('/admin/quicksetup/',endpoint="quicksetup",view_func=QuickSetup.index,methods=["GET"])
|
73
|
+
# admin_bp.add_url_rule('/admin/quicksetup/',endpoint="quicksetup-save", view_func=QuickSetup.save,methods=["POST"])
|
74
|
+
|
75
|
+
|
76
|
+
app.add_url_rule("/<proxy_path>/<user_secret>/admin/static/<filename>/",endpoint="admin.static")# fix bug in admin with blueprint
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
flask_bp.debug=True
|
81
|
+
app.register_blueprint(admin_bp)
|
82
|
+
app.register_blueprint(flask_bp)#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
83
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
@@ -1,5 +1,14 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
|
4
|
-
|
1
|
+
from flask_admin.contrib.sqla import ModelView
|
2
|
+
from flask_admin.form import SecureForm
|
3
|
+
class AdminLTEModelView(ModelView):
|
4
|
+
list_template = 'hiddify-flask-admin/list.html'
|
5
|
+
create_template = 'flask-admin/model/create.html'
|
6
|
+
edit_template = 'flask-admin/model/edit.html'
|
7
|
+
details_template = 'flask-admin/model/details.html'
|
8
|
+
|
9
|
+
create_modal_template = 'flask-admin/model/modals/create.html'
|
10
|
+
edit_modal_template = 'flask-admin/model/modals/edit.html'
|
11
|
+
details_modal_template = 'flask-admin/model/modals/details.html'
|
12
|
+
|
13
|
+
# form_base_class = SecureForm#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
14
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
@@ -1,5 +1,25 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
import pprint
|
3
|
+
from flask_babelex import gettext as _
|
4
|
+
import pathlib
|
5
|
+
from hiddifypanel.models import *
|
6
|
+
|
7
|
+
from datetime import datetime,timedelta,date
|
8
|
+
import os,sys
|
9
|
+
import json
|
10
|
+
import urllib.request
|
11
|
+
import subprocess
|
12
|
+
import re
|
13
|
+
from hiddifypanel.panel import hiddify,usage
|
14
|
+
from hiddifypanel.panel import hiddify_api
|
15
|
+
from flask import current_app,render_template,request,Response,Markup,url_for
|
16
|
+
from hiddifypanel.panel.hiddify import flash
|
17
|
+
|
18
|
+
from flask_classful import FlaskView,route
|
19
|
+
|
20
|
+
class CommercialInfo(FlaskView):
|
21
|
+
|
22
|
+
def index(self):
|
23
|
+
return render_template('commercial_info.html')
|
4
24
|
#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
25
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
@@ -1,5 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
|
2
|
+
|
3
|
+
# from flask_socketio import SocketIO
|
4
|
+
|
5
|
+
# socketio = SocketIO()
|
6
|
+
|
7
|
+
|
8
|
+
# def __init__(app):
|
9
|
+
# socketio.__init__(app)
|
4
10
|
#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
11
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
hiddifypanel/panel/admin_2.py
CHANGED
@@ -1,5 +1,35 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
|
1
|
+
from flask_admin import Admin
|
2
|
+
from flask_admin.base import AdminIndexView
|
3
|
+
from flask_admin.contrib import sqla
|
4
|
+
# from flask_simplelogin import login_required
|
5
|
+
from werkzeug.security import generate_password_hash
|
6
|
+
|
7
|
+
from hiddifypanel.panel.database import db
|
8
|
+
from hiddifypanel.models import User
|
9
|
+
|
10
|
+
# Proteck admin with login / Monkey Patch
|
11
|
+
# AdminIndexView._handle_view = login_required(AdminIndexView._handle_view)
|
12
|
+
# sqla.ModelView._handle_view = login_requiredsqla.ModelView._handle_view)
|
13
|
+
admin = Admin()
|
14
|
+
|
15
|
+
|
16
|
+
class UserAdmin(sqla.ModelView):
|
17
|
+
column_list = ["username"]
|
18
|
+
can_edit = False
|
19
|
+
|
20
|
+
def on_model_change(self, form, model, is_created):
|
21
|
+
model.password = generate_password_hash(model.password)
|
22
|
+
|
23
|
+
|
24
|
+
def init_app(app):
|
25
|
+
# admin.name = app.config.HIDDIFY_CONFIG_PATH
|
26
|
+
admin.template_mode = app.config.FLASK_ADMIN_TEMPLATE_MODE
|
27
|
+
admin.init_app(app)
|
28
|
+
|
29
|
+
# Add admin page for Product
|
30
|
+
# admin.add_view(sqla.ModelView(Product, db.session))
|
31
|
+
|
32
|
+
# Add admin page for User
|
33
|
+
admin.add_view(UserAdmin(User, db.session))
|
4
34
|
#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
35
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
hiddifypanel/panel/asset.py
CHANGED
@@ -1,5 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
from flask import g, send_from_directory, url_for
|
2
|
+
|
3
|
+
|
4
|
+
def send_static(path):
|
5
|
+
return send_from_directory('static/assets', path)
|
6
|
+
|
7
|
+
|
8
|
+
def init_app(app):
|
9
|
+
@app.url_defaults
|
10
|
+
def add_asset(endpoint, values):
|
11
|
+
def get_asset(path):
|
12
|
+
return url_for('asset', proxy_path=g.proxy_path, path=path)
|
13
|
+
g.asset_url = get_asset
|
14
|
+
|
15
|
+
app.add_url_rule('/<proxy_path>/asset/<path:path>',
|
16
|
+
'asset', view_func=send_static)
|
17
|
+
pass
|
4
18
|
#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
19
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|