hiddifypanel 7.1.9__py3-none-any.whl → 8.0.0.dev0__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 (40) hide show
  1. hiddifypanel/VERSION +1 -1
  2. hiddifypanel/VERSION.py +2 -2
  3. hiddifypanel/base.py +18 -15
  4. hiddifypanel/cache.py +11 -0
  5. hiddifypanel/drivers/abstract_driver.py +5 -0
  6. hiddifypanel/drivers/singbox_api.py +52 -0
  7. hiddifypanel/drivers/ssh_liberty_bridge_api.py +53 -0
  8. hiddifypanel/drivers/user_driver.py +30 -0
  9. hiddifypanel/drivers/xray_api.py +113 -0
  10. hiddifypanel/models/config.py +3 -1
  11. hiddifypanel/models/config_enum.py +7 -1
  12. hiddifypanel/models/proxy.py +3 -0
  13. hiddifypanel/models/user.py +3 -0
  14. hiddifypanel/panel/admin/UserAdmin.py +6 -6
  15. hiddifypanel/panel/commercial/restapi/resources.py +2 -2
  16. hiddifypanel/panel/custom_widgets.py +10 -10
  17. hiddifypanel/panel/hiddify.py +23 -1
  18. hiddifypanel/panel/init_db.py +27 -1
  19. hiddifypanel/panel/usage.py +6 -17
  20. hiddifypanel/panel/user/link_maker.py +1 -1
  21. hiddifypanel/panel/user/templates/home/all-configs.html +104 -91
  22. hiddifypanel/panel/user/templates/singbox_config.json +110 -0
  23. hiddifypanel/panel/user/user.py +32 -26
  24. hiddifypanel/templates/fake.html +4 -0
  25. hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
  26. hiddifypanel/translations/en/LC_MESSAGES/messages.po +72 -18
  27. hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
  28. hiddifypanel/translations/fa/LC_MESSAGES/messages.po +62 -18
  29. hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
  30. hiddifypanel/translations/pt/LC_MESSAGES/messages.po +62 -18
  31. hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
  32. hiddifypanel/translations/zh/LC_MESSAGES/messages.po +62 -18
  33. {hiddifypanel-7.1.9.dist-info → hiddifypanel-8.0.0.dev0.dist-info}/METADATA +3 -1
  34. {hiddifypanel-7.1.9.dist-info → hiddifypanel-8.0.0.dev0.dist-info}/RECORD +38 -33
  35. hiddifypanel/singbox_api.py +0 -55
  36. hiddifypanel/xray_api.py +0 -115
  37. {hiddifypanel-7.1.9.dist-info → hiddifypanel-8.0.0.dev0.dist-info}/LICENSE.md +0 -0
  38. {hiddifypanel-7.1.9.dist-info → hiddifypanel-8.0.0.dev0.dist-info}/WHEEL +0 -0
  39. {hiddifypanel-7.1.9.dist-info → hiddifypanel-8.0.0.dev0.dist-info}/entry_points.txt +0 -0
  40. {hiddifypanel-7.1.9.dist-info → hiddifypanel-8.0.0.dev0.dist-info}/top_level.txt +0 -0
hiddifypanel/VERSION CHANGED
@@ -1 +1 @@
1
- 7.1.9
1
+ 8.0.0.dev
hiddifypanel/VERSION.py CHANGED
@@ -1,3 +1,3 @@
1
- __version__='7.1.9'
1
+ __version__='8.0.0.dev'
2
2
  from datetime import datetime
3
- __release_date__= datetime.strptime('2023-07-30','%Y-%m-%d')
3
+ __release_date__= datetime.strptime('2023-08-03','%Y-%m-%d')
hiddifypanel/base.py CHANGED
@@ -5,30 +5,29 @@ from flask import Flask, request, g
5
5
  from flask_babelex import Babel
6
6
  from hiddifypanel.panel.init_db import init_db
7
7
  import hiddifypanel
8
- from hiddifypanel.models import *
8
+ from hiddifypanel.models import *
9
9
  from dotenv import dotenv_values
10
10
  import os
