hiddifypanel 10.70.0.dev8__py3-none-any.whl → 10.70.2__py3-none-any.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.
Files changed (34) hide show
  1. hiddifypanel/VERSION +1 -1
  2. hiddifypanel/VERSION.py +2 -2
  3. hiddifypanel/drivers/singbox_api.py +3 -2
  4. hiddifypanel/drivers/ssh_liberty_bridge_api.py +2 -1
  5. hiddifypanel/drivers/user_driver.py +5 -0
  6. hiddifypanel/drivers/xray_api.py +5 -4
  7. hiddifypanel/hutils/github_issue.py +9 -7
  8. hiddifypanel/hutils/proxy/clash.py +50 -24
  9. hiddifypanel/panel/commercial/restapi/v2/user/configs_api.py +2 -2
  10. hiddifypanel/panel/common.py +2 -0
  11. hiddifypanel/panel/init_db.py +14 -14
  12. hiddifypanel/panel/usage.py +8 -4
  13. hiddifypanel/panel/user/user.py +3 -0
  14. hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
  15. hiddifypanel/translations/en/LC_MESSAGES/messages.po +12 -6
  16. hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
  17. hiddifypanel/translations/fa/LC_MESSAGES/messages.po +10 -4
  18. hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
  19. hiddifypanel/translations/pt/LC_MESSAGES/messages.po +47 -17
  20. hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
  21. hiddifypanel/translations/ru/LC_MESSAGES/messages.po +21 -13
  22. hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
  23. hiddifypanel/translations/zh/LC_MESSAGES/messages.po +21 -21
  24. hiddifypanel/translations.i18n/en.json +6 -6
  25. hiddifypanel/translations.i18n/fa.json +7 -7
  26. hiddifypanel/translations.i18n/pt.json +26 -26
  27. hiddifypanel/translations.i18n/ru.json +15 -15
  28. hiddifypanel/translations.i18n/zh.json +21 -21
  29. {hiddifypanel-10.70.0.dev8.dist-info → hiddifypanel-10.70.2.dist-info}/METADATA +1 -1
  30. {hiddifypanel-10.70.0.dev8.dist-info → hiddifypanel-10.70.2.dist-info}/RECORD +34 -34
  31. {hiddifypanel-10.70.0.dev8.dist-info → hiddifypanel-10.70.2.dist-info}/WHEEL +1 -1
  32. {hiddifypanel-10.70.0.dev8.dist-info → hiddifypanel-10.70.2.dist-info}/LICENSE.md +0 -0
  33. {hiddifypanel-10.70.0.dev8.dist-info → hiddifypanel-10.70.2.dist-info}/entry_points.txt +0 -0
  34. {hiddifypanel-10.70.0.dev8.dist-info → hiddifypanel-10.70.2.dist-info}/top_level.txt +0 -0
hiddifypanel/VERSION CHANGED
@@ -1 +1 @@
1
- 10.70.0.dev8
1
+ 10.70.2
hiddifypanel/VERSION.py CHANGED
@@ -1,3 +1,3 @@
1
- __version__='10.70.0.dev8'
1
+ __version__='10.70.2'
2
2
  from datetime import datetime
3
- __release_date__= datetime.strptime('2024-07-29','%Y-%m-%d')
3
+ __release_date__= datetime.strptime('2024-07-30','%Y-%m-%d')
@@ -5,6 +5,7 @@ from flask import current_app
5
5
  import json
6
6
  from collections import defaultdict
7
7
  from hiddifypanel.cache import cache
8
+ from loguru import logger
8
9
 
9
10
 
10
11
  class SingboxApi(DriverABS):
@@ -24,7 +25,7 @@ class SingboxApi(DriverABS):
24
25
  try:
25
26
  xray_client = self.get_singbox_client()
26
27
  inbounds = [inb.name.split(">>>")[1] for inb in xray_client.stats_query('inbound')]
27
- print(f"Success in get inbound tags {inbounds}")
28
+ # print(f"Success in get inbound tags {inbounds}")
28
29
  except Exception as e:
