hiddifypanel 3.0.0.dev64__cp310-cp310-manylinux2014_x86_64.whl → 3.0.0.dev66__cp310-cp310-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hiddifypanel/Events.py +27 -4
- hiddifypanel/VERSION +1 -1
- hiddifypanel/VERSION.py +1 -3
- hiddifypanel/__init__.py +7 -3
- hiddifypanel/__main__.py +13 -3
- hiddifypanel/base.py +88 -3
- hiddifypanel/base2.py +40 -3
- hiddifypanel/models/__init__.py +10 -3
- hiddifypanel/models/child.py +26 -4
- hiddifypanel/models/config.py +105 -4
- hiddifypanel/models/config_enum.py +207 -4
- hiddifypanel/models/domain.py +106 -4
- hiddifypanel/models/proxy.py +55 -3
- hiddifypanel/models/usage.py +58 -3
- hiddifypanel/models/user.py +171 -3
- hiddifypanel/panel/__init__.py +7 -4
- hiddifypanel/panel/admin/Actions.py +170 -3
- hiddifypanel/panel/admin/Backup.py +80 -4
- hiddifypanel/panel/admin/ChildAdmin.py +122 -3
- hiddifypanel/panel/admin/ConfigAdmin.py +54 -4
- hiddifypanel/panel/admin/Dashboard.py +70 -4
- hiddifypanel/panel/admin/DomainAdmin.py +195 -4
- hiddifypanel/panel/admin/ProxyAdmin.py +128 -3
- hiddifypanel/panel/admin/QuickSetup.py +127 -4
- hiddifypanel/panel/admin/SettingAdmin.py +224 -3
- hiddifypanel/panel/admin/Terminal.py +51 -4
- hiddifypanel/panel/admin/UserAdmin.py +277 -4
- hiddifypanel/panel/admin/__init__.py +82 -4
- hiddifypanel/panel/admin/adminlte.py +13 -4
- hiddifypanel/panel/admin/commercial_info.py +23 -3
- hiddifypanel/panel/admin/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/clash_config.yml +1 -0
- hiddifypanel/panel/user/templates/home/multi.html +1 -1
- hiddifypanel/panel/user/user.py +233 -3
- hiddifypanel/static/css/custom.css +6 -0
- hiddifypanel/templates/500.html +1 -1
- hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.po +194 -190
- hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/fa/LC_MESSAGES/messages.po +123 -120
- hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/zh/LC_MESSAGES/messages.po +123 -121
- hiddifypanel/xray_api.py +109 -3
- {hiddifypanel-3.0.0.dev64.dist-info → hiddifypanel-3.0.0.dev66.dist-info}/METADATA +1 -1
- {hiddifypanel-3.0.0.dev64.dist-info → hiddifypanel-3.0.0.dev66.dist-info}/RECORD +74 -76
- hiddifypanel-3.0.0.dev66.dist-info/top_level.txt +1 -0
- hiddifypanel-3.0.0.dev64.dist-info/top_level.txt +0 -2
- pyarmor_runtime_000000/__init__.py +0 -4
- pyarmor_runtime_000000/pyarmor_runtime.so +0 -0
- {hiddifypanel-3.0.0.dev64.dist-info → hiddifypanel-3.0.0.dev66.dist-info}/LICENSE +0 -0
- {hiddifypanel-3.0.0.dev64.dist-info → hiddifypanel-3.0.0.dev66.dist-info}/WHEEL +0 -0
- {hiddifypanel-3.0.0.dev64.dist-info → hiddifypanel-3.0.0.dev66.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,278 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
__pyarmor__(__name__, __file__, b'PY000000\x00\x03\n\x00o\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00x1\x00\x00\x12\t\x04\x00\xd1\xa2\x1c\xf5c@R\xeb\x0f\xbe\x8e\xdd\x93\x82\xb8\xf7\x00\x00\x00\x00\x00\x00\x00\x00\xa7\x0f\xc9v\x05\xe8XqT\xde\x9e6\x7f\x12\xc4\xd1\xb5\xcb\xac\x87\xc0\x8bu\xc7\x95\xf8\x1dhG\xbf9\xa2\xf0v\xe7\xb1jv\xeeeS)^\xb7\x15H\x08j1\x1b\x045\xe4\xed7nJ\x1a\xc6\x01H\xba\x04\xcc\xd9\xbb\xca)Y\xeb6\xe3\xb9"\x1a\xc4WR\xaf\xf4\xd85\x1b,\xfc\xaa\xf1^j\xac\xcdo\xaa\x92\x02\x15\x89\x1c\xce\xb1\x8fT\xb8yO\x02\xbep\xdc\x13hq\xb0\x8b\xb8\xb7\xfa\xf6\x06*q\xfb\xda?\xf8~\xe6&\n\x17=:v\xf0\xdamX\x1d\x8f\xe7k\x91\xd7\x81\xef\xf5\xca48f([\xa9\xf8x\x9d2\xb5R\x8f\x11\xf7\x8ag\xfd$\xaf[M\x02\x18\xcd{\x98\x18\x15M\xe9\xd6{\xa3\xa6`\xfd\x9c\xb3\x7f\xc1\x9d,\xea\xd8j\x1bI\xb0\x9e\xdc\x1e\t:~l=>\x88\xb2~\xafp\xdc_\xe5A\x12\x12\x86\xd5\xe0\xebH\x80\'\x8b\xda\xadX\xe2\xfe\xd3\xa9\xc8\x7f\xfd\x1a\x19\xab\x10bo\xd9\xd0\xd0b\x08\xee\x17\xac\\j\xe6v\x8fl\x1eF\xb9 \xee\xa9i\x88MBF\xe4\x01\xda"\n8q\x90\xca\xca\xb67B\x13\x0fB\xc5\x0f\xad)\x17\xe5\xbb\xceW+<\xa8\x0c\x96\x1c\xceg\x8c\x92\xcb]Ygx\xa8AF\x897\x8f\xedMg\xbc\xc2\xf7W\x97im\xc4x\xa14\x01\xd4\x145Y4\xcc\xd8\xd6\xa9\x95@\x04^K\x9ee\xb3@\xf7\xbd\x92t\x01[cJ\x16\xe6\x17qh\xd9\xd0a\xe9\xd5F-\xa8\x850Y\xdc7;*|$\xb0qZ\x0c\xaf\xaa\x8bz\x11t\x85\x85Q\xe7\xe5\x03e\xca\xf3p\xf4\x178db;\x0e\x15qU\xf8\xf4\xce\xa0\xdaH7XG-q\xeb\x9a\xd6\xf3\x01\x8a\x87\x9bW\x1b\xd8\x9a\x93:\xe1\x0e\xa12v\xce\xec\r\xf5\xd5\xfa\x8a\xab\x16J\xdfQT?\x91M\x97\x94L\x06\xd0y\xbc\xfb^\x19$/\x97;\x9fi\xfd\xce\xf1;\x01\xa8T\xb2\xef\xc4\x08\x07l\x98\x17pN\xb9\xc9\xc5\xf9\xdb\xae\xb2\x14\xbd\xe4\x02A\xa6\xff\t\x01\xf1D\xd5\xfd,#j/\xcf\x0e=\xbb\x04\xb7\x7f\x89\x0e\xdb|V\x88\xe4&\xce\r\xd4\xe5\x0e\x8f6\x89_\xf4\x0f!<D\x85\xbbk"\xc7\x02\x9e\x1c\xb3\xea\x7f\xb4\xdc\r\x97\x87\x91\xba\xfb6>\xc1\x9eIJ\xcc\x1dmw\x81\t\xe9d\x87mm\x1e\x98\x92\x00<\x98\xc5o\x05\x9a\xf9N\x9d\xb5U\xe1\xed\x16C\x9f\x0e\xafR\x9d\xa7\xe4\xeb\x11\x8f]\xc9\xc3\xf5\xa5v\x07N\xf8\x07\x07\x95)\\\xc2\xba\xa4\x16\x8c\rK\x81\xbe\x0b\xbearQ\x9b\xadux\'OL\xf1G\x8f\xda\x8f\xf7+\x9d![\xcd\xbe\xa2BiL0\x14\xe8\xe1\x92\xa4\xb6\xcc+&\xc3\xbc\x8f\xc6\x85\xc9u]\x93\xfc\'\xc1\xc2\xbe\xd7H\x91\x89\x0f7NE\xa9\xbc4\xaf\x93\xfdv8)\xed/\x1eM\x05F\xca\xfa\xfb\x83\xe5\xb1y>\xfa\xcd^+uF\x9d\xeb{\x8e\xd0\x94\x19em\x8a\x9e\xb1zW\xc0\x8c\xd7\xb7\x9d\xd9\xec\xabaSm\xb77\xb9\xe3k\x18F:\x88\xac\xb4k\xda\xc4b\xdc6\xdd>\x8f2\xa7\x00$\x01\xfdN^09\x00"\xcd\xdd\x04&\'k\x9ag]t\xdb\xaeP&\xcb.\x07\n\x89\x97\x9d\xed\xf7*\x0cS{]\x18i\xcd1F\x9dG\xa45&-B\xed "\xcb\x00[\xd4\xbb\xdb\x94\x01\x1fBp\x8a\xfe\xd2\xaf\x9e`\xcf\x86\xa7\x98/\x81\xbc\xb3\x9d\x9e\xfa\xa3,\x07c\x8b\x9aJ\xbc\xad\x99/|\x80\xb0\x12\xc7\xb9\t\x16F\xb4\xadJ\xd7\x92\x04<\xdac3\xc4\x13\xb3\xe0\xc5t\x05u\xa0\xb6/+\xea\x02\xefj\xe4\xd6\xe4{\xb1x\x17\x04\xed\xc4\xfa\xae\xdd\rL\\\x1a<\xc2P\xe6~\xcd\x87#\x9d\x0bz\xf9\t\xe9|S\xb1-\xe2\xfa\x91jz\x87\x12\xf8\xde\xed\xe6\xd7\xa6%\xeb\xd5\x01(M\xf0my\x13\x80\xd6\x9b,\xaeP5\xef\xf7\x84\xd9\xce\xd7\xdf\x0e\x00\xffk\xc8\x0c\xceD\xed\x8f7\x18\xf5\xcd\xc0\xe8\x0b$\x16E\xe1\r\x9a\x97[\x0b\xeb$^1[\xc1G\x0be|\xee\xc8\xc7S<\xf8~kC\xb0G\xc6(\x07<\x96`\xc4|x\xc5\x88"\x1bv\x11\x9a\xc5\x94\x90\xd5[X\x1b\xbb\xd4;`\xa0\x14\x80\xf0\xc99o\xfc\xc1\xabi\xf4x9^\xac\xa5\xc9G\xd84\xccl\xee\xbf^\xcdA\xdcw e(q\xa7O\x00\x15\x13\xa7<\xddL\xe2\x89\x85\x9a\xa6\x05\xcb\xd5Z\xfckM\xf3\xe3\xfc\x1c\x1d9\xbeN\xcdzb2p\x99c\xdd\x96\xc3\x9bl\xe6\xd7\xd1\xe6\x19\xad\x9bi\x06\xef\xe8\xed\xf6\xc5\xdd\x10\x91\xcf\x97\x9b`\xf0\xf4\x1e\xaa\\.>d\tv\x90m\xa4\x93Z\x1d0J\xc3\xf1&\x1c\x0e\xc3\x1b&\xce\x8es\xe1\xd7\xe0\xf0[T\x9a\xb77oz.\xa7n@\x16\xe3\xd8\x81\x86^AU\x11\x19\xb1\xb4\xf6\xce\x17p\x96A\r\x93\x925\x90\x96z\xc6\x81\\\xce\xe1\xc41\x93\xdd\x0fq2\xf3\n\x12\x05\xd0\x0cR\x80\x95\xfd\xc6B\xe9\xdd7[W\xb1\xdb\x9a\xb1l\r\xf8\xae\xa8o\xd6\x82\x13\xe5-\x18\xc0\xd7N\xfb\xe5\xc5\x0bO\xc0kT\xf6U\xa9{S\x9b\xde\x1f\xe5\xb9$\x07x\xbc!P\xbdf\x00\xb5\xdd \x8b\x00\xea\x13\xe0/\xc52\x1dE6\xf7f@\xbbZ\xfbra\x90\xe6\xbb\x8b\xf4o\x9dl\xdd\n\x17\xd1\xb5\xcc\xd3\x14\xadVx\x87\x93\xe06\xb8\x82y\x12F\xe2\xa9@P\x80\xef\xb5\x19\x83\x04\x06\x7f\xf1\xa7\x15\xb3n\x8c!\x18\xca[dX\xf8_\xda\xdb\x9d\x7f\xab\x0c\xf5\xf0$\xb1\xe8\xdfT\x0f\xc0\xd3\x1d\xfc$\x07\x16\xa2\xc9\x04x\xe9\xc2\x07\xd3:\xdf\xc4`F\x1a\xf8u,\x97P\xa2\xed\xdb\x1a\xa7\xff~\x96\x90\xfc\x1c#\x15\x08\xca\x96\x005|\x1d\x070\x90\xd6;\xc9sgV\xbf\x8e^9\x8eE\x0c\xec\xa9\xa9Q7{8k\xfc\xacr\x9d\x9a\xd2\xf3\xde\xb7\xa5\x0c%\x05\xa2H\xfb\xa8a\x10-\xeb\xaf\xa9D\xbei\xdeFj\xa8c%\xce\xc3\xb1+\x05r\xce\xc0\x8f\x83\x88|B\x93\x7f9\x8e\xb8=\x96\x85\x8f\xd7\xd0\xd9k\x87\x02V\xfc\xc5\xf1D\xe8~\xf3\x01\x96\r/;r\xa0>\xbd\x90d4\xean\xbd\xb4\x177>\xa9\xae\x1cney}a{\xcd<\xe9\rI\x1c\xbc\xd3\xc0\x96\xb8\x88\x00\xa1\xe63\xa7\xa2\xccm\t\r\xe0\xad^\xc7d\t\xc9R\xfc\x9a\xc1\x91\xa9U\xc0E=\xb4\xeb +\xdbt\xaa#*\xda\xa8\xd1-\xf7z\xb4e\x8c\xb6\x946\xd9\xfa\x0015\x90\xe3}"\r\x03v\xd9`\x9aV\xcf\x8a\x9ch\xfa\xff\\NA)\xf6\xcb\xee\x85\xc3\xea\x0c\xb1\x89uQ\xa281\x83<\xc6Mm\xe2v\xbb\x82.\xd8dC\xfc\xde\xa5,\xdd\x84\xa4\xa7\xd64\x83\x9eNDf\xff<Wrr\xf7\x1e\xa7=\xf2\x0f\xbb\x07(\x99n\xe5\x01\xbf~\x92\xa3\xc4\xdf\xd3\x00ZG\x8b*D\xf1\x90k\xcc\xe9 ZK\xa9\x01\xedwP\x923\x17\x89\x82\xbd\x05\xd4\xc5pK\xed\xd6-\xc3e\xba\x99\xe1\xc62\x16\x940\xe7\xe5{\x07\r\x7f${9\xfb\xdd_FN\x82@\xcc\xe8#\x19\xbcK\xd9\xc4\xc7\xa8\xc9+^\x91\xbb\x86x\xc8\xc2\xa6\x86\xe7q\x15\xb48\xd3f\xadEx \xdb\xba8v\x8bP\x13\xec\xb4oX>\x075\x06l\xc3\xec\xd4\xab\x1e\xbb\x17c\x12\xf2X\x8f,\x99c3R\xf8\xd6\x85\xf1\xb6,\xcd\xcb\x92\x12I\xee\xad\x95\x95\x86\x1aa\tl\x03\x13\xe3\xd7FK[\xd3bk\x8c\xd3\xfe0\x87^\xdc/\xf1\r\xa1 \x03K\x93\x94\x87\xf1amR[I\x9d?\x06\xd5V\x86$\xbe\xf9\xec\x97\xab>\xba)O\xfd\xa0\x85\x0c\xa7\xdciV\xa9)\xf4\x1e?\xea\xfe\xfc\x96>\x04IF\xc9\x06TN\x0b\x13\xd6\xbbb\xff\x9aA=3\xc5Qk/j\xb9\x13\xb8*\x0c\x19\x02\x1a\xfd\xdd\xbddV\xc4\xb2\xd2\x0eX\\\x06=\xef\xa5\xb6\x18\t\xdd\xca\xee\xde\xdc*\xcf.\xf7\xbb\xd1@/\xcc\xfd"\xdc\x00\xbdE\xb51\xe5\xd7\xb3\x08\x05\xe5P\x9c\xda_n\xc2\x17\xb1\xcb;\x9em\xab\xd6S\xbb\xf4\xe5\xdb^\xbb\xbeKHq\xa6\xbb\xe1J\xaaW\xfa\'\x9e\x8cAAU\x94\x9dCT\x934Z\x0e\xdf\t\x00\x1e/BJ\xec;\xb2\xb6\x1ca\xd8 \x86\x9d\x83\r\xe6\n\xc2\xd1=\x99b\xe2\x97\x11\xc7\xb2\t\xd5n\xbb!\xe8\xe66)z\xfd\xa6yC\xd0\xf5R\'\xcb07\xad\x0b\x83\xda\x12\x85b\xb4\xf0\x93\x19NF\x8aU\xe7\xa8\xfd\xc9\xfaI\x04D\xca\xa3\xbaa\x146@M.{\xa2\x1c\xc3\xa3\xb8\xbdb\xf5\x7f\xaf\xe3\xac`\x89\xeb<\xec\xd1\x15\x84\x06\xbc\xcf\x11\x94W\x1c\xfb\x0e\xba\x8c$o4\xe0\xc76\xbf\xdf\xee\x82)6Z\xb9_[\xb85\xa4\xbcz\xeb.\xdf\xc9\x0c\xe5\xdbU\xfc\xd4bA\xc5\xa1"\xa5\x08\x18\xee\x88\xbd\xb7\xb05]N]\xaa\x9f\xaasvK\xec\xdcS\xa4\xf3j\x9a\xf0\x16_\x92%\x003\xf8v\x05\xdf\xb3\xadsj\xe9uz-\x8e!7\xaa\xb2\x9cO"=*:;Fu\x04\x80\xb5\'`f\xa2\x0b\x8di\xde\xe3\x0b\xe8>XK\xe0\x9aW \xd8\xe8\x1d\x9b\xac\xd3\x1f\x0b\x0cC\x84v(\xf4\xa35\x0f\x80\x07\x8c1\xf4\xd0\x92:\xfetX\xf5<\xa3\x9ev\xba\xa9&\x1f\x10\x88\xc2\x7f\xda\xf2\xd4W_\xa5\xb1\xbe\xd2\xe5\x80<\xa1c\xf0\x9d\x1a\xca\x16+\xe4\xae\xac\xf7\xfe\x96\xde\xab\x82u\x1f\xa7\'\x8a\x83Y\xe9k\x7f\x1e\xf2\x1f\xbc\xf6\xd6\x8c\x86\x92\xf0\xf2\x13\xd2\xbaY\x0f\x07\x1b\xe4\xd7\x87\xc6\x94\xee\x18]1\xa2\xd8M`\x9ay\xa5\x91\x0f;X\r\xd9\x98\xef\xb6\xbepX\x13\x00)\xef\xfc\x88c\xeb\xde\x84e\x99\x1f\xdb\xdf4\xda\xec\xae"\xce\xae\xfa\xcb\x9e\xe1\x96Y#\xa2F[\xb4k\xb9+o\x9c\xbd\xe7rU\x90\xae\xfb\x9b\x01\x1f\xc7\xda\x90UW\x8d\xf0\xae\x1753 df\xa53\xa8\xcb\xfc\x8b\x13\xd7\xf0\x89\x05\x17X\x1d\xa1\xe4\xf1\x13\x8f\x14\xdfJ\x91\x08m\xe4\x92C\xc4\x1f\xb4\xb7\x98\xa4\x8a\xde\xf7t6\x94\x8e\xee\x1c\xf7\xf7\x83\xdc\x97\x86\xf4\xf0,:\x84\x1f\xd9hRQ\x9f\xcf<\xd8&\xc4\xcb\xce\r\x9fe\xe3\xcc\x18#F\xbexl\xe0\r\xbbh\xa2\n\xde\n\x16\xe2\x08Y"\xa8\xf9\x93\xd8v\x0bP\xf7\xdd\x83.v\'\x95U\xddn\xdc\xec\x01\xaeOw/Q\x8bVz\x04`\x11\xa7&w\x1eX\xdb\x89R\x92\xe3\xb8Q45\x04rZ\xaa\x82\x0fe{0\xd3|\x8c\xe2\x11N\x96&\x17\x9b\xad\x1bQ$\x96~\x89\xa7\x8cn\x0e4\x93g\xf4\xd3^\x08\x1f\xc5d\xf7\x0e\xd3\xe7D\xd7\x16\xfcJTP\xbc\x91\x08@%\xea\x88\xf1sf\xbb\xdd<\xd8\x10\xbb\x9fO+\x07\x047\xcbXC\xb7+By!\xd0o\xf7\xa9\xb2@\x10.\x8c\x9c\x99\xa5\xf9\xb4\xe4\xda)\xd2\xcf\xc1\xc0S\xca\xf5C\x1es\x9eMe4\xb2I\xa9\xf4\xa1\xb8\x17\x8a\xdce\xcb_~\xec\xed\xdbS\xd8:\x82Q#\xefA\xf6|)\x1b!\x0f)\xa3\xdc\xaa\x00\xb4\x12\x96\xe8\xbd\nX\x86Ml\xfcc\x1bu-\x16D\xedvH\xb7\xfe=\xe9\xe9#]\x95\x9en\xc0\xfc\\\xc4\xd5\xac\x9a-\x94\xc6\xe2J\x8a\xd7y\x97f7\x06\x9c\xc8\x0f\xee\xe4\xe4-\xac\xba\x8d{\xd3\x1f\x86W\xbb\xa6o\x9c\xd8\xcf\xcaj\x16\xa6\xa6,\xa4\x99\xa5\xc3i[\xe6\\\\[fW\x8ca\x89\r\xbcAl\x16_-\tc\x06}\xa6Q_\xdeL\xb2\xf1\xe12\x1c\x17\xed,O\xde\x8dk\xd7\xd4P2}\xb5a%\xa7\x05\xa20\x80 o\xda\xe7*p\xe5\xd2\x10\x18\x16\xc1\xa9M\xcf\xff\x1b\x9ej\xc6\x0c9\x03\x9a\xfa\xb9o\x103\x8d\xb6m\x877\xd8\x88\x9bkC\xb4\xc0WGED\xe7\xa6S\xc6X\x05\xde\xee\\\xb4\xf6\xed\x0e$}m|B\xf1\x8f\xb0\xbb\t\x1b\xc5y\xc5\x13\x98\x9d\x95#\x91?\xea*\xad}\x04n\x12}l\xf20=`x\xd1\xd7\xa5\xa9\x1d>\x8cZp\xe7\xd2\x02\xe6>\xc5 \xfa\xc7m4\x16\'a\xd0\n\x10YM\xaf\xc9\xb3VE\xcd\xe8\x16y\xb9\xf6\xf2\xf8\xf5\x16W\x94\x08\x12\x88\xee\x08\x10y\x9f\x1b\xc5\xfa\xe6\x8a\x96\xfah*\xb6\x15n?\x8a\xe8|<\t^\x14PQ\xec\xa5\xfc[\xec=\x0ck\x8a/\x92\xc5b\x85\x98\xeb\xb9Y\xb8\x98[i\xc3x\xb1\xa2?%{Hfk\xedM\xfb\xe8\xbe\xaaiid\xae\xa4\xde\xed3\x1f\xa23\xbe\xa1\x18\x0e\xaeb).A0&d\x87T\x16\xfcw\xbc\xafS\xeb*\x05\x94\xcd\xa5*|\xb9sH\r\xccB<\xea\xcfnm;e?P\xe2\x8dEy\xd0\xed\xeb{nhe\xa3\xbd;Cs@}\x8c\xc9\x8cg\xc8\xd7\x94r/\xe2\xff\xd0\x8eH-.\xce\xebP9\xa1\xa6\xa8\x98\x98}J\xfe>\xaa\xfd\xc2yV\x93]D\x07\xb0\xe6j\x94|UM\xb1;\xc5\xf7\xce\x88j\x8a<\x07\xa7\xe3\xdel|l\x1df\xf8\xfe!\xbfdf\xe5\xd7K:\xb9\xf4\xb4f\xee\x1ft\nF\xae\xbaI7\xc2\xc4z\xc6 \xbc4]\xb8\xa41\xaa4\x8f\xf8\xc2\x88\xb4\x02\x9e\xa6\xdfN}|\x8b\x9f\xdaN\xcc\xad?gE\xae\x06me-3\x91\xd8\xd8\xc0r\xf3\xdf`\x9abq\xd6\x94\x0fB\xc5-#\xc3hp\x93C\xe0\xe2\x99\x01\xa6g\xc0\xaf\xa7: \xc4\x8d\x0f\x04\x14\xf6\xd8\x02\xb9\x16\x91\x1bW\xde\r\xe2\xe3\xe2$\xd5E\x02\x1f;\xd0\xc8\x93\x10\xb6ry4\x0e\xdb\xe5C\x12@\x12v\xa9\xd7Z\xe4\x8a=}\xe1c\xbb\\k8\xec^\x82\x07\xd0$\xe3\xad\xe8\xc4\x05{\xbeDN\xe5\x89\xecM\xf6W\xef\n\xf3\x0e\xc9th?\xfa\xacr\xe5\xc2\x92\x1d\xe6\xf5b\xe6fJ\xe4\xc4t\x10\xa37~N\xeb\x1d/qx\xc2b~\x1a\x02\x9cB\xdd\x8bDW\x95K\xf9\xb7!\x1c\x7f\xae\x1d/\xd3\xff\xed2\xd4)\xef\x0b\xa8)\x9eU\x89p[\x1a\xd5\x0e\xf4\x18(\xd9\n\xbdP).\x7f\x98\xd2\xc5\xc3\x1b\x07\xac\xd4\n\x83\xa2\xa8\xbbl&\xebH\xa9{\xee5I\xa0\xb9vA\x87\\\x1c\x933\xddw\xe3g\x99\xdd\xd0\xe3_\xd6\xf3;{-\x0en\x9a?\xa8\x83^\x1b\xd0\xacI\xba\xfe\x1f\'\xc5\xd5\xdc\x9c\x8fR\x0fUYm[2\xe9\xb6\x0f\x96\x12\xed+\x1bY;\xd7\x97~\x90\x88@l\xe0l\x99\x86o_\xf5\xe3\x10\x07+\xa8e\xf3\xf3\xa2\xc2s\xb8\x8e.4\xcae\xef\x97_\xf3\xd4\x12+\xe1\xbb\xdcF\xa7e\xdd\xfd\x03o\x15\x93Q\\\x97?\x92\xbcj1*P7/\x12j\r\x12\x0b\xab}_*C\x11_\xa7\xf4\x14Dj\xb6J\xaa\x15\x8f\xf8\xfdS\x90\xa2$}\x88\xe9\xbd\xb6\x92\xe1)t\xea\x0b\x85\x02\xb4\x86\t\xa8+\x9b\xd9sD\xd7\x95=t\xfa%!\x93\x0b\x8e~\xadx{<-\xc3\x84O+\xe46\xcb\x1a\xe1\xe6\xf1\x08.S\x0e\x0e\xf9hV\xc4\xfc\xa8\x12\xb1E\x9e@<9=\xc2\xe2g\xcao%\x9f}\xbb\xc9Zt\xd4\xc3\x05\x97fb\xbbc\xbc\xdaB\x88~\xb7\x81P\xb1\x92\xafR\xefo\xd1\xd3t\xf6\x83p\xa9\x85B`\x95\xbcY\x1d\x08\xb5\xf98\x86\xc7\xc2\t\xf1\x97\xc2t\x05\x05K"\xc5Z\x17F\x8b\xea\xe5\x0f\x95r\x96,1\xae2AxPg%\xc7-\xee\xd9\xb8\xe0\xe5\xdf\xcc\xa8\xcc\xd7\xe4\xaaa\xd3\xdeh\x8e\xb5\xe15\xb9tpn}/\xe8SB\xf8Z\x19\xad>\x19\xf0\xbfvj\x1a\x1a\xe1p;\xef\xe9./R\xe86\x8b\x96\x98\xb3\xd7\x87\xbe(S\xeb[\xd3\x17\x89\xc2\xe1\xb1\x16v\x17H\x81\xaf\xac\n\xe9\xff\xda3^\xbb\xf3Fh[@%\xbb\xcd\x87\xb7\x9f\x1aFY\xdc\xcaJ(\x0eH(\xb5n\xb3\xca\nd\xd0\x04\x02\x19\xb4SL\xcbH\x8b3\x83]\x14o\xd3\xa9\xd8\x99b\xabXN\xf2\xf4\xe5\xbc\x14\xdd\x14-\xe5\xe0\xb2a\x05\x03\xb4Y#\x1c|AE\xdb\xa3\xa0_\x07\xb8Y\x88\xecO\x88c/\xe3`\xf4\x12)\x1b\xc5\xa6h}3\xae\xca\xa8\x15csy\xa52\xba\xe1\x9a\x8b\xcfx\xfc\xef\xe2" \xea|S\xe8R2\xea]i\xfa\xb5RMvw5\x85v\x0b\x109c\x19\xdb\xe0\xcd\xf5\xb3\x89\xba\x05\xf5\xb1\x99b\x1c\xdf\xa1\xf2\x03*\xd4l7\xdbiu\x9f\xe5\x1a=\xf7\x93\x8d+\xf0\xdb\xdd\x06Fo\xa8_\xb3\x97\x1d\x04NT\x99\xf2\xb6\xeb\x0bO\x1c@\xf0up\x7f\xe1\xfet\x01\x96v\x06J\xe4\xea~\xa9f\x95\xdf\xf6\xb7\x12`\x9b\xfd\x8c\xday.\xea\xb0\x82\x86\xa0\xef/\xc5\xab\xd1zg/\xfaU\xae\x1b\xeb!\xa3\xbe \\\x9a6\x1f\x9eX\xfc\xc95\x04a.&0\xba7\xf7v\x11\x99v\xd8\xbca\xd1?\xac\x8f\xafm\xe7\\\x84\x1am\xd1D\xd0h\xebr\x97\xd2\xde\x1b\x11\xe4\xb7\x9bV-\xec0\x84\xb8\xbb\xe7\x98Q\xbf\x94\xc8\x05\xba\x93t\xe0\xa7\x08\xdd$ \x1fO\xd2P1\x0eP V@\x1d\x15\t\xbclBi\x83.\xc3N\x05\x9e\xb3\xdc\xd8=\xc8\x05A\x06\x990z\x9c(\xdce`\t\xee\xd3c]_\xd87\xa8\xd0_\x17\xd1SM\xeb\x91\xf195x\x80\xd9&gkO37\xa7\xa14\xdd\xfe\xbc\x83\xcd\x87\xa8\xecf\x83\x15B\xe1\xab\xbc\'MT\xbb\xa7t\x19\xb3\x8b{\r\xc0V\x1c\xae\x8fq\x7f!e,X2\xcf\x8f\xbd\xb0-\xfe\xca\x9bQ>\xe5^1N^\xfbg\xdd\x02\x00r\xfd\x86\x16k\x0cv\xe11<A\x11\x1b\xf5\xe4\x9f\xf4\xb5\x8dUS;\xdd\xe6$5{\xff\xe7NY.\xefK\xe0\x00\xe54\xf0\xe1\xae\xa7\xfdL\x1f\xe3x\x07\xed\x97\xa6>\x99n 1\x90\xbf\xc3\xa1\x0f\xe0z\x07\xffY\x08\x80\x9a\xba\x8a\x9bH\x8d\xac\x95x}\xbb \xdcP\x17\xe9\tQ:0$#\t6\xb1\xe5a%\xa4\xbd\x85\x01\xcep\\\xc0g\x9d\xbe\x08\xd4Z\xef\xc8;}\xa3+K\xf8\x04\xd3T\x11\xc6\xf7\x0b\xcb\x1b\x82Kx7\x99X\x05\xb2kA\x94\x16\x86\xcdSV\x13x\xacX~\xd2\x00n`\xedR\x11\xae\xdcK\xb8\x01\xc0\xc2\x9d|.\xab[\xf0\x10\x81F]\xe2D\x1f\'K\x11Hx(\x96\xf2\x1d\xef\xa8gT\x9e\xd8\xaf8+\xb9g+I\xc5\t\xa5\xc00\xfa\xb5D\xba\x1dr&K\xeb\xdaR\x81\x9a|\x82\x8a+\x884\xea\xe9e 0\x01X\x87\n\x8bv\x1d\xd0\xa9\xb5\xbfjc,B\xcdd\xc7\xfe\xadrm.\xd9\x02\x86\xbb\x9d\xbf\x08\x1c^-\x80\xcd\x14\x83C\xba\xdfs\xab\x021\xd9S$\xd7\x0c\xae\xef\xa5\xd9/R\x98\x0b\xd3$\xad\x1e\xfe\xb9\xb51\xc5\'\x80\x0e\xefO\t\x02X\xa9^\xb71\xe3)\x1b%\x08\x08\xa0\x7f<\xd9l\x7f\x82A\xd14:\x03r\xd3\xcao\x07\x83\x9a&=\xdc\xff\xd3S\x99\xdaSiY\x0bZ\x8e\xeb\xde42\xbd,\xf9\xb2j\x831\x19[\xe6\x02/d\x0fP\x03\x87W\x96\xc9\x8dw\x06\x1f\xc6\x9dfu\xf1\x1fj\x08\xe4\xdb\xbd\x02o\x0ef/\xaa\xb4\x8eL\xfb\xd2+!\xec3\x87Gd4\xadyg-\x8e$\xee\xe6\xef\xc9\xe2\t\x11\xde\xb9\rZQ$\xa2\x11\x93J\xee\xbd\xd1,\xc3E^5\x1c?\xc9_H\xea\xd9\xad\xe6\xc7\xec\xa2\x10\xd5\xe5\xc2\xe7\x87\xa5~w\xa8\xc0AT^D\xbeX\xa7\xb0\x08[\xdf\xe6\x1d\x04\x13$e\xb4\x00du\x95aP\xcc\xde{IS\xeb\xdfd\x1aV\xb7\xb2u\xe0%;\xe8~~\x1c\x87\x80\xef\xc13\xa7Yt\x1b1\x04\x91y0x\xb3\x12\xcf%3\xdd\xed\xe0\xef\x9a\x9d&(\xaf{whM\xd8\xba\xed\x83\xb2\xaf\xba\xbd\xc1j\xd6#@S\xa9\x1e\x9d\r\x0b|\x0b\xeby8\xdd\x04Fd]E\x8e\xf3aLDW\xcc\xfb\xf6\x15\xa7;\xfe\x89\x0bN\xfa\x10\xee\xa6\xa8\xa8\x1e;ah\x86\x17\xdd\xedzO\x02|[lXw\x1a\xc8\n$\x00\x91\xba$\xe9\xa8\xdd\xa7\xb9=\xa2\x8a\xab\x95\xe4\xcb\x14\xe7jh\xd3\xd8\xac^\xc8\xd5r\xec\xf5\xde\xbb\xe1\x08\xc1\xe9kB\r~\xd0\x9b\x85\xc2\xb2\xca\x0c\x87\xa2\xf0\xecD\xb5/\nG\xaaU@\x13d\n\xa0\xe0\xb0\xefR\x8e\xa4\xa5\xa2\xa4\xc4\xa1\xe0\xc9\x97\xb2\xd5[\xd9#\xd5#\xc1\x0b\xe3\xf4\xcc\x89cqB\xd3\x9b\xdc\\\x84\xce\xc3\xea%\x1a/\xe8\x95\x1f\xd1dbB%?\xf3I\xc8\x88\x90\xfcq\x85\x8d\x10\xa8\xc2\xd5\x80\x9a<\xfd\xff\x91\xcf(Qz\x03\xe4T\'\xda\r\xde\x92\x8e\x16vg\xfb\xfa{T:\xabS`/\rx\x07q:\x81p\xab\xc4$w\xb2\xae\x86T\x05\xf60a\xae\xcd\xda:=:\x1b\x8f\xd7\xfc\xfa#\x11Cg\x9b\x14\xcf\xdf/\x1bv\xba\xad\x98\x0e3\xc7\xc3\xe1\xb8\x0b\x83m\x08\xa2\xb3\xcd8\xa4y\xa0\x921\xcd\x12\xa44\xb9\xc2\x97\t*\xeb\n\x7f*r@\xec\xcc4\xc4u\x94v[\xbf{\x92\xc0m&\xd7\x1c\x14@\xe1x\xe0\x92*jY\x17\xe3\x80\xfb\x0fZ\xe0\x02=\xe1t\xb3\xf4\xc9\x89\xe86\x03r\x170\xe8\xef\xa5p\x8c\xffz\x0bU(G\x95M\xcd\xed\xa0\xa9D1\x99)\xc5\xa13\x8fI\x98\x95\xcf\x82O\x0b\nG\xdbHv\x81n\x8cl\xec4;\xf1y\x05\xfbW\xbc!\x1c\xcf\x16#\xb2\x9e>M\xb4gz\xd1\xdc0i\xf3B\xcf\x18\xf7>VM\xbb<9yIq\x1a\x1eM 5B\\\xba\xef\x16en N\xa9\xd3w\xfe\xbb\x96\xa2\x9b\x14A\x1f?\xcd\xf1\xef\x15\xb3\xb7\xfe\xc6\x1c\xa09d\xa8O8\x82\x94\xd9(C\xe1\xc6\x1f\xfe\xc3\xe5\x85@@\xa3\xda%sp\xbb\x93\x18\xa5\xb1\xc2\x07\x0e\xbaZ\xca\xdeoo\x90W\x87\x0e\x03\xc9\x96z\x07\x10\xaa\x90\xb2(\'eD^\x01\x96\xf3\xe7C\xa1\xdbso\x0b\xd4\x83v\xf1\xe9Y\xe4\xc7f\xc5\x06\x88\xb1\xb4\x18u:\x89\x07\x1c\xe5J>\x03;3\xe4\x13\x80\xe0\xc7[\xeb$<\x96/\xf5\xed:$\x1d\x187\x01}\xf5\x7f\x8c\xcf\xe5q]\xf8\x14\xb1s\xe5N\x1b\x0be\xb3M\xe5\xac\xf9o\xa2a;\x05(Xl]\xb2\xe6R#\xd0\xc0\x9cx\xaat\xc9\xb0}\xdf\xbd\xa2\x15\xa0d\xf3(\xd2\x0e\xa9\xd0T\xeaj\xee\x0c\xb4\xc0\x9an\xba\x90@\xbd\xa0\xff{\xa7}Q\xf6\x9aUp\x19\xb4\xfe\xe0\x1f\xca\xdf\xa2\xe8A\x10\xe6;\x01\xd5\xcdDr`\xca\xbfM\x83\xe7\xa8\xbb>0\xcf$\x8an<\xf3<H2C\x9eA\xfcA-\xbf\xc4\x81\x89\xe4\xf1\x98\xea\xc6:\x10\xb8\x0c\x84\x87>\x08W\xa9!?\xb2\xee\xaar4W,\x8e3&\xd2\xde\x99\x90a\x9d\xfb\x8f\xe1h\xe2\x83\xb1XW4\xef]\x90\x19\xf7\x84b\xa6p"\xe6\xb1\x81\'\x90\xd9\x1f\x8a\xfeg\x849\x96B\x14wfo\x01\xbbK\xd9\xa2\x1f\x9a\xd7sn\xc8\xda]\x94l\x105\x8c\xae>;YVi*\xf1\xea\xaa\xec\x0b2\x94?\x0f\x12\xa1\xa0\xf3\xc5\x0e\x96XA\xed\xa4\xbe\xaa\xf1_\x1e\x0b`\x8a\x8ct\xe3\xb4k\xaa|B\x82h\xf6pF\xa7\xd5\xb5bk\xaf\x84V\x1c\x1fV\xb8\xdb:\x82\x91Pwf\x83Z\xaa\xe2\xda>)\xfel\x7f Q\xb1_oF)JU\x88\x7fv\xea\xced\xef\xce\xb5\xef\xd1\xb6Fu\xacjZ\xb9\xf5h\xf0\x8f.\xff9\xfe6\xc7\xef%R\xb0U\x82\x1f\xef\xc7:\xd9)\x80\x98\xf5\xa0\xfc\'\xd3(\x03(\xa4:\xc2n\xc6GO\xf7\n\xbd\xb4\xc5\xec\xde\xd8>\x0c\r\xd2\xc4\xca \x90V\xd3\xe0\xf3\x0c}Zm\x8dmc\x10\xa7`\xde\x1c\xa0\xdc(\xa5s\xa6\x92R\x97\x06\xe7/\xebL\xc5\xd3\xf4\xadl\xbbA-\xd9\x93+\xb3\xa0\x14\xd8\xfc\xd3H\xc5\xb2\xf7-\xc0\x9eg\x83n\x97\xd5\x0egL\xe1|=s\xdc\x99N\xe4\xd8+\xe8[\x00y\xe9\xdb\xa8\xf4\xe9\xc5t\x01\xb5\xe9k_\xf1\x8a6\xdfw\x12\xef*@\x06\xc3\xf4f\xf5\x0f\xbd\xf5VP-\xd1\xe4w6l\xbf9\xa0\xaa\xc0\xbcn\xf0FQ)|Y\xb23d\xdc\xb7\xc5Rz\xd6\xbc\x03\xa2\xb6\x03\xa1}\xa9=\x9dm6\xc2\x8e!\x02\xe7\x01n\xb2\xcc\xb0\xb6\xd1\x93\xae\xe6\xd9\xa6l\x8f\xce\x1c\x1c\xb0\xa8\x11\xa4\x98\xf4\x10\xb6\x1f\x18\x9a\x17\x96"\x01\x92\x96\x15LB7\x0288\x0c\xac\xb6\xc8P\x8f\xa6C\x81Jc\xda\xf3<\x9c\xf2m0\x91N\x18\xc2\xc5\xb8\x1fM\x7f\x8aQ\xeb\x10o3\xe9\xb6\x82^Sx\xe0\x1b\xc3y\xaa\xd6RKjb\x9c\xbd\xfa\xa8#$\xc9}Tg\x0er\x12\x00a\xde\x95\xa5T\xd8/\xbd\x12RR\x00\xe5v\xdd1Q/\xea\x0f=\x8ehg\xccs\x93\xf9G\xe7e\x93\xd1g\x8b-\x8c\xdf\x1a\x1e\xf6a\x1e\xc0\xfb\x91b\xef\xc7\x88\x06b<\x81[=.j\xf9Q%\x12d/\x91\x1b((\x9aw\xf7=\xeeT\xd3\x9b\xb0\xb1\x83\x9d\xde\xf0\xe3L\x0b\xd9\x1e\xb1\xf1\x18\xbc\x03Q\x03\xc0\x9f\xe7\xd7\x04\x89-\xef\xbd\xd47\xa31?.Z\xa1S\x14L\xb1\xcb9\xde\xfe \x13L9\xd7m\xff@\xfd\x9c\x85[d/\xc8L0\xdd\xf0\x95!\x02Z\xce\xb7\xe7\xf2|"\x1b\x8b\x13E\xcb\xa3\x01$\x8d\xf5Q\xa6\xa2\xd6\x96\xcd)\xcaPt\xee\xa3\xf9W\xb2\x19\x1f\xfaWH\xec\xa6\x84"\xbe|9\xdf\x99\x9b\xf9\xbd\x8c\xb8\xa5^Vw\x10\xb86\xd0\xc3\x8b\xa4\xc3\x17\xe1\xef\xe8\xcc\xbe\x95\x91\x87\xc8\xe7\x8e\xa9\xc7\xf0\x10\x7f\xc8\xe20U\xd2\x9e\x9fgQ\xdc\x87\xccBp\xec\xd5\x82\x9ey\xc8+\xaa.\xddp\xca\x9aD\x1c\x8b\xd2g\x13\x874\xb5\xbdX\xf2\x8e-R\x95<\xb4\xdf\xa8?\xab\xca\xaflpf\x14a\x8ea\xb52\x11\x9c\xcb\x11f\xfc\x892\xa0\x03\x11\xc6\\\x8f~\xb8\xc4\x18b\xca\xd6\x1d#\x1a\xff<\xeb\xde\xd1n\x17\x0c\x97\xf2y\xd9\x0b\xaf XYLdGd\x0f\x03\xda\x11\xe1\xbc\xfe\x12\xe8)\xfdU\x892\xb8_\xf7\xaa\x07\x06)40[l\x89\x92\xbdT\x8d\xf3\xb1+]\xad\xf6\xba-\x0ekmx\xfc\xfa\xea\xb4\xc9`~\xa9u\xb9+m\x1c\xcf\xd7Yz\xc1l\xd84\xed\x00\xa7\x98&\x11ax\x94y\xdf\x9d\x87\xa1\xdc\xee\xd5\x1f\xcf\xbf\xfb\xf4\xaf\xbd\xe2[\xd4\xe8$z\xfc\xaf\x0b\x98,\xd2\x15\xf7`H(\xa0\xca\xd9x\xa0\xf6\x8f?\xe4\xfb\xbb\xdc\x81l\x0e\x0c#\xfe\x9b\x84$#if\r\x06hQL\x8dB\xb6y/\x1c\x89\x8b\xbek9]\xba\xa5\xfe5\x87\xb3\x1e4A\x08Xq\xd3V(\xff\x86\x00\x11\xb6h\x92\xfc\xdd\xcaZ\xe8\x95\xb6B\xd8=-\xac\xb7\t\x8b\xddH\xeaD*\x9e!\xd7z\xffIr\x8f\x86)\x00{\xbb\x0b\xebrV,\r\xf8Y\xb1\x8b\xe3\x9a\xa8!7\xb8\x19\xb8\r\xd1/\xd91\x84\xe7\xae\xb3V^w\xb2-\xc8\xd4K8\tdt1\xc9\x89\x10U\x9c\xe9\xe4\xc1\xab\xc5\xf9:*\xa0\xab\xae\xa22n\x81\x97\xe1\xd1\xca6\x0f\x15\xc1:\xf7\xda\xdf\xdc\xcd\xc4\xaa@\xaed@\xb8\x8f<\xde\xa9\xab\xd9\x96\xf7\x84Z\xc9}\x9d\xb4\x82\x81\r\xaf\xab\xe7\xf2"\xca!\xe0[\xea\xc0\x9fH\x86\xd0?\xf9\xa9\xdf\xf1{\xe6@\xba\xea\x14\xef\xf3#\x8du\x9a\xday#v\x84ueu\xfe\xf4j\xdb\xc2[n\x82>\xa0\x80\xe6\xfe\xb6\xb2\xdcG\x87Gn\xeen0s\xa6\x90\x12\x86\x16\x95-\xef2m<\x86*\xb5@n\xe0fy\x8f\xbb}\xcc\x9cR\x149\x84J\xc5\xf8\xe7x\x9c\xc4\x7f"\xc4\xb2\xecz\x0fXJ\r\x80\x0f\xfa\'\xae>FZ-\t\xb4\x11\xbdu-La\xfe<\x1b\xb3HU\r\xd8\xd1\x8as^\x05\x9f\xa9X\xd5\x18Q\xa7\xe9\xe0\xf7h\x04\xa9 \x9d\xbd\x80\x03\x97\xb2_\xd4s)\xc8Z\xc2\xa38,\xd12\x93\xe6\xb4\xf6\xf0&\xd5\xcd\xf7\xdb,\xe0\xbd\xe2\x11s`\x06\xa8\x07@\x8d\xea\xaf\xfb\xa9<\xef\xc2\xbb\xe2\xc7e6,}\rq\xfb\x82\x06\x99\xb2{\xf5\'\xac\xd0M\xb1K\xd6\xe1\n[i$\xdb;\xe0\xa0\x10A\x89\xebc]g\x90\x8b\xacV\x0f0\x1an<Y<\x854_$\xc3\t*\xc5ze9P\xd2J]\xd4\xf0\xd6\xa2y\xd4]\x1eS:\nDe\x8e\xbd\xc9\x15\xbc\xfd\xcf&\xf57\x01\xf7\xbd|;\x85\xbf\xe7 \x91\\l\xe7\x8d:\xeb\x19\xb4\xb8\xf1\x95\x155n\x01\x8f\x95b\x97\x81\x8d\xfdZd\x11\xe1hwU\xce\r2\x91\x95\xacL\x07+\xed\xd0\x15&\x99\xf4u\x07c\xda\x16\xd8\xd9%$\x8a\x8a\x8f\xa7\x17\xb6G\xd3P*\x17_?\x0c}F\xbeI\xf4\xf6\xc1\xfb\r1f\xaaU,w\xfc\x08]:\xb8\xd1\xf4I/\xd4\xff\x81\xf7n\xa5\xe5\xee\xd1\xe6\xfd\x10\xaaw\xed\xf4\x82bCO\xfa\x10\xaf=c\xdb\xb5\x01\x176\xa0\xef\xff3k\xd4\xcf>\xf3\xa5\n&(\xa4.\xed\xfc?\xfc\x03\x97\x99p\x0ch75\xe4j\xc71\xec\xd0v\xb3\x11\x87\xd8K\xa3e"J\x13J\xcbwP\xf0?4\x91\x03C&\xf2o\xa6\xd2l\xd0\xdb\x81\x94W\xb1|\x92S\xe3@\x17\x96\x9b\x16/.ys\x92+D\xfa7\xab\x88\xee\x88\xbejI\xa0\xa1KDQ\xe4<\xbb\xa0D\xd3\x9a\xef@\r\xcc\x9c;G4o\x12&m\xa8\x97\x898\x1a`\x1cM\xd5\x1bLS\xaf)\xd5\x8b\xa8C\xaa\xdf\x9f)\x8e\x84\xacM\xd9\x84\xe8YA\xc3\x0f\x80\x9b61\xedl\xcd[\xce\x80#3~\xe8\x86\x91\xc1\xc4h\x8aI\xb6X\xef\x86\xb7\x036l\xa2\x05?\x1f\x19q}7\xad\xde\xda\xd6i\xfc\xd1%J\x92l\xacq\x8c\xc6r\xe1\xc1M\xdfV\xd1:q>\xe8\x9fX\x18\xbe\xd1\xef b\xa0\xaf\x04\xd3\xe6\xf8\xcf\xd4\x9ae\x96C\xeb\x84\x11\x82\xac\xd9\x9dc 79\xce\x10\x87v\xdb\r\x1cS\x9d\xab\xeaa\xa3S\x8a\x81\x98\xa7TB>\xf0\xe3\xdfWp3k\xe1\x80\x97\x9eNs\x17\xe7\x04\x85\x0by\xb5\x8dm\x89|J\x8c\x8c9\x04r\x0e\x15\xb0R\xc0\xe57IMU\xef\xbdrp_\xe2C`\xfe\xd1^\xccs\xb0\xce\xc6\xc4\x19\xa5\xca\xe7R\xf3\xf4\xde\xe6p\x8e*0\xe7\xb8"\x15\xb8\xfc\x13i\xa8\xd1]\xd9\x13\xac\xf0\xe6O\xcb\xb4d&\x0c\x0eAA\x89\xea 6\x1d\xdbR\xf3\xd8\xfb\xaf\xa7\x17>\x8b\x94\xbf&0\x8e\x81a\xf3\xc3\x03t\x06\xe78g\xa4\xb2\xaa\x1baU\xd6)\xce\x0b\x84\tDp\x8d\\\x10\x94\xfdy\x8f!\xc5\x8c\xfb\xb9\x8b\x88\x8c\x16\x13Ib\xbd\x93x\x016\xd7\xf37{\xc1_\xc9\xb9\xf5\x01t~\x97#F\x10+\x07\x10\x81\x8eW\x04\xf9\xf0r\xf5G\x80\xc1W\x08d\xa5(\x07?\\\x8e\xe5\'\xa9\x88\xcf\xfb\x18\xd9\xda<\xec\x01\xd4Z\xed\xd6\xc9\xec\xd9\x06\xad\x90\xc00+c\xdd\x91\xf9\x9b\x17\xda\xaa"\xec\xc7\x9e,\xad\xb5\x82YNJ\xf9\xc0\x85\x92x\xbe\xc6\x87\xd9A\xfcf\xc9\x8b\xe5\x14\x16\xa6{T$\x03@O\x02\xc2\xf5\x1e\xf8\x0e<\x01S\xa4\xa1\xe9d\x19N\x9f,\x94.>a"6\x0c\x8e[\xa9\x96P\xceG\x1a\xd9@\\\x02\xfe\x18P\xfb\x17\xba\x1f\xe4\xbfR4]y\x0cC\x07 -\'\x91\xe0n\xec5x\x14\x8a\\x\x96"\xf5\x89\xee\x86\x1c\x08H$Xp\xc6\x92N\xbc\xb0\x0cu\xcaK+\x8e\xf3\x17:\x1e)\x93\xb5\xe3\xccs^\xc1\xdf\x83\x95>-\xc3\xfc\xbb\t+\xe2~\x1f\xca\x1b3\x91\x97\xcf\xdc\xfa2\xc9/\xfd&lW\x0b\xb3\xff\xcd\x8e[\x1d\xa6\xfa\xdc\xa9Bx@\x91xS\xff\xfcZ\x94\xa8\xc4\x9a\x06\x8b\xd6\x11^2\xa4\x05\xaa\xef\xbe\xc6l\xbe\xef\x99Y\xd0\x8em_\xa0n\xdf\x19\xf8IJ\x196\xf9\xdf4\x13\xad?xN\x99\xa9\ty\xda,\x05\xb4\xb6\xd9\xcb=<\xf7"\xae\xd1\xbd\x89\xb0\xed\xbe\xd43"\x95\xff5\xb0\x8a\xb8~\xb7d\xff\x8b\xdb\x04p\xc7B\xbc\xc3\xb5>Q\r\xd0\xa9\xfe\x1cg\x88G\xc3\xbd%e\x9cX\xf1s\x10N@\x7f\x0f\x7f\xd6\x91\x08\x0b9\xa5\nH\xe9\xb9<(\xc8\xb9\x11\x12\x92\xc3\xfa\xe3Y\x84\xf1\xcd\x1e\xb65\x9bTwX\xba\x15\xd9.\xbf\x85\x0e\x1c\x92B\n5\xfbk\xb42\xb3Q\x18B^\xdd;\x7f\xa8\x8d\xe3\xd2K\xb8f\xf0\x8e\\z\xf4\xfc\r\xda\x9c:!\x9a\xf0E`lJ\\\xfc/\xf6\xe8\xba\x95\xc1{\x95\xa3\xa6x+\xb6\xfcB\x87\x92\xe3\x82tcjb\xce\xa3\xea\xb3\x9c(\x91Kw\x05\xd2)\xae\xb1\xd1\xfcz\x8b\x18b\x0b\x1cv\xff\xf4@\xc6\xc3\xa0-\x019\x980\x04\xea\x06\x03\x98~!`\xd0e\xb3\x150\xf8\x1e\xaa\xb8G\xb7Eo\xaejg \xaf\xdf\']5\x05\x8b\xf6_\x0b\xa5\x9a\x82\xed\xb0\xedW/\x93\xd5 \xb1\x18\xd1\xd4Q\x00\x8f\xaa2#\x99\x0e\xfd\xe8W`\xd6L(f,\x1c\x92\x19`,%e0\xcc@2rf\x93LC\x8a\xa5?s\xd9\x14\xfa7B\x7f\xda\xf6Nut\xa2m\xfc\x11\xf5:UUz\x10\x87h\x95\x89\xcb\x8d\xe0\x96R\x86\x9a8Mlq\x9d\x02\xc1\xd2\xf6J\xd2(\x15\xb9PHg\xe2\xa2,PI \xa6\xfd\x04\x15\xce\xdd^&-2LD\x83P\xd9\x82\xf1-`%\x95~\x12{\x05cx\xd9&i\xaf\x1b\x9b\xc6J\x11\xbb\x89\xfaN\x11\xc5\xbe\xb8\xebG\xc0L\xdb\xb2d$\xa3\xbfP\xf5\x81\x11\x86\xd0\x8d\xbf\xe2\xcf\xe8FYMu\x95\x86J\x1a\xd2\xb3\xf6v\xa0S`a\x1d$\xaa$\xc9\x15\x84F\x9cb\xe7*\x10c&{\xa5\x8c[;\xb8\x1f\xa5\xa1\xd1\xaa/\xb5\xceb\xc7\xf3~\\\xc6h#\xcf\x08\x9c\xe5\x80\x162\xf5\xd7w\xd9\xf1?\xa7\x94hHj\xc0+\x92\xbe\x181o\xf5\xe2\r\xf9\x87\xc8p\x00A\xf8\xaa^\xc1\x9f\xf8\xc6\xd4\x91\x1a\xdc^\x03Z\xfb\xf4.\xc3\x85|z\xe6\xfc\xbev\xde\xea\x1a-\x9cN\'\xbac\x0e\xa7\xbf\x86\x15\xeeZ\xc6\x0e4ol\x03c\xb0\xe3{\xa3\xf4K\xa2<\xef\x94len25\xef\x97B}`\x93\xae\n\x8e\xb5\xc5Y\xea\x8813\x05\xcd\xff\xeb"\xfek$\xa8\xba\xbc\xe7\xa9\x08+\xeeQ\x1f\xb8\xe8P5\x9a\x9c~E\x80_>\xe1\x14\xef\x1e\x9c.\xb0\x05%\xfc.v\xb5\xb7\xc3\xb4+\x87/h\x018\x04+\xa3}\xff9/G.,\x03\xe89\x0b\x82\xdc\xc2(\xcb\x0f\xa2y38\xf17E\x92:g\x13\x0e\xf9k\x91\x80\r\x0f\x91?\xe2\x18\x96@?\x03v\xc7\xaa\xfd\xa0\r\x19\x98\xa7yC\xd1"2(\xc2 \xd7\xe1\x92\xa8\xeb\x06\xe7j\x8b\x89\x95\xde\x92\xe3Ya\x16A\xb4\x81\x99#\xf7\xf8\x0c[\x04Q[\xe4\xa71_\x05\x10\xdb\x92\xbf\x9f\xbdw\xac\x12\xf8s.\r \xa8\x15\x84\xaf08\x8d\x17\x07\xaf\xd1\x87\xb6\x89\xa8\xf7n\'U\x02\xbc\'\x03\xcb\xf5x\x7f\x86L>wEg\xda\xad\xb6\xf0S2p\xa6)\xb6H\xa3\x85\xfc\xd5]\xe0F\xd0\x8f\xf1\xfb\xe8\xcf+\xd3w\xc1\x1b\xeeD\x00\x06\'9\x16\\\x8d\xd4\xc2f0q\xa9B\xd7p\x11\x91l\xadr\xcb\xbd\xa3E\x14\xc6\xf2\xc4\t\xe5\xedc\x87\xb4 V\xb06AMb\x8a\x0c\x80\xab\xf8mW\xb3!\xe8\x80\x04A\xd7\x1f\x08\x13\x02\xa2\xeaw\xc0\xad\x04"i\xbd\x11|\xad\x7f\xe07\xf0\x1f\xf3\x1f\xae\xaa6\x94\xeb\xb8!n\xbf\xb5\xf7\x10x\xdf\x0c\xdb\x91}Q\xfbM\xc5?\x0c\xe7_\x1e\x94\xd5\xfck\xa3\x93B\xc8\x91gy\xc3@\xd9R)\xbe\x86{\x1c\x00yU\xed\xb9\n\xac\x18\xa2^$\xdcO~8\xe5\x80\x86"6m\x9da\xf4\x1e\x80u"\xed}-S\x8d\x86,\xb2\xc0\xdf\xf4\xbd\xa28jy\'\x88]\xc1\x9b\x9f6\xa1+n\xd5g\x94\xc18\x80\xa1\xc4\xb7\xcd\xc9\x80?\xdf\x8b\x02>?;\x9e\nH;\x05e\x08\x9b\x8a\xe9\x91q\x0c\xf9\xeb\x84\xd5\x10J\x1f\x81\x88\x8c\n\xaf\xba\xfd"Y\x84\x13M\x1bk{k\xdat>\x0f\x92E`\x06\xc9Cm\xd4\x9a\x93\xbc\xef\xe9\x8am\x8c^,\xa9B\x1d\xe6\xd8\x8b\x9b\xd6\xa4R\x8d\xdc;\xea9\xba!\xe9\xfb\x12\xf7\x9aD\xf6\x07z\xf3\x93\xc9\xd1\x9c\xae\xaae\xbe\xfd\xb8\x8f\xe0e\x9f\xb7J\xef\xed\x17\x076\xa9\xa1\x13\xb3\x1dE\x12hn52\xdcTKz\x1b\x112\xfa\xcb\x0f7\x9e\xba\xb9Ytm\xd5\x10\x92\x94ft\xf0\xb6\xe7+\xc8\x08\x0c!\x8b?&\x07+$\xc8\xa4\xfa\xf0\xd0\x13\xa74&\xf8\xe3\xa7\xc7\x07\xc64O\xd1M\xb3\x81 \xc3\xafzP\xf0=\x12\xc1\xa1\x12\x0fu\xc6\xe0\xa2\xc6nq\x8f>\xf1\x89J\xf1\xf0\x90\xf4U\xa9\xaf\xd2\xd6\xcds\xa5\x9b\x94C\x0e\x06\t\xe2W:\xca75\xdb\xb6\x81\xd2\n\xba9G\x02B\x83\xad\xa7\xf3AQ\xe3\xc4\xdfV\x87\x8c?\xb3+\xcc\xa9\xde\x96at}\x81\xb8-C,\x9cK\xe0\xa55.AG\x97\rEK\x93\xaa\xae\x85\xd8\xad\x0e\x8d\xda\x80\x9a7\xb8\xb07\xdf\xe1\xe1\xd7\xbbT\xdbVb\xa4\x98\xe7\xce\r\x88\xd7\xa28or\xf4h,A\\}\x13@\x16u\x9b[\x03\xa4\xc5\xb6g\x18x\xca\x12\xbe9*\xda[\x97t\x1a$H\x1c\xbc\x01\xbaF\xd6\xd5)\xfd\'\x14_\xc9)\xd4`\xd8\xf1\xf1\xfc\xe8\x1c\xc8\x96\x17\x07\x9a\xf6\xdeTbp(\x96\x8e\xe4\xc1{\x0f\xd1\xaeA\x96\x80\xc3\x16V\x92\xb8\t\xa3\xc1\xaa\xa3b\x81K\xfb+!_\xc1s\xba\xf8\x95\xd5J\xeb\xd9\x10+\xa0\xf7@\xf5\xf3\x90@x\x8boo\xdeP\x11\xday\x18\xa54\x81\xeeC\xbfT\xe9\x89\xafo\xf0\xf4W\xd8\xb8\x99\x84\xf5\x94\xf8\x87\xaf\x16\xb1L\x8bp\xccP\xf4\xa4\x9b\x95\x7f%\xc7\x0eRr\xaa`K\xf2\x91\xae\x85\xd9\xbe\x9ag\x83p\x81o\x1c\x8d\x8d\x96n\xe1Gy\xf3k\x83\x19\xc0\xed\r\xe1\xe5Wtl\x1bJU?q\xb9\xf2\xc3\x0e\x97\xfa\x1f\xdce\xc9\x11H\x954\xe3\x0c\xd2P\x1d\xdf\xe2\xae"W\x04\xb6$cG\x97\xdf\xf7\xee\x83\xbf?\xd1\xab6w\xfd\xcbj\xc9\x03E\x99\xca\x8e\xfd\xfcsd\xd8\xa2l\xf9\xbe\xac\x98\xc6\x82\xec\x18U\xc7\x8f}\x97\x16\x90Cu\xc0\xf8\x8a\xbejo\x12\xb7\x85\x08\xed\x8fB\x18\xcfr}D^,\xa0!\x1b\xa1\xd7G\xd1$vL\x9f)\x1f\xd5\x82\x8a\xc5\x81=\x82d\\\x9f\xd6\x01\x81`E5H5\x88\x0e\x10\xfc\x0e\xea\x977\x1d\xde\x1b\x96MD\xf3|9\xd2\t\x1cP\x1c\xec\x80\xa4\x9d$x\x1f\xef\xcaA\x99\xbe\xa5\x17b\xc5\x84\xbe\xd3\xfc\xb5\xe0\x93Fw\xe5\x19\xeb\x0c\xcd/\rA\x87\xc6\xe3\xb2\xf4\x03\xcd\xc6s\xe9\xca\xd5E\xce\xfe\x93\x13\xec\xb1\xa2\x7fN\x80)\xed\xde\xeb\x9e?\xde\x1a\x06\xdc\xb2\xe0HAn\xecN\x8bl\xacQ\x92\x15\xb9y\xbb\xbc\xaa\xedV\x81\x01S\xc8\x1cLoz\xc8}\xcd\xbc\xd9\x1a\xb33\xf5\x9c\xe8\xb2\xafL<1\xc52\xd2(\x06\xcc\xaf\x10P\xc7\xa9?/\xae2\x03P\xc4\xbf\x92\x86N\x84\x8f\xdd\xc5\xb6In\x1f2`\x90\xa0\xa1\xd5\xb4)Vg$\x1bj%\xb2\xc2\x1eT\xea\xd9\xd2\xfd\xf8\xff\xb2%\x0f\xcb\xc9\x04\xd4\xaa\x91\x0c\x0f]\x82&p\xa75\xb8\xe6T\xd1\xcd\xf3\xc9\xd6\xc1\x18\x93\x9c\xfa\xfa^\xf1\x7f\x8co,\x1f\x19kt2\xa6rl\xbf\xeb\x8a\x12#\x9bW,\x99\xd9\x98\xfe\xd3)r\x99\xb2tS&F=\xa1=\x92Y\xe9\xe7\x7f\xbb\xbc\xca\xefn\xb2\xd5@\xd5\xfb.\xf8\x84\xcb\x1a\x96\x81k\x06=\xe3\x1b"\xf0\x1c\xbe\x87\xf4\xd98\xea\x944\x8eh-\xc3\xa2\xc5\x1b\n\xdf(\xd9L\xa5]\xc3t\xcd^\x0c\xeb\xa8\xb5\x9f\x99\xc3h\xaa\xd4\xdb{\xccs\x1as\xa0\x8eG|Y\xb0=>\x81\xa0\xcfH\x1b\xed\x8e\xc0\xe3\xa0L^>)\t\xf3C\xb2\xf5\x93\x95\xfcm\x03\x16\xf2\xc3\x8c;\xeeXx\xfc`\t<\x99p=\xc8\xb5\x05\xf0 K\xf4\xd6w\xe77\x98bE\n\xd1\x93\x92Q -\xa71\xe0\x9bb\x98\xb4F\x1c&\xfcZ_9\x1e\xbeG\x8f\xc9^\xf3EL\xbc\xad\xd2\xa5T=\x1d\x88x\xea\xe0\x9b\xfcm\tM\xdee/XO\x1fN\xd3\xf5\x13\x1a\xc8K\xf82I\xb0T:\x8b\xf0\xca32\xad\xbb\xc4%D\xd7\x9b\xd7\xb6\xbb\xfc\x10\xe6\xad\xa6\x91\xff\x19\x801\x07\xf9\x90\n\x80\xfaN\xb3\xfd\xb4\x90\\\xe8\xa8\'\xad\x91*\xbd~\xdf\xdd\x99\x9bN\xd3\xd5\xe7\xf0\xe1\xef\xda\xc9\x9d\x91]\x0f1\xa4\xdb\x10}\x13q\xa1\x89,\x99\xff]\xf9\xc8\xcbyJ\xbeU\xcea/I/\xa9\x085uBE~\xb0\xde8\x92\xd6\xe7\xc7UA\xf1G\x84\xae\xa8\xb6\xbd\xed\x06\xf4\xe4\xeav\x0c\xa7\x19@S\x99\xd8\xdd\x041K\xdf\xb1\xd6\x15>\x7f\x94\x92f\xaa\x90mo\xa6\x85<V"4W~i\x10\x9e\x00\\\x0c\x86\xef\xfd\xd2\x1fB\xdbo\x1a6\\\x9b:\xab\x152\x1c>-\n\xf5\xe1n@\xb1\x165g\xad\xdf`\xf1\xe6k%\xfb\x00\x9b\xcc\xe17\xd4J\xc3\xb5\xa4\xa6\xe7\x0f`\x08\x7f\xac\x11Ah/K\x85\xc7O\xaaMZ\xb7\x1c7\xf4\x19%^\xd9.\xb4\xbep,\x9f\'\xc3\xe6+!\xdd\x16 \xab\xb9/\xd8\xba\xb2\xcdgU\xad]\xd1%\x1fXu\xca7/\xabu\x9b=\xa6\xf0\x80\xab\xcb\xb4-\xb7\t(\xee\xe9C\tEQ\xdbS\xa9\xc5\xf3"y\x18\xa2\xa8\xe4\xe1\x9e\x04\xcfp\x81 g\xef\x90@\x1fq\x10y\xaa\xd2\xf9\x07\x8c-\xf3\x1b,\x86T\xf1\x85\x95\x85YQ=\x11\xae\x8d\xc4\xf5\xaf\xc5F\xb8\xfd \xc4<@<\x85-h\x7fV9\xf5\'\x17\xebD\x0b\xa4~\x0f\xb0\x9c\xfeu\x82z\xac\x18\x0e\xf52\xc0\xc2^\x05{7\xe5\xaa#\xa3\xe4\x84\xa4&},`@\xb9\xfc\x86\xdb\xd0\x84\x86\x0fS\xcd\xeb\xd2u_\xfc\x99L-\xd5-&B\xa7I\x8b\xc62\x12\xb1=7#\xdf\xf9\x99\x08$\xd3\xaf41Z(\xab;(A\xdf>\xb4+{\xb02\x11D\xa7]\xfd\xd2\xb8\x8av\xc4n\xe5\x91\xec\xdd\xcdg\xc1%\x8b(\x0f\xf1\xcd{l\x97\xab\x1a5s\xb3\x03\xcd\xc5m\xb3\x1d\xc7\xfc\x1fq\xf0\'w\xdb\x0e\xe4\xa6]\xe6/S|1\xd8\x1cw\x850\x90\x11\\g\x07z\xbeu\xd7j)\xf6\x7f7\xcd\xf2|\xbe*\x95\xad\xdb\xc9\x12$\xe8\xbf\xde~\xaf\xd2=\x9c\x88\x1f\xba\xba\xc8Z\xf0\xd2\x84C\xaf\xc9-\xa1;\x1f\xab\x06?BO{Gy\x90HU\xdf\x8f\xae\xfb\xaa\xbe\xab\x01\xa2t\xb0\x90\x12\xc7\x10\x00\x92@\xb4\xde\xc3\x86\xb8\x1b\x97P.X\xd4\xdd?\xb1\xadz\x8b\xa3\x9b\x82\xedY\xa7/\xfa*Au\xb4\xcb\x9f_\xdeV\xe85\xf4GLN\x8cA\xa1\xf6\xe60\xc8\x95\x17*\xed\x08KF\x8e\x02%m\xc3(\xe28P\xf1\x07\x88L\xc6k\xd1d\x1c\x06d\x8b\xf1\xb6`t\x8e$n\xa1\xde \xb1\x10\xe9\xc6]aE\xf3\xf7\x07\x94oT\'\xa0G<\xb3\xa3I%PH\x9bq\xa6M)|VM\xbe\xc9\x93Nc\xcb\xd7\xeef\x0c\x17/\x0b\x0e\xdeR\x9e@>)\xeb\xd0\xf2\xfe\x10\x81\xa4\x03j\xf0Nt\xbd=>I\x0f\xa6-\xe8 \x15o\xe9\xd72\xe6o\xc0ee4\xf5`\xf9}\x92V\x1f\x85f\x03\x7fCJ\x05\xd4\xf3\xb3\x9f{6\x0b\x13\xdf\xee.R\x05\xd9\xe0!\xb7\x85\x16E\x14\xb2\xef\xd5\x05\x16C\xba\xdd\xb5E\xf9R\x1a\xa9\x04\x1e\x83\xac\xd8\xad\x07q#\xb34\xd9\xa2\xb8!\xb0\x12\xec\x1a\xa3(\xbe\xdfC\xe0qN\\2\x15\xa2\xea\x07D\x13\xf7\xbf\x1c\x19\xeeL\xfe\xc6\x83\xa7\x8e\x8e\xe4\xa06\xd3g\x81\x89\xc5:w\x1f\x97\x16\xf8P\x98\xa6\x03|\\\x83\x8aAx\x83\x1d\xbcw\xd5\x98H\x15\xde,\x15\xb3\xe8\xb3{\xb0\x0cP\x0b\xc0\xf8\xf5\n\xe4\x1ac\xf1\x18\x10Y\t\xef>\xc9RXy\x8fX\xde\xa6\xee\xb1\xc9\xcb\xb2\xb4\x1d\xa7\xed\xba\xd2\'K\xd3\x00\xf8a\xc9>\x7f\x84R\xa0\xa6K_\xb7`[\xb6X*.\x1d8U1/R\xa8^\xe5Qm\x07\xa4\xe5\x84r\xb4"\x80\xc6\xd2V\xfd%\xad\x0b]QZu\x82v\x92N\xce\x8fT\xe3\xf5\xa8\xa5\xf3:J\xca9\xe3\n@f\xd4\x8e\xf8\x91\xcer\xa3\xca\xaf\xeaG\x02|\x9c#\x0e4\xf9c\x05\xbbF\xd9C\xdd\xb7\xaeQHS\x11\x137-\xb9\x93\r\xd5\x1a\x8d{\x83~\x01G\xd9M\x88\xf8\x11\x0cW\xc5c\xb9\xd2\x8d\x0c\xfc\xd0\xf7\xe7@n\xff\x0c\xca\xe5c\x1c\xdd\xeba\x17\xc6\xfcX3\xce\xea\xdey\xdf\x05\xb4\xc1\x14>\xabqX\x10l\xbcj\x1cc\x15\x86\xd6\x7f%b\xbb\xf2\xb4\xe9ViB\t\xddb\x8a3+\xb2\xeb\x02\xb3\xdf\xfb?\x86\xa3\x9b\t\xf1\xfe\xf9\x01wB\xda\x95\xda\x9f\xd2\xc6\xf9\x1f \xa4\x8aC\xect\xc2\x9dU\x83[\x14\x8aR\xc3\xe5\x9f\xd3\xebPhr\xdeY0|j\xef\x94\x0f\xd0\xaa\xa1J\xbd&\xf4\xc1\xf5`\xdbQ\xae\n\xa4j\xc0\xc6\xf6C5\x89\xe8j4\xc7>{\x88:l\x9f9v\xbd\x82\xdd#\xa0\x8e\xae\x160\xe9\xf1\xc8\xd9%J\'\xab\x99\xb1z\x07\x03L\xac\x0c\x04]\x7f%\xb5\xf8%T\xa4\xc6\xbeXi\xdc\xe8\xc9\n\x7f\xd3W\xc4\xf8\xcd\xff\xd4\xb82\rB2\xe0\x14\xfe\x13%O7\xb5PT\xb9\xdf\x1b4gr\x05\x8c\xff\xb5a~\xcb\xa7JV\xf8\xb9\xb1_M\xca\r\x1c\x0b\x06W\x82\xfc\xe5G\xde\x1d\xe7\x81\x8d\x15\x7f\xd5\x92\xc8\x80\xaa\xd7\x9fC\x05\x0b\xdc.\x8174\xbd\xac\xc5S\xd1\x9fY\xe7Jl\x9e^\x1c\xf9m1O\x9a-\x0b\x95\xb1iN\xec~\xcf\xb8V\xb0\x07Jh&\x80v\'\x89@\t\xff@6#\x97l\xd4)T\xf4 E\xd6P\xab\xc49\xcc\xbf\xe8\xd6t\x0c\xeb$\xfe\x87\xb4\xc8\x1aX\x07k\x89\xd2\xa3\xc8\xda\xae\xc3\xa6\x9a5\x9e\xfc\xa2\xff\xbcd\x02\xe7\x1b\x94a\x0e5~\x9e\xaab<\x85\xc5\xb1\xca\xb3\xd12\xbe\r\x8d\\s}\xf2\xf9|7W\x08\xc8%\x97B\x9b\xdb(rE\'\x99\x958\xe6\xbc\x05$\x99e\xb2O\xd9U\xe2\x9csdL\x05f.[\x7f)\xbd+\x0e\xf3\xfe\x0c=\xa9\xa1\x15Kfb\x1f"\xa6\xe3XRd\xed\xed\x1d\xf80j#0\xca\x03mv\x14\x15\xd5\x8f\x0f\xe7\xe35\xa9DU\xcd\xd1\xc7\xb8\xdc\xea\\$\xf78KD\xeb\xe8\xe1\xcc\xebR\x9a/\xc1E\xceL3\x08\x81\xe0\xf5\x9fu\x8e\xafGQ3\x13l\x05R=\x01\xff\xdf\xaa|XO\x8a\x9f\xb5\xa11j\xa1v=\xf3}C\xe3\x02\xfc\x90k\x06O&\x0e\xfa\x89\xa7i\xcb\x18*\x8f\x1c\x8f\xcb\xda\xf3}o\xfa\x12P*\xe3V\xeeL/\x8cE\xc4\xb3X\x01\x8f.>\x08\xe9\x04\xac4\xa3\xc0@\xe4\xc5vt\x1bv(g\xf88\x86\x8d\xce\x1b{\x0b\xd5\xe4\xe3\x08\x0b^\x8b\'!\xcbLm\xc2\x91\xb7\xd9u\x8a}$\xdd\x05\x04i\x82$S<@\xd7\xf7?n\r\x81\x17m!\xda8bC\xef\x9a\x8b\ta2\xaf\xf98g\x9cB\x1f5\x84zV\xe6`k\xae:\x04L$fL\xe53Ez\xbd\xce\x01\xc3@\xe0J\xe6\xb71\x06X\xd4\xe0\xe6\x8c\x8ev`\xe56\x95\x1f\x07\x96\xee\xf5O\xcc\x8d\xe1d\x1b,\x13\x8f\x8b\x12\x02O\x99f\x99p\xf44US\x8f\xbb\xcbX\xef\xd1\xb1\x16\xfcS\x98\x93\x97\xbc\x98I\xe9\t\x1f\x0fV\'\xb9\x11h\xb7v\x828\x97\x0b\xc4\x93O7\x9f\xd3\x13%\x1d#mA\x02;3\x00\x8b\xf9U\x11\xd4\x87{\x10>\xdc\xf5$\xba\xf3\x17ig\xdc\xb6\xa9\x14\x91\xef5\xae\x949\x12\x7f\x00ls`\xb7\x95\x9dlj\x04\xafw\xb4TM\xc9\x0e\xae\x02fu\x04\x19R\xc7\xea\\\x10\x06;\xf6(\xe6\x17ae\xdb\xc6\x87\xf1\x00\x80\xc8\xc6P\x91\x8c~MX5\xe3\xcaX\xc0/\x8e\x16\xef\xda\xf7\xfayf\xd8\x05\x93\x0e\x0b\xef\xad\x81\x96 \xb6\x9d\x19\xf1a\xc2\xd7\x88\xf8\xa9\xd0YR\x1b;(J\xc68&\xe2\r\xb3\x83X\xcb\xe6\x03<\xee\x18\x13\xc1\x00k\x1ab+g\\@A\xf0\x02ho0K\xe5\xfe\xea\xc8e\x95>\xfdC\xb4\xbb\x7f\xf0\xae\xe5\xd6d\xcf\xd0%O\x99\xfet\x8d\x99\x9a(\xa5\x81\x04\xd8{g\xb8\x99\xc6\xa4"\xe9\xda{uI\x85\x98W\xa9\x95;\xf1\xfaS\xc3{\x1a0\'\x11\xa3\xb6\x05Zz\x96n\x89\x99\xee\xe7r\xf2`D\x81\x88\xcf\x85?\xf7L\xd9\x8b\xc5~\xad\xbc\x19ilK\xab\x8d\xa2\xdd\xb6f\xcf\xa66M\xa6\x12%\x97o\\\xc5w\xcf\xa9\xc1\x8c\xb5d\xb7\t\xb0\x9e\xb2\xbf\xc1\x80\x83h\x00O\xc1\xe3s7p?JF\xea\xf6P\x83\xab<\xb4\x8c\x86V\r&\x8a\x1e\x83R~\x01\n\x1c\xbePZ+(\x8d\xaf\xf8\x83|\xf1\nj.\xe9EQd\xef\xbe\x01\xdd\x1bhn\x82\xbe\xee\xe6\x00R\x8c;\xb1\x96\xf0\x0c\x1fN2\xb4\xb2\x12\xf2L\x81\xff\x1e\xde\x02\x97A7[w\xbb\x9a\xabs\xd9\x9b_t\xe6\x9f\xa1%/\x8c\xed,\xd0T\x12\xcd\xe9;D\x1f\x06\xda\xe1x\x1bH\xe0\xefs\xfc\x80 \xe0e6\x19\xb90k\x8f\xe4\xea\xe4\xf1\x7f*\x05\x85\xec\xf2G\x99\xd8<\x0fS2\xc6\x97\x8bC[*\x16\x1d\x91|\x98\xa9\xe8\x87;\xd2KU\xf69\r\xe08\xf1A\xda\xca\xd2\xe8=\x14\x87\xd5\x15\xe6\xff\x9a\xaf\x0c\xbc%M]\nX\xa2\xb3\x8d\x11%\x1fl\xde\x99\x95@\x0f\x07:\n\xcd\xa9\xb5\xeb\xb5\x87\xa7\xc3\xef\xc5\x95S\xb2k\x8e\x15\x03{\x8cc0\x99\x98Q\xe8|\xa3\r\xdaG\xe55T\x95\x85h\xbb\x07\x05\xfa\x85\\\xb3\xce\xc5\x81(9(\x85zp\xd1\x1e\xf5\x8cXs\x8an\xef\x9a\xf2On\xc3\xd94\xce\xc4\xbcH\x03\xd2\x84\xda[\x8fW\x97\xf6\x1bc\t\x12\xb7\xc4\xb6->\x8c\x80\x03Yj\xcb\\\xd1\xfc\xfd\xf3\xd4h\x93`\xd4\xbe\x07\xe9&E&B\x19-\x1c\xe4\xc0s\xb1\x0e\xb2\xf0\x86\xc5\xe7\x9f\x90\x8f&\nL]\x0f\x05\x85\xb6\x14?\xd3\\v\xa3\xe9v\x86\\\xb0$\x08\xc1\xc3\xae\xac\x13\x8ch\xf5\xb8\x8c\xba/\x06/Y\xcesV\x8eA\xbf\xfcW\r\x1b\x86\xb1\x90\x03\xc2\xc0\xd6s\x17\x02\xe2\xcd"g\xf3F\xb9%\x0e\x8d\x90Z$\x95Ak\x173H\xb0.V#~\rh\xe8_\xbe\xe0I\xfcUQ\xc0\xf8\xc5J__J\xf0\xd0\x98\xc4y\xd8\x85\xf0\x11\xa4w\xf6\xa8\xcc\r\xd6\xe8\xca\x96*\x89\xd1^\xbf\x07\xdc\xdaw|^\xe6\xb4\xfe\x8ef\'y\xc3\xfe\xf9\xbb"\xf6(\xe8>J\xc6\x81F\x90~\xa3\xc3$\xc7\xb8~\x93E\xe5\xf6\x8aq0iL\xf8*\xc8`\x12\xe0\x81\xdf\x01\xd6\xea\x9c\xfd\x14\x08H\x05\x9d\xc4\xd2\x86\r\x8a\xf2y\x85\xc5m}\x8a\xdd\xd1pr6e\xce\x03\x93\xd0\xfcrf\xf6\xec\xb4\xea\xbe_\xfa\xa8=\x9b\x1c\xc3k`\x14\xa8\xcf\x15 R\x07\x9d|\x8d\xeb\xd32\xa4\xe8\xfd\xea\xf3`Ai\xf1\xba\x84w\x8e1P\xb2\x04\xad\xe5\x17l\x97\xa1\xa4\x98\xf9`b\x8e\x14j\xfa\xc0\xec}v\xf2\xf1Ya\xd3_\x01^\xf2\xceC_\r\xcb\xad\xc0\xe09\xf7Tf\xe6!\xcb!\xac]")\x19X\xe3\xc69)\x13\x03V\xa7c\x0e\xc3\xca\xad|\x98\xde\xa6b;\x02\xc3\xea8\x9d9H\xf0\x05)8\x16@\xe8%\xe4@5Fq.O9\r\xc3k\xa14X\xbe\x0bn\x9f\xdc\xdcb\xaf#\x9b\xdcn!')
|
4
|
-
|
1
|
+
from flask_admin.contrib import sqla
|
2
|
+
from hiddifypanel.panel.database import db
|
3
|
+
import datetime
|
4
|
+
from hiddifypanel.models import *
|
5
|
+
from flask import Markup,g
|
6
|
+
from wtforms.validators import Regexp,ValidationError
|
7
|
+
import re,uuid
|
8
|
+
from hiddifypanel import xray_api
|
9
|
+
from .adminlte import AdminLTEModelView
|
10
|
+
# from gettext import gettext as _
|
11
|
+
from flask_babelex import gettext as __
|
12
|
+
from flask_babelex import lazy_gettext as _
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
from hiddifypanel.panel import hiddify,custom_widgets
|
17
|
+
from hiddifypanel.panel.hiddify import flash
|
18
|
+
from wtforms.fields import StringField
|
19
|
+
from flask_bootstrap import SwitchField
|
20
|
+
class UserAdmin(AdminLTEModelView):
|
21
|
+
column_sortable_list=["name","current_usage_GB",'mode',"remaining_days","comment",'last_online',"uuid",'remaining_days']
|
22
|
+
column_searchable_list=[("uuid"),"name"]
|
23
|
+
column_list = ["name","UserLinks","current_usage_GB","remaining_days","comment",'last_online','mode',"uuid"]
|
24
|
+
form_extra_fields = {
|
25
|
+
'reset_days': SwitchField(_("Reset package days")),
|
26
|
+
'reset_usage': SwitchField(_("Reset package usage")),
|
27
|
+
'disable_user': SwitchField(_("Disable User"))
|
28
|
+
}
|
29
|
+
list_template = 'model/user_list.html'
|
30
|
+
form_excluded_columns=['monthly','last_online','expiry_time','last_reset_time','current_usage_GB','start_date']
|
31
|
+
page_size=50
|
32
|
+
# edit_modal=True
|
33
|
+
# create_modal=True
|
34
|
+
# column_display_pk = True
|
35
|
+
# can_export = True
|
36
|
+
# form_overrides = dict(monthly=SwitchField)
|
37
|
+
form_overrides = dict(start_date=custom_widgets.DaysLeftField)
|
38
|
+
|
39
|
+
# form_overrides = dict(expiry_time=custom_widgets.DaysLeftField,last_reset_time=custom_widgets.LastResetField)
|
40
|
+
form_widget_args={
|
41
|
+
'current_usage_GB':{'min':'0'} ,
|
42
|
+
'usage_limit_GB':{'min':'0'} ,
|
43
|
+
|
44
|
+
}
|
45
|
+
form_args = {
|
46
|
+
'uuid': {
|
47
|
+
'validators': [Regexp(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',message=__("Should be a valid uuid"))]
|
48
|
+
# 'label': 'First Name',
|
49
|
+
# 'validators': [required()]
|
50
|
+
}
|
51
|
+
# ,
|
52
|
+
# 'expiry_time':{
|
53
|
+
# "":'%Y-%m-%d'
|
54
|
+
# }
|
55
|
+
}
|
56
|
+
# column_labels={'uuid':_("user.UUID")}
|
57
|
+
# column_filters=["uuid","name","usage_limit_GB",'monthly',"current_usage_GB","start_date"]
|
58
|
+
|
59
|
+
column_labels={
|
60
|
+
"Actions":_("actions"),
|
61
|
+
"name": _("user.name"),
|
62
|
+
"UserLinks":_("user.user_links"),
|
63
|
+
"usage_limit_GB":_("user.usage_limit_GB"),
|
64
|
+
"monthly":_("Reset every month"),
|
65
|
+
"mode":_("Mode"),
|
66
|
+
"current_usage_GB":_("user.current_usage_GB"),
|
67
|
+
"start_date":_("Start Date"),
|
68
|
+
"remaining_days":_("user.expiry_time"),
|
69
|
+
"last_reset_time":_("user.last_reset_time"),
|
70
|
+
"uuid":_("user.UUID"),
|
71
|
+
"comment":_("Note"),
|
72
|
+
'last_online':_('Last Online'),
|
73
|
+
"package_days":_('Package Days'),
|
74
|
+
|
75
|
+
}
|
76
|
+
# can_set_page_size=True
|
77
|
+
|
78
|
+
def search_placeholder(self):
|
79
|
+
return f"{_('search')} {_('user.UUID')} {_('user.name')}"
|
80
|
+
# def get_column_name(self,field):
|
81
|
+
# return "x"
|
82
|
+
# return column_labels[field]
|
83
|
+
column_descriptions = dict(
|
84
|
+
# name=_'just for remembering',
|
85
|
+
# usage_limit_GB="in GB",
|
86
|
+
# current_usage_GB="in GB"
|
87
|
+
comment=_("Add some text that is only visible to you."),
|
88
|
+
mode=_("Define the user mode. Should the usage reset every month?"),
|
89
|
+
last_reset_time=_("If monthly is enabled, the usage will be reset after 30 days from this date."),
|
90
|
+
start_date=_("From when the user package will be started? Empty for start from first connection"),
|
91
|
+
package_days=_("How many days this package should be available?")
|
92
|
+
)
|
93
|
+
# column_editable_list=["usage_limit_GB","current_usage_GB","expiry_time"]
|
94
|
+
# form_extra_fields={
|
95
|
+
# 'uuid': {'label_name':"D"}
|
96
|
+
|
97
|
+
# }
|
98
|
+
|
99
|
+
# can_edit = False
|
100
|
+
# def on_model_change(self, form, model, is_created):
|
101
|
+
# model.password = generate_password_hash(model.password)
|
102
|
+
|
103
|
+
|
104
|
+
def _name_formatter(view, context, model, name):
|
105
|
+
proxy_path=hconfig(ConfigEnum.proxy_path)
|
106
|
+
if hconfig(ConfigEnum.is_parent):
|
107
|
+
from hiddifypanel.panel.commercial import ParentDomain
|
108
|
+
d=ParentDomain.query.first()
|
109
|
+
else:
|
110
|
+
d=Domain.query.filter(Domain.mode!=DomainType.fake).first()
|
111
|
+
if d:
|
112
|
+
link=f"<a target='_blank' href='https://{d.domain}/{proxy_path}/{model.uuid}/#{model.name}'>{model.name} <i class='fa-solid fa-arrow-up-right-from-square'></i></a>"
|
113
|
+
if model.is_active:
|
114
|
+
link= '<i class="fa-solid fa-circle-check text-success"></i> '+link
|
115
|
+
else:
|
116
|
+
link= '<i class="fa-solid fa-circle-xmark text-danger"></i> '+link
|
117
|
+
return Markup(link)
|
118
|
+
else:
|
119
|
+
return model.name
|
120
|
+
def _ul_formatter(view, context, model, name):
|
121
|
+
if hconfig(ConfigEnum.is_parent):
|
122
|
+
from hiddifypanel.panel.commercial import ParentDomain
|
123
|
+
domains=ParentDomain.query.all()
|
124
|
+
else:
|
125
|
+
domains=Domain.query.filter(Domain.mode!=DomainType.fake).all()
|
126
|
+
return Markup(" ".join([hiddify.get_user_link(model.uuid,d,'new',model.name) for d in domains]))
|
127
|
+
|
128
|
+
def _uuid_formatter(view, context, model, name):
|
129
|
+
return Markup(f"<span>{model.uuid}</span>")
|
130
|
+
# def _usage_formatter(view, context, model, name):
|
131
|
+
# return round(model.current_usage_GB,3)
|
132
|
+
|
133
|
+
def _usage_formatter(view, context, model, name):
|
134
|
+
u= round(model.current_usage_GB,3)
|
135
|
+
t=round(model.usage_limit_GB,3)
|
136
|
+
rate=round(u*100/(t+0.000001))
|
137
|
+
state= "danger" if u>=t else ('warning' if rate>80 else 'success')
|
138
|
+
color= "#ff7e7e" if u>=t else ('#ffc107' if rate>80 else '#9ee150')
|
139
|
+
return Markup(f"""
|
140
|
+
<div class="progress progress-lg position-relative" style="min-width: 100px;">
|
141
|
+
<div class="progress-bar progress-bar-striped" role="progressbar" style="width: {rate}%;background-color: {color};" aria-valuenow="{rate}" aria-valuemin="0" aria-valuemax="100"></div>
|
142
|
+
<span class='badge position-absolute' style="left:auto;right:auto;width: 100%;font-size:1em">{u} {_('user.home.usage.from')} {t} GB</span>
|
143
|
+
|
144
|
+
</div>
|
145
|
+
""")
|
146
|
+
|
147
|
+
def _expire_formatter(view, context, model, name):
|
148
|
+
remaining=remaining_days(model)
|
149
|
+
|
150
|
+
diff=datetime.timedelta(days=remaining)
|
151
|
+
|
152
|
+
state='success' if diff.days>7 else ('warning' if diff.days>0 else 'danger')
|
153
|
+
formated=hiddify.format_timedelta(diff)
|
154
|
+
return Markup(f"<span class='badge badge-{state}'>{'*' if not model.start_date else ''} {formated} </span>")
|
155
|
+
# return Markup(f"<span class='badge ltr badge-}'>{days}</span> "+_('days'))
|
156
|
+
|
157
|
+
def _online_formatter(view, context, model, name):
|
158
|
+
if not model.last_online:
|
159
|
+
return Markup("-")
|
160
|
+
diff=model.last_online-datetime.datetime.now()
|
161
|
+
|
162
|
+
if diff.days<-1000:
|
163
|
+
return Markup("-")
|
164
|
+
|
165
|
+
state="danger" if diff.days<-3 else ("success" if diff.days>=-1 else "warning")
|
166
|
+
return Markup(f"<span class='badge badge-{state}'>{hiddify.format_timedelta(diff,granularity='min')}</span>")
|
167
|
+
|
168
|
+
|
169
|
+
# return Markup(f"<span class='badge ltr badge-{'success' if days>7 else ('warning' if days>0 else 'danger') }'>{days}</span> "+_('days'))
|
170
|
+
|
171
|
+
column_formatters = {
|
172
|
+
'name': _name_formatter,
|
173
|
+
'UserLinks': _ul_formatter,
|
174
|
+
'uuid': _uuid_formatter,
|
175
|
+
'current_usage_GB': _usage_formatter,
|
176
|
+
"remaining_days":_expire_formatter,
|
177
|
+
'last_online':_online_formatter
|
178
|
+
}
|
179
|
+
def on_model_delete(self, model):
|
180
|
+
if len(User.query.all())<=1:
|
181
|
+
raise ValidationError(f"at least one user should exist")
|
182
|
+
xray_api.remove_client(model.uuid)
|
183
|
+
# hiddify.flash_config_success()
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
# def is_accessible(self):
|
188
|
+
# return g.is_admin
|
189
|
+
def on_form_prefill(self, form, id=None):
|
190
|
+
print("================",form._obj.start_date)
|
191
|
+
if form._obj.start_date is None:
|
192
|
+
msg= _("Package not started yet.")
|
193
|
+
# form.reset['class']="d-none"
|
194
|
+
delattr(form,'reset_days')
|
195
|
+
delattr(form,'reset_usage')
|
196
|
+
# delattr(form,'disable_user')
|
197
|
+
else:
|
198
|
+
remaining=remaining_days(form._obj)
|
199
|
+
msg= _("Remaining: ")+ hiddify.format_timedelta(datetime.timedelta(days=remaining))
|
200
|
+
form.reset_days.label.text+=f" ({msg})"
|
201
|
+
usr_usage=f" ({_('user.home.usage.title')} {round(form._obj.current_usage_GB,3)}GB)"
|
202
|
+
form.reset_usage.label.text+=usr_usage
|
203
|
+
form.usage_limit_GB.label.text+=usr_usage
|
204
|
+
|
205
|
+
if form._obj.mode==UserMode.disable:
|
206
|
+
delattr(form,'disable_user')
|
207
|
+
# form.disable_user.data=form._obj.mode==UserMode.disable
|
208
|
+
form.package_days.label.text+=f" ({msg})"
|
209
|
+
|
210
|
+
def get_edit_form(self):
|
211
|
+
form = super().get_edit_form()
|
212
|
+
# print(form.__dict__)
|
213
|
+
# user=User.query.filter(User.uuid==form.uuid).first()
|
214
|
+
# if user and user.start_date:
|
215
|
+
# form.reset = SwitchField("Reset")
|
216
|
+
return form
|
217
|
+
def on_model_change(self, form, model, is_created):
|
218
|
+
if len(User.query.all())%4==0:
|
219
|
+
flash(('<div id="show-modal-donation"></div>'), ' d-none')
|
220
|
+
if not re.match("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", model.uuid):
|
221
|
+
raise ValidationError('Invalid UUID e.g.,'+ str(uuid.uuid4()))
|
222
|
+
|
223
|
+
if form.reset_usage.data:
|
224
|
+
model.current_usage_GB=0
|
225
|
+
if form.disable_user.data:
|
226
|
+
model.mode=UserMode.disable
|
227
|
+
if form.reset_days.data:
|
228
|
+
model.start_date=None
|
229
|
+
model.package_days=min(model.package_days,10000)
|
230
|
+
old_user=user_by_id(model.id)
|
231
|
+
if old_user and old_user.uuid!=model.uuid:
|
232
|
+
xray_api.remove_client(old_user.uuid)
|
233
|
+
|
234
|
+
# model.expiry_time=datetime.date.today()+datetime.timedelta(days=model.expiry_time)
|
235
|
+
|
236
|
+
|
237
|
+
# if model.current_usage_GB < model.usage_limit_GB:
|
238
|
+
# xray_api.add_client(model.uuid)
|
239
|
+
# else:
|
240
|
+
# xray_api.remove_client(model.uuid)
|
241
|
+
# hiddify.flash_config_success()
|
242
|
+
# def is_accessible(self):
|
243
|
+
# return is_valid()
|
244
|
+
|
245
|
+
def after_model_change(self,form, model, is_created):
|
246
|
+
hiddify.quick_apply_users()
|
247
|
+
def after_model_delete(self,model):
|
248
|
+
xray_api.remove_client(model.uuid)
|
249
|
+
hiddify.quick_apply_users()
|
250
|
+
|
251
|
+
def get_list(self, page, sort_column, sort_desc, search, filters,*args, **kwargs):
|
252
|
+
res=None
|
253
|
+
print('aaa',args, kwargs)
|
254
|
+
if 'remaining_days' == sort_column:
|
255
|
+
query = self.session.query(self.model)
|
256
|
+
count = query.count()
|
257
|
+
data = query.all()
|
258
|
+
data=sorted(data,key=lambda p: p.remaining_days,reverse=sort_desc)
|
259
|
+
res=count,data
|
260
|
+
else:
|
261
|
+
res=super().get_list(page, sort_column, sort_desc, search, filters,*args, **kwargs)
|
262
|
+
return res
|
263
|
+
|
264
|
+
# Override the default get_list method to use the custom sort function
|
265
|
+
query = self.session.query(self.model)
|
266
|
+
if self._sortable_columns:
|
267
|
+
print("sor",self._sortable_columns['remaining_days'])
|
268
|
+
for column, direction in self._get_default_order():
|
269
|
+
# if column == 'remaining_days':
|
270
|
+
# # Use the custom sort function for 'remaining_days'
|
271
|
+
# query = query.order_by(self.model.remaining_days.asc() if direction == 'asc' else self.model.remaining_days.desc())
|
272
|
+
# else:
|
273
|
+
# Use the default sort function for other columns
|
274
|
+
query = query.order_by(getattr(self.model, column).asc() if direction == 'asc' else getattr(self.model, column).desc())
|
275
|
+
count = query.count()
|
276
|
+
data = query.all()
|
277
|
+
return count, data#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
278
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
@@ -1,5 +1,83 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
|
4
|
-
|
1
|
+
from flask import Blueprint,url_for,request,jsonify,g,redirect
|
2
|
+
from flask_admin import Admin
|
3
|
+
from hiddifypanel import Events
|
4
|
+
# from flask_sockets import Sockets
|
5
|
+
|
6
|
+
from .SettingAdmin import SettingAdmin
|
7
|
+
from .DomainAdmin import DomainAdmin
|
8
|
+
from .ConfigAdmin import ConfigAdmin
|
9
|
+
from .commercial_info import CommercialInfo
|
10
|
+
from .ProxyAdmin import ProxyAdmin
|
11
|
+
|
12
|
+
from .Actions import Actions
|
13
|
+
from .Backup import Backup
|
14
|
+
from .QuickSetup import QuickSetup
|
15
|
+
from hiddifypanel.models import StrConfig,ConfigEnum
|
16
|
+
# from .resources import ProductItemResource, ProductResource
|
17
|
+
from hiddifypanel.panel.database import db
|
18
|
+
from hiddifypanel.models import *
|
19
|
+
from .Dashboard import Dashboard
|
20
|
+
|
21
|
+
from flask_admin.menu import MenuLink
|
22
|
+
|
23
|
+
import uuid
|
24
|
+
from flask_adminlte3 import AdminLTE3
|
25
|
+
flask_bp = Blueprint("flask", __name__, url_prefix=f"/<proxy_path>/<user_secret>/",template_folder="templates")
|
26
|
+
admin_bp = Blueprint("admin", __name__, url_prefix=f"/<proxy_path>/<user_secret>/admin/",template_folder="templates")
|
27
|
+
flaskadmin = Admin(endpoint="admin",base_template='flaskadmin-layout.html')
|
28
|
+
# from extensions import socketio
|
29
|
+
|
30
|
+
|
31
|
+
def init_app(app):
|
32
|
+
|
33
|
+
from .UserAdmin import UserAdmin
|
34
|
+
# admin_secret=StrConfig.query.filter(StrConfig.key==ConfigEnum.admin_secret).first()
|
35
|
+
#
|
36
|
+
# return
|
37
|
+
# admin = Admin(endpoint="admin",index_view=Dashboard(),base_template='lte-master.html',static_url_path="/static/")
|
38
|
+
flaskadmin.template_mode = "bootstrap4"
|
39
|
+
flaskadmin.init_app(flask_bp)
|
40
|
+
adminlte=AdminLTE3()
|
41
|
+
adminlte.init_app(app)
|
42
|
+
|
43
|
+
Events.admin_prehook.notify(flaskadmin=flaskadmin,admin_bp=admin_bp)
|
44
|
+
|
45
|
+
|
46
|
+
@app.route('/<proxy_path>/<user_secret>/admin')
|
47
|
+
def auto_route():
|
48
|
+
return redirect(request.url.replace("http://","https://")+"/")
|
49
|
+
|
50
|
+
|
51
|
+
# flaskadmin.init_app(app)
|
52
|
+
|
53
|
+
flaskadmin.add_view(UserAdmin(User, db.session))
|
54
|
+
flaskadmin.add_view(DomainAdmin(Domain, db.session))
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
SettingAdmin.register(admin_bp)
|
63
|
+
ProxyAdmin.register(admin_bp)
|
64
|
+
Actions.register(admin_bp)
|
65
|
+
CommercialInfo.register(admin_bp)
|
66
|
+
|
67
|
+
QuickSetup.register(admin_bp)
|
68
|
+
Backup.register(admin_bp)
|
69
|
+
Dashboard.register(admin_bp,route_base="/")
|
70
|
+
|
71
|
+
|
72
|
+
# admin_bp.add_url_rule('/admin/quicksetup/',endpoint="quicksetup",view_func=QuickSetup.index,methods=["GET"])
|
73
|
+
# admin_bp.add_url_rule('/admin/quicksetup/',endpoint="quicksetup-save", view_func=QuickSetup.save,methods=["POST"])
|
74
|
+
|
75
|
+
|
76
|
+
app.add_url_rule("/<proxy_path>/<user_secret>/admin/static/<filename>/",endpoint="admin.static")# fix bug in admin with blueprint
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
flask_bp.debug=True
|
81
|
+
app.register_blueprint(admin_bp)
|
82
|
+
app.register_blueprint(flask_bp)#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
83
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
@@ -1,5 +1,14 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
|
4
|
-
|
1
|
+
from flask_admin.contrib.sqla import ModelView
|
2
|
+
from flask_admin.form import SecureForm
|
3
|
+
class AdminLTEModelView(ModelView):
|
4
|
+
list_template = 'hiddify-flask-admin/list.html'
|
5
|
+
create_template = 'flask-admin/model/create.html'
|
6
|
+
edit_template = 'flask-admin/model/edit.html'
|
7
|
+
details_template = 'flask-admin/model/details.html'
|
8
|
+
|
9
|
+
create_modal_template = 'flask-admin/model/modals/create.html'
|
10
|
+
edit_modal_template = 'flask-admin/model/modals/edit.html'
|
11
|
+
details_modal_template = 'flask-admin/model/modals/details.html'
|
12
|
+
|
13
|
+
# form_base_class = SecureForm#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
14
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
@@ -1,5 +1,25 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
import pprint
|
3
|
+
from flask_babelex import gettext as _
|
4
|
+
import pathlib
|
5
|
+
from hiddifypanel.models import *
|
6
|
+
|
7
|
+
from datetime import datetime,timedelta,date
|
8
|
+
import os,sys
|
9
|
+
import json
|
10
|
+
import urllib.request
|
11
|
+
import subprocess
|
12
|
+
import re
|
13
|
+
from hiddifypanel.panel import hiddify,usage
|
14
|
+
from hiddifypanel.panel import hiddify_api
|
15
|
+
from flask import current_app,render_template,request,Response,Markup,url_for
|
16
|
+
from hiddifypanel.panel.hiddify import flash
|
17
|
+
|
18
|
+
from flask_classful import FlaskView,route
|
19
|
+
|
20
|
+
class CommercialInfo(FlaskView):
|
21
|
+
|
22
|
+
def index(self):
|
23
|
+
return render_template('commercial_info.html')
|
4
24
|
#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
25
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
@@ -1,5 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
|
2
|
+
|
3
|
+
# from flask_socketio import SocketIO
|
4
|
+
|
5
|
+
# socketio = SocketIO()
|
6
|
+
|
7
|
+
|
8
|
+
# def __init__(app):
|
9
|
+
# socketio.__init__(app)
|
4
10
|
#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
11
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
hiddifypanel/panel/admin_2.py
CHANGED
@@ -1,5 +1,35 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
|
1
|
+
from flask_admin import Admin
|
2
|
+
from flask_admin.base import AdminIndexView
|
3
|
+
from flask_admin.contrib import sqla
|
4
|
+
# from flask_simplelogin import login_required
|
5
|
+
from werkzeug.security import generate_password_hash
|
6
|
+
|
7
|
+
from hiddifypanel.panel.database import db
|
8
|
+
from hiddifypanel.models import User
|
9
|
+
|
10
|
+
# Proteck admin with login / Monkey Patch
|
11
|
+
# AdminIndexView._handle_view = login_required(AdminIndexView._handle_view)
|
12
|
+
# sqla.ModelView._handle_view = login_requiredsqla.ModelView._handle_view)
|
13
|
+
admin = Admin()
|
14
|
+
|
15
|
+
|
16
|
+
class UserAdmin(sqla.ModelView):
|
17
|
+
column_list = ["username"]
|
18
|
+
can_edit = False
|
19
|
+
|
20
|
+
def on_model_change(self, form, model, is_created):
|
21
|
+
model.password = generate_password_hash(model.password)
|
22
|
+
|
23
|
+
|
24
|
+
def init_app(app):
|
25
|
+
# admin.name = app.config.HIDDIFY_CONFIG_PATH
|
26
|
+
admin.template_mode = app.config.FLASK_ADMIN_TEMPLATE_MODE
|
27
|
+
admin.init_app(app)
|
28
|
+
|
29
|
+
# Add admin page for Product
|
30
|
+
# admin.add_view(sqla.ModelView(Product, db.session))
|
31
|
+
|
32
|
+
# Add admin page for User
|
33
|
+
admin.add_view(UserAdmin(User, db.session))
|
4
34
|
#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
35
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|
hiddifypanel/panel/asset.py
CHANGED
@@ -1,5 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
from flask import g, send_from_directory, url_for
|
2
|
+
|
3
|
+
|
4
|
+
def send_static(path):
|
5
|
+
return send_from_directory('static/assets', path)
|
6
|
+
|
7
|
+
|
8
|
+
def init_app(app):
|
9
|
+
@app.url_defaults
|
10
|
+
def add_asset(endpoint, values):
|
11
|
+
def get_asset(path):
|
12
|
+
return url_for('asset', proxy_path=g.proxy_path, path=path)
|
13
|
+
g.asset_url = get_asset
|
14
|
+
|
15
|
+
app.add_url_rule('/<proxy_path>/asset/<path:path>',
|
16
|
+
'asset', view_func=send_static)
|
17
|
+
pass
|
4
18
|
#واقعا برای 5 دلار میخوای کرک میکنی؟ حاجی ارزش وقت خودت بیشتره
|
5
19
|
#Email hiddify@gmail.com for free permium version. Do not crack this cheap product
|