11
- def create_app(cli=False,**config):
11
+
12
+
13
+ def create_app(cli=False, **config):
12
14
  app = Flask(__name__, static_url_path="/<proxy_path>/static/", instance_relative_config=True)
13
15
 
14
- for c,v in dotenv_values('app.cfg').items():
16
+ for c, v in dotenv_values('app.cfg').items():
15
17
  if v.isdecimal():
16
- v= int(v)
18
+ v = int(v)
17
19
  else:
18
- v=True if v.lower()=="true" else (False if v.lower()=="false" else v)
20
+ v = True if v.lower() == "true" else (False if v.lower() == "false" else v)
19
21
 
20
-
21
- app.config[c]=v
22
-
22
+ app.config[c] = v
23
23
 
24
24
  app.jinja_env.line_statement_prefix = '%'
25
- app.is_cli=cli
25
+ app.is_cli = cli
26
26
  flask_bootstrap.Bootstrap4(app)
27
-
27
+
28
28
  hiddifypanel.panel.database.init_app(app)
29
29
  with app.app_context():
30
30
  init_db()
31
-
32
31
 
33
32
  hiddifypanel.panel.common.init_app(app)
34
33
  hiddifypanel.panel.admin.init_app(app)
@@ -58,10 +57,14 @@ def create_app(cli=False,**config):
58
57
 
59
58
  @app.before_request
60
59
  def check_csrf():
61
- if "/admin/user/" in request.base_url: return
62
- if "/admin/domain/" in request.base_url: return
63
- if "/admin/actions/" in request.base_url: return
64
- if "/api/v1/" in request.base_url: return
60
+ if "/admin/user/" in request.base_url:
61
+ return
62
+ if "/admin/domain/" in request.base_url:
63
+ return
64
+ if "/admin/actions/" in request.base_url:
65
+ return
66
+ if "/api/v1/" in request.base_url:
67
+ return
65
68
  csrf.protect()
66
69
 
67
70
  app.jinja_env.globals['get_locale'] = get_locale