29
30
  print(f"error in get inbound tags {e}")
30
31
  inbounds = []
@@ -63,5 +64,5 @@ class SingboxApi(DriverABS):
63
64
  else:
64
65
  res = d + u
65
66
  if res:
66
- print(f"singbox {uuid} d={d} u={u} sum={res}")
67
+ logger.debug(f"singbox {uuid} d={d} u={u} sum={res}")
67
68
  return res
@@ -4,6 +4,7 @@ import redis
4
4
 
5
5
  USERS_SET = "ssh-server:users"
6
6
  USERS_USAGE = "ssh-server:users-usage"
7
+ from loguru import logger
7
8
 
8
9
 
9
10
  class SSHLibertyBridgeApi(DriverABS):
@@ -59,5 +60,5 @@ class SSHLibertyBridgeApi(DriverABS):
59
60
  redis_client.hincrby(USERS_USAGE, client_uuid, -value)
60
61
  redis_client.save()
61
62
  if value:
62
- print(f'ssh usage {client_uuid} {value}')
63
+ logger.debug(f'ssh usage {client_uuid} {value}')
63
64
  return value
@@ -5,6 +5,7 @@ from .wireguard_api import WireguardApi
5
5
  from hiddifypanel.models import *
6
6
  from hiddifypanel.panel import hiddify
7
7
  from collections import defaultdict
8
+ from loguru import logger
8
9
 
9
10
  drivers = [XrayApi(), SingboxApi(), SSHLibertyBridgeApi(), WireguardApi()]
10
11
 
@@ -27,6 +28,7 @@ def get_users_usage(reset=True):
27
28
  except Exception as e:
28
29
  print(driver)
29
30
  hiddify.error(f'ERROR! {driver.__class__.__name__} has error in update usage {e}')
31
+ logger.exception(f'ERROR! {driver.__class__.__name__} has error in update usage {e}')
30
32
  return res
31
33
 
32
34
 
@@ -45,6 +47,7 @@ def get_enabled_users():
45
47
  except Exception as e:
46
48
  print(driver)
47
49
  hiddify.error(f'ERROR! {driver.__class__.__name__} has error in get_enabled users {e}')
50
+ logger.exception(f'ERROR! {driver.__class__.__name__} has error in get_enabled users {e}')
48
51
  # print(d, total)
49
52
  res = defaultdict(bool)
50
53
  for u, v in d.items():
@@ -59,6 +62,7 @@ def add_client(user: User):
59
62
  driver.add_client(user)
60
63
  except Exception as e:
61
64
  hiddify.error(f'ERROR! {driver.__class__.__name__} has error {e} in add client for user={user.uuid} {e}')
65
+ logger.exception(f'ERROR! {driver.__class__.__name__} has error {e} in add client for user={user.uuid} {e}')
62
66
 
63
67
 
64
68
  def remove_client(user: User):
@@ -67,3 +71,4 @@ def remove_client(user: User):
67
71
  driver.remove_client(user)
68
72
  except Exception as e:
69
73
  hiddify.error(f'ERROR! {driver.__class__.__name__} has error {e} in remove client for user={user.uuid}')
74
+ logger.exception(f'ERROR! {driver.__class__.__name__} has error {e} in remove client for user={user.uuid}')
@@ -3,6 +3,7 @@ from hiddifypanel.models import *
3
3
  from .abstract_driver import DriverABS
4
4
  from collections import defaultdict
5
5
  from hiddifypanel.cache import cache
6
+ from loguru import logger
6
7
 
7
8
 
8
9
  class XrayApi(DriverABS):
@@ -65,7 +66,7 @@ class XrayApi(DriverABS):
65
66
  try:
66
67
  xray_client = self.get_xray_client()
67
68
  inbounds = {inb.name.split(">>>")[1] for inb in xray_client.stats_query('inbound')}
68
- print(f"Success in get inbound tags {inbounds}")
69
+ # print(f"Success in get inbound tags {inbounds}")
69
70
  except Exception as e:
