hiddifypanel 9.0.0.dev20__py3-none-any.whl → 9.0.0.dev22__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.
- hiddifypanel/VERSION +1 -1
- hiddifypanel/VERSION.py +2 -2
- hiddifypanel/models/domain.py +3 -2
- hiddifypanel/panel/admin/Dashboard.py +6 -1
- hiddifypanel/panel/admin/DomainAdmin.py +5 -2
- hiddifypanel/panel/common.py +94 -50
- hiddifypanel/panel/hiddify.py +14 -0
- hiddifypanel/panel/user/user.py +160 -21
- hiddifypanel/templates/admin-layout.html +7 -1
- hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.po +98 -74
- hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/fa/LC_MESSAGES/messages.po +96 -49
- hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/pt/LC_MESSAGES/messages.po +104 -45
- hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/ru/LC_MESSAGES/messages.po +202 -361
- hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/zh/LC_MESSAGES/messages.po +88 -54
- {hiddifypanel-9.0.0.dev20.dist-info → hiddifypanel-9.0.0.dev22.dist-info}/METADATA +1 -1
- {hiddifypanel-9.0.0.dev20.dist-info → hiddifypanel-9.0.0.dev22.dist-info}/RECORD +25 -25
- {hiddifypanel-9.0.0.dev20.dist-info → hiddifypanel-9.0.0.dev22.dist-info}/LICENSE.md +0 -0
- {hiddifypanel-9.0.0.dev20.dist-info → hiddifypanel-9.0.0.dev22.dist-info}/WHEEL +0 -0
- {hiddifypanel-9.0.0.dev20.dist-info → hiddifypanel-9.0.0.dev22.dist-info}/entry_points.txt +0 -0
- {hiddifypanel-9.0.0.dev20.dist-info → hiddifypanel-9.0.0.dev22.dist-info}/top_level.txt +0 -0
hiddifypanel/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
9.0.0.
|
1
|
+
9.0.0.dev22
|
hiddifypanel/VERSION.py
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
__version__='9.0.0.
|
1
|
+
__version__='9.0.0.dev22'
|
2
2
|
from datetime import datetime
|
3
|
-
__release_date__= datetime.strptime('2023-10-
|
3
|
+
__release_date__= datetime.strptime('2023-10-30','%Y-%m-%d')
|
hiddifypanel/models/domain.py
CHANGED
@@ -8,6 +8,7 @@ from strenum import StrEnum
|
|
8
8
|
from hiddifypanel.panel.database import db
|
9
9
|
from .config import hconfig
|
10
10
|
from .config_enum import ConfigEnum
|
11
|
+
from sqlalchemy.orm import backref
|
11
12
|
|
12
13
|
|
13
14
|
class DomainType(StrEnum):
|
@@ -47,7 +48,7 @@ class Domain(db.Model, SerializerMixin):
|
|
47
48
|
show_domains = db.relationship('Domain', secondary=ShowDomain,
|
48
49
|
primaryjoin=id == ShowDomain.c.domain_id,
|
49
50
|
secondaryjoin=id == ShowDomain.c.related_id,
|
50
|
-
|
51
|
+
backref=backref('showed_by_domains', lazy='dynamic')
|
51
52
|
)
|
52
53
|
|
53
54
|
def __repr__(self):
|
@@ -76,7 +77,7 @@ class Domain(db.Model, SerializerMixin):
|
|
76
77
|
|
77
78
|
@property
|
78
79
|
def need_valid_ssl(self):
|
79
|
-
return self.mode in [
|
80
|
+
return self.mode in [DomainType.direct, DomainType.cdn, DomainType.worker, DomainType.relay, DomainType.auto_cdn_ip, DomainType.old_xtls_direct, DomainType.sub_link_only]
|
80
81
|
|
81
82
|
@property
|
82
83
|
def port_index(self):
|
@@ -1,4 +1,6 @@
|
|
1
1
|
import datetime
|
2
|
+
import os
|
3
|
+
import re
|
2
4
|
|
3
5
|
from flask import render_template, url_for, request, jsonify, g, redirect, abort
|
4
6
|
from flask_babelex import lazy_gettext as _
|
@@ -23,7 +25,7 @@ class Dashboard(FlaskView):
|
|
23
25
|
))
|
24
26
|
|
25
27
|
def index(self):
|
26
|
-
|
28
|
+
|
27
29
|
if hconfig(ConfigEnum.first_setup):
|
28
30
|
return redirect(url_for("admin.QuickSetup:index"))
|
29
31
|
if hiddifypanel.__release_date__ + datetime.timedelta(days=20) < datetime.datetime.now():
|
@@ -70,6 +72,8 @@ class Dashboard(FlaskView):
|
|
70
72
|
d = domains[0]
|
71
73
|
u = def_user.uuid
|
72
74
|
flash((_('It seems that you have not created any users yet. Default user link: %(default_link)s', default_link=hiddify.get_user_link(u, d))), 'secondary')
|
75
|
+
if hiddify.is_ssh_password_authentication_enabled():
|
76
|
+
flash(_('ssh.password-login.warning.'), "warning")
|
73
77
|
|
74
78
|
# except:
|
75
79
|
# flash((_('Error!!!')),'info')
|
@@ -85,3 +89,4 @@ class Dashboard(FlaskView):
|
|
85
89
|
db.session.commit()
|
86
90
|
flash(_("child has been removed!"), "success")
|
87
91
|
return self.index()
|
92
|
+
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from hiddifypanel.models import *
|
2
2
|
import re
|
3
|
-
|
3
|
+
from hiddifypanel.panel.database import db
|
4
4
|
from flask import Markup
|
5
5
|
from flask import g, flash
|
6
6
|
from flask_babelex import gettext as __
|
@@ -248,6 +248,9 @@ class DomainAdmin(AdminLTEModelView):
|
|
248
248
|
def on_model_delete(self, model):
|
249
249
|
if len(Domain.query.all()) <= 1:
|
250
250
|
raise ValidationError(f"at least one domain should exist")
|
251
|
+
# ShowDomain.query.filter_by(related_id == model.id).delete()
|
252
|
+
model.showed_by_domains = []
|
253
|
+
# db.session.commit()
|
251
254
|
hiddify.flash_config_success(restart_mode='apply', domain_changed=True)
|
252
255
|
|
253
256
|
def after_model_delete(self, model):
|
@@ -260,7 +263,7 @@ class DomainAdmin(AdminLTEModelView):
|
|
260
263
|
set_hconfig(ConfigEnum.first_setup, False)
|
261
264
|
# if hconfig(ConfigEnum.parent_panel):
|
262
265
|
# hiddify_api.sync_child_to_parent()
|
263
|
-
if model.
|
266
|
+
if model.need_valid_ssl():
|
264
267
|
hiddify.exec_command(f"sudo /opt/hiddify-manager/acme.sh/get_cert.sh {model.domain}")
|
265
268
|
|
266
269
|
def is_accessible(self):
|
hiddifypanel/panel/common.py
CHANGED
@@ -23,27 +23,9 @@ def init_app(app):
|
|
23
23
|
def internal_server_error(e):
|
24
24
|
if not hasattr(e, 'code') or e.code == 500:
|
25
25
|
trace = traceback.format_exc()
|
26
|
-
trace = remove_unrelated_stacktrace_details(trace)
|
27
|
-
issue_body = f"""
|
28
|
-
# Internal Error Stacktrace:
|
29
|
-
**Error Message**: {str(e)}
|
30
|
-
```
|
31
|
-
{trace}
|
32
|
-
```
|
33
|
-
## Details:
|
34
|
-
**Hiddify Version**: {hiddifypanel.__version__}
|
35
|
-
**Python Version**: {python_version}
|
36
|
-
**OS**: {platform()}
|
37
|
-
"""
|
38
|
-
|
39
|
-
# Add user agent if exists
|
40
|
-
if hasattr(g, 'user_agent') and str(g.user_agent):
|
41
|
-
issue_body += f"**User Agent**: {str(g.user_agent)}"
|
42
26
|
|
43
27
|
# Create github issue link
|
44
|
-
issue_link =
|
45
|
-
# Remove proxy path and uuid from stacktrace details
|
46
|
-
remove_sensetive_data_from_github_issue_link(issue_link)
|
28
|
+
issue_link = generate_github_issue_link_for_500_error(e, trace)
|
47
29
|
|
48
30
|
last_version = hiddify.get_latest_release_version('hiddifypanel')
|
49
31
|
has_update = "T" not in hiddifypanel.__version__ and "dev" not in hiddifypanel.__version__ and f'{last_version}' != hiddifypanel.__version__
|
@@ -53,40 +35,11 @@ def init_app(app):
|
|
53
35
|
|
54
36
|
return render_template('error.html', error=e), e.code
|
55
37
|
|
56
|
-
def
|
57
|
-
if hasattr(g, 'user_uuid') and g.user_uuid:
|
58
|
-
issue_link.replace(f'{g.user_uuid}', '*******************')
|
59
|
-
if hconfig(ConfigEnum.proxy_path) and hconfig(ConfigEnum.proxy_path):
|
60
|
-
issue_link.replace(hconfig(ConfigEnum.proxy_path), '**********')
|
61
|
-
|
62
|
-
def remove_unrelated_stacktrace_details(stacktrace: str):
|
63
|
-
lines = stacktrace.splitlines()
|
64
|
-
if len(lines) < 1:
|
65
|
-
return ""
|
66
|
-
|
67
|
-
output = ''
|
68
|
-
skip_next_line = False
|
69
|
-
for i, line in enumerate(lines):
|
70
|
-
if i == 0:
|
71
|
-
output += line + '\n'
|
72
|
-
continue
|
73
|
-
if skip_next_line == True:
|
74
|
-
skip_next_line = False
|
75
|
-
continue
|
76
|
-
if line.strip().startswith('File'):
|
77
|
-
if 'hiddify' in line.lower():
|
78
|
-
output += line + '\n'
|
79
|
-
if i < len(lines)-1:
|
80
|
-
output += lines[i + 1] + '\n'
|
81
|
-
skip_next_line = True
|
82
|
-
|
83
|
-
return output
|
84
|
-
|
85
|
-
def generate_github_issue_link(e, issue_body):
|
38
|
+
def generate_github_issue_link(title, issue_body):
|
86
39
|
opts = {
|
87
40
|
"user": 'hiddify',
|
88
41
|
"repo": 'Hiddify-Manager',
|
89
|
-
"title":
|
42
|
+
"title": title,
|
90
43
|
"body": issue_body,
|
91
44
|
}
|
92
45
|
issue_link = str(github_issue_generator.IssueUrl(opts).get_url())
|
@@ -169,4 +122,95 @@ def init_app(app):
|
|
169
122
|
if (not telegrambot.bot) or (not telegrambot.bot.username):
|
170
123
|
telegrambot.register_bot()
|
171
124
|
g.bot = telegrambot.bot
|
125
|
+
else:
|
126
|
+
g.bot = None
|
127
|
+
|
172
128
|
# print(g.user)
|
129
|
+
|
130
|
+
def github_issue_details():
|
131
|
+
details = {
|
132
|
+
'hiddify_version': f'{hiddifypanel.__version__}',
|
133
|
+
'python_version': f'{python_version}',
|
134
|
+
'os_details': f'{platform()}',
|
135
|
+
'user_agent': 'Unknown'
|
136
|
+
}
|
137
|
+
if hasattr(g, 'user_agent') and str(g.user_agent):
|
138
|
+
details['user_agent'] = g.user_agent.ua_string
|
139
|
+
return details
|
140
|
+
|
141
|
+
def generate_github_issue_link_for_500_error(error, traceback, remove_sensetive_data=True, remove_unrelated_traceback_datails=True):
|
142
|
+
|
143
|
+
def remove_sensetive_data_from_github_issue_link(issue_link):
|
144
|
+
if hasattr(g, 'user_uuid') and g.user_uuid:
|
145
|
+
issue_link.replace(f'{g.user_uuid}', '*******************')
|
146
|
+
if hconfig(ConfigEnum.proxy_path) and hconfig(ConfigEnum.proxy_path):
|
147
|
+
issue_link.replace(hconfig(ConfigEnum.proxy_path), '**********')
|
148
|
+
|
149
|
+
def remove_unrelated_traceback_details(stacktrace: str):
|
150
|
+
lines = stacktrace.splitlines()
|
151
|
+
if len(lines) < 1:
|
152
|
+
return ""
|
153
|
+
|
154
|
+
output = ''
|
155
|
+
skip_next_line = False
|
156
|
+
for i, line in enumerate(lines):
|
157
|
+
if i == 0:
|
158
|
+
output += line + '\n'
|
159
|
+
continue
|
160
|
+
if skip_next_line == True:
|
161
|
+
skip_next_line = False
|
162
|
+
continue
|
163
|
+
if line.strip().startswith('File'):
|
164
|
+
if 'hiddify' in line.lower():
|
165
|
+
output += line + '\n'
|
166
|
+
output += lines[i + 1] + '\n'
|
167
|
+
skip_next_line = True
|
168
|
+
|
169
|
+
return output
|
170
|
+
|
171
|
+
if remove_unrelated_traceback_datails:
|
172
|
+
traceback = remove_unrelated_traceback_details(traceback)
|
173
|
+
|
174
|
+
gd = github_issue_details()
|
175
|
+
|
176
|
+
issue_body = f"""
|
177
|
+
# Internal Error Stacktrace:
|
178
|
+
**Error Message**: {str(error)}
|
179
|
+
```
|
180
|
+
{traceback}
|
181
|
+
```
|
182
|
+
## Details:
|
183
|
+
**Hiddify Version**: {gd['hiddify_version']}
|
184
|
+
**Python Version**: {gd['python_version']}
|
185
|
+
**OS**: {gd['os_details']}
|
186
|
+
**User Agent**: {gd['user_agent'] if gd['user_agent'] else "Unknown"}
|
187
|
+
"""
|
188
|
+
|
189
|
+
# Create github issue link
|
190
|
+
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)
|
191
|
+
|
192
|
+
if remove_sensetive_data:
|
193
|
+
remove_sensetive_data_from_github_issue_link(issue_link)
|
194
|
+
|
195
|
+
return issue_link
|
196
|
+
|
197
|
+
def generate_github_issue_link_for_admin_sidebar():
|
198
|
+
|
199
|
+
gd = github_issue_details()
|
200
|
+
|
201
|
+
issue_body = f"""
|
202
|
+
# Bug:
|
203
|
+
**Description**: "Describe your problem"
|
204
|
+
|
205
|
+
## Details:
|
206
|
+
**Hiddify Version**: {gd['hiddify_version']}
|
207
|
+
**Python Version**: {gd['python_version']}
|
208
|
+
**OS**: {gd['os_details']}
|
209
|
+
**User Agent**: {gd['user_agent'] if gd['user_agent'] else "Unknown"}
|
210
|
+
"""
|
211
|
+
|
212
|
+
# Create github issue link
|
213
|
+
issue_link = generate_github_issue_link('Please fill the title properly', issue_body)
|
214
|
+
return issue_link
|
215
|
+
|
216
|
+
app.jinja_env.globals['generate_github_issue_link_for_admin_sidebar'] = generate_github_issue_link_for_admin_sidebar
|
hiddifypanel/panel/hiddify.py
CHANGED
@@ -724,3 +724,17 @@ def __parse_user_agent(ua):
|
|
724
724
|
if res["is_browser"]:
|
725
725
|
res['app'] = uaa.browser.family
|
726
726
|
return res
|
727
|
+
|
728
|
+
|
729
|
+
def is_ssh_password_authentication_enabled():
|
730
|
+
if os.path.isfile('/etc/ssh/sshd_config'):
|
731
|
+
content = ''
|
732
|
+
with open('/etc/ssh/sshd_config', 'r') as f:
|
733
|
+
for line in f.readlines():
|
734
|
+
line = line.strip()
|
735
|
+
if line.startswith('#'):
|
736
|
+
continue
|
737
|
+
if re.search("^PasswordAuthentication\s+no", line, re.IGNORECASE):
|
738
|
+
return False
|
739
|
+
|
740
|
+
return True
|
hiddifypanel/panel/user/user.py
CHANGED
@@ -7,7 +7,6 @@ import datetime
|
|
7
7
|
from hiddifypanel.models import *
|
8
8
|
from hiddifypanel.panel.database import db
|
9
9
|
from hiddifypanel.panel import hiddify, clean_ip
|
10
|
-
|
11
10
|
from . import link_maker
|
12
11
|
from flask_classful import FlaskView, route
|
13
12
|
import random
|
@@ -19,15 +18,149 @@ import re
|
|
19
18
|
|
20
19
|
class UserView(FlaskView):
|
21
20
|
|
21
|
+
# region api
|
22
22
|
@route('/short/')
|
23
|
+
@route('/short')
|
23
24
|
def short_link(self):
|
24
|
-
short = hiddify.add_short_link(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
short = hiddify.add_short_link(
|
26
|
+
"/"+hconfig(ConfigEnum.proxy_path)+"/"+g.user.uuid+"/")
|
27
|
+
full_url = f"https://{urlparse(request.base_url).hostname}/{short}"
|
28
|
+
data = {
|
29
|
+
"short": f"/{short}",
|
30
|
+
"url": full_url
|
31
|
+
}
|
32
|
+
return jsonify(data)
|
33
|
+
|
34
|
+
@route('/info/')
|
35
|
+
@route('/info')
|
36
|
+
def info(self):
|
37
|
+
c = get_common_data(g.user_uuid, 'new')
|
38
|
+
data = {
|
39
|
+
'profile_title': c['profile_title'],
|
40
|
+
'profile_url': f"https://{urlparse(request.base_url).hostname}/{g.proxy_path}/{g.user_uuid}/#{g.user.name}",
|
41
|
+
'profile_usage_current': g.user.current_usage_GB,
|
42
|
+
'profile_usage_total': g.user.usage_limit_GB,
|
43
|
+
'profile_remaining_days': g.user.remaining_days,
|
44
|
+
'profile_reset_days': days_to_reset(g.user),
|
45
|
+
'telegram_bot_url': f"https://t.me/{c['bot'].username}?start={g.user_uuid}" if c['bot'] else "",
|
46
|
+
'admin_message_html': hconfig(ConfigEnum.branding_freetext),
|
47
|
+
'admin_message_url': hconfig(ConfigEnum.branding_site),
|
48
|
+
'brand_title': hconfig(ConfigEnum.branding_title),
|
49
|
+
'brand_icon_url': "",
|
50
|
+
'doh': f"https://{urlparse(request.base_url).hostname}/{g.proxy_path}/dns/dns-query"
|
51
|
+
}
|
52
|
+
|
53
|
+
return jsonify(data)
|
54
|
+
|
55
|
+
@route('/mtproxies/')
|
56
|
+
@route('/mtproxies')
|
57
|
+
def mtproxies(self):
|
58
|
+
# get domains
|
59
|
+
c = get_common_data(g.user_uuid, 'new')
|
60
|
+
mtproxies = []
|
61
|
+
# TODO: Remove duplicated domains mapped to a same ipv4 and v6
|
62
|
+
for d in c['domains']:
|
63
|
+
if d.mode not in [DomainType.direct, DomainType.relay]:
|
64
|
+
continue
|
65
|
+
hexuuid = hconfig(ConfigEnum.shared_secret, d.child_id).replace('-', '')
|
66
|
+
telegram_faketls_domain_hex = hconfig(ConfigEnum.telegram_fakedomain, d.child_id).encode('utf-8').hex()
|
67
|
+
server_link = f'tg://proxy?server={d.domain}&port=443&secret=ee{hexuuid}{telegram_faketls_domain_hex}'
|
68
|
+
mtproxies.append({'title': d.alias or d.domain, 'link': server_link})
|
69
|
+
|
70
|
+
return jsonify(mtproxies)
|
71
|
+
|
72
|
+
@route('/all-configs/')
|
73
|
+
@route('/all-configs')
|
74
|
+
def configs(self):
|
75
|
+
def create_item(name, type, domain, protocol, transport, security, link):
|
76
|
+
return {
|
77
|
+
'name': name,
|
78
|
+
'type': type,
|
79
|
+
'domain': domain,
|
80
|
+
'protocol': protocol,
|
81
|
+
'transport': transport,
|
82
|
+
'security': security,
|
83
|
+
'link': link
|
84
|
+
}
|
85
|
+
|
86
|
+
items = []
|
87
|
+
base_url = f"https://{urlparse(request.base_url).hostname}/{g.proxy_path}/{g.user_uuid}/"
|
88
|
+
c = get_common_data(g.user_uuid, 'new')
|
89
|
+
|
90
|
+
# Add Auto
|
91
|
+
items.append(
|
92
|
+
create_item(
|
93
|
+
"Auto", "All", "All", "All", "All", "All",
|
94
|
+
f"{base_url}sub/?asn={c['asn']}")
|
95
|
+
)
|
96
|
+
|
97
|
+
# Add Full Singbox
|
98
|
+
items.append(
|
99
|
+
create_item(
|
100
|
+
"Full Singbox", "All", "All", "All", "All", "All",
|
101
|
+
f"{base_url}full-singbox.json?asn={c['asn']}"
|
102
|
+
)
|
103
|
+
)
|
104
|
+
|
105
|
+
# Add Clash Meta
|
106
|
+
items.append(
|
107
|
+
create_item(
|
108
|
+
"Clash Meta", "All", "All", "All", "All", "All",
|
109
|
+
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']}"
|
110
|
+
)
|
111
|
+
)
|
112
|
+
|
113
|
+
# Add Clash
|
114
|
+
items.append(
|
115
|
+
create_item(
|
116
|
+
"Clash", "All", "All", "Except VLess", "All", "All",
|
117
|
+
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']}"
|
118
|
+
)
|
119
|
+
)
|
120
|
+
|
121
|
+
# Add Singbox: SSh
|
122
|
+
if hconfig(ConfigEnum.ssh_server_enable):
|
123
|
+
items.append(
|
124
|
+
create_item(
|
125
|
+
"Singbox: SSH", "SSH", "SSH", "SSH", "SSH", "SSH",
|
126
|
+
f"{base_url}singbox.json?name={c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}&asn={c['asn']}&mode={c['mode']}"
|
127
|
+
)
|
128
|
+
)
|
129
|
+
|
130
|
+
# Add Subscription link
|
131
|
+
items.append(
|
132
|
+
create_item(
|
133
|
+
"Subscription link", "All", "All", "All", "All", "All",
|
134
|
+
f"{base_url}all.txt?name={c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}&asn={c['asn']}&mode={c['mode']}"
|
135
|
+
)
|
136
|
+
)
|
137
|
+
|
138
|
+
# Add Subscription link base64
|
139
|
+
items.append(
|
140
|
+
create_item(
|
141
|
+
"Subscription link b64", "All", "All", "All", "All", "All",
|
142
|
+
f"{base_url}all.txt?name=new_link_{c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}-{c['mode']}&asn={c['asn']}&mode={c['mode']}&base64=True"
|
143
|
+
)
|
144
|
+
)
|
145
|
+
|
146
|
+
for pinfo in link_maker.get_all_validated_proxies(c['domains']):
|
147
|
+
items.append(
|
148
|
+
create_item(
|
149
|
+
pinfo["name"].replace("_", " "),
|
150
|
+
f"{'Auto ' if pinfo['dbdomain'].has_auto_ip else ''}{pinfo['mode']}",
|
151
|
+
pinfo['server'],
|
152
|
+
pinfo['proto'],
|
153
|
+
pinfo['transport'],
|
154
|
+
pinfo['l3'],
|
155
|
+
f"{link_maker.to_link(pinfo)}"
|
156
|
+
)
|
157
|
+
)
|
158
|
+
|
159
|
+
return jsonify(items)
|
160
|
+
|
161
|
+
# endregion
|
162
|
+
|
163
|
+
@route('/test/')
|
31
164
|
def test(self):
|
32
165
|
ua = request.user_agent.string
|
33
166
|
if re.match('^Mozilla', ua, re.IGNORECASE):
|
@@ -120,7 +253,8 @@ class UserView(FlaskView):
|
|
120
253
|
domain = request.args.get("domain", None)
|
121
254
|
|
122
255
|
c = get_common_data(g.user_uuid, mode, filter_domain=domain)
|
123
|
-
resp = Response(render_template('clash_proxies.yml',
|
256
|
+
resp = Response(render_template('clash_proxies.yml',
|
257
|
+
meta_or_normal=meta_or_normal, **c))
|
124
258
|
resp.mimetype = "text/plain"
|
125
259
|
|
126
260
|
return resp
|
@@ -170,7 +304,8 @@ class UserView(FlaskView):
|
|
170
304
|
if request.method == 'HEAD':
|
171
305
|
resp = ""
|
172
306
|
else:
|
173
|
-
resp = render_template(
|
307
|
+
resp = render_template(
|
308
|
+
'clash_config.yml', typ=typ, meta_or_normal=meta_or_normal, **c, hash=hash_rnd)
|
174
309
|
|
175
310
|
return add_headers(resp, c)
|
176
311
|
|
@@ -210,7 +345,8 @@ class UserView(FlaskView):
|
|
210
345
|
if request.method == 'HEAD':
|
211
346
|
resp = ""
|
212
347
|
else:
|
213
|
-
|
348
|
+
# render_template('all_configs.txt', **c, base64=do_base_64)
|
349
|
+
resp = link_maker.make_v2ray_configs(**c)
|
214
350
|
|
215
351
|
# res = ""
|
216
352
|
# for line in resp.split("\n"):
|
@@ -262,7 +398,8 @@ def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
|
|
262
398
|
default_asn = request.args.get("asn")
|
263
399
|
if filter_domain:
|
264
400
|
domain = filter_domain
|
265
|
-
db_domain = Domain.query.filter(Domain.domain == domain).first() or Domain(
|
401
|
+
db_domain = Domain.query.filter(Domain.domain == domain).first() or Domain(
|
402
|
+
domain=domain, mode=DomainType.direct, cdn_ip='', show_domains=[], child_id=0)
|
266
403
|
domains = [db_domain]
|
267
404
|
else:
|
268
405
|
domain = urlparse(request.base_url).hostname if not no_domain else None
|
@@ -284,7 +421,8 @@ def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
|
|
284
421
|
domains = Domain.query.all()
|
285
422
|
elif mode == 'new':
|
286
423
|
# db_domain=Domain.query.filter(Domain.domain==domain).first()
|
287
|
-
domains = db_domain.show_domains or Domain.query.filter(
|
424
|
+
domains = db_domain.show_domains or Domain.query.filter(
|
425
|
+
Domain.sub_link_only != True).all()
|
288
426
|
else:
|
289
427
|
|
290
428
|
domains = [db_domain]
|
@@ -309,8 +447,10 @@ def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
|
|
309
447
|
d.has_auto_ip = False
|
310
448
|
if d.mode == DomainType.auto_cdn_ip or d.cdn_ip:
|
311
449
|
has_auto_cdn = True
|
312
|
-
d.has_auto_ip = d.mode == DomainType.auto_cdn_ip or (
|
313
|
-
|
450
|
+
d.has_auto_ip = d.mode == DomainType.auto_cdn_ip or (
|
451
|
+
d.cdn_ip and "MTN" in d.cdn_ip)
|
452
|
+
d.cdn_ip = clean_ip.get_clean_ip(
|
453
|
+
d.cdn_ip, d.mode == DomainType.auto_cdn_ip, default_asn)
|
314
454
|
print("autocdn ip mode ", d.cdn_ip)
|
315
455
|
if "*" in d.domain:
|
316
456
|
d.domain = d.domain.replace("*", hiddify.get_random_string(5, 15))
|
@@ -321,9 +461,6 @@ def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
|
|
321
461
|
UserMode.monthly: 30
|
322
462
|
|
323
463
|
}
|
324
|
-
bot = None
|
325
|
-
if hconfig(ConfigEnum.license):
|
326
|
-
from hiddifypanel.panel.telegrambot import bot
|
327
464
|
|
328
465
|
g.locale = hconfig(ConfigEnum.lang)
|
329
466
|
expire_days = remaining_days(user)
|
@@ -333,7 +470,8 @@ def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
|
|
333
470
|
if reset_days >= expire_days:
|
334
471
|
reset_days = 1000
|
335
472
|
# print(reset_days,expire_days,reset_days<=expire_days)
|
336
|
-
expire_s = int((datetime.date.today(
|
473
|
+
expire_s = int((datetime.date.today(
|
474
|
+
)+datetime.timedelta(days=expire_days)-datetime.date(1970, 1, 1)).total_seconds())
|
337
475
|
|
338
476
|
user_ip = clean_ip.get_real_user_ip()
|
339
477
|
asn = clean_ip.get_asn_short_name(user_ip)
|
@@ -360,7 +498,7 @@ def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
|
|
360
498
|
'ConfigEnum': ConfigEnum,
|
361
499
|
'link_maker': link_maker,
|
362
500
|
'domains': domains,
|
363
|
-
"bot": bot,
|
501
|
+
"bot": g.bot,
|
364
502
|
"db_domain": db_domain,
|
365
503
|
"telegram_enable": hconfig(ConfigEnum.telegram_enable) and any([d for d in domains if d.mode in [DomainType.direct, DomainType.relay, DomainType.old_xtls_direct]]),
|
366
504
|
"ip": user_ip,
|
@@ -375,7 +513,8 @@ def add_headers(res, c):
|
|
375
513
|
resp = Response(res)
|
376
514
|
resp.mimetype = "text/plain"
|
377
515
|
resp.headers['Subscription-Userinfo'] = f"upload=0;download={c['usage_current_b']};total={c['usage_limit_b']};expire={c['expire_s']}"
|
378
|
-
resp.headers['profile-web-page-url'] = request.base_url.rsplit(
|
516
|
+
resp.headers['profile-web-page-url'] = request.base_url.rsplit(
|
517
|
+
'/', 1)[0].replace("http://", "https://")+"/"
|
379
518
|
|
380
519
|
if hconfig(ConfigEnum.branding_site):
|
381
520
|
resp.headers['support-url'] = hconfig(ConfigEnum.branding_site)
|
@@ -119,9 +119,15 @@
|
|
119
119
|
<li class="nav-item d-none">
|
120
120
|
<a href="https://t.me/hiddify" target="_blank" class="nav-link">{{icon('brands','telegram','nav-icon')+_('admin.menu.telegram')}}</a>
|
121
121
|
</li>
|
122
|
+
<li class="nav-item">
|
123
|
+
{% set issue_link = generate_github_issue_link_for_admin_sidebar() %}
|
124
|
+
<li class="nav-item">
|
125
|
+
<a href="{{issue_link}}" target="_blank" class=" nav-link">{{icon('solid','bug','nav-icon')+_('Bug')}}</a>
|
126
|
+
</li>
|
127
|
+
</li>
|
122
128
|
<li class="nav-item">
|
123
129
|
<a class="nav-item nav-link" role="button" data-toggle="modal" data-target="#modal-donation">
|
124
|
-
|
130
|
+
{{icon('solid','bug','nav-icon')+_("Donation.title")}}
|
125
131
|
</a>
|
126
132
|
</li>
|
127
133
|
</div>
|
Binary file
|