hiddifypanel/cache.py ADDED
@@ -0,0 +1,11 @@
1
+ from redis_cache import RedisCache
2
+ import redis
3
+
4
+ redis_client = redis.from_url('unix:///opt/hiddify-config/other/redis/run.sock?db=0', decode_responses=True)
5
+
6
+
7
+ def exception_handler(**kwargs):
8
+ pass
9
+
10
+
11
+ cache = RedisCache(redis_client=redis_client, exception_handler=exception_handler)
@@ -0,0 +1,5 @@
1
+
2
+
3
+ class DriverABS:
4
+ def get_usage(uuid,reset=True):
5
+ pass
@@ -0,0 +1,52 @@
1
+ import xtlsapi
2
+ from hiddifypanel.models import *
3
+ from .abstract_driver import DriverABS
4
+
5
+
6
+ class SingboxApi(DriverABS):
7
+ def get_singbox_client(self):
8
+ if hconfig(ConfigEnum.is_parent):
9
+ return
10
+ return xtlsapi.SingboxClient('127.0.0.1', 10086)
11
+
12
+ def get_enabled_users(self):
13
+ if hconfig(ConfigEnum.is_parent):
14
+ return
15
+
16
+ def get_inbound_tags():
17
+ if hconfig(ConfigEnum.is_parent):
18
+ return
19
+ try:
20
+ xray_client = self.get_singbox_client()
21
+ inbounds = [inb.name.split(">>>")[1] for inb in xray_client.stats_query('inbound')]
22
+ print(f"Success in get inbound tags {inbounds}")
23
+ except Exception as e:
24
+ print(f"error in get inbound tags {e}")
25
+ inbounds = []
26
+ return list(set(inbounds))
27
+
28
+ def add_client(user):
29
+ if hconfig(ConfigEnum.is_parent):
30
+ return
31
+ # raise NotImplementedError()
32
+
33
+ def remove_client(user):
34
+ if hconfig(ConfigEnum.is_parent):
35
+ return
36
+ # raise NotImplementedError()
37
+
38
+ def get_usage(uuid, reset=False):
39
+ if hconfig(ConfigEnum.is_parent):
40
+ return
41
+ xray_client = self.get_singbox_client()
42
+ d = xray_client.get_client_download_traffic(f'{uuid}@hiddify.com', reset=reset)
43
+ u = xray_client.get_client_upload_traffic(f'{uuid}@hiddify.com', reset=reset)
44
+ print(f"Success {uuid} d={d} u={u}")
45
+ res = None
46
+ if d is None:
47
+ res = u
48
+ elif u is None:
49
+ res = d
50
+ else:
51
+ res = d + u
52
+ return res
@@ -0,0 +1,53 @@
1
+ from .abstract_driver import DriverABS
2
+ from hiddifypanel.models import *
3
+ import redis
4
+
5
+ USERS_SET = "ssh-server:users"
6
+ USERS_USAGE = "ssh-server:users-usage"
7
+
8
+
9
+ class SSHLibertyBridgeApi(DriverABS):
10
+
11
+ def get_ssh_redis_client(self):
12
+ if not getattr(self, 'redis_client'):
13
+ self.redis_client = redis.from_url(hconfig(ConfigEnum.ssh_server_redis_url), decode_responses=True)
14
+
15
+ return self.redis_client
16
+
17
+ def get_enabled_users(self):
18
+ if hconfig(ConfigEnum.is_parent):
19
+ return
20
+ redis_client = self.get_ssh_redis_client()
21
+ members = redis_client.smembers(USERS_SET)
22
+ return [m.split("::")[0] for m in members]
23
+
24
+ def add_client(self, user):
25
+ if hconfig(ConfigEnum.is_parent):
26
+ return
27
+ redis_client = self.get_ssh_redis_client()
28
+ redis_client.sadd(USERS_SET, f'{user.uuid}::{user.ed25519_public_key}')
29
+ redis_client.save()
30
+
31
+ def remove_client(self, user):
32
+ if hconfig(ConfigEnum.is_parent):
33
+ return
34
+ redis_client = self.get_ssh_redis_client()
35
+ redis_client.srem(USERS_SET, f'{user.uuid}::{user.ed25519_public_key}')
36
+ redis_client.srem(USERS_USAGE, user.uuid)
37
+ redis_client.save()
38
+
39
+ def get_usage(self, client_uuid: str, reset: bool = True) -> int:
40
+ if hconfig(ConfigEnum.is_parent):
41
+ return
42
+ value = redis_client.hget(USERS_USAGE, client_uuid)
43
+
44
+ if value is None:
45
+ return 0
46
+
47
+ value = int(value)
48
+
49
+ if reset:
50
+ redis_client.hincrby(USERS_USAGE, client_uuid, -value)
51
+ redis_client.save()
52
+
53
+ return value
@@ -0,0 +1,30 @@
1
+
2
+
3
+ from .ssh_liberty_bridge_api import SSHLibertyBridgeApi
4
+ from .xray_api import XrayApi
5
+ from .singbox_api import SingboxApi
6
+
7
+
8
+ drivers = [XrayApi(), SingboxApi(), SSHLibertyBridgeApi()]
9
+
10
+
11
+ def get_users_usage(reset=True):
12
+ res = {}
13
+ for user in User.query.all():
14
+ d = 0
15
+ for driver in drivers:
16
+ d += driver.get_usage(user.uuid, reset=True) or 0
17
+ res[user] = {'usage': d, 'ips': ''}
18
+ return res
19
+
20
+
21
+ def get_enabled_users(self):
22
+ d = []
23
+ for driver in drivers:
24
+ d += driver.get_enabled_users() or []
25
+ return d
26
+
27
+
28
+ def add_client(self, user):
29
+ for driver in drivers:
30
+ d += driver.add_client(user)
@@ -0,0 +1,113 @@
1
+ import xtlsapi
2
+ from hiddifypanel.models import *
3
+ from .abstract_driver import DriverABS
4
+
5
+
6
+ class XrayApi(DriverABS):
7
+ def get_xray_client(self):
8
+ if hconfig(ConfigEnum.is_parent):
9
+ return
10
+ return xtlsapi.XrayClient('127.0.0.1', 10085)
11
+
12
+ def get_enabled_users(self):
13
+ if hconfig(ConfigEnum.is_parent):
14
+ return
15
+ xray_client = self.get_xray_client()
16
+ users = User.query.all()
17
+ t = "xtls"
18
+ protocol = "vless"
19
+ enabled = {}
20
+ for u in users:
21
+ uuid = u.uuid
22
+ try:
23
+ xray_client.add_client(t, f'{uuid}', f'{uuid}@hiddify.com', protocol=protocol, flow='xtls-rprx-vision', alter_id=0, cipher='chacha20_poly1305')
24
+ xray_client.remove_client(t, f'{uuid}@hiddify.com')
25
+ enabled[uuid] = 0
26
+ except xtlsapi.exceptions.EmailAlreadyExists as e:
27
+ enabled[uuid] = 1
28
+ except Exception as e:
29
+ print(f"error {e}")
30
+ enabled[uuid] = e
31
+ return enabled
32
+
33
+ def get_inbound_tags(self):
34
+ if hconfig(ConfigEnum.is_parent):
35
+ return
36
+ try:
37
+ xray_client = self.get_xray_client()
38
+ inbounds = [inb.name.split(">>>")[1] for inb in xray_client.stats_query('inbound')]
39
+ print(f"Success in get inbound tags {inbounds}")
40
+ except Exception as e:
41
+ print(f"error in get inbound tags {e}")
42
+ inbounds = []
43
+ return list(set(inbounds))
44
+
45
+ def add_client(self, user):
46
+ if hconfig(ConfigEnum.is_parent):
47
+ return
48
+ uuid = user.uuid
49
+ xray_client = self.get_xray_client()
50
+ tags = self.get_inbound_tags()
51
+ proto_map = {
52
+ 'vless': 'vless',
53
+ 'realityin': 'vless',
54
+ 'xtls': 'vless',
55
+ 'quic': 'vless',
56
+ 'trojan': 'trojan',
57
+ 'vmess': 'vmess',
58
+ 'ss': 'shadowsocks',
59
+ 'v2ray': 'shadowsocks',
60
+ 'kcp': 'vless',
61
+ 'dispatcher': 'trojan',
62
+ }
63
+
64
+ def proto(t):
65
+ res = '', ''
66
+ for p, protocol in proto_map.items():
67
+ if p in t:
68
+ res = p, protocol
69
+ break
70
+ return res
71
+ for t in tags:
72
+ try:
73
+ p, protocol = proto(t)
74
+ if not p:
75
+ continue
76
+ if protocol == "vless" and p != "xtls" and p != "realityin":
77
+ xray_client.add_client(t, f'{uuid}', f'{uuid}@hiddify.com', protocol=protocol, flow='\0',)
78
+ else:
79
+ xray_client.add_client(t, f'{uuid}', f'{uuid}@hiddify.com', protocol=protocol, flow='xtls-rprx-vision', alter_id=0, cipher='chacha20_poly1305')
80
+ print(f"Success add {uuid} {t}")
81
+ except Exception as e:
82
+ print(f"error in add {uuid} {t} {e}")
83
+ pass
84
+
85
+ def remove_client(self, uuid):
86
+ if hconfig(ConfigEnum.is_parent):
87
+ return
88
+ xray_client = self.get_xray_client()
89
+ tags = self.get_inbound_tags()
90
+
91
+ for t in tags:
92
+ try:
93
+ xray_client.remove_client(t, f'{uuid}@hiddify.com')
94
+ print(f"Success remove {uuid} {t}")
95
+ except Exception as e:
96
+ print(f"error in remove {uuid} {t} {e}")
97
+ pass
98
+
99
+ def get_usage(self, uuid, reset=False):
100
+ if hconfig(ConfigEnum.is_parent):
101
+ return
102
+ xray_client = self.get_xray_client()
103
+ d = xray_client.get_client_download_traffic(f'{uuid}@hiddify.com', reset=reset)
104
+ u = xray_client.get_client_upload_traffic(f'{uuid}@hiddify.com', reset=reset)
105
+ print(f"Success {uuid} d={d} u={u}")
106
+ res = None
107
+ if d is None:
108
+ res = u
109
+ elif u is None:
110
+ res = d
111
+ else:
112
+ res = d + u
113
+ return res
@@ -1,3 +1,4 @@
1
+ # from hiddifypanel.cache import cache
1
2
  from sqlalchemy_serializer import SerializerMixin