70
71
  print(f"error in get inbound tags {e}")
71
72
  inbounds = {}
@@ -130,10 +131,10 @@ class XrayApi(DriverABS):
130
131
  try:
131
132
  xray_client.remove_client(t, f'{uuid}@hiddify.com')
132
133
  if dolog:
133
- print(f"Success remove {uuid} {t}")
134
+ logger.info(f"Success remove {uuid} {t}")
134
135
  except Exception as e:
135
136
  if dolog:
136
- print(f"error in remove {uuid} {t} {e}")
137
+ logger.info(f"error in remove {uuid} {t} {e}")
137
138
  pass
138
139
 
139
140
  def get_all_usage(self, users):
@@ -164,5 +165,5 @@ class XrayApi(DriverABS):
164
165
  else:
165
166
  res = d + u
166
167
  if res:
167
- print(f"Xray usage {uuid} d={d} u={u} sum={res}")
168
+ logger.debug(f"Xray usage {uuid} d={d} u={u} sum={res}")
168
169
  return res
@@ -137,12 +137,13 @@ def __github_issue_details() -> dict:
137
137
  def __remove_sensetive_data_from_github_issue_link(issue_link: str):
138
138
  from hiddifypanel.auth import current_account
139
139
  if current_account.uuid:
140
- issue_link.replace(f'{current_account.uuid}', '*******************')
140
+ issue_link = issue_link.replace(f'{current_account.uuid}', '*******************')
141
141
 
142
- issue_link.replace(request.host, '**********')
143
- issue_link.replace(hconfig(ConfigEnum.proxy_path), '**********')
144
- issue_link.replace(hconfig(ConfigEnum.proxy_path_admin), '**********')
145
- issue_link.replace(hconfig(ConfigEnum.proxy_path_client), '**********')
142
+ issue_link = issue_link.replace(request.host, '**********')
143
+ issue_link = issue_link.replace(hconfig(ConfigEnum.proxy_path), '**********')
144
+ issue_link = issue_link.replace(hconfig(ConfigEnum.proxy_path_admin), '**********')
145
+ issue_link = issue_link.replace(hconfig(ConfigEnum.proxy_path_client), '**********')
146
+ return issue_link
146
147
 
147
148
 
148
149
  def __remove_unrelated_traceback_details(stacktrace: str) -> str:
