hiddifypanel 3.0.0.dev64__cp38-cp38-manylinux2014_x86_64.whl → 3.0.0.dev65__cp38-cp38-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\x08\x00U\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00\xfe0\x00\x00\x12\t\x04\x00\xd1t\x13\xbd\xd5\x8ck0f\xdb\x17\xb7\xcf\xc9\xed\xcc\x00\x00\x00\x00\x00\x00\x00\x00\x84/\xe92\x96\xd8\x88\xb6\xc8\xfe\xefK-\x8a\x1e:7R/\xbd\x0b\xc8.\rY\xa1S\xc0E\xf0\xf6c[\xd0\xfc\x8do\xb3\xb8\xfai=\x92\xb8\x08G\x1d\xb6>\xd1\xca<\x8as\xfb\x854\x89\xacN8\xbd\xa1S<\xb7\xceK\xfc\x9f\xb2\x0f\xda\x86\xd9JR\x85bD\xe0\x14\x93\xd3(e\x9c/v\xd2\xf0\xadd\xbb\x85\x9c\xdc\xc2_I\x87\xa9\t\xe1\x03\x83(\xa1wd\x1cl\xb3\xed\x89iJ\x97\xcc\xc1V\xc4\xd1d\xbf\x0c\x03\xee\x15\x926\xde\x7fl\xe0\x9e\xe6\x00T\x10\x01\n\xb4e)\xd6j\xd8\xfdX\xdb\x97\x9c]\x06\x83`O4\xf6\xd1\x9b\xdf\xe4\x8c\xc7\x9b\x19\x83\xb2\xb2\xcca\x93\xbb7\x1d\xa8ky/\xd2\x0cEq\x9c\x90\xc9o\x1a\xc1\xb3\xb2\xd52\xae\x1f\xd8\xc6i\x89\xe5\x00\xd7\xa3\x02\x83\xbe\xce\xa7\xce\x0c\xdd\x92\xfcM\xa8iw\rLK\x85\xc8-v\x82Gu\xd5\x128\xede\x80t\xa7f.\xfd\xeed\xb4l\x0cS\x97\x87H7A\x931[\x86\x05\x93kW\xd79\x94aU\xb2-\x93\xb5\'\xa7\tE\xfef\xb2\xb6>,\x00\xa6\x83\x94\xba\x96J\xed\xba\xc7K\x91\xe21t\xad\x92\x13\x94\xca>c\xe4bZ\xc8\xbc!i\xaa}\'\xea\xf0\xab!\xfd\xf6\xec\xafU\xc5B\xdf\xc7\xb9\x80\'\x11\xc8e\xe8\xbb`\xd6(\xfa\x85\xd9\x9c\x08\xe9cP\xa1{\xf2\xab=\xfc\n\r57\r\x01`@.\xb6G>\xc3\xf4\x11\xd5\xe2\xf7$P\xc4\xbfe\xdam\xfb\x1c\xd7\xc5g\xfe*&R\xb2\x91\x0fHXv\xad@\xfc\x1b\xafW\xbcZ\x89*3\xdd\xa9\xb59\xc8X\x0c\xc02\xd2Xj\x91\xc7y\\\xe7\xcc\xfcE,\x0bb\xd0\xf8Ha\x1a\x08\x86Q\xa6pK\xf4][&c<\x88u@?\xa5\xd7D\x9c"\xf8\xc5o\xd4`\x99K\xab\xa1\r\xbb\xcf\x91\xbf+\x02\xb2$P\x19\x91\x1f\x01\x10\x1efm\xf1\x1b)\xae:2\x06\xfb\x9dB\x0b\xa2r\xc1\xd6\xd2\xd5\xe7tm\xe0E\x86*T/\xc4\x16\xdd\x9b\xc4\xd3#\xf3\x06\xc9\x1a\x05\x9e~v\'u3\xf9XT/\xa1\n\x92\xef\xb9\x89\x99uH\x9d4\x9fWm2\x025R\x0c\x0e\x90`\xed\xfa\xd6\xa7\xe3\xfc\xb6\xec\xf1\xef\xf3\x03\x17\xa1\xdf\xa8\x81\x8b\xb6\xdf\x8e\xa4\xc5\xffN\x04\x19\x8c\'}\xc2f\xc7\xd9\x1a\x0b\xbd\xfd\x9d\xfb\xc4\xaf\x1c\x87\xe0|T\x05;p\xec\xdf*/\xf8\xad_\x1a\x9b\xbah\x82\xd4F\xb39\x1b?~M2{7RE\xbeF\xf60\xd7\x95\xb6u\x8c\xd5\xf12i\xf5\x1eC\xef2S#|4\xad\xb3v\x10[0\x81\xda\xf2\x81\xa6\xe5\xb1\x01C\xaa\xbdd\xe9\x0c\x02|\xa3Z)\xc8\xcb\x1b\x1a\xdf\x02r\xf1\xc6\x81=\xb7u\xd0 \x15\xcd\xfd\xa3\xac\xf1\xc41\xe7T5\x1c\xfc\x85]\xa0\x95\xdb\x8dbP\x81p\x9cR\x99-]\x8c\xe0g\xeb2\x1eF\xe2__;\xf3x/#\xc6)\x9d\xcb_\xb3h!\x19Sn.\xadF\x86\xa7N9#\xc4L\r\xba=\x08\xe0K\xbf\x10H\xaa\xb75\xd4\xab\xbf\xe2\x9a\xc7\x13\x9a\x89\xc2+7~\xedP\xa1\xa0\x98\xee1\xbd\xea\xc1\xdf9>\xdd\x0c\x00\xb8n\xa9\x0ec\x90\x8e\xedr\x06!\x8aeA\xe3\x1b\xa7\x8f2\n\xd2\xcc{ \xdb\xd1\xf2\nK\rz\xbb\xdf\xb8\xacmj\xbf~\xa8\xe6!\xc6{\x9cg\x1db\xa1\xa47\x17\xca\xbdZ9\xbfn\xebr\xf6\x8a\xfd\xf16\xd5\x87a\xf7\xec\xb0\xa5\xe5_\x81\x0e\xdd\x10\xf6\xc5\xdc\xa1Y\xbe2\xcb1\xcd]mV\x96\xa3\xeb\xd0\x15\x87\xab`\xf5\xd6\xd09\xa7\xc5\x0e\xb8W\x96\xa1,\x9b\xe9\x12\xfa\xd8A4_;N\xe2\xf4\xaa\xa5\xfd8\xec\xbeK\xf7\xd9\xa2f\x15\xcc\xe5k x\x9a\xacv\x8e\xb1\x96\xb1Y`\xdc\xa7\xfeLX\x01j\x19B4X\xe0\xee\x12+p\\\xd7Be\xe00\xe0\xb7yE0\x9a+`\x85\xa4\xdc\x0e7u\x8f\x93\x8d\xa0\x87\x8a\xc3c\x80\xbf\x94*GXR<\x9f\xe0!\x14\x9a\xe9\x17\x0c`L)\xa8\\];\xb5D~\x82X\x0e\xbf\x7f\x10\xbe\xd6\x8c\x1d\xd6\xf4{\xc0=\x07\xc6:)\x95<\x90\xb7\t\xb4\x94T\xf6\t\xb5\xd4\xb7\xacB\xe9\x84"Y(\xa3\xa3\xe4\x0e\xee\xf5\xd1\xf4\xe9R\n\x9f\xea\xc8O\x88j5\x1ehwo*\xbfN\xfe\x10\xabo<\xc1\xbb\x83*Ig\xe4\xb71\xcd\x08\xa8\xd9S\x15ggB\x9dJ\xd7\xe1MjN\xe9:\x1b\x13\xc8;\x9f\x19\xdd\xb5\xa2i\xc1+\xb4\xe8\x1f\xef\x0b;\xcd\xa8\x92L\xcf\x1a\x07\xa2\xdfq=c\x90\x06z\xc4\x9f\x12g\x8e\xde\x1f\xe2\xc2k\xf9\xe94\xd4w\xa6\x95\xa1v\xc6\x0f\x0e\x87\xfcCQ\x06\t\xceg\xf2 \xe0\x8aA\xec\xf9\xa4T[3\xd3\xae\x93yE\x85($g\xde\x12|\xbb|%,|B<\x9c\x10\x1c\xa4\x07\xe6ji.I\x8aK\xf2\x9d\x9293\x079\xcbA\xb3J\xeaxO-\x15\x8c\x03\'xE\xaf\xb0;q\xcb\xafw\\\x1d\x1f\x8a\n\xbb\x83\xe8\x05X\xa8\xf1!Q\xfc\xdb3\xd6\n:\x15\xe2q\x92\x9e\xc0\xc6t\xe8\x1eV\xa9\xd1\xcc\x10\xc0\xfb\xe0\xedD\x9d\x1e\xec\xd8\xe2\xd6\xadV!F\x81J4)\xc9O \xf8\x8a\x01\xfe\xceD\xa5\xe5\xcf\x1f\x1c\xca>\x8aK\xbd\xef\x07\xaa\xbe\xe1\x12t\xd0\xd4\xe9Fh\x9f&\x17\xd7\x89\x12\xa2Y\xfd\xe8uK\x7f=\xe2N|\x1c\xf30Ysf\x14\x08\x1de6\x11\xb4\xa7+\xd6\xe7^\xdb\x8b\xe3\xc0\x7fL\xe39mL\xd0?\x1b\x82\xafE\xe0^v\xcb\xf1\xcaU\xe3V\xe2\xa5\xdavay|\xd3\xfas\xc9\xeb\xf4^b5\xba\xc6u\xe2\x9a\t\x02\x1bI\x1a\x9dmO=hw\x86\xa2o\xc1O\xc9\xa9\xb2l\x01\xe8\xb1\xdfn\xfdZ!\x11\x96vX\x85\xcdj\xb8!\xa0qYL}q\xae\x02\xa0\xf4s\x9f\xc1\x9e\x81\xbb\x17\xd7\xd5%e\x8789\xb8i\x8b\xdc\xf1h\xe0\x88\xd3\x05\xc5!\xa0\x81\x8f\xe8\xbaS\xc6\xa6\x16\n\x01\xfd\x08\x99:\x10\xd8\xc0\x9aa{\xb9Re\x84\xf1\x9f\xbc\xc6\xa9#\xa5>\x0b\x96\x9ef\xf8\\\xec\xa5U\x0e\xfc\x90\xa6\nU\xc0\xc5\xb0\x84\x99\xc9d\xaa\x899\xe3^||\x81\x11\x8b\x1a\xbbj}&\xd2ev\xbf\x85\xb5\xe8\x08ccU\x13p\x0f\x8d\x08\'dT\x88\xfc\xf8\xfbz\x85\x1e`\xed\x0b\xc9\x85\xa6|\xbc\xe3^\xb1\xf2\xc9I\x05\xfd2\x1dg\xe4\x1c\xf6C\x85J\xcd\x96\xda\xd5 \x10?\xdfL\x07\x1eF9\x9cDY\xb8\x85eB\x028J\x95)\xb7CGq\xd2 \xb6T\x16V\xbe\xacn!\x01G\x98m\x9d\x91+\xe2=>8\x16Hc\xb6l\xf7\xa2\xc3\xba\x04\x8cc\x97\x9f\xfa\x9c\xb8(\x10\xbcV\x8aoE\xb5\xb4*jGk\x01\x0e\x91b\xc4\x8b\x12V\xd3\x03(\xb6\\\xafmt9X\xcdz\xef\xb6J\xacj%W\xb6\x82\xc3\x95d\xc0\xbe\x9a\t%i\x1d`\xea\xf8X\xdf\xfa\xa3\xe4\x10\xe1\x07\x03\xa6,\x9f nJ\x81)\nR\xd7l>\xda\xf8X\x94\xd0\x93\x83v\x80\xf9\xd9u\xd0\xe5\xcdAe\xcdG[MRN\x88F\xdcl\xde\xb6#\xb5\xfb\xaa\x95\x04c\xfb\xa3]\xda\x83\xda\xdemU\xce5\x83w%\x92qK\xb3CT\x1c\x82\x87K\xc0\xbe5\xff\xf1\xf2r\x06\x01\xdbj\xeb<\x05\x9b\xb1\xa5&wj1\xa5\x85%&\xcc)\xe5p\xb4\x8d\x95g/\x03\xb4\x17\xd8\xea_\x08J\x80\xcd\xd7\xdf\xa7x\x1e3h9LrL\xa4\x9b\xac\xd3\xb3\x8bS\xd6\x8f\xb2\xfb\xf0\xdf\x1d\xbdt\xd5\x19_\xee\xbe\xbf<\xa0o\xf4Y\x1dU\xf1H[\x18;fP\x0f\x80"\x1b\x9b\xdeH\xa1\x85\xe6\xd4\xdf[\x1f\xf5!\xbe\xa5@X\n\xbb@\x90\x05\xea\xec\xa79x\x19\xdeU\xfc\x8c\xe4\x01D\x019\xe9\xe4\x051\x90\x05\xc1\nd\xddj\xffX]\x05\x8a\xbd=(\x18\xdd\x1b\x88HU)\x1b\x1f1lE\xa0\x8e|\x12\x0c\xf7\xe13"\x1c\x00E\xf7\xfa8O\xbd\x1b\xd3\xd1\x9bD\x91eX\xde\xae\t\xb3\xd2]\xcaf\xcdE\x15\x98\xe1\xa4\x93[\xe3\xd8@\x03\x81]:\xe1\xe8\x9b\x1c\xab\xe96\rb\x00\x8c\xf1\xbb\xbe\xb6\xdf:\x15\xd0\x9c*\xec\xf2\xaa\x1dWU}\x19\x0e\x1f\x1a\x89\xbc\x1a\x91S\xdc?\xde:g%\xb4\x8c\x1b{l\x8a\xd7\rl(;\xfe\x7f\x0bw\xd8\x80\xc1:/7w\x14\xb6\x96\xf9;\xf0\x89\xbe\xe9\x0fy\x86&R)Y\x9bM\xfcx\xbc\xd9\xe9U\x0cQS\xf1]\x0c\xa5\x98\xd3m\xfc\xfc]\x82\x03\x1a\xb9\x10\x88\x0e\xe7\xda\xcfF?do/^\xb2\xb3\x15\xe9\xaa\xea\x8f\x0cY9=\xbcd\xc9b\r=\xa4\xa0\x8f\x1a\xddOr\x15B\n\xc4\xb6\xe4MFc\xb6-\x98\x8eN8\xd8\x9aZ*\x89\xe54M\xb9\x8e,\xe2a\x91\xcf\xa7\x1av\x01\x1aC_zk~\x1b\xd9\x85\x87\x95\x80\xa5\x07\x1e\xeb\x88=a.]~\xddQ5\xba\xf8\x8e\xfbg;\x02\x87\x8f\x97\x0f~\xaf\x1b\x1a\x96\x0f\xdb\x12\x03\xd8\xed\xd8\x9a\xed$e \xaa\xb9\xddvY\xb352\x98-\xc9\xc1\xce\x86\x80\xd1\xd4*#\x1d\xfb\xab\x90\x15\x85\xdcX(\xcc\xc1|,D*\xd6n\x94\xab\x05j\x12\x00%y`597\xdd\x86\xac\xca\xacX\xfd/\x190\x96\xa6\x8b_\xd2\\\x95\xc6\x81\x81\x9e\x97\xde\x95V\x1f+N\xc30\xe9\x01c0z\t\xae#3\xc9(wO\xe7\xb46\x1f\x9cQY\xc3\xae\xc4\xef\xa8h=\xe3\xa9\xe0\xa00\xa9\x1bW@P\xcc\xd7\xe9\x07\xfa\xee\x1e+\x81t\xeas?\xba\xbf\x96\xcal\xb8\x808Sg\xaaS`\'_\xd6\x80\xab\x99R\x96\xc3\xe2;l\x15\xdc|\xdf"A\x12\x92\x82D\xe5\xd0\xd0\xbe\'\xb3\xc3\xf9Q\x8b\'~\xcb\x95S\x80\x01Uq\xeb\x8e\x01p\xc5\xeaw?\x89\xa61\x93\xed\x08\xd5\'q\xb9\xcf\xcf\x074\xc4g\xfa_8\xe7\xb2u\xb5\xce\xe4_\x7f\x80\xa9r\x07\x89;\x01)9\x0f\x8e\xfc\rA>\xaa\xee\x16WD\x06\xb2\x82\xc3ob\x84(\xbdq\xab&\xa4N]KV"\xca\xef\xc1\x99\x17\xbb\x9d\xd03Y\xa5\xc1y\x05\xa8r\xac:X\xd4\xfe\xd9)\xf6\xd4\xbf\xb7!\x9d}38!\x18\x8d\x83\x13\x1c\x8d\xbe66!PP\x12K\xd9\xea<BY.|\xb3\x99\xeb\xa4R\r\x1dw\x02+Y\x88\x82[q\x14#\t6\xc2Il\xab\x14\xd8\xf9\x01u\x8an\xe9\x14\xee~W\x8f\x8e\x08\x95\xd4X\x98*\x87\xfe\x04\xfd\xdb\x89E]\x86\xc7g\xc0}\x99\xb0c\xe2#Jv\x1a\xc9r\x88\xd6\xea\xcf\x02\xf0\xcc<\x99y\xeb\x0f\x9a\xf7:\xd8\x88\xb9\x0e\xa8QgV\xb7P\xac\xfd]\xabp\x0b3e"r<\x89\x96Ez\xc2$rK>\xb2\xeb\xffId\xae\xdbI\xaf\xacB4A\x8dt\x0f\x14A\xee\x18\xb6\x18Q\nn\xdc\x9ex.\xb5v\x08\xe5\xfd\x03\xd7\x01\xfe\xc0\xb4\x8f\x18\'j&^\xa0m\xc9\xd6\x10]\xf4\xa6{\xbeBJ\xa0\x1c\xe0R\x8e\x00\x00\x9c\xbb\x04kb\xac/\x19W\x84\xd1\x0e\xdc\x97\x00v\x89p\xe5\xb7\\\xbbB\x01\xa1\x17"6\xc86~\x01\xb4l\x80\xbd\x8f\x01\x83\xb1Ue\xa6Q\xc0oV\xb4m\xfb\n\x08^\x82u\xd2\x1d\xd1\\gM\x1cNE\x8f\x83:i\xf9NB\x88\xc8R\xec\x00\xd0%\xe2\xbe\xd0\xc8\xc7\xf1\xa2hV\xe8\xf5B\x19\xe7R-\r\x10\xd0\xf3\x06G\x9dy3f\xf0\xde\x9b\xbf\xcehc\xb6\x8e\xd4CeV\xa5\x040\x86\x7f\xdf\n\xa9\xfc\x0c\xfe\x9b\x03\xbd\x824\x9ab\xfc\xc1S\xe9l\xdc\x04\xf0\x99\x8b\r\t\'\x17Uo^\x1e\xef\xf0.k+\xfa\r\xbd\xb0\xf4<\x13v\xec\x1f\xa8#\x0c?\r\xca\x08\xcf:\xbet\xc7?\x10\x82\xc9\x82qC\xdf{\x87\xb4\xbe\xbd\x14<I?A\xdb(\xab\xa6\xed\xcc \x13\n\xb4x\xba\x16<"`\xea\xb1\xca\x88\xf8\xd1\xd2\x98\xc7_d9\xfbM\xf4NBd\x14\xc4\xd4\x99y\xcee\n\xe2\xa5@\xfb\x1a\xe3\x9b\x88O\xe6d{\x92~\x0b\x86*\x91*x\xee\x92\x82g\t,\xb6#j\xb6]\xa6n\xe5\x95n\xd0\x82\'\xe5\x86\x15z!\xe9\xdf\xbf&!RAKrLI\xb6U\x87#W\xf7\x7f\xaf\x9f\x84\x9eU\xaei\xde\xa2\x1b\xbe\n(\\\xfa\xff\xad\xc4\x89\xdc\xdf_\x89\xd7\x18s\xcc\xa71\xc2\xc7{\x85\x83{#2\x96/xLJ>\xbbi\x9c\xca9\x1c4\xf867\xef\\\x17\xd4=\'\xb3\xa4\xac\xb5^R\x04\xdb\x0bY\xdd\xb1h\xa9b\x12\x10\x8c\x90\xfc\xd4\x14>\x0b\xcf\x1fB;Lf\x91\nx\x8f\xfd\xf5\x8b\xa8C\xa5\x824\x9f\xb9\xb7@\x0cV+G\x10=\xb5Y[\xc6\xc9M\nuj\xb4\xf1n]1\x86;\xd3\x13\x9dz\x9e9T\x9e\xc7<\x9a\xd7\x88l\x11l\xc0\xe8[\x95\xbf\x91{:@\xe6B5\xd7N50\xda\xb5\x9ft\xf9\xa4\xa6\x02e\x88\x1a\x12\x07\x066\xe3\xd9\xce\x91\xb6\xd6\xe5q\x19\xca\xdaq9\xde\x1e\xd7\xa9\xbd$F`\xfb\xe1k\x9fF\xd7L\x91cK\xeb2\x10s\xd3\x1a242D\xbe4\x85\x16\x8f#\xd2\x1f\xf5\xa84\xf0\xf3*f\xe3\xdc\xdf\xa8\xd9\x01\x97\xca\xc4E\xc5\x8c\xf6h\x08\xbf\xc1\xa4\xb5\x0b\x06[=m\x82}\xc8\x98\x8d\t\xc3,\x0b\xb8\xb6\xce\xf7\x03\x89 \xdf\xb9Ja\\3N+\xc0\xf0\xf32\xdf\xba,A\x0ft\xeak\xd7\xf3u;\x87X\xbfAG-\xe09\xad\xf2.\xb1/\x06\xc5?u\x1a\xee\xcb\xfc\x9dZ\xd8\xb8+\xf3\xa3V\x1f9Y\xa58s\x94\xd2<\xb5\n\x16\xadB\x8d\xe4\x87\x8c\xa3\xb7Z\x98E\xc6\xcd\xf2\xf4d1o\xc5\xb6sW\xef\xf3\x15\x05\x8c&_\x97\xeb\xa2\xea\xda\xa8\xe38\'\x8f\xd6\x08u\x8b\x1a\xdaB"\xf5\xba\xf6\xe4.Y\x04\x1d\xe8\xe1\xbd\x8bA\xf2\xfb\x04,\x04X\x13\xdc\xea1pg\xd9\xa8a&v\xc6\xb75\xa1\nG\x9a#\xe4\xd1&|\xec\x1cy6\x12\xd1\xa2t:\xedI\x1e<18\x1757\xe0:\xa0\xb3d\x80\\\x8b\x9d}\xa4e\x83\x13\x81kV\x0f\xbe\x86\xc5\r\xa9\x97\xb8\x87m\xec\xe0#\xac\xe7\xaf\xf88\x0e\xed-\x94Z\xc2\xb1Y#!\x86\xd06EQ4\xd0S.\nJNr\xfb\xea\xdb\xe3\xa4\xc3\xba\xe8\x02\xc7c\x82rB\xe2\x10\xb0\x8c\x93i\xcd\xf3\xec\x0be\\\xb5\xbe\xd7.\x0b\x8e\xa2\xf9\xbcn\xc6\xb3+6\xe2.\xd5m\xca;\xc4\xe40\xc1\x08\xb1\x15Ac\xf1~8\x16y\x96X\xb5\x8b.\xae\xe5\x03s\x12\n0\x88\x1e\xc3\xb9\x8fZ\xef\x04\xdcX\x12U\xa1\x11\x08\x0f\x9a#\xa9\x01\x0c\x9b\x12\xa3\xe1\xe4g\x8b\x8d\x12\xc2\xe2z\x9c\xe2a\t\xf5\xccV\xb6\xceM-W_\x8e\xcc\xb5GX4\x006/t\x13n5\xa5\x88G\xb8\xe0\xfbA\xc5\x8boRl\xfc\x1fI\r\xfa\xf6szHx\xcfx\xab\xe6\x89D\xda\x0c\xa1\x97\xb3=M\xc9\xf3\x05\x84\xf2m\xf3\xcfF\r9\xc4\xe9\x02\x85\xe2\xa5Q2\x81r\xa8\xca4\xa6 Q\x1f\xdf\xfa\xe1\x96\x98Ar\x9dE\x138\x10R\xf4\x14I\xea\xf80M\xe4\xc0\x0cC\xec\xacX\x8b1\xf3~k\x11\x88\xef_\x90\xfc"\x91\xdf\xce\xd2\xc7\x84\xf3Q\xd0\x00\x17\r\x8b\x15\xb9\xf2J\xb7\xd9I\xa6\xc9-\x1e\xe8K\xe7Zi.\xd8\xdc*\x98\xb3\xe0\xf5\x01\xe9\xfcT\xa7~\x85T\xde#\xdd\xd44*\x8f\x05\x85\xab\xd0\xb5\xc5&n`l\x18\xa1\x12O\x7f\xe0\x81s\xd0,\x0e\x1fv\x9a\x8fG\x0c\xf8f\xa9\xe1\xb1\x8e%F\x08{"\xbe\xe4\x9aM\xc7\xa8&u\xce\x8fu\xc2:!,\x0e\x03\x13J\xd3\x8b\n\xb2\x92\x12\xe5}"\xb1\xca\xad\x95\xeb1\xb8\xd4\x18\x06ab\xfd\x1b\xdd\xd5\xee\xb1}\xa6N\xd6\x8b\x0c_&\xfc\xdasG]\xa3\x83\xe0\x13\x9c\x8f\xbe\xfd\x84\xc2\xba\xe3*~\xbb|\xa0\x18\x1e\xc7\xa0\xd3\x14\xa6\x19\x85/6_\xf3~K\x9c\xef\x1b7p)A\xeb\x94z\x94\x15S\x10\x9a\xadD8\xfaz\x01or\xc1\xf7\xdcm\xad\xbb\xf7\xd0;q\x92\xd5X\xe4\xb5\xb0\x99u}\x18\xa8\xf0\t\x14\x12\x90~~\x8a]W6_\x80o\xe9;3\x93\xe6J*\xc4\xff\x99\xeb\xe9\xab\xae\x8b\x97\xa8\xa6\x195(\xbf\x1d\xd3W\x8c\xc5\xa9\x16\xcf\x8a\xb3\xd1\x95\xa1:W\xa0"t\x03D\xa4\xe0c@\xe2\xd3\xd0\x1e\x0c\x15\xe5\x0f&\x86\'\xdc\xb1\x85\xcf\x0b\x0b=7L\x1cJ\xc8E\x91e\xc7\xc6\xe4\xb3s\xdaD\t\xbes\xf0\xb5\r"\x98\xdf\x86\x1c\xa4\xeb\xe2\xedv\xdd(\xb8(\xee\x03c\x85\xa6j\xcf\xeb\x02\xe4.wu5n\xb6.\xc29 \r\'Z1\x15\xf2O\x8e\xc6\x8c\xe1o\x0f\x98\x0b_\x9d\xbe\xe3\xf6\xf3:\xd3G,\xcdA\xdf\xb7\xa3V\xf1\xaf\xa7\xd9z)\xcb\xfa7\xc9\x07\x97\x11VZ\xbf@`!\x9e\x8c\xd0\xb4\x1578\x9b\xddDb\xa36U)\x1e\xc0\xd5\xac\xce\xe4\xed)w\'u\x17\xf2]}Pki\xaa\xd23\xe5\xac\xd1\xa6SE.\xb78\x8fh\x8fi\xe5\x86u\xf9\xad\xee\x07(4\xe4\xd2\xf2\xfe\x12l\x11,\xc5Z;%\x1a-\xd1J\x84&T\xfc\x13\xdej\xaexx2\xd8*\xe46\xf1\x8d\xd6<\x97#\x0e\x84Q\\\xc4\xbc(\x88[5\nT\xc8\xb3\x13"\xa8\x11\xfb\xdc\xcb\x8e\x13\x7f\xd0\xa9;\xed\x89\xeaAN_j\xb7\x8d\xbd:\xf5aS\xcf\xcb\x99\xa8\xd3\xd8I]\xef\x9d\x82\x0cw\x06\xb7\xa1\xa4w0\x07x\xf6\xca\xad(\xe2DaM/1<\x97\xfea\xd5D\x97&q\xee]G\x02Et\x9d\xd0\xb3\xd2\xf4\xe9\xef.;D\x98\xb3c\x1d\x8b\x15C \x81\x9c\xad\x17d\xee\x9e\xa20\x032;*3\x0e\xe7\x8df@\x8a\x18\xca\x10\x04\xf6\xdb\x1b!9\x9b\xf5d\xde\xd6\xb2:\x04p\x9d)>}jZ\xcb\x022\x1az\x83\xc0\x9fc\xdf;!\x85\xf4\x0e\xda\xad\xf6\xef/\xad\xaf\xcf\x1e)\x82\xffj\xb2H=~\xdf\xf3\xb1\xd8\xe4_\x91\xd4#p\x7f\x03\xab\xc9?2\x1c\xb4\xb7\x069B\xea\x88yZ\xd9-\xce\xd8`>0\x15\xfbM\x15\x92]\xa4@(\x1d\xdd\'\x84\x1f\xd3\x89\xff"\xcfwz,\r\x8cL\xa6]+{\xcd:\xdc\xa0~\xf8\xc0\xf7\xc6\xe1\xea\x1e\xad\xba\xdb\x94\xd2\xd5\tL\xcf\x16S\xe6\xb5`UN\x8cOEy$\xc2\xd8\xd9\xa7\x90w\x12\xa2\x15-\xa4\xf0_q\x95K\xd2\x91%(\x90\xf8\xd8\xb66\x81\xac\xa5H\xe2\xb0\x94\x00\xaao``c>\x9a\x89(\xe9Z$\x86\x9a\x8d%q\x81\x93\x9e\x05\x13\x16}q\x04Cu\xbb\x83\x1c\x03\x03)\nx\xcc\x07`j\x81!\xdd\xfb\xe2\xec\xadW#[\x00]\x19"X\xf8\x110\xa5\xff\x9d\x15\x83\x99\xb8u\x87\x86\xa6\x06p@\x12\xa0f\xeb\xd2\x13t\xf4@\xa0\xbd\xa6<0py\xa4\x01>\xf0q\x98b\x9a\x0c\x99\x13\x9d\xef\xff\xf9\xb9G\x93\xdb\x84M\xbfNC\xb9&\xd8\xea\x97\xb9\x95\x1c\x06 \x16}\x81~{\xaa\'\xb0\x93\xf3\xb4bI\x92/\x19\x85\xaa\xda\xbb\xf9\xbc(\xf6\x87\n^Uj7\xd6d|\xf0Y\x95\xd1\xa4\xf9\xa8m\xe60\xef\xa5\x9cJo\xadT\xbf<+\x8eS\xc0\xd6\xc2\x90[\x84\\\xc7\xa5P|1\x94:+\xea\xe8T\xdf\xe3\xda#Y\x8c\xad.\xbfJ\xd7Ct\xc2\xce\x8f\xd6:*+\rs\xfb\x1a\x9fSfj\x9fE\xda\x13\x0f^=\x1d\xf1\x99\x10 ^\xf0\xc5\xa3\xf3\xcd\xa1H\x02\xb9\xd9p\xe2\xa2\x8c\x9bGQ\x8a\x18\xc7\x81\xbc}\x86\x1a2\xb0\x9e"\xefI\x9eT\xf1y\x00/<\x1aG\xc5;.\x01\x7fd\xa0\xa1\xa9\xdbu{:\x11\xbfH\xd9\xd1M\x92\'7Wj`H9\xf8\x98Olr\xdf\\1\xdc7\xf0#\x11\xc3\xc5\xa2\xe4]\xfc^\\t\x1f\xa3\xc4X\xc9$\x07gX\x86/\xc0!\x18\xc3\x90\x15\xab\xd3"\xcckd\x1e\xf5-\xbb\x15\xd3\x8c\xda\x9d%y\xf5,R\xa0\xf6\x82\xd8\xb8b\xec\x93\xab|\xad=\xb6x\x89\xbc\x12\xf0AT-\xa9P\x9e\rv@(\x1dK\xef\xc6\x8a\xbf\x1dD\xc2+l\x9b\'\x9fH`\xa6b\x84A\xa3\xed\x93l@\xe5\xda\x88\x13\xec(er\t\xc3\xcc\x8f\xa1\xf7\x87\xbe\xa2?\xf0<\x86\x9d7h8z#\xc4\xbf\x9f\x8apiQ\x0f\x8a\x12%\xaf\xa6\r\xa6\xb8\xfc`\x0e\xa9\xa8\xf8\x14\x1egk\xdd* \x13\x1d[s\xba!\xe8Y\xb0\xae\x8aw\xea77\x9c\xf3&!7bY\xe6\x83\r\x9b+R\xdc\xcaLC\x91\x11\x9f=\xa9/w;u\x03\xed\\\x90G\xc6\x91\xd20\xb4\xcf\xb8\xd3\xbarm\xe4[\x94a\x97\x88b\xb2"\xb3p\x1e-\x87\xdd\x0fo\xea\x91\xf1)\x82\xfa!RU\r~0q\x0c\xee\xfd\xe3\xd6\xb8R1PC\xa2\x9f\x9b\x1f\xa5\x83\xef\xde]Y\xf7\xde[x\xdc\'\xeb6\x1d.\x7f\x90\xccdlY\xa2\x9f\xa6\xfd\t\x97i*f\x1b\xa7\x8eb\xf7c-\xb1\xdc\xa5&q\x81\xa4\x1cn\x13G~3\xb3\x84\xeeX~\xc7\tT\xc5\x87\x1a\xe6\x8c\xb05[\x11\xd1\xbd\xe3\xf3f4c-#\x924\x1f\xf5C\x137\xad\x91A\x00\xb5\xa8\xa7{,I\x8e\xa2\x84\x1e\xf4\xbd\xe1@\x13\xfc\x16\xf3\x08\xeb\xed\xd6IK\xfafR\xa6k\x08n\xe1\xe4\x8d\x99\xee~\xaa\xe2o\x84V{>\x9f\xf0R\xf7\xbd\x04\xf4l\xdb\x0b\x13rrOX\xc4\xfb\x9f\xd1pT\x9c\x1ca\xb5\x0c\xc8\xdf\xf1\xe7\xd1\xcc\x8f\xeb\xe3\xbb \x1f\x9e\x06\xe7\x9e=o\xbe~\xac\x16g\xc5\x92>\xb7D\xe1\x94\x1cE\xa7\xe3\x16\x10\xd2L\xcd%M\x1e\x8e\x0eel\xac\x95\x88\xcb&G*\xe8w\xa5\xaen\x84@\x0c\x1f\xe16\xd5x"\xaa\xd5B*;\xc7\xc2C\x8b\xd8J\x1e\xca\x97\x02\xe7V<S\x9e7\xd6\xa4\xde\x84\xe0\xa1\xb5\xfaE\xddp-\xc6\x80\xe3\xb8\xac\xcc\x13i\x15q\n#L4\x922*\x8a\xe2p\x9f`\xf4jz\xe0)\xd9\xc5\xa1\x9a\xe2\x17M8\x1aQ\x8f\x90\xf2\xce\xd5\x98\xfb:\x1b\x04\x08\x03\x0c\x10\xca\xaaZ\xd8D\'\xecRA\x15\xd7\xc0\x04\nx\x0c\x0eg\x80df\x0f*GR\x95(\xbbi\xee\xb6\xad\xb7\x9dL\x05\x94#\xf5x)\xbb~\x89D\xe6\x89\xc75\x1c\x1d>\xd2\xb2\xe4\x14\xb0r\xc21\xb3\xadzyw\xd9\xff\x17y\xdc"N\xc1s\x87\xbb\x84UA\xa91\xd2p\x82:\x06\x9e\x00.\x0c\x81\xea\xae9`\x19\x14;V\xe3\xa3}\xfa\x82\xbe\x9f\xb0\xf8\xb7\x03O<#Y\xa0bS\xd1*\x06\x87\xbe2\x19\xea\xc5\x16f\xaf\xe0=\x0b\x9a\x04\xcd%m?\xa3,\xdd\xf83\xac\x1c\xe6\xe65\xf4\xc8\x80\xfa\xe8\xf3\xbaz9\x05\x05\n\x8d\xfa\xac\xe1\xe8\x92\x92\x01p\xb2\x1f{\x80\xdb0\xc1\xf4\x97\xb7r\xedt\x06\x0b\xcc\xf5\xccHch\x02\xc7\xe5\xdaa\xb4\xbe0,\xb8\xb3\xd5\xd5\xffO\x90\xd7sU+\x8e!\x93\x90\n[M\x19J\xadY\x86\xe6:\xd0x\xc5\xbd@\xa6bNlt\x0f\x0f\x8e\xdb\x17r\x9e\xc1\xb1*\xdb-\xc4\xa7\xef\xa6\'\x15\xbd\xa0H\x1a>B\x89\xb5\n\xfe\xf8Z\x13fd\x85\\\xae\xady\xdd\xf5\x88\xca\xee?\n\xa3\x99\xd8\\%Y \xd0\x93\x89\x9c/5\xef\xab7y~\xa9\xea\xdc\x1b\xd2\xab\x89\x9bH\x93\xb8S\x11\xc3\xbc\xf4\xfc\xca\x87Y\xc75\xc4M\x17\xa1L\x1ag\x02\xdai\x8a\xad\n\xda\xbe\x93\xd6\xacm\xedh\x90\x98\xf4y\xfd+\xa6Id\xd4\x03s\x04Ih\xe2\xab\x19\x90\x84MW5z\x94z\xe1\x8f\xd5\xa6\xda/\x12\x02\xec\xd2\x85\xef/\x9d\x81T\xcb\xd9\xbf\xdcm\xc68[u\xa4!e\x9e@A\xab\xe8S\x90\xf2\t\x87(\xe0\x18\xc0Q`Y\x84\x84\x9a\x02\xc9\xcb\x96\x7f\xa9\x87\xe0!L\xa1\x0c\x9aS\xe9\xd3\xc9\x12T\xf29\x19K\x1e|?w_\xda\xdc\x16N\x00\xd6\x07\x1fa\xa8_\x16\xb2wl\x07\xb2\x04\xe4\xbbb\x12\xd9\x03\x96\td\x18\xaa)\xcd\xc0\xe8\x92\t\x90i\xa7\xefC\x08\xbf\xa6\xcb\'\xfdR\xcc\x8b\xd4\xd8\xa3D\xc9\xf0\xd7+)\x82\xb6\xc1\x90\xd9(G\x1a\xf5m\x8f\xc1\xbb\xd9\xee\xb3\xf8q4\xfc\xf7mRa\x9e\x93t\x1d\xa1\xc8\xb7\x9c\xc7T\xd4\xab\xdd\x11\xfeM\xe4\xab\xf8`_\xfbX;XQx\n\xed\xed\xdc\x9b\x1d\x94\xe9\xd1Z%,\xe8\xaf\xab\xb4\xed/\xfe\xc8\xac)i\xeaYE_\x94\x97J\xb7\x8f\x82\x1b\xb7\x11\xe9\xab\x82\xf7\xc8k\x8f\xca\xdc\xb8R\xdd\xb9\xc2k\xc8\xf7\x1e\xd3\xf5\xd3TA\x87\xabV<\x15\x96\xca\xc2#\x8e;\xb6\xbeH\xed\xb8(Z\xf9\x98L\xdc\xbe!\xd0f\xdd\xff9\x8e\xee\xad\x1e\x0b\x86\x87\xc1h\x8f@\xc7X]+L\x80\xea\xa6\xc5.N\xa3E\x84\x0f\xa7}\x8a\x0e2\x19>\x04\xa5\x16\xe4\x1b>\x99\xfc;c\xb5\x80\xda\xc7\x9d\x99\xd9\x12v\x9e\xf2\xa4>\\\xa0\x0c\xe9K-^\x98\xfb\x92\xf7\x94\xa8\x14\xdfr\xfb,\xd2?\x06\x7f\xfc\x80\xa3\xf8\xa4\xe3Wh[\xf7\xfcz\x97?\x1b\xe2\xee\xc9\xeaGpe\x91K\x90\xdc\x95\x99\xd6IyV\xc8*\xc7*DJP\xc6\xce\x1e\xde\xc0#\x87X\xf9@\xf4s>\x9d\x83\x94\x17\xfdk\x1dH\xe8>(\x1a\xad#)\x10\xb7\xd8\xc98\xaa\xd5]\xb4I\x87\xcf3\xd0\xb6\xfa\xdcI\xd8\xa7Z2\x14\x95\t\xd9Y\'\xe5\x00\x98\xdfhS\td\xc4\xbb\xcf>*\x17\x84\xca\x89\xe8o&\xf6\xe0\x1fAG\xa7l\xe3 4;\xc3\x8a)\xea\xfac\x80\x86\x1co\x12 vJ8\x9c\x81e\x90\x96\xbc\xf2\xbb\xd2\xc2M\x96\xf2oM\x06\xc1\xeb\\\xd6~\xa9/\xd5{\xbdH\x9fj\xdfRqv\x9c)\x8f7\xb1\t\xc8\x84Bi\x1e\xc8D\x06\xf7\xa8\xaa\xadtH\x04\xbb\x94\xf0\xb7\xf3\xb8\x11m\x17\x869\xe2\xecJ\xa2H\xac?EX\x18\xf9\xbbs\xf8\xbb\xa0\xcd!\xafo&\xb6\x8f\x95\xfa=%Q\xa2?\xee\xb5\xe5\x00\xd7\x0f\x93\x96\xe8\x03\xc7\xe8\xe5\x91\xfc\r\xc5\x8cq\xb1N\xa3\x86C\xb2\xef\xdc\xc4\xfb<\x97U\x8e\xa4\xf19\xd3\xccR\x7f.\x85\x84\xaf\xf2L=\xea2\xec%rX\x16\xb5#\x13\xcdLkm>R\xd1(\xa9\x0b$\x14\xb4V\xe8l\x13\xfe\xa3\x0e\xb8\x15\xaeN\xbc\xec\xe0\x9f>i\x87\xb2\xb2\xa5\x99\x89\xffK\xeb^\xaf$@C\t\x07;\x1b0@\x9a\xb5\xa5\xcdy\xe7\xb1\xbb\x1adV\x9e\xde\xb0\xb1\x16\r8=\xa0u,\xbc\xbe9\xaa\xb9?\x1d\xdc\x13!Ge\xc9>u\xc2V\xd1\xa1\x9cC\x1d\x9c\xcf\xb9\xfe\xa3\xdb?\x16\xba\x07\xb1J\x15>\xef\xabU\xf8\x8c\xf7\xb0\xff\x7f\xc8$v\xeb\xb8\x85\x0f\x81-\xca\x9c\x8a\xf9\x83\xba\xb9\xf9\x8d1B\xb1\xc3\x840 \x87\xb4\xe77\xf6\xd1H\x88\xcd\x8c\xffw\x18\xef\xc4X\x10x\xbas\xdc\xecl\xb0XW\x977\xad\x98gm\xf9Mh{\xf4r\x8b\xd6<\x15F\x9c=\xd8w>\x89\xa8\xa0R[G\xa6S\x97\xe8\xd6\x0b\xbb\t\xde\xd74\xa2n\x86\x04\x01\xdd8vZ\xe7\xbe\xb9\xeb^\x14\xebb\xfc\xfd\xa1\xe0\xb2\xfb\xa7\x06$\xfee\xb9,\n\xf5\xd9\x14M\xa3\x0c\xdd-\xb24\xef\x8e\x8e\xa1\x14cx"\x1e\x03kR\xa4eUC\xc0\x0bEr\x12\xf2[\xc2qDa\xeedoi\xe4\xeb8\xce:e\xceH\xdd\ts\xf7a\xd0\xadS\xc2\xfa\xdd5\xe0G\r\xe7\x9d+\x18\xf7\x9bu\xec\x06!\xa9\x85d)\rj\xa6y\xff\x8e\xd8\xaa\xf5R\xbc\x1b_(&\xe6+\x17\xed\x92.\xe0\xfayU\xe2\x1c\xc1\x06\x9e%v\x97: \x138\xa2.p\xc7@\xa0L{\xba\x9e\xc3\xa0\xad\x17V\x17\xec\x99V\xff\xec\xf5\\\xfam`\xe9\xc2\xb8?\xabR9\xa2H1\xc8\x08\xbd\x19\xa5\xcc\xd8t\x8d\x03zo%\t\xe0.wv\xc9lP\x10\xe7h\xb9\x81\x16\xe8\xbfkU\x1b\x8e\xd8\x85\xf8\xdf\r\xcf\xb3\xc7\xad\x1d\xe6\xf25\tr\xef!\xd1~\xf0\x9a5K)\xc6r\x99+D\xd6\x99\x9a4\xb1\xc7zrN\x9f<\xf9RW\xa2\xbek\x02\xba\xf6\xc6\xe7\xb3\x0f\x1db\xe9@\xba\x96T\xffI\'\xeaxr\xe9\x8b\xe0\xe3q{\x8a\xcb\xee\xb7V\x03O>\xe4\x01\x03[\xab\xf3b\x93k#y\x8e\xe9\x19\xb4\xbb\x9b\x12%\x1eZ$\x89\xc8\\\x80\x0ck\xf1c.\xd2\x0c\x85=\x99\xc1\xca\xeb\xe1\xcd\xc3\xf7~pt!\x81\xaa9\xacw\xe4\xc3J\xc0\xaf\xe8\xc2\x9c\xdfT\x006\x8e\xbc\xa2Y\xe2\x00\xd9\x1b&\x15\x9e\x1b>\xa7\xf0\x15\x12\xa6$\xbftt\x93|\x95F\xa4R\x84\xf4.\n\xea\x97\xe8\xadR)\x05r,y\xd1,`>A\xd4\x9e\x89\xa3\x0c}\xa3S-\xa4\x1e\x88m]q)\xc5\x1a#\xc9g<\x08\x9fo\xee^\xce\x94T\xd1\xd0\xafr\x17~\xb0\xfe\xa1\x97\xba>\xc6\xd5\xe6\xb8\xbeh4:\xc9K\x1c\xfa?)\x81\xb9\xbd@\x81\xad\xe2\xda\xba,\x82\x0f\xb0|Tj\xfc\x85d\xe4\x81\xfa\xf13\xd0V\xd7_\xad\x15\xbaI\xed\x972J\x94\xee\xcdq\xaa[\xf0\xce\xb3\x18\x0c\xc2\x88q\x95{\xb1@\xbc\x04R\xe6\x1e\xf3\x05\x15\xde\xf5\xcd\x9c.O)\xae\x05)\xda\xfb\x93\x8c\x04i;u\x05\x92\t\x1a\xdfx\xcc\xd1\xb2\xa9\xce\x18\xde\xbd\x03\xed\xdd\x84\xa7v\xc3\x98\xcfG\xe4)\nAH$8\xde\xcf\xbf\xb8\x0f\x87\xe4\x8e\x1a\x1f:5UkP{U\xd7J\xc28`\x81J\x98\x12-4\xf8\x1a\xceY\xef\x90o\x8a\x86F\xf1m\t\xa2-\x1b\xe2\x87\xb0\x98\xd9\xbfr\xbf]ula\x06\xf6\xc6XS\xba\x8d\x17\xf8.\xac\xe0\x0c\x1a\xbd\x97\xf5\xf0T\xa0\xf3\xb6\xb3\x85\xcf!Bi6b\xb1\xe2\x0b<\x15<\xa0H\xda\x1e\xa3\x86\xda\xe1\x8f\xd88\xcd\xc4\x9dW\xef\x1d\xbc\x03\xf6{\xd9e\xc5i\xdc\xf7\x95\xc5I\x85\xff+\xff\xf2\x03r\x93PH\tUB\xa4\xc85\x81\xd6\x8e[R\xbe\xec\x1b\x93W\x94\xea\x93X\x0b\xef\xb4r0S\x0e\x8c\xef\xc3\x05\xc8\x1dc\x8cCw\xb8\x05\xea\xbc\xc0\xfa\xebS\x85(\x86\xa0\xb2B\x84\x96.\x10\x98Sl\'d\xd7\xae\xe3ta\x93\x990Wx\xbc\xc3H\x03_S\x01\xc0h\x84\xf4\xd3p\x06\xef\x1f\xb4\xfbH\x16\x0f\x90\xecDs\xd49\xa0\xb0\xcbr\xe9\xc7\xb9V\xa7\x95\t5\xd2\xfc\xe4\x0f\x8d\xa5\xaf\x19\xfcE\xfe\x8c\x95\xcc\x1aI\x19\xaf$<\x1fA8AT^\x03\x1d\xcat\xc7\xb9\x8d\x07\xaeo\x99\xc0\xc8\x81\xa1\x90\x03\'5\r\xc2v\x1d\xac\r|\x8d\xa9\xf4\x13\xdfk\x81\x17I\xd4\xf9\xfaG\x9fi\x88K\xdf\x97\xdbw0|\xf4\xbe\x85\xd7\x0b\xcb$\xf3\xa9\n:**c\x10\x18\x80\xf7\x1a\xbe\xef\x88{\x87S\xbc=\x14J\xdf\xc1.\xc6\xa6\xb6_pb\xe0\xc6\xaa\x91\xa713\x9eO\xacZ\xf0\xc5\xb1\xd3\x7fE\xd9&\x8c6\x9a7\x10\x95g\x9e\xa5\xe7\xc5g\xc3\xb8f\xd5\x9e\x14>\xe1\xff\xb1\xe3OUE9\xe7\xa1oXE\xb5\xfc\xdf\xa5\xbe\xf2\xf4\n\x11\xd4;\xee3\xfa\x87f\xfb\xa1\xd4\x12]\x11\xb2\xca\xf6\xeaF\x9eI\xc6q]\x1f\x9d\xf6\xbf\x86\xbf1\x95\xa2\x8b\xb7pcN\xd3\xeeWf\x03\xca\xef\xc0\xd1\xb2\xbb\xdb\x10S\x03f\t\xe3\xa2\xd1\x84\xa8>\xe3\xda\xa6 \xf8 \r\x05\x04u\xca\x07R\xaa\xdd#\xf8\xdd\x03\xac\xd1g\x95\xaa]"\xdd\xa9\xb3W\x88\xd4\x8fj\x89\xed\xdb\xfc\x80\xce\'\x9e\xaaw\xa2\x1e\x13\xe2_)\'\xc6&\xcc\x18\xae\xdep\xe7\xb4\xc8\x19=\xc1\xa9\x91\xde\x00\x98B\x01u\xbd\x9d\x114\xc9W\x16\xca\xd1\xae\x8e\xbb"\xf55\x8c\xdb\xbcw\xd74\xed\xd1n\xa0\x86\xb4Ts\xb8\x91\x8ad\x1c\xd2\xfd\x01V\nu\xe5\x00\xc957\xab\xcb\xcc\xc2\xbe\xf3\x164f\xdd\xdcx\xe9T\x83&\xec$T\x01\xd7\x95\n:\x92\x1a\x87B\x1c\xf7,\xc9,%@\xadH\x05\x9b.\x1aPx[\xa0\x01\xe4p\xdbg\xb5D\x93n\xd1\'\x1b\n\xbc\x80+Q\x1e\x15\x8d\xd8\xe9tY\xd5u\x9anG\x89Ti9\x90\x9f4\x0ef\x00\x81"1hf<\xe6\xf5\xae\x8c\xc1\x1a\xab>\x86\xd4\xca\xac\xe1Zg\xed\xdb\x9a\x91\xbdRe\x0b\x9e:\x97\x1f\xfc\r\x8a\xca\x0f\xabLvI8\xa2 \xfa\xcdK\xca\x85b\xd6)*\x03\xab\xc42e\xfeG\x17B\x8d\x1aa!\xd7\xbdY\xca\xa6\xf9\xf48\x08\x11\x89\xdb\xbd\x18l\x81\xa8UU:\xac\xd2\xb6p\xc4\\\xeeI1\xc2\xc9\xdf\xce\x81\xf1\xe9h10\x07.\x8f\xa1Ix#.Nm\xf7\xe87w77\xb1\x97\xd7\xb8\x96\xfcO\xa6)\x96\x01\xcc\xfe\x87\xb5y\x0e\xff\xf0\x9579"\xe9N\x90t\x1e\xf23\xdfM\t\x1f\x1eX\x8c4\xc5\x81\xf0\xcd/x\xf5h\r]\xd9\x0c\x080n\xf3\x91\x9c\xe6G\xbdeeY\xb0\xf6\x9bH\xc4\xec\xa2\x151!n\xbf\x03\xecd\x83#\xb5`S\x0b\xf7\\ST\xfe\x89\xad\xb1|[.\x81*\x12y\xd5x\xaaR\x04\xbc\xc2sv\x0f\xfc\x81\xf1\x93,\\\x16n\xcbGf\x17S\x14\xea\xd9\xf2\x8f\xe9\x96$Y\xc2T\t\xd6\x90]\x8e\xb3\xda\xd3,\xd2L\xc0\x8a\x80\xb2&\xdc\xe4G#\xad*3L\xac_\x07\xbe\x8co#F\xbc\xe4\xd5^\xc1=\x81\x16\x9auI}\x81\xf5\xf1`(\x00\x06\x95Q\xa9\xeff~\xf0xR`\x86\xb6\xd0\xc1\xae\xf9\xd7\xfb\xa6\x0f\xee\xbe\xe6k\x19-M\xd3\x06\\\x0b\xf5\xcf\x9d\xb7\x01\xf2v\x95\xb4\x1cU\xd0a\xbeV\xe0%j\xc6\xb7\xae\x8a\x0eU\xc3[\xe2,B$\x06\t\xe9\xc4\xdd\x0b\xb8K\x88\xd9\xd3i>E\xe9H\x86\xc0\xa5\x97\xfe\x07\xe1CR\xa7E`\xb2\xb5Fm\xf9`\xceI\x8b\x86`wE\xf2\xbb\xd6R!lO\xf5\xd1\xfb*\x8f\xb7\xedQ\x90\t\x9d\xae\xde#y\x9d%F\xf0\xad\x92\xff\xa6\x8b\xf8\xc9\x9b\xbe\x9e\xb1\xabyae\xc6x\n\xc9\xe7C*\xe2\xb2\xfbG\x8c\xee#\xdf\x1cEw9U\xfa\xf7\xd2\xf1\xcc\xe8\x03w\xb2[\x12\xeb\nF\xe3c\xf7\x1b8\xd7J\xae\x95\xf6\x17(d~]Y\xfe#\xbe\xfb"\x9a\xa4(\xd28\xbe=\xccV\xa94\xc3o\xa6\xf0`\xfbt\xe6\x9d\xc3\xc73gX\x96\x85\xd8\xee\xfd\x85\x11\xab\xb3\xa9\x98\x93\x13\x7f\xdcJ\xa6s\x12Fx\xa1{\x97/\x8b\xc9\x87v\xa4\xa5\x1aM\x92\xc7\xd5\xe1\xb4\xb3\xb0\xa1\xb5\xfa>\xc1\x07=I\xd9n\xb7\xbcxY\xcb\xe5\x7fz\xcf\xb8\n\xde\x9e\xf4CM\x7f\xfb\x01\xdfd\xf0\xea[\xf5\xe3j\xff\xbd@\xac\x1e\x14\xe4 \x14\xf22&oN\x94\xb8\x03U\x98\x03N\xadIyao\t\xe0$\xd1\xe6c\x0eO\xf5{&\x8e\x12\xe9E\x9b\xb1<Lr\xe4\xa7*\xb1\x92\xab\x1a\xf3\xca#\x1f\x96\x16\xbe\xbf\xe7\x0b\xd5\x80TV\xa0\xd9f-\x8c\xc1\xb3_\x19\xee\xb3\xf3\x89\xce_~\x94\rQ\x03\x82\xf4\xac\xdd\xb9\x90\x0eK\x01\xec\x8e\xbf\x04=\xdc\xdc\xc8\x91yl\xb5\x17\x98\xedw4b\xbf\x1a\x1c:\xac\xc1\x91\xeag\x11\xb4z.\xd6\xa9k\x92;\x19@u[\x80N+\xebo\xd2\x08\x9fpE\x86O\xf7\x0b\xcb\xa5\x80\xf0\xbd\xf7WaY|[\xce\x86E\x87\xf3\xb3{\xba\x1b\x08\x1e\x9a\x97\xads\xea}Np!\xb1\xa1\x06\'\x13R\xf4\xd5mM^\x88\x02rU\x80\x95\xe9\xfe\r\xff\xdc\x92\x16\xc0\x9a\xd8\x1c\x91\x03O\xddA\xd2k\xf2rH\xf6>\xb2>\xc9\x12\x06\xb2\x9b\x84]\xbc\x10\x02\x18y\xda\x0f\xf9\xe2{\xa6\xdf\x92 9W\x8f\'\xaf~\xeb_\x1b\xd0T\xdc\x8fz*\x12\x9fN\x91e0\xbe\x8eU\x9e}\xd1bq\x15\x1d]-c\xa6s\\My\xef\x96U[\xbek8\x92\x91*J\xbbx\x93\xb0v\xc5\xdd\x86YT\x97\xc3\x8a\x18\x94\xdcc\xa0\xb1Ei\xb0\xa2\xad\x124\x06\x0f\xa3\xa2=c\xfa\xf8\xa9\x8b\xed\xcb\xb3\t\x0fd\xcb\xee\x1ebBK6 A\xa1W\x94\x16w"Z\x8e\xbc=\xc8\x13i\x0bJ\xc4\xbd\x8en\xc8\xc1\x8d\x89\xbb\x0e9\xb3\xab\xdf/\xf2\xfd?(\xe8#:\x85\xa0\xe7\xb0C\xa2\xef\xae\x0f\xb2E\xa2|\x08/\x969\xa1u\x82!\xab\x07\x1d\x87?1\xdcF\x1c\x88\x9bJ\xd9\xb4\xda\x8c\x99\xf7\xfa\xa6K\x19\'\xe8\xbbX\rQ\x17\x13\xaf\xb1\xa3\xa4\xee\xd4\xde\x8bGmC>\x9f\xfd\xfaCi\x0b\xb0\xb8\xb3\x7fvtF328f\x0cC\x8f\xe4ivM.\xe5\xdc\xe6\n\xec\xad\x94\x8a\x02\xd7\x7f\x1fG\x9a\xdc\x08~\xbd\x17D\xd9\xaa\x05\x15D\xa2\xb3\x8f\xfbAd\xd7\xbd\xbf\xf2J\xe9\xbb\x94\xccF@\xca\x8c"*\xb7H\xf9\xba!\xe6\x90\x17\t\x9au#!`\xf7\xcd\xb2\x06\xc7F\x83\x84\x0c?\xc3\xdb\xb9\xb7"\x063\xd4km[R\xb9jVDS&\x0f\x8eu\t\x073\xcaP\xb9\\\x84\x8b\xfe\xe1\x12\xd5\x8b\xbf\x17\'\x8b\xc1lc\xc7\x0bh\xfd\x04\xc8\'\xbb\x93\xebD\xe8\xce\xf7\xca\xea6QnsE\xf6\xf9\xbf95\xf3\x7f\x9b\x0e\xe6\xef\x7f\xb8@yzc4\xd9\xc2\xfa\xd7\x8b\x88"\xa9\xde\x01\x8a\xd5\x14\xaf2\x16\x83\x89\xdeL6\xdf\xa2\xd9v\xef\xc8Ph\xa5\xe5\xc1\x1f\xab\xb3\x8f\x06$\xcc\x16"\xfa\x9d\x0e\xc3t\xed\xc4v6\x9a;7\x14\xf2\x02BT^\xb8]A1u\xec\xba\xa3\xb2c\x9dk\xd9$\xe0.Mj\xe7\xb7P\xb7\xde\xe4SW\xab\xe2?\xac\xcc3}A\x80\xcd\t\xcb\x89\xaect\x11\xf0\xf8\xf4\x12\x9f\xad\xfd{\xe4\x1c\xfd\x9a\xcf\xe1\x11=5\xe3\x0f\xf2T\xa2\x8e\x8e\xe0(lE\x17\xf9/:\xab\xff\xc5\xcf\xb2\xa9\xe5\xcf_nu\x9a\x8d_\xe1A\x83\xd6\x95~\nXX\xf3\xa76\xd2\x0e\xf2\xf0o;\x87qdQ\x0c\x92\xaf\xd9\xf84\xec\ta\x87\xe9\x9cyI\xe9\xfd\x90\xa6\x81\xc8\xf9\xcd\xce\xe1\xc7g-\xb2L/\xa0\xe0w\x80\xdd~\xeb!V?@\xbc\xa8\xa0\x8f3\x01)a\x01\x18\xa9\x9a\xa6 \xa4"\xcc\xa0\xa7\xc1\xb4\xa5\xa2\x80\xe9\xc5\xd9\x18Vdh\xfa\xc0\x0b\xdb\xa2\xd4\xd4\xa76\xa6\xde|P\t\xa6\x9cw\xd6i\xa0&\xc6\xcb_\xce\x1b9\xf4pB\x13J\xd7\xd7\xc5\xa4\xab\x8cJ\xe3\x1e\xa9czLn\xb9\xd0\xd5\xc9MQ\xc4-\x06+\xe7\xe0\r\x85\x8d\ry\xfc\xf06\xba<\xa3\xe5\x9a\xf4w0\x95\xc8\xd1\xb0\xc8\xf8\xeb\xcb\xf6\xfc\x07\x18\x89x\xb2V\x90\xea^/\x89x:\xd6\x19\x15c!\xb6\xe9\xf5+\xe3\x9c\xe9\xf4\xf4\xaadW5/\x16|\xb0vq\xd9\xc9)|w\x1ao\xf5\xb0\x17h\x80\t\x0b\xf7\x06\x0eu\xcd\x13\x1a{a@\xb4\'\xdbN\xa1z\xe27\xe8\xda\x89\x06\\\xe6\x81\x03;\xdd\x06r\xf2\xc3\xfa\xfd\x7f\x1d\xc2\xcar[\x071`\xa6\x14\x16\xc7t\x8f\xa1\xfcs\xc1\x83\x81\xcd\xbfN\xed{h\x07E\xeee\x86a9\xfd\xdc\x03\xb5$Pj1\xe9\x94\xc7\xbbq\x93\xf8\xd0\xd8\xc7\x04B\xdd\x97\xde\xfc\xcac\xc5\xf4\xb5\xfb<5\xe0a9\x1dnEk\xb5^\x91\x02EP\x0e\xab`!\x91\x07\x014\xe3\x18\x9f\xab\xb5\xba\x85\xac\x02 \xc3\x15\x19\xf9TP-\xebj~3\xfa\xb7\x91\x9a\x9f.\xc7K\xacXt\xccJ\x9c\x87m$\x8e+\xa7\xb0\x99 }\xd8\xa7\x04\xd5\xac\xf9I\xe5O\xb3\xeb\xa2\xa78>\xb7\x92\x08\xdfk\xca\xb4\x8c\xc2H\xa9`\xdc1\x13\x9a.X\xc7\xfcs\x14\xa6\xc9\x0e\xb7\xa2\x8f\x91\xfc\x97\xb8\xa8+V\x0bd4<\xbc\xda\x11\x98\x02\x95\xf5\xedHl\x8f\xbd\xb1\xa0\xf8\x12\xb4f\x8eV\xfa\xf4}\r\x8e\x07\xeeb\x899\x92\x00x\xf7\xd1\x95>\xdb(5\xc8QK\xb1\xf8\x8c\x07\xdb\xd7\x07\xb32[\xc4\x19\xb5&!\xff\xdd\x17\xee\x87\xcc\xff\x9a\x8b\x9aM7d\x92u\xbe\xd3\x8c\xe7B\xe1\xee\xf2\x1d\x9d\x81\xd4\t\xa9\xb6\x9f\xf7\xf1\x9cn\xbc\x83CLN\xd8,\x1fQ5\xbbV\xe9\x03^\x1b\xb8\x0c>\xf7\xd2\xd0)\xce8Iu\xe8\x13\xbax\xb2\xfc\x08\xd0\xd9\xf8.}\xbej\xfc[H\xad\x0b5\xad\x86\xbe\xcb\x1bx<\xf9\xaf\xf3/~\xde\x92\xf6\x9c\xd6Po\xc7\x00\x97\xf6KzT\x15`C\xc61\x8et\x1dPm~\'$`\xdfY\xdb\x03\xb8K2\x9b:\x83\x8f\xce\x00k\xef\xc2\x81\xfd.n\x06p\xcd\'\xdaU[\x83,m\xe1p\xe1F\xb2t\x0f\xb4"\x13n\x830\xd2\'i\x14\'\xc4\xdc\x18\xf8\xaf\x1f\xa4\nR\x8fC9[\xa6\x9b\xe0)\xac\xbff\x7f\xdb\xc4\x19yw\xaa\xa5\x08\xce\xaa\xe53\x1b\xbf@\x97\x17\x99\xcf\x97\xe2 X\xd8\x80\x8bH\xf7\xb9:O=|\xeb\xaf\xcc.U;\xddG]:\xf1\x1c\xdb\xd7\xcbz\xd5n^dq\x0e\x01\xdf\xf2\x02C\xa8,]\xb2\x9e\xd0\xea\xeaG\x9fQp\x8bl\x85\xe8\xad\\\xcb\xc0\xf7-\x7f1\xfc\x9a,e6mO2\xe7\x04\xf2\xa9\n\xe3N]\\E\xa0\x8ba\x9c=\x1aaSmL\x86\xce\x9f\xe1N\xbb\xe6\x94\\t\xc3SB\xa0!\xcf\nr\xe5\xefQU\xbe\x0e\x8f\xd3(\x16J3n\xa5]cyt~\x02\xe2k\x06i~5@\xd2>\xb8a\x8d\xd9\xeeP\x01\xab\r\x83}(\xca-\xc9q\xe1\xc9\xa0\xa4\xef\x05\x1a\x9a\x1d\x99\x9a\xd0\xdfd\xcb\xed:\xac\xe2\x92`\xd1\x08\x1be\xec\xcb\xdb\x0f\xda!\xd8\xac\x96\xca\x95\x94\x80\xda\x92\x81\x17\x08\x12\xc2\xed*&,\xd6\xea2\xfcu\xea\xd1\xb4TC\xfe\xa0\x04\xa9x\xfa\x1dX\x84\xa3i\x10\xfcy\xf1ov\xaf\xc62I\x0b\xe2\xfaE\xa2\xdf\xef\xe6\xcf\xdacV\x1d\x94\x911\xd5\xcb%\xa3\xdb\x02=\xd4\x1dy\xba\xb7\xfcx\xbd1\xa0P\x9eL\x13x\x1b\xf44E\t\xf1\x82\xb2\xa1\x18I\x87\x93\x0f~\x98\xdb\x92\x9aS\xd9&\x91\x1e4o\x9e\xf3"\x9c\x9d\xa1\xfc&\xb1\xaeT\xd9=\xa2"\xd6x\xfa\x8b}k\x0c!B:\xd7\x14pV\x90gRxk7\x85\x10\xb4\xe2a3\xdf\x03\x81\xed\x06\xcf\x13\xe7\x9bE\xea\xad\xbf\x81Z\xb8\xb7\xc4\xbdb\x08\x98\xc2\xb6\x8e\x98\xb7\x97\xb4Ti\'p\x17\x8aQ\x08^iF\x87\x1f\xf5f\x0b\x115\xcaj:\xb3l\xb6\xa6t\xa5\xb3\x13!F\x9a\\|\xe2\x07\xceO\xbc\xec"\x94\xc06,\xdd\x17*\x99\xa9X\xd4GM1\xee\x12\x83F\xbf\xf8\xe3\xaf\xb6\xa0\xb3\xf0\x10N.\x97\xf0\xe3##\xd6\xa2\xa5p\x0f\xfe\x8b\xcax\xfem#\x89\xe7\xc4\xa9\x1e\x15SP]\x1a\x1b \xbb\xe5\x16\xca\xddP\xd4+`\x84T5\x93\xb5\x1c{\xd26\xde\x81@\xbd\xb6\x1d\xc5\x8c\xe1\x87\xd8-\xa8\x12\xdbsr1\xbc\xcbR\xde\xa3$8s\x81{\x06A\x85\xae3U\x15\xf3})5\xf3_\x15\xf8\xef\xeb\x9c\x84\x1a\x8e\xdd\xec0`Kh\xf0\xbbBc\xc7<\xd7\x98\x0e\x18\xf0\xb1\xd3_ i\xe5DX\xddJ:.\xdaj\xb2"\xdcs\xbf\x99\x95\xff\xa8\x13\xed\x16\xdb\x16\xd2\xaf@T\x96P\x97@\xdeO[\xc1\xae\xca\xd4\x97\xefK\xb0\x8c\xf4\x00}\xf5-"G3\xa9\x084\xd9!L)^)\xd3\'e\xaf\xa4:\xda\xe7s\x1ak\x7ff~jL#\x9c\xa4\xb7\x01a\x7f\x93\x82<\xe0S\x1c\x9a\xf8\xb5\xce-L\x80\xaf\xa9\x0e-1>\x1bL\xe4\xef\xeb\t\xb8J\x90\x9c2\x90\x10\xe3\xe0\xa1\x0f]\xa4.P\x98w/f\xa6\xd1Ru\x95\xfc\xd0\x97(a\xe2"\x8d;\xb9\x10|\xa1[\xb1\xd5~\x12\xd9hw\x8aQJ\x01\x9c\xa3\x02+\xb5\x85"Z\xb6\xef)\xbf\xe4St\xea\x85&\xdb \xab\xe6|\xaa>\x7f7\xfet\xc4q\x92\x0b\xb1{Z^\xf9\xfa\xd8yS\x98\xf2p\x13>\x1c:\xa0\xfa\xcc\xc9\xb0\xffPi\xaa\x1d=SC\xb2\xeb\xcd\xac\r\xc3\xe0.\x9c\x19x\xad/\x87\xdf\xc9\xbf\x95u\x19\xecUD\xb82`\x8e\xed2\xf8\x17[\xbc+\x0e:\xd2\xf0\x84\x92\x8b\xb2\xb6\x93A\xf2\\f\xa8\xfa\xdbn\xc8\x9f.\x950\x1e\xb7\xc2\x15\xc5\xf3\x17O\xd0)b\x19\x8f\xbc\xdf\xad\x9dd\xe5\x12\xa6\xdb-\xb8\xc3\x01\xb3\x0e\x8f&W\xb0\x16\xdf\x93\x95\xe9\xa2\xfa\x15\x862\x97\xc6G]\xa5BqW*\xb9\x00;MS\xf3\xbb\xdd\xa9DFQ8\xaa\xb4\x80\x0cQB\xe57\xd0/\x80O\xf2\xa1\xe9\x1d\xfb\x91\x08U\xe5[\x1f\x96\x9c\x02\xb6\xd6Gn3\xaeY8\xf4\x143M\xf3\x1e\x01\xbeYU\xed\xd5\x05%\x9d\xf5\xc2\xc9\x039s.y9\xb3\xefz\\\xe3\xb1\xe1\xc42\x18\xc1\x8d\xe2\x10N\xfd\x96\xcd\x18Y[H\x14\xd4x\x86X\x9e\xd4\xf9\xb4}x\xb0\xf3\x10\xbb4\xd2p{\xdf44\x01\xde\xe5\xcdMb\xc9?\x93\xfc\xd8\xafw8o\xc2v\x7f\xe6h\xf6\t\xd5\xf2\xe6?\xf9\xf8\xf2\xe4\xd0\xcf~\xca\x01\x9b\xf3\xe4\xd7<LX\xcd\x9dC\x9d\x80\xe0\xf7\n\x7f\x91,f\xf34\x19\xe8h\xe9\x81\xe8\xb6g\x1dy\x0f[GI\xf9p\x13\x14\xac|\xf8|\t\x00I\xe7\xf2\xc3\xb3\xad2\xe1kM\xcc\xbe\x14\xf1\x13\xcf\x06j\xbc\xb7\xdf\xc3\x04\xf9wr\xe4\x91c\xc1\x9a{\xad\x9c\xcd\xd6\x81\xae\x82\x85\xc6i\x7f\xf9Do\x99\xfb\xa4\x83\xd3\x91z\x9b\x84I\xca|\xcb\xe7\x8d\x00QW\xc3i\x04|H\x08c.\x8b\x06(\xd2\x15\xf9Lx\xbaA\xe0@\x8ei\x94\xce\xecj?\xee\xd9\x8c\x87\xb1[\x9d\tc\x9f\xfc\xffT\x8ee\x00\x98k\x9fV\xee\xb1\xc3\x88\xbc\xfa\x04\x91\x06\xe0%\x8b\x99a\xb6\xbb9\t\x88\xee\x91\xb8\x1f\xad\x80\x82\xe1\x16\xdc4\xf8\xc9\xdb\xd9\xb0s\x80\xc7\xb0V\x8a}m\x90\xae\x80&\xfbyo\xfe;z}\x1e\x0f\x18\x0b\xca\x1c\xa9=\xf0\x02 \xca\xeb\x06[G#3u\xfc)\n\x13\xf6\xdf\x91\xaa\xe1j;\x81\xb6n\x82\x97\x1fG\xaa\xfd\xdc\x9b!w\xf5\x1e\x9c\xd81\xfa\xbb\x93\xf7\x94m4U\xacD\xadb\x95\xed\x82\xd6\xee\x97\xdf\xab\x18o\xaf\xeau\xc3{S\x0f\x8fOd\x10\xab\xb3\xc7\x1c\xef\xed\xb7\x1a]\x86\xcb\xc0G\xc5\x7f\xe5\xf9\xd7\xafft\xf1x\x96+\xe6\x02H\xf0`\x0e\xf3B\xb8a\xc9C\xfa\x86\xd9\xdfJ\x8b\xfeA\xc3\xcd\xd9uqMM\xcb\xe9\x1f\x1c\xef\xc7\x7f\xb7E/\xd4\xa4f_\xcb\x9b"VN\xb7\xe1ve\x95)\xa1\xd3\x1fH\x9c\xde`\xf6$Q\x7fy\x14$\\\xdb\xe6v\xeeC\x16\x0f\xb0\xf9s\xc1\xd0$\x8dWV\x0c1\xd2~y\x82\xbe\xdea\xc3\xd9\x83[u\xadQR\xbb\xa7\xcb\xd6ckk\x03\xe7\xf6\x9bi\xc3\x16\x184\xce\xf7v\x106\xd1\x99\xb1\xaa\xad\x7f\x9f\xf6C\xb7Z\x7fj\x12\x12XA`\x9b\x04\x8b:\x94\xd0\xc0\xc4\\\xc9\x89\xde\xe1\x88\xf9\xbe\xebj\xe2\xc0\xddH\x08/\x83*\x14\x99Av\xe5\xbf1\x1e&\x08\xd4b\xfb\x87\xf7\x96\x00te\x17t\xae`9\xb0Y\xe9\x97\xe1\xc2\xf2\xabYV\x82R\xc0\x81\x14v\x96o\xb0X\x96\xbaw\x00\x83T\xf8\xed\xf5\xef\x18\x8c\x99\x0f\xa4P\xf2<4\xbf\x01Y\x0f,\t\xfc\x86R\xe8KO\xf4Md\xcdj\xa1\x0b\xdc0\xaf\xfa}_*l\xa3\xf0@\x988\xbbc\xed\x9bG\xd4\xe8\xf0rZ\x1c\x1c\xba\xc3\x8d\xaah\xb5\xb2\xb8K~\x87\xee\xc7IU\xc4\xb4\x00\xa4*\xf8\xd7J\x87\xd4f\xcaP\xea\x95{\xfdS\xf4k,\x10\xf7?@\xcc3\x9a\xe1\xb9*r\x80\xbbC\xccb\xbd\xa6a\xf2\x8f.X\xd8\xb8D\xd9\x9b\xf2\x91\xc6g\xbb\x04\xcc\xb6K\xa8)\xd2W\x9f\xf3\xbb\x90\xd2\xcb\xb2\xaa\xd1k{\xe2\xcc\xad\x7f\xc2\xdb\xcfW6Fr\x88\xbf\x9c\x07\x0e\xd8\xa8\xe0\x84v\xeaZe\xe3\x86\xf9\xc2\xc6L\xd27o\x8b\xd4H\xc05W\x19\x9e\xde/]\x1cg>E\x1ck\x96#\x84\x1b<\xa4$\x81\x8by:\xa5\xa1k$K\x04bU\n\x8d\x06\xb2\x84t5\xf1!jp$\nk\xff+\x86\\O{C\'\xcfU\xaa:?\xe2\xb3\xe1>\xae7\xc0\xb9\xa1\xa9k\xb0<\x03\xd7a\xc3s\xa1%\xa2T\x8e4|H\x8cf\xf6/n>\x96A\xcb\xb1\xbau\xe4\x83\xe7\x03\xde\x8e\x85\x04\xb2\x87\xe9\x94\xf9[\xd3\x03\xaa/i\n>\xc0/tj%pC\x0e\xd7\x95G\x075\xefM\xe4\xdb~-r\xcej\xe0W\xb7\xb8\x02\x82{\xcb9Uc\xa8\xcc\x13\xa2\x9f\x85\xa62\xc4}\xd5P\xde\x1b>p\xcbMBm\xcew\x0f\xcb\xdf\x94\xb8n`{\x1e\xf3M\x1e~Q\xed\xc9q\xf4\xc0k\x08\xc4Z3Q\xf9P\xbc\xa3\xbbf\x96\xd6q\xf9\x04F\x07\'T\xfa\x8a\x8e\xad22r\x90\x8e\xbejO\xf2y\xb5!\xe8\x12\x881\x8b3\nv\x08I\xd8\xc1T\x82\xb9-F!\x19\xa74\xee(;X\x91\xa8H\xf2j$\x01\xec\x8b\xecl\x14-\x07=I\x11\x8c\x19\xeaQ`\x8b\x18\\c\x87\xe54v\x1e\xd5\x8c\x9f\xcf\xa8j\\\x0e\x9a\n\xd87\x879eV\xcbzH\xb2\xe9?\xa9\x91\xf68\x8fg\x87\xe9\xede#\x1c\xec\xbb\xde\xbb\xd1M_\x98\xbaH\xea\xc6\xda\xca\xb2?\n\x10\xc5\x03\xaa\x91\'\xf8\x15Gu."\x14z\xdf\xef\xedR\x05yP\x97\xba}\x12-\x89\x94\xe1H\xdc\xd9\x82Z\x05\xab\xb9\xb6c\xcc\x04u\xa8o\x13\x1bS=\xf2\x1a\xa1?\xc4F]\x8d\xac\x1e\xe4\xa9a\xfa\xc6\x1e\x8a,<\xb6\xf7\xde\xc3"\xc6\xf6|\xe6\xaf\xd5\x82P\x07\xd1\xddQ\x10\xb2\xbb5\x99\x03\xe4*\xb5sb5@\xd2u\xe3W(\xfc\xd0"ge0\xa4E\xb1\xf0nu\xd3\xc7q\xa1\x98L\xd3a\x07g\xd8\xc9\x1c\xd4\x08\xba\x08t\xc8%\x03\xb3\xcf\xd2\x08\x90\xaa\xe0\xc2q\x01\x9f\x14\xcf\x86\x0e@\x04\x14\xd3\x9bu\xdf\xae\x10\xf0Hw.\xe0_v\xf4\x15\xf5\x81"\x05\xa4eA\xaa9\xf0x\xbf|q\x80)\xdd\xa3\xbd~\xd2\xd5\xff-)\x98VM\x1d\x8a\x9a\xaf\x10\'\x9e5\xae\xeeh\t\xa9\x82#\x98\xe6u\xabj\xfb\xa0\x01:45@\x98\xebG\xf3\xdf2(\xd0b\xcbV\x18\x92T\xb6XT9v%_\xc23\x8feD\x8co\xb8\xb4\xe5\x83q\x0e.6\xf6e\x1a\xc9]l\xad\xd7\xa8D\xf6\xdb8\xcdFp\xae*)g\xd0\xef\x987\xcc\x17S\x95Y\xcegQx\x11GyC"\x92\xcdNA$\xa3k\xd8c2g&o\x01\xb1\xee\xd5(\xa0\xc5\xf0\x98\x81A\xeem\x1c\xa5\x9a\xae\xd84/a\x05-\x01\r\xcb\xdc\xecp\xdcHY|\xdf\x8d\xa9\xd0\xcdbg\x99\xc7g\x86\xc6s\x8e\xf1\x94R\xee\x90I8\xba\x8a\xa1\xc4K5\x90\xb0Q\t\xd1\x08\x9b\xe5\x18\xc5\x85f\xdemd\xa9tP\x81u\xbcA\x97\xb5\xaf\x8cM\xa8\x87\xd2\x8e:`\x1bw9A\xea\x8c\xb3&cWOjK\xfb\x081\xcd\x8bo \x1e\xff\xe2)\xa3nX\x1d^\xa6\xee4\x87C\x97\xbe\x9f\x1a\xa4{\xc7\rcT\xfb\xd3\x15')
|
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
|