2
3
  from flask import Flask
3
4
  from flask_sqlalchemy import SQLAlchemy
@@ -48,6 +49,7 @@ class StrConfig(db.Model, SerializerMixin):
48
49
  }
49
50
 
50
51
 
52
+ # @cache.cache()
51
53
  def hconfig(key: ConfigEnum, child_id=0):
52
54
  value = None
53
55
  try:
@@ -74,7 +76,7 @@ def hconfig(key: ConfigEnum, child_id=0):
74
76
 
75
77
 
76
78
  def set_hconfig(key: ConfigEnum, value, child_id=0, commit=True):
77
-
79
+ hconfig.invalidate(key, child_id)
78
80
  if key.type() == bool:
79
81
  dbconf = BoolConfig.query.filter(BoolConfig.key == key, BoolConfig.child_id == child_id).first()
80
82
  if not dbconf:
@@ -26,7 +26,7 @@ class ConfigCategory(StrEnum):
26
26
  telegram = auto()
27
27
  http = auto()
28
28
  tls = auto()
29
-
29
+ ssh = auto()
30
30
  ssfaketls = auto()
31
31
  shadowtls = auto()
32
32
  restls = auto()
@@ -41,6 +41,9 @@ class ConfigCategory(StrEnum):
41
41
 
42
42
 
