hiddifypanel 3.0.0.dev63__cp39-cp39-manylinux2014_x86_64.whl → 3.0.0.dev65__cp39-cp39-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hiddifypanel/Events.py +27 -4
- hiddifypanel/VERSION +1 -1
- hiddifypanel/VERSION.py +1 -3
- hiddifypanel/__init__.py +7 -3
- hiddifypanel/__main__.py +13 -3
- hiddifypanel/base.py +88 -3
- hiddifypanel/base2.py +40 -3
- hiddifypanel/models/__init__.py +10 -3
- hiddifypanel/models/child.py +26 -4
- hiddifypanel/models/config.py +105 -4
- hiddifypanel/models/config_enum.py +207 -4
- hiddifypanel/models/domain.py +106 -4
- hiddifypanel/models/proxy.py +55 -3
- hiddifypanel/models/usage.py +58 -3
- hiddifypanel/models/user.py +171 -3
- hiddifypanel/panel/__init__.py +7 -4
- hiddifypanel/panel/admin/Actions.py +170 -3
- hiddifypanel/panel/admin/Backup.py +80 -4
- hiddifypanel/panel/admin/ChildAdmin.py +122 -3
- hiddifypanel/panel/admin/ConfigAdmin.py +54 -4
- hiddifypanel/panel/admin/Dashboard.py +70 -4
- hiddifypanel/panel/admin/DomainAdmin.py +195 -4
- hiddifypanel/panel/admin/ProxyAdmin.py +128 -3
- hiddifypanel/panel/admin/QuickSetup.py +127 -4
- hiddifypanel/panel/admin/SettingAdmin.py +224 -3
- hiddifypanel/panel/admin/Terminal.py +51 -4
- hiddifypanel/panel/admin/UserAdmin.py +277 -4
- hiddifypanel/panel/admin/__init__.py +82 -4
- hiddifypanel/panel/admin/adminlte.py +13 -4
- hiddifypanel/panel/admin/commercial_info.py +23 -3
- hiddifypanel/panel/admin/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\t\x00a\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00\xc81\x00\x00\x12\t\x04\x00\x1f\xdd\xfe\xe0\xef\xa0\x07.9\xd8Z9\xbe\xfc\xd1:\x00\x00\x00\x00\x00\x00\x00\x00\xfa\xcf!\x1b\xe6XD\xdfw\x19=j\x0f\xcd\xdeg\x1a\x07\xf0\xad\x94\xa7\x0c\xfe\x15\x9fC\x1e\xb9\xb3`\xe4\xbb\xbc+\x06e\xdd\xc5;\x8dd\xcfE\xa9M\x00j$^\x15\xed\x0b\x06\xed\xd5c\xa0\x14`\xa3\x818N\xc5\xfcx\xa8\x06x\xd5k\x82(\xbf\r\x01$F\x06\x12i\xa8\x96oE\xbd!\xcf\xc4\x02du2B\xcf\r\xbc=1x\xaf\x17\xc8\xeat\xcds\xed\n\xf9.s\x94\xab\t\x95\x93\x8d\xee\x00\x1c\xccb\x10\xb1\r\x0e1\xc9\x88E\xea\xfe\x88[\xfck\xd6\x8e\x12\'1\xdd\x90C\xdcOM\xff\xf2,\r\xddy\xf7j)\xe5+\xf5\xc8\x04\xd6|\xd8q/Xy\xb6[\x10\xb0I\x1d\xa3\xe1}\xa5\xb7\xb0}I\x06\xa9\xb6u\\\x8a \x10_G\r\xf4\x8b\xa2\xd7co\x03\xe2\xe0\xc6\x07\x92\xbeM|\x9c\\mz\xc4\xb1X|\xb0\x11y\x0f\x01w\x86*nv\x80\xdb\xf5r\x14\x0e\xf5\x1a\xc1\x13\xd0\x9b\xb6\x91\x9e\xcb\xc9wk\xdeS\xcf\xc4\xc5\x0f\xdb|\xaa\xc6[\x1bz\xca\xd2\x10tj\xf5\xa0\xea\x84\xc1\x1do\xber\x8f\x97\x9e\x9dO[;\xd8\xec &\'\xfd\xb4\x94S}d\xdc\xa8\xbd0\x04C\x98|\xe8\xe2\xa2&p\xfe\xd3\x9e\x8bH\x8b;9\x14D\x82|\r\x02\xefW\xa9\x01+;h\x7f\xd1\x01\xd3\xfd\xb4\x0e\xa2}\xdd.\xcc\x8b\x8c\x84\x92\tD^\xd2I\xf5\xd7)\x00\xb5X\x8dH \x81Dj\xccg\xc4{0\x81\x8df$\xdc\x82\xc0\x80\xf9\x83\xa9D\xb0\xa157yD[\x93\x8eN\xdc\xee\xeb\xbf\xa0\'\xb7\xfbDq\x8e\x1a\xdb|`\x83=w9\xcd\xbf^s\xb3\xff+\x92^\xd5\xf9\xc5AO\xb7\x06$W\xd0\x9a\xa2-\x15\xee7\xa7=6\xb4\xc8\x94\x05\xa8\xed\xad\xf6\xab\xa7\xc3\t\x11\x14up\'\xdc\x16h\xf9la\xe2\xa6u\x9f\xd1\xb9i\xf0\xc1]m\xf2\x10\xd4\xaa=\x9f\x88lYU\xd2\xadt\x1e\x11E3\xc8\x80\xf5UfT\x96\x84+\xb3\x9ab9o\x8f\x93K\xe2#\xbf\xc8H|\x00Mc\xcb\x9a\xa0W*\xf4\x13\xc9\x19\xe7y\xd1\x85U\xfe\x89\xb3\x9b\xbaUA9{\xb6R\xef"\x9d\xcb\xd7\x0b\xa1\xd14\x03\xbe\xd1\xa8^\xc0\'\x04!\x08\xd9\xd3C>\xf1\xe12\xb7\x81=m\x1b\xb6\x05C\x94\xf3\xed\x81\xb5\xf5*\xfd\x1c\x9ep\xb3i4\xf0\xbe\xceU\x04%\xfe\x02\x16\xebY\x1f\xed\x1a\xa9\xa4\x85\xc9\x8b\xf2\xee\x9eu\x8c\x86\xbb\x01\xb5^yM\xa7\x8c\xf7\xf9\xf1\x04\x1b\xe1\x8cO#KM\xcb\xf2#\x11Z\x97\xe2b\x95\xe1umzk\xdc\x19r\xe6K\x12\x0c\x03\xbf\x11+\x8aZN\xd7\x87K\x94\xc0Bm\xfc\xa5\x98*\x8d}/Y\x85%\xa9`\xed\xa7\x84]\xdd\xe2\x0e\x03\x86\xdbe\xfe\x0b)\x95\xf1\x9c|):\x8e\xa2\x95q\xbd\xf3\x08\xcf\x81\x0fz\xf5\xbe\xcd\xe5<cS\xbf\x90\x07\x95~f\xa4T\xdb\xf1\xa7yw]^\x10c\xee~\xf3KGY\x06\xdd\xc9\xc6Q\xb1\xa6\xe7\xc2\x13\x9fOsM\x0e\xb0T~\xe3\xd3\xa5\xd7M\x94a\x86\xbb(\xc7\xa0\xba\x99\xb6\xacS\xef7\xa2/\r\xf1\xe0\xec\x88\xad\xfd\xf0\xf1\xc4\x12\xce0@\x8d\xdc?\xf8\xcb\xdcg\x05\xa1\xc6]\xf3I\x8d\x8a\x927\x05\xba\xf1\xa5\xfdA\xc6\xd6\x13\xff%|\x87\xb0\xf0\xa0\x95\xe9\xd3\x17\x14U;\x8c\xb8)\xa0]\xe2\x93\xba\x95\x93I\xc7D\x13\xdc\x98\x8a\x04|\x16\xf0\xb1~\xcf^\x1bD\xc4\xda\xef\x17\x9d~K\xc2^7;\xc2\xf6\xcee\xb1M\\\xbe\xccF\xb5\xf3O%\x1al\xf0}\x8e\xddm;(o\xa1\x85zp\x17\xa6\xcb\xc6(\x12\xb6g\x85\xac\xf0\x92\xcaVyE\xeb\xa5\xa2\x1c\\j\x98\xab\x13|\xb0~\xb75\xa2]N@\x8fN/\xf6\xe1\x1c)\xa2\xdd\xbe\xbf"\xa6\x97\xd9\x9a.\x11\xc0k7\x16\xfbA\r\xca\x13\xf0>\xdb\x12G\xbdR\xca\'?\xd1\xf3i\xc6s\x13\x94\xd1\xa1\xf7\x83\x84\xda\x94\xb5\xc4\x1c\x1e\x86\x1a\xe0|\x1e\xce\x01\x8b~\x85\x1c\xff\xde\xd7\n,_\x13sM\xd6\xe7\xfe/U\xb0\x01RF\xf8\xf8\\A\xfa\x99\x8d\x81o\x967u\xda+\x9a\xbf\xfa\xcb\xf6\xde\xca?\xb1\x81\xcco\xcc\xeb\xfa\xfd\xa2E\xf6\x8f\x81\xb7\xbde\xbe\xcd\xc5\x11\xa3\x1eK\xfb\x04\x0ez\xeeEl\xed\x19\x87\xfd\x97/\x85(\x1b\x88\xc3\xfcC\xe1\xac:\x08?\xc9\xa54\xf2\xad\x16D\xb4\xf2\x9b\x85*\xa8)I<&\r\xa9Z6\xf5m\x90\xa1\x04\x7f\x8b7\xa2[v\xd2O\x86#\xc9\x83\x92\xb7\xb6Q\x05\x0b\xc8\x03d\x1d\xc6*\xc9o\x80@\xf1\xa6$>E\xa6l\xdb\xf6=\xaf\xab\x1ew\x0b\x98\x07\xe9\x9f\x13\xd6N\x92\xa9\xc9\x1e]\x1c\x81S\x12\xad\x82\x06\x82\x8dD\xd9\x8b\xab?\x82\x96\xe4\x9f\xe7\xe3\xa3%[\xa4sW)v\xc8&\x07\x85\x11\x85mUL^y\xc3\xbb\x16\xca\x1f\x9e\xe96\\\x9cg\xcd\n\x06\xbe\xbb\xbc\xcf0,\xcd\x9e\x83\xbe\xf6\x8d\xb1\x9c\x0c{d\xe6vn\x03\xb0\x1f2\xe1C\x95dd\xf5c\x0e\xca^,\x05{\xec\xa1q\\~\xd0\xbf\x1f\x8f\xc9eg\xfb{\xe5\x8b\xcex\xc40\xdf%\\\x90\xd7@\x83c\x19\n\xf1\xd4\xfc\x92\x94q&c\x03.\xff^r\x8f\xc0\xec\x01\\\xb0\xbd+\xdc\x96p\x90s\xbbR\x8a\x93\xa6\xec\xc6\x91\x89\x14yj{\xbe\x93Hk\xe3\xd4\xc6!\xd1\xd5\x9a+\x0b\xd8W) \xf09\x7fOS\x84\xe2\xba^\xf7\xbe\x1f\x15u\x03\x988\xa2\xa6\xd7\xb7\x9b\x0b\xbe\xd1\xd2\xf9\x8e\xb3\x0c\xbdj,\x12\xc0`\x88\xa6u\xb9\xc4bNv\x03f\xc0\x86\xd5\xd6\xd0P\xd6\xf6\x07=\xe5oI\x97\xf4\xb9\xed\xe0\'\xf0\xc2\xa7\xd7z}\xdcP\r@\xad\x9c\x7fOJ8\xf19\x86O\xc7\xef\xd6\x03\xc2\xe1\xc1\xea\xdd\x17\xd5v\xa8\x8a\xb4C\xbf\x91\x19\x15\x01u\xcb\x94\x97\xf3\xab\xfc\x7f\x17t\xb0\xfbL%3U6j\x9f<\xa4\xed\xd7\xf0\x94\xb1\xba\xf5\xa8\xa4\xa9\x12\'\x02zL\xf5]\x96%\x8e?z\xe6\xad\x89\xa0\x967\x03\'\xf3a\xb0H\xc9\x10\x9e[\xaf\xbc\xb8\xa3\x82r\xc1\xbb\xc7n\xb8$T\xfe\r\xc8[5\x88\x92Q\x1fq\x1d\x90h\xcf\xfeAb\x02,\xae\xf8j_{\xdf\xac\xf0\xe1B\xe2I;\xd9\x16ou\x82#Ae\x9b\x15\x7f\xe9\xca/\x0fB\xce\x9e\xb2\xea]\xed\xc7\xe7\x9fT\xae4p(\xd4\xdff\xdd\xe2\xad\x9b\r\xde\xd4\xae\x06\x82D\xfa\xf2\xa3\xba\xb2\x17\xb5)YS\x87J{\xf9\xef\xe3\x0b\x96(\xb2\xe7\\\xb2\xb3\xf2J\xe7\xf4\xb1\xce\x9f\xd2\x845\xaf\xb4\xaf\x01\x94\x0c8Q\xb5|\x82\xb8p\xbd~\xe7=\xcc\\\xdc\x12\x8d\xe6\xe6\xee-\x8c#\xd5R\xc5Zr\x8b\x88[\x90uq\xb5\x10\x89\x86\xfb!\xbe\x00\xa8\xa4\x9c\xd9\xb95G\x9fsO\xa6\x0f\xab\x86l\xc0\xe5\xaa\x8a\x91H\xb1\xe9.ne\xeb\xb1\xf5\x86pFB\x18\x16io\xbe\xabj\xc7\x02\xa0\x91ky\xab\xac\xea\x94j\x8b\x1b#\x85\x05hp\\][\x83\xbb\xad\x8c\xb8\xf3hW\x19\x8f%(\xf7\xf1\xdb\xa1\xf9E\xf5\x9bHL\xd3k\xc9X\xa2V+7\xb8h\xb1\'\xef\x0f\x17b\x8e\xa2\xc7\x80\xcbpBO\x83[\xe3J-\x14\xfe\x1c0\x8b\x06\x9d\x15\x83N\x8e\x02\x03\xdbv\x1a\n\xf7t\xb9[\xe1\xb0\xea\x1f\xc4\xb2\xe8\x99\xa2\x9f\xc8+\xbbc\xa2\x90\xde\xf91o\x903\xd6;\r\xa1\xf3\x80\xcc\xa9\xd1B\x10\xb5\xe1/\xa1\x04#\xa4K\xc5\xa4\xfc\xa4y\x85v\x7ft\x17Vi\xd5\xc0\x8eG\x04\xe6m\x9d_\x84\x88Hua^%\x90\'-\x86\x07\xf4\xa1}\'w\x7f\x80\xb1vf\xbf\xa43\xbc\x8d\xe5\x00\x9di\x18\x06q\x15\xf7\xb1\x90\xc6\xe2V\x93\x07+\x91\xf7F\x03\xb4\xdc\xc1\xc7\xbbSL\xc8\x9e\xe3\xc0=\xb5&\xdc\x1a\xf8\xd9%\x00^\xf1\x88BH\xbc\xfc}\x12\x12W\x80C\xf7\x03B\xd8\x9f\x93\xd9\x8du89M\xab\xa9\xc0(}`\x19\x10e;f\xef\x81\xd7\x1f7W\xd3\x12"\xff%\x91z\xac\xfb{=4a\x92\xc1 \xe0\xc9}3:\xe5\xffu*\x1bh\xef\xed;\x7f\x03,\x85\x0c\x04{\x9b"w\x18\xd1\x8aL\xc4n6\x7fm\x97%\x855Nm\xcd\x11,\xcaY\xae\xb3\xda\xe1\xb6p\x03\x81\xc2\x18j\xe1\x0e\xcc\xe4\x91\xab\x88T\xbfQ\x95\x12\x1aY\xfc\xaa\xd0\xf2\x0f!\xd5\xa99Dc\x83\x9at\x1a8W#\xe2\x1c\no\x13\xb0F\xb42\xf7C\xe3\xcf\xa2\xb4\x80"\xe5N\xddSw}\x80\xc8\x8a\xcc\xf1\xc6\x88\x97/x\xc2\xe8ri\x99j\x94\xe3\x9cp\x87\x12\x98\xb2\xb8\xf88\xa0\x8c\xd0 \x82\x1a\xf4-\xb0{\x8cFRuB(O\xf5\xf6\xbb\xb3\x1fb\xae\x90\x15\xbf\tf\t\x85\x9aF\xba\xa2\x82\xfb\xa8X\xae\xef;\xa8\xf2p\x8e\xb0\xb6\x10\xde~b\xc2\n\xd1E\x05T>\x9c\xd8^Yq\xa3\xb0y\xe8\x8f\xb9\x9c\xc7\x85\x03\x83]\x82\x0b\x96\xa1m\x066\x95EA--\\\xb1*\xea\xa86\x1b#\xa7\x96\x9d\x8c\xd9\xb0\xd2K\xb9\xa3\x87\xfcW\xef\xa5\xe24\xaaw\x00$jjj\xb4\xedy\xdaS\x1f\xebg\xf5w\xdf\x04\xe14z\xda)&\x8d0Y\x1a(\xdfy\x08\xa6S?\x8c1G\x80s\x1d\x16{#\x87\x8e\x9b,\xa4\xc0xH\xffql\xb5c\xd0\x0f\x85~\x99\x87\\\xa9\x0e\xae\x14\xbe5{@\x93^,\xa1\xf0}\xcf\x02\x121\xb4\xeaJE\xadg\xc5\xb2Md\xf6\x9a\xa5\xf8\xb5\x9d\xa8\xf1a(\xf4\xb3\xda\x07XF\x08{\xa3\xa1<\x08\xe1\x9ef[C\xe9M\xc1|\xc7\xe3\xa3B>>bY\xbfpm\xd1p\xc1\xf8+~\xad\x95\xeb\x8e?\x8b\xbe\xd4.\xae_$aJ\x9b\x92\xc3M\xb1G\xf3l8\xe3\xfa\xda\xfb\xd6\xa6\xd7\x93$1\x89\xc7fYv\x04\x1bP\x06\t\x17\xa1e\xa2\x1c\x9e\xd9 \xe1V\x01P\xa2\xd4F\xf1\xfbZ.j\xa5\xea}Xk\x99\xb4\xbb\xae=\xa3\xe46\x05\xc5/V\x92~\x96\xef\x1b{\xe5]f\x0c@\x84\x9aQw\xadG+\xd7\xbdQ\xea\x1e\xe1\x8d\xe2@=\x80\xd0\x98^\xa5\x7f\x14\x7f\xd3\x8f\x86[\xfe\x8e8QU\xab-R\xd6\x10Z\xfd\x9aV\xeefC\xb1\xa7\xc3\x96\xa8\x9b\xbdc\xcdC\xb9i\x11^ Y\xdbV\xc9\xeb\x9f`]#\xd9\x91\xb8\xbc\xfb,\xe7\xa7\x19\xca\x17\x9a\xd1\xf1\xf0\x91\\\x9af\x95![h\xe2C.\xcc\x15\x13o\x0e\x1c1\xfcm\xcc\xa7\xc08\xb6\xf2\x87\xeb:<A\xde\xfc\xc4q\xca\x1cgy\xe4l\xb8\x82\xf1S\xe3\xb8\xed}l\x96\xda2\x1a\xf4\xfd\xa4x$\xa9\x00\x8ad\xf0\xce\xb3\xaf\xba\xb6bVR\xe3\xdf\x0c\x83\xdd_R-\t\x1b^\xc3\xc9tjf\x04\xd7\xd2\xaa!\x1e\x1c\x01\xddn\xdc2\xbe\xd8\x95\xf4\xd2\xc7\t\x90\xefM\x9f\x07\x11\xb6O\xd8B\xd1e\xdf\xd9\xdaV\x05\xd14\xe4y\xc0\xdc\x88\xf1\t[\xd1O\x12)\xd5\xb8\xbfH\x8f\xf60\xdf\xd4nz\xdc\n\xe8\xb7lN\xe7\xe3\x98\xc1\x1b\xd8Qe*\xcb\xc9\x18i\xc7\x81H\x93\xdd&\x8999\xdb+\xab\xae\xad\xfb~"\x1a\x7f\xfdb\xab\x90>\xd9\x85\x16\x9f\x8a1\x92\xde\xc6\x02\xff\xea\xe1H\xe2\x81\xa9\tkD<\x0f\x93u\xc4\x85\xa9&\xa5x\xaa`\x93\xf1\x9e\\i\x9b\xaf\x95\x8f\x06m\xeb\x86\xc1\x84Px@\x86\x12\niOm\xf6\x1bg\xe2\x14y\x12\x89)\x03W\x86Q"\xf9\xc5S\xe6:#\xcb?\xceu\x13\xe5\x08X\xaa\xf70\x8d\xad\x98"\xc4G5NW\x0c\xf4#\xbcp\x8c\xf84\x9d\xa3\x8f\xb3\\\xe8\xbe\'\xf0\xd0\xa7\x0f\x84\xf3"\xc8\xcc5\xd9\x81\x9d\xe9$\xe6\x84\xc0\xdf\x94\x8dJbB.\x1a\xb0\xe0.pD\xdb\xd0\xc2\xec\xbf\x1c\xe1\xb7\xb4\xfb\x1e\x05W\xd1\x9b\xc9JEa\x84v/#\x8e\x04\xe0\x93%\xfdg\xa25e\x94J\xc7k\xe4=,\xc0\xd9X?\x1f\xca\xda\xcb\xe8\x92E\x81[J\x80\xea\x84\xfc\x1aY\xfe\x9c\x95\x95\xe7Mg\xf7JJ\x116)i\x9f\xe8\x01f#\xaa,R[\x18\x08\xd4\x9cE\xdc\xbe\x86a\x95\x92r\xf5\xc7t\xf2\xa7\xeaF\xc4\xf9\xd5\x9c\xb2OLV\xd6\xf9\xc4\x06\xc6<\xc1\xee\x84\x18-9\x06\x07\xcf\x13R\x1d@\x9b&<\x98n\xb3\x8a%\xd6\xa7\xe7\xf7MB\x05;\xc5\x9b\x1b\xb2_+\xd2\x05?\xe8\xdd\xb4\xe0u\x0fa\x17\xde\x19\x99.\xe6\x18\xc84x\xcf/\xf3\xbb\x14\xcf?s\r\xafc\xb7m\xfb\xe2\xe8\xf3\x96/\x8e\xac\xe8\xaa\x9dW\x8fm[2\xe7\x84\xb1y\x94(\xa6`\xfe\x98\x03\xa7\x12\xb0\x854x\xa8\x92\x1a\xde\xc2H\xd8\xba\xb6k\xdaq\xec}\xf0X#\xc6\xe7\x8ae,-b3\x9c\xc5\x9c\xf2\x03t\x7f\x132`\xc9\xd6\x9cr=\xcf\x176\xb2\x7f\xdd]P;\x1fcUP\xa1\xee\xee\xd06\x86\xadW\x1e\xc5I\xa8L\xf2\xf3\xd7\xfe\x8cN\xa1\xe0=\x17m\xe4\x88\x03\xdb\x19\x0f\xf93\xb1!\xd7^;\x7f\xe1\x9f\x86\xf7\xd0\xb3\x9f\xac@\xc1\xb1\x87\xa81\xf7y\xf1\xbb8\xba\xea4\xc4^"!\xbam\xaa\x94\xf4=jH\xb3W\xc4d\xe5$1\xd9\x17\x03*\xb9.8`\x8b\x8a\xa1j\xf7/aYVS\xb8\xbe?#\xd6\xdd\xbb\xf1\xa7\xf2W\t\xaaC\xe84\x07\x9f(\xd9_sn\xf5do\xe1\xcb,{\xd6\x03\xffF\x89\xca6O+o\x03/\xe0\xee(\x90\x03\xff\x93B8\xd5\x0bu\xc8lw\xde\xbaY\x9e\xca\xc0x],\xbc\x14\\>I\x84\xfe\x84\x06\x0b\xea\x1d\xf7uDu\xbbv=\xd5\x84\x83l\xe2\xa0\xf0i\xba\x03\xa0\xbb\xedC\x81\x15\x13\xc2W\xaa.\xb9_$\xf0^\x13~\x80u\x82\xbaG\x00\x8a\x98yq\x85\x8ar\xf5!\x89N/WC[\xfbN\xdc\x10\x9f\xf4\xfd\xb5\x98\xbaA}}\x92\x88_\x0bd\xe0\xd4\xd6>K\x91~\xa6\xf2\xe1\x04a\xb0\xae=\xc3\xd6\xd9\xa6&\xe0\x1ap\x05\xac\xb4\xc2\xcd&\xbdO[\xfe\xb7b&\xf6\xf3Z\xdf\xd1\xb9\xf5\xa1\xb4\'i\xf8\x1d\x02\xde\xb8\xad\xc1\xfe\x8e\x9dY\xbf\x0f\xe7\xed\xc2xa\x1f\x15\x93\x9e\xb3F\xbe\xc52\xf9\x01\xb6\xf3_\'\xa7*\x7f\r_\x00\xb4\xa1@r\xa3t\xad\x07b\x85Gg\xf0s;\x10t*|\xe9\xf4\x15b\x1b\xf3\x1e\x05\xc4\x0fS\xed9\xb3v\xaa\x8b\xfb\xa0\x01\xe1\x9a\xe6\xe3 :g\x82\x9c\xf2U\xb5l\x14\x85xK\xea[4\x0c\'\x13\xdd\xb7K\xca\xa4\x90&"0\xbe\x84.c\xe3\xbe\x1b\x97\x9eg\xb3-)\xb6\xe6\xf4u\x83\xfb\r\x13\x07\x99\xbdb\xca\xb6.\xe1\x8d\xa0\xe6\x93g\xdeM\xe9M \xf9\xc7K0\xacG\xb7\xd7_\x0b\xa4R\xa8\xc6\x1fk\xd0\xc6\x8f-2\xe0\x94=\x8bO\xec$\xbb5\x1c\xada\xfc\xd0H\xb0\x9f\x94\xdf\\om\xe6\x03W\x9d\xbc\xb3\xd3e<\xbd@\xd4\'\xbf\x96\x00\xb6:Lgl\xcc\x90\x8a(\x8b\xd6H\xff\x18U\x83\xa7\xe5\x9e\xfce\xe5J>x{&\xb7\x9a7b\xf0/\x96\x1drz\xf47b\x9c\xb5\xfb\x99-p\xb1s9D\xcf\xda\x91\x05\x9f\xa4\xccC\xab\xec=(\xae\xe1\xa4\x98\x17\xbc\xb2\xa5\x0fK\x8a!\xd5\n\xf1w\x82\\\x99H\x80H\x04\x98u\t!\xd8\xff\x00 \xa6\xd6^U\x089\xffU\\i\x97\xbfp1[\xb5\xb6\x052;\x87\xec\xa6\xb3\x17\xf1z{\xa1\xda\x87\x1dM_|\xfa0\xee\xe9u\x88S\x7f\x08?\x9a\xd6?\x8f\xb8m\xc1ZT\xe1\x05\x8d\xb9\xa3g\x8f\xefu8q\xf3=G\x02Y\x9a1C\x9df\x17/\x83\x8d\xb3\xce\xd3D-\xd81\xf2\x00\xf7\xed\x81\x8c#\x9f\xf0e\xd0\xf9\xf5Hb1)\xe8\xadM\x85.k\x8f"\x12{\xd1\xb9\xe5{\xf2\x07\xb3~\x81\x13\xd9}\x07\x0f;\xb6\xd1i\xe4\xa2z\x94\x11+\xb8yd\x80B\x80x"\xa94m\x13\xcd\x89FK\xf5\x85\xaf\x0f6_\xa8d\x96ho.\xd39\x15\xbep\xcf]\x1b\x08\xe0\xc6\x91q\x15\xbcl\x87\xf9\x1am\x9fT\xe5\xdft$\xb1\x86%\x9cr~\xaa\x84\x16b\xb7A\xad\xac_\xcc\xc2\x89"\x11\x1b\xe0\x04C\x182[p\xc9\xa1\xe5\x8d\xa2\xde L\xfc*\x17,\xea\xe3EPS\x1c\x10#\xe2\x99\x02\xd5x\x97io,\xfa\x8dW\x90\x83\x9fAJ3\xac>H\xa4^\xe4|\xad\xe6\x8f\xde-\x04H\xb6(\xb9\xe2\xeb"\xf76\r\xec\x1fb\x0c\x80X\xe0ic}\xf3\xc1\x89~\xde\xb1\xc0\xbc\xcc\x9b\xe6L]a\x0e\n-\xc2\x9b\x90\xf4\xdaA\x0f\x11y\x90:\x93Cd\x08"\x9f\x19;\x94\xd2\x96w\xc4\x1b:\xdf\xd9\xe1\xb2c\xb1\x0c\xfb\xa7\xc0dde"\xd1\x81\xfep\x92\x818\xf4\x03\xa3\xa5NI\xb7\\\xba\xc9(\xb1-\xfd\xcb Irc\xe8\x0b\x80\x18\xb5\xe8\x14\xbf\xf0\x0f\x87*e\xdc\x7f}\xe4\x81\xc9-Lxz$0\x1b\x02S\xa0\x9d\x04\x123\xa7\xb4\x94,\xcd\xc7g\xc9\xb4i\xd5\xc5\x91\xe0\x14L\xb4!\x80\x90\x02\xaaR\'\xb0\x1f\x00\xae\xdcP\x1c/\x08\xb3\xb8R:~\\-\xdfx\xc79\x8e\x15\x88\x19\xe1\x9dR\xbb@\xe8]\xe9\x87\xab\xfdy\xd0I\xa9\xd7\x99\xe0r\xa5\x7f\xfc\x88\x0b\x15\x86*A\x13Dq\x1b\xed\x13x\x8d$=_\xfc\xf1]\xb4\xf1\x0e\x16ju\xb6H\xee\xd7\xe5\x1d\x17$\xb8j\x7f\xa7Mvg\xb1\xe8J9KX\xf2\x16gz\x8a\xf9\x0c\xd4\xab\xf2F\n.i\xc8\xe0(\x1d/uJ\xa6H\xd0/\'\x1d\x82\xf2\xbc\xa6\xc4^\xa4\x1e\xa5\x1c$\xfa\xc4\xa2Bw\xb6\xce!1$eV\xec\x03Tq\xd7U\xd9\xf8m1\xf8\xc0\xb6\x08\xfd\x1f\x9e\xc7#\x95\x14Z\x8c\xe1\xe7A\x01\x83Aj\xaey\xf6L<\xdb\xca\xec\xcfA\x1c_\x0f\xc0\x99j\xb6VLt\xc5Vn\x7f\xb8\xb6\xe2\xbf\xc9\xf8V\xc3w\x91\x0exq\xd4\xcf\xe7\xe1mE/Bhp\x89\xe2\x9e\xfd\xad\xea\xa5\xf67\x8c\xabE\xc3\x8e\xd5PD\x1f\xce\xb0\xb26\x85[f\xd8\x18\xac\xaf;W\xa0\x9dva\xf5\xca*\x9f\xb9\xdbV\x12\x84\xa9\xef\x9b\xb6\x9c\xec$>\x01\xd6\xa2\x96J\x04\x8e\xecmw\x91?\xd0\xf6*U\xef\xd4\xa1\xa0\x0c\xf1\xf5S\xba)]\xfcZ\xbe\x93\xa8\x84D]i\xfb&\xd3@\n\xd5tq\x99\xb6\xeb_^\xdb{\xd2\x18\xce\x87\x90d\x9amI\xe8\xda\xd3\x8c\x95\xd9\x17\x84\x04\x9d\xee\xfc\x81;\xa6|\x88\x8f\xec\x97\x05,\x04J-[."\xfe\x16\xf0\x06\xe3Z\xf8\xe1__L\xb4f6\xee\xdaM\t\xcf_\x01\xbd5\x81Md\x0c\nF\x0ev\xe1\x91\x872i\xa5@\xbc\x1a\x84+8}q\xb9\xdeq\x0cS\xbd\xc2\xb2\x07f<YE\x13\xedz\xf4P\xce[\xb5\xba:(\xa8\x8f\x01\x93\xa2\x93^av\r\x81\x8a\x80- \x15\xa0\xa5\x0b\x94\xdb\xe76\xbf]\xfd\xa0\x93\xf4\x93nzafY\x0e\x91c\xf0\xb4n\xb06\x9f\x08G\xcd\xb7Mz\r\xc8\x94\xee\r\xb3\xa0\xdcF.=\xad\x84D[}\xe6\xa2\x0c\xa2\xd92\xfc\x80p\x84\x8f\xcf\x08\xfe4\xadx&n\x82\x8a\xbd\xc4\\>\xa0o\xca\x08\x86]\xd6\xad=\xdcX\x82-"\x02\xeb\xb4;fc\xa12d\x86u)\xc9\xb9z\xee\xfd\x00M~\x97\xa8\xba,\x02Y\xf8MS\x06\xc7\xbek^\xf3g8G[\xa6\xe0<\x04u\x80b(\xe5\x8d\x07:\xa9\x0e\x95\xf9s\xeaZ\xea"6\x94qL\x18\xb5\x94In\x00\x87\xff@vP\xe7\x01^\x95\x93\xc3B\x82\xcbk#\xb6\x1d,z\xb0\xc8d\x93`\x9c\x1a\xe9\x1e\x8b\xa7\xa5\x85Mm\x89\x11\xcd\x11\xeb3\x801\xb0Jj\x00\xb0\xd8\xbc\x11\x9e:\xdbNco\xf7u\xa6\xde\x90\x9e\xa6\x8f\xa5\x8f\x96\xa7\xbe\x11\xf7e9\xfc<\xea\xc4\xfa\xfe\x1c\x91%|\xa5\x91\x86\xa7\xff\xb6y\xd0\xd3K\x8a4\x82\xa3\xbfqc\xd4\xe8\xe7\xaa\xea\xe0\xd5\x19H|\x05$\xc2\x0f6\xa2\xc0\xb7mf:\xa5\x1c\x8f\xd2\xa5\xa8m3\xd0\xfe\x85`\x998U\x87_\xf6C \xe2\xd7\xe2-\xd7#(\xa8\xd1K\xc5\x1dB.i\xfa\xa2W\x89\xc7\xf9\xc0\x18>\x0c*\xf2\x14\xd2\x06\xbb\x89\xaf0#\xeb\xeeK\xa4\x83\x9a\xd8^\xa7\xc1d\xb1\x9b\xeb\xd1aO\xc9\xcd\xabg\xd9\xf1\x8b\x9f\xb1W^8m\xb4B\x92z\xf2\xa1J:\x8c\xa5\xe8\xd5\x92\x02\xb1L\xa3\xf4\x96\xb0.]\x01>\xbe"4?\x05r\xdaf\xdbD\t=\xea _p\xde\xbb\xba\x8446\xdf>O\xfc\xa5\xca\x02b\x0b\x9d!\xc4\xd4\x95\xe2\x0b@L\x98\xb1\x04\r\x8dv\x0ff\xc8\xb2\x1d.\xe5?\xe5\xb1`\xde\x15\x85jT\x96\x8b\x8c\xfb??\xc28ml\x16g\x95\xc5\xbf\xdb\xb3\x8d"}\xe6\x96>\x9d\xa0\xb8\x0c\x87\x1c\xcc\xec\xe9\x1c\x1c\xa8\xed\xf5\xde\x95\x02* \x92\xd6\xf9?\x91\x87\xeam\x9e\xc9\xaf\x9a\x06\xaf\xf5\'\xff6f\xce9L\xb3\x15W\x1d\x99\xab)#\x9a\x96.I\xc0Spy\x0e\xa0@\xab3\xb3\xb5\x8e\xf8&\x08\xf5wE{X\x19r\x0b\xeeb21l\xe0s\x0c\xf8\x0cD<0m\xb6NE\'7(&\x8c\xb4\x05\xcf\xbf\xf5<\x91s\x83t\xa8l\x1c\x06\xd3\x7f08o\xe1\x88]\x98?)\xd8\x88\xfc\xb2\xd2e{\xdb\xb6\xf9Qn\x08iF\xf8\x8aU\x92\x9e\xdf>l\xf9\x0cq}\xce*F\xac\xfd\xb4\xf5\xa9\x1fa\xa6\x17\x9dY\x80&\x12_\xcdh\x89\xb1J\xea\xfdYEm\xda\xca\xb9\x1a\x03G\xfc\xb9\x9fhn\xc6\xcd\x1d<~\x1f\xc2|\xb3\x81\x07\xc4\xfb\x98(\xd9\xabsM\x89\x00T\xd7Y\xe4N!\x82\xbbc\t\x06\xff}\x9bhMTu{\xef*\xab\x9f\xb0\xbe\r\xb2\xe3\xa6\\\x16\x94S\xf52n\xcd\xa6\xa0\x01\x91\x87\x86F0\xe1=M\x1b\x1eO\xaa\x9fNU\x89C\x8b\x83\xe5\xb0\xd4%\t\xc2\x0e\x986\x99\xdc\x83\x8e\xd4\xc0i\xf5zsg\xdd\x8c\xbe\xc0d\x00\x85\xd5k\xa5\x18 o~\xce(\xeb\x1c\xb3{\xf6~\xd2\xbd2\xeda\xa6)\x16\xbeGmp\x81K\xdc\xf0-\xd0\xc1X\xdf\xf5\xbb\x98\xe6\xac\xd4(\xd0\xa2\x13\x9a1\xaa\xe8\xa8\xef\xdd\xcap\xcfG\x02\x12\xc8\xad\x03@%\x15sJc\x9d\xa3\xc04#)\xcdB\xadh\x94\xb0\xeed\x0b{\xc5\xe3\xa5\x96-\xc1\xf6\x86v\xcd\x03vzx\x01\xd7h\xc7\x12fP~\xef\xfb\xa7l~\xcd\x84\x93R\x80Q\x0f\n=Ap\xd3\x13\xa9DN\xa2\x8f\x81\xd5\xc7Iym\xb0t\x1f\x90\x04\xaf7#\x95\x10g$\x07\x1b\xa4\x1dTe0\x83S\nD\x90\xfc\xf7\xed\x94\xfd\xa8\x85\xc1\xa9\x01\xf3\x92\xd6\x93\xdb\xfdZ6\x8fm\xfb\x92\x8f\xe0\xaa\x89c\xe7i\xc7\xa6\x9b4\xb4L\xc5\xae\x1cb&R\xda%\x1a\x96ES\xd1\xd5QXM\xab\xe7UN\xdby(\xacM\r\x84\x0b\xdd\xea9\xf7\xb0m\x8f\x944\xd6+\x19{e\x96Y\xf5\xa2\x91xy\r\x83]\xd6iAB1[s[\xe0\x02%\x1dN\xa94\xa4-n\x88\x02\xacX\xff\x8f\xa1\xdb\x1d\x00\xcf\x06\xeb\xb82Q\xe4\xdc=6\xaf_{\x9cA\xddg\x03|\xb6\x14\x1d\xeb\xeco\x08\xe9\x84V\x0b\xdb\x1f}Uq\x9aq^r\x9cw\x8a\x06\xdf{A\xba\xafW\xf2o06\x16kN\xa9\x9f<.\xdf\xb1\x10;W!\x9aU\rw\xebo\xec\xd2B\x034[\xf6A\nv\xde\xba_w\x87\x8d\x1c\x182\xaf\x91\x9f!\xb8\x86j\xd8Y\x99\xcc\xfdP|\xe4\xc1.3\xbd\xc9VZ5\x1e\xffs\x02\x808\x8a\x93\x06k\xcf6D\xb8\xcact\xb6\x1b\xb8\xf3\x13\x14\x8a\xe1*\x85SA\xcc(L\x13[\xb50\xbb3\xaa\x14\x93\x0fj\xcc\xf8\x14\xd4\r~\xc8L\xebX\xb5\xf9\xa3\xee\xa1\x81\xf0p\x05\xba_o\x1b\x9c\xe2\xc0I\x05\xec\xc6\x7f\xe3\xd9\xd8 \xa3LgJ\xd7\xd6\xd2\xc1\xc4\x07\xd6\x03l\xf4\xa0\xf8\xd4\xf6z\xfa\x16\xe1\x7f\x81[\x8bP2\xd6x\x13\xfad\xe3<\xc1\xf1\xb9^\x9b\xf9\xf3\x95\xf9\xb0ay\x98\xc6\xa3c\x82\xf2\xc3\xd8@\t6\x8b\xd0\xf1\x83A)!\xf5\xa8\xd8)\x86cp\xe3\x04Udd\xe4\xb7V;A\xc1\x0fwN\x06\xda\x91\xa1\x01\xe9\xa5\x02!o\xe8>D\x08\x88\xde \xdek\xf9\x94_\xa1\x06\x84\x10yj\xd6S\xc0%\x8d\xc7\xc5\xf0\xba\xd2\x8e\xed,\x16C\x95\xf8\x06\xc0\xff-\xd4\xafn\xf2\xf7\xdf\xe6\xd4\x04\xc7jcO\xd9|#\x98yQg\x04OdB\xfc\x1a\xc3!\x9b\xfc\xbf)>\x94\x81\x9eVGL\xa7\xac\x7f\xe6\xdcZ\xa5%\x05\xbfR\xddZ\xd2q\xfe\xde?s\x15\xd2\xcc\xc6o\xe5ZA\r\xf0\xba\xa0_)\x07m\xae\tI\xce\'~\x89Q`!\x82\xc2O\x12\xa7\x82\xc1~\xe3\x86\x010\x89\x7f\xac\x14\x88\xad\xb2Vu\x0b?-!l\xcc\x1cx\xde"\xb4h\x19\xb4\x12\x93\xc2Z%\x10\x16`@#K\xb1\xb18\x05\xce\xd1\xb6\xb5\xcb\xb5\xd0\xa3\x1c\xc8\x16\xb3|\xe5\x8a{f\xa3Q_Et$\xe30z\x199\xdb\xcf\xe6\xddn\xe0~\xd5\x0fU`b\x85\x06\x16\xae\xdee\xe1\xe31\xcaiV\x8c\xae\x19X\xe9^\xb9}7\xf0\x976\xd0\x89\xc4\xe9|s\xe1\xd6 {,~\xed\x80\x9bJ\x0f$\xe5K\xf2\xb5+\xf8t\xd4\xf4\x1e\xa6\n\xb4\xf8>\xe3\xcf\xa3\x17,\xa2\x9e\xcc\x0f-#\x98h+\xc1\xae\x1f3\xdf\x120\x85\xb0F\xa3\xf8v\xd4\x83\x13PQ\xbb7\xb3\xd1\x86=S\xb5\x8b\xd7TX\xe4#\x07\xc9\xf6\xe3\xb2\xb9\xd79*"\x8c\xb9u\xf0}\xcc\x10\x06s\x9cO*\xba\xbc.\x13PZ9\x1e\xb0}\xbc\x91\r^x\xaa\xfb\xe37\xeaj\x8c\x8a"\x83\x93!\x8a\xc8\xa3\xdfF\x184m\xb8\x98`\xa0\x86s?\xf4v\x15\xc28p>.\x7f\xedG\x1b\x9f\x91\xc4P\xbe\x05z\xc4\x0ec\xec0\t\x7f\x06\x1e+\xd0\x08\x90\x16\xf9\x9atf\x9ag\x81\xd8A\xd0nt_f\xc8D\xc1D\xc2I\xc6\xe8uOAN\x8f\xf3>{g\xec\xff\xcc\xafu\xe6\x969\xa6\x8b\xa8U\xd8f\xabu\xb5P\xf9\x19\x9e\x03\xc3\x8f\xb3sFG\x90F\xd0\xb8\xb9f\xa4-\xea\x18\nQf\x12\xbc1\xee\x817B\xf8r\x98\x97\x14\xd4\xc9\xaa\x99qC\xe7"1\x99\xa3\x05z3m\xf9\x9e\x82o\x14\x11\xc4\'\xca\x85\x1b\x97\xdbt;\xfc\x1a\xb3uhe.5\xbc7\xf8\xd7\xe8$V\x1e\xb2\xbe\xeb]\xcd\x830\xc1\x1f%\xf7;uG]e\x08$\xf1\xc12\x01V\xdc`\x9bK\x9c\xc8-\\\xc9\xdd\xee\xbd\xf90\xcc\xc1t\xe0Ms\x8c|\x9d\x03IV\xae\xa2\xfa\xf4\xa2\x0fH\x9e;\xcc\nI\xdf\xd3\xb7\xbf@\xa9M\x8e!\x14\xf7\xc38\n\xc7\x9dI\xb0\x93\x92\xeb\x987Vi\x19\xb7\xce\xf1\xfeB\xe1X27\x10cA\xa2\xe0\x94\x06\x9a)GR\x96\x1bv \xfbm\xbf\nAb\x0c;m\xcfPxxy\xa24\xa9\xf8\x82P\xfclwq\xc2\x98\xb6\x12\xddA\xfc\xf9R;\x0c\xb3\xddy\x86\x9b\x9a\x07S\xfb\xfcx,)\x9b\x99\xaf\xd3"\xb8\xa9Uu\xb4\xe0\x94>\x173Q\rr8\xbc\x11V\x07\x0b\xb8\x9aO\xb3\x11\xc7`\x15\xcb\x1f%\x11\x8b\xd9\x9b\xa1m\xcb\xdf\x8a\xa4\xc0}"\xa0\xe4\xca\xb1r\xbd\x03I\xb8v\xf2%\xa3\xf5\xdc\xea3\xeb\xa8\x01\xc3\xd9\xa4\x0fYZ\x83!\xcd\xc0c\'-F\x07\xf1C}\xfe\xd3&{q\xc5~\xa9\x91B\x8cE\x86\xa97\x06\xe7\xd7\xf7\x8b$\xff\xa5\xa8\xf3z\xb3\xf8\x96\xfbw\xd1\xd8Y\xa2\xc2\xa4\x8a7VeS\x03]x\xadY:\x89\xd0\xd7\xe6\xd2\xd1\xdbTJ\xa0ydV\xd0B\xf97J\xab\xb3i\xef\xc738\xc0\xee\xf1\x9b\x855\xdd\xb5\x1c"\xb1K\x88\x9a\xc4r\xbc\xd2\x80:\xd4\xbf\xbfe\x91\xa8\xc9\xb2\xcd\x97^\xd5\xb9s\x1dP3\xf6\x8aw\x85\xde\xdbG@\xdc\xcd5\xbatm\xd9\xf4\xb0\xe7N\x88 \x86o\x91"\xb5F\xc7x\xdbr-\xee\xe4\xc8\xa8{\xcdi\xf3\x14\xf7\x87+s\xf2\x13\x9d\x17\xb5\xec\xa2\x8e<\xd3J\xb6\x9d^\xf5Q\xcb\x02\xfd\xc5\xf4\xf9\xae\xda\xdfx\xae\x05o\xd3\x11c\x9bX\x8dr,G\xab\xdd\xf2bp\x06k;\xe1_\x10)\x8d\xe8v\xe6\xea\x84!\xb1\r<\x1bc\xb0\xc05TL\x8a\x89\x98\xdb\xf8A\xcd\xaf\x90\x81p\x08O\xdc\x9c\xb2\xf1X\xdb\x11\x7f\x04.\x88\xe4J\x88\xd9\xaf\xfc\xd7\x8cE\x03$`\x8b\xc3\xb87\x81\x82G\xf7\xdf\x01\xf2T\xd1\xfe\x9c\x1d\xb9\xf8\x0b\xb4T/\xd7\xd7GO\xd3\xa6\xf0)\x83\x99k\x81-\xbfY:\x02\xc5\xcb&8*\x87h\x18\x08\xeb(\x87c*\xf1dd\x03\x0c\x14\xda\xa6\xb1\xad\xe3\xaa\x14\xf8\x88 \x9c\xda8\x7f\xca\x03\x7f\xd9\xfb\xe8key\'\xe1|\xd4\x14u\xd3\xa9\x95~\xb8^\x8b\xfe\x15\xfd\xdb\xd0\xc3\x8fXBQ},\xb7\x8f\x08\x1f\x7f\xb7\x998\xe7`\xa1s\xf6\xf4\xb4\t\xd9_\x9fV<Sq-Z\xbb\x15\x8es\x13;S\xc3\x97"\xb0\x91\xe4\x94tH<|\x07\x07\x06\xcbC<\xb9\x84\xba\xd3XE\xd6{CI\x18\xd5\nv\xfe\xdc;\x18\xf6%\xd9c\x89\xba\xe5\x12\xea\xf5\xb0kRI\xa9\xba\xae\x1ar\xccj0C\x82\xfce\xa1\x1b)@/0\x8cD\xb0\xdak\x17A\xe7\xe9\xd5sS\xa5^\xb1\x0c\xc1p"%\x1dySb\xa7F\xbbZ,\xf4p\xba\x06s\x95\xfa\x7f\xf8\x8e\x8a\xbb\x1f\xfcm\x9ekrs8\x06)K\xe3\x87\x07\xe4\x17;\x85\xac\x95\xe4\xff\xb7\xc7\xb1(;1\x8b\xfa\xd1}\x8d\xb0\xb6\x94\xef\xed\x87\x8d8\xcbJ\xb5\xec\xa7\x11\xe8U\xb7\x9e\xc1\xb0\xa8\x06\x98\xf3;\xbf\x1e\x81Z\x7f\x14F\xbc3\xd1$\xaf\x0ei#\xd5]\xa28\x82\xff\xe5\xa5\xa2\xf1\xaeed\x17.\x13\xabw\x04\xfcw\xdfg_/\x94t:lK\xbbm\xea\xd6\xe4;"\x04e;s\x08Q4\x1d\\\xd4Y\xbah\x07i\xb9\xfd\xf9\x81;\xb5\x07\xb8\x83\xee\xe4M\xd4?\xad\xff\xa0\xc6\xd4_\x0f\x8b\xd3\xa4E\xbe}[ \x17\xdc\x7f\xc5\xb0\xa83\xba\x99\xde\xc1\x8dc\x86\xc5I#hF\xdc\xd3[\xc0\x07\xab\x1e0\xb0w5\xbaI\xea\xc4K}\xfa\xe1h\xea\xf2\xbd\xfeu\xfdI\x9c\xa7\x9bP\xa5\xf1R\x9a\xb9XM\x8e\xf6\xc5C\xa5\xaef\x80s\x05;\xc8F\x8cg\xe2K\x81$\xbb\xf5\x14\xcd#\xbb\xde\x8d\xf2\xad.\xb7\xac\xea\x85\x10)X\xeaF\x9c\x0e\x11C\xfdx\x88u\xec=\x87n\xca\x9f\xc7\x125R\xc9f\xa3\'\x94\xacn\x8a\xe3\xc8\xab6\xe6`\t~U.\x93\xd5H\xc1ov|\x10\x03\x02\xe0\xbeg\xbb\x15\xb7\xd0\xe5\xb18\xffc\xc9-KhPn\xc6)\x1f\xf80\xdf\xc4.\xb6c\xeeG\xa4\xa2\'\x8b\n\x02\x8d+\xca\xf0sV\'p\x8a\x12 \x0e$\xabo\xd1\xad\xb8\x1c\x16U?\x02:T\xdc\xd5\xfa\x07\x8b8u"\\\xb1\xcfy\x86U\xf0\x9e\xfb\x08m\xca\x85\xd8,\x90\xed\x00Xb\xe8\xe9T\x18\xaf\x92\xcc\xc6\x01GV\x98ye\xfa^\x9a\xf1\x93\xba2\x07:\xfb\xd3M\xd0\xb0\xd0\xe8\xf6\x9d\x16-.\x99dV\xa6\x8e\x99Xp\xad&Pn\x08\x9b9tM\xbd\xcc\xbb_V\xe8\x10\xe9\r\x93\x98M1\x94\xaf\x86\x19>\x03\x08\xbcR\x8a\x195\xde\xdb\xe5\xa5\xae\x98\xe6\xac\x1e\xd4/7\xb7\xe0\xd8\'\xf4?\xb9S\x14u\xdd9\r\xfc;L\x08\x83#\xadw\xf8\x07\xd2\xf8\x8f\xcc;5\x91\x87\x11t#\x8c\xbe\\\xfa\xf2\x82y\xfe\xf5k\x82\xf9J\xe9\xfaK\xf2\x1eV\x1f,+n\n\xfeRdI\xe5U\x92\xc6\xb6\x16\x8d#\xce\xfe\x17\xed\xba\xc2\xb1\x80\x86l#\xb4\x9cG\xac\xf30Sz\xa6_\x15-\x91\x1et\xb3\xdb\xf9\xfcb\xday\xd7\x88\xd2\xef\xa2\x98\x98\x98hvB\xb3\xf5i5 \xdd\x8bC}\x13L\xc0\xa1\xa4\xf1\xf1\xb9\x9ac)\xca\x1a\xb5K{\xa8\x96T\xaau\xd1\x8e[\xe2\x91\x85%S\xf1\xf1\xd5\xf8_\xe7\x18f\xb6\xfc>>PJ\xdd\'T\x99\xe8yz\x99L\x1aK\xe8yy<\x0bl\x13\x8b\xf5\xf51\x03\x8e\x9d\x037@\xa2\x9e\xa7\xa3~\xd1yxl\xd2\x03\'\x12\xe4:\x80:\xbd\x87\xb7\xad\xbf\xb5\x06\x049\xcag"\x04\xe8\xa3\nM\xed~&\'r\x1c\xe3\xb9V\xb4\xe4H\xc7\\\x9f\x1c]\xb4\xb1\xb0\x13\xad\xf9\xe9.\xe2\xa8\x92\xe8i\x8c\x06=\xa6:\xaf7\xf8\xd5\x9e\xcc\xe1S\x81]\xc0\xd1\x87\x90\xb0l\r_\x93\xa3R\xa5\xfe\x17\xcc\x9d\xfa\x00\r\xcb\x12\xd9\x08x\xa6>+\xbf3\xaf\xc2\x7f\xfd\xf8N~\xc2\xe3\xa2\xba\x99A\xb1\xe2\x1d/\x1bd\xa7\x8a\xd3\xf7\x91% pT/\x86\xc8\xb2J\x9c\xf3\x04\xb2H9\xe5\\\xb0\xfdk\xb6\xb63\x88\xd0\xbd\xa6t%\x98\x98=\x81\xf2\xc3\xc4\x8d\xf9Sw\xe7C7\xd5c\xb6}6\x9c\x17S\xfd\x84\xbe\x8d\x023\xbd\x90\xc6\x85\xf4\x11w1\xbcQ\xe7\x9e~{@d\xdcq\x81\xcb\xc1\xb7X \x10\xed\x1f\t\xe9\x1dw\xfa\x00\xc9\x99ttt\xa63\xbaGM\x1f\xe3\xd5\xdc0\x19c\xe7Vm\xdam\xf2\xd9\xfe\xd7p\xe2;\xe37~\xaf\x93\\L?u\xd9\x9f]\xeb\xdd\xc1\xfc\x10p@mL,`.\xca\xd2+%9\xf9\xf0\x8fe^\xa6Re\xd8\x96[\tg\xdc\xe5\xb4\'$\xcdo?\xa4\x94w\n\xd6\xa6u-\x95\x13\xa4\xf5<T\x19\x15\xf8/\xc8\x08\x08\x9dm\xa5\xf6\x0c)\xda\xab6\x88\x18S\x81\xdd\xbf\x04cR\xbc\x02\\\x1d\xb1\xb2fHa\x8bL\xd0\x02YD\x80R\xf1\x9e\x08\xbd\x05\x0b\x13\x8bz\xa7\xed-\x15\x9d\\\x98\xff\xa92\x93L\x87\xb51 \xfa\x90^\xba\xc5\x1e4@J\x10\xd5\xb3V[\xb6;\x9dg]\xb0\xf7\xad\x18\xcc\xc6$P#\xd2^\xac\xf5[\xcc\xb8\xa9\xb9\xc1\x91}Ze\x9ac\x88O{,p\xca\x0f\xeb\xee[}\x93\x95o|\xab\xf2\xb6\xa4|\xcd\xea_.\x1c\x02z%b8I9\xa7\xfa\xc1\x071\x8f\xa0R\xeb\xb4-C`)\x1f&Q\xd0\xc8\xafYG\xa3\x9c\xef\xb7\x985\xcfN \xd7h"\x11\x00\xba\x195\x03\x9e\xd6\x8a7\xd6\xa4\x9d\x87h\xf1\xcbs)w\x00\x87\xbap\xa9\x01u\x7fN\xe7,\x8c\'\xaa_\x8e\xa0\x8a\xd31#\xcd*\xfd\x97U\xaa\x0c \x94\x88;\xfa\xce\x8e\xca\xec\x91\x86f2M*c\xe9\x92\x08\xfaGb\x8bX\xcf\xd6E\xa89k\'a`)*\xf4\x94\x0cK\x9d\x9d\xad~\xc1\x01\xb0\xd3p\x9a\xc3\xa4;&\xd1^\xb7\xb4\x9b\x9fH\xdd\xabp?K\x07T\xd8\xa7\xd2\x90Y\x96\xbfP"`\x8e\xd2\xd4\xfd?`\xd7.e4}\xe3\xda\xfe\xc7\x9d\r\xd9hn\xdbM\xb1\xb4y\xcc,\xcc\x98\xcc{\x8a5Q\xd1\xc8.\xb1w"A\x96\x82\x0f\xa4&\xac\rV\xd4\x14*\xb4\xd2\xf447\x95\xed\x0c:\x87\xa5\xab\xbb\xcaHY]\x83k\x9f\x0e\xd1\xc40\x16\n;^ \xe5\xc2`\x9am\x16\x0c\\!w\xe3\x01\x0c%\x0f\x10\x87@\xeb\x02\xfbc3y\xef\x13\x02j\xb4\xa0Aq\x12\xeb\xae\x94\x1e\xea\xf9\xb5\x95H\xc9\xa6\xca\x93\xf3\xe1\xe0\x0f\x1f/(M\xef$\x1a\xba\xbcJK\xbc\x1b\xdc\xf6*}\xc7\xb7A\x04I\x82\xba\xfa\xfd\xb9\xd1\x9d|\xf0lA\xee\\\xf7\x1f\xe7G\xd2\xd0PI\xc5\x18\xff^\xbd\xed\xe1\xee\x9ae\x1f\x94r\xf7\x10\x03f\x9f\x1b\x1e\xc9}B\x19}V\xce\xf6(\x03\xbe\x81\x05\x06\x9a\x00\xe6i\x80\x99I1G\xe4\xddR\x87p\x9f\xeb\x8b\xaf=_\x0b\'\x99\'\x8eJ\x98\xf8d2\xce\x8a:i\x94d\xad\x06\x87\xed\xf7\xb7\x9d\xe8\xdaXg\xbb\xe7\x04HT7\x95,\xca>\xa9\xa2\xad\xf0\xf4\xcbT^\xab\x8f\xackW1\x92a\x12\xc3\xcf\xbf\xb94)p+\x06\xbe\x9a&H8,w{\x8d\x06~&z\x0e\xf9`\xadu\xb8kP\xa7j\xa1F\xfdl\xa5N\xffj\x81\xefJ\x05N+\xf6\x12\x82\xe9\xa0z\xf9}a\xc8\xe0\xc64\x01\xbd\x04\xd6muB\xf6\xfe\xcb\xd2&\x8cx\xceUY\xd8\xfc\xa0\xac\xad\xfeo\xf2[,\xeb\xecI\xfd\xdc\xd5**>\x8c\xa0\xec\xf7\x0f{\x08p\xff~l\xbfz\xa6 6\xd5ik\x9d\xe5\xaf2\xe0\x12\'#\x83\xe64\xb9l{\x12\xe4\x1a\x10|\x03\xfb\x99\r\xc1\xa1\xaa\xf509\xcc~\xfe\xb1\x9a|\\r^\xdf\x15E\xb2#\x1a:|\x92X\xd9\xaav/\xeb3\x8f\x1cYs\xee\xd8\xdc\x10\x93\x99\xd0\x83\x87\x19l\xac/\\]\xf9\x87cCL\xb0\x05\\ykE\xc4\xe0\xc2Dp\x7f+\xb9\xa7\x14\x8e/\xe69\xa6\xcd{O\xe4c\x12I\x86eD\xf0y7\xd2O\x9e\xa2\x8c\xe3\xe1\xc1\xa9>\x10:\xf2\x0b@\x1a\x7f\xad\x01\x01=\xaf\xda\xbf\xc71\r\xb7G\xc9\x13\xde\x96f\x1a\xc1e\xdc\x1d\xb9\xc0\x15\xf6\x85\xb8\xa4H7\xed\xbb\xfb5q\xdd\xeb\r\xae\xdc\xab\xe7=rw\xcfOup\x0b\xd7\'P\x89Y~]\xfe<^B\xed\xc4\r\xa4\xe3\x17\xd1\xee/>\xd3\n\xef\x1e\xf5\xc4$\x07\x7f\xec%\x8d:\xb7=\xda\xe2>\xf1l\xe1\xc9~-0\x96\xd28\xea\xf0\n\x91\xfd\xf9\xae]}\xa8\x83\xef\xc3\x0cQ2\xabM\x84\xa3~\xc1\xc8\x06\xa4\x9c\x05\xf7\xb5\n\x92\x14\xd2Vj\xdd\x85oA\x89\xec\xf1{\xfc\x0fu\xef\x0b\xa3g,\xfaao\x8f\x9d4!u\x19\x8f;\x801i\x8d\xf7y~\x00\xbb\xd3\x13\xd5\xd8\x8d\x16\xa8\xb0\xd7\xfb\x0e\xec\xe0Ub\xf5z\x98\'\x80\x88\x04H\x12\xcb\x80\xee\x00\x9b\x94\xa5\xc8\xa6U\xa3,\xd9\xacB#\x97\xeeS\xdc\xb2\xfeLm\x9d\xebK;Z\xdb=\xef\xd1yK\xdb)\x03\xed\x81s\xaa\x07\xcf`\xd9V#`\x1e\xf1\xd8\xc73\xf68[\x19=|K[\x9d\xc5u>\xea\xe0}p%_Y\xde@MW\x9dy\xc2\xa0\x82y\xea\xe7\xe4\xd2\xc8\xbe\xf5\x08\xd8\x17\xb1\xb7L\xdeJiX\xf7bNH\xb6\x88\xe3\xa6\xd1\xd8\x05X\x89\xf4\t\x054\xc7.\x00\x077\xbdZ\xb6e\xeb9_\xe0\xb7!\xff\x1dT\x86(P\x14\xacq\xd2\x02h\xb5S\x9e\xdc\xce!\xdbE\xc4\x0e\x8e\x18k*}\x98b\xdbH\x7fA\x1cP\xbd\xf1\xbckJoh\xcd\x91c\xc8y\xa3\xe0`\x99\xe6\x81\xf5\xe2\xbe\xef\xd9\xdc\xe4*r\x0f\x01\x00\xe7\xa9\xf7*/!S\x86\xe6q\x9a\xe7\xe9\x9b\x92\xf7\x1a\xdc\x9a\xc6\xf9\xcf/\xfe\xfcC\xdf$\x07EJF\xac~\xc7\x8d\xdc<@\xc4\x16.\xffF\xff\xe4\xc4\x84\xa5\xe9=\x04dx\xb7\xc5\x0e\xbf\xbf$[u\xd5\xae\x05\\\x88\xa7\x04i|l\x1e\xaa\x10\x1b\xacy\r:\xdf\x90\xa8\xb39\xa9f\xf6\xc3\xe7\xbc\x7fK\x03;\xc2\xady\xf8\xb9[W-6\xbb\xbf\xcf\xcb\xb9\x126\xbd\x97f\xea\x8bR\xd2e\xf3\xcf\x9bS\x89\x17\xa3M\x15\xc4W\x08\x017\xa7\xdb[\xd4\xf5\x10\xba\x18\xb5\x89\xc2\xd7\xaf\xa5a\xe62\xb28Q\x11&\x95\xde\xbf\xdf\x06|1\xb3\xfdnl\xd6\x06s\xb0\xd9&\x1f\xf51\xf7\x87w_\xf5\x81\x8av\xf3\x861\x01jt\xd1P\xcc\x03\xc2\xaes1b\xff\x17\xdc\nE2\xb0\x08G\xd9\x8ba\xa1\x11\x08\xe8\xb4\x7f\x9c]\x14/*\xd3\x1b\xa0\x91\x08E\x1e\xda\xb6\xa3\x9fw#\xa8[D\rRY\x98\xb2\xcdXF\xa0\x93\x1aa`?\x92\xf5\x19sb\xefv\xd1\tl\xa1\x06>\xf8\xe8\x1a7\xd4\xeb}4\x8b\x8e\x80\xeb\xca\xe3F$\xc3~\xedA\x82\xa6\x05\xeb\xc1\xb4\x98a\x0f\x08\xa0\x0f\\E\xcb\x1b\xebV\xdc>\x15*\xacNe\x83\x97k2\x12\x1f\x93\x05\xcc\x9840\xaf\x99d\xabO\xdd\xd4\xd4\t\xfb\xd1\x809v\xfd\xa2]\x93d\xb3ch|\x8bGCO\xa7\xf0\x00\x8b\xc6>D\xe1S\x98\x15\xd4H7\x8f\xb4\x8a\x1fTIv2\xce\xa3\xed\xf3\x14F\xe3p\x10\xac\x86!W\xb7\x91\xb1\x07\x11\xfd\xc5\x14\xf5(\xf7kuSeb\xf8\xa4C!\x89\x9ey\xb9}\x98\xedm\xfep\xc5\xe8\x08\xd6_\xc3\xb0Om44\xc7Z$g\xca\x0e\xc9\x96-\xa8\xb1\x9cT\xb0fq$\x1eK\xe6\xf7\xd3\xc5e\x0e\x99\x0fA\xd9\x97\xbc\x08\xe2;\x9f[\x8c<l\xa3,\x03\'\x9f\r\x17}.\x15J\x7f\xa5?\xf2(_6\xf9!\xb7\x18\xcd(i\xf4\xeb\xc0\xae\xfe\x96$\x14\xb1\xd6\x17\x8a.\xadM\x16}\x84pLEup\xfd\xbd\x1e\x8fp\xbc\x85f\xc8\xd3\xa6\n;V\xd7=\x0e\x1b\xb1\xc4\x0e\xea6\xf7a\xc4\x99\xedxa\xfb\xcaQ\x98\xc3\xb0\xb2\x16\xe5\xcd\x13\xc2%\x88\x9f\xac-\xba\x1egs\x13\xa2\x9a\x00;\xa0\xf6\xa5\'\x8e\xbf-\xbe\xc2\xd7\xce\x1fk\xf6\x858\xee\xa67\xcf\x1ax\xd5\xbc\x14o$\x9ef\x0ba\xa5W\\\xc1w\xb6\x81\xee\xe2\xc3\x18\x84\xaa\xda\xdf\xa4Q\xb0\xa3\x8by\x17\xc3\\\xc2\xe5\xe7\xd0\xf0\xde+\xa5%\x9bn\xc5\x18\xf7&[e\xa9!\x9ey\xa9\x84<\xe7l\t\x8a\xaa#\xbf\xcb\x022\x9d\xbc&9Z\xce\xeb\xa2\x15{\xc8\x15\x90g^\x8f\xbc\x13\x81`{\x0b\',\xee\x002\xc3\xe8\x16\x88\'\x0c&N\xa2\xfap\xd7\xf2$\xccqkS\x1d\xef\xe2\xc3u\x9b\xb0\xf0\x92\x85\x8c\xf8\xa3\x7f\xdc\xbf\xe0D@\xa3#K(\xe2\x8d**\xd8\xca\x9c"rh\xe4\x14ku\x9a\t\xf6[\r\xa8\x17\x1c)\x18Z\xfc\xb4\x84u(\xfbz\x8c\t\xd0$\xa3p\x89\xc5\t\xf3KnK}\x89\x1b\xd4,\xe8m\'\xa07\xe2\xb5\x85\x1a\x92\xae\x83o\x9a\xfd\x7f8\xff\xcf\x8dh\'\x963\x08\x18D\x0e_\x18Zc\xd5\xf8\xa1T\xdc\x1cC\x9a\xa2xF~\xb3\xd3\xdd2O..\xa5rC}G\x9e\x14\x0b\\\xc9\xf4\x8eg\xd6\x91\xaeqM\x8d\xad\xba\xa5\x83\x86B\xc5\x99\'d\xa4\x1a"\x0e\xc9Q<\x87(\xf1_\xc4\x08\xce\xdb\xac\x8e\x01\'\x89\xb2\xd0\x0f\xb2j\xa2\xa3\xf4\xd0\x85\x111y\xb44\x0f\t)\x90\x90kh\x9e\x05\x07\x91\xb0IL\xdf\x8d/\xfb\x1b\x16\r\xfal\xa1\x83,\x82\xb10T-J\xc2F=l\xc9j\xf3\x8d\xe6\xb2\xbdG\x1c7\xcf\x1au{\xdeD\xbco\x8f\x1a\x0eW\xe9\xe8\xc9\xa64m7:S\xcd;\xea`\xf3\x04\x89\x05\xa0\xa6.qUs\xe1\xaf\xa6\xd4\xfe\x95g\x9ee\xc4\xe4]\xadz\x1b\xd64\xd2`\xd2Y\xb1\x08\x0bU\xdcP\x1a\x8e\x80\x1an\xf4\x13tr-\xe31a=\x8bs]\x0b\xbd\x06\x840\x00\x17g\xd8\xe2J\x89o\x8c\xa5\xd0Q\x08:\x0cP\xbf\xb3$\x94\x885m~F\xd6\xa0\x9b]D\xea\x1c\x9a)46\xfeX\x83y\x89\x11\xf2\x8d:XJ\x8d\xd0\xd93c\x92\x8a\x02\xbc"}\x16\xca[\xcd\xa8\x11rg\x05\xdb\x18\xda\xf5\x15\x087\x85a\xd8N<h\x80kl\xa4_7S\xea\xb09\xa9\xe7\x12\t\xad\xe5:\x8c\x81\x89\x80k\xad\x0b\xc9ijC\xfa,#\x9c\xa5\x10\x8d\xe9#\xbaP\xed\xc5\x01K\xecz\x01\xdf\x8e=\x8abD+".\x8e\xec9\xd4S\xed\x0c\xf3\x96P\xff`\xe0\x88"I\x9b\x02>a\xd8c\xa18\xb7z/\x8b\xd38\xefs\xfeK\xeb\x87\x9b\xa0N\xb8\x8b\xf3F\x04\x94\x14?\x1c\xc6L\x97\xddx\xd7\xafC.9\x8a\xe9\x01\xd6em\x99\xb7[\xd8\x05\x9e\xf8\x93`U\x12\x87\xfa\x9dRMa-\xa7\xf4\xc1\x18\x19\xad\x81\x980\xe7\x9d\x9b\x87>\x8d`\xf6},4|\xa3\x03\x895\x02\xf1\x1cf\x98\x08`\xc5\xd9/\x06\xd3\x00\xe9s\xd4pk-F\xe8\x07\x02KC8\x85>e"\x80\xb4\xfd\xe6u\xe9\xe5[\xb3\xde\xc4N\x0fw\x8c\xd6\xb6q\x80B[\xff\x85h\x85\x94\xe3\xd2\x16\xfa\x8d\xee\xfe@\xe9\\7t\xcd\xee\xc8\\\x82\x94\x9f$\xb3\xc2=m\xb5\xedYT\xbb\x99#\xf0\xff3\xa4(\x16R_\xe6]z-\xaa\xde\x90\x03&L\'\xf4IS#\xd1\xaf\t\xd6\x18\xca\xafe\x1cD\x07V\xc4\xd7\x15>\x03\xe3\xc7\xcb\xc2\n\x17M\x1botS\xf2~\xde\xe1f\xec/\x12-j\x8d\xd6\x86/\x8e\x1f\x85%"Rj\xa5W/As\xfe\xe3n\x1fN\x84\xc3d\xa4\x81\x13\xd3\xa2\xa1\xb5[\x11a\xa8\xf4\xbc\xa8\xe9xb\x87\x81\x08\xd6\xd1\xd1\x90\x80\xb2\xa4K\xf9IY\x8bB\xfe&y\xc2\xb4\xd8\xb5<\x1c\xe9\x8b\xa7a0\xb0\x03\x92\x94nj\xd2\xab\x8d?,?\x11\xef\x176oT#\xec\xa7;\xec\xe1\xa6\x8aFom\x01TF\x07\x90\xa0\xde\xea\xbd\xeb\x03\n{E\xedk\xf1\\\xc6\xca)\xe3T\xc2osw\x18\xecAkAW\x92~|\xea\xe5\x81.\xc5y\x1e\x82j\xa7s\xba\xe6\x8c\x8bjgl\xde\xe4E!|\xe5\x01\xbb\xde\x97\x9a\xf18\xf2Q\x8c\xad\xfd\xc7\xcb\xe2A\xc6\x17?\x17\xed\xaa\x18 $?\xd1c\xcd\xd1I\xa4&\xa9jw\x17\xaa\x03_\xa5\xf4\xce%t\x82x*\xb6\xa59#\xa5\xe2\xbc\x07\xb8\x94\x1d2\xc9E\xfb\x11lf1\x88\xe6\xaf\x15\xbd\xd9\xfe=!\xab9\xaeM\x98\xefU\x84H\xf7\xb9D\x92H.\xb0\x1c\xe4q;\xf2\x00\xb3\xbdKx\xc0\xdc\xa4\x8e\xb0~\xdfy?\x81\xe5\xe8\xf9\xc1T\x8f\xcc\x89\xed\xda\xa4\x11\x01\x15\x9a\x85\x06\x96{]3\x19\xc2\x8bm\x81WI\xb9\xa9\x9a\x14\x06\xd6\x0fS\xef+\xe1-t\xc08\xb4\xc7i\xe0e\'\xf9{a?\x81\xb22\x07\xd7\x9c\x83%8 \x8c\xca\xbbe+\x90\x8f\x94Z\xe2\x98\x07\x92\xd4\xfet`\xcc\xfbq\x1b\n\x05*\x0cb\xde\x1b\xad\xd9\xba\x92\x8a!oy\x9b\x85\xd7\xc3:8\x87\xba\xf9\x9ar\xe0\x07\xf9zX]\xd6\xc9:f\xa3\xf1\xa9\xb9g\xba\x1e\xcb\xef5b\\\xaa\x1a\xcb\xd4\xf1\'\xfe-\xb9\xac\x18\xb2\xd2\xed\xf8\xac\x98\xb3(\x9f)\r\xfbO\xe2\xeb-\x955\xaeN\xd2d<\t\xaeX\xec\xab\x95(\xe1\\\x8b\xdez5\xb3\x87_\xc5k\xd4}\xddY\x0bn\x9bUm8K\x05\x8c\x8fb\xea\xfa1\x18zE\xe3\xf5\x13f\x93]\x8ctI\xb4*5O\xdf\x0f7\xe0\xd7\x19\xed\xbd\xed=Rr\xd1\x87\xde,W\xcf \x8c\xf9g\x87=\xc7^v\x94x\xf3\xbf~\xfa\xb7:\x98\xba\xca2\x0b\xb3\x1eL\x95\xc7n\x05\x90u\xc5^\\\x18\xb3\xda\xa7\x7f\xf4=\x93\xba~\xd44H\xa2\xe6\xfd\t\xaa`\xc4\xdd\x05\x90"\xcf\xd7\x06Ac\xd8\xcc\xcd\xd3t\x03o\x9f\x90\x19\xe7v\xf2\xd5\x08\n\x1c\x9e\xc5:\xe09\x1b0]\xdb[\xab\xb8\xc4\x8e\x81\xd4\x9a\x84\xd7-\x98N\xf0\xfb\xfc\x14\x977\x0c\xe2\xeb\x07 \x12\xab\x06\xbd\xf3/\xf2J\x9f\xc8\xcf\x9a{\xc7\xd0\xad?BQ)\x18I\xad\x15\xb7\xfeO\xbe\xcbu\\)5nc\x01\xfe\x82\xe3\x05\x1c\xb6\x04\x1f9b\x13m\xeb\xd8\x9bQc\x87\xd4\xf9\xbdR&\x08\xc7\x1c\xb0\xcb\xf2\x072\x86\xf9IO\xbeKS\xfc\x7fv\xf8\xbfV\xbd\xcc\x89I\xa7\xe3o\xa3\xdb\x0f\xac\xd7`\xd6\x94\xabR\x99\xa5d\x06,\xdbL\x93\xe9\xd9\xfb\x11V5^\xaa\x91\xb8\x9ar\xe7\xdb\xe1Y\xf2\x9dR\x89o\x9fhjRA\x92}\x8a\x19\xf9\xb4\x1b\xe4\xd1<[\xb5\xe6\xfd\xbd\xdc\x8f\xa5$\xc7d\xab\x154\x01\x1a9\xeah\xbc\xbe\xaf\xea\nE/*\n\xff\xcc7{\x97P\xd3\xf6\xb5\x16\xcb\xc3tt\xdc\x1c+iZ#\'\xf9\x84\xa8^\xa1\x8e\xa3\xd5\xa3`\x00\x1d\xa5\xb4\xc3\xd1,\xc6\x887\xe1;\x1b\xae\x94\xd3\xde\x99\xbd\x1d\xbd_V\xead\t\x80\xc5\x80\xf7MJ$\x15\x03\xba?\xb2\xef;\x17\x9b\x96\xc2"/\x8c\xe4\xe4\\\xed\xbfr\x96\xae\xf4\xa0\xb2\x84l\xa5\xa1D\xb4%j\\\xc1\xd5;\x7f\x00\\U\x17\x12A\xd0\x00\xf7\xbd{n\xffj\xc5\x8e\x97\x9d\xe5\xb7\x9e\x9f\xe9\xb1\x98\x97\xe7\xac+\xb4]\x15\xa4\xbe\x05\xf3\x82K=\x89\xd3\xdc\x9f=\x95\x88\xcd\xd2,7\xf9x\x01Bwow!\xd8\xc9\xaa\x7fa\xc0Kg\'\xbc\xa8\x96\xc1It`\xeb\x00\x8c\x9aB6\xa1R\x93y\xef\x0bkr\xb0p\x15\xef\xf3\xdb,\x0cl\xa6\x9aa\xd6"\x08sw0\x04<\x92K\x81|J\xe19\xfb]\x05\x1f\x11\xa7\xbf\xa70\x9b\xa9~\xb1\xe2\x11\xe6.$\xf8\x17\xd7\xc6\xd9\xe1\x1a\x1ae"\x87\xd1\xbc\xe76\xaee\x19\xc26\x95\xbd\xce\x1f\xa7\xf1\xdf\x152\x9bp\xf1\xaf`\x8bYj\xff\xb6\x06F\xd6;\x04\xa3\xd6\xe8\xfa\x9bSu\xfbT\x98)\xc7\xbe3O\xc9\x14\x0b\x0f\x11\xb3\x86<\x8f\xb6\x94\xf4\xc6\x1c\xab\xe0\x99\xab\xc8o\xd4\x19\xcbN1\xd2;h\xf2\xc9\xfa\x0b\x1b~,\x18\x0e\x88auO\x05\x8eP\xa8\x96\x16\xbc\x90\xff\xbfRv\xe1^-V\r\xe0\x9a6\xa1\x92M\x8e\x07\x94v\x1c\xf2fc\x9e\xf063OI\xa0\xc2\xaa\xc4\x0f\t.\x8f\xdc\x03Z\xf5\x9f-w\xc6\xe4L\x07\xcfK\xec|\xe5!\xb2\x88G\x14t\xa57\xeb\xea\\\x0b\xcb\xee\x93K\xc0.Aq\x9c\x05\tW\xaa-\xef\xaa\x9dw\xd5y\xa5\x8b\xfc\xb9Lh\\\xae\xd5G\x8c5\xef\x8f\x8d\xc9\x9f\xd2\x83\x10y\xb9\x1c\xeb\xda\xc6t0\xb6J\tO\xab\xa9\xfb%\xf8et\xe0N\xabzrF\x128\x1d\'x\xc2a\x18\x91\xd94\xc8b\xdf\xbcf\x1dw\x0e\xd9\xee\xb1\x8b\x1bK\rg\x9a\xc5\x88m\xa2\xa9\xe2v\xfb}\xc1q\x9687\x96}5\xb4&N\\\xc5\x82\x85\x01\x99\xe2\x9d\xed\xc8\x00&\xf6\x14\xbb\xdc>\x9d\xae\x96Z\x1c\x86j\xe9\x12\xea\n\xda\x1a3\x10\x84YK\x06\xec\xc2U@\x07\xe8f\x10\x8aF4z\'=x\xdaB\xd9^\xe3\xbb\x8ai\xa0\xda\x13\x10l\xf8h\xae/\xf0\xfd\xc5M\xb1\x85=\xce\x1b^\x9d=\x94[\'\x1d\xb8\x0bU\x98&\x1d\xa1\xdc\x11}bX\xc3i;\xa9GC%\x1c>\x82\x8b!_R\xf6p\xc3\xf9\xd2\x83\xb1\x0e\xcay\x91\x9aE\xc1\xf8\xd1"\x0e\xa5\x1b\x04a\x9cp\xee\xd5\xd30:\x12#\x16\x98\rK\xc3\xbf\xd6\xff\xf83H0\xf4\x8c\xa0\x0b\x99)\xae\xecG&\x7f\x94\xfd\x19\x92|(\xd9\xf4Xg\x98?\x92\x13\xbe\xa3\x03\xc8\xfd\x14\x17\x95\x18\xc8"J\x85H\x91\x02V\x87\xe9\xce\xac\x89\xb9\x1b\xb1W_L\xc5\xc7\xf3PZ\xc6\xeb\x97w\x8bR\x1bA6"\xdb\xdfP\xe6E\xa3e\xf8^J\xdcp\x87Fr\x01?I\xff\xde9\xc6(\xb8\xe0\'\x05G\x8fI1\xac\x1bv\x128\x18\r\xa4\x7f\xb8cP\x01\xa0M\xd8\xb8\xd12\xd4\x7f)\xdd\xe5\xfa\x08!\x81\xf0\x0f\xaa\xf9\xd3\x18\xac\xa8\xc4(\xc0\xe0\xb5\xa5l[\x12\xca\xcf,\xac1\xc1A\x89\'+\t\x049\xfe\xe9m\\N\xe9\xd1/\xa5\x13[\x1eIb\xf3\x1f\\wMK\xa4\xd7\x99\x84\xe8\x8a\xb2\xb0\x8e\xd1\xda\xfb\x12\xc6\x96\x00\xa6\x10N\x8c\xb7nep8\xbf2e\x06v\xa5\xbe\xc7\xd3\x89\x9a\x1d\x85\xcfV\xdaU\x99\xda\x19:\xa8\x1d\xb8\x12C\xb8\x90\xf6\xa5\x8c[u*\x01\x89\xc0O1\x00d\xa1\xff\xd6\x89Jb}\x06\xbb\xebc\xcb\x85M \xbf`\xfb\x12?\xac/\x8aX\x1cJ\x12\x08\x8a0\x15(%{\x05t\x04\x80\xbd4\x81\xc7\xf4\xfa\r\x17\xd5\xf7T\xe8\xfd-\xb7Xq\xd0LR\xf8\xc3m\x183\xf5\xb68\xb3i,\xa4Mp\x7f\x91wpLv\xb0\xb9s\t\n\x94\x99\xfaq\x84\x9a&0\xf0*7]M\xe2\x1f7\xf0\x0e\xc5\x1a\xce\xe0@\xef\xfb\x8dS\t-<\xba\xdd\xd1\xc5\xea\x97\x14\xe2\xda\x97.\x9e\x92*\xf1a\x8d\xb1\x98"P\xf3\xdaRV\x14\x9e\x93\x18\xfc\xdfM5\x9dp\x1a"B\x8c\xa9!\xeb\xa3@c\xdb\xf7')
|
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
|