hiddifypanel 3.0.0.dev63__cp310-cp310-manylinux2014_x86_64.whl → 3.0.0.dev65__cp310-cp310-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/templates/config.html +1 -1
- hiddifypanel/panel/admin/templates/proxy.html +2 -2
- 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 +11 -0
- hiddifypanel/templates/500.html +1 -1
- hiddifypanel/xray_api.py +109 -3
- {hiddifypanel-3.0.0.dev63.dist-info → hiddifypanel-3.0.0.dev65.dist-info}/METADATA +1 -1
- {hiddifypanel-3.0.0.dev63.dist-info → hiddifypanel-3.0.0.dev65.dist-info}/RECORD +69 -71
- hiddifypanel-3.0.0.dev65.dist-info/top_level.txt +1 -0
- hiddifypanel-3.0.0.dev63.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.dev63.dist-info → hiddifypanel-3.0.0.dev65.dist-info}/LICENSE +0 -0
- {hiddifypanel-3.0.0.dev63.dist-info → hiddifypanel-3.0.0.dev65.dist-info}/WHEEL +0 -0
- {hiddifypanel-3.0.0.dev63.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\n\x00o\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00x1\x00\x00\x12\t\x04\x00{\xb6!v\x0e\x13P\xa18\xe0\xbc\xd2p\xa2\xab\xa0\x00\x00\x00\x00\x00\x00\x00\x00l8\xfe\re.\x07\xee\x92\x12`\xd6\x832\x1aR\x81%8\xd0j\x85\x1cM\xde\x00\xaa\x1e q\xa5\x8cp\xc0\xdc\xa9\xd6W\xbb\xca\xe8\xf5\xb2\xf4\xcb:#F\xcc\xd2\xba\x8d\xc0\xe1\xc4\x92\x14\x15\x0b\x1f\xff\x19\x9c\x0cu\xfa\x8f/!\xedD\xf5\x9e?]\xd3.LG\xc5\x07\x98\xfeDf\xd8\x8e5M\xe9\xbe\xb7<\x08\x9crQ\xe7\xf8\x0f\x1ad\xf8\x0c\xe8\xe6\xacF\xbe\xd9F\x19\xed\x15\x96\xaaU\x9d\xb7\xca\xf3:R\x9f\xf6\xa2\xa7\x18\xb6\x05\xefl>\xbd\x17\xb5\xdd\xca\x85=F\'6G\x16+\x96\xb8K\x08\xc3\xd92\xa6\x14p\xf07<\xd6\xf9\xb2\xa6\xcc \xac\xd3N\xa9+p\x1eHo\xf9\xac]e\xba\xba\xb17\xb9\xf8<\xda\x8d\x92\x94\xbd\xc7D p\x03*\r\xf8\x8eCm\xacP\x8ac!M\x02-v\xd0\xb3"\xae\'\x18\xf1\xac\xaa\xed\xdeA\x98\x8dKp}284\xfa\xf1J\xd8\xbb:m\x8e\x138\xa1\x01\x12\xb4\x94\xb0\xa6\xf4#\x99\x95sn\xf6\xfb\xe7\xe5~\x9b\xa5\x94\x1e9ix_(\x8d\x16M\x19q\xf7U\xc3!\xb9\xae\xda\xd6\xe2QP\x85g\x133\x08$\x86\r\x9d\x9a\x1f\x84[\xaa\xf9\x0f\xa9q\x1f\x8c(\xea<4\x01\xf0\x87\xc9\x8f\xdeU9S\xf3\xd6\xc6\x02[\xaa#\xb4\xb4ks\xd0y\x88\x8c:\xbe[\xaa\xd9\xd6s,\x02\xeb\xe7Y\xda\xfa\xb9T<\xfd\xad\xec\xedwXz\xec^a\xe8\xfc\x0b\x10A\x8b\x06\x85\xe7\xaeV3\x91E\x0b\xb6>\x07\x88\xf2\xe7\xbb\xc7\x89\x1f\xba(\xb7y,V\xe9\xab\xbe\xb2\x19\x07\xbc\x03\x9ed\xf00j\xfd\xe8\x87O\x184\x0f\xa6 \xaf,H\xb9[o\x83\xee\xf6\xdd\xc6\xc5T\xf6\xe7\xce\xa0\xe6\x96k\xc7\xb8\x80d\xb7\xcfE\xbd\xe5o\xcd\\\xcb0m\xca\r\xca\xdc\xf4\xc6=\x1bB\x10\xdf\xfe\xf8\xcc\x8a5\x93&L\xf713\xf9\xe8$g\x94x\x04\x884\xcb\xd5\xdf\xfd\xcf\x01_&\x8b5g\xa8\xbc\xdc{\xdc\x01\xd4\x18\x1e\xc50\x13\x928g\xfc.\xefGI\x1c\x03\xb9\xb2&(\xf6\x8e\xb8\x16\xd0\xc7\xa9q\xed@K\xcb\xd1\x02Y\xb0\x0fN\x08\xb6\x90\xd4\xde\x88\x12\xbb\x9e\x83\x1b\x9d9\x91\x8eN+H\xbda\xf2+\xfb\xbe\xa27nM\xc9\xe6\x06\x0fn?\x01\xa3%l\xfc\xab\x94\xf2\xf2\xba\x8f\x97\xe4Z\xe7\x82q\xd0\x1cD\xd8y2\x8f\xe1\x91\x02N&}Mx\xe2\xd3\x01\xb3k\xda\xb4I\xe2C\xe2\x18\xbb\x8e\xe2\xd4\xa6[N\xe0\xc8\xbc\xbd$\xb1G.\xa3\xf1\xb9\x83\xeeT\xecb\xb53\x15}\xdfU\x03\xb5A\x1f\xbbn\xe0\xac\x0e\xed\xd5\x98d\xfe\x92Bh>\x89_\xa9D\x8a\x14\x7f5J\x19=X\xd3\xac\x9f\xa7\\\xf2g\x91s.\xd6\x8bo\xde\xb3\xe2e\xf0fY/\xb2m\x89*\xfe\xaf\x18\xfb\x02\xa6\x02\x17\x97\xec\xc9\xc6j\xcd\xdcs\x06\x13\x07\xdd\x97*\xbe\x8a\xdd\x03\xc1rP\xe2\xf9\xba\x14\x86\xa8\x1a\x8e\xa1w\x9c\xc3\xdd\x99x\xef{\x81\xae\xa0\xfe\xf9~\xa7\x1a\xbe\xf1\x9a\x11\x06\x99\x1d\xb0\x16\x14\x9fK\x8d\x04\xa8\x8a\x8a\x888U\x86\xf2\xf2\xf6y-b\x9d\xaa\x17\x8e.\x18-?\xe2\xed)\xd5\xac\xd5Y\xd1p=\x1eX}\xa4\x13\xeb2\x88B:)\x9cs\x0c\xdd\xffzvg\x97\xa1\xcb\x93v\x95@[\x90j\x97\x99\xc1BV\xa4\xde\xbd\x81h\xb64s\x9a)b\xbe\xfa\xe7\xc82\xf5\x06b\n\xb6h+<\'r\xc8\x12\x85,\xdb\xc5\xd4?\xf5]\xb9\xa0\x8eG\xfcY\xb4lnW~30\x12\'a\x0eA\x98=I\xddX\xd5@\xa8\xa3\xfd\x8c\x19\xfa\xbb\xf4\x10\xc9\xfc\xb5\x8cx\x1c~b\xb4\x07\x94B\x11\xc7\xe7`_\xdc\xff\xaf\xb4\xd3`\x02,c\x9aS\xd7\xd0\x7f\xb8\t\xe9\xec\x16\xf3\x93s\x1f\xd4\xe8\t\x8e\xfd\xb9\x86\xe9n\xd8\xb6\xffb\x85\xdd\xc7\xadF\xd7 \xe8\xaf\xa1\xa2\x1a\xdf;<Q|\x01\x0c\xc3\x8bW.X\xb7:\xe9y\x1fI\x89\xcf\xed\xcdMWKy\xa4\xc7g\xeb\xca\xf6Z\xe7\xdd=\xfbP\x8dF)\x88m\x81\xbe\x8cDX\xe7\xc5\x96x\x8f\xb7\xc6\xcaT3\xab\x19\x990Tx\x02\x7ff<znM$$\x19\xf9\xb0`\x91\x8e\x92\xdf\xe6\xcf\x8d(CD\x0f\xe1\xedW3\x9bG\xde\x08\xf3\xcd\x8fv*\xa5o\xa8\xe3\xb2d(\x17\xb7\xbf\x8f\x1e\x1e/\xd8\xc2Ip\x95\xc9\xaa\\\xf61l\x90\xcc\x99\xd0&S\xf7e\xb4\xdc\xeb\xb2\xe1_\xc4m\x9e\xfb\xf4<\xfe\xe7\x07<?2U\xef\xe8<\xbe\xf9\xca\x88\xab\x08Th\xb7\x92f\x04SGP\x9a\x7f\x1d\xf3n\xa2\xe8fA\x9a\x16BP\x0f/\xbc\xb2\xfd\xc3i\xe6\xfb\xa6\xd1\xe7.\x9a\xbb\xdd.\x8aK1<]\xb5ar\xcf\xc9\x80\x0e\xf1~}\'\x0e\xb2\x07\xad\xf5\x8c\xd3\xbb\xda\xde\xe79\xa1\x96Z\xc4\x11\x8a\x0f\x0e\xe0\xa5g\xd0.Pu\xed\xa3\x8a\xf4]\xbe\xd8\x13*q\x07\xe9\x14\xf0\x05?\x9b|\xd6\xc0U\xbb\xbc\x9a\x17\x06B#j\xfdw\x84{y*\x8cl_n\x90\xe8|\xf9\xf7g]6j\x06\xf5\xa3iG\xf32\x17_\xf8\xfcp-("\x00\x10\xc6\x86<\x87\xe0FW\xfc,\x7f^>\xd4l\xb9\xe56\x80\xc7\x96\xe1\x93d>\x8cU\xdc\x8d\x04\xc0\xe0dkZg\xef\x9b\xef`Z\xa1S\xcfZN3;]W\xf5\xd6\xd9\xe1\x95(\x17\xb8\xffm\xef\x82awrZ\xd9g\x05e\xca\xcd\x86M\xa5`K/\xe0p\xa7Z\x1a\xe1bv"\xb1)\xa0\xde\xc45\xc0\xba\x91\x1fi\xbe\x95\x85P.\n\x84\xadD&\x83{\x89\x9c\x82\xe8.K?\xaf\xc3y\xd3\x95\xc33\xffn\x97\x1c|\x02\xd36\x86\xbcAA\xf5\xec\x89\xae\xdc\xbe<\x975\xcb\xed\xfe\x85\xf5\x06\x0cX\xa2\xc1\xa4U\xbfci\xcc\x07\xa0\x19f\'=\x00\xc08/\xfb\'\xb5\x0f\xed\xbd\xd3\x9b\xb2%J\xf8gJ1\xf8>e+\xaa\xc8\x83U\xd5M\x1d\xc9\xc6\x1a\x1c*9\x12G\x91C\x94\xb2\xb2\x9b\xdd\x98\xd7d\x01a\xf4C\xcc\xc9\xd3\x10<\x1d\x1d\xc9h\xac\xaf\xc6\xbd*u\xa5x\x18\x110\x19\xfe\xbb\xd9\xb1\xa8>zv\xed"\x1e\xb0\x9aP[:\xacPKv\xfe1SX\xcc\xd9\x8b\x11\x14\xd58\x0c\x16?gr\x8d\xb4Z\xbeQ\x0f\xfd\x9a\x8e\x92\x08\r\x19\xfd\x18\x14\xe3\xdc\xf8\xb1\xcb\xa4\xe0\x84X\x98o\xb9\xef\xca\xa2\xad\xc6o\xd7\x86\xdf9\xe4\xaf\xff\xa7\x9d\xd9q\xa8\xff\x87\x13\xfb\xd9xL\'A]\xc8\x01\xfa\x94`\xa1\x85\xe5\x82\xb1\r\xa8\xcf\x11i\x10/\x9a\x96^\xc4\x1f\xfc\x85\xcd\x07\xdc\xf8\xa2\x98Uj\xce\xec<G\xb3\x1f\x14.HGtA\x17[\xe0\x90n\xab\xcd\xef}\xb8\xa7\xef\x8a\xbd\xa1W\x11\xdf\xa6\x10\x1c\x8e,\x99\x9bRp\xd4Z\x83\x08\x95:\nN\xb2\xbeR\x14\xc0\x93\xad\xe7\xea\x83\xd1\xb6rO\x11u\xcd\x07\xdfl"G\xcd\xaer\x8f9igx\x7f\xc1+\xd5\x06\xb9\x95\x1bT\x04\x8fWNt\xe2 \xa9G-6\xd7o\x05r\x0c\x9b\xb9t\xd7iMD\xc7\x13W\x1e\xda\x071\xc4\xbd\x8b\xf7\x84\x03\xa8\xc8\xbd0qk\xbb\xb9w\xf1\xacT\x04n\x96h\x91\x81\x06\x10\xc1[\xca\xa3\x8e{\xf1\xdf\r\rWU\xa5i\xc9\xbf4Hd\xbf\xf5\xd0\xf5\xb6\xbd\x992\xf0\x1a\x8a\x10\xbc\xc1;\x1d\x0fR\xf9\x9c #\xb90\xa8M\xd0\xa4J\x03Q\xd1\xad\x9aI(\xc7R\x91\x98U\xe4\xa7\x1a\xb6\xc9}\xb3\rQ\xe5:C\xd8W+g\xe2Wo\xe0\xba\xee\x85Z\xc7$\x96}N16\x89^\xd3\xcd\x1ei\xe2\xea#\x04"$\xed\xd3\xe5\xd4\xef\xc5\xf7\x80\xd9D\xf1\xa9{\xd0\xfa\xc6\x94\x1b3\xce\xfe1\x9d\xa9q\xb2}}\xd3\xb1\xfb\xc0y_)\r\xec\xe2(\x94{\x8e\xf0\xc4\xcbk\x13\x9a\x89W\x82d\xe1\xaf7\xc8\x12\xfa\x90\r\\\xb2\x88t\xd5\x8dS\xd8g\xcf\xf8\x9c,y&X\xccwwk\xc5(\x1f\xa8!\xa2\xa7l+\x8f0\x93E\xb8\xcd\x9b$\x01/_\xab\x8dX*d\xf1_\x124\xfd7\xf8\xe1\xb7F\x93|k9b\xc0\xdaU\x81\t\xf6\xbe\xfa\x15 W99\xbd\xd7\\\x99\xec\xd2\xf5P0V\xa5T$|\xb7\x84\xef\x0b\x8d\x14\xfb\x01\xf8\x99\x01\x17\xd1M\x81\xd2hT\xab\x016\xdc\xe2\xa0\xda\xc1\xca\xc38v\xcc"\xa4\xfdu:X\x93Tf\x1c\xb5!C\x98\xf71\xa6\xb6\'\xdf\x81s\x13\xb8t[S\x82\xbc\x04\xf0\x90\x88\xe3\xaf5-\xeb\x04\xc0\xfbT\xe4\x9fP$\x9e\xc6p\x0b\xd8\x1b\xd3\x19n\x14\x19\xad\xea\x9b"\xf7\xbe\x8a\x13VKqdA\xa9\xce\x9fh\x82\x91\x1fE\xcb\xe9\x93\x88\x05\xb3J\xd9\x15i~i\xda0rF\x16k\xfdd\xb9\xb1\xc7\xa9|\xc3\xe0&\xb7\x85I\xf3}\xd4\x1a\xb9\x94\xa8\x04IV\x15\x948\xba#\xb0\xf7;\xe2\xd2T\x91`J\xaf/\xf6\x01\xd7\xf1a\xce\x97\x13\xd2\x99\xd3\xf3\xb1\xa3\x02-s\xdc\x07/\x04\xf0\xd1\x8c\xcfy<sU\x8a\x10\xe0\xedI\xa7\xe9\xdb\x04k|\xf3Y\x03\x13V\xb3\x15\xee\xff\x9a\x07\xa7;y\xc3\xf0\x9ct\xa1\xab\xa2\xf6(_f\x9c\x03Nn)\x933$w\xd9F\xafW&\x19\xcc\xd3\xbc^r\nE\xd6\xb3\x8bcd\xdb\xad\xacX>\x06\xa18\x98D\x86\x83\xf7~\xcck\x87\xb9VE\xc0\x88\x12\xb6\xb3p\x8e+\xc1)\xb3T\xb7\xa1\xb1\xfa\xfc|\x9b&q\xbeQ\x87?@\x1c\x9bc\xce\xd2\x03\xa0\xcf\xae\x80Bk0Z}\x05G\xca/\x0b\xf5\xc7\xaf!\x02\xbe\xbb\x8d\x15[\xaf R\x95&F\xee\xe3.`\xf1\xba\x94VU\xa3z\x13\xd9\x81\xf6\x1c\x90jf~\xaf\x98\x83p\xbcn\xdd\xc4\xc1\xff~\x86\xe5\xbd\xc6\xd9\xd1\xa2|\xc6\xaa\x12G\xf3z\x8az\xfcot$\x0bOU\x99 \x88\x9f\xb1\x84*9\xb0d\x92\t9\xde\xbd\xaeE%\xebLq"K&\xda\xd4\xf3(h\xeb\xcd\x86\x99\xb6\xac\xcd\xc1\x0el\xa7Y\x04\xd3\xb5!\\\xc7d\xc1N\xdfc\xea2\xb3\x06\xa1 \xd0\xf7\x8e\xf7\x9d\xe6\xbcX\x87\t\xae\x11\t\x895\x90k\x12\xfe\x8a2\xf9\x93\xe2\xd9\xf7\x92\xfa\xbag\xec\xd2\xbf\xbd\x8a1\xd7c\xc3a\xf1\xce\xf9A\xe11\xab\xc1y\x15@\xc5*)\xcc\xadh\xeb\xc4\xf9\xfb1\x98t\xc5e\xf2\x9b\rgwN\x88\x91\x85\x90\x1b\xb5\xc73MN\xe8<\x0e\\\xc5\x8e-\x8b\x17\xbagD\xd4\xda\xb4\xbdp\xbd5*\xa57\xfe=k5\x92\x83\x84\x83\xd18\rUrHL\x07\x7f\x8cW\xb3\x07\xeb\x88\x0b\xbbl7d\xc1=~\xb9Z\xe2\xa4\x8d\xea\xe1\xb0w\xec\xea\x85\xc5\xba \xbbu\x0f1\x9aMX\x9by\xd72\xb7q\xcc\xe8P\x8f\x95C\xdf\xf04\xc86\x908\x97\x0f\xd4\xd8\xa6_N\xc7\xea\x17\x05?\xdft\xe2\x13I\x06\xaf(\xed^\xdf*\xddq\x95\xb7~\xacs\xab}\xc9N\xd3\x9d\xd97\xfby\x06(\x0b\xd0P\xb8Oe\xadR*\x96\xd5Im\xf6\xc3\xdf\xd4yg\x15z\xabN%BK\x89\x90_41\x15^3\xfbb\x86\x9a!\xb5\xf6?\xc02\xb0\x8d\x1e\xa8.\xf1h`\xd8\xc3\x9b)\xb5#\xd2x\xa9\x8d\xfa\x9cT\xbf}#\x19\xa6\x9fMa\r\x88\xb1\tY\x84\x08k\xde\xf4~k\xaf\x93\xd5\xdd\x96\xc3\xb7R6t;\x05\xc6\x93\xb3\x00\xc6\xe3?\xe3\x89\xf7tE\x18\x96/\x81\xdasl\x1d\xe6"-\x1a\\<U3\x1c\xa39\x04!\xfc\x7f\xde\xb69\xc1\x11\xb6\x1d~R\x8aiu\x18)\x9e\xd6|e;\xbcQ\x00\xcbK2\xfe\x87?\xb6\xb2^\xf0\xc3\x05>I\x04\xd5\xdc\xd1\x07H>\xbfp\x1b\xe7\x13u\x1aH\xc8\x98h\xf4\xc8\x1d\xe9\xe7\x00\x05\x8c y\xde\xf7`\x19\xc0!C:s\xd3\xa6\x0c\x17.\xb8\x8c9\xd0{!\x0b\xee\\\x1f\xf1\x15\xcc#\xe3\'\xd6[\x88\xfd\x0b\xc2\x02p,\x00\x9av\xc1\xb1\x08!\xb8<\xda\x1f\xd0+$\xe9f\x84\x9e\xbe\xca\x11\x1b\xef\xb0*\xb2\xd2\xee3g\xebs\x0f\xa4g\x05\xd5Nn\xba\xd2\xa1\x7f\xd8\x90S\xf0\x19*w\x9a?\x8f\xf2\xcd\x1d\n\xdf\xe4&\xfc\xb1v\xa4\xbav9\x80+Pe\xbf%&\xa3|\xa0\xd4\x81Tu\xa1\xc98f\xdef\x07\xa4\xc9@*\xf8\xcc^\x06">n$\x8d\xb8*"\x16\x14"\xdd\x89mM3\xdac\x99\xf8\xd9P\x00\x8etC!\xfa\xd9\xc5\xd7\xf0\x95)\n\xc9\xae\xabh\xa9\x00oTP<!\xa1\xd2\xf7k\xb7X\x8b\x12`\x7f\xa6\xa19\xef\xe7M\xfe^\xbe\xfat\xf5\xf2$;\xd3\x97\xadz\xb3\x8f\xa0J^\xdcs\xd2\xf2O\x0e\xfc\xe0\xa8L\x1c\x17\x03\xbc\x8f9[\xa9F\xc2<cj\xe4>\x1e\xc0I\xc5R\x17-L\r4\xc0J;\xb1\xf6\x7fh\xac\xb3\xf8\xec\x1a\x9d\'\xed\x94 *\xf8v\xda\x17\xe9r#R\xf8\x10\x91\x85\x17n*D\xa0\xae+\xdfW\xfdR\x97o\xc5|\xc8\xa9\x80\xed2\x9d\x00\xd3*\xe0\xdd,\x1d\xa8\xbe\xc8\xb1$@W\x97([\xee\xeaN5\xc5\xf3@\xe0\x00\x9f\x91\xd8\xd2~\xcc#EVN\x8e\xd4\xa1]!vY\x04r\xa3%Y)\x87\xbc\xcf\xa0\x0b\xae\x10\xfbY\x1dK\xb4\x90\x1b\xce\xfa\n\x98=\xd07\x87?:\xf1\xa80rs\xec\x9c\xe6\x14#\x14j*9|A\x9b\xb7\xf9\xe0\xb2xh\x99X\xc3\x89nm\xb8S+\xac\x88mM\x0ct\xdc\xe1\x80\x13\x13g\xf1\xd7\x17F\x03C\xac\xe3w\xac\x17 \xd1\x99\x0e\xe0#\xa5\x02\xdd\x17\xbe\xac}\xcfTK\xf0\r\x8ar\xb6\x1e>) \xd8\x8f\x83\xcf\x0ch\xefm\r\xe9\xd1a\x02\xd5\xd8"\x02\x1cN\x84\x99\rD\xee\x97\xa4i\xcf[\x1b\x87Bc|S\x8c\xc3p\xdf\x1a"e\xb3\xf0\xfb1c\xb5\xf1h\xe7\xef\xden\x90\xa6\x87\x95f\xfd]\xdb\xa8\xe8a\x81\xe1/k\xf3\x87M\x9d\xa8V\xb5?\xd8k\xd3\xeb&\\8$\xfb\x1ayl\xcf\x83\x11\xe8\x91\xab.\xb1\xf6\'\x97\xa1\xb7:\x03\xbe \x9a\xdc\x12\xd3\x16BA:{X\xd6\x0c\xdc6\xb2\xd2\x97f\xa9;}q\x14%>N\x05O\x88\xe51\x12\xc2!\xdf\x80\x1b\x8f\x0f8\xfe\x07\xd8\x1e\xc6\x91\x07\x8c\xca\x1a\x81V\xf2\x9e\x92\xed\xa7\xc1\\7]\x7f\x93\x84\xe0f\x0cT\x84\xf1\xbf\xa7\xf0PD\xa5\x8dz\xbbV1\xc2H\xd8;\xc4\xb6$\xe2\n:\xb2{\xda\xc4P\x15P\x04\xb6YW\xc8\xfa\xd7;6\x8e$\x8c&Q\xc0\x93\xd0hu\x89\xae\x17\xd3\x86dI.\xab\x02Rk;\xcbI\xa3/\xf8\xde\x9cdMP\xa2\xa3\xd6\x82\t\x1cy\xdd\x9f\xb7~6{\xec/\x01\xc3Xlo&P\xfdi\x7f\xbb\xfc\xa0\x12\xd3\x14\xa4\x96\xbd\x9c\xb0\xc7\xd4\xe3\x05\x99$\xc2\x93\x1d\xcb*\x92\x9cg\xdd+U\x94\x9ek\xbb\x7f\x96e\xc8XHE\xe2e\x0e\x07:\x91h\x1aj\xda\x07L\xa5E\xfb\xea&\xa7\x9e\xd2\xac&x\x01z\xf6\xec\xfe(\x8e)\x18@C\xfa\x1fn\xc3\x18s\xae\x8bK\x05\xc6\xb8\xd5o%\x0eW\xa9j=WE\x11"CK\r\x86C\xbe\xb70\x0b\x01\x8f\xa7V>\x1d\x04e&\x82 \xcc\xa3Bj\xa8\x13\x85\xa9\xab\xa9\x98\xacs\xa5D\xa4\xa5\xa9C\xef\xd0\xea\xe2\xb8\xae\xce\xfb\xc3\xc7k\xb4\xca\xe0}_\xf6\xbb\x98L\x1e\xce>\xea\xc4\xbf\xbfH\xde\x11%$!\xec\x12\xfbC\x13\xe7\xff\n\x8c\x95Q\xeaX \xa4`\x0c\xe4\xc9f/\x8e\xf7\x18)\x15W"n\xb6\x99\x0e\xd9\x04J\x9e~:>\x1cH\xc9%\xf8p\xf2H\xd8\x94\xc4,T\xfa\x152x\x1a&\x89\x82t3\x16\x87\x8f\x99Xl~\xd4\nR<\xf7[D%\x1c\x99Z\xca\x98\x1d^!L\xe6rN\x90\xdf,G\xb2\xf1\xef\xd0}|E\x89\xd9`\xb9H\xe0\xb7\x89%\x0f\x18_\xf8\xff\xa5\xaeX\x98\x18E\xa3:\xb8\xf6\xf7\x02S\xae\xc7\x9c>\x84F\xfa\x1b\xbf\xeb\xde6z\x01\xda\xba\x18\x886\xcfi\xc0X/\x12\x85\xb0\x99Z\xd8$W\xdc\x8e\x8c;\x89\xc2\x17\xbe\x06{l?B\xe9A\n\x05O\x07\x86\xe8+X[\xd7\x89\x8d8}\xf5\xed\x9eK\xf1\xd6\x03\x11db\x06\xa8h\x9cyY\xe0\xbdh\'\x89ax\xbe\x9d\x15\x08\x0c\xf5\xd0\x05\x07\x11\xf7\xfd\xe0\xc3\xb8t\xce\x9c\xb1\x98\xc5<\x10FE!{\xce\xcdn\xde\xd7\'i0\xe68\xfb\x81\x8b\x86\x1f?b\xf7\xe9\xf0\xc1]\x92\x9b\xea\xb1\xd5\xc3\xda\x11k\xb9\xb4\xc1%\xde\xd6a\xc7g\xe2\\\x9b\xb1H\'.2\x93\xc3=\xed\xda\x84\x104\xe1\xa9~\x06i\xeb\xa9\\\xf9\x8a\x93.\xc2\xaa\xfc\xeeuE\tH\xf3\xd8\xb2\xd3\x01\xc7\xb2$\xf7\xd1\xeb\xf4\xcc\xebV\x92\x81\xf3_\x00\x96x\xd0\xe4.i\xfe-\xe9(y;\x19\xd8\xc1\x9d\x05;&C\xe6@\x12\x1by}x\xd34*\x86\xe9\xec\x9c\xd6\xc1:\x12$\x1d\x85\xbf>\x9c\xef\xb1f\xe7ofg.\t\x1e\xca\x914R#\x16\xc3C\x1b\xca\x19\x04\x91\xa5\x9c\xd9J\xfe\xd5\xb3\xb3:e\nfS\xfb\x9c6\xefg\x19T\xe7\xbcm\x80\x8bz\xaa\xf7\xe5H\xab\x04\xb7=\xe3\x1d\xe1)\x86\x19\xa3c}\x826\xbe\x90\x04\xd7C34\xa0\x9dh>\xd0b\x87\x1eP\r4\x07\xfb\xd8\xc8\x7fy\xe2!P\xbc\xdb\x05s,\x8di\xc9\xef\x19\xa9\x0bA\xb7\xcfe\x8d\x00o\x96\xe6u\xf1\x86/\x97\x92\x02\xb6\xc8ly\x95\xe6\xe2\x9b\xfa\xca\xd1\xd8\xb4\xc1\x19\xd7>\xca5\x14\xc3\xea\xad *\xb9\xbcv\x1a\x07\xb0n2\x92Q7n\xd64\x8d\xc2q5\x0b7%\x04\xc8\x14E\x94\xc2\xdd\x87x\xd0\xa4\xef\x02\xed~{\x94Z#pV\xef\xad\xa4/\xb2\xf8\xaf\x8d7\x8ceS\x0c\xf4\xd8\xd5\x19\xbdJ\xf8\xab\x8be\xda9\xb5\xbf\xe2\xf9\xa0aR\xfe\xe2\x8e\x8cv\x05\xe7*\xae\xbc%3\xbb\x1f\xe2\xd96nP\xce\'\x16\xa3\xfa\x86\xf3\xa13\x98DZ7\xae\x9f*.Dh(\xbd\xc8\xb7\x82\xcf\\\x10\xe3\x1e\x0b.\xa8T\xdd5\xfc\xaa\xb1}z{y\xd3\x92\xeb\\\xf6?{Ou\xde\xa1\xf9\xac\x9eB\x91\xa6\x96\xd4\'\xffE\xb8z\xeeq\x93}\xbb\x1e\x97/\xd4\xd1\xe9R\xdd\x16\xa6a\x0e\xd9\xb5K\xfb\xab"\xbe\xe7 \xb0\xb5\x12\x07;\x01\xdc\xfbG\x10\xb6i3\xd9}\xc0^4j\xc9\xe7{\xe1\xdcs\xc3\x8f\x10\xf9\xe2<MEj\x10\x8d\xd0\xca\xa2\xda\xb8\x8e\xd8\x07\x93\xd3\x0c\xe0j\xe9;\x9b\xa1\xf7\xb0\xf0\xe7o]\x19\xd1H\x02\xd1\xe9\xb7\xe0\xb2^\xaaCTQ\xc3\xef5yM\xf9\x89\xbd+\xa8\x14C&C\xfa\x92\n\xe1\xd0`\x88>M8\x89k}\x8f\xac<\xf4\xe5\x91\x1c\xd0\xd0E\xcc\xe4\x90\xc3\x80\x8e\xbas\x18\x9e\xe0\xdbp\xeb\x9f.s,\t\xe9\xda\xf8\x19wm\x9b\x0c@\xb0X\x01\x83b\xbd\xd23HdCOL\x9b!Z\xa3+H\xacBs\xff\xe2\x08\x0f"\x8cA\xfe\xf9m&Ws\xdf\x05\x1c\xf5\x9d\xe0\x97\xe0\x15\x01\x9dj\xc9\x12\x16\x19\x92\x8a/\xbf\x05{Ov;\x12\xb6^,\x12t\xeb\xdc\xbd}\x11\x1a\xc6\xbc\xc3X\x84\x08\xf3j\x92\x81Ff\xca*\xfc\x17\xc0\xa6\x19\x1a\x1eMaV\xc27\xfe\xc2\x7fy\xb2\xa0\xd3\xff\x86\x9ci\x1a\xb3)\x07\xe8\x1dp\x91\xc7\xb7-\xdb\xc5\xf3\xa7\x048bN\xd9\xfeMf\x8fU\x94\x01\xa0\xee\xf1?\xf6,\r\xb0\x87\xf4l\xb3\'f\x06G\x01\x16\xab\xad\x8dg\xb0E\xa2t?\xff>91\xd1\x95\xfe\x82l<\xb6\x1a\xb8\x96f\xbe\x9a_\xa9\xa5v\xb3\xfa\x7f~&\x03\xe2\xb6e\xbbk@\xb8\xf3\xfb\x01\x84\xc6\xc1K\xc6[4Gt\xae\x85\x07\xc7\xf4\xd7=\xf2\x94\xf1\xd5\xefv\xb6L|\x05\xa7\xbeZ\xfaa\x1d\x861Wtu\xc5\xde\xbb\x95^\xccv!Aa\xd5\x91\x9c\xcfP\x9btkH\xf6\xbf\x05\xbaD\xba\xaf\x82\xa7\x02{\xced^\xa2\x06\\\xdf\x92\xce\x9e\x99*\x84VVT\x02\x97\xba\xc1d\x19\xb2S\x02\xaa6a\x16\x058\\\xce{\x0e\xa2\xc0\x9cDa\x892^\xf6\x86\xe0\xe8\xc0\xae\xef\xd0R\x8d3\xaa!\xebr%\xb6Q1\x9b\x1a\xc7]U\xfd\x84\x88\xd9\x12?\x8f\xdf\x1fd\r#\xcd\xc2\x87\xfd\x90\xe1\x9f9P\x0f\xb6\x92\xa0\x80\xea\xca\x0f\x9fk\xe0s\xbf\x9a\'\x95\xec&\xcd\xe1\xac`\x9e:\xef\x0f\x0ct\xf9KX\x1d7\xeb4\xa9>\xba\xe5\xd4\x8a\xe6\xb8\x9f\x84\xf1\xb8c\x8f\xaf/\x00\x84\xb0a\x90cZ\x85\xe0`utt\xd2\xc2 \xc67\xba\xc6I\xa9\xb0\x0fSg\xf2\xebox\xab\xd9\x8c\x9a\xad\xdb\xe6\xff\xcfKCej\x96\xeb\xa0 \xf9\xc7\x91p\x137\x80Ki\x82\x97\x8fL%\xb7[\xd9\x82\xb0\xb6\xbd\x0c\x86\x0c\xee\x90<\xd8I\xe7M#\x9aj\x9d\xcc\xf4\xb7\'k\xc5\x13\xd1\xa6\x85\xa3\x84\xf2W\xf4U\x99\xc8\x12\x8ehk}\x81Pl\xd9\xcb\x05\xfb\'\x1d\xd5\x93{X\x9d\xf8\x95\x85\xefy\xc2\t>\x8e\x95S\xe1\x9az\xac(\xb9\xf6\x82\xe9\xc1\xcc}\xbc\x8e9\x8d\xccNn:\xdb\xba\x1b/\xd24\xcf}\xa0\xdc\x11\xdb\x0e\xbb\xe9\xa2p&\xc8\x85\xbb\xf5\xbd\xb7\xc9f,2E/\xc7\xf6\xe2\x1b\xed\x15T}\xc0\xf5\xb8\xd4\x7f\x88\x08\trJ\xeb8\xa4\xd3\xbf\xc0G\xc5\xe8&x\x1a\x1f\xa0/\xc7#\xee\x87q&\xe9a\xf3\xdc\xc2\xbbs\xac\x1a&F8\x86\xc9\xf0.?\xb8\xb3\xc54\xb8\xae\x0c0\xf7\xf4z\x90\xb4)\xbeS\x97\x8e\xd4h\xd4Fx/C\x04\x1a\xe5\xdf\xef\xddx\xed\xa5f\x00\x18\xb7\xad\x14\xfa*W8\x11\xa8\x0c\xffs\xe4\x9f\ra\x16\x0bXh\xfcc\x11\xb8xW\xb8\xf4x\x89\x81\xbb\x85\xa3\x7f4)\xab\x8c\x92\xfb\xb4\x15\x0c\xa8\xa3>\xc6w\xcc\xa9O6\xf3\x8b\xe8\x13&\x93\xe4\xb8^j\xab\x95\xdeW\x9f\xd35\xa7\x8f\x1d\xb6Z\x1aY\xfe\xe7=6\x87\xcf\x9d)\xc0\xcf<v\x86\xd3\xf9\xf5p\x05\x05D\xdf\t\x8eM\xbd$\x96\x12\x98n\xb0\x04\xe4\xe8K\xc2\xfas\xb2{\xdc\x8b\xb2\x17g\xe2\xaa\xeb\x9e^\x86\x84\xf0GU.\xa2\x90^\x92\xf2\xe8z\xa2\x97\xde^N=\x92\x12`b\xc95\xec\x0e@\xc4\x08\xe8Y\x0c\xa93\x87\x8c`\x11Jc\xc0}\xaeY\xea\x8c\xb1x\xf8R\x07!3;\xd6\xeds\x1a\x04\xbc\xbb\xb7\x1dp\xd3\xcaB\x08\x8a\xa53\xc8\x06Z$\xb4,\x83\xa2\xf5Iv\xad\x997CV\x16#\x8c q\x02\xf6`\xcf]\xc1\xd5D\xa9y\xb0\x11\xe8\xaf~J\x1bF2ID\xd6g\x9d\xb8e\x08\xdd\x86\xda1\xac\x93F\xdb\xf5}\x9c\xee_\x14\x0f\xbc[\xa7x\xdb\xe6t\x96\xcd\xdfS\x82>M\xcfj\xfa\xf1\xe5\x99\x1a\x8e\xcd\xef\x15\xf32QP*\r\x9cy\x17\xb6^\xf6r\xba39(\t\xbf\x831\xd3S\x0b3\xa0J\xec\x0c\xd2vh\xc3\xa8\xdf\xbb\x17\x91\nD\x8a\x19Z\xa6\t(|Z\x03\xd0\x18\xb32\xcf\x85\t\xf9S\xe3\xe6\xc0\xee,\xf1RAq\xc6=\xe4\x1f\xc8\xc4\xa5\xf7\x86\x99O\xfcM\xdc\x0c7\n\x82\xd1<[\xac\xd4\xc5i\x11\xaf\xc9\xef\x03b\x86O\xad\x9d|)\x81\xfdg\x02]?\xab\x86,\xbei\'L\xbdub1:&y\xc2Q\x95i\x08yBa\x81\xef\xf6l\x1dy\xf7a\x93\x80\xe9\xe9\x1c)\xd7\xf82\n\xcfV\xf0\xfaj\xc3zDm`&\x13\xddgj"\xc83\x17\xbd\x03w\x8dW\xce\xc5X\xab4\xb9\xb4\xbb\x9e\xd5P\xc88\xd0\x18\xfe\x97\x0f\x14<H\x94\xc0\x0b\xd6\x01\xb3\x85\xd1n\r2\xd4m\x14\xf9\x1c\xfbv\xcb14\xc1]\x072\x82\xa6\t\xb7\xda\xf5\x0f\xc1k\x15De-\xf6.\xe6,\xc3y\x8e]\xc4\xca\xfd\xd4\xb4\xe5\xcf\x9b\xae\xd53]\x19\xf7\xf6\x8c\x1f\xbc\x81\xf3(T\\}{\x8a\xec.%Bp\x0c\xb0\xe3\xf1H\xe5\xb3\x00\x05Z\xce\xb6/|\xdb\x7f\xd5\xca\xe1 \xfek\x13!#\xa1\xd2\xf6\xfeeG\x82\x151\xefa\x90im\x0cr\xc9eN\xae\xeaz\x85\x8a\x10(\x9f\x94\x1d\x83Q\xef\xb2\xcc?\xac\x11\xd14\xae4g\xda\x95\x11L<\xbc6_\xc9_\x04\x06\x8e\xc80\x1b\xd5\x19O\xfd\xd5JI\x19\x9d\x7f\xfa7Xw\rz\x1d\xc0n\xe7\xed$#\x1e\xda\x81i\x89\x90\x119\xdc\xca\xfee\xe5,\xa4\x86\xfe\xb5\x0f\'\x12\xf1\x1e\xe0\x01IT\x04~\xf4}\x99\x16\x13\x9e\xfb\xd1r\x81\xc0\x81s\x88\xffVc\x93\xfb\xedx\xe2%\xc11\x95\x7f\xb6IO\xec\x99\x18\xe6Jc\x9aa\rg\x83\x8d\x12T\xad\xe8\xd3C;o<#\xe5\x86\xe5~8j\xddRp;\xb9d{\xdf\x84\xb0\x1b\xfa\xfal4\x96\xdeQj\xa7\x83*f\xf3{\x00\x18R\xf4\x02\xd6."f$&\x8e\x8e\xe3\x15\xa4r\x87Z\xf3\t\xa5\x94R_\xd8P\xdf\x0b\x98\x95\xf77D\xe5\xba\x10\xd5\x8en\xa9\xd4\xbb\xf2t8\x99\x1aX\xaf\xc7\xa6\xe0Ek\xfb\xdfH\xa2\xa7o\r\x86}\xfa\xdbf\x9f\x19\x89\x1cV\xfdT\xba\x8c\x90s\x13\xa5B~\xbc\xecSt3\x13|ZLr\xe6y\xb3L\xb9\xc8\xc1xR\xea\xda\xeb\x9a\xdc\xee\xf3N\\c\x0f\xe1\xeb\x1c\xef\xb6\xee\x8f\xbc\xd0\xde\xf5\xf1Y\xd2\x10?\xcc\xb1d\x966\x99\xebq\xdd\x9b\x87\xf6\xc9$\xfb\xe1\xd3\x80F\xb7\xea\x8eF\xc5\x88\t\x83\t\xd0-\x9f\'\x08\xcf\xc9uN]} C\xf0\xcf7r\x8d\x1b\xe9\xa5\xea\xb9\xf8\x07\xe1;U\x16\xe0\xf2\xb5\xd0\x83X\xd3\xf7\xe4V\x9b\x1d\xb1\x0c-4\xbf\'\xeb\x07Q\xdc\xe8r\t\xde\xa6\xdd\xf3u\r+\xb0\xe4\x8a\xc5zA9\x80\xfd\x1ez+\xc8k>y\x84\xba\x1e\xff8\x04|WEo\t\xb8\x82IRq\xd3\xa6\x1c\x06\xf5\\K\xd9\x9bvG6\x1e$i\xa5\xd5\xbc\xaa\xc8kx\x19\x89\xf4\x95\xd2j\xac\xf9\x08\xb8\xe0SPeg\x04@\xce|\xa3\x11\xe3\xb6\xce\x07\xde\xfd\x0e*\x9b\x1d{\x07\xa1Z\xfb<1\xcc\xf2Hch\x9d.st\xc8U\xff+XlT\xbc\x14\xaf\x01O\x89k)\t\xdb\x95\xe2\xb0\xb2t2G\x00\xe5a\x80Z4k\x1a7\xcf\xd0e\x95\x9c\xf9\xa0=l\xe9\xaa\xa4\xd1c\x0e\xa4v\xa8\xed\xc2\x93\x18\x8e\xa3\x06\xb3\x8f\x8ef\x94(\xccep\x1f\xafH$v\x90\x9e\xb79\xa4\xcd\xa2\x9d\n\x94g\xf4\x835\xbf\xe4\xa2\xc2\x84|\x1f"\xb8\x99muz\xf0i\x0c\xba\xcb\x13\xcf\xb0Z\xcdD\xaeGI[(\x8b\xe1\x088\xf7\xfeI\xd8xU\x9c\xc4\x0b\x99\x0f\xb7\xfa\xdb\x975j\x93$1\xe5\xf0\x8e.>\xe4\xceTc\xfc\xb5\x128\xd6\x9eM\xb2M\x06\x0eN\xc3\xef\xac\x86\x15\xe5\tz\xcb\x16[nT5\xfb\xd4\xe5\x85V\x8fD\xec!)\x8e:7\x9d\x9d@\x94\x9a\x84p\xf8B\xcc9\x8d\x0cpor\xd0\xbfU\xc0L\x16\xe9ZY#\x1bH\xc8P\xa4\xe2<{\x0cq\x9f\xfd\xc3@A\n^<p9\xd29\x01F\xda\xf1\x80\x89\xe7\xf5\x9c\xc7\xf5\x7f(\x0c$\x81 \xf3\xf9g\xdf.8\x06\x190r\xda,\xef\'\xaf\x19c\xeb\xcasE\xa0\\\xc7x\nD\x91\xcd\xddv\xc2\xee=!\x93i\x7f\x87n\xb3Hz\xc9y)\xdc\xc2g\x08!\x952\xa6\xfb\xaa\n\x94\xa8\xa8\xfa\x14\xfa\x8b=l\x86*\xd7h\xc6\xaf\x80\x07\xeb\xa8\xdd_=\xfc\x07\xd0&\xcd\x7f9\xa2\xb4\x94\x1dr\xf8\xb2\xb83\xf0\xda\xf8\x10\x9bP\xa7s\x88.%\x99\x9a\x9d L\x1e[F\xe6:\x06\x8c\x00D\xf6]\xc6gi\xbf\xbc\xbf2i\x05=\x10I:\xcb\xfe.Z\x9b<\xaf\xf1\xcc\xb45D.\xd5Q\xaf\xf1\xb5"i\xea}\x81\x14+Je\xf3Z\xf14\xb4\'a2\x03\x08~P\x92R\xc85\xc3\xb3h\x02\x99E\xd7\x86\xa6?Y\x7f\x9b\x90H\x00LI\x1fo\x9a\xb2Z-o\xb5Sgjw.\x89\x8e8\xd80\xfe\xf3A\xe6\x1b\x9d\xb8f-\xb7\x7f+\xe4M\'\xd5\x17\x82\x12\x85\xf9\x16\xc0\x86\xd9b\xdcap\xf6n\xd1Ss\x00\xda\xb32\xf5s\xda=\xfa\xa1\x18\x047\xd5\x1fO%B\xb6Tl\xb9\xb70\xdcb\xc7u\xf4\x85\x98|\xa7(]\x84\x12E\xf4\x8b_\xcb\xc7\x18\x92\x1eu\xd6S\x95\x14@\x85\\,?\xe3\xb2q@\xf9J\x97w\x81\xbb\x8c\x08l\x86\xbb\x8a\xe3\x11\xe1\xf9\xdb\xab\xbd \xb0`\xe1b\x03\xb8-\xf9\x9e%o\x10J\xf7\xac\xb7\xd1\xdd\x1dYC6\\\xb1\xd8\xc9\xaf\xea\x14;\x1er\xfa\x17MiN\x80m+\xd3\xb3\x14\xf1\xe4g\xed\x17\xc8\x90\xab\x95\xacW\xc7\x12\xd6\xd2L\x9c\xee\x9bi\x17\xc9}f\x9e\x12\xe7?\x9cz\x90<\xafJ~?\xcf1\x98t\xa2\xfd\xacL8N+T\x956\xbd\x8f\xe4 j\x0f\xc4\xb3\x95\x8b=Qw\xe8zW\x1fUQfX\xc6\xaf\xc4\r\x9e\xbcr+\'\x19XN\x06\xbf\x06\x98\xc5\xc0vT\x0cf\x11\xa0\xd9FG\xb8N\x11\xd76\xd0C\xc6%_\xd0\xb0\xf9\x02\xf3\xa6U\xe4\xe9\xe0g>\xe5!#\x16\xdd\xed\xe1G\xde8S\x0b\xc13\x96\r7\xf2\\\xf5\xc5\xf7\x173ny\\\x0cWH\xa2B\xa1\xf3f\xca[K^7:\xd94\xdb(lN\x9b\xdd\x8bd\x80\x9e%\xc6\x025EJ\x0b0\xf9\x9d\x0fEig\x0b\xb6\xa6`}k\xc5SX\x0f\x8f~\xc0\xde\xae\xb1v\xb2\x86\xf8:\'4\xf1\xf7b\x9b\xf5`B>\xad\x8b^\xce\xf4\x1b\x8b\x8f"-\x0c\x1f\xf7\x93\xc17\x12\xb2`\x9d?2 \x137\xc4L\xb8R\x81\xe5}%}\x80s>\xcd+\xc9\x0cBL\xa1c{\x9e\x02\xc0\x85\x95^y&\x1e\x82o/\x8aKZ\xec^<\xbe\x13\x98\xe6Cq\xc8\xc0\x0f\xec\xcd\xe5\xff7w\x1d\x02\x992\xed\r\xa1\xcbV\xa1\xa1\xc3\x9e!/\x9a](N\xa1\xb8%\xbb\xe5\xa7\xbf1\xf8\xca\xde)!\xcf\xd0\xf5\x19\xbb\xc7+m\x94\xdep+e\xeb;w\x8f\xa1\x06 r\xe61\xf9\xe7p;\x87\xc2\ti\xcf\xec\xc1\x08oFMx8\xdd\xe3^Y%1\xef\x90c\xeb#Y\x9a\xba\x94[\'\xc7K\xceR\x13\x1e\xe6\xfc\x9c\xfc\x0f\tS\x91\x08\xec&\xbdt\xa7o\x98\xdc\xba\x164\xd7\x84\x9f$~q\x93\x81@\xe0\xfde\xdb\xd6]\xb2\xcc_p\nR\xcb\x95p\x92Z\xa2\xda\xa9\xcc\xf9w\xe1\xe0\xc7\x88\xf7_/\xd5P\xbeZ\xcf\xf7\xb6\xa9\xc8\xfb\x032t\x1a{\xbc\xb9\x90\xa8\xedI59\x82z\xcec\x9eKc\xf5>\xe1\xc1\xa6-\x0f\xf8\xb4\xe0<\x896\xbe\x84+EP\x07is\xde\xfa\x8f\xa5\xb4\x8cq\xc2\x93K\x08A\x1c\tQ1\x94\xac\x82gm\x9f\xd1\xf2]S\xc9\x12 \x8c\x1d\x90\x88[[\xe5v\x83\x8c<\xe7\xeb\xdf\xbc\xe4\xa7C\x9d\x1b>\x1a)Pgq\x9a\xc2\x82\x8d\xce\xba\xf2(o\x88\x1e\xa9#\xb5\x10\x86\xb9\x81\xd4Z\x87\xa4L\x1e\xaf\xe8\xfa\xe6\xdc\xa2;\x02\x14\x85\xb6G\xc8#\xb8lA\xf7\'\x92\xd8\xa5\x1e\x885\xd5\x19\x9f\x8a9\x0c\xccqb6\x08\n\x12\x8fn\xf2?\xcf\xa8:ey\xa7&\x91\x9fO~%\x8e\x94\xb4\x85\xbb\x97\x0f\n:\xf4"W$\xd6\x92\xd3a\xb5\nD\x93\xae\xf9\xbeM\x8b\x95\'\xa5\x98\xd2\x84\xe5U\xc6\xc3\t\x1e\x19]\x1d\x9b\xd71\xadZ\xb6W\xe6Q\xb60(\xc0\x8c\xedjc9\x0c\xaa\xbcER\x00\xf6w\xa1o^,\x1e\x19\xca\xe3\x0f\x04j/\xc7\xfdc\xab\xc0\x14n"G\xa9&\x00o\x0b9}\xbamn[\x02\xea]\x0bL\x9d\x85\xbb\x86\x0e\x96\xf0\xef\xeabc \x1f+\xfe\x83\xb3M\x1f:T\xd3\xf3a$\xac\x87v9Wd#\xd5\x1c!\x85\xf5\xf5\x05"\xc2\xf0n\xb2Z\x1d\x18M\xac\xd3\xeff\xac\x11B^T.m\xaa#$\x81_\xff\xc8,\xd4\x86\xe7f<\xb6\xd25v\x06\x10\x99\xae;LS\xe2\xab\x8d\xdf%\x1f\xaa\xe1*.\xb04\x89\xb8\xe0]_Xx{K\xfa9\xdd\xd2_\xc8\xf3C\xc1\x13\x91\x15\xa0\x11a\xac\x97\xa0\x85\xbeu\xeeN\xde\xf8BWwO \xfb\x10\x03\x1eg\x05r\xf2s\'\xe3F\x04\x83t\x17\xac\xc9\x17\xd9g\xcfEE=\x16\x15\xd0\x97T\xc9@\x02\xc1\x96\xfc\x85f\xb6\xd6\xdeKp\x9cv;\x9d)\x12\xa0\x16U\xbc\xf2J\xaf\x08D\xdf\x1e\x85\xf3\xe5s\xd0\xb6\xa1|dL\x95\xf0\xff\xbd\xa1\xb6\xa2\x16\xf4\xb7\x9f(\xcf\x05\xbc\\\xbc\xa2\xbe\xe8\xba\xd0\x18\x14\xc1\xe5\r\xeb37\xb8m\x0b\xc7\x07o\x14b1!<\xd1\xc9\x93\xb7w\xf5s\x05\xd4\x13\xc0Y\xef%z\x96\xb7\xc3k\xf4\x99\x19\x0eK\xe2?\xa5^Kt\xca\xa6\x16\xb6#\xefM\x12rO\xe4d\x8f\xef\xc7\x0b\x1e\xcdR$\xfe.w\xc7\x12\x8b\xe7\x92L\xc3\\\xfb\x06C"?\x0e0p\x8b\xcd\xe5\x7f\xa1Q\xa9\xd9\xa9C\x90\xb4`\x84\x18\x1f\xdfo\xa4v\x86\x94l\xa5\xb2\xa7\x97\x1ck\x88\xa4"\xa7\xb1\x9a\xafX\xadc\xd4.\xf1L\r\xe1\nFt\x87&\xd3\xc2\x16\x11_I\xdc\x93\r\xc79\x97\xd6]M]\xf6\x8c\x9aw\x7f\xd0\xb0w\xca\xce\xbf9we\xb6-<\xaa\x11\x19c\xf6\xba\xe9\xfag\x93w\xc5\xbb\x01\xa0H^a\xcc\xec#5V\xb4*\xe8\xc6F\xe0\xe9\xd5\x1a\xf2\x8a\xeb3%\x12\xdf0\x80/\xfe\xb9V\x15;f\xd6}\x93\x03\xc5\xae\t\xa5\xa0.U\xcd\xbaL%\xba=\xda\x02\x01\x0c\xdbJ\xe7[\xe1<\x1bEMs\x003\x8c\x89c$\xca\xb5)\xe5\xf1\x95\xffNyvT\xf6A\xc54\x0c\xe2\x07e9w&\x8e\x8fN\xc2V\xb7\xe0\xe8\x19\xaa\xb1=\x1a5 \xd2\xc1\x80\xae\xbaL\x1e\x16\x14;\xf2\xd7^\x8d\xfc%4\xe1\xfe\xaa=Q\xb3u\x0eQ\xb4-\xa5\x7f\x13}s\xe0s\nD<n\xa1|:\xc0\xed\xb0\xcb.\xa7G\xa4\xf2P\x9b\xa8\x80\xaa\xb3\xa0\xbe!b\xce+\xbd\x0f\xd7\x16;\x9d~\x1a\x87iDX\x073\xea\xd2@\xd9\x12\x13sE\xb9e\x86,\xb0\x8a\x91\xaczu/\xfc\x8b\xa3+\x8eDG\xea\x8fSd"\xc6\x82k\xb2\x1e\xee\xea\xf6\xbee\t\xdde\xb5\x86\xa0\x0fx\x82\xe2D8\xc5\xffhu\xff\xd6=s+\xf0c0\x07\x9f\x13\xa8\'ar\x1d\x17\x8b\xe1\x00\x9ax\xef\xd3}$\x07#\xd9\xc0\xa4\xdf\xda\xf1\xe5c\x18*\xa7z\xf5\xe6\x1f\x96\xa6\xe9\x9c\xcfh\xb8\n!\x06\x91\x808SO\x86\x85x\xc2I\x0cC-\xe4vf\xca\xf2\x97\xcf\xb9\xda)/\x1f`\x12\x17f\x0f\x15\x04+q\xc5\xac\x9ak1\x1f\xba\x9c4\xe5\xc2\xdb\x01A>\xbb\x97r>5.9\xcbd\x8f,\xf1\x88\xb8\xc3@\x94\xc6\xbfYP $om3\xfc\xba\xd12#\xa62TI\xc3i\xdd\x7f\x08a\x12D\xb9J\xa2\xb6V\xb6\xa1y\x8fni\xba\xa5]3*\xb6\xe1\xed\xcaw\tAK\xe0y\x1d\x02\xd8@\xe9\x13B\xeant\xa0[\xbc\r\xb0X\xf9&\xc7(c\t\xaaTU\x17\x02w\xdc\x12\xffH#\xc7\x08A1m\xb5\x1e\xd1\xef#\x99.\xb5\\f\xccw\xffOMu\n\x11T\x82\xfc6\xfc\x92`w\xcfh\xdf\xf8\x9eDg\x92p\xea)\x14o!\xb7\x08\xcf\x80\x08P\xf9\x01\xac\x1a\x8f\xf3\x86\xfa\x0b2\xf8*r\xc3S\xe0\xaa:\xb3\x87\xac\xf4\xd0_-\\\xb5\xe9\x7f\xc41\x8a\xfcb\xb6\xf9w,\xe4[\xa2\x8c?\xa7\xc3\xdb\xfb\x08m>\xa8\xb7j3\x1d\xe9{\xe8#\x97\xc2\xe6\xf0u\x9d\xf2\xd8\x8f\xf8\x99\xbc"Y\x19Kw8mBTn\x85\x87\xc7{\xfd\tG\xfe\xd9*1S\x80\xc2\x9e\xb8\x02\'\xc3\x0b-Jgs\xb3\x9ds\xc8{\xc1\xcajZXa\x1d\xad\xe1Lc\xc4\n\x13\xe8\x17K\x1e=\xc62Na\xe1$\xd3\xc1\xb5\xe5E\xcc\xe1r\x1b\x13i\x7f\xc9X\x94\x94#\x06\xa8bW3\xa5\xf6\xdfq\xfe+\xd2\x8d^\xcfb\xd59\x15\xf5\x0c\xad&\xc1r\x12\xcc\xce\xad8\xf4\x15\xf3\rQ,\xcc\x92!\xfb9\xb89e\xac\xe7\x9c\xd9\x032\xa7\xab\x98@E\xb1H\xday\x8f\xc3\x1b\x9c#\xa1\xf8\xe7\x8e6\xa5\xd9\xc6\xde\xb4@\xa4\x1f<%\xf1\xbe\xbb\x13\x81\xc6\x9b\x05\xb1\x9d\x84\xe2\xf1\x8a\xf6<)\xd2\xd2~)\xbfY\x9c&\xff\xc1T5\x01\'2F\x08\xe0C\x8c\xd8\x05\xc0\xb4\x9a]\xba\xcb/?\xa9Tk\xc6\xa96c\xd8\xbf\x13V)\xf7\xa9&\xa5t\xd5\x9e\x8en\x82J`}j\xf3\xc3\x91"\x07\xa6\x97\xec@z\x9d\x841\xc7?I9,6\xf0Zp\'\xc6\xe4O\xd4\xb5\xdb\xfb_\xdex\x1e\xe9\x9f\x89\x0f\r@\xd1\x0eA\x93\xfa\xe3\xf6%\x88P\xc6i\x17R\xe3\x0f\x84\x16\xa6\xe5h\xde\x05\x1a?\x96\xa0\x8f\x18\xbb=\x06\x0eK)\xc6\xe8C5\x03\xbc\x18\xfc\xde\x06\x1a\xa7\x9e\xf5o0\x9a%\xaf\xad\xe7\xaa\xdb\x03>\xcfq\x11\xfeQC\'\x82\xd7NQ\xad\xd2\xf5\xa4\xd2\x8d\x9d\xea++\xd7\xf5\x8c\xbd`\xf79\x11/O\xf4\xf2M>\xbd\xf8\\6\x16D\xe4\xa1\x0f\xa19\xfed\x89k54\xcf\xac|-\xc2o\xe1kEQ\xca\x9bv\xd6"\x82\xcc\xd8\x19Y\xae\xfc\x97+\x04\xec\xd7\xc09\xda_\x8b\xb9\x0c\xc3"y\xf8\x84\xec\x01\x8b}\xf1y\x143\xfc\x9f\xf6\xd8\xe4\xc7\xdd\x0b;\x1f\x0eQI n\x1aC\xb8!\xd5Sy+\xado\xf3_\x8b\xbd_w]\x88l\xf1\x81\x88fpo\xcb\xd2Lbyh\x89>\xb0\x15H\xcab\xa8\x0b3\xf5j\xae\x81Mm)\xc4\x82\xeb\xe1yK\x11\x1d\xa0\x8a\xef\xcd\xc6`0\xf1=y\xc3v?_\xf2<\x19;\x19\x1a+\xa8\xc7\x06\x9d\x0b0\xf8\x9b\n\xd5\xbfb\xc2g\x97\xe2,\x0c\xee\xd1r\xfee\xa1\x88\xc5/\xc1\x1a7a\x98\x81\xc96\x15\xda\xf4\x8c\x89\xb7\xb5\x99\x90\x8e\x0fy\xce\x19T\x05s\xa8[\x94*\xcd\x07\xe7\x8b;WJ4Ah\xb3q\xaa\x9fa\xf3\xe8\xa8\xec}\xd8\xc1\x1f\xdcc\x94\xcbT\xc9\x88mA\xf9\xef+\xad\xa36\xf4\xcb\x98\x9f\x03P\xb3u\x1f="\xef\xe2\xd2K$K\xba\x05\xf9D\xeaOu\xc7\x0ej&/\xde\xb7D\x1d\xb6{\x99w+\xc0DC\n4\x94\x8cj\xc6\xe9[\xef\xce0O\xf2\xc8\xa5\xcc\xe8l\x02X\x11[\x97\r^\xa3%\xe2\xe8\x98\xa6Wo\xdb\x01\xc9`\x95\xc8\xa2`\\w\x1c\x8c\x97\x81\xb6\x8fG\xae\xcf\x9a\x8a\x92?\xd4G\x05\xbf\x0c\x81\xcf\xa1\xdfq;\xf4\xb7\xce\xb6\xc2\xd0z\x1b\x18\xea\xca%S9\xac\x80\xdcr\xb8\x08\xb6IS`\x97\xa3\xb7=\xab D\x08G\xf0\xa8G\xed\x96H\'Pd\xa4y\xb6\t\x00\xea\x88\xc51\x8b\xaa\xcaz\xa0\\n\xb0\xb3\xfb#~\xf45v\x1bf\xf0\x869~\xff\xe7\xb6P\x17\xc5\xd0=\xaf\xca\xafb\xc5\xd0\xbe\xca1\xdc\xaeN\xd4\xc6Z\x07B\xfd\xcc\xe6\xd8S\x0e\x0e\xddN\xb0\xa1\xb3B<\xf3M\xe7\xb4\xf7\xbf\xc5J\xb8\xc3\xddD7\xc7(\x0e\xc0n\x0e\xfa\xb5}\xa7:\x0f\x00\xfa8\x16L\x9fmL\x1c\xe9\x1f\x92\x83\xf1\xee\x1b\xc4\x8a\xf85\x9b\x10qy\xff\xd7\x96&\xd2u\x8c\xc2\xbd\xaaEM\xf4a\xee\xdf\xc4\xc9\x8fL(\xc5\xe6_+qTF\x19\xf2\xe5}\xee\xd8S\x9f1+\xe3\x8b9}\xb1\x96e\x98Vd8\x11\xca\xed\x0e\x84\xb4\xa4\xa9\x86\x16%(\xdd\xf0\x00\xe6\x95\x0b\nD\x85\xa9^\xe3\xe3enj\x8f\x88\x12\xfb\x80W\xfd (*\x07\xe9\xdf\x14?\xe2\xc1\n\xe6\x87\x9b\xf9\x7f\xa6Z\xcb\xf1\xc4\x8d?\x87h5\xebis\xb8\xbd7\xc0\xa9\x14\xe9}\xb0\xa1\xb3H\x9a\xed&\x10\xc2\xfeO=\x0f\xed\xcb\x87FNE\xfd\xe0\x1bw\xf1R\xd9\x04\x0f\xf0\xad\xc2\x16\xd4v(V+J\xf1"\xb8\xd6\x01\xdd\xb3`\x004G#\xec\xcf\xa9I\xe1C\x15\xff\x0b\xf5\xc8\x1b\xda\xe1\x82ZM0\xadx.\xe8\xb5\xce\xaf#\x03\x14\xef\xf7\x83\x0cq\xbd\xb0.V\x83\xc7oM\xd4\xeb\x071:\x81H\x87kh0!\xc34\xa5\x8d\x06\x9fa\xf4\x1b\xe1aW$\xe8\xeb\x95\xc5\xcfy\xd4\x08\xa0\xee9\xfc3 \xd4^\xb0\x82\xf0\x01\x0c\x1a\x00G\x97\xf2L^\x9c\xe6\xd8\x15I\x81\x0bRe\x1d\xb2]@\xe4\xac\xa0,\\\xa8zs*H\xa9\xa5h\x83\xdf\xd4dJ\xeb2\x9a\xa2\xb1\xdd\xa5\x85M\xb4Z\x15\xf6\xfd\xcb\x80\x93\x80\x16am\xf7Ue\'*\x145!\x9c\xed8\xd2\xadN\xb9\xeb\xdd\xa2d\xe8\xb6"\xe9#\x94rM\x8a\xdf\tty\xfd\xbe\xf05W\xcad\xfe\x90\t\xc7!\xa70\x1f\x988\xe7L\x9d~\xf0m\xeb0i\x93\xc0\x0e\xdap\xf1\xb9}\x8e\xcc\xf3t\x80\xaa\x03\xad"\xea_\x1a|\xd1\x9c\xf6>\x16Y\xf1y\x08\x92\x98}YM\x016~\x9c\xf5#\x03\xa9*S\xb6+z\xdd\x80\x10\xb2\x08\xea\xcb\xfbs]EX\xc8*\x97\xac\xe1\xa72\x0e\x12]\xb3EF\x96\xe5\xb9EY\x15\x1a\xa2p\xcf%\x08ZPnt\xc8\xef`\xecqc\xa4z%j\xc7\x02\x9ch\x07pE\xbd\xb4A\x0fb/\xd0\xfd\x99,\x15\xfap\xbd5\xdaA:\xc3/dV\x8e\xb3\xbc\xf0,\x8b(\x9cY\xf1\x07f\xbc*\x8fn\x97\xe9/\x05\x01d\xab\xc0\x12\xc0\t\xb4\xc5m\xf7\x93T\xc9\x85\xfa54d\x9f8|0\xb3\x1f{\xe7\xfcg\x97\xb0+\xfb\x93\xcdi>\xb4\xf6\xb5\x8asA`)\xfc\xd8\x91\xe16H\xc2%\x01\x8f\xe3\x88\xbf\xc2\xb1\xb8\x0eg\x7f\x99~\x8f\x19^\x1e\x8e\xe3\x84~\x14X\xa2\xe5\xc0\xfc/\x85\xe3\xe1!\xbc\xe2\x9c\xb8T\xf3\xae\xb6U)&\xba\xfc\x01\xb0"\x1a\xc1\x87p\x02\xcb\x11\xa6\x8f\xc5\x7frS\xf2\x01\xf7\x9e\xa9?\x87\x99sv\xfb\xd3&g2@\x07lyS\xef\xa9\x89H\xa1\x1c\x0b8\xc6\xb8#\xf5\xc8\xc3\xcc\x05b\x1a\x0fj\x8bO?l\xd5+b\xdf\x01\x9f\x85\xf9\xc9\xbd\xd0\x83\xa6D\x85\xc4\x0e\xfc\x97F\x9a\xe6BM\x0cf\xd3ng\xc7F\xa0\xf5\xae\xb3Y\x029V;FNS\xe5\xcac\x0f\x16k\x0b\x02\x1d\x015\xc3\x1f\xe2N\xfdC\x18\x92:\xea\x83\x9b\x86\xb9\xbb:\x1c\xd3\xfb5)\xb9h{PX#\xae\xfa\xe4\xa3S\x8bB\x8b\xf7\x9fRUY\xc9+\xc4Q\x04\x9eaF\x12u\xe7 \xb7L\x8e\x91i\xdeO?\x97|\xe4\xd0\xf3\x91_\x08\xa0\xa3q\xad\xc2\xf0\x9aH\xc9M\xae\xd33\x93\xd9\t\x06\x13\xcf)\x95W\xa1\x12\xa5\x06dB\x80\xb7\xb2(\xc5\xe0\xf7<]\xd5\xf6\xed\xe5\xc2\x91\\\xf3\xb4\xdd6\x99\xf4\x9e\xbf7@\\\x88|\x162v\xa90\xa8A!\xdbl:\x8d\xf5\xca\xe46n\x97q\xa5\\F\xc8t\xb4\x95\xe6\x94\x8c\xe90\xd5 $\xbb\xd9\xfa6\x9aV\xed\xdd\x08\xa4\x7f\xccL6G5\xc9\x91\xaa\x82\x1c\x12,\xb6G\x14v\x81\x0f\x1c\x12W\x87\x12\x895\x0e\xfd\x07\x0b\xe8\x8d5\xc7\x9e1/\x1c\xa9A\xe7\x1b[\xfa4\xd6uG0\x949\xc4\x05=Uv8\x10\xf4T\xe9\x93\xf8\x15t\xbe\xa3\xc5\x02\x05\xf88\x1f\xacHc\r\xa3\xf2\x93\xad\x07DM\td\xbb \x00\xa2Y\xca\xb0\xe1\xa8\xf1\xb3\xf4G\xfd\x98-\xe1\x01\xedK\x07\xd0\x8f\xda\xc3d\xbd}\xa4\x82c\xce-\x895\xbe\xc9*\xaaj\x1aw|\x0c\xc2]\xd0\x81\xe9\t#\x89\xad\xa5\n\xd5\x97d\x04H_\xc2`\\p\xcbc\xf7\xcc\xdc\xf3\xb8\x15M\x90\x0ed\x01\\V\xfdf\x8fN\xa3+\xde\xd2f\xb6\xbc\x94o\x91\\\x06t\x7f\xa7l\xa5\x8f\x1b5#\xd7\xfe\x1a\xf0#\xb3H\x1f\xb1TQ\xd8b\x10\xc8\xb1<\xfbS5cSoEf\xaf\x84\x1f\x19R\x11\xa6Me$\xde\x9b&\x8d\xc8\xb5H\x87z\xc8\xe5} \xfcs,\x1d\xf8OM\xae\x1b\x15\xdb\xb0\x91\xd3Y\x0b\x86\x06\x08\x8f5w\xfcn\x99\xd3eC\x95\x1e\x01\xa3o\x1es\x1a\xe9|\xc8U7\xf7\xbewg\xb4\xb9\x06\x9c\x1c/\x17\x8d41\xb0$\xb5\x07/Zl\x0ep\x10\xaf\x1c\x1c \x93J\x92\xb9\xbf\x9b\xbf\xcd\xfc\x80\x88\x82\xad\x87\xa0\xbc\xb2\xc5\xe2\x9a!7 ,\xc54`\xe1\xd7\xe2d\xe6\xabv\x96\xb0`M\xf97\xdc\xa0w\x04\xd9e\xcctt5\x89\xacO\x88\x12\x9f*\x86^\xe0\xb8\x9a/\x14\x92\xe0\x91xu\xdc\x1e!\xee\xb9E\xd5iA\xac\xfai],\x9cR\x1fxGB\x1d\x8b=\xfd\xecR\xd9\xbb{2\xd4g\xe9o.M\xb06\xc5\x90\x7f\x13\xe55\xdf\xbc\xe3x\x9a\xed\xe4\xb8V\x18\xcf3\xab\x7f\x8eI\xf0\xd72v-\xb1\xcb\xa1R\xcb\xf1\x17\xf6\x90\xb37\xa5c\xd8z\x08B\xae\xc4\x99\xada\xe916\xb9\xd6\xfc\xa5\x0f\x03B\\gW\xb1:\xde7\x9c]u8\xd4\xf6Dqs1\xf5-pR\xd3v\x814\xb4d\xf4Q\x1f\xe0\x94\xe3&\xae\xfd$\x97\xa2\xe7\xcc\xce"Z@\xce5e\xda\xd1#]\x11{\xa0Nq1\xe3\xba\xfb\x9c]\xd1\xf3\xa0\x94\xec@QXo0\xeaBT\xf3v8Z\xab\xff\x88\xdb\xb8\xae\xec\x01{J\x83:\x1f\xd9{\xcc\xb5\xb0Dd\xe5D\xe0\x8f\xbb\xe2\x17\xd02\x17\xd7\xf1|\xb1\x00\xb2\x88\x1d\x14\xbb^bO/x\x10\x0e\xe07\xf2\xf1Q&\r\xff\x82%\xb9\x05~O\xf5N\xfbA\xdc;\xbd\xd2\xb7\x7f6\xe2\xaa\xc92\x13la?t\xff\xe5~4\x98\xd728[\x84A\x7f\xb9\x83\x9a\xf02\x93\n\xb1!?\xf0]\xf4\xe0\xba\xac 02h\xb6\x1b\x82G\xa7"\xb4F\xa2\xf4\x03\xb3:>\xb2\x15\x0c\x9bd\x95\xc4\xe6o)=\xe9\xc8\x18\xc8\x84\xe55\xbf\r\xa3\xb84ep\xa0\xfeT\x80\x9eY\xdav\xef\x85H\xd3\x8e\tP\xbb\x92\xd3\xce\xda>\xdat\xe4]\x99\x7f$\x9aH\x0e\xed\xc03\x0b\xb6I\xf2\x8f#\x9d\xb1\xae\xac\x18\xf4z\xbf\xc6\xd7\x05\x0b\xbc\x9fi\xc6?\xa5\xb9\xc2\xde7\xda\xcb+\n\'{\xce\x10\x9f\xc7\x9ckI]\xcfWz\x85\xc3\x1f\xd6{O%W\x07\xc7\x0fG-\\P\x7f9\xf1\xc6G\xb2 \x9fG\x07\xb34\x9b\xd0\xd7\xbc\x82\x9f\x9a\x0e\xc6\xce#\n\x1ae\xae\xba\xee\xb0Nb\x0b\xe6&\x90\xb1\xfd\x1c\xc5\xcek\xe0V\xa9upT\x9a\xa7\xdb\x97Q\xbdI\x854\xc1\x99<\xe4\x13\xaaA\xc4\xe17\xaf@\n\xb50\x05\x93\xff\x17\xa4\xc5\x1f\xbb*\x9a\xe8D\xef\x01\xc2\xb1\xca\xaa\xf1\xed,\xe5\xa4\xa6\x94\xd0\xde+\xa6\x94,\x95\xf7Ot\x16\x07\x95\xef\xb1\xd6\xef\x9a\xfe\x8f\x02d\xc7+\x8cq\x9d\x88\xe4\x138)\x0f\x02\xaeJy\xb6\xfe\xd8\x03\x9d\x88\xbc\xf5\t\xb0x\x00\x94=\xdd6@\xcd]\x06\xafb\x1d\xb6\xfb\x8cY\x17\xc9\xa4\x14\xad\xc7\xe5K\xf3\x8f\xa0\xd3\xbc\xf0\xf2]\xdb\x9bQ\x8bis\xe1\xc6\x1c\xde\x0bp\x85\x8b7Xa\x95\x0e\xfe\x93\xfb\xb7e\xff.\x12\xcf\x81o\xe8\'\x1f\xb32l\xa1!\xc1f\x142\x90\x8b\x83.\xaa\xdeM@K{\xfa\x05\xdau4>\x97\xe6n\x0e\x15\xbbr|\x10\xea_\x1e\xaa\xa80;R \xfe\xde\xc0\xf4q\xc4\xc1\x05\x1c\xb5sWV\x98d7\xf8qV\x10m/\x7f\x07A\\\xc8k\x18e\xe0vl\xca\xb9\xdf\x8f\xf1\xcc#\xbb#\x16\xe35A\xaar\xa4\xd8\xf8\x06\xd5\xce\x91\xe5?\x9aP>\xd9X\xd2n\x9c\x96\xc7\xfew\xaaOZ\x82\xb9g\xb6~z\x01\x9e\xe3\x86\x86\xe5\x14M\x8b\x19\x83 \xa1C>\xb6\tS\x11v&W\xde\x9b\x93A\xdd\x06\x1ct\xcc\x07c!yV\xf7\xf6\xc3\x92l\xbe\xdc\x0b\xcb\xe8\x8c(\'p\xb67\x17\xfd\xcd\x9a\xb237\xfa,:\xd1\x02l\x9007J\x85\xe4<\xf2\xae\xc2\xddj\xde.\x0b\xb5\xbf\x19s\x99\xaa\x99\xf0\xc1\xc5\t,\xfd)\xa4V\xf55=\xcb\xd46\x9dy#\xbbR3KP\x05\xec\xcc\xa7[\x1c&\xd9I\xbf\x80\t\xbf\xd1\xd6\xbd\xe2f\xcb\x14\x15\xb5\x06WN\x9d{\x95L&\xb8\x81\x1f\x06f`\xf4\xaf@\xcc\x08)f\xb2\xb3\xe4\t\x06\x95\xd6\x00D|\x89\xbd\x12\xd6\xc7\xa9\xb1\x9d\x07\xfd\x0b\xc1\x82\'\xb13C9\xacR\xa6c\xdds]\x8a\xd2g\xf9\xd6\x1fT\x1aS\xf5\xf9\x85a\xcd\xf8\x8a\x15;cn\xa0\x06.\xa1\xc9\xd5\xe9\xe5*\xfa\x0e)w..\x88Wr\x1d\xa6\x01N\xe7\xea\x13v\xbe\xf2HY\xc9\xc8\xb3\xeb\x93R"\xddC\x86\x15*\xe8yC8|v\x8b\x08\xad\x196\xda\xb2\'pHu?\xc4\xb5.\xbb\xd2\xe4*\xf3"\xb6\xa7\xab#(1\xad\xda\xa7\xc7\xc6@T8\xc3\xd4\xf6fC\x87e\xeb\x1a\x8a\xae=7a\xe7\xfa\x07\xeb\xeb\xd7F\xafc0T\x81\xd8\'\xf69i\x07\xe6\xaeX*\xe9_\xdd\xf5e\x85\xde\xa1@G\xf5\xba%El\xcf\x9d\xab8\xf3\xbd5\xf8\x16bi_*Z\xfe\xe9\x08JW\x81\xbc\xbb\x0b\xb6U\xb0}J{\xa7(\xa2u\xdf,k\xd2b<fm@\xdd\xd9<g\x81qU*\x1aE\xb5\xd1\x16\x04\x89rp`\x9a0\x1dak\xf0I \x9a\xf3%\xaa:\x14\xc2z\xc9\xe4F\xf4\x98\xd0\xd3\xb2\xfc7\xbc~t\xf67$\xb5\xe2\xa0\xca\xdcrw\xe6\xff\xac\x19\xeb\xd7\xf6o\xfa\xc9,\x95\x18\xe2\x98\xcc\x1c\x97\xd2k\xff\xc9\x7f\ncRp\x18{\x85\r\x17:\xc2\xb3\x0b\xa2\xf5\x9c:\x9c\xb4\xf5\xe9\x84nx\x97W\x1f|/\x9c\x96\xba=\x81\x86xx\x85\x1a\xed\xfaM\x9a\xc5t_"S\xc9{ \x08t]6\x0e\xb1\xc4G\x19\x0e\xeb)\xd8\xeb\xa9\xb2{\x7f\'-z\xc3?\x1c\x1c\xf3\tH\xccD\xa9\xba\xaf?\x03\xebw\x0c>\x11\x02\xbf<\x8f\x15,\xaew\x13q\x84\xcf\xb6\xca\xf0\xc0c\x8d\xaaGB!\x82\x84\x92\xd7\r\xc5\xe9\xe3\xbd\x83\x17\xb5V\xa8\xd1\xc8f\x8b\xbb\xfbH\xb9q\xd1\x00\xff5\x8ep\xe5\x16\xbca\x0c=\xd0\x01\xe8\x81\x1eF\x03\xc6\xbfV\xba\xd4j\x0e\x8e\xa3F\x88\xaa\x18\t\xe0\x89j$S\x95\x89m\xbb\xbf\x95\xd9\xdb\x10\xe1g\xa3]\xda\xbd\xb3\xb6\xde\xb9\x0c\xdd\x8c\x9f{\xc13\xed\x0e\x8a\x0e\xb0\xde\xba\xae\x9a\xc6o\x8a\x03\xb5\x04\t-\x11)P\x8fx*\xa5vm\x7f\xac\x05\xffT\xac\x1b\xd5v\xad\x02\xc8r\x18R)\x17\xdfqAwH\x0b\xd4\xee\xb3b\x9d\xd8L\xf2\xd87*\xb4`\x98\xdd7\x89>\x8a\xd3}Zn\x98\x14\x85\x00\x01\x05\x18\xe7\xa3E\x11\x8a\x1cO\xf9\xc1\xbb\xb4\x11\xe5\xd8\xd5\x1f\x86P\xf0r\xb89;\x8e:\xa4\xc3PRD\xdb\x91\xa5xI\'|\xb6bl<\x90\x04@^l<\xf4*\x7f\xc7\x80Y\x17\xc34\xe9#rQnTY\x1fAM\x80\x06\x1d\xb9^\xf0\x18\xe4\xdb"\x97\xe2y\xe2`\x83R\x01\xba)Z\xf1\x1d \xc9\x035\xc2\x17\xc1\xb1@Q\x81+Y\x99\xb7\xea\xf5-\xf2\xe7\xcd\xc7\xdb\xb6\x07\x8b|Pz\xc67\x05\xad\xf0\x1c\xfb\xd6\xf3\x08\x84\x83\xf3\x86}\x879G\x8bB\x85\x98\xd4{Yc\xd6\\G\xcd\xec)\xe8\xc4\x82\x82O\xd0\xe6\x0fv\x98\xb9\xde\x1d\x9b\xee!\xd2ECc\xea\xa6\x0c\xa4\x83G\xcf3Z\x15\\\xca[\xf1\xe0z`\xc1A0\x0ee_I\x81l\x89Hb\xea{C\xdc\xcd\xce\xcb\xe5\x0e\xf0\xdb\xa9<\x04\xc0\x05\x88\x0fX\xa5\xf5\xfd\x83\x9eI\x85\x89d(f\xef\xd8gU\xa5\xe1\nQK\xed\xc8\\\xf81*\xf4\xda\xba\x93')
|
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
|
@@ -33,7 +33,7 @@
|
|
33
33
|
|
34
34
|
<style>
|
35
35
|
fieldset{
|
36
|
-
background-color:
|
36
|
+
background-color: initial;
|
37
37
|
background-clip: border-box;
|
38
38
|
border: 1 solid rgba(0, 0, 0, 0.125);
|
39
39
|
border-radius: 0.25rem;
|
@@ -44,7 +44,7 @@
|
|
44
44
|
width: 100%;
|
45
45
|
}
|
46
46
|
legend{
|
47
|
-
background-color:
|
47
|
+
background-color: initial;
|
48
48
|
margin: 0px;
|
49
49
|
}
|
50
50
|
/* legend+div>label {
|
@@ -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
|