43
43
  class ConfigEnum(StrEnum):
44
+ ssh_server_redis_url = auto()
45
+ ssh_server_ports = auto()
46
+ ssh_server_enable = auto()
44
47
  first_setup = auto()
45
48
  core_type = auto()
46
49
  warp_enable = auto()
@@ -139,6 +142,9 @@ class ConfigEnum(StrEnum):
139
142
 
140
143
  def info(self):
141
144
  map = {
145
+ self.ssh_server_redis_url: {'category': ConfigCategory.hidden},
146
+ self.ssh_server_ports: {'category': ConfigCategory.ssh},
147
+ self.ssh_server_enable: {'category': ConfigCategory.ssh},
142
148
  self.core_type: {'category': ConfigCategory.advanced, 'apply_mode': 'apply'},
143
149
  self.dns_server: {'category': ConfigCategory.general, 'apply_mode': 'apply'},
144
150
  self.warp_enable: {'category': ConfigCategory.hidden, 'type': bool, 'apply_mode': 'restart'},
@@ -25,6 +25,7 @@ class ProxyTransport(StrEnum):
25
25
  # h1=auto()
26
26
  WS = auto()
27
27
  tcp = auto()
28
+ ssh = auto()
28
29
 
29
30
 
30
31
  class ProxyCDN(StrEnum):
@@ -40,6 +41,7 @@ class ProxyProto(StrEnum):
40
41
  ss = auto()
41
42
  v2ray = auto()
42
43
  ssr = auto()
44
+ ssh = auto()
43
45
 
44
46
 
45
47
  class ProxyL3(StrEnum):
@@ -49,6 +51,7 @@ class ProxyL3(StrEnum):
49
51
  reality = auto()
50
52
  http = auto()
51
53
  kcp = auto()
54
+ ssh = auto()
52
55
  # hysteria=auto()
53
56
 
54
57
 
@@ -61,6 +61,9 @@ class User(db.Model, SerializerMixin):
61
61
  max_ips = db.Column(db.Integer, default=1000, nullable=False)
62
62
  details = db.relationship('UserDetail', cascade="all,delete", backref='user', lazy='dynamic',)
63
63
  enable = db.Column(db.Boolean, default=True, nullable=False)
64
+ ed25519_private_key=db.Column(db.String(100))
65
+ ed25519_public_key=db.Column(db.String(100))
66
+
64
67
 
65
68
  @property
66
69
  def remaining_days(self):
@@ -6,7 +6,7 @@ from flask import Markup, g, request, url_for, abort
6
6
  from wtforms.validators import Regexp, ValidationError
7
7
  import re
8
8
  import uuid
9
- from hiddifypanel import xray_api
9
+ from hiddifypanel.drivers import user_driver
10
10
  from .adminlte import AdminLTEModelView
11
11
  # from gettext import gettext as _
12
12
  from flask_babelex import gettext as __
@@ -195,7 +195,7 @@ class UserAdmin(AdminLTEModelView):
195
195
  def on_model_delete(self, model):
196
196
  if len(User.query.all()) <= 1:
197
197
  raise ValidationError(f"at least one user should exist")
198
- xray_api.remove_client(model.uuid)
198
+ user_driver.remove_client(model.uuid)
199
199
  # hiddify.flash_config_success()
200
200
 
201
201
  # def is_accessible(self):
@@ -251,7 +251,7 @@ class UserAdmin(AdminLTEModelView):
251
251
  raise ValidationError(_('You have too much users! You can have only %(active)s active users and %(total)s users',
252
252
  active=g.admin.max_active_users, total=g.admin.max_users))
253
253
  if old_user and old_user.uuid != model.uuid:
254
- xray_api.remove_client(old_user.uuid)
254
+ user_driver.remove_client(old_user.uuid)
255
255
 
256
256
  # model.expiry_time=datetime.date.today()+datetime.timedelta(days=model.expiry_time)
257
257
 
@@ -267,13 +267,13 @@ class UserAdmin(AdminLTEModelView):
267
267
 
268
268
  user = User.query.filter(User.uuid == model.uuid).first()
269
269
  if is_user_active(user):
270
- xray_api.add_client(model.uuid)
270
+ user_driver.add_client(model.uuid)
271
271
  else:
272
- xray_api.remove_client(model.uuid)
272
+ user_driver.remove_client(model.uuid)
273
273
  hiddify.quick_apply_users()
274
274
 
275
275
  def after_model_delete(self, model):
276
- xray_api.remove_client(model.uuid)
276
+ user_driver.remove_client(model.uuid)
277
277
 
278
278
  hiddify.quick_apply_users()
279
279
 
@@ -5,7 +5,7 @@ import datetime
5
5
  from hiddifypanel.models import *
6
6
  from urllib.parse import urlparse
7
7
  from hiddifypanel.panel import hiddify
8
- from hiddifypanel import xray_api
8
+ from hiddifypanel.drivers import user_driver
9
9
  # class AllResource(Resource):
10
10
  # def get(self):
11
11
  # return jsonify(
@@ -27,7 +27,7 @@ class UserResource(Resource):
27
27
  def post(self):
28
28
  data = request.json
29
29
  hiddify.add_or_update_user(**data)
30
- xray_api.add_client(data['uuid'])
30
+ user_driver.add_client(data['uuid'])
31
31
  hiddify.quick_apply_users()
32
32
 
33
33
  return jsonify({'status': 200, 'msg': 'ok'})
@@ -1,3 +1,12 @@
1
+ from flask_admin.contrib.sqla import ModelView
2
+ from wtforms.widgets import TextArea
3
+ from wtforms import TextAreaField
4
+ from flask_bootstrap import SwitchField
5
+ from wtforms.fields import StringField, IntegerField, SelectField
6
+ from hiddifypanel.panel.hiddify import flash
7
+ from hiddifypanel.panel import hiddify
8
+ from flask_babelex import lazy_gettext as _
9
+ from flask_babelex import gettext as __
1
10
  from flask_admin.contrib import sqla
2
11
  from hiddifypanel.panel.database import db
3
12
  import datetime
@@ -6,17 +15,8 @@ from flask import Markup, g
6
15
  from wtforms.validators import Regexp, ValidationError
7
16
  import re
8
17
  import uuid
9
- from hiddifypanel import xray_api
18
+
10
19
  # from gettext import gettext as _
11
- from flask_babelex import gettext as __
12
- from flask_babelex import lazy_gettext as _
13
- from hiddifypanel.panel import hiddify
14
- from hiddifypanel.panel.hiddify import flash
15
- from wtforms.fields import StringField, IntegerField, SelectField
16
- from flask_bootstrap import SwitchField
17
- from wtforms import TextAreaField
18
- from wtforms.widgets import TextArea
19
- from flask_admin.contrib.sqla import ModelView
20
20
 
21
21
 
22
22
  class DaysLeftField(IntegerField):
@@ -1,12 +1,14 @@
1
1
  import socket
2
2
  from sqlalchemy.orm import Load
3
+ import glob
4
+ import json
3
5
  from babel.dates import format_timedelta as babel_format_timedelta
4
6
  from flask_babelex import gettext as __
5
7
  from flask_babelex import lazy_gettext as _
6
8
  from hiddifypanel.models import *
7
9
  from hiddifypanel.panel.database import db
8
10
  import datetime
9
- from flask import jsonify, g, url_for, Markup, abort
11
+ from flask import jsonify, g, url_for, Markup, abort, current_app
10
12
  from flask import flash as flask_flash
11
13
  from wtforms.validators import ValidationError
12
14
  import requests
@@ -667,3 +669,23 @@ def generate_x25519_keys():
667
669
 
668
670
  # Return the keys as a tuple
669
671
  return {"private_key": private_key, "public_key": public_key}
672
+
673
+
674
+ def get_hostkeys(dojson=False):
675
+ key_files = glob.glob(current_app.config['HIDDIFY_CONFIG_PATH'] + "/other/ssh/host_key/*_key.pub")
676
+ host_keys = []
677
+ for file_name in key_files:
678
+ with open(file_name, "r") as f:
679
+ host_key = f.read().strip()
680
+ host_key = host_key.split()
681
+ if len(host_key) > 2:
682
+ host_key = host_key[:2] # strip the hostname part
683
+ host_key = " ".join(host_key)
684
+ host_keys.append(host_key)
685
+ if dojson:
686
+ return json.dumps(host_keys)
687
+ return host_keys
688
+
689
+
690
+ def get_ssh_client_version(user):
691
+ return 'SSH-2.0-OpenSSH_7.4p1'
@@ -30,6 +30,8 @@ def init_db():
30
30
 
31
31
  add_column(Domain.grpc)
32
32
  add_column(ParentDomain.alias)
33
+ add_column(User.ed25519_private_key)
34
+ add_column(User.ed25519_public_key)
33
35
  add_column(User.start_date)
34
36
  add_column(User.package_days)
35
37
  add_column(User.telegram_id)
@@ -108,11 +110,34 @@ def init_db():
108
110
  return BoolConfig.query.all()
109
111
 
110
112
 
113
+ def _v44():
114
+ import ed25519
115
+ for u in User.query.all():
116
+
117
+ privkey = ed25519.Ed25519PrivateKey.generate()
118
+ pubkey = privkey.public_key()
119
+ priv_bytes = privkey.private_bytes(
120
+ encoding=serialization.Encoding.PEM,
121
+ format=serialization.PrivateFormat.OpenSSH,
122
+ encryption_algorithm=serialization.NoEncryption(),
123
+ )
124
+ pub_bytes = pubkey.public_bytes(
125
+ encoding=serialization.Encoding.OpenSSH,
126
+ format=serialization.PublicFormat.OpenSSH,
127
+ )
128
+ u.ed25519_private_key = priv_bytes.decode()
129
+ u.ed25519_public_key = pub_bytes.decode()
130
+ db.session.add(Proxy(l3='ssh', transport='ssh', cdn='direct', proto='ssh', enable=True, name="SSH"))
131
+ add_config_if_not_exist(ConfigEnum.ssh_server_redis_url, "unix:///opt/hiddify-config/other/redis/run.sock?db=1")
132
+ add_config_if_not_exist(ConfigEnum.ssh_server_port, random.randint(5000, 20000))
133
+ add_config_if_not_exist(ConfigEnum.ssh_server_enable, False)
111
134
  # def _v43():
112
135
  # if not (Domain.query.filter(Domain.domain==hconfig(ConfigEnum.domain_fronting_domain)).first()):
113
136
  # db.session.add(Domain(domain=hconfig(ConfigEnum.domain_fronting_domain),servernames=hconfig(ConfigEnum.domain_fronting_domain),mode=DomainType.cdn))
114
137
 
115
138
  # v7.0.0
139
+
140
+
116
141
  def _v42():
117
142
 
118
143
  for k in [ConfigEnum.telegram_fakedomain, ConfigEnum.ssfaketls_fakedomain, ConfigEnum.shadowtls_fakedomain]:
@@ -366,7 +391,8 @@ def get_proxy_rows_v1():
366
391
  "restls1_2 direct ss",
367
392
  "restls1_3 direct ss",
368
393
  "tcp direct ssr",
369
- "WS CDN v2ray"]
394
+ "WS CDN v2ray"
395
+ ]
370
396
  )