@@ -181,10 +182,11 @@ def generate_github_issue_link_for_500_error(error, traceback: str, remove_sense
181
182
  issue_body = render_template('github_issue_body.j2', issue_details=issue_details, error=error, traceback=traceback)
182
183
 
183
184
  # Create github issue link
184
- issue_link = __generate_github_issue_link(f"Internal server error: {error.name if hasattr(error,'name') and error.name != None and error.name else 'Unknown'}", issue_body)
185
+ issue_link = __generate_github_issue_link(
186
+ f"Internal server error: {error.name if hasattr(error,'name') and error.name != None and error.name else 'Unknown'}", issue_body)
185
187
 
186
188
  if remove_sensetive_data:
187
- __remove_sensetive_data_from_github_issue_link(issue_link)
189
+ issue_link = __remove_sensetive_data_from_github_issue_link(issue_link)
188
190
 
189
191
  return issue_link
190
192
 
@@ -1,6 +1,7 @@
1
1
  import yaml
2
2
  from hiddifypanel.models import ProxyCDN, ProxyL3, ProxyProto, ProxyTransport, Domain
3
3
  from hiddifypanel import hutils
4
+ # https://wiki.metacubex.one/en/
4
5
 
5
6
 
6
7
  def get_clash_config_names(meta_or_normal, domains: list[Domain]):
@@ -32,11 +33,15 @@ def to_clash(proxy, meta_or_normal):
32
33
 
33
34
  if proxy['l3'] in ["kcp", ProxyL3.h3_quic]:
34
35
  return {'name': name, 'msg': f"clash does not support {proxy['l3']}", 'type': 'debug'}
35
- if proxy['proto'] in ["ssh", "wireguard", "tuic", "hysteria"]:
36
- return {'name': name, 'msg': f"clash does not support {proxy['proto']}", 'type': 'debug'}
37
- if proxy.get('flow'):
38
- return {'name': name, 'msg': "xtls not supported in clash", 'type': 'debug'}
36
+ if proxy['transport'] in [ProxyTransport.splithttp, ProxyTransport.httpupgrade]:
37
+ return {'name': name, 'msg': f"clash does not support {proxy['transport']}", 'type': 'debug'}
38
+ # if proxy['proto'] in [Proxy.shado]:
39
+
39
40
  if meta_or_normal == "normal":
41
+ if proxy.get('flow'):
42
+ return {'name': name, 'msg': "xtls not supported in clash", 'type': 'debug'}
43
+ if proxy['proto'] in [ProxyProto.ssh, ProxyProto.wireguard, ProxyProto.tuic, ProxyProto.hysteria2]:
44
+ return {'name': name, 'msg': f"clash does not support {proxy['proto']}", 'type': 'debug'}
40
45
  if proxy['proto'] in ["vless", 'tuic', 'hysteria2']:
41
46
  return {'name': name, 'msg': f"{proxy['proto']} not supported in clash", 'type': 'debug'}
42
47
  if proxy['transport'] in ["shadowtls", "splithttp"]:
@@ -49,7 +54,31 @@ def to_clash(proxy, meta_or_normal):
49
54
  base["type"] = str(proxy["proto"])
50
55
  base["server"] = proxy["server"]
51
56
  base["port"] = proxy["port"]
52
- base['alpn'] = proxy['alpn'].split(',')
57
+ if proxy["proto"] == "ssh":
58
+ base["username"] = proxy["uuid"]
59
+ base["private-key"] = proxy['private_key']
60
+ base["host-key"] = proxy.get('host_key', [])
61
+ return base
62
+ base["udp"] = True
63
+ if proxy["proto"] == ProxyProto.wireguard:
64
+ base["private-key"] = proxy["wg_pk"]
65
+ base["ip"] = f'{proxy["wg_ipv4"]}/32'
66
+ # base["ipv6"]
67
+ base["public-key"] = proxy["wg_server_pub"]
68
+ base["pre-shared-key"] = proxy["wg_psk"]
69
+ # base["allowed-ips"]
70
+ return base
71
+ if proxy["proto"] == ProxyProto.tuic:
72
+ # base['congestion_control'] = "cubic"
73
+ base['udp-relay-mode'] = 'native'
74
+ base['reduce-rtt'] = True
75
+ base["skip-cert-verify"] = proxy['allow_insecure']
76
+ base['sni'] = proxy['sni']
77
+ # base['heartbeat'] = "10s"
78
+ base['password'] = proxy['uuid']
79
+ base['uuid'] = proxy['uuid']
80
+ return base
81
+
53
82
  if proxy["proto"] == "ssr":
54
83
  base["cipher"] = proxy["cipher"]
55
84
  base["password"] = proxy["uuid"]
@@ -58,16 +87,6 @@ def to_clash(proxy, meta_or_normal):
58
87
  base["protocol"] = proxy["ssr-protocol"]
59
88
  base["obfs-param"] = proxy["fakedomain"]
60
89
  return base
61
- elif proxy["proto"] == "tuic":
62
- base["uuid"] = proxy["uuid"]
63
- base["password"] = proxy["uuid"]
64
- base["disable-sni"] = proxy['allow_insecure']
65
- base["reduce-rtt"] = True
66
- base["request-timeout"] = 8000
67
- base["udp-relay-mode"] = 'native'
68
- base["congestion-controller"] = 'cubic'
69
- base['sni'] = proxy['sni']
70
- return base
71
90
  elif proxy["proto"] in ["ss", "v2ray"]:
72
91
  base["cipher"] = proxy["cipher"]
73
92
  base["password"] = proxy["password"]
@@ -82,7 +101,7 @@ def to_clash(proxy, meta_or_normal):
82
101
  base["plugin"] = "shadow-tls"
83
102
  base["plugin-opts"] = {
84
103
  "host": proxy["fakedomain"],
85
- "password": proxy["proxy_path"],
104
+ "password": proxy["shared_secret"],
86
105
  "version": 3 # support 1/2/3
87
106
 
88
107
  }
@@ -98,16 +117,26 @@ def to_clash(proxy, meta_or_normal):
98
117
  "path": proxy["path"]
99
118
  }
