Compare commits

...

45 Commits

Author SHA1 Message Date
mercury 1d69729bf1 update version 2024-11-09 21:35:43 +04:00
mercury 387f1618b1 ~ip~ tag for templates 2024-11-06 23:19:51 +04:00
mercury 9da11e2b35 fix adguard password 2024-11-06 23:06:06 +04:00
mercury 0b95c75005 timeout for check status adguard 2024-11-06 22:35:32 +04:00
mercury 62c4314beb docker installation 2024-11-05 18:35:31 +04:00
mercury 1dfb3da089 update version 2024-11-04 19:44:47 +04:00
mercury 7358730864 fix update script 2024-11-04 19:37:12 +04:00
mercury 57cd1019f5 fix restart 2024-11-04 19:34:41 +04:00
mercury dfbcd67f83 restart button 2024-11-04 19:23:15 +04:00
mercury 5016c6bda3 ability to enable/disable ports 2024-11-04 19:06:42 +04:00
mercury bc3914c3b9 json beautifier when saving template 2024-11-04 17:33:15 +04:00
mercury 4675371f19 update version 2024-11-04 11:50:10 +04:00
mercury 6efe31d404 you can change the position and name of the outbound, filled in by the bot 2024-11-04 01:14:55 +04:00
mercury 700bb96706 update version 2024-11-04 00:19:17 +04:00
mercury 30ae9ba2ea ability to create and edit templates
directly in telegram
2024-11-04 00:06:12 +04:00
mercury 4e92d96812 change the default domain for reality 2024-11-03 23:13:56 +04:00
mercury bd7a75d6c9 select outbound for rule 2024-11-03 23:12:00 +04:00
mercury 8c666fd284 fix cyclic installation of ssl with an empty domain 2024-11-02 21:48:57 +04:00
mercury 442fbe5105 adguardhome status and reset button 2024-11-02 21:47:45 +04:00
mercury 53392f4cb2 метки для шаблонов 2024-10-31 00:15:00 +04:00
mercury 4ef0de6e1c ability to download origin template 2024-10-30 23:16:17 +04:00
mercury 1cf24407c0 nip.io button to quickly change domain 2024-10-30 22:39:55 +04:00
mercury d3470bd8ea update version 2024-10-27 01:53:55 +04:00
mercury 1fcddf49e3 fixup! fixup! fix warp update 2024-10-27 01:42:25 +04:00
mercury a0d9bada2b fixup! fix warp update 2024-10-27 01:32:13 +04:00
mercury 32109c4526 fix warp update 2024-10-27 01:12:29 +04:00
mercury ca37736cd5 fix menu rulesset with empty rules 2024-10-26 23:14:03 +04:00
mercury 1c4fff50d1 fix menu warp after update 2024-10-26 22:47:43 +04:00
mercury 6ffb4d0a79 update version 2024-10-26 22:41:07 +04:00
mercury 394062cbe0 fix warp off after update 2024-10-26 22:29:07 +04:00
mercury dd8897575f fix warp off after update 2024-10-26 22:18:36 +04:00
mercury 9ab05de320 fix update menu 2024-10-26 21:58:10 +04:00
legiz-ru 71f7db5bac update singbox 1.10.1 windows x64 (#26) 2024-10-26 19:47:15 +04:00
mercury 237da68f14 duplicate the rulesset list in the message 2024-10-26 14:44:06 +04:00
mercury 961ebf3423 xray->routes->proxy <=> Pac 2024-10-25 21:02:58 +04:00
mercury ddcaea751f update version 2024-10-25 18:43:32 +04:00
mercury ce8cdac7c7 Fix for auto-backup not triggering on the first tick 2024-10-25 18:36:54 +04:00
mercury 00aae6c2f7 adguard: list of allowed clients 2024-10-25 18:12:05 +04:00
mercury 89c0139ef6 show safe search status 2024-10-25 17:38:50 +04:00
mercury c57053c8a0 copyable warp key 2024-10-25 17:14:52 +04:00
mercury 3cc16469ff warp registration delete before off 2024-10-25 17:11:46 +04:00
mercury e06544b00f update version 2024-10-24 23:45:25 +04:00
mercury c5b7e1ffdc warp registration fix 2024-10-24 23:15:44 +04:00
mercury 7d21937f04 ability to override i18n 2024-10-24 22:32:16 +04:00
mercury 16138648ca fix openconnect link 2024-10-24 21:54:37 +04:00
22 changed files with 1426 additions and 176 deletions
+3 -1
View File
@@ -20,4 +20,6 @@ update/*
!update/update.sh
override.env
override.html
override.html
override.php
docker-compose.override.yml
+414 -114
View File
@@ -142,9 +142,21 @@ class Bot
case preg_match('~^/autoupdate$~', $this->input['message'], $m):
$this->autoupdate();
break;
case preg_match('~^/ports$~', $this->input['callback'], $m):
$this->ports();
break;
case preg_match('~^/adgFillAllowedClients(?: (\d+))?$~', $this->input['callback'], $m):
$this->adgFillAllowedClients($m[1] ?: false);
break;
case preg_match('~^/appOutbound$~', $this->input['callback'], $m):
$this->appOutbound();
break;
case preg_match('~^/domainsOutbound$~', $this->input['callback'], $m):
$this->domainsOutbound();
break;
case preg_match('~^/finalOutbound$~', $this->input['callback'], $m):
$this->finalOutbound();
break;
case preg_match('~^/processOutbound$~', $this->input['callback'], $m):
$this->processOutbound();
break;
@@ -172,6 +184,9 @@ class Bot
case preg_match('~^/exportList (\w+)$~', $this->input['callback'], $m):
$this->exportList($m[1]);
break;
case preg_match('~^/hidePort (\w+)$~', $this->input['callback'], $m):
$this->hidePort($m[1]);
break;
case preg_match('~^/deleteYes (\w+)$~', $this->input['callback'], $m):
$this->deleteYes($m[1]);
break;
@@ -184,6 +199,9 @@ class Bot
case preg_match('~^/applyupdatebot$~', $this->input['callback'], $m):
$this->applyupdatebot();
break;
case preg_match('~^/restart$~', $this->input['callback'], $m):
$this->restart();
break;
case preg_match('~^/branches$~', $this->input['callback'], $m):
$this->branches();
break;
@@ -286,9 +304,6 @@ class Bot
case preg_match('~^/checkdns$~', $this->input['callback'], $m):
$this->checkdns();
break;
case preg_match('~^/resetnginx$~', $this->input['callback'], $m):
$this->resetnginx();
break;
case preg_match('~^/adguardpsswd$~', $this->input['callback'], $m):
$this->adguardpsswd();
break;
@@ -398,6 +413,9 @@ class Bot
case preg_match('~^/deldomain$~', $this->input['callback'], $m):
$this->delDomain();
break;
case preg_match('~^/addNipdomain$~', $this->input['callback'], $m):
$this->addNipdomain();
break;
case preg_match('~^/(?P<action>change|delete)(?P<typelist>\w+) (?P<arg>\d+)$~', $this->input['callback'], $m):
$this->listPacChange($m['typelist'], $m['action'], $m['arg']);
break;
@@ -434,6 +452,9 @@ class Bot
case preg_match('~^/xtlswarp(?: (\d+))?$~', $this->input['callback'], $m):
$this->xtlswarp($m[1] ?: 0);
break;
case preg_match('~^/xtlsproxy(?: (\d+))?$~', $this->input['callback'], $m):
$this->xtlsproxy($m[1] ?: 0);
break;
case preg_match('~^/xtlsapp(?: (\d+))?$~', $this->input['callback'], $m):
$this->xtlsapp($m[1] ?: 0);
break;
@@ -443,9 +464,15 @@ class Bot
case preg_match('~^/xtlsrulesset(?: (\d+))?$~', $this->input['callback'], $m):
$this->xtlsrulesset($m[1] ?: 0);
break;
case preg_match('~^/templateCopy (\w+)(?: (.+))?$~', $this->input['callback'], $m):
$this->templateCopy($m[1], $m[2]);
break;
case preg_match('~^/delTemplate (\w+)(?: (.+))?$~', $this->input['callback'], $m):
$this->delTemplate($m[1], $m[2]);
break;
case preg_match('~^/downloadOrigin (\w+)$~', $this->input['callback'], $m):
$this->downloadOrigin($m[1]);
break;
case preg_match('~^/downloadTemplate (\w+)(?: (.+))?$~', $this->input['callback'], $m):
$this->downloadTemplate($m[1], $m[2]);
break;
@@ -1063,17 +1090,18 @@ class Bot
public function cron()
{
$period = 10;
while (true) {
$this->shutdownClient();
$this->shutdownClientXr();
$this->checkVersion();
$this->checkBackup();
$this->checkBackup($period);
$this->checkCert();
sleep(10);
sleep($period);
}
}
public function checkBackup()
public function checkBackup($delta)
{
$c = $this->getPacConf();
if (!empty($c['backup'])) {
@@ -1085,8 +1113,8 @@ class Bot
!empty($start)
&& !empty($period)
&& empty($this->backup)
&& $now - $start >= $period
&& ($now - $start) % $period < 10
&& $now - $start >= 0
&& (($now - $start) % $period < $delta)
) {
if (!empty($c['pinbackup'])) {
$this->pinAdmin($c['pinbackup'], 1);
@@ -1758,6 +1786,11 @@ class Bot
}
}
public function addNipdomain()
{
$this->addDomain(str_replace('.', '-', $this->ip) . '.nip.io');
}
public function addDomain($domain, $nomenu = false)
{
$domain = trim($domain);
@@ -1806,7 +1839,7 @@ class Bot
$this->input['chat'] = $c['admin'][0];
$this->input['message_id'] = $r['result']['message_id'];
$this->input['callback_id'] = false;
if (empty($p['domain'])) {
if (empty($p)) {
$this->addDomain(str_replace('.', '-', $this->ip) . '.nip.io', 1);
$this->setSSL('letsencrypt');
}
@@ -2052,25 +2085,22 @@ class Bot
];
}
public function resetnginx()
public function adguardSync()
{
$nginx = file_get_contents('/config/nginx.conf');
$default = file_get_contents('/config/nginx_default.conf');
file_put_contents('/config/nginx.conf', $default);
$u = $this->ssh("nginx -t 2>&1", 'ng');
$out[] = $u;
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
if (preg_match('~test is successful~', $u)) {
$out[] = $this->ssh("nginx -s reload 2>&1", 'ng');
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
$conf = $this->getPacConf();
unset($conf['domain']);
$this->setPacConf($conf);
} else {
file_put_contents('/config/nginx.conf', $nginx);
$pac = $this->getPacConf();
$pac['adpswd'] = $pac['adpswd'] ?: substr(hash('md5', time()), 0, 10);
$this->setPacConf($pac);
$ssl = $this->nginxGetTypeCert();
$c = yaml_parse_file($this->adguard);
$this->stopAd();
$c['users'][0]['password'] = password_hash($pac['adpswd'], PASSWORD_DEFAULT);
if (!empty($ssl) && !empty($pac['domain']) && empty($c['tls']['enabled'])) {
$c['tls']['enabled'] = true;
$c['tls']['server_name'] = $pac['domain'];
}
sleep(5);
$this->menu('config');
yaml_emit_file($this->adguard, $c);
$this->startAd();
$this->adguardProtect();
}
public function adguardpsswd()
@@ -2241,7 +2271,12 @@ class Bot
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
$out[] = $this->stopAd();
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
$this->adguardChangePswd($pass);
$c = yaml_parse_file($this->adguard);
$c['users'][0]['password'] = password_hash($pass, PASSWORD_DEFAULT);
yaml_emit_file($this->adguard, $c);
$p = $this->getPacConf();
$p['adpswd'] = $pass;
$this->setPacConf($p);
$out[] = $this->startAd();
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
sleep(3);
@@ -2252,12 +2287,8 @@ class Bot
{
$out[] = 'Restart Adguard Home';
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
$out[] = $this->stopAd();
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
$c = yaml_parse_file($this->adguard);
yaml_emit_file($this->adguard, $c);
$out[] = $this->startAd();
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
exec('git -C / checkout config/AdGuardHome.yaml');
$this->adguardSync();
sleep(3);
$this->menu('adguard');
}
@@ -2466,7 +2497,10 @@ DNS-over-HTTPS with IP:
{
switch ($type) {
case 'includelist':
$this->pacUpdate();
$this->pacUpdate($_SESSION['proxylistentry']);
if (!empty($_SESSION['proxylistentry'])) {
$this->xtlsproxy();
}
break;
case 'blocklist':
$this->xrayUpdateRules();
@@ -3346,6 +3380,7 @@ DNS-over-HTTPS with IP:
public function pacMenu($page = 0)
{
unset($_SESSION['proxylistentry']);
$rmpac = stat(__DIR__ . '/zapretlists/rmpac');
$rpac = stat(__DIR__ . '/zapretlists/rpac');
$mpac = stat(__DIR__ . '/zapretlists/mpac');
@@ -3426,7 +3461,7 @@ DNS-over-HTTPS with IP:
'callback_data' => "/addCommunityFilter",
],
];
$data = array_merge($data, $this->listPac('includelist', $page, 'pacMenu'));
$data = array_merge($data, $this->listPac('includelist', $page, 'pacMenu')[0]);
$data[] = [
[
'text' => $this->i18n('back'),
@@ -3565,7 +3600,7 @@ DNS-over-HTTPS with IP:
{
$text[] = "Menu -> " . $this->i18n('xray') . ' -> ' . $this->i18n('routes') . ' -> block list';
$data = $this->listPac('blocklist', $page, 'xtlsblock');
[$data] = $this->listPac('blocklist', $page, 'xtlsblock');
$data[] = [
[
'text' => $this->i18n('back'),
@@ -3584,7 +3619,33 @@ DNS-over-HTTPS with IP:
{
$text[] = "Menu -> " . $this->i18n('xray') . ' -> ' . $this->i18n('routes') . ' -> warp list';
$data = $this->listPac('warplist', $page, 'xtlswarp');
[$data] = $this->listPac('warplist', $page, 'xtlswarp');
$data[] = [
[
'text' => $this->i18n('back'),
'callback_data' => "/routes",
],
];
$this->update(
$this->input['chat'],
$this->input['message_id'],
implode("\n", $text ?: ['...']),
$data ?: false,
);
}
public function xtlsproxy($page = 0)
{
$_SESSION['proxylistentry'] = 1;
$p = $this->getPacConf();
$text[] = "Menu -> " . $this->i18n('xray') . ' -> ' . $this->i18n('routes') . ' -> proxy list';
[$data] = $this->listPac('includelist', $page, 'xtlsproxy');
$data[] = [
[
'text' => 'set to ' . ($p['domains_outbound'] ? 'proxy' : 'direct'),
'callback_data' => "/domainsOutbound",
],
];
$data[] = [
[
'text' => $this->i18n('back'),
@@ -3607,6 +3668,22 @@ DNS-over-HTTPS with IP:
$this->xtlsapp();
}
public function domainsOutbound()
{
$p = $this->getPacConf();
$p['domains_outbound'] = !$p['domains_outbound'];
$p = $this->setPacConf($p);
$this->xtlsproxy();
}
public function finalOutbound()
{
$p = $this->getPacConf();
$p['final_outbound'] = !$p['final_outbound'];
$p = $this->setPacConf($p);
$this->routes();
}
public function processOutbound()
{
$p = $this->getPacConf();
@@ -3619,7 +3696,7 @@ DNS-over-HTTPS with IP:
{
$text[] = "Menu -> " . $this->i18n('xray') . ' -> ' . $this->i18n('routes') . ' -> package list';
$data = $this->listPac('packagelist', $page, 'xtlsapp');
[$data] = $this->listPac('packagelist', $page, 'xtlsapp');
$p = $this->getPacConf();
$data[] = [
[
@@ -3645,7 +3722,7 @@ DNS-over-HTTPS with IP:
{
$text[] = "Menu -> " . $this->i18n('xray') . ' -> ' . $this->i18n('routes') . ' -> process list';
$data = $this->listPac('processlist', $page, 'xtlsprocess');
[$data] = $this->listPac('processlist', $page, 'xtlsprocess');
$p = $this->getPacConf();
$data[] = [
[
@@ -3671,7 +3748,8 @@ DNS-over-HTTPS with IP:
{
$text[] = "Menu -> " . $this->i18n('xray') . ' -> ' . $this->i18n('routes') . ' -> rulesset list';
$data = $this->listPac('rulessetlist', $page, 'xtlsrulesset', 1);
[$data, $tmp] = $this->listPac('rulessetlist', $page, 'xtlsrulesset', 1);
$text = array_merge($text, $tmp ?: []);
$data[] = [
[
'text' => $this->i18n('back'),
@@ -3702,6 +3780,9 @@ DNS-over-HTTPS with IP:
$domains = array_slice($domains, $page * $this->limit, $this->limit, true);
$i = 0;
foreach ($domains as $k => $v) {
if ($type == 'rulessetlist') {
$text[] = "<blockquote><code>$k</code></blockquote>";
}
$data[] = [
[
'text' => $this->i18n($v ? 'on' : 'off') . ' ' . ($basename ? basename($k) . ' ' : '') . (in_array($type, ['rulessetlist', 'packagelist', 'processlist']) ? $k : idn_to_utf8($k)),
@@ -3748,7 +3829,7 @@ DNS-over-HTTPS with IP:
],
];
}
return $data;
return [$data, $text];
}
public function listPacChange($type, $action, $key)
@@ -3928,7 +4009,7 @@ DNS-over-HTTPS with IP:
[
[
'text' => $this->i18n('chat'),
'url' => "https://t.me/+BYuWVd36cZYwNTMy",
'url' => "https://t.me/+Wfxg6-nrokBlMmYy",
],
[
'text' => $this->i18n('donate'),
@@ -4159,7 +4240,7 @@ DNS-over-HTTPS with IP:
$expose = $m[1];
$pass = htmlspecialchars($pac['ocserv']);
$text[] = "Menu -> OpenConnect";
if (!empty($m[1])) {
if (!empty($cs)) {
$text[] = "<code>https://oc.$domain/?$cs</code>";
}
$text[] = "password: <span class='tg-spoiler'>$pass</span>";
@@ -4347,6 +4428,22 @@ DNS-over-HTTPS with IP:
];
}
public function templateCopy($type)
{
$r = $this->send(
$this->input['chat'],
"@{$this->input['username']} send the template name",
$this->input['message_id'],
reply: 'send the template name',
);
$_SESSION['reply'][$r['result']['message_id']] = [
'start_message' => $this->input['message_id'],
'start_callback' => $this->input['callback_id'],
'callback' => 'copyTemplate',
'args' => [$type],
];
}
public function addTemplate($n, $type)
{
if (empty($this->input['caption'])) {
@@ -4365,6 +4462,30 @@ DNS-over-HTTPS with IP:
$this->templates($type);
}
public function saveTemplate($name, $type, $json)
{
if (json_decode($json, true) === false) {
return [
'status' => false,
'message' => 'wrong format',
];
}
$pac = $this->getPacConf();
switch ($name) {
case 'origin':
file_put_contents("/config/$type.json", json_encode(json_decode($json, true), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
break;
default:
$pac["{$type}templates"][$name] = json_decode($json, true);
break;
}
$this->setPacConf($pac);
return [
'status' => true,
];
}
public function delTemplate($type, $name)
{
$pac = $this->getPacConf();
@@ -4373,6 +4494,27 @@ DNS-over-HTTPS with IP:
$this->templates($type);
}
public function copyTemplate($name, $type)
{
$pac = $this->getPacConf();
$pac["{$type}templates"][$name] = json_decode(file_get_contents("/config/$type.json"), true);
$this->setPacConf($pac);
$this->templates($type);
}
public function downloadOrigin($type)
{
switch ($type) {
case 'sing':
$f = new \CURLFile('/config/sing.json', 'application/json', 'origin.json');
break;
case 'v2ray':
$f = new \CURLFile('/config/v2ray.json', 'application/json', 'origin.json');
break;
}
$this->sendFile($this->input['chat'], $f);
}
public function downloadTemplate($type, $name)
{
$pac = $this->getPacConf();
@@ -4411,6 +4553,14 @@ DNS-over-HTTPS with IP:
'text' => "origin",
'web_app' => ['url' => "https://$domain/pac?h=$hash&t=te&ty=$type"],
],
[
'text' => $this->i18n('download'),
'callback_data' => "/downloadOrigin $type",
],
[
'text' => $this->i18n('copy'),
'callback_data' => "/templateCopy $type",
],
[
'text' => $this->i18n($pac["default{$type}template"] && !empty($pac["{$type}templates"][base64_decode($pac["default{$type}template"])]) ? 'off' : 'on'),
'callback_data' => "/defaultTemplate $type",
@@ -4419,7 +4569,7 @@ DNS-over-HTTPS with IP:
foreach ($templates as $k => $v) {
$data[] = [
[
'text' => "$k",
'text' => $k,
'web_app' => ['url' => "https://$domain/pac?h=$hash&t=te&ty=$type&te=" . urlencode($k)],
],
[
@@ -4576,6 +4726,9 @@ DNS-over-HTTPS with IP:
{
$text[] = "Menu -> " . $this->i18n('xray') . ' -> routes';
$p = $this->getPacConf();
$outbound = $p['outbound'] ?: 'proxy';
$data = [
[[
'text' => $this->i18n('block'),
@@ -4586,16 +4739,24 @@ DNS-over-HTTPS with IP:
'callback_data' => "/xtlswarp",
]],
[[
'text' => $this->i18n('process'),
'text' => $this->i18n('rulesset'),
'callback_data' => "/xtlsrulesset",
]],
[[
'text' => 'domains: ' . ($p['domains_outbound'] ? 'direct' : $outbound),
'callback_data' => "/xtlsproxy",
]],
[[
'text' => 'process: ' . ($p['process_outbound'] ? 'direct' : $outbound),
'callback_data' => "/xtlsprocess",
]],
[[
'text' => $this->i18n('package'),
'text' => 'package: ' . ($p['app_outbound'] ? 'direct' : $outbound),
'callback_data' => "/xtlsapp",
]],
[[
'text' => $this->i18n('rulesset'),
'callback_data' => "/xtlsrulesset",
'text' => 'final: ' . ($p['final_outbound'] ? $outbound : 'direct'),
'callback_data' => "/finalOutbound",
]],
];
$data[] = [
@@ -4654,23 +4815,33 @@ DNS-over-HTTPS with IP:
public function offWarp()
{
$p = $this->getPacConf();
if (empty($p['warpoff'])) {
$this->ssh('pkill warp-svc', 'wp');
$p['warpoff'] = 1;
} else {
$p = $this->getPacConf();
if (!empty($this->selfupdate)) {
if (!empty($p['warpoff'])) {
$this->ssh('warp-cli --accept-tos registration delete 2>&1', 'wp');
$this->ssh('pkill warp-svc', 'wp');
}
} elseif (!empty($p['warpoff'])) {
$this->ssh('warp-svc > /dev/null 2>&1 &', 'wp');
sleep(3);
$this->send($this->input['chat'], 'Registration: ' . $this->ssh('warp-cli --accept-tos registration new 2>&1', 'wp'));
if (!empty($p['warp'])) {
$this->send($this->input['chat'], 'License: ' . $this->ssh("warp-cli --accept-tos registration license {$p['warp']} 2>&1", 'wp'));
if (empty($this->ssh('[ -f "/var/lib/cloudflare-warp/conf.json" ] && echo 1', 'wp'))) {
$this->send($this->input['chat'], 'Registration: ' . $this->ssh('warp-cli --accept-tos registration new 2>&1', 'wp'));
if (!empty($p['warp'])) {
$this->send($this->input['chat'], 'License: ' . $this->ssh("warp-cli --accept-tos registration license {$p['warp']} 2>&1", 'wp'));
}
}
$this->send($this->input['chat'], 'Proxy mode: ' . $this->ssh('warp-cli --accept-tos mode proxy 2>&1', 'wp'));
$this->send($this->input['chat'], 'Connect: ' . $this->ssh('warp-cli --accept-tos connect 2>&1', 'wp'));
unset($p['warpoff']);
} else {
$this->send($this->input['chat'], 'Registration delete: ' . $this->ssh('warp-cli --accept-tos registration delete 2>&1', 'wp'));
$this->ssh('pkill warp-svc', 'wp');
$p['warpoff'] = 1;
}
$this->setPacConf($p);
$this->warp();
if (empty($this->selfupdate)) {
$this->warp();
}
}
public function warp()
@@ -4678,7 +4849,7 @@ DNS-over-HTTPS with IP:
$p = $this->getPacConf();
$text[] = "Menu -> " . $this->i18n('warp');
$text[] = "status: " . $this->warpStatus();
$text[] = "key: " . $this->getPacConf()['warp'];
$text[] = "key: <code>{$this->getPacConf()['warp']}</code>";
$data[] = [
[
'text' => $this->i18n($p['warpoff'] ? 'off' : 'on'),
@@ -4953,15 +5124,26 @@ DNS-over-HTTPS with IP:
break;
}
$outbound = $pac['outbound'] ?: 'proxy';
$c = json_decode($this->replaceTags(json_encode($c), [
'~outbound~' => $outbound,
]), true);
foreach ($c['outbounds'] as $k => $v) {
if ($v['tag'] == $outbound) {
$index = $k;
break;
}
}
switch ($_GET['t']) {
case 's':
$c['outbounds'][0]['settings']['vnext'][0]['address'] = '~domain~';
$c['outbounds'][0]['settings']['vnext'][0]['users'][0] = [
$c['outbounds'][$index]['settings']['vnext'][0]['address'] = '~domain~';
$c['outbounds'][$index]['settings']['vnext'][0]['users'][0] = [
'id' => '~uid~',
'encryption' => 'none',
];
if ($pac['transport'] == 'Websocket') {
$c['outbounds'][0]['streamSettings'] = [
$c['outbounds'][$index]['streamSettings'] = [
"network" => "ws",
"security" => "tls",
"wsSettings" => [
@@ -4973,10 +5155,10 @@ DNS-over-HTTPS with IP:
"fingerprint" => "chrome"
]
];
unset($c['outbounds'][0]['mux']);
unset($c['outbounds'][$index]['mux']);
} else {
$c['outbounds'][0]['settings']['vnext'][0]['users'][0]["flow"] = "xtls-rprx-vision";
$c['outbounds'][0]['streamSettings'] = [
$c['outbounds'][$index]['settings']['vnext'][0]['users'][0]["flow"] = "xtls-rprx-vision";
$c['outbounds'][$index]['streamSettings'] = [
"network" => "tcp",
"security" => "reality",
"realitySettings" => [
@@ -4986,29 +5168,29 @@ DNS-over-HTTPS with IP:
"shortId" => '~short_id~',
]
];
$c['outbounds'][0]['mux'] = [
$c['outbounds'][$index]['mux'] = [
"enabled" => false,
"concurrency" => -1
];
}
break;
case 'si':
$c['outbounds'][0]['server'] = '~domain~';
$c['outbounds'][0]['uuid'] = '~uid~';
$c['outbounds'][$index]['server'] = '~domain~';
$c['outbounds'][$index]['uuid'] = '~uid~';
if ($pac['transport'] == 'Websocket') {
unset($c['outbounds'][0]['tls']['reality']);
unset($c['outbounds'][0]['flow']);
$c['outbounds'][0]["transport"] = [
unset($c['outbounds'][$index]['tls']['reality']);
unset($c['outbounds'][$index]['flow']);
$c['outbounds'][$index]["transport"] = [
"type" => "ws",
"path" => "/ws"
];
$c['outbounds'][0]['tls']['server_name'] = '~domain~';
$c['outbounds'][$index]['tls']['server_name'] = '~domain~';
} else {
unset($c['outbounds'][0]["transport"]);
$c['outbounds'][0]['flow'] = 'xtls-rprx-vision';
$c['outbounds'][0]['tls']['reality']['public_key'] = '~public_key~';
$c['outbounds'][0]['tls']['server_name'] = '~server_name~';
$c['outbounds'][0]['tls']['reality']['short_id'] = '~short_id~';
unset($c['outbounds'][$index]["transport"]);
$c['outbounds'][$index]['flow'] = 'xtls-rprx-vision';
$c['outbounds'][$index]['tls']['reality']['public_key'] = '~public_key~';
$c['outbounds'][$index]['tls']['server_name'] = '~server_name~';
$c['outbounds'][$index]['tls']['reality']['short_id'] = '~short_id~';
}
$c['route'] = $this->addRuleSet($c['route']);
@@ -5017,13 +5199,18 @@ DNS-over-HTTPS with IP:
}
$json = $this->replaceTags(json_encode($c), [
'"~pac~"' => json_encode(array_keys(array_filter($pac['includelist'] ?: []))),
'~dns~' => "https://$domain/dns-query/$uid",
'~uid~' => $uid,
'~domain~' => $domain,
'~short_id~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['shortIds'][0],
'~public_key~' => $pac['xray'],
'~server_name~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['serverNames'][0],
'"~pac~"' => json_encode(array_keys(array_filter($pac['includelist'] ?: []))),
'~dns~' => "https://$domain/dns-query/$uid",
'~uid~' => $uid,
'~domain~' => $domain,
'~short_id~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['shortIds'][0],
'~public_key~' => $pac['xray'],
'~server_name~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['serverNames'][0],
'~app_outbound~' => $pac['app_outbound'] ? 'direct' : $outbound,
'~process_outbound~' => $pac['process_outbound'] ? 'direct' : $outbound,
'~domains_outbound~' => $pac['domains_outbound'] ? 'direct' : $outbound,
'~final_outbound~' => $pac['final_outbound'] ? $outbound : 'direct',
'~ip~' => $this->ip,
]);
$json = $this->clearEmptyRules($json);
@@ -5153,11 +5340,6 @@ DNS-over-HTTPS with IP:
"download_detour" => "direct",
];
$route['rules'][$k]['rule_set'][] = $r['name'];
switch (true) {
case preg_match('#~(.+)~#', $route['rules'][$k]['outbound'], $m):
$route['rules'][$k]['outbound'] = $pac[$m[1]] ? 'direct' : 'proxy';
break;
}
}
unset($route['rules'][$k]['createruleset']);
if (empty($route['rules'][$k]['rule_set'])) {
@@ -5260,23 +5442,6 @@ DNS-over-HTTPS with IP:
];
}
public function adguardCheckPswd()
{
if (empty($this->getPacConf()['adpswd'])) {
$this->adguardChangePswd(substr(hash('md5', time()), 0, 10));
}
}
public function adguardChangePswd($pass)
{
$c = yaml_parse_file($this->adguard);
$c['users'][0]['password'] = password_hash($pass, PASSWORD_DEFAULT);
yaml_emit_file($this->adguard, $c);
$p = $this->getPacConf();
$p['adpswd'] = $pass;
$this->setPacConf($p);
}
public function adguardProtect()
{
$h = substr(hash('sha256', $this->key), 0, 8);
@@ -5327,6 +5492,12 @@ DNS-over-HTTPS with IP:
$text .= "DNS over HTTPS:\n<code>$ip</code>\n<code>$scheme://$domain/dns-query" . ($conf['adguardkey'] ? "/{$conf['adguardkey']}" : '') . "</code>\n\n";
$text .= "DNS over TLS:\n<code>tls://" . ($conf['adguardkey'] ? "{$conf['adguardkey']}." : '') . "$domain</code>";
}
$status = $this->i18n(exec("JSON=1 timeout 2 dnslookup google.com ad") ? 'on' : 'off');
$safesearch = yaml_parse_file($this->adguard)['filtering']['safe_search']['enabled'];
$text .= "\n\nstatus: $status\t\tsafesearch: " . $this->i18n($safesearch ? 'on' : 'off');
$allowedClients = yaml_parse_file($this->adguard)['dns']['allowed_clients'];
$text .= $allowedClients ? "\n\nallowed clients: \n - " . implode("\n - ", $allowedClients) : '';
$data = [
[
[
@@ -5353,13 +5524,29 @@ DNS-over-HTTPS with IP:
];
$data[] = [
[
'text' => $this->i18n('add upstream'),
'callback_data' => "/addupstream",
'text' => $this->i18n('fill allowed clients'),
'callback_data' => "/adgFillAllowedClients 0",
],
[
'text' => $this->i18n('delete allowed clients'),
'callback_data' => "/adgFillAllowedClients 1",
],
];
$data[] = [
[
'text' => $this->i18n('check DNS'),
'callback_data' => "/checkdns",
],
[
'text' => $this->i18n('reset settings'),
'callback_data' => "/adguardreset",
],
];
$data[] = [
[
'text' => $this->i18n('add upstream'),
'callback_data' => "/addupstream",
],
];
$upstreams = yaml_parse_file($this->adguard)['dns']['upstream_dns'];
if (!empty($upstreams)) {
@@ -5388,6 +5575,35 @@ DNS-over-HTTPS with IP:
];
}
public function adgFillAllowedClients($delete = false)
{
$pac = $this->getPacConf();
$out[] = 'Restart Adguard Home';
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
$this->stopAd();
$c = yaml_parse_file($this->adguard);
if (!empty($delete)) {
unset($c['dns']['allowed_clients']);
} else {
$c['dns']['allowed_clients'] = [];
$c['dns']['allowed_clients'][] = '10.10.0.0/24';
if (!empty($pac['adguardKey'])) {
$c['dns']['allowed_clients'][] = $pac['adguardKey'];
}
$c['dns']['allowed_clients'][] = getenv('WGADDRESS');
$c['dns']['allowed_clients'][] = getenv('WG1ADDRESS');
$c['dns']['allowed_clients'][] = '10.0.2.0/24'; // openconnect
if (!empty($xr = $this->getXray())) {
foreach ($xr['inbounds'][0]['settings']['clients'] as $v) {
$c['dns']['allowed_clients'][] = $v['id'];
}
}
}
yaml_emit_file($this->adguard, $c);
$this->startAd();
$this->menu('adguard');
}
public function menuLang()
{
$data = [];
@@ -5463,7 +5679,7 @@ DNS-over-HTTPS with IP:
];
exec("git -C / branch -vv", $mm);
return [
'text' => '<pre><code class="language-shell">' . implode("\n", $mm) . '</code></pre>',
'text' => '<pre><code class="language-shell">' . htmlentities(implode("\n", $mm)) . '</code></pre>',
'data' => $data,
];
}
@@ -5483,6 +5699,20 @@ DNS-over-HTTPS with IP:
$this->delete($this->input['from'], $this->input['message_id']);
}
public function restart()
{
$r = $this->send($this->input['from'], 'restart...');
file_put_contents('/update/reload_message', "{$this->input['from']}:{$r['result']['message_id']}");
file_put_contents('/update/key', $this->key);
file_put_contents('/update/curl', json_encode([
'chat_id' => $this->input['chat'],
'message_id' => $r['result']['message_id'],
'text' => '~t~'
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
file_put_contents('/update/pipe', '2');
$this->delete($this->input['from'], $this->input['message_id']);
}
public function configMenu()
{
exec('git -C / fetch');
@@ -5507,6 +5737,10 @@ DNS-over-HTTPS with IP:
'text' => $this->i18n('+ subdomain'),
'callback_data' => '/addSubdomain',
],
[
'text' => $this->i18n('nip.io'),
'callback_data' => '/addNipdomain',
],
],
];
if ($conf['domain']) {
@@ -5546,12 +5780,6 @@ DNS-over-HTTPS with IP:
];
}
}
/*$data[] = [
[
'text' => $this->i18n('reset nginx'),
'callback_data' => "/resetnginx",
],
];*/
$data[] = [
[
'text' => "{$this->i18n('add')} {$this->i18n('admin')}",
@@ -5612,6 +5840,10 @@ DNS-over-HTTPS with IP:
'text' => $this->i18n('fake html'),
'callback_data' => "/addOverrideHtml",
],
[
'text' => $this->i18n('ports'),
'callback_data' => "/ports",
],
];
$data[] = [
[
@@ -5628,6 +5860,10 @@ DNS-over-HTTPS with IP:
'text' => $this->i18n(exec('git -C / rev-list --count HEAD..@{u}') ? 'have updates' : 'no updates'),
'callback_data' => "/menu update",
],
[
'text' => $this->i18n('restart'),
'callback_data' => "/restart",
],
];
$data[] = [
[
@@ -5641,6 +5877,69 @@ DNS-over-HTTPS with IP:
];
}
public function ports()
{
$text[] = 'Settings -> Ports';
$f = '/docker/compose';
$c = yaml_parse_file($f)['services'];
$data = [
[[
'text' => 'Letsencrypt 80 ' . $this->i18n($c['ng'] ? 'off' : 'on'),
'callback_data' => "/hidePort ng",
]],
[[
'text' => 'Shadowsocks ' . getenv('SSPORT') . ' ' . $this->i18n($c['ss'] ? 'off' : 'on'),
'callback_data' => "/hidePort ss",
]],
[[
'text' => 'DoT 853 ' . $this->i18n($c['ad'] ? 'off' : 'on'),
'callback_data' => "/hidePort ad",
]],
[[
'text' => 'Wireguard-1 ' . getenv('WGPORT') . ' ' . $this->i18n($c['wg'] ? 'off' : 'on'),
'callback_data' => "/hidePort wg",
]],
[[
'text' => 'Wireguard-2 ' . getenv('WG1PORT') . ' ' . $this->i18n($c['wg1'] ? 'off' : 'on'),
'callback_data' => "/hidePort wg1",
]],
[[
'text' => 'MTProto ' . getenv('TGPORT') . ' ' . $this->i18n($c['tg'] ? 'off' : 'on'),
'callback_data' => "/hidePort tg",
]],
];
$data[] = [
[
'text' => $this->i18n('back'),
'callback_data' => "/menu config",
],
];
$this->update(
$this->input['chat'],
$this->input['message_id'],
implode("\n", $text ?: ['...']),
$data ?: false,
);
}
public function hidePort($container)
{
$f = '/docker/compose';
$c = yaml_parse_file($f);
if (!empty($c['services'][$container])) {
unset($c['services'][$container]);
} else {
$c['services'][$container]['ports'] = [];
}
if (empty($c['services'])) {
file_put_contents($f, '');
} else {
yaml_emit_file($f, $c);
file_put_contents($f, str_replace('ports:', 'ports: !override', file_get_contents($f)));
}
$this->ports();
}
public function branches()
{
exec('git -C / branch -r', $m);
@@ -5753,6 +6052,7 @@ DNS-over-HTTPS with IP:
$this->input['message_id'] = $rm[1];
$this->input['callback_id'] = $rm[1];
if (file_exists($this->update)) {
$this->selfupdate = true;
if (!empty($m)) {
$this->send($this->input['chat'], "<pre>$m</pre>", $rm[1]);
}
+30 -2
View File
@@ -282,8 +282,8 @@ $i = [
'ru' => 'пагинация',
],
'exchange' => [
'en' => 'open ip',
'ru' => 'откр айпи',
'en' => 'client isolation',
'ru' => 'изоляция клиентов',
],
'ocserv' => [
'en' => 'OpenConnect',
@@ -345,4 +345,32 @@ $i = [
'en' => 'expose-iroutes',
'ru' => 'изоляция клиентов',
],
'fill allowed clients' => [
'en' => 'fill allowed clients',
'ru' => 'заполнить белый список клиентов',
],
'delete allowed clients' => [
'en' => 'delete allowed clients',
'ru' => 'очистить белый список клиентов',
],
'success' => [
'en' => 'success',
'ru' => 'сохранено',
],
'error' => [
'en' => 'error',
'ru' => 'ошибка',
],
'save' => [
'en' => 'save',
'ru' => 'сохранить',
],
'copy' => [
'en' => 'copy',
'ru' => 'копировать',
],
'restart' => [
'en' => 'restart',
'ru' => 'перезагрузка',
],
];
+67 -4
View File
@@ -11,6 +11,9 @@ if ('POST' == $_SERVER['REQUEST_METHOD'] && $_GET['k'] == $c['key']) {
require __DIR__ . '/calc.php';
require __DIR__ . '/bot.php';
require __DIR__ . '/i18n.php';
if (file_exists(__DIR__ . '/override.php')) {
include __DIR__ . '/override.php';
}
$bot = new Bot($c['key'], $i);
$bot->input();
exit;
@@ -44,8 +47,63 @@ if ($hash == substr(md5($c['key']), 0, 8)) {
$t = json_decode(file_get_contents("/config/{$_GET['ty']}.json"), true);
}
if ($t) {
header('Content-Type: application/json');
echo json_encode($t, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
header('Content-Type: text/html');
$t = json_encode($t, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$name = $_GET['te'] ?: 'origin';
$type = $_GET['ty'];
echo <<<HTML
<!DOCTYPE HTML>
<html lang="en" style="height:100%">
<head>
<!-- when using the mode "code", it's important to specify charset utf-8 -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="jsoneditor.min.css" rel="stylesheet" type="text/css">
<script src="jsoneditor.min.js"></script>
<script src="jquery-3.7.1.min.js"></script>
<script src="https://telegram.org/js/telegram-web-app.js"></script>
</head>
<body style="height:100%">
<div id="jsoneditor" style="height:100%"></div>
<script>
jQuery(function($) {
var tg = window.Telegram.WebApp;
// create the editor
const container = document.getElementById("jsoneditor")
const options = {}
const editor = new JSONEditor(container, options)
editor.set({$t})
tg.MainButton.show().setText('{$bot->i18n('save')}').onClick(function (e) {
var self = this;
$.ajax({
url: '/webapp/save?' + tg.initData,
method: 'POST',
data: {
name: '$name',
type: '$type',
json: editor.getText()
},
dataType: 'json'
}).done(function (r) {
if (r.status == true) {
tg.MainButton.setText('{$bot->i18n('success')}')
setTimeout(() => {
tg.close();
}, 500);
} else {
tg.MainButton.setText(r.message);
}
}).fail(function (r) {
tg.MainButton.setText('{$bot->i18n('error')}')
});
});
});
</script>
</body>
</html>
HTML;
exit;
}
@@ -78,8 +136,13 @@ if (!empty($_GET['hash'])) {
require __DIR__ . '/bot.php';
require __DIR__ . '/i18n.php';
$bot = new Bot($c['key'], $i);
setcookie('c', substr(hash('sha256', $c['key']), 0, 8), 0, '/');
setcookie('a', $bot->adguardBasicAuth(), 0, '/');
if (!empty($_POST['json'])) {
echo json_encode($bot->saveTemplate($_POST['name'], $_POST['type'], $_POST['json']));
die();
} else {
setcookie('c', substr(hash('sha256', $c['key']), 0, 8), 0, '/');
setcookie('a', $bot->adguardBasicAuth(), 0, '/');
}
die('ok');
}
}
-2
View File
@@ -12,7 +12,5 @@ if ($c['debug']) {
$bot = new Bot($c['key'], $i);
$bot->cleanQueue();
$bot->setwebhook();
$bot->adguardCheckPswd();
$bot->adguardProtect();
$bot->syncPortClients();
$bot->setcommands();
+4
View File
@@ -14,6 +14,10 @@ $bot = new Bot($c['key'], $i);
$bot->selfUpdate();
$bot->restartTG();
if (!empty($bot->selfupdate)) {
$bot->offWarp();
}
$bot->dontshowcron = 1;
$bot->adguardSync();
$bot->sslip();
$bot->cleanDocker();
+749
View File
@@ -0,0 +1,749 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="240"
height="144"
id="svg4136"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="jsoneditor-icons.svg">
<title
id="title6512">JSON Editor Icons</title>
<metadata
id="metadata4148">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>JSON Editor Icons</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4146" />
<sodipodi:namedview
pagecolor="#ff63ff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1026"
id="namedview4144"
showgrid="true"
inkscape:zoom="4"
inkscape:cx="13.229181"
inkscape:cy="119.82429"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4136"
showguides="false"
borderlayer="false"
inkscape:showpageshadow="true"
showborder="true">
<inkscape:grid
type="xygrid"
id="grid4640"
empspacing="24" />
</sodipodi:namedview>
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1"
height="16"
width="16"
y="4"
x="4" />
<rect
id="svg_1-7"
height="16"
width="16"
y="3.999995"
x="28.000006"
style="fill:#ec3f29;fill-opacity:0.94117647;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
x="52.000004"
y="3.999995"
width="16"
height="16"
id="rect4165" />
<rect
id="rect4175"
height="16"
width="16"
y="3.9999852"
x="172.00002"
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
id="rect4175-3"
height="16"
width="16"
y="3.999995"
x="196"
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
<g
id="g4299"
style="stroke:none">
<rect
x="7.0000048"
y="10.999998"
width="9.9999924"
height="1.9999986"
id="svg_1-1"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
x="11.000005"
y="7.0000114"
width="1.9999955"
height="9.9999838"
id="svg_1-1-1"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
</g>
<g
id="g4299-3"
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,12.000001)"
style="stroke:none">
<rect
x="7.0000048"
y="10.999998"
width="9.9999924"
height="1.9999986"
id="svg_1-1-0"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
x="11.000005"
y="7.0000114"
width="1.9999955"
height="9.9999838"
id="svg_1-1-1-9"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0" />
</g>
<rect
id="svg_1-7-5"
height="6.9999905"
width="6.9999909"
y="7.0000048"
x="55.000004"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
x="58"
y="10.00001"
width="6.9999909"
height="6.9999905"
id="rect4354" />
<rect
id="svg_1-7-5-7"
height="6.9999905"
width="6.9999909"
y="10.000005"
x="58.000004"
style="fill:#ffffff;fill-opacity:1;stroke:#3c80df;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
<g
id="g4378">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="10.999999"
width="7.9999909"
height="1.9999965"
id="svg_1-7-5-3" />
<rect
id="rect4374"
height="1.9999946"
width="11.999995"
y="7.0000005"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
id="rect4376"
height="1.9999995"
width="3.9999928"
y="14.999996"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
</g>
<g
transform="matrix(1,0,0,-1,-23.999995,23.999995)"
id="g4383">
<rect
id="rect4385"
height="1.9999965"
width="7.9999909"
y="10.999999"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="7.0000005"
width="11.999995"
height="1.9999946"
id="rect4387" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="14.999996"
width="3.9999928"
height="1.9999995"
id="rect4389" />
</g>
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
id="rect3754-4"
width="16"
height="16"
x="76"
y="3.9999199" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 85.10447,6.0157384 -0.0156,1.4063 c 3.02669,-0.2402 0.33008,3.6507996 2.48438,4.5780996 -2.18694,1.0938 0.49191,4.9069 -2.45313,4.5781 l -0.0156,1.4219 c 5.70828,0.559 1.03264,-5.1005 4.70313,-5.2656 l 0,-1.4063 c -3.61303,-0.027 1.11893,-5.7069996 -4.70313,-5.3124996 z"
id="path4351"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 82.78125,5.9984384 0.0156,1.4063 c -3.02668,-0.2402 -0.33007,3.6506996 -2.48437,4.5780996 2.18694,1.0938 -0.49192,4.9069 2.45312,4.5781 l 0.0156,1.4219 c -5.70827,0.559 -1.03263,-5.1004 -4.70312,-5.2656 l 0,-1.4063 c 3.61303,-0.027 -1.11894,-5.7070996 4.70312,-5.3124996 z"
id="path4351-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
id="rect3754-25"
width="16"
height="16"
x="100"
y="3.9999199" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 103.719,5.6719384 0,12.7187996 3.03125,0 0,-1.5313 -1.34375,0 0,-9.6249996 1.375,0 0,-1.5625 z"
id="path2987"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 112.2185,5.6721984 0,12.7187996 -3.03125,0 0,-1.5313 1.34375,0 0,-9.6249996 -1.375,0 0,-1.5625 z"
id="path2987-1"
inkscape:connector-curvature="0" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
id="rect3754-73"
width="16"
height="16"
x="124"
y="3.9999199" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 126.2824,17.602938 1.78957,0 1.14143,-2.8641 5.65364,0 1.14856,2.8641 1.76565,0 -4.78687,-11.1610996 -1.91903,0 z"
id="path3780"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<path
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
d="m 129.72704,13.478838 4.60852,0.01 -2.30426,-5.5497996 z"
id="path3782"
inkscape:connector-curvature="0" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none"
id="rect3754-35"
width="16"
height="16"
x="148"
y="3.9999199" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 156.47655,5.8917384 0,2.1797 0.46093,2.3983996 1.82813,0 0.39844,-2.3983996 0,-2.1797 z"
id="path5008-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 152.51561,5.8906384 0,2.1797 0.46094,2.3983996 1.82812,0 0.39844,-2.3983996 0,-2.1797 z"
id="path5008-2-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<rect
id="svg_1-7-2"
height="1.9999961"
width="11.999996"
y="64"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="svg_1-7-2-2"
height="2.9999905"
width="2.9999907"
y="52"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="52"
width="2.9999907"
height="2.9999905"
id="rect4561" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="80.000008"
y="58"
width="2.9999907"
height="2.9999905"
id="rect4563" />
<rect
id="rect4565"
height="2.9999905"
width="2.9999907"
y="58"
x="85.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="rect4567"
height="2.9999905"
width="2.9999907"
y="64"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="64"
width="2.9999907"
height="2.9999905"
id="rect4569" />
<circle
style="opacity:1;fill:none;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4571"
cx="110.06081"
cy="57.939209"
r="4.7438836" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="116.64566"
y="-31.79752"
width="4.229713"
height="6.4053884"
id="rect4563-2"
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
<path
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 125,56 138.77027,56.095 132,64 Z"
id="path4613"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615"
d="M 149,64 162.77027,63.905 156,56 Z"
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="54"
y="53"
width="11.999996"
height="1.9999961"
id="rect4638" />
<rect
id="svg_1-7-2-24"
height="1.9999957"
width="12.99999"
y="-56"
x="53"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
transform="matrix(0,1,-1,0,0,0)" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="53"
y="-66"
width="12.99999"
height="1.9999957"
id="rect4657" />
<rect
id="rect4659"
height="0.99999291"
width="11.999999"
y="57"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="88.000122"
width="11.999996"
height="1.9999961"
id="rect4661" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="76.000122"
width="2.9999907"
height="2.9999905"
id="rect4663" />
<rect
id="rect4665"
height="2.9999905"
width="2.9999907"
y="76.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
id="rect4667"
height="2.9999905"
width="2.9999907"
y="82.000122"
x="80.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="85.000008"
y="82.000122"
width="2.9999907"
height="2.9999905"
id="rect4669" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="88.000122"
width="2.9999907"
height="2.9999905"
id="rect4671" />
<rect
id="rect4673"
height="2.9999905"
width="2.9999907"
y="88.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<circle
r="4.7438836"
cy="81.939331"
cx="110.06081"
id="circle4675"
style="opacity:1;fill:none;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
id="rect4677"
height="6.4053884"
width="4.229713"
y="-14.826816"
x="133.6163"
style="fill:#d3d3d3;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4679"
d="m 125,80.000005 13.77027,0.09499 L 132,87.999992 Z"
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 149,88.0002 162.77027,87.9052 156,80.0002 Z"
id="path4681"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<rect
id="rect4683"
height="1.9999961"
width="11.999996"
y="77.000122"
x="54"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="77.000122"
y="-56"
width="12.99999"
height="1.9999957"
id="rect4685" />
<rect
id="rect4687"
height="1.9999957"
width="12.99999"
y="-66"
x="77.000122"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
transform="matrix(0,1,-1,0,0,0)" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="81.000122"
width="11.999999"
height="0.99999291"
id="rect4689" />
<rect
id="rect4761-1"
height="1.9999945"
width="15.99999"
y="101"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-0"
height="1.9999945"
width="15.99999"
y="105"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-7"
height="1.9999945"
width="9"
y="109"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1"
height="1.9999945"
width="12"
y="125"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4"
height="1.9999945"
width="10"
y="137"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4"
height="1.9999945"
width="10"
y="129"
x="82"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4-3"
height="1.9999945"
width="9"
y="133"
x="82"
style="fill:#ffffff;fill-opacity:0.8;stroke:none;stroke-width:0" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,100.0254 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,100.5991 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1452 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533865,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550756,0 6.710442,-2.4113 7.650391,-5.9414 0.939949,-3.5301 -0.618463,-7.2736 -3.710938,-9.0703 -1.159678,-0.6738 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,99.9629 c -1.270084,0.039 -2.541493,0.3887 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5402 -3.710937,9.0703 0.939949,3.5301 4.09768,5.9414 7.648437,5.9414 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4056 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,100 0,2 -2.4999996,0 L 12,107 l 4,-5 -2.5,0 0,-2 -3,0 z"
id="path3055-0-77" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.96599996;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9850574,108.015 14.0298856,-0.03"
id="path5244-5-0-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.96599996;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9849874,132.015 14.0298866,-0.03"
id="path5244-5-0-5-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,123.9629 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,124.5366 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1453 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533864,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550757,0 6.710442,-2.4093 7.650391,-5.9394 0.939949,-3.5301 -0.618463,-7.2756 -3.710938,-9.0723 -1.159678,-0.6737 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138-12" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,123.9629 c -1.270084,0.039 -2.541493,0.3888 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5422 -3.710937,9.0723 0.939949,3.5301 4.09768,5.9394 7.648437,5.9394 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4055 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1-3" />
<path
id="path6191"
d="m 10.5,116 0,-2 -2.4999996,0 L 12,109 l 4,5 -2.5,0 0,2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,129 0,-2 -2.4999996,0 L 12,122 l 4,5 -2.5,0 0,2 -3,0 z"
id="path6193" />
<path
id="path6195"
d="m 10.5,135 0,2 -2.4999996,0 L 12,142 l 4,-5 -2.5,0 0,-2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.96599996;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4500"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073242"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073242 -3.833708,2.213392 -3.8337072,2.213393 0,-4.426785 0,-4.426784 3.8337082,2.213392 z"
inkscape:transform-center-x="-1.2779026" />
<path
inkscape:transform-center-x="1.277902"
d="m -31.500004,60.073242 -3.833708,2.213392 -3.833707,2.213393 0,-4.426785 0,-4.426784 3.833707,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073242"
sodipodi:cx="-36.611614"
sodipodi:sides="3"
id="path4502"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="scale(-1,1)" />
<path
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073212"
sodipodi:cx="11.55581"
sodipodi:sides="3"
id="path4504"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="matrix(0,1,-1,0,72.0074,71.7877)"
inkscape:transform-center-y="1.2779029" />
<path
inkscape:transform-center-y="-1.2779026"
transform="matrix(0,-1,-1,0,96,96)"
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4506"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073212"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615-5"
d="m 171.82574,65.174193 16.34854,0 -8.17427,-13.348454 z"
style="fill:#fbb917;fill-opacity:1;fill-rule:evenodd;stroke:#fbb917;stroke-width:1.65161395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,55 0,6 2,0 0,-6"
id="path4300"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,62 0,2 2,0 0,-2"
id="path4300-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:#ffffff;fill-opacity:0.8;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:0.8"
d="M 99.994369,113.0221 102,114.98353 l 7,-6.9558 3,0.97227 2,-1 1,-2 0,-3 -3,3 -3,-3 3,-3 -3,0 -2,1 -1,2 0.99437,3.0221 z"
id="path4268"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccccc" />
<rect
id="rect4175-3-5"
height="16"
width="16"
y="4"
x="220"
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 234,6 0,2 -5,5 0,5 -2,0 0,-5 -5,-5 0,-2"
id="path3546"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<g
transform="matrix(1.3333328,0,0,-1.5999992,-139.9999,127.19999)"
id="g4383-6">
<rect
id="rect4385-2"
height="1.2499905"
width="5.9999924"
y="12.625005"
x="198.00002"
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0"
x="198.00002"
y="15.125007"
width="7.4999928"
height="1.2499949"
id="rect4387-9" />
<rect
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0"
x="198.00002"
y="7.6250024"
width="2.9999909"
height="1.2499905"
id="rect4389-1-0" />
<rect
style="fill:#ffffff;fill-opacity:0.8;stroke:#000000;stroke-width:0"
x="198.00002"
y="10.125004"
width="4.4999919"
height="1.2499905"
id="rect4389-1-9" />
<path
style="fill:#ffffff;fill-opacity:0.8;fill-rule:evenodd;stroke:none;stroke-width:0.68465352px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 207.00001,16.375004 0,-5.625005 -2.25,0 3,-3.1250014 3,3.1250014 -2.25,0 0,5.625005 -1.5,0"
id="path4402"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
</g>
<path
style="fill:#ffffff;fill-opacity:0.8;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 164,100 0,3 -6,6 0,7 -4,0 0,-7 -6,-6 0,-3"
id="path3546-2-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-3"
height="16"
width="16"
y="28"
x="4" />
<path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path4402-5-7"
d="m 15,41 0,-7 -4,0 0,3 -5,-4 5,-4 0,3 6,0 0,9"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.68465352px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 31 KiB

+6
View File
File diff suppressed because one or more lines are too long
+48
View File
File diff suppressed because one or more lines are too long
+3
View File
@@ -16,5 +16,8 @@ dns:
tls:
certificate_path: /certs/cert_public
private_key_path: /certs/cert_private
filtering:
safe_search:
enabled: false
log:
file: /logs/adguard
+22 -17
View File
@@ -68,26 +68,26 @@
{
"flow": "xtls-rprx-vision",
"packet_encoding": "",
"server": "",
"server": "~domain~",
"server_port": 443,
"tls": {
"enabled": true,
"insecure": false,
"reality": {
"enabled": true,
"public_key": "",
"short_id": ""
"public_key": "~public_key~",
"short_id": "~short_id~"
},
"server_name": "",
"server_name": "~server_name~",
"utls": {
"enabled": true,
"fingerprint": "chrome"
}
},
"uuid": "",
"uuid": "~uid~",
"type": "vless",
"domain_strategy": "ipv4_only",
"tag": "proxy"
"tag": "~outbound~"
},
{
"type": "direct",
@@ -110,6 +110,20 @@
"protocol": "dns",
"outbound": "dns-out"
},
{
"createruleset": [
{
"name": "pac",
"interval": "15s",
"rules": [
{
"domain_suffix": "~pac~"
}
]
}
],
"outbound": "~domains_outbound~"
},
{
"createruleset": [
{
@@ -154,15 +168,6 @@
},
{
"createruleset": [
{
"name": "pac",
"interval": "15s",
"rules": [
{
"domain_suffix": "~pac~"
}
]
},
{
"name": "warp",
"interval": "15s",
@@ -173,12 +178,12 @@
]
}
],
"outbound": "proxy"
"outbound": "~outbound~"
},
{
"outbound": "direct"
}
],
"final": "direct"
"final": "~final_outbound~"
}
}
+1 -1
View File
@@ -30,7 +30,7 @@ stream {
map_hash_bucket_size 128;
map $ssl_preread_server_name $sni_name {
#domain
www.microsoft.com reality;
telegram.org reality;
#domain
#ocserv
+7 -7
View File
@@ -36,14 +36,14 @@
}
}],
"outbounds": [{
"tag": "proxy",
"tag": "~outbound~",
"protocol": "vless",
"settings": {
"vnext": [{
"address": "",
"address": "~domain~",
"port": 443,
"users": [{
"id": "",
"id": "~uid~",
"alterId": 0,
"email": "t@t.tt",
"security": "auto",
@@ -56,11 +56,11 @@
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "",
"serverName": "~server_name~",
"fingerprint": "chrome",
"show": false,
"publicKey": "",
"shortId": "",
"publicKey": "~public_key~",
"shortId": "~short_id~",
"spiderX": ""
}
},
@@ -84,7 +84,7 @@
"domainStrategy": "AsIs",
"rules": [{
"type": "field",
"outboundTag": "proxy",
"outboundTag": "~outbound~",
"domain": "~pac~"
}, {
"type": "field",
+2 -2
View File
@@ -18,13 +18,13 @@
"streamSettings": {
"network": "tcp",
"realitySettings": {
"dest": "www.microsoft.com:443",
"dest": "telegram.org:443",
"maxClientVer": "",
"maxTimeDiff": 0,
"minClientVer": "",
"privateKey": "",
"serverNames": [
"www.microsoft.com"
"telegram.org"
],
"shortIds": [],
"show": false,
+4 -1
View File
@@ -16,6 +16,7 @@ networks:
- subnet: 10.10.1.0/24
volumes:
adguard:
warp:
services:
up:
@@ -117,6 +118,7 @@ services:
- ./update:/update
- ./.git:/.git
- ./singbox_windows:/singbox
- ./docker-compose.override.yml:/docker/compose
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
IP: ${IP}
@@ -302,7 +304,7 @@ services:
ipv4_address: 10.10.0.14
logging: *default-logging
ad:
image: mercurykd/vpnbot-ad:1.1
image: mercurykd/vpnbot-ad:1.2
build:
dockerfile: dockerfile/adguard.dockerfile
args:
@@ -510,6 +512,7 @@ services:
- ./config:/config
- ./certs:/certs
- ./scripts/start_wp.sh:/start_wp.sh
- warp:/var/lib/cloudflare-warp
hostname: warp
container_name: warp-${VER}
depends_on:
+1 -1
View File
@@ -3,7 +3,7 @@ b:
u: # запуск контейнеров
$(eval IP := $(shell curl -s -t 1 2ip.io || curl -s -t 1 ipinfo.io/ip || curl -s -t 1 ifconfig.me))
bash ./update/update.sh &
touch ./override.env
touch ./override.env ./docker-compose.override.yml
IP=$(IP) VER=$(shell git describe --tags) docker compose --env-file ./.env --env-file ./override.env up -d --force-recreate
d: # остановка контейнеров
-kill -9 $(shell cat ./update/update_pid) > /dev/null
+1 -11
View File
@@ -10,17 +10,7 @@ apt install -y \
iproute2 \
xtables-addons-common \
xtables-addons-dkms
mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/gpg | gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$(lsb_release -is | tr '[:upper:]' '[:lower:]') \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt update
apt install -y docker-ce docker-ce-cli containerd.io
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.29.6/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh
git clone https://github.com/mercurykd/vpnbot.git
cd ./vpnbot
echo "<?php
+6 -3
View File
@@ -7,10 +7,13 @@ if [ "$off" == 'null' ]
then
warp-svc > /dev/null &
sleep 3
warp-cli --accept-tos registration new
if [ ! -z "$key" ]
if [ ! -f /var/lib/cloudflare-warp/conf.json ]
then
warp-cli --accept-tos registration license $key
warp-cli --accept-tos registration new
if [ ! -z "$key" ]
then
warp-cli --accept-tos registration license $key
fi
fi
warp-cli --accept-tos mode proxy
warp-cli --accept-tos connect
+1 -1
View File
@@ -6,7 +6,7 @@ After=docker.service
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=path
ExecStartPre=/bin/sh -c "touch ./override.env"
ExecStartPre=/bin/sh -c "touch ./override.env ./docker-compose.override.yml"
ExecStart=/bin/sh -c "IP=$(curl https://ipinfo.io/ip) VER=$(git describe --tags) docker compose --env-file ./.env --env-file ./override.env up -d --force-recreate"
ExecStartPost=/bin/sh -c "bash ./update/update.sh &"
ExecStop=/bin/sh -c "docker compose down --remove-orphans"
Binary file not shown.
+12 -9
View File
@@ -12,17 +12,20 @@ do
key=$(cat $pwd/update/key)
curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "останавливаю бота"/')"
docker compose down --remove-orphans
curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "очищаю директорию"/')"
git reset --hard && git clean -fd
curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "скачиваю обновление"/')"
git fetch
if [[ -n "$branch" ]]
if [[ "$cmd" == "1" ]]
then
curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "меняю ветку"/')"
git checkout -t origin/$branch || git checkout $branch
curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "очищаю директорию"/')"
git reset --hard && git clean -fd
curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "скачиваю обновление"/')"
git fetch
if [[ -n "$branch" ]]
then
curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "меняю ветку"/')"
git checkout -t origin/$branch || git checkout $branch
fi
curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "применяю обновления"/')"
git pull > ./update/message
fi
curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "применяю обновления"/')"
git pull > ./update/message
curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "запускаю бота"/')"
IP=$(curl ipinfo.io/ip) VER=$(git describe --tags) docker compose --env-file ./.env --env-file ./override.env up -d --force-recreate
bash $pwd/update/update.sh &
+45
View File
@@ -1,3 +1,48 @@
09.11.2024 v1.97
- новая ссылка на чат поддержки. пожалуйста не размещайте ее на форумах и чатах во избежание набега leafers https://www.youtube.com/watch?v=9tlNJmjuKD4
06.11.2024 v1.96
- фикс пароля adguard
- таймаоут для проверки статуса adguard
04.11.2024 v1.95
- отключение портов контейнеров из меню
- перезагрузка из меню
04.11.2024 v1.94
- xray: возможность перемещать и переименовывать outbound заполняемый ботом
04.11.2024 v1.93
- adguardHome: сброс настроек
- adguardHome: статус работоспособности
- xray: выбор outbound для списков
- xray: выбор outbound для final
- xray: дефолтный домен reality microsoft.com заменен на telegram.org
- xray: создание шаблона путем копирования оригинала
- xray: редактирование шаблона прямо в боте
30.10.2024 v1.92
- возможность скачать origin шаблон
30.10.2024 v1.91
- кнопка nip.io для быстрой смены домена
27.10.2024 v1.90
- очередной фикс запуска warp после апдейта
- правки фраз меню
26.10.2024 v1.89
- xray rulesset: фикс меню при отсутствующих правилах
26.10.2024 v1.88
- xray rulesset: дублирование кнопок текстом
- singbox 1.10.1 для windows x64
- фикс с включенным warp после апдейта
- фикс с нерабочей кнопкой апдейта, обновится можно через /autoupdate если поймали не рабочую кнопку апдейта
25.10.2024 v1.87
- xray: в routes добавлен раздел proxy - зеркало раздела Pac
25.10.2024 v1.86
- фикс не срабатывания автобэкапа во время старта
- adguard: вывод списка разрешенных клиентов
- adguard: кнопка заполнения разрешенных клиентов - собирает все clientId со всех контейнеров
- adguard: вывод статуса безопасного поиска
- warp: при выключении удаляется регистрация deviceid
24.10.2024 v1.85
- фикс удаления состояния warp после рестарта
- возможность перезаписать фразы меню бота через app/override.php
24.10.2024 v1.84
- фикс показа ссылки для openconnect
24.10.2024 v1.83
- фикс ошибок доступа контейнеров при автообновлении
23.10.2024 v1.82