371
397
 
372
398
 
@@ -1,5 +1,5 @@
1
1
  from sqlalchemy.orm import Load
2
- from hiddifypanel import xray_api, singbox_api
2
+ from hiddifypanel.drivers import user_driver
3
3
  from sqlalchemy import func
4
4
  from flask_babelex import gettext as __
5
5
  from flask_babelex import lazy_gettext as _
@@ -15,15 +15,8 @@ to_gig_d = 1024**3
15
15
 
16
16
 
17
17
  def update_local_usage():
18
-
19
- res = {}
20
- have_change = False
21
- for user in User.query.all():
22
- d = xray_api.get_usage(user.uuid, reset=True)
23
- sd = singbox_api.get_usage(user.uuid, reset=True)
24
- res[user] = {'usage': (d or 0)+(sd or 0), 'ips': ''}
25
-
26
- return add_users_usage(res, 0)
18
+ res = user_driver.get_users_usage(reset=True)
19
+ return add_users_usage(res, child_id=0)
27
20
 
28
21
  # return {"status": 'success', "comments":res}
29
22
 
@@ -34,10 +27,6 @@ def add_users_usage_uuid(uuids_bytes, child_id):
34
27
  add_users_usage(dbusers_bytes, child_id)
35
28
 
36
29
 
37
- def is_already_valid(uuid):
38
- xray_api.get_xray_client().add_client(t, f'{uuid}', f'{uuid}@hiddify.com', protocol=protocol, flow='xtls-rprx-vision', alter_id=0, cipher='chacha20_poly1305')
39
-
40
-
41
30
  def add_users_usage(dbusers_bytes, child_id):