100
119
  return base
101
- elif proxy["proto"] == "trojan":
120
+ base['alpn'] = proxy['alpn'].split(',')
121
+ base["skip-cert-verify"] = proxy["mode"] == "Fake"
122
+ if meta_or_normal == "meta" and proxy.get('fingerprint'):
123
+ base['client-fingerprint'] = proxy['fingerprint']
124
+
125
+ if proxy["proto"] == "trojan":
102
126
  base["password"] = proxy["uuid"]
103
127
  base["sni"] = proxy["sni"]
104
-
128
+ elif proxy["proto"] == "hysteria2":
129
+ base["password"] = proxy["uuid"]
130
+ base["obfs"] = "salamander"
131
+ base["obfs-password"] = proxy.get('hysteria_obfs_password')
132
+ return base
105
133
  else:
106
134
  base["uuid"] = proxy["uuid"]
107
135
  base["servername"] = proxy["sni"]
108
136
  base["tls"] = "tls" in proxy["l3"] or "reality" in proxy["l3"]
109
- if meta_or_normal == "meta":
110
- base['client-fingerprint'] = proxy['fingerprint']
137
+ if proxy["proto"] in ["vless", "vmess"]:
138
+ base["packet-encoding"] = "xudp"
139
+
111
140
  if proxy.get('flow'):
112
141
  base["flow"] = proxy['flow']
113
142
  # base["flow-show"] = True
@@ -115,11 +144,8 @@ def to_clash(proxy, meta_or_normal):
115
144
  if proxy["proto"] == "vmess":
116
145
  base["alterId"] = 0
117
146
  base["cipher"] = proxy["cipher"]
118
- base["udp"] = True
119
-
120
- base["skip-cert-verify"] = proxy["mode"] == "Fake"
121
147
 
122
- base["network"] = proxy["transport"]
148
+ base["network"] = str(proxy["transport"])
123
149
 
124
150
  if base["network"] == "ws":
125
151
  base["ws-opts"] = {
@@ -94,7 +94,7 @@ class AllConfigsAPI(MethodView):
94
94
  create_item(
95
95
  "Clash Meta", "ALL", "", "", "", "",
96
96
  # f"clashmeta://install-config?url={base_url}clash/meta/all.yml&name=mnormal_{c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}-{c['mode']}&asn={c['asn']}&mode={c['mode']}"
97
- f"clash://install-config?url={base_url}clashmeta/?asn={c['asn']}#{config_name}"
97
+ f"{base_url}clashmeta/?asn={c['asn']}#{config_name}"
98
98
  )
99
99
  )
100
100
 
@@ -104,7 +104,7 @@ class AllConfigsAPI(MethodView):
104
104
  create_item(
105
105
  "Clash", "ALL", "Except VLess", "", "", "",
106
106
  # f"clash://install-config?url={base_url}clash/all.yml&name=new_normal_{c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}-{c['mode']}&asn={c['asn']}&mode={c['mode']}"
107
- f"clash://install-config?url={base_url}clash/?asn={c['asn']}#{config_name}"
107
+ f"{base_url}clash/?asn={c['asn']}#{config_name}"
108
108
  )
109
109
  )
110
110
 
@@ -148,6 +148,8 @@ def init_app(app: APIFlask):
148
148
 
149
149
  @app.before_request
150
150
  def base_middleware():
151
+ if "generate_204" in request.path:
152
+ return "", 204
151
153
  if request.endpoint == 'static' or request.endpoint == "videos":
