hiddifypanel 3.0.0.dev63__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/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\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\xf1\x16\xe4q2\xe2s\x04\xae\xbed\x84m\xf7\xf63\x00\x00\x00\x00\x00\x00\x00\x00\xec)%\xc8*<\x103\xc2\x12\x9f^\xd7\x86\x8a\xc9H\xbd\xfd\xcc\x9b\xa1m\xae\xef\xa57\x8a\x07\xc0~\xf9[v\x06\xdb+\x81]\xa8F(?\xbd\xf9\x853\xf9r\xa6\x9c\x0c\xa5\xbev\xb0|)V\n\'[zy\x95\x07\xcc\xce\xbc\x14\xbf\x94\\nid\xb6\xa8\xf9\xd3\x02oc\xf2\xc8h\xe5\x84q\x88\x91\xb3\x91\xbb\x8a\xee\x91\x99\xbc\xc9^\xcc\xdf\xd9?L\x17y\xae\x91\xdcT\x92\x84@X\xa7\x15a\x04\xbeJ\xda\xaf\x9c>\xa0\x1a+\x0b9%\xbc\xf7iq\xde\x80\x95\xceg\xcc#\xed\x8fJsu+]\xdb\xaf\xd8\xca\xf2}\xd8\x8e\x84T\xba\xf2\x8aGsf(\x80K\x88\xac\xb7\x06J\xb9?\xbe\x93o\x0cJTW$2\x01\xec\x08o\x8d!\x92\xd7^\x8d\x89\x9f\xe1\x92\x8f\xa3Eo\xfa\xb6\xddL\x8d\xb0u\xf0:\xc0^\xed\xcf\x04;\xac\xa1W\x19:J\x87\xca{PUV\x86D\xc0\xf1\xb8\x0b\x05I\x89fq\x8e\xa88\xc0\x93\xfc\xbfzA\xfcK\x0e\xf8h\xcc,\xb9\xd4T\t\x06\x1bp0\xea\x8b;K\xf1\x94\x1a\xaak\xce\xa1!\xcb8\x07j}/\xeep\xef\x1a Mak\x12=@\xbd\xf6\xd4\xd7i5\xba\xc9\xaeh\x97M\n7\xe3K+t(\xde\x8a\xb8\xfb"\x8e\x1f3\xfc\x8ev\x9e#\x91\xcc\x8b\x04\xc3\x8f\xff\xdc\x880\xb3\x0bx\t\xfe\xbd\xcd0#\x8a\x92$9\x9b\x04 Q\xae\x99\x17\xb3+\x9b+\xc7\x9agAb_\xe6\x93`(\xa0Z\xd2\xe3\xa7S\x8c\xa0d\xc6\x1c\xe4\xafl\xf6\x0b\xdd\xd9\x15\xa8w\x11\x9939\xd5\x0b\xb1\x8e\xaa\x03\xfc\x1a\xb4\xaa9.\xf5\xe5~#\x97\xcc\xfbv&@\xbak\xc8\x87\xf1\xfbx\x84\xcb\x84\xe94~\xd5\x91\x0fJU\xbb\x8dr\xe8d\xd8\xdfd\'=\xdf\x16q\x00\xe3\xd0\x8e=+\xca\xe3[\xcd\xdf\x86\xcf\xdaP&T\xa7c\xdb\x1f2\x15\xae-$k\xef:\x80\xd2\x1ew\xc9\xf2\xca%Z\xc6\xb4C\x02\xc3)\x1f\xc3\x89\xf7\xa2\xd5\xf7IG\xb1D\xd9\xc1{\xdbL\xe0m\xbb\x05-u\xc17\xefHR\x08O\xdeP\xb8e\xe2\xdc\x8c\x00\x14\xc2&\xd2(\xdc\xd3$\r\x10T\xc8\xd3\xca{\xb3\xdc1\x8d\x95\x88v\xcb\x96\x80^\x18\x9e\xd48\x7f\xd2\x05\xd2\xbas\xc6@\xde\xb6\xc53\xa7\xa2\xbb\xa1\x83\xab\x89\x1d)\xdb\x9c\xa0\x01IU^\xb0\xd2\xdf\xe4\x05\xc9o\xa2x\xbc1\xd7O\xc5\xfdU\x1d\\\x0f\xd59(T\x1d\x90\xcd\xd4d$\xd2\xec\xc6}:\x16\xf2\x0c7\x15\xe0\x18*\x87\x88\x1bO\xf8\xeaQ\xce\x93\xf3aZ\x86\x80\x07\x05\x9b\x14\x87^\x98\xa7X\x91\xfe[~\x96U\x86\x1e&.cL\x88\xebR"Hl\x8a\xd1=|=\xe5)\xc6\xf3/\xa7\x88\x02m\xeb\x0b\xdbG\x1b\xa6(\xa4=\xa4\x8d\xd5\x15\xf9\x0f\x00Y\xba\xc2"`.,\x835\x081\xa2x\xa6\xf9\x96\xb0\x0c\xa5\xd2\xbf\xcd*\xa1\x9b\xead3)X9\x10\x99\x91\xf4_\xcc$I\x11\xec\xfb\xf2T\xf2\xf2\xb5"w\xc9\x9b\x92z\xf1\xbf\x97\r\x05\xde\xbat3\x18Ee\x94\xcdA\x81\xec\xd9\x82\x9a\x05?,\x94\xd2\xb3\xa8\xfd\x08\xbb\xd03@.\xd6\xc1\xe4\xfc\x99j\xa4\xbe\xec\x9b:\xd4+:\xf4\xca\xc47\xc7\x97\xefz\x1b\x90Vg\x95\xf5\x9b\x17\xbe\xfe_&\xc7\x98\xea#\xb3\xd4ib\xa5\xa1\xe8\xa0\xcdJ\xe5\x00\x16J\x92\xc8A<\xf3*\x01p\xca\xa1x\x1b\xbb\x1d\xe9\xa1\xba\xa1\xcax\xffdHh\x86P\r\x7f"\x8d$\xce\x90\xb8\xd9+R\xffgT\xb0p\xd7\x90\x152\xe7J\x15\xe5\xd6\xee~\xdc\xf93\x86\x1eM\xf6\xeb\xfe\xeb\xb6\xc0\x99\xf4c\xcc\xabv(+xL=z\xcf}@B({#:\xbdqM\xa5\xc6\xaa\x93\xb1\xcb\x14P\xbe\x1c\x1eo\xcc\x99#\x18\x8a\x84\xdd#3o\x97\x13\xe2\xb9\xb6&~\x0f\xc8\x1f\xfdG\xb9J\x1b\x97\xee\x13fo\x85\xcet{\xd6\x14}\x7fe\xb4\x1b\x18\x0e\xc3\xf6\xbc\xa7\xe9U3\xf6C\xb4Ah\x96X&\x82}\x9a\xf5<\xfe\xac\t\x03\xc8\'\x9b\x8e"\x0b |\x02\x8c\xbbC%p=5\x12;\x7f-\xa9[3\xb6L\n\x8f\x9b\xae\x08\x86\x14\\\t\xc0D\xac\xba.`\xa2\xd1aQ\xcfc?\x97;}\x082\x12\xe7\xb5\xc4;\xb1\x04\xd96W\xa9A\xf5\x9dP\xc3\x835\x9eze\xb2\xad\xa9\'\xb7-@\xd5\xe4i\xd0\xc7\x9aeP\xe3\x13\xca\xf5Y\xc0\x13}\xa38\x0c\xd6V\x13\xcc\xbe\xce\xf0\r\xe5\x0cJ\x12G\xdb\xd2\x08\x83\xf0\xd2\x0c\x93\x85\x1f\xe1S\xd2l\x15mSZe[b"\x12gq\xde\x10\x9f\xd5\x92s_\xd8\x83\xa8\xdc\xc9\x19\x9d\xdb\xce\x8d\x13\xad\x1f\xe4\x91 +\xc9\xeb\xa4QL\x14\x1a\xf58S\xd1\xad\xd1\xfcl\xab\x0c\xca\x0c:qb\xbb\xfd\xd9\xce\x17\x93\x03\xaf\xb4^\x9fc=l\x866`\x0f=:$\xea\xa1\xe3\xabJ\xa1\xdb\xaf\xa1\xef\x8d\x80s\xdb$\x7f\xdb\x0c.\xac\x995\xdaN\x11\xc1\x9as\xb01_\xfd\x1e\x18\xc5j\x1e0\xc8\xb6\x83/\xf4Ic\xef\x89\x16\x8bV\xd1\xc0\x9eT\x97j\r\xcd\xc8\xe3\xe8}\x0e\xa7\xe5/\x92\xfc\xecz6\x1a\xc2b|\x8dk0\x19\xbc\x14\xe4\xa2\xae\x9dPq\x0b\xa0w\xf5\x8c\x10\x06\xd0\xcb\xee\x9a\x9c\xe1\xbc\xc5\xdf\xb6<\xb8B\x1d\xder\x8e\x01/3\xa8\xf2Y\xc2W\xc2D\xcc\xf0I\x98~*\xd2@QxQ\xa14\xf8\xec\xc7\xd1\x92+}8\xd6\xe9~\xcb\x85\xe5aG{\xbe>\x95<\x16\xd0\x8a\xd8!\xe0p\x7f^0Tv\x19\xaa\x0eV\x1f\'\x13\xbdR\xc8\x7f>\xc3H\xb2<\xbe\x0eQ\xa9\xf2\xce\xe0\x0eA\x8b\x12\xf9F\x9d\x91\xda\x9f\x14w\xe5m\xc5Md\xd2\x9d\xbck=\xdb\x0eLJ\xc7\xb5\xd8\x08.V\xce\xa7G\xcaf\xc7\xb6O\xbeHA!\x9aJ\xaf\n\nsMQB\xb4\x13\xa7y\x94\xa5(o\xa9\xb3#\x19p\xac2]W\xbd \x8eWL\xa5"\x8a\xa5\xac\xa8\xa5N\x93\xdd\x1a\xb6\x06\xaa,7\xef\xc3\xdd\xdd\x9dt\x8f2\xd4\xe2t\x8a2\xc8\x8e\xda\x18\x07@\xc2\x99E\xe0j\x14dqj\x1eX\xde\x90\x1f\xbd\x84\xc4\xc7\x9a\x96\x1d&\xb1\xa7L\xce\xb3\xa6\nWQ:\x80\xa4|\x1b\xde\x019\xf5\x16\xdb\xcf\x8f\x90\x1b\xab\x01\'\x89\xa4\xd2 \x04dd\xa9\x19\xed\xd8\x81\xd9\xce\x97\x11\x12R\xdd`\x11P\x0b\x10\xbb\x0b\x08\xa6\xc6\xc8\x9d\x1a3\xf5\xe7\xa6\'-8-\xe9\xcb*\xb9d\x91\xe8\x05}\xe3<:\xc7\xb7\xdc\xf4h\x9bZ\n<F\xf9\xe4H\x05\xecD\xff\x94\x17\x91\x95\x1d}\xf2$\xae\xaa\x91l\xf4\xdc\xf5\x9e\xf7\xdc\n\x0by\xcaw\x93\x1b\xc57\xd9\x14\x06\xa1\xd38\xce\xca\x07k\xed\xc5\x8a\x06\xf2\xd9/~\xedB\xfc{\xc9\x95\x1a\xe5\xf0\xd850^Z>\xbe\x15;\'\x1d\xaaMr\xdb\x8d%\x12\xb0\xb0R\xab\x81C\x89?\xa6\x155\x9a!\xbf\xf7\xce\xcbA<\xe1\xfb\xe2\xc7`.8\x97M\xdd\x84v}T\'\xc5\x02\xa6\x1fV\xc5\x86oF\xefb\x88\xa0\x9f\x00 \xb0\xb1\xeew\x0c\x90\xd0\x9b\xa9\x9c\x04\xd5ZO\x8e\x9e\x17\x14}lM\xbb\xe4\xdc\x9d\x83S\xa3\x8d/\xb2\x9d\xefpQ\x91=\x0e\x88\xe2\xfc\xd4\x05\x00\x19!\x99\x17\xd52\x94T\xc6\x00\xa6\x05\xfb\x02[\xf7\x080\x8b\x80.\xf7\x8a\x9b\xd2/\xa9\x1a\xae\xc3\x0e\x993BF\x82;k\xb4\x06\x05\xda\x9d\xb1Y\xadXIqR>}\xc0h\x8fB\x892\xcakk\x06kvTi\xb2\xe6\xf3\xa0dK\xed\x18\x9c\x91(ZO!\xdah\xe6G\x8c\x0f\xa02]N?\xcf\xdc\xf5x\xb9\xaa\xd9\xd4\xa4G\t\xf5Y\x07\x08!\xc2\xa8\xddL\xf0\x17\x91\xdan\x8f\x05\xc8\xb4\x0e\x03\x9d\xae\xc1+\xdb=\xdb\x9d\xc0J\xc0\n\xa4\xc84vK\xd4}\xb2e\xea.\x9b\xb1^\xc3\x1cF\x93~\xdeu\xd3\x8d\x04~)\x02\xe4(\x83_\xf6Qt`P\x18x:\xfc\x91x\x08x\xff)\x95|\xaf=a\xadK\xc9\x96\x9c\x9dfI\xbc\xa2\x9c\x05F\x11@\x9b\x16\x1ae\xb6\x88Q\x95\xc9\x83+}f\x94@#\xaa\x00Y2bg\xd27|\xeb\xc0G\x98\x7f!\x16\xb3N\xbc\xca\xa6\xa5\x8f\x06i\x9c\x84\x06\xf45\x86\xc1\x93q\x98\x9c\xb4\xe7\xed\xea\x85/\xb3u\x84\x99Bq.@ z\xe94\x17\x93u\xf2k\xad\x87*J\xdd\xc71\r^\xb7G\xc8d\xf8\x8a\xc0\xf9d\xc5\xdb\x03T\x8bp\x86\x1c\x01\x9dd\xc9~d0\xcc\xe4.V\xf3\x99\xaae~\x98@\x1a\x1a\xa2\xd2\\TO\x926\xb6J\xa8\xd9\x01\x9cN\xc6\xba\x13#~qv\x13_\xa6\x85\x82\x18-\x1c\n\xb7\xd6\xdd\xf7\xfb\xa2\x05D\xda-\xa7D\x8c\x99\xe5\xec\x00\x88\x9f\xbe\xd7\xec\xaa\x1b\x85@6\x1e\xe1\x9a\x1a\xd7\x01\xfe\xa7\xe2u.\x1f\xdeRk\xe4&\xc5\xd8\xbf~\x0c\x7f$\xd5\xb2t\xe0\xb3\xba`\'N&\xd0\x9d\xdda\xd7 \xfa(/x\x1d\xebe8\xa7\xb0\xa7Z\x95\x0e\xd8\xb7{?\xc5\x8f\xf2;p\xc5D\x18\x81\xed\xa3\xfc\xa4\xb5\xf9M|\x80\x9e\xd7\x8a\x92L?(~\xd2\xef0\xf0kK\xa2\xb1\x8e\n\xf6~\xec\x86\x83\x10r\xb0\xb8\xce\xe4N\x98m\x8eR\n6(K\xe0?\xaf\x8ar\x95\xb5\x1eO\xc3\xa0\x9el\xa4t\x1f\x9d[\x0f\x99p\xda![\xa4\xb6m\x8cCI\xe4S\x94[jN\xf1\x99QC\xea\xd8\x1d\x9dE\xd7\xf0H\x93\xf3\xa7\x83f\x92\xbd\x8e\x12\x0f\x81\x18h\x81\x0f\xf7\xd9\xbb%\x9f,\xaf\x19-\x7f\x91\x0b\xaa\xee0\x8d.P\xb5\xd8\xf2q\x89\xfc\xbc=\xc2\xbb\xc4{\x97H\xa7\xbdX:q\xcf\xf1\x02\xff\xb15\xe2\x9d\xc2+\xc0\xfa\x92+\xc2\xbeU\x13\xe0\x11\x9f\xcbi\xca\x87\xb5Y\xca\xa3!Hx\xb1v\x0b\xd5\x1bT6\x9a\xc2"\xfb\xd8\x00\xa7g2-\x86\x1c\x9c\\\xb2\xecQ!\xcc\xb7U\x8a\x8d\xd4\xe2\xbaN7M\x1a\xa9i\x04n\x9b,P\t4\xf7\xa5\xdd\xd4Z"\x19{\x06\x039\xf3\xaf\x80jx\x04\xc5.\x8c\x81\xeb\xc4\x96=\x88\xf0\xc3oe>a>\xd7\xe1?\xf6\xf8\xab\x9c\xfb\x9d\xd8A\xf1\xd5]\xb6\x03%\x179\x83\xd7\xde\xe4\xc5\xfe_\xc3\xd5M\x12M\x0e\x03<j\xc2\xc0\x05u\xa1\x044\x17\xbc\xad\xb3\x93uh\x81gH\x04\xd7\xdc\xcac\x94\xc5\x01N\x0e\xa4M(\xc4I\x89B\xe6\x9c\x98nP\xcb\xa7z\xc5t\xcc\x9ag5\xbe\x8a\xe3\xca\xbe\xa4F\x84\xda\x02\x9e\xc9\x1ed\x8a3\x8b\'h6\xaf\x90}\x82t\xe7\xe9\xe6\xb3\xc6\xfd\xe6o\x13e\xd0k\x90\x91P0\x1f\xa8\x13;X\xd2#4&\xfe\x07\xaf\xbfV\x8e\x86\x02\x07Fv7[\xc9\x8f\xd4\xa2\x0b\xe9D\xcc(\xd7IW\x9a\x03N\x8b.\x94\xbfy\xca0PO\x15\xa5\xb5M+\xa0\xb1\xe0\xb9\xcd^)\x0b\xa4D\x97P\xa9q0\xdc\xacL\x12N\xa8\xdcE@1\xdc9\x9a$\x84\xd3\xbc\xf7\x9e8\x866\x0e\xea\xde\xe4m\xfe\x97\x93G\xf1\xfet\xa8\xf8\xd1:\xcd*\x95\x817\xe4"7qs\xa2w\xe6\xf9<~\xdbCP1\xaa\x88\xa62?\xb9\'\x91\xdb4\x9a\x1d\xf8\xaa4\xd6I={6\xb9K\x13\xb5\xdb_ \x96\xc8\xdd\xc8\x84\x8e\xb3.\xf9\xaa\x837q\x90\x150\x9f\x97\xd4\xcb\x1c\xe1\xe5.\xcc\xca\xf0\xf2\xa4[}\xc5\xde\xa4\x00\x12SL\x99c\x053m\xab\x96O\xcfu9\xb1\x0b,)\xc8=\xe7\xc9\x9d?\x13\x99\xb5k\xfc\xaa\xe3@\xc6h,6\x91l(\xd8\x8a\xc7\xd0/\x19D\xba\x86\xd0\x7f\xd2-\xab\x01\xa6\x1ay\xd8\xb5\xb0\x96z\xdf\xcb\xdf[,n~\x92\xb1h\xa5\xc1{\x06\xf6\xf1\xe2i\x99\xf5\xba\x8f\x14\xd6\xe3\xa1\x9dQp"\xde \x0b\x86\xd6\x90\xc2]\xf03}\xd8\xfc:\xe2\xceG\xcd\x01)2\xe7\xd6\xe9\x99\xeaK\xc1\xf0IE#\xdc\xc8\r\x85\x00u\xfaz\x0c\xa2/\xeb\x9ez3\xcc>-\xbba 6_\xbc\xfa\xdc\xbe \x8cE\x86/\xebE\x14,\x12\x88\x7f\xdc\xc5\x9e\xb6\x03h1Sr\xc2t4\x88\xdd"\xf5\xe9j\xe5\x82\xbe\xf3\x1c\xaeN\xbc\x94\x19\xc78\x93\\\x17Q\x1f6K\xfd0\xc0\x90\x7fz\xdd\xc1R\xb4\xeae>\x11}B+\x13o\xcd\xcfQ\xa4p:TB\x88\xcf>d\x9f\x10\x95\x19e\xc6\xab\xeb.\xc4\xd6\x85j\xb02\xe7;\xb7\xfbQ \xee\\\xee2\xac\\R\x80G\x86\xb5\xae\x04\xbf\xd2LS\x10\xe2#\xb4\xea\xe04\xb2O\x89\xe9;\xb1.\xed\xea\xbf\x165\xab\\\x91\xda\xe1\xf8\x95=+\xf7_\xd1\xd1\x9c\xf0?\x1eCs\x07Z\x8a\x9f\x92\x81O\x17|{\x0c\x9anW\x10\xcd1\xe3\xc9\x88u\xa5\xafF\x98\xe1P\x1f}K\xc3\xab\xc8d\xe5\x12\x17g:4#\x07]UH\x00}0m\x84nZ\x0f\x1f4\x94\x8e\xa7\x95CL\x8d\xb8\xbeB\x10\xe7\xbf\xa3\xe8wJN\xa8.\x07Y\x1e\x95\xd9B\xdf;\xe5\xd0E\x14\xf3F|3f?^if\xeap\x7f\xcf\x18\x91\xeb]x\x1b\x8f\xd20\x15\x80W\xd7\xa9Ts\xa2\xaeK\xd4\xcb--\x82\xe2S\xc9\x04k`W\r\x82f1\xe0\x17\x19i\xf0\xe0`\x0b\xb4YG=(\xb9#\x14k3~\x04\x9c}i2\x94\xa1\xfb\xd5|\xcdM^\xe6\xaa\xa11\xc61??\x11G1\xcd{-\xb0\xed\x80W\xa0\x87\x95\xc3@\xb00\xdc/\x16\xfd\xc5\xebw\xd8W(\x89\xe8\x19\xc5)\xd2\xafTK\x00\x0bC\xed[]7D\xcfk\x1e\x1f\'\xe0\xf2c\xab\xe8\xad\x18\xc6?!<\xab\xf4Jo~EE\x03e\xf8\x84\xfa\x90\xa7\x1a\xb2\xbe\x98b\x0e\xe9\xc0(\xf8\xf0\x02tMI\xd1\x17\x00\x83\xcf\x8a\xcc\x03\r\x87\x85Cu\xdeJ\x12\x05\xd5\xbc\x18P\x0680\xefg\xcf.\xab\x8f\xb4\xdbF\xeb\xb2v\xb71\xd2\xbc\xd1\x1d\xc0-e\xbb/\x9a\x06\x9aE\xcei\x1c\x13\x8e!\xc7\x06i\xaa\xfd\x90\x0e\x8b\x97\xb1\xbe\xb9\xe5\x0c\xf9\xfei\x10\xb9\xc4\x95\xe0\xcbf2-\xfc\xfa\xadp\xcf\xad\x99\xc1c\x19E\x18g\xa4\x81\xa2\x8a\x0b\x8e|H\xdco&\xc0\x16\xb4V`\x19\xc4\xbfzf\xea\xa6TM\x95\xc4\xb6\xe6\xce\x9f\xba\x81\xa0?\xa0\xc2?\xb8A>\x9btNS\xcf\x9fZr\x1d]\x10\x95\x85\x15=M@\x82\xbeO\x84\x07\xfchM\xbb\xf0\xae0\xf5\x00`\xee\x89\x1b /b6z\xd1\xc4\xfcuzh\xcbVa\x9bE\x9e\x85bld\xfa \x89\x90\xc8]\x16\xf9\xd3\xcc\xa7\xf1\xc3\xe4{+\xb5\xf3\xfee\x02Xs\xc32\xa9\xde\x9c\xfc\xef\x07\xe8\xc4\x0b6-\xcfX\xce\x14j\x8a\xf3hh\xc3\xc9Hfz\xf0"oO0\xa5q\xa2\xb1\n\xca\xbf\x94\x11vr@\x12\t\x7f+\xdc\xda\x92p\xaa\x8b\xe1\xa6k\xf4\xa3\xfa\xbb\xce\xe1T\x80{=v\xe94\x7f90\xca\xc3\x83\xbf\x8a\x16\x8a#\xe8\x028>\xdf\x15\xa1\x89_E\xe5.%@}\x03\xd0\x19`\xc4kV\xa5\x1e\xa2\x88\xd6c\x01\x86\xb5\xce\xe0\xda{j\xfeJ\xa1\x13l\x1f>UZ[\xb2\xc57z\x99\xf3\x12\x80c?\xfc\xf2>0&\xf89\xc4\xe0\xff\x03n\x8b\xea\xa2\x89\xb3\xa1\xc6\xd6\x1cr\xc4\xf9F\xf5/\x81\x144\x1a\x13o =\xcb5<l\xc3\x95YK)K\xaa\xad1\xc0\xe1cH\xdb\xc513\x1a\x13\x90\x15\xa6x\xf5\x8d\x95\xe7-X\xa8\xf5\xb4\xed\xcd\x82\x95J\x08\xea2\x99\x9b\xe8\xdd\x0cq\xe6mR(c\xdb\xfa\xf2\x823P\x87\xdccF\xf8\x89\x15\xd1\xa4\xc7\xd4\x1e\x9b: Ea,j`\xbdF%X\xc6\x8bL\xb5`Jl\x98\x15%\xcb_B9\xddI\xa6\x91\x91\x9dS>\xde9\x1d\xde\x16\xc9\xa8\xc9\xc4\x92\xc3h{y\xd1R\xe5h@"\xc14\xd0\xf4\xb8\x02\xf0[\x08\xbf{\xbcp\xad\x9f\xe9\xfa\x9cg\x97C\x93\x1a\x93(\xdd\xb2.H\x7f!\xa9_\xd2\x1c$\xac\xc5\x90\xc7\x89\xac!\x9a\xf0\x11\x8f\x86\xcbS\n\xce\xb1\xbe\xcel\x07G\xfb\'\xa7\x0e\xe2\xd3ZJ0\x12\x88a\x9c\x8cve\xd4\xf9N\x88\x03\xc4\x12\xca\xb2:\xc6\x96:\x9c\xfb\x9f\xe7\xaa\x04\x87\xe0\x1f\x87AN\x82\xa9$1\xf6\xe6dA4\x1fi\xc1Ui\xcf\xf8\x83.\xff\xe2\x11\xa2m\xfdi~6\xd4\x02\x18\x81\xaa{\xbd\x1a\x1c\xb2\x9e\x1f\xdfd|x\xc7Q_\\.\xf8\x16R\xdb\xf8\xc9\xd0\xd2\xab\xcfw"\xcc\xc67>\x9b\xcc\xe7m\x88\xc1\x92\x9e*-\t\xd8A!\xd3n\xf2\xe1\x00\xe1\x7f\xaa\x9b\xc7\xb7wx\xec\r\xcb\xf9\xe3\xd8\x1b\xef\x91\xc5\xdb\xff\x91\xd3\x8d\x14*$\xd3\xdf \xa85\x08VI\xf1"\xd9\xc7gdd\x88D\xb9\x1a\xf4#\xaa\x15\xebT}|wd\x83\x1eS\xa3q6\x14\xe3\xae\xdbx\x1b\xb9\x87#\xe1\xe0\x95\x9e\xbcR\n\x91\x96\x0b.!m\x05b \xcd\xd9e\x0fS\x00\x1d\tq\xae"\xc5\x1fWw\xab\xcc\xa5\xadZy\x82p\xf7\xa8\xc7\\\x93(\x83k\xf5b1K\xd6.}Fn\xeb\t\xb6Ul\r\xb3\xe7n/\xcf\xd4\x08:\xa5\xa2n\x95\xd6\xea\xcf!s\xf5\x88|j\xa0\xbf%\x07%8<\xfc\xbb*\x08\xb2\xe9\xe2\xa1Uo\xc7\x1a6\xf7\x8b3s\x03G)\xe6\xf1\xb5\x16.\xd4\x98\x940L \xa9&\xe2En\xbf\x83\x11A\xf0=\xe8UO\x01\x18\xa2\xb1\xa7\xdb2\xa7wD\x89\xffwi\xfd\xe6\x8c\xa7/pV\xdft\x1d\xa9_/\xb01\xd2S\x8b-\xdd\xa0\xc7\xb3\x1a\xf1\xe6\xc2\x99&T\xa1\xd3\xd4\x1b\xf1\xad\x01\xef\xf8\xf1/,&yw\x9ek\xf5\\7\r\xa4\xd8C+\x17\xe6\xe4\xf9%o\x1a\xfajmx@YV\x14\xff\t\xbf\xddy-\xe4\xae\x16\xde\x8b\xee\xaf\x90\x9bh\r\x85\x1d\xc5o\x8e\xea:\x08^%4\x02\xb8\xf7j\xc5\t\x18"\xff\xbc\xb7#\x81\x18\x1d\xa7|Pk=\xe5\r\xf8+\xef\x11j\xa2Pp\xa9\xf6\x10\xee\x96\x84\x93\xcbM\xe4\xa3wp0\xc2fy\x0cP\xb6d\xb1\x93\xb4\xe9z\n#\x12\xf8\xb5\x82\'@\x91c`\xfck\x07\xd9\x128\xa0\xf8\xf2\xb3d\x1c\x1d\x08\xf5\xa0\x9e\'\x11\t\x99\xca\xfc^\xb3\x1eB\xb8A\xe2\x18\xc0\xc0u-u\x92]\xfd\xb8\'m\xa4\x7fA\x1e\xda\xbc\xe3\xe6\xb9\xf8\x84>Je\xe1\xce\x05\xe1x\x88\x03V\xd4\xc7I\x9a\xfd\xc4\x05\x0e\xecu\x8dL=\xaf\xbc\xc13\x89\xb1V\xc39\xbf\x01\xc5\xaeu\xe90\x07@\xc0\xc3\xca\x98\x05\x04\xcbO\xdf\xe9\xa3\xd1+\xce\x07r\xae\xb0\xfe\x130\xe8&\xc4\xcd\xe0Y\xd9.\xfb\xe4\xed\xe9\\\x8a\xc2\x0e(/4\xcaB\xdc\xc8\xff\xab\xae`\xa8\x16e\xef\xe9\'ic\xdf\xc5\x92\x8c\x0f\xb92\xe3\xd7\x1b9(eh^\xf0\x10,Z\xe6\xf6{\xeb\x8f\xf4\xc6\xb9\xf0Z9h\x03\xfenG\xa3\xa2Y;\xd3\x84\xf1!\xfdn\x96\xe9o\x11\xfe\x01\x80i\x1a\xfe\x14\xc8\x9c\x93\xf4\xec\xc6s]\xfc\xb9^\xc8D\x1d\x9a\xab\xa1\x11\x94&\xeb"a\xa8\xd9\xbff\xf2\xc0:x\x07\xaf\xf7\x072\xbf\x0e\xcd\x9437\xfcuwg,\xba\xdf\xbas\xa7Y\x1e\x18\xa8\xf8/\xfeM\xee\xa0\xeeP\n(}\x8c\xbahZ\xcd\x03(d\x03sE\xe2\x7fF\xdc\x0e\xa9S\xc6\xca6\x0c2\x8f%\x1f\xff<.\t\xcb\x0b]\xf1\xeb\xc16\x86\x14\xe5\xdc\x8e\xeb\xf9\xcc;\x06\n/VZ\xf1u\x9f\xbb\xa2\xec\xb5J\xf8\xa8\xa4)\x07)D\x06\xc6\x05{\xc4\x8bo\x1dM\x0c\x11]{d\x89\xafm\xc8\xeb\xecqh\xa2\xae\x1c\x18a^-\r\xa5#\x9f\x1e\xfc\xdb*m\x99\x17\x05\xdc\xc0{\xbb:\x1e]\xd5}\xab2\x11\xe0w\xf6\xae\x84\xc4~\x9e\x99\x02\x8a\xf3ZA\xa4\x80m\x89\xaaA^F\xb9I\xc5j\xaah\x00\xa7\xe8\xfd\n\xf4v\x1cM\xdf\x0b< \\4\x81\xc5\xb1\x8fm\x92\x9d\xea\x9bY\x8c\xfe\xc1\x17a\xe4]\x08\xf2A\x82\x03\xe0\xe1+\xfc\xe2g\x17Cu\xad\x821\x85\xf8\xa8\x134\x88S6>\xed>r(\xd8Z\x9f\xa3F\x90\xf8\xfc5\xd75l\xcd\xff\x99a\xb2N_\xa5\xd0n\xd3\x87\xa7\x01JTH?\xdf<yZ\xa1\x03\xfb\x7f\xc5\x92\xd6\xba\x132\xe3\xb4\xd11q\xf1\xb6\xdd\xbe?[\x0b\x7f\x8b\x06\xb6\xe8H\xc3\x91\xec\xdf%\x14\xc0Oh\xb8\x92|\x9a\x17e\x08w\xb4\xef\x10\xa4\xd3\x1e\xdc\xde\xc6=y\xdf/4e\x96U\x89\xe6\x97\xe7\xd4\t\x81\xf4\x81\x07\xdf\x97\x8e\xd2W\xac\x10\xbd\xd4\x10GED\xa5l\x05,\xf1+\xe7\xb9\x87\xefD\\\xd2l\xe3&@\x8d_\x88R:\xf5j\xf06\xf7\x0ea\x04\xf9O\xe5\xe0\xf7\x8e\\\xdaCA\xb4\xfe\xf4kDcBZ<\x9a\x11\xa3>V<\r\x99\xe4\x13!$\xa0\xa5\x16\n\xd0Y\x1bd\xc6\xbc\xaf\x14\xf9\xe5q\xee\x10\xa6\x9f{\t\x96\xd0\x84\xedq\x81\xaa\xb3\xa6M\xc8(#\xaey=\xa9\x98\xab\x1b\xef\xb7\x05\xdb\xa2\x05%=\xba0\x95\x08\xc0\xd49\xb2)\x17\xc4\xcb\x98\xf8\xe9D\x0f\xcdH\x89\xb9\xdf\x80\x95\x81v\xf8F"G\xe2,\x91\xd5\x16\x06\x08\xa6u,\x18\x14-\x1e\x92\x80\xff\xf3k+\x80k\xdb\x8f\xfc\xfeA \x06\xb5\xf1i{\xbd\xdbU\xdb\xc3\x05W\xe7\x15D\x1e\xbbH\x08D*\xf0\xbcayIDX\xe2\xc0\x01\xc1/\xf9\xe6\x8a\xe0\xa6~-7\\\x83\x1do\xb9\x111\x8c\x10\x12\x88\x91]\xcdB\xc7\x94\x84\xd8;\x05\x15\xaa\x7f6\xe2\xbdj\xcd\x01\x9ef\x11\xddm\xef\x9dG\x97\xdf\xe9\xe2\x19@\x1c6\x13\x83))\xf6\xa6\xbb\xec\xfe"\x9a\x94\xbb\x9f\xb1\x7f|\x10@\xae\xa5).\xb8\xccs\xc4\xa1\xac\xf0skXx(\x0e<\x9c{\xa1\xa0\xf8\xe6f\xbc:\xd4\xbe{\xd1\x8fvu\xccO3p&\xd0\x15%\xd0\xaf\xf0\xf2\xdc\xd2\x19\x10/\xb8\xa1p\xdc&\xf0a\xcd\xb0x\xb7F\xe5\x08\xf5Y\xd5\xd8\x04\x90\xba\x10\xc3>s\xf2\xd1\x92\xbb\x9d:N0\x15\x18\x10\xce\xe9\x99\xf5\xa1\xd2\xe9\xa67\xc1C\xff\xf8\x88\xd1&\xf0\x05\xf3\x91\x9b\xf3\xc4\x0f0m\x87\xc7\xaf4k\xcca#\x8c_0}FCP\xc3\xe9A\xb9\x0e\x14z\xdc\xd5\x06\xb3A\xef\xa0\x02\xbe\x0bK\xe2\xfb\xee\xdc86(Ox;\x07;\xe8\x9c\xdc#\xf7?eEa\xd9\'\xd6\xa1\x85\x17\xc6)1\xc3P.\xcd\xc4|\xa8\x17\xa4H\n\xc6~i\xf0\xd4\xbc;_f\xcbr\x8b7n\xf4\xa5u4\xb4\t\xbb\x92<R\x9a\x05F\xbb\xb5\xc6-\xf1\x7f\xe0S\x99\xbd\xdd\xb3L\xcb9\x14%"\x8da\x97\xae.\xae\xbc2\xb5\xd1\xe7\x9b\xb8f\xb7\xbb1h\xac\xd4\xfa\xfaq\xf5\xb3\xaf\x90\xe8\x95\x84-\x0bW\xc4\xc8-\x95\xca\x11\x80[x\xc5\xf3\x89f\x17\x00;zQ\xd1wIQ}f\x90+\xea\xe1\xd6hu\x97\xfa\xdd\x0f\x05tC\xc9\xeb\x12\xfe\x9bXwvB\x98\x90\x11!\xe7S\x16\xcf\x8c\x11\x16\xa9.\x8e\xa6\x1e\x01\xb5\x0eU\n\x84\xa7$\xb3\xcaS`\xe2\x13X\xfc\xa5\xaeb\x16\xa4\x17\xa9\xce\x870/\xa9\xcc\xfbKCA\xdd\xa1n\xee$M\x81\'\xb6\x19\x02w\xa1O\xd0\xb4+TO^Bg\xf0?\xb9\xf0a\x0e}\x86\x89\\x\xc8\xe0\x14\xc6U\x9a\x1c7\xaav\x01Npkq\xc0\x8c\xc2\xe8 K\xdc\xe1L\x1d\xaa)zz\xf4-@F\x1e\x12\x07\xa7H\xf6\x91(6C`\x0c\xff\xc5\x95\xf9\xd0\xa4X\xda\x01\x8d\xd0lki\x15A\xb7\xa1\n\x82]\xa2,v\xe3\xa8\x08\xab\x93?\xca\xb3\xb1p\xd6>\xab\x83\x16\x0c\x11\x97!\x8c\xe70D\xe7\xb7=\xeb\xd64M\x81^\x1e\xd1\xce\xcc\x9fN7<\xbbo\x86h\xb4Y\xc3Bn5\x83\xc3\xc4D\n\xe7\xff\x9dF\x08D\x8d\x97\xca\x97+\xef\xee\x8a\'\x17\x88\xaaE\xe7k\xaccL\x03\xcep \xde\xb9\xc0\x0e\x15>\xde+\xb3r\xa5Q}\xe78;\\\xc6Qm&\xee\x1f\xf5r\xde\x82;7L\xcaD\xa5\x9e\x7f\xc8|\xc4\xb9\x14\t\xdd\xc5\xc1\xab \x97\x0es\xeb@\xbc\x7f\xe60\xa1\x05\x87\xcf&Q\xc4\xfd?\xce<\x87d\xff\xf7\xde\x12!\xb2\xac\x94\x16D\x8d\x93P\xfe\x86\xa3}u\x93\xbc)JHZC\xcf\x95\xcc\xf9(\xaab4vO\xa1H\xb81.\xab\xe3?\x03&Kg\xb4\x8dK=\xb7/\x8a\xe3Sc=\xe3\x0b$\x1eW\x10\xfa~,\xc6@\x9d\xb5@\xf8%~\'\xe7\xba4\xb9g\xd9\xfc\x99o\xf9oAc\x83?\xb6l\xdbE\xf6)\x1d\xda8vt4\xc1\x8em&\xa7\x90\xdd\x84Z\x80\x15!X\xc42\x13$\x96\x18\x1c\x85\x0bx<\xcf\xfc\xb2\xd6f\xe6\xa7\xb7r\x1e\xb8b\xe8Z\x1a\x9c\xf9\x0b\x139d-\xae\xb8z\xb1\xd7\xa2\xf2\xed\x137\x99\x1f\r\x19 ,\xb1;\xd4\xc4>\xac\x82;\xcf\xcc\xeb\xd0/.f\xccl]d\xb5\xc5(\xa1<\xcf\x11d\x99\xfaU\x06\xd8\xf2\x85Q\x04\x926B\xd9\xd8\xac\xb7\xcd\xa18\x7f\xa8\x18s_\'A\xb6\x85\xad\xa9\x8ch\xca\xc5b\xcbu\xbdZT/\xb1\x1e\x80\x17hu\x06\xa0[\x9d\xe7T\xad(}\x97(\x04\x1a\x8ekV\xa9}\xf7\xba:\xb6\xce\xcdF0,I\xd75\xf5i\xd4\x079mnX$\x91\xe8wk\n=\xf4n\xb2\x8b\xb0\xcc\x93\xd6VW\xfb\x18\xb0\xcbHLa\x8b\xb4\xe5kT\xf9H\'\xd9\xe2\xbe\xc3\xbbF\x85\x8ce\xe2\xba\xc5.\x1e\xa76+\xc02:K]$,2\x86vtO83<\x95\x0cG\xd6\x91\xdf\x86\xfd\xd4\xb6\xa3\x16\xc3\xa1\xaf0\x02\xbd(\xb5\xb4/\xabf"\xfd\x81\xec\xd0s\xa1\x88\xaaRd$\xa0\x9aJ\xce+x#/\xf6>\xdd\xcc\xa8E\xa9\xd84\xc0\x8e\xb1\xdb\x87\xdd\x9e\x96Z\xb3\xfci\x01 -z\x00\xbe:\x85\x81R\x14\x1f\x9e\xa5\xc5\x8cb\x17\xbf\xdd\x19\x1f\xfbCC\xb9$\\V\xb5\x04O\x86\x81q3\xe1tc\xe4}\xe5M\x12\xe5\x90\xa1Nng\xec\xc1\x8f[\x95b\xb0\x19\t\xe9\xe4\xaf\xeb\xa2\x15\xaat\x8e\xb9{86\xc5,\xda(2\x80\xcf\xbd\xa0\xd0\x15\xe6z\xb1\xd6\xd6\x8b\x98\xbf.yh\xbf\xd2\x8d\xac\x16\x84\x1c\xa2^\xee\x88<,\xde|\x18\xf4\xd6\x14<\xfew\xb5B\x93O\x89\xe02\x137\xca\xbf\xf3Ta)\xfd\xad\xe19\x01\x10V{\x1b|\x7f\x08\x12\xa4\x9eW\x80\x12\x17\x03\xbe\x97\x88\x0b\x8bz8\x01\xach\x01^\xcf=\x98\x02s\x97\xcb\xa2]\x08\x8e\x85\x85a\xd5\x81\xba\x82\xdb\x8e\x03m\xf8$!\xdf\xaeT7\xc3\xfe3\xf0\x98=\x99\x85\x82\x88\x19\xe7\x18"\x1a\xa8\xb6#\x05\x05\x94\x8c\xdd\xac\xa2\xb9\x16\xee\x99\x1a:;\xd1\xd8\x93\x07\xa3\x0e\x12h\x92\xfb\x9f\x0fL\xe5\xed\rnH\xa2\xd3MS\x80\x8d\t\x91VB\x11\x19\x8c\xe5\xf6\xf1\xcc\x9b\x1d+\xf8\xea\x9d\xa0\xf3\xc30L\x1e\xb0\x9d\x17\xf9\x98\x85\x948(\xc7\xef\xd5\xceT\xfb7\xaf\xc2!ZFbD#\xf3\x82\xbe)\xf6\xbd\x0c\x15\x99\xb9\x83W\xf3\x99\xda\xfe:\x1ek\xb4\xfe\xb6%\x80\xce\xbc\x8f]\x9f\xec f\xc5!\x10dl\xf6\xff\xcf\xe2t\x88WQX\x1fH\xf5\xb0r\xa4\x89\xa0\xb1\xf6\xd7k\n\x06\x99\xael\x96\xa2\xea\xf4\xc9\x88&^\xb9\x0b\xe8\xda?6\xe2MH\t\x05l\xd3\xbe,\x9e\xeb\xc4\x08\xde\xdb/\xb0\x85\x98B\xf09/\xf8\xf8\x14\xe8K\x9e\xc3\x99\x18\'1qwm\x1cI\xa5"]s`\xf8+\xb6x\xe5\xe0:r\xa4w\xb7\xf7\xd2FN\xfe\xc7\x0e\x10\xa9c\xde\xf3\x14\x90\xb0+`CW\xce\x9d\x0e\x95V\x91\xeb\xc4\xfc\x19\xc3\xb3\x1c\xa6N\x07\xe3Q\x05U/\x9a\xc7\xfa\xe7\\\r\xfd\xb6\x84\xf6\n\xc0}\xd2B\x83\xd3+N\xe2g\xd93]\xc8\x89\xaa\xc9">\xd8W\xa0|\x136\x7f\xdf\x81G\x9c\x11\x99\xdcY\xbeh\xb5\xad+eI\xa9\x9f\x01>q\xbb\xaf\xbc\xdf\x02c\xd9i\xdd\xfe\xb6\xd7\xcbM\xe8\x98\x8d\xfd\x93\t\xac\x85\xb9\xb8\xc1\xa3tG\xa9\xb5\x9c\xe3a\xca\xd3\x1a\x05\xdb/\x96;o\xea\x8e\xc5\xdczW\x1d\x0b\x13\x91\xdf\x0c\xc1\x03.l\xd5\xc1QP(Iy\x12\x03\x84\x0f\xc9\xd2\xff\xdbZ\xbe\xbb\xe0\xf9\xe1\xa54/;![W\xcd\x96\x90\x87\x8c\xba\xd1\x90\xbc\xc3/\xda\x9a0\xd6\xf6/\x18!f\x06=\xc5a\xbf\x8ci\x88f"&b\xdf~&\x86W\xadK&=\xa7\x11Rb\x15\xd6\xd3\x01\xe1q\xb4ND&\xd4\x18\x86Nx\x04L(\xcfZ\x0f\x8b\xfex\xe9I\xa3Sl\xe5\xd1.\xba\x8eb\x1c9y:@\x07\x84\xa7\x88I\xf6\xbb\xab\x85<\xcc`P\x80\xcb\xfcE4Rk\xf3\x8e\xb4\xd7\xff\xb3\xd7\x92o\x83\xee.\xf4\x16\x00\x02*\xf0\xfd\x13\xc4\x9a\xc6A\xb0\xaeV\xad\xfc\xd9\x1a\x16\x92\xa9]\\>\x06\t\xac#Y\xda\xbd|e\xd5g\x7f\xe4\x1fYPQ{y\xf0l"\x94t\xbe\x14\x17P\xe60m\xb1\xd3\xcb\xe3\xb2j\x84\xe3\xee\nY\x7f;w]\x9et\x00\x8e\xf5}\xfc\xd3\xbbod\xf9\xbd\x02y\xdbp\x06\xee\xba"B,\x89F\ri\xe5\xe8\xf3\xa2#\x8dK{\x1e\x8b\x05\xca\xf0D\xf9\xc9\xc1+{\x17\x96,o*\x9d\xa8~t\xb1\xb4\x89\xa5\xc5\xbb#`_\x8f\xce\xe9\xd6\x12\x88dU\xcd`\x16\xa2\x8d\x1d\xfd\x0e\x85A\xb6\xa7\x17\xa9\xed\x92\xb3\xf2s)\xeb\x81gI\x18\xf5\xcb0\x17\xba\xf1\xd0\xd8\x18\xbb\x8d,Y\x08\xa5e\xa6\xf4\xe4\x1f\x80L\xacrm(e\x9e\xa6\x85\xf3\xc2\x00\x1f\xd2\xa9\xd8\xbc\x9d\x83\x1cz\x19n_3i\xff\xcc\xa9(\xe4\xd8\x98\xb9_\x1f\x8e!\xc5N1\xdf\xc3Dzqh\xc3\xc8p\x9c\x16\x1a\xfb\xb0@\xe5\re\x9am\xa0^\x97G8\x8d\xe7=W\xb9j\xb3UH\x0b7\xaf\xeaB\xac\xa0\x0fR\xf9\xde\xd4\xbf%o\xb4\xbd\xee\xa3\xec3t\x85#\xc2I7;y\x8a:Y\x9d\xde\x90#\xa0K/\xc6G\xe3x\xcb\x0b\xcb\x00\x1e~`n\xbbqD\x8cDG\x823\xa0\x93\x1d\xcd\xb0\xdbd\xa0s\x80%1\xcbF\xe1\xec\xd0lK\xde\xd5\xf0\x97\x0c\x1d\x185gYQ\xc6\xd7\xd5xtS;\xd0\xaa9\xfcxaY\xdc\xd8\x0b\x1a\xd2 \xa1\x11\xb0\xdfW\xf2\xfc\\S\xa4\x17\x05\xccjv\xf2\x0b\x04\xd4Rt\xf7\x88\x0eM\xaf s\x0f\x05\xa6\x1aW\xb1\t\x9b.\xa1)\x1aC\xc7\xa4Z\n\xff\x10\xb0\xf0%\xa4\xab\x13\x07W\xfa\nM\xad\xbe\xe0\x9f\x10\xc6\xc3+\x9f~7W\xac\x93w\xe5^z&5m1\xe9\xd5\xb9\x14\xe1Y\x97\xfc\x7f\xafej[\xaf\x1e\xf9I9\xaf1\xa8lcuN<_,\xc8\x03$\xbdL\xc4\xb7\x05LP\xfd\x9b`}C\x12<\x80`\x8e\xd7/\x85r4\xab{c\xc7\xe8\x85W\x88T\x06\xce/\x8bi\xe3\xa6\x14\xcai\xd0\x9d1\xcd\xe1/z\xcd#o\xb3\xc9\xc5)\xaa\xc56\xed\xc7\x15\xdcw\x88{\x83\xa1v\xe3P\x96\x03\xd1\xe0\xa9Z\xa7\x88\xa0Z\xeem\xf6\xa6[J%\xe2-\x1f\xe0\xeaeO:\x0bz&\xa3w\x1a\xaa\xe1\x88\xf3\xd6T\xbb;\x8dgU+\xc6\xf4\x00\xf4\x8f\xc5G\xdc\xc8ha\xf9\x9a\xc4\xfc\xd6\x1b\xc3\xc3"\x81\xcc\xf5\xb0-\xe2\x97a:7\x96m\x17\x8cV%\x9f]\xcaB1)iB\x97\t8D\xdb}\x15l\x9b\xd8\xa0`/\xdf\xa2>W!\xefQ?\x1d\x84X#\x87\xf0\xb0\xd1\x1c%~X\xc1U\x15\x91r\xbc\xd1+\x8e\xe3HmOV"+\xf1\x07\x0c\x1b\xceW?\xa7\xc7\xb9P\x14K\t\n\x8d@\t\xe8O\xc5p\xc2Z-*&\xd5\x91_1\x0fJ1#\xd3T=\x99\xe0\xc0\x14\x0b\x83\xd0\xcfV\xaa\xd7\xd0iN\x1d\x15=_\x96z\x0b \xad\x05\xcaJ\x82\x98/b\xca\xeb\x9f\xb7\x03\xc4\xaa\x9d\x18\x19\xae\x05\'\xe4y\xee\x04"O\xe2\x7f^\xb3J\xc7\xfd\xea\xceW\x8a\\\xa7\xd1\xee\xa2@}nCM\x19\n\xfb4K\xf2\x15J\x15\x84\xce\xd3A\xcc\x11\x1b"aV\x83\xe0\xd4g\xb5\xa5\xd0\xb3\xb1^v\xd8\xfe1\xd0\xf7\x88&2\x89\x86 L\x19X\xb9i\xc5 \xc7\x15\x1f\r\x9e\x95D\xb0\xa3%\r\xbf\xb1[9M!}\xcf\xe8d\x00\x05\xc5\x9c\xb0\xa6\xc0\xf84*\x0fh,\xc0b/\xab\xb3k\x82\xc6\xb16i\xe0\xe4bYX\xbbe\xe8\x8d8\xdc\xb3\xc3%\x0b\xc7\xa4V\x9e\xd6\xc8"\xd8\xec\xaf\x07\x01\xac/a\xbfS\x18S\x81\x0e\xd7#]+l\x96(\xa3\x1c\xac\x7f\x83l\xda\x1a\x92\x92 *W\xd12(\xc6\x82\x1f\xf90<KU\x85\x8c\xed\x99\x9c\xc7\x1d\xc8E\x1c\xcb\xbe\xe13\xe8\x7f\xa3d:\xab\xf0\xc4\xff\xfc\xfcA&8\x8f\x1bl\xd1\x00\xa7o\xa8\xf8\xb7\xda\xb0T\xf2I\xc4\xf9\xc1Q^\xe2\x8e \xd6\xd8p\x14\xcf\x1d\xd44o\'V[\x17\'\x16l\x1f &\x11\x07\xcc\xaa\xff\xc0\x9b\xa5\xed\xd0\x0fx\x10n\x85\x05\xd9\xe9TJ\x01l\xe8\x02\xb5i\xed\xf7~ph\xe8<3?x7\xea1h\xd4\x91\x82ZK\x8b\x8dG=r\xf8\x8b\xdb\x04\x16"X\xba\xf3\x9e\xdd\xdc/\x9d\x11\x91h\x8b\x95\x88\xe5vF\xdd\x85\xc9\xc5\xbe\xbd\xdda\xfb\x1b\xd5\xe3l\xa1h\xd4\x13=\x127\xb6\x0f\xe2\x82^3\xb8`\x037]\xf8\xc3Iv\'\xffj\t\xe1;\x84\xbdj\xaa\x9a\x8af\xde\x0e\x81\x83\x9b\x81o17f\x92\xe2\x1f\xbdU\xbb\xf4}\xc9b\x04\x16\xc4X0\x8d\xf0\x90\xf2\xe1\xbc\xc0\xa9h\xd3\x86\xda*\x98Q)\xd8;\x06\xbe\x08\xa5\xa8\x883\xa0\xb4\x8es\x01\x17\x04?\x1e\\\xed\t\x9f%3V<\xa6\x82\xb0\xdf\xeb\xaf\x8d\xdb+\xf7\\l\t\x18\x1a\x9d\xfbl\xae\x9a\xe6\xec\xda\xec\x93\xc8\xe6\xf8f\xd5\xce\x84\x1f\xd9l\xaa\xb2\xa7\xb4\x82\xd8\xce\xb8I\x8d\x12b\x8e\xdd\x85\x9b\xea\xe2\x8e\xb8\x12\xb1\'K"\xa9\x06\xd2rf?\x15O\x0b\x9f\x06y\xcf\x00\xc5\x1a\xf0\x15;\x10\xfaSV\x98\xef\xa013\xe4a{\xeb\xf1\xef\x86\x9a\x87%\x1d\xa2@n\xaa\x00W#R\xbd\xb3r\xc0&\xcc\xc8\xf9Sc\x1bZ0\xf9\x08\xf3\t\xe0\xc1\x00\xc3*\x83\xcb\xf1_\xf6\xc5\xf8#\xc5\xc0q\xd3\xc58\xe4\xec\x12-aSL\t\xcf\x12\xea\xfaP\xb9\xf8\x17\xcf\xb8\xc5\\W\xd4J:\xac\xd5}\xd3\xde\x91\x9al\xf9n:p\x98\xfeu\xbc4\x05["1\xd4\xc5\xcc$q\x9f\xb3\xca\x83V\x98\xbb\xe7\x85kc\x03\xfe;\xb2\x85Q\x9c\xed\x17G\xaa\xf9\xeeI\xbf\xd3&\xaa3\xb7\x089>r\x0b\xd1\xa3\xe6W\x95\x12QM\x82\xe5\x87\x91\x9en\xf1\xb8\x91\xcd)\xc6\xf2\xa3\x04]J\xae~n\xd1)\x10\xb5\x16&\xd1y,`\x83\xcf\x0f\x94\x19\xe9\xfd.\x81*\x07go\xab\xc4\xd5\x8d\x0291\x06\xaa\xcf\xd5\xc8\xd2\xc2\x9d\x06W\xf2\xc8i`\x1dXD~\xfb\x03\xfa\xe2\x91\xc1\x83\x01!<\x1cMW6z\x14\xa1^\x80|\x99\xe9<?\x05\xf4\xb7C\tF\x04\xe8\xafM\xc5\xe90\xac+\xe9\x95$\xa6\x02\xfe7\xb6B\xc4C\x8d\x8f\xe0\xad\xf0\x98\xff\xd4\x00F`\x08<\x14\x98\xc6\x08**\xf1\xae\xbe\x9ea\xd1\xb5\x01\xd2c\xfd\xbeD\x9f\xd6\xfa\xdfb\x1e!\xfa\xdd\x83\xb2\x9b\xec\xb5\x97\xa2"\x06\xb5\x85\xea~\xb2H\xad\x03\xd2P\n\xad\xdb\x90_\x1e\x8e\x03r^\xa4\xe15\x00.D\xf9]\x88\x8b\xa8\xb6r\x84\xffu\x9a\x93\xdf&q\'\xea\xab\x870I%\xdclK\x18\xab\x13\xbe7yZ\x00\xd8\xd4\xdc,:R\xf4\xff\xd7B>\xf7\xf9\x92]\xf0\x91\x96ag\xc4.\xd6\x93-\x88HM\x9e\x15\xc4\xed\x1c\xb4\xae\xc5M;D\n\x86\x13rm\xbd\x0f\x87HL\xf3\x9ev\xac\x1ch\x1c\x0fz\x98\xfa\xbf{o\xb3\x84wg\x9c\xa5w%\x81\xb2\xdc\xeb\xde\x0eM\x10\xdf\xd9$\x06b\xb1\xbf\xfd1j\x1d\xe8\xcbO\xbb\xf6k^\xca;W\x00\xee\x1c\xc9\x87\xe9\xe8\xbe\xfd\xb1\xe7`\xb2\x90\xcd5v\'\x8b\x9e\xd2\x82\x88b}\x8a\xda-\xa8\xed\xe2v\'\xb9Z*\xd1\xe9\xb4\xebq\xf1\x03\xb9\xd4\xf3\xa7\xd2H\x99\x80\xbb)\xc2:\xb6z\x9e"`V\x92/#\xbf\xccj\xf8=\x88\'\x00\x84\xd1\x8e/[~?\xc4\xe9\xa6\x15d\xd3\x1b\xc3i\\\xe0\x8f\xc0p\xfbG\xbd\x98y\x00\xd8\xe3\xea\xd6>\xc4\xec\x1f\xe3q\xf0\xc5\xdfF\n\t\xd3:\xc8\xfe\xcaq\x91\xcd\xce\xf2\x8c\xc1\\\xc4J#\xc2\xb0\xc1\xdb<\xf4\xe5-\xef\x1a\x95\xec\x93\xc4\xeb\xa4\xec\xb7s\x86g\xb2g\xee\xb8r\xc2\x9b\xa6\x81\x01f\x86_\xf0.H\x8d\x0cG\x83\xc1\x037\xd9~\xd6\xa1\xd7j\xe4m2\xd2\xeaE/N\xd9M5\xd9\x16\xc6\xa6\xd4?I,\xe3\xf8\x91\xa9^\xf1Q\xbbO\xc7\x8dTM \xaa\xe6\x06i\xa2&\xa33\xc6\\\xc4\x13\x10\x1eH\x1d\xd0\x08\xc6\x85>\x1f\xc33\xb3\xc4\xdd\xdf\xc2\x11\x1do\x7f\x90.\xa9\x1c\xe6\xe80\x1d|O\x1b\x8fk\xda\xa0\xf5?\x11\xbb\x8f\xbc\xd6;\xaf\xa3\x8cP\xdd\xd9\x03\xcf\x82\xdc;\x0c\xf62\xf5|\xd3\xc4\x16\xc4\x04\t!<\xea\x1a\xa3\x99}\xf7\x11\x8a\xb2XZ~\xd9:\xb89\xab\xf3\xad<:\x89\x07.\r\x1f\x10)\xa0\xa9A\x1b~*\x0cR\x9e0\'{X\xb43<\x7f\x06:\x930Y\x01\xb1\x7f\x1e\xc2Q\xb5\xa56\x89\xe1\xa3\x1a\x1b\xde\xd2\xe0\xee\xf0\x8b\xdc@\x1a\xb7\xc8\xbeYC \xcf@\x10\xc14yz\xdc\x1d\x1e\xba\xa0\xfe56\xb1\xde\xf2\xb1gt1\xe46\xb2\x99\x9a\'\x9c\x84\xac\xe6\xedZ\xf2\x11_\x9b(\xb7X\xc1t\x14\xf3\x82\xcex|\xc7\x0c\xce\xe3\x1c\xcb\xbf[@E\x85\xa95\xf3\x89\xb76w!W\xc5\x0e\x86\x12\x96buJ\xde\xbd"\x1eT\xea[@\xda\nL}\xc1\x89\xbaR\xdem\xd7\x17vpx\x98\x10Jo\xb6\x1c\xf1\x8dR\x9e7\x1bR\xbbt\xa7A\xaf\xcbebS \xd2Q$\x9d\xf0\x18\xa3\x0e\x11_M}\xed\x0eH\xd8\x0bIx\xcasc"Y\xb0\xbf\x93\xd1\xce\xb5\x0c\xc5\xf0\n\xed\\\xb4\x88:r\xef\xf0<\xb1\xd8\xf5\xef\xa6>Lo\xbc\xafh\x00o\xce{\xc5A|[W\xbb\x16\x8f\x02\xe6\xcb\x0b \xa9?\x83\x8f\xcfj\xf9\xdb\xe6sU\xadWgq\nHn\xbf\x9f=\xacd\n\xc0\x95\xc3\xbenf\x81W\x10\x9e\xff\xb5\xad\xca\xa5\xfb\\svv\x93\x1e\x93A\xdd\x1b6\xafmx\x80[;?\x12\xe0\xc1\xe2\xe8\n\xbb\x9f\x93h\xca\x9a\x1b\xd5~K\xb2\xba\xad\xb66\xa1\xb0\x8c\xd9\xc0\x9b\xf8\x11a\xc9\x87\xf6\xfc\x8e\xbf%\xe8J\x85^\xf9@\xc0N\x98\xf5\x10\xcc\xed\xe8\xc0;t\xb2!\xb9iA\xe3O\\\xd1\x8a\tE\xf52s\x0c\xe2\x00f7\\\xa2<\r(\x06.\x00\x10\xc7\xbb\xb90\xac1\x19\xbbB9\x89I8\xb9\t\xe0M~\xad\xcci\xf8l\x9bc\t\x8f\x17\xd9\xeb\x06\x7fMZ\x06\xdf\x9b\x96p\'\xa6\xc8&\xc2i\xda,\x83\x19R\t\xe9\xe0\xe3n0DB\x9c\x029\x82\xd1\xb2Y\xef\xec?Q\x9a\xa5\n!yF\xb3`\x0e\x0b\x8a\x8c\xab\xf1\xc7\xf4\x99\xc3l.\x05\xf8\xe4\x9c\x12\xcc\x9c\xb8\xa0\xa3\x80\xd3\'\xfciu\x85\x06\xdb\xb4]\xa0g\xfeS\xaa\x1d \x1f\x9f\xfe\xa6\xfb\xe2\xe9\x16\xd4\x9d@\x03R\xdd\xb7\x03\xe0"fJ\xccut%\xa0\x81T\xfc\xc8\x15\x01p\x7f\x08\xd89\x9b\xdam\xd6J\x80\x18F\xcej,\x9a\xabuD\xfct\xed\xf6\xdb\x07\xed\xe9\xee`\xb9f\x96\x19-\r\xab}*\x10\xbb:[V\x9f\xe6\x83[S\x0e \x08\xf2\x0e\xec\x1cn\xb9\xc6z*\x8b\xdd\xef\x16\xbf\xc1\x11v\xe7X~%Mkj\xdbj_\x13\xd5\x9a\xd9c;\x06;\x12j}\xfa\xb2\x97\xe7\xae\xd7AOq\xa4\x0e\x1a!\x93x\xf1S\xc6S\xf3`?\x8e\xa8\xff;\xd9\x9cQ$\xb1\x7f\x90\'\xca\x8b\xda\xd3#\xc66\xcb\xda\xf0-\xbb\x93\xcf,\xb0\xa0@\xc9\x97\xbeX\xbb\xd2a\xcc\xb2:|\x97?\xfat\xa5\xff\xc2\xb2\xb2;\x82\x1c\x86gT\xd8\\)\x126u\xdeZ\xce\x84\xcb\x15\x84\x99\xf9+\xdb{|u\x1e%\x18\xd9\xc0\x97LK?G\xbc6s\x9a\x15\xd5\xfc\xdanE\x17\xdbY\x99O\x86!\x93\x08\x1a\x8a9Lz\'\xcb\x90\xf6\xf3\xe1\xf6\x08\xb0\x07\xfbnB\x9e\xdaT\xd2\xe9\xc7\x10\xaeg\xa8\xa3wd\x14buw\x8a\x1fgT\x105\xa1AH\x07\xf6\x0c>RC\xf4E^1\x1d`\xdd%{\xc3*\xce{\x14\x0e\xb5\x87\xd5@\x9c\x05\x0b\xc3z\xa0\xeaj\x08\xb7!\xd3Z\xb1\x82\xfa!\xda\xa0\x83\xd3\x00#U7\xee!|k\xd3\xa1\xad5$%\xb0\x83\xd7\xd2UZ\xf8B:FXh\xdaI\xf7DC\t>\xa3\x13\xa4_\x85F!s?\xb8\xdf\x04\xf7\xfb<#\x906\x1b\xb8\xfc\x9d\xddX\xfdm\xa0l\n\x15T\xea\xaa\xc8k8\x90k\xeb\x03\xc5%K\x85\xe6\x85gOg\x02\xb1Q&\x0bx\x96I\x8a\xae\xe4\xea\xdd\xe7\xe1\xa2\x866\x909E\xad\nF|eIB/\xa9\xefSK\x90\x8c\x08\n\xb7\xea\xf4+=\xc8-\xd9\xed\xe6\xcf\xea\x00\xa5e\x92\xa1\x1c`\n\xdb9\xba=\x9dj0\x03\x8eW)\xc4?\xe7L\xc8\xad\xfb\x8c|\x95\x9d\xda6\xfb5\xab\x05\xf8p\x11r[\x17\xd1\x07\x93&\x06u\xa7\x90\xdd\x011\xd7\x80G_\x14\xf0+\xcc\xdbF4\xaa*\x9e]\x17\xe1j\xda\xa3\x06Oo\xfe*\xb8\xd3fwn\x94\xfe\x0bh\xb3\xf9}\xa6#J,i\xafr\xb7\xfft\xb0z\x8e\x95AU\\h\x18\x07Y\xf6\xfc\xa72\xb9\x9f\x94\x88\x0c\xc0,\xa1\xde\xd7\x03c\xa5a\x1e\xd6\xb7\t\xb6\xf9\xcf{ah\x1chV\xc27Q\xf6R\xb3\xc8\xbfG\x95\xa9\x98}\xd9i\x82\xfcN\xd7|D.\xf0\xf6)\xd7\xb2\xef}\xac\xd4\xbc]\x1f\x0b\xdc\xb7\x1c\xb6\xe5\x93\\\xbf\xd6w\xc1\xfb\xf3d\x1aj%\r\xba\xd8\x8f)M\xe9\x91w\x15[w\x97Y\xd1qY\xaa\xd2\x92\x99;\xdc\x04\xbdb\xbe\xf7\xdb\xaf\xdbk\xf0Il\xddo~\xc4\x12L\xa7\xde\x86\xc7I\xd2\xdd\xfc\xbb\xa7\xfe\xf5CE\xb6`+\xd2\xee\x8d=\xf4\xd4$\x16S\xce&\x8c\xc9Hp\xbb\x84\x10JN\x9e[-\xd5\x98W\x01\x95#\xff\xd48{0!\x94$\xf4\xf7H\xeb\xf4\xd3QL\x9a\xcf\x01\xc8g\x98\x8a\xea\xef\xa4\xc9\t\x9e\x11u\x90\x85\xeaB\x0f\xe4\xfc\xea$\xe0\x19\xfcZ\xd5*91\xf5\x1eeE\xe2\x84\xe6\xdb/R\x98\xf8t\x9d\x8e\x98) \x90;%~\xef$\xb1\xa4\xaa7Uv\'\xc1\xd5!k\x828\xf1*\xf4\xfb\xc3\xber\xe1\xf9f\x94\x1cH\xe4lp\xa3%&o\xa2\xdc\xe0\x05\x1d6*.\xdc\xa8\x07\xb7\x80\xef.w\xc3\xdf\x0c`\x05\x18\xfd\xf2\xba\xbf\xe5{\xac"Gl\x17\x08j\xa0OT\xc4eM\x06\xc6u\x9e\xcc\xac\xad\x84\x1a\x12~Dg\n<w4\xd7n\xcf0\x8c\xe5\xab\xeb\xcf5\xd5\x08\x91r\xecK\xcf\xc1\xcc/\x12o\xcc\xcfH\x80\xe6-\x16V\x0fU\xcd\xf8G\xca\x9b\x12+\x07\xe9\x7f\xab\x04\x10\xbc\xd8\xe0\xd0\x86\xd3\x17\x8d\x12_\xf8\xe3W \xd3\xa2(\xd0\xb6\xed\xdb\x9d^dQu9\xa5\\A\\b\xa3^\x90\n\xbcr\x87)i\x87_(\x9a\x07\x98\x9aj\xf5\xc2\x11\x8d\xd0\xba\x06G\xbd\xa2\xfbK4\xcd\xe32\xd6\xd11\x04fQ\xe1G\x87\xb1\xb3m\x87\x84\xb5\xfb\xff\xab\x01\xf1\xf3\xf8\xb4\xeb5\\\x8e\xec\xb6\xa8;\x937!O\xce\x17P\xb1\xb34\xd1uv\x15\xa4\xae\xb1\xf8\x92k{\xbc\x98F\xd7^\xcb\xb8\x16\xea#Y\x841~\xc1\xc9\xc0EX\x96\x99U\x02\xfc]\xbb\x1b\x98\x84\xaf\x83\xbd\xd0\x82\x92\x0c\x01om\x041R\x0c\xb5b\x89\xdb6\xc8\xec\'"\xe9,\xb3zr\x88n8)\x0e\xe0\xd8\x0f\xb7<\\\xf0\xa9\x92\x1e\xc5!V\xec&Y\xb6\x96 \xe4Z\x97k\x9bPp9\xc4\x97\xfb\xf5j\x90\x9aV\xe4\xf8\x88\xca\xaf\xf4_\xf1\x99\x83\xdc\x86\x9a\x84Q\x04\\\x02c\xacA\xb3t\xf3\xf5B\xeb\x96\t\xf9t\xcf\xc7D\x81T\xfb\xabU\xe8H\x1e\xa8\x9arL\x911\x0b\xd1\xe5}\x0f\rQ\xc4+\xdd\xd5\x01E\x13@{\x98\x89\x88Y\x88\x066f\x89\xa0\x19%o%\xce\xdc\xb2\xccn\xde\x04\xb43\x90\x9e\xe5\xc3\xf7\x83\x1f\xe2\xa2\x8f[;\x10\xdf\t\xf7\xe5t\x19,\x87+~c\x8a\xb6O,\\\x8fEY\x17\xb2\x1d{\xbe4\xf1T\xb4\xfb\x84\xac\x8c\xcf-4\x82\xef\xc1\xcc\x96\xe6\xae\xab\xe5\xd4`\xaa\x10\xffh}d\xe7\xad\x01d\xf8R\xb3\x91\\\x06hr\'W\x97\x1b\xa4\xb3M\xce\x9d\x95\x99?Q\x1dF\x86\x89\xb6\x01\xc6\x84\xeb\xf9\x1e\xdf\xd2\xfe\xc2\xb6w,\xfb\xad\x18\x13\x7f\x90D\x1c\xc54\xd2D\xb7\\`\x08\x18Sc\x8c\xf2~#\x06\xecp\x8c\xce\x8c\x9c\xf3\xc5\x00Q\xfbQ\x836\xa17#\xc9%\x1d\xe8\xd5;\xd3N\xc9`\xf5,H\xb5\x91\xd5Q\xc8\xfcu\xc23\xd6\xcd\x99\x06\x9d\xf8qj\xbe\xea\xc3[\xdb\x95\x99m\xa4|a\xf5O\x0c\xd6\x98\x80k\x9c\xc9o\xf7\xc1\x99\x8fi\x91}\xf0\x14\xe9A\xb4\xee\xa4\xcfg\x01+\x13\x01\xd8\x84\xfd\x8b\xc9${\x8a\x1aC{9Gyw,\x9eP\xf6v\x00\xd3^\xe8\xbb\x93!\xac\x82dnDN7\xb3s|\x142\xe6Z e\x197\ny\xdb\x9e\xf0\x92H1\xfcv}\xd2\xb4\x80\xef1Q\xea4\x1f>\xc2\x1e\xf9\xb4\x82QZ\xda4>]\xb9\xfd\xeb%\xf5(\x85\xd4\xb0D|\xd1\x17~\x87\xd8\xa7\x91\x83{6+\xd1Y\xa4\xa5\x96\x1d_\xe55u\xc1X\x1e|\xcc*\x85@0\xa7\xa4%M\xd8m\xb7\xbcY\x9bz\xfb\x18\xd6Z\x86\xc0\xe2\xb3H\x84kt\x7f\xad\x83\xd9\x1b\x9d-\x1e\xd7`?M\\?+%;z\xfb\xf9W@p/\x97\x05\x15\xfe.\xbb\x0cvY\x82\xb7\xd60\xee\xe1\xddB\xb4l\xb20wI\xde\t\x8e\xbc\xd3\x16\x00\x16\xf3\x1a\xf6\xedog \xed\x1f\xa1\x7f!\xa0\x91\xe1gH;\xa6E\x88\x02oA\xdf\xec"\xb3\x8e \x147\xa0Y\xf6db\x8b\xd1y\xb0\x1f\xf3\xb1C\x9f\x9f\xb7d\xb8\xac\xf564\xe1\x16\xde\x9cFO\xb3\xb7 x\xeec\x13\xb4\xaf\xcdJ\xcc*<b\xd2Wd\x12\xce\x1b\xa4f\xce\xea*\xefB\xd0\xe1\x1f\xa2z\xc9\x81\xea\x1fW\xa3Xj/\x04B\x0c}\xae\xcaZ\xc2kZ\xc9\xbc\xf4\x8d\xb6hI(k\x01\xa9\xaa?\xfd\x927SM\xbc\xc9\x8b\xd0\xdae\x93\x08B\x89\x01Fi\xc7$5\x92\x9c\xa3I\xb9x$\xf7\x810\x1efM\x18/\xe5\xff\r\x03\xad\xe3\xd5K\xb1\xec\xa8\x19\xffR)\xb1\xa7\x89&UW\xa0\xe9:\xa8\xce\xcc\x12\x10\x97h[\xc6\x8f\x0e\xa8\xb9@Q\x81\xf6\x93,\xeb!O\x1c0?]\xfeA\xa3E\x1d0\xb5,\xa7\x91@|\x15\x13\x15\x89+\x8d\xdf\xf5\xe5MY\x81\x1e`\xb8\x94\xc5b\x818dy\xce\xfe\x94\xe4\x15\x03N\x10Y\xf7\xb2d\x8e\xae\xae\x8a\xe14\x0c_\xe6\x89J\xc7\x91\xce\xd8zN\xf9\n\xc1\x9c\xd6\x91\xbb\xfe@\xa3\xc1$\xb9\xbf\x9617Zm\xd0\x94o\xd6\x97\x8d\xbdI\xb0X\xbeld\xd9\x98\xb2sBA\xbe\x8d\xe359\xd5I\x84\xab\xda\xb5\x9d\xa7\x10\x84\x07\x03\x92D\x0e\x9b\x9e\x80J\x86I\xdc\x124!qH\xa5A\xee5p;Ht=!\x10\x90\x1a\x00\xa3\xb9:\xa7X\xcdw\xa0tu\xdbr\xb6z\xe6\xb1g\xa2\xec1r\xba!\x8e\x02\xc4\x93\xcbcLr\x02\x1cF\xbfV\xac\x99\xefH\xac$$J0\x8e\x97\xab4#\\*\xfe\xd4\xe9\xf6\x18\xde\x1e)\xecg<\xc5\x07UO=<\xf5\x0c\x06\xcf\xa4\xdc\x90\x1c\xcd"w\x17y\x97G\x93;\xc3{F\xee\xd7\x90\x91\x95&\xc76\xaf\x05,Us`3\xac\x8e\xfd\xe9\xd5\x9b7\xc6\xc3N,JN(pB\xa9(1{\xc40c5\xde\xa75U\xad\x88>\x1d\x0f.\xac\x81\xd9/\xc8\xbc\x1e\xbe@\xea+R\xd6\x88g\xe8\xf5\x81\xe7\xef\x80i\xd3"\xb5\xb8\x83\xae#:\xaf\x84\xc3\x9e\xb1\xa1\x1e\x8b\xf64/f\xea\x02R\xb0\xca\xc3%\xe6R\x7f\xdf\xd8\x83>\x06`\xb4\xb2\xcd\xee\x91R\x07\xc8i\xc4a\xa5\x94\x1d>\x02e\xf6\x181\'T\x0c\xcf\xd98\xd7\xb1\xd4\xd4h\xdd\xa9=\xabD&\x05L\x8e\xaa\xec\xc5\x8d\x13\xc5\xba\x88_)l\xbbz\xaf[\xc3}D\x19\xca\x94x\x0c\x8a\x9a\x9f\x86[5\xbf\xeb\xb9\x90\x9eZ\x83\x1a:X\xd5MF\xae\r\xa8B\xf9S\xb0\xb1fvA\x019\x14|+\xbe\xf7\xda\x97\xa0\xdd\xa3-e\x8cp\xf7\xdb\x8d# \xdaw\xeb\x84\xe4?\x17@\x81\xbd\x16V\xbbC\xa0\xbe\xcf\xa9\xac\xcej\x9f\xfaW\x17\n\xf8\x9e \x01\x1d\x1e\x18\xfa\x1e\xf6\xd7\xb5\xac\x83\xe5\x9fI\xf2\x11\x8c\x90\x8d\x06\xf4\xed\xc3\x18\x89\\\xf7\x87\xb6\x17\x93\xfa\x10%\xc7\x80&/\xcb\x84\xae\xe7\x1f\xa6|\xaa)\xf84\xc4\x01A\x7fs \x12S~\x88\x12\xe6\xaf\xc6\xdb\xad\xdd\xb9\x18\xb2%@\xaa|.G/I\x97\x80\xbek\x045fC\xfe\xef\xd2+o\xfa>\x0e\xd0u\x93Y\xa7L\xd9\xa6\xe54\xf5\x10\x0fD\x94\xa3\xe3\xec\xcf\xe3\x071\xf1L{r\xc8 \x02\xde9\xd1\xfaL\x03\xe0\xa2\xf99\x82-\xd9\xd7\x1d\xfd\xc6\xeeF!Zm\xde\xd0CXi7{z\xaa\xfd}\x1d\x80\x0e\xa7\xec\xd9mm$u\x04\xa9\x8a\x1a\xe4Rt\xa5\xc9>\x7f\x17_\xba\xd16C\xb3T}Vg\x9d\xbf\xc2@`\xc1\xa1\x7fw\x12M\x031\xec\xe4X\xf3\xf5\xe3\xa6\x17\xa70\x88\xd9\x8a\x94j\xfb\x07\x1b\xd5\xde\x85v\x82\xc9\x96>\xfcyz\xac$Wi\xef\xf3\xd5\xc4\x85\x85\xfa\xdb\'?h[\xa1L"\x1d\xbeB\xa8\x18E&\xa3\xb5\x1a\xfe\x1d\x90O\x12\xbc)\xfe\xda\xfec,[\x87)\x10\x88\xdb\xdd|\xd3\xfa\xa5\x9cg\xac\x193*O`\xc1mv\x9au\xedV\xb8\xc4d\xa3eU\x9fh\xf4\xfa<Q\xb9\x82\xe1\x0e\xf2\x90\xaft\x05\xe5\xe9\xb6\xed\xec\x8b\x95\x89Q\xa2r\x03\x17\xa8<\x889\xe2\x1c\xab\xe0{ +\x15.q_\xd7W\xf3Lc\x16=\x1eXG\xcede\x92\xe3\xa12j\x02|\x86\x85t\x9dTo\xea\xde\x83\xcb\xf2]"5XL\xa1r\xf3G\xd5Z\xe1\xf2Tl\x86\xc3\x83\x00wF\x9f\xa1\xd8mE\xb4D\xf1\x14\xc5D\xbf\x04E\\\x91\xb7\xf7\xdd\xbe\xf2\xe9F\xe6%E\xb3L\xd1i\x99\xba\xe6\xe0\xd6\xa5\xe8\xe9\x91\xbe\xf8\xa5\xa0\x95-\xd7\xa8\x8a/\xee\xf6/\x08\xd4\xc3\x9f\xa11\xe9\x0eK\rU\xcd\xcfU\xf1!B\x199E\x14\x87\x1d\x0c\xf1\nGv\x81n\xcc\x02\xc4\xb8')
|
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
|