42
31
  print(dbusers_bytes)
43
32
  if not hconfig(ConfigEnum.is_parent) and hconfig(ConfigEnum.parent_panel):
@@ -46,7 +35,7 @@ def add_users_usage(dbusers_bytes, child_id):
46
35
 
47
36
  res = {}
48
37
  have_change = False
49
- before_enabled_users = xray_api.get_enabled_users()
38
+ before_enabled_users = user_driver.get_enabled_users()
50
39
  daily_usage = {}
51
40
  today = datetime.date.today()
52
41
  for adm in AdminUser.query.all():
@@ -73,7 +62,7 @@ def add_users_usage(dbusers_bytes, child_id):
73
62
  detail.current_usage_GB = 0
74
63
 
75
64
  if before_enabled_users[user.uuid] == 0 and user.is_active:
76
- xray_api.add_client(user.uuid)
65
+ user_driver.add_client(user)
77
66
  send_bot_message(user)
78
67
  have_change = True
79
68
  if type(usage_bytes) != int or usage_bytes == 0:
@@ -91,7 +80,7 @@ def add_users_usage(dbusers_bytes, child_id):
91
80
  user.start_date = datetime.date.today()
92
81
 
93
82
  if before_enabled_users[user.uuid] == 1 and not is_user_active(user):
94
- xray_api.remove_client(user.uuid)
83
+ user_driver.remove_client(user)
95
84
  have_change = True
96
85
  res[user.uuid] = f"{res[user.uuid]} !OUT of USAGE! Client Removed"
97
86