152
154
  return
153
155
 
@@ -17,20 +17,7 @@ from loguru import logger
17
17
  MAX_DB_VERSION = 100
18
18
 
19
19
 
20
- def _v94(child_id):
21
- set_hconfig(ConfigEnum.wireguard_noise_trick, "0-0")
22
-
23
-
24
- def _v93(child_id):
25
- set_hconfig(ConfigEnum.quic_enable, True)
26
- set_hconfig(ConfigEnum.splithttp_enable, True)
27
-
28
-
29
- def _v92(child_id):
30
- db.session.bulk_save_objects(get_proxy_rows_v1())
31
-
32
-
33
- def _v90(child_id):
20
+ def _v95(child_id):
34
21
  result = (
35
22
  db.session.query(
36
23
  DailyUsage.child_id,
@@ -67,6 +54,19 @@ def _v90(child_id):
67
54
  db.session.commit()
68
55
 
69
56
 
57
+ def _v94(child_id):
58
+ set_hconfig(ConfigEnum.wireguard_noise_trick, "0-0")
59
+
60
+
61
+ def _v93(child_id):
62
+ set_hconfig(ConfigEnum.quic_enable, True)
63
+ set_hconfig(ConfigEnum.splithttp_enable, True)
64
+
65
+
66
+ def _v92(child_id):
67
+ db.session.bulk_save_objects(get_proxy_rows_v1())
68
+
69
+
70
70
  def _v89(child_id):
71
71
  set_hconfig(ConfigEnum.path_splithttp, hutils.random.get_random_string(7, 15))
72
72
  set_hconfig(ConfigEnum.splithttp_enable, False)
@@ -8,7 +8,7 @@ from hiddifypanel.models import *
8
8
  from hiddifypanel.panel import hiddify
9
9
  from hiddifypanel.database import db
10
10
  from hiddifypanel import cache, hutils
11
-
11
+ from loguru import logger
12
12
  to_gig_d = 1024**3
13
13
 
14
14
 
@@ -23,6 +23,7 @@ def update_local_usage():
23
23
  return _add_users_usage(res, child_id=0)
24
24
  except Exception as e:
25
25
  cache.redis_client.set(lock_key, "locked", nx=False, ex=60)
26
+ logger.exception("Exception in update usage")
26
27
  raise
27
28
  return {"msg": f"Exception in update usage: {e}"}
28
29
 
@@ -46,9 +47,10 @@ def _reset_priodic_usage():
46
47
  # reset as soon as possible in the day
47
48
  if datetime.datetime.now().hour > 5 and current_time - last_usage_check < 60 * 60 * 24:
48
49
  return
49
-
50
+ logger.debug("reseting user usage if needed")
50
51
  for user in User.query.filter(User.mode != UserMode.no_reset).all():
51
52
  if user.user_should_reset():
53
+ logger.info(f"reseting user usage for {user.uuid}")
52
54
  user.reset_usage(commit=False)
53
55
  set_hconfig(ConfigEnum.last_priodic_usage_check, current_time)
54
56
 
@@ -67,6 +69,7 @@ def _add_users_usage(users_usage_data: Dict[User, Dict], child_id, sync=False):
67
69
  for adm in AdminUser.query.all():
68
70
  daily_usage[adm.id] = DailyUsage.query.filter(DailyUsage.date == today, DailyUsage.admin_id == adm.id, DailyUsage.child_id == child_id).first()
69
71
  if daily_usage[adm.id] is None:
72
+ logger.info(f"creating a new daily usage {today} admin={adm.id} child={child_id}")
70
73
  daily_usage[adm.id] = DailyUsage(admin_id=adm.id, child_id=child_id)
71
74
  db.session.add(daily_usage[adm.id])
72
75
  changes = True
@@ -90,7 +93,7 @@ def _add_users_usage(users_usage_data: Dict[User, Dict], child_id, sync=False):
90
93
 
91
94
  # Enable the user if isn't already
92
95
  if not before_enabled_users[user.uuid] and user.is_active:
93
- print(f"Enabling disabled client {user.uuid} ")
96
+ logger.info(f"Enabling disabled client {user.uuid} ")
94
97
  user_driver.add_client(user)
95
98
  send_bot_message(user)
96
99
  have_change = True
@@ -129,7 +132,8 @@ def _add_users_usage(users_usage_data: Dict[User, Dict], child_id, sync=False):
129
132
  # Remove user from drivers(singbox, xray, wireguard etc.) if they're inactive
130
133
  # print(before_enabled_users[user.uuid], user.is_active)
131
134
  if before_enabled_users[user.uuid] and not user.is_active:
132
- print(f"Removing enabled client {user.uuid} ")
135
+ logger.info(f"Removing enabled client {user.uuid} ")
136
+
133
137
  user_driver.remove_client(user)
134
138
  have_change = True
135
139
  res[user.uuid] = f"{res[user.uuid]} !OUT of USAGE! Client Removed"
@@ -425,6 +425,9 @@ def add_headers(res, c, mimetype="text/plain"):
425
425
  resp.mimetype = mimetype
426
426
  resp.headers['Subscription-Userinfo'] = f"upload=0;download={c['usage_current_b']};total={c['usage_limit_b']};expire={c['expire_s']}"
427
427
  resp.headers['profile-web-page-url'] = request.base_url.rsplit('/', 1)[0].replace("http://", "https://") + "/"
428
+ # resp.headers['test-url'] = f"http://127.0.0.1:90/{hconfig(ConfigEnum.proxy_path_client)}/generate_204"
429
+ # resp.headers['test-url'] = f"http://{request.host}/{hconfig(ConfigEnum.proxy_path_client)}/generate_204"
430
+ # resp.headers['test-url'] = "http://connectivitycheck.gstatic.com/generate_204"
428
431
 
429
432
  if hconfig(ConfigEnum.branding_site):
430
433
  resp.headers['support-url'] = hconfig(ConfigEnum.branding_site)
@@ -1000,7 +1000,9 @@ msgstr ""
1000
1000
  "this time, please copy and save your Proxy links which are:"
1001
1001
 
1002
1002
  msgid "adminuser.force_update_usage"
1003
- msgstr "adminuser.force_update_usage"
1003
+ msgstr ""
1004
+ "Every 6 minutes the usage is being updated. For updating it now <a "
1005
+ "href=\"%(link)s\" class=\"btn btn-info\">press here</a>"
1004
1006
 
1005
1007
  msgid "all"
1006
1008
  msgstr "All"
@@ -1015,13 +1017,17 @@ msgid "app.foxray.title"
1015
1017
  msgstr "FoXray"
1016
1018
 
1017
1019
  msgid "app.hiddify-clash-android.description"
1018
- msgstr "app.hiddify-clash-android.description"
1020
+ msgstr ""
1021
+ "Hiddify Clash Android is one of our client apps which is not being updated "
1022
+ "any more. "
1019
1023
 
1020
1024
  msgid "app.hiddify-clash-android.title"
1021
1025
  msgstr "Hiddify Clash"
1022
1026
 
1023
1027
  msgid "app.hiddify-clash-desktop.description"
1024
- msgstr "app.hiddify-clash-desktop.description"
1028
+ msgstr ""
1029
+ "Hiddify Clash Desktop is one of our client apps which is not being updated "
1030
+ "any more. "
1025
1031
 
1026
1032
  msgid "app.hiddify-clash-desktop.title"
1027
1033
  msgstr "Hiddify Clash"
@@ -1051,7 +1057,7 @@ msgid "app.loon.title"
1051
1057
  msgstr "Loon"
1052
1058
 
1053
1059
  msgid "app.nekobox.description"
1054
- msgstr "app.nekobox.description"
1060
+ msgstr " Nekobox is a Sing-box based clients "
1055
1061
 
1056
1062
  msgid "app.nekobox.title"
1057
1063
  msgstr "NekoBox"
@@ -1875,7 +1881,7 @@ msgid "config.splithttp_enable.description"
1875
1881
  msgstr "This Protocol send and receive information in individual channels "
1876
1882
 
1877
1883
  msgid "config.splithttp_enable.label"
1878
- msgstr "Split HTTP"
1884
+ msgstr "🈁 Split HTTP"
1879
1885
 
1880
1886
  msgid "config.ssfaketls.description"
1881
1887
  msgstr ""
@@ -1992,7 +1998,7 @@ msgstr ""
1992
1998
  "control over XRay proxy setup."
1993
1999
 
1994
2000
  msgid "config.sub_full_xray_json_enable.label"
1995
- msgstr "XRay Full Config Link"
2001
+ msgstr "⚙️ XRay Full Config Link"
1996
2002
 
1997
2003
  msgid "config.sub_singbox_ssh_enable.description"
1998
2004
  msgstr "config.sub_singbox_ssh_enable.description"
@@ -6,6 +6,8 @@ msgid ""
6
6
  " Search\n"
7
7
  " Settings"
8
8
  msgstr ""
9
+ " جستجو کردن\n"
10
+ "تنظیمات"
9
11
 
10
12
  msgid "%(count)s records were successfully disabled."
11
13
  msgstr "%(count)s رکورد با موفقیت غیرفعال شد."
@@ -657,7 +659,7 @@ msgid "Root"
657
659
  msgstr "ریشه"
658
660
 
659
661
  msgid "Russia"
660
- msgstr ""
662
+ msgstr "روسیه"
661
663
 
662
664
  msgid "Save"
663
665
  msgstr "ذخیره"
@@ -1004,12 +1006,16 @@ msgstr "FoXray"
1004
1006
 
1005
1007
  msgid "app.hiddify-clash-android.description"
1006
1008
  msgstr ""
1009
+ "Hiddify Clash Android یکی از برنامه های کلاینت ما است که دیگر به روز نمی "
1010
+ "شود. "
1007
1011
 
1008
1012
  msgid "app.hiddify-clash-android.title"
1009
1013
  msgstr "Hiddify Clash"
1010
1014
 
1011
1015
  msgid "app.hiddify-clash-desktop.description"
1012
1016
  msgstr ""
1017
+ "Hiddify Clash Desktop یکی از برنامه های کلاینت ما است که دیگر به روز نمی "
1018
+ "شود. "
1013
1019
 
1014
1020
  msgid "app.hiddify-clash-desktop.title"
1015
1021
  msgstr "Hiddify Clash"
@@ -1039,7 +1045,7 @@ msgid "app.loon.title"
1039
1045
  msgstr "Loon"
1040
1046
 
1041
1047
  msgid "app.nekobox.description"
1042
- msgstr ""
1048
+ msgstr " Nekobox یک کلاینت مبتنی بر Sing-box است "
1043
1049
 
1044
1050
  msgid "app.nekobox.title"
1045
1051
  msgstr "NekoBox"
@@ -1874,7 +1880,7 @@ msgid "config.splithttp_enable.description"
1874
1880
  msgstr "این پروتکل اطلاعات را در کانال های جداگانه ارسال و دریافت می کند "
1875
1881
 
1876
1882
  msgid "config.splithttp_enable.label"
1877
- msgstr "Split HTTP"
1883
+ msgstr "🈁 Split HTTP"
1878
1884
 
1879
1885
  msgid "config.ssfaketls.description"
1880
1886
  msgstr ""
@@ -1993,7 +1999,7 @@ msgstr ""
1993
1999
  " می کند."
1994
2000
 
1995
2001
  msgid "config.sub_full_xray_json_enable.label"
1996
- msgstr "لینک پیکربندی کامل XRay"
2002
+ msgstr "⚙️ لینک پیکربندی کامل XRay"
1997
2003
 
1998
2004
  msgid "config.sub_singbox_ssh_enable.description"
1999
2005
  msgstr ""