Make podkop-plus coexist cleanly with the original podkop

This commit is contained in:
ushan0v
2026-04-12 03:38:06 +03:00
parent e9a2b27147
commit 820fa6a1c5
34 changed files with 1016 additions and 886 deletions
+4 -4
View File
@@ -14,17 +14,17 @@ async function main() {
for (const file of files) {
const filePath = path.join(sourceDir, file);
if (file === 'podkop.pot') {
const potTarget = path.join(targetRoot, 'templates', 'podkop.pot');
if (file === 'podkop_plus.pot') {
const potTarget = path.join(targetRoot, 'templates', 'podkop_plus.pot');
await fs.mkdir(path.dirname(potTarget), { recursive: true });
await fs.copyFile(filePath, potTarget);
console.log(`✅ Copied POT: ${filePath} → ${potTarget}`);
}
const match = file.match(/^podkop\.([a-zA-Z_]+)\.po$/);
const match = file.match(/^podkop_plus\.([a-zA-Z_]+)\.po$/);
if (match) {
const lang = match[1];
const poTarget = path.join(targetRoot, lang, 'podkop.po');
const poTarget = path.join(targetRoot, lang, 'podkop_plus.po');
await fs.mkdir(path.dirname(poTarget), { recursive: true });
await fs.copyFile(filePath, poTarget);
console.log(`✅ Copied ${lang.toUpperCase()}: ${filePath} → ${poTarget}`);
+1 -1
View File
@@ -8,7 +8,7 @@ if (!lang) {
}
const callsPath = 'locales/calls.json';
const poPath = `locales/podkop.${lang}.po`;
const poPath = `locales/podkop_plus.${lang}.po`;
function getGitUser() {
try {
+1 -1
View File
@@ -2,7 +2,7 @@ import fs from 'fs/promises';
import { execSync } from 'child_process';
const inputFile = 'locales/calls.json';
const outputFile = 'locales/podkop.pot';
const outputFile = 'locales/podkop_plus.pot';
const projectId = 'PODKOP PLUS';
function getGitUser() {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PODKOP PLUS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-04-11 21:49+0300\n"
"PO-Revision-Date: 2026-04-11 21:49+0300\n"
"POT-Creation-Date: 2026-04-11 01:33+0300\n"
"PO-Revision-Date: 2026-04-11 01:33+0300\n"
"Last-Translator: ushan0v\n"
"Language-Team: none\n"
"Language: ru\n"
+5
View File
@@ -4,6 +4,11 @@ export const STATUS_COLORS = {
WARNING: '#ff9800',
};
export const PODKOP_UCI_PACKAGE = 'podkop_plus';
export const PODKOP_LUCI_VIEW_NAMESPACE = 'podkop_plus';
export const PODKOP_LUCI_VIEW_DIR = `/www/luci-static/resources/view/${PODKOP_LUCI_VIEW_NAMESPACE}`;
export const PODKOP_LUCI_I18N_DOMAIN = 'podkop_plus';
export const PODKOP_CBI_PREFIX = PODKOP_UCI_PACKAGE;
export const PODKOP_LUCI_APP_VERSION = '__COMPILED_VERSION_VARIABLE__';
export const FAKEIP_CHECK_DOMAIN = 'fakeip.podkop.fyi';
export const IP_CHECK_DOMAIN = 'ip.podkop.fyi';
@@ -1,5 +1,8 @@
import { Podkop } from '../../types';
import { PODKOP_UCI_PACKAGE } from '../../../constants';
export async function getConfigSections(): Promise<Podkop.ConfigSection[]> {
return uci.load('podkop').then(() => uci.sections('podkop'));
return uci
.load(PODKOP_UCI_PACKAGE)
.then(() => uci.sections(PODKOP_UCI_PACKAGE));
}
@@ -1,10 +1,12 @@
// language=CSS
import { PODKOP_CBI_PREFIX } from '../../../constants';
export const styles = `
#cbi-podkop-dashboard-_mount_node > div {
#cbi-${PODKOP_CBI_PREFIX}-dashboard-_mount_node > div {
width: 100%;
}
#cbi-podkop-dashboard > h3 {
#cbi-${PODKOP_CBI_PREFIX}-dashboard > h3 {
display: none;
}
@@ -1,11 +1,13 @@
// language=CSS
import { PODKOP_CBI_PREFIX } from '../../../constants';
export const styles = `
#cbi-podkop-diagnostic-_mount_node > div {
#cbi-${PODKOP_CBI_PREFIX}-diagnostic-_mount_node > div {
width: 100%;
}
#cbi-podkop-diagnostic > h3 {
#cbi-${PODKOP_CBI_PREFIX}-diagnostic > h3 {
display: none;
}
+17 -16
View File
@@ -1,6 +1,7 @@
// language=CSS
import { DashboardTab, DiagnosticTab } from './podkop';
import { PartialStyles } from './partials';
import { PODKOP_CBI_PREFIX } from './constants';
export const GlobalStyles = `
${DashboardTab.styles}
@@ -9,55 +10,55 @@ ${PartialStyles}
/* Hide extra H3 for settings tab */
#cbi-podkop-settings > h3 {
#cbi-${PODKOP_CBI_PREFIX}-settings > h3 {
display: none;
}
/* Hide extra H3 for rules tab */
#cbi-podkop-rule > h3:nth-child(1) {
#cbi-${PODKOP_CBI_PREFIX}-rule > h3:nth-child(1) {
display: none;
}
/* Hide extra H3 for nodes tab */
#cbi-podkop-node > h3:nth-child(1) {
#cbi-${PODKOP_CBI_PREFIX}-node > h3:nth-child(1) {
display: none;
}
/* Hide extra H3 for rule set tab */
#cbi-podkop-ruleset > h3:nth-child(1) {
#cbi-${PODKOP_CBI_PREFIX}-ruleset > h3:nth-child(1) {
display: none;
}
/* Vertical align for remove rule action button */
#cbi-podkop-rule > .cbi-section-remove {
#cbi-${PODKOP_CBI_PREFIX}-rule > .cbi-section-remove {
margin-bottom: -32px;
}
#cbi-podkop-rule .cbi-section-actions > div {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-actions > div {
display: inline-flex;
align-items: center;
gap: 4px;
}
/* Rule reorder visuals */
#cbi-podkop-rule {
#cbi-${PODKOP_CBI_PREFIX}-rule {
position: relative;
}
#cbi-podkop-rule .cbi-section-table-row {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row {
position: relative;
}
#cbi-podkop-rule .cbi-section-table-row.placeholder {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.placeholder {
opacity: 1;
}
#cbi-podkop-rule .cbi-section-table-row.placeholder em {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.placeholder em {
font-style: italic;
}
#cbi-podkop-rule .cbi-section-table-row.drag-over-above::after,
#cbi-podkop-rule .cbi-section-table-row.drag-over-below::after {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.drag-over-above::after,
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.drag-over-below::after {
content: '';
position: absolute;
left: 10px;
@@ -69,17 +70,17 @@ ${PartialStyles}
z-index: 2;
}
#cbi-podkop-rule .cbi-section-table-row.drag-over-above::after {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.drag-over-above::after {
top: -1px;
}
#cbi-podkop-rule .cbi-section-table-row.drag-over-below::after {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.drag-over-below::after {
bottom: -1px;
}
/* Vertical align for remove node action button */
#cbi-podkop-node > .cbi-section-remove,
#cbi-podkop-ruleset > .cbi-section-remove {
#cbi-${PODKOP_CBI_PREFIX}-node > .cbi-section-remove,
#cbi-${PODKOP_CBI_PREFIX}-ruleset > .cbi-section-remove {
margin-bottom: -32px;
}
+1 -1
View File
@@ -19,7 +19,7 @@ const config = {
const syncDirs = [
{
local: path.resolve(process.env.LOCAL_DIR_FE ?? '../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop'),
remote: process.env.REMOTE_DIR_FE ?? '/www/luci-static/resources/view/podkop',
remote: process.env.REMOTE_DIR_FE ?? '/www/luci-static/resources/view/podkop_plus',
},
{
local: path.resolve(process.env.LOCAL_DIR_BIN ?? '../podkop/files/usr/bin/'),
+114 -42
View File
@@ -16,6 +16,7 @@ ZAPRET_ARCH_CANDIDATES=""
ZAPRET_ALREADY_PRESENT=0
ZAPRET_REQUESTED=0
ZAPRET_SKIPPED_REASON=""
PODKOP_PLUS_I18N_REQUESTED=0
PODKOP_PLUS_RELEASE_JSON=""
PODKOP_PLUS_RELEASE_TAG=""
@@ -380,28 +381,62 @@ resolve_podkop_plus_release() {
[ -n "$PODKOP_PLUS_RELEASE_TAG" ] || fail "Failed to detect the Podkop Plus release tag"
PODKOP_PLUS_PACKAGE_URL="$(printf '%s' "$PODKOP_PLUS_RELEASE_JSON" | jq -r --arg ext "$asset_ext" '.assets[] | select((.name | startswith("luci-app-podkop-plus_")) and (.name | endswith("." + $ext))) | .browser_download_url' | sed -n '1p')"
PODKOP_PLUS_I18N_URL="$(printf '%s' "$PODKOP_PLUS_RELEASE_JSON" | jq -r --arg ext "$asset_ext" '.assets[] | select((.name | startswith("luci-i18n-podkop-plus-ru_")) and (.name | endswith("." + $ext))) | .browser_download_url' | sed -n '1p')"
[ -n "$PODKOP_PLUS_PACKAGE_URL" ] || fail "The Podkop Plus release does not contain a luci-app-podkop-plus .$asset_ext package"
[ -n "$PODKOP_PLUS_I18N_URL" ] || fail "The Podkop Plus release does not contain a luci-i18n-podkop-plus-ru .$asset_ext package"
PODKOP_PLUS_PACKAGE_NAME="$(basename "$PODKOP_PLUS_PACKAGE_URL")"
PODKOP_PLUS_I18N_NAME="$(basename "$PODKOP_PLUS_I18N_URL")"
PODKOP_PLUS_PACKAGE_VERSION="$(extract_package_version "$PODKOP_PLUS_PACKAGE_NAME")"
PODKOP_PLUS_I18N_URL=""
PODKOP_PLUS_I18N_NAME=""
if [ "$PODKOP_PLUS_I18N_REQUESTED" -eq 1 ]; then
PODKOP_PLUS_I18N_URL="$(printf '%s' "$PODKOP_PLUS_RELEASE_JSON" | jq -r --arg ext "$asset_ext" '.assets[] | select((.name | startswith("luci-i18n-podkop-plus-ru_")) and (.name | endswith("." + $ext))) | .browser_download_url' | sed -n '1p')"
[ -n "$PODKOP_PLUS_I18N_URL" ] || fail "The Podkop Plus release does not contain a luci-i18n-podkop-plus-ru .$asset_ext package"
PODKOP_PLUS_I18N_NAME="$(basename "$PODKOP_PLUS_I18N_URL")"
fi
}
detect_installed_podkop_version() {
detect_installed_podkop_plus_version() {
version=""
if command_exists podkop-plus; then
version="$(podkop-plus show_version 2>/dev/null | head -n 1)"
fi
if [ -z "$version" ] && command_exists podkop; then
version="$(podkop show_version 2>/dev/null | head -n 1)"
printf '%s' "$version"
}
is_original_podkop_present() {
pkg_is_installed "podkop" ||
pkg_is_installed "luci-app-podkop" ||
[ -x /etc/init.d/podkop ] ||
[ -x /usr/bin/podkop ] ||
[ -d /usr/lib/podkop ] ||
[ -f /usr/share/luci/menu.d/luci-app-podkop.json ] ||
[ -f /usr/share/rpcd/acl.d/luci-app-podkop.json ]
}
migrate_podkop_plus_config_if_needed() {
[ -f /etc/config/podkop_plus ] && return 0
[ -f /etc/config/podkop ] || return 0
if ! pkg_is_installed "luci-app-podkop-plus" &&
[ ! -x /etc/init.d/podkop-plus ] &&
[ ! -x /usr/bin/podkop-plus ] &&
[ ! -d /usr/lib/podkop-plus ]; then
return 0
fi
printf '%s' "$version"
if is_original_podkop_present; then
warn "Detected the original Podkop installation together with a shared legacy config at /etc/config/podkop."
warn "Podkop Plus will not import this shared config automatically. The new version will use /etc/config/podkop_plus."
return 0
fi
cp /etc/config/podkop /etc/config/podkop_plus || fail "Failed to migrate the Podkop Plus config to /etc/config/podkop_plus"
chmod 0644 /etc/config/podkop_plus || true
msg "Migrated the Podkop Plus config to /etc/config/podkop_plus"
}
reset_legacy_config_if_needed() {
@@ -410,32 +445,35 @@ reset_legacy_config_if_needed() {
default_config_url=""
default_config_tmp=""
[ -f /etc/config/podkop ] || return 0
[ -f /etc/config/podkop_plus ] || return 0
current_version="$(detect_installed_podkop_version)"
current_version="$(detect_installed_podkop_plus_version)"
if [ -n "$current_version" ] && version_ge "$current_version" "0.7.0"; then
return 0
fi
if ! pkg_is_installed "podkop" && ! pkg_is_installed "luci-app-podkop" && [ ! -x /etc/init.d/podkop ]; then
if ! pkg_is_installed "luci-app-podkop-plus" &&
[ ! -x /etc/init.d/podkop-plus ] &&
[ ! -x /usr/bin/podkop-plus ] &&
[ ! -d /usr/lib/podkop-plus ]; then
return 0
fi
warn "Detected a legacy podkop installation."
warn "The current config will be backed up to /etc/config/podkop-070.<timestamp> and replaced with the Podkop Plus default config."
warn "Detected a legacy Podkop Plus installation."
warn "The current config will be backed up to /etc/config/podkop_plus-070.<timestamp> and replaced with the Podkop Plus default config."
confirm_prompt "Continue and reset /etc/config/podkop?" || fail "Installation cancelled by user"
confirm_prompt "Continue and reset /etc/config/podkop_plus?" || fail "Installation cancelled by user"
backup_path="/etc/config/podkop-070.$(date +%Y%m%d%H%M%S 2>/dev/null || echo "$$")"
mv /etc/config/podkop "$backup_path" || fail "Failed to back up /etc/config/podkop"
backup_path="/etc/config/podkop_plus-070.$(date +%Y%m%d%H%M%S 2>/dev/null || echo "$$")"
mv /etc/config/podkop_plus "$backup_path" || fail "Failed to back up /etc/config/podkop_plus"
default_config_url="https://raw.githubusercontent.com/${REPO_OWNER}/${REPO_NAME}/${PODKOP_PLUS_RELEASE_TAG}/podkop/files/etc/config/podkop"
default_config_tmp="$TMP_DIR/default-podkop-config"
default_config_tmp="$TMP_DIR/default-podkop-plus-config"
download_with_retry "$default_config_url" "$default_config_tmp" "default Podkop Plus config" || fail "Failed to download the default Podkop Plus config"
cp "$default_config_tmp" /etc/config/podkop || fail "Failed to restore /etc/config/podkop"
chmod 0644 /etc/config/podkop || true
cp "$default_config_tmp" /etc/config/podkop_plus || fail "Failed to restore /etc/config/podkop_plus"
chmod 0644 /etc/config/podkop_plus || true
msg "A fresh Podkop Plus config was installed. Backup saved to $backup_path"
}
@@ -476,19 +514,26 @@ remove_old_sing_box_if_needed() {
remember_autostart_state() {
if [ -x /etc/init.d/podkop-plus ] && /etc/init.d/podkop-plus enabled >/dev/null 2>&1; then
PODKOP_WAS_ENABLED=1
return 0
fi
if [ -x /etc/init.d/podkop ] && /etc/init.d/podkop enabled >/dev/null 2>&1; then
PODKOP_WAS_ENABLED=1
fi
}
stop_conflicting_services() {
[ -x /etc/init.d/podkop-plus ] && /etc/init.d/podkop-plus stop >/dev/null 2>&1 || true
[ -x /etc/init.d/podkop-plus ] && /etc/init.d/podkop-plus disable >/dev/null 2>&1 || true
[ -x /etc/init.d/podkop ] && /etc/init.d/podkop stop >/dev/null 2>&1 || true
[ -x /etc/init.d/podkop ] && /etc/init.d/podkop disable >/dev/null 2>&1 || true
}
deactivate_original_podkop_if_present() {
[ -x /etc/init.d/podkop ] || return 0
if /etc/init.d/podkop running >/dev/null 2>&1; then
warn "Detected a running original Podkop service. Stopping it before installing Podkop Plus."
/etc/init.d/podkop stop >/dev/null 2>&1 || warn "Failed to stop the original Podkop service."
fi
if /etc/init.d/podkop enabled >/dev/null 2>&1; then
warn "Detected an enabled original Podkop autostart. Disabling it before installing Podkop Plus."
/etc/init.d/podkop disable >/dev/null 2>&1 || warn "Failed to disable original Podkop autostart."
fi
}
cleanup_legacy_installation() {
@@ -496,19 +541,18 @@ cleanup_legacy_installation() {
stop_conflicting_services
pkg_remove_matching_prefix "luci-i18n-podkop-plus"
pkg_remove_matching_prefix "luci-i18n-podkop-"
pkg_remove_if_installed "luci-app-podkop-plus"
pkg_remove_if_installed "luci-app-podkop"
pkg_remove_if_installed "podkop"
rm -rf /usr/lib/podkop-plus /usr/lib/podkop /www/luci-static/resources/view/podkop
rm -f /etc/init.d/podkop-plus /etc/init.d/podkop
rm -f /usr/bin/podkop-plus /usr/bin/podkop
rm -rf /usr/lib/podkop-plus /www/luci-static/resources/view/podkop_plus
rm -f /etc/init.d/podkop-plus
rm -f /usr/bin/podkop-plus
rm -f /usr/share/luci/menu.d/luci-app-podkop-plus.json
rm -f /usr/share/rpcd/acl.d/luci-app-podkop-plus.json
rm -f /usr/share/luci/menu.d/luci-app-podkop.json
rm -f /usr/share/rpcd/acl.d/luci-app-podkop.json
rm -f /etc/uci-defaults/50_luci-podkop-plus /etc/uci-defaults/50_luci-podkop
rm -f /etc/uci-defaults/50_luci-podkop-plus
rm -f /usr/lib/lua/luci/i18n/podkop_plus.ru.lmo
rm -f /usr/lib/lua/luci/i18n/podkop_plus.en.lmo
rm -f /usr/lib/lua/luci/i18n/podkop_plus.ru.lua
rm -f /usr/lib/lua/luci/i18n/podkop_plus.en.lua
}
append_arch_candidate() {
@@ -715,12 +759,25 @@ decide_zapret_installation() {
warn "Continuing without zapret."
}
decide_i18n_installation() {
if confirm_prompt "Установить русский язык интерфейса? (Install the Russian interface language package?)"; then
PODKOP_PLUS_I18N_REQUESTED=1
return 0
fi
warn "Continuing without the Russian interface language package."
}
download_podkop_plus_packages() {
PODKOP_PLUS_PACKAGE_FILE="$TMP_DIR/$PODKOP_PLUS_PACKAGE_NAME"
PODKOP_PLUS_I18N_FILE="$TMP_DIR/$PODKOP_PLUS_I18N_NAME"
PODKOP_PLUS_I18N_FILE=""
download_with_retry "$PODKOP_PLUS_PACKAGE_URL" "$PODKOP_PLUS_PACKAGE_FILE" "$PODKOP_PLUS_PACKAGE_NAME" || fail "Failed to download $PODKOP_PLUS_PACKAGE_NAME"
download_with_retry "$PODKOP_PLUS_I18N_URL" "$PODKOP_PLUS_I18N_FILE" "$PODKOP_PLUS_I18N_NAME" || fail "Failed to download $PODKOP_PLUS_I18N_NAME"
if [ -n "$PODKOP_PLUS_I18N_URL" ]; then
PODKOP_PLUS_I18N_FILE="$TMP_DIR/$PODKOP_PLUS_I18N_NAME"
download_with_retry "$PODKOP_PLUS_I18N_URL" "$PODKOP_PLUS_I18N_FILE" "$PODKOP_PLUS_I18N_NAME" || fail "Failed to download $PODKOP_PLUS_I18N_NAME"
fi
}
download_and_extract_zapret_package() {
@@ -771,7 +828,11 @@ download_and_extract_zapret_package() {
}
install_packages() {
set -- "$PODKOP_PLUS_PACKAGE_FILE" "$PODKOP_PLUS_I18N_FILE"
set -- "$PODKOP_PLUS_PACKAGE_FILE"
if [ -n "$PODKOP_PLUS_I18N_FILE" ]; then
set -- "$@" "$PODKOP_PLUS_I18N_FILE"
fi
if [ -n "$ZAPRET_PACKAGE_FILE" ]; then
pkg_remove_if_installed "zapret"
@@ -803,17 +864,28 @@ main() {
sync_time
check_system
decide_zapret_installation
decide_i18n_installation
deactivate_original_podkop_if_present
pkg_list_update || fail "Failed to update package lists"
ensure_bootstrap_tool "jq" "jq"
ensure_bootstrap_tool "unzip" "unzip"
if [ "$ZAPRET_REQUESTED" -eq 1 ]; then
ensure_bootstrap_tool "unzip" "unzip"
fi
resolve_podkop_plus_release
migrate_podkop_plus_config_if_needed
reset_legacy_config_if_needed
remove_conflicting_dns_proxy
remove_old_sing_box_if_needed
resolve_arch_candidates
decide_zapret_installation
resolve_zapret_release
if [ "$ZAPRET_REQUESTED" -eq 1 ]; then
resolve_arch_candidates
resolve_zapret_release
fi
cleanup_legacy_installation
download_podkop_plus_packages
+5 -6
View File
@@ -16,7 +16,6 @@ LUCI_PKGARCH:=all
LUCI_LANG.ru:=Русский (Russian)
LUCI_LANG.en:=English
LUCI_MAINTAINER:=ushan0v <ushan0v@users.noreply.github.com>
CONFLICTS:=luci-app-podkop podkop luci-i18n-podkop-ru
PKG_LICENSE:=GPL-2.0-or-later
LUCI_LANGUAGES:=en ru
@@ -38,23 +37,23 @@ exit 0
endef
define Package/$(PKG_NAME)/conffiles
/etc/config/podkop
/etc/config/podkop_plus
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)$(HTDOCS)
$(CP) $(PKG_BUILD_DIR)/htdocs/* $(1)$(HTDOCS)/
$(INSTALL_DIR) $(1)$(HTDOCS)/luci-static/resources/view/podkop_plus
$(CP) $(PKG_BUILD_DIR)/htdocs/luci-static/resources/view/podkop/* $(1)$(HTDOCS)/luci-static/resources/view/podkop_plus/
$(INSTALL_DIR) $(1)/
$(CP) $(PKG_BUILD_DIR)/root/* $(1)/
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ../podkop/files/etc/init.d/podkop $(1)/etc/init.d/podkop-plus
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ../podkop/files/etc/config/podkop $(1)/etc/config/podkop
$(INSTALL_CONF) ../podkop/files/etc/config/podkop $(1)/etc/config/podkop_plus
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) ../podkop/files/usr/bin/podkop $(1)/usr/bin/podkop-plus
$(INSTALL_DIR) $(1)/usr/lib/podkop-plus
$(CP) ../podkop/files/usr/lib/* $(1)/usr/lib/podkop-plus/
sed -i -e 's/__COMPILED_VERSION_VARIABLE__/$(PODKOP_PACKAGE_VERSION)/g' $(1)$(HTDOCS)/luci-static/resources/view/podkop/main.js || true
sed -i -e 's/__COMPILED_VERSION_VARIABLE__/$(PODKOP_PACKAGE_VERSION)/g' $(1)$(HTDOCS)/luci-static/resources/view/podkop_plus/main.js || true
sed -i -e 's/__COMPILED_VERSION_VARIABLE__/$(PODKOP_PACKAGE_VERSION)/g' $(1)/usr/lib/podkop-plus/constants.sh || true
endef
@@ -4,7 +4,7 @@
"require ui";
"require uci";
"require fs";
"require view.podkop.main as main";
"require view.podkop_plus.main as main";
function createDashboardContent(section) {
const o = section.option(form.DummyValue, "_mount_node");
@@ -4,7 +4,7 @@
"require ui";
"require uci";
"require fs";
"require view.podkop.main as main";
"require view.podkop_plus.main as main";
function createDiagnosticContent(section) {
const o = section.option(form.DummyValue, "_mount_node");
@@ -565,9 +565,127 @@ function parseValueList(value) {
return value.split(/\n/).map((line) => line.split("//")[0].split("#")[0]).join(" ").split(/[,\s]+/).map((s) => s.trim()).filter(Boolean);
}
// src/constants.ts
var STATUS_COLORS = {
SUCCESS: "#4caf50",
ERROR: "#f44336",
WARNING: "#ff9800"
};
var PODKOP_UCI_PACKAGE = "podkop_plus";
var PODKOP_LUCI_VIEW_NAMESPACE = "podkop_plus";
var PODKOP_LUCI_VIEW_DIR = `/www/luci-static/resources/view/${PODKOP_LUCI_VIEW_NAMESPACE}`;
var PODKOP_LUCI_I18N_DOMAIN = "podkop_plus";
var PODKOP_CBI_PREFIX = PODKOP_UCI_PACKAGE;
var PODKOP_LUCI_APP_VERSION = "__COMPILED_VERSION_VARIABLE__";
var FAKEIP_CHECK_DOMAIN = "fakeip.podkop.fyi";
var IP_CHECK_DOMAIN = "ip.podkop.fyi";
var REGIONAL_OPTIONS = [
"russia_inside",
"russia_outside",
"ukraine_inside"
];
var ALLOWED_WITH_RUSSIA_INSIDE = [
"russia_inside",
"meta",
"twitter",
"discord",
"telegram",
"cloudflare",
"google_ai",
"google_play",
"hetzner",
"ovh",
"hodca",
"roblox",
"digitalocean",
"cloudfront"
];
var DOMAIN_LIST_OPTIONS = {
russia_inside: "Russia inside",
russia_outside: "Russia outside",
ukraine_inside: "Ukraine",
geoblock: "Geo Block",
block: "Block",
porn: "Porn",
news: "News",
anime: "Anime",
youtube: "Youtube",
discord: "Discord",
meta: "Meta",
twitter: "Twitter (X)",
hdrezka: "HDRezka",
tiktok: "Tik-Tok",
telegram: "Telegram",
cloudflare: "Cloudflare",
google_ai: "Google AI",
google_play: "Google Play",
hodca: "H.O.D.C.A",
roblox: "Roblox",
hetzner: "Hetzner ASN",
ovh: "OVH ASN",
digitalocean: "Digital Ocean ASN",
cloudfront: "CloudFront ASN"
};
var UPDATE_INTERVAL_OPTIONS = {
"1h": "Every hour",
"3h": "Every 3 hours",
"12h": "Every 12 hours",
"1d": "Every day",
"3d": "Every 3 days"
};
var DNS_SERVER_OPTIONS = {
"1.1.1.1": "1.1.1.1 (Cloudflare)",
"8.8.8.8": "8.8.8.8 (Google)",
"9.9.9.9": "9.9.9.9 (Quad9)",
"dns.adguard-dns.com": "dns.adguard-dns.com (AdGuard Default)",
"unfiltered.adguard-dns.com": "unfiltered.adguard-dns.com (AdGuard Unfiltered)",
"family.adguard-dns.com": "family.adguard-dns.com (AdGuard Family)"
};
var BOOTSTRAP_DNS_SERVER_OPTIONS = {
"77.88.8.8": "77.88.8.8 (Yandex DNS)",
"77.88.8.1": "77.88.8.1 (Yandex DNS)",
"1.1.1.1": "1.1.1.1 (Cloudflare DNS)",
"1.0.0.1": "1.0.0.1 (Cloudflare DNS)",
"8.8.8.8": "8.8.8.8 (Google DNS)",
"8.8.4.4": "8.8.4.4 (Google DNS)",
"9.9.9.9": "9.9.9.9 (Quad9 DNS)",
"9.9.9.11": "9.9.9.11 (Quad9 DNS)"
};
var DIAGNOSTICS_UPDATE_INTERVAL = 1e4;
var CACHE_TIMEOUT = DIAGNOSTICS_UPDATE_INTERVAL - 1e3;
var ERROR_POLL_INTERVAL = 1e4;
var COMMAND_TIMEOUT = 1e4;
var FETCH_TIMEOUT = 1e4;
var BUTTON_FEEDBACK_TIMEOUT = 1e3;
var DIAGNOSTICS_INITIAL_DELAY = 100;
var COMMAND_SCHEDULING = {
P0_PRIORITY: 0,
// Highest priority (no delay)
P1_PRIORITY: 100,
// Very high priority
P2_PRIORITY: 300,
// High priority
P3_PRIORITY: 500,
// Above average
P4_PRIORITY: 700,
// Standard priority
P5_PRIORITY: 900,
// Below average
P6_PRIORITY: 1100,
// Low priority
P7_PRIORITY: 1300,
// Very low priority
P8_PRIORITY: 1500,
// Background execution
P9_PRIORITY: 1700,
// Idle mode execution
P10_PRIORITY: 1900
// Lowest priority
};
// src/podkop/methods/custom/getConfigSections.ts
async function getConfigSections() {
return uci.load("podkop").then(() => uci.sections("podkop"));
return uci.load(PODKOP_UCI_PACKAGE).then(() => uci.sections(PODKOP_UCI_PACKAGE));
}
// src/podkop/methods/shell/callBaseMethod.ts
@@ -907,119 +1025,6 @@ var CustomPodkopMethods = {
getClashApiSecret
};
// src/constants.ts
var STATUS_COLORS = {
SUCCESS: "#4caf50",
ERROR: "#f44336",
WARNING: "#ff9800"
};
var PODKOP_LUCI_APP_VERSION = "__COMPILED_VERSION_VARIABLE__";
var FAKEIP_CHECK_DOMAIN = "fakeip.podkop.fyi";
var IP_CHECK_DOMAIN = "ip.podkop.fyi";
var REGIONAL_OPTIONS = [
"russia_inside",
"russia_outside",
"ukraine_inside"
];
var ALLOWED_WITH_RUSSIA_INSIDE = [
"russia_inside",
"meta",
"twitter",
"discord",
"telegram",
"cloudflare",
"google_ai",
"google_play",
"hetzner",
"ovh",
"hodca",
"roblox",
"digitalocean",
"cloudfront"
];
var DOMAIN_LIST_OPTIONS = {
russia_inside: "Russia inside",
russia_outside: "Russia outside",
ukraine_inside: "Ukraine",
geoblock: "Geo Block",
block: "Block",
porn: "Porn",
news: "News",
anime: "Anime",
youtube: "Youtube",
discord: "Discord",
meta: "Meta",
twitter: "Twitter (X)",
hdrezka: "HDRezka",
tiktok: "Tik-Tok",
telegram: "Telegram",
cloudflare: "Cloudflare",
google_ai: "Google AI",
google_play: "Google Play",
hodca: "H.O.D.C.A",
roblox: "Roblox",
hetzner: "Hetzner ASN",
ovh: "OVH ASN",
digitalocean: "Digital Ocean ASN",
cloudfront: "CloudFront ASN"
};
var UPDATE_INTERVAL_OPTIONS = {
"1h": "Every hour",
"3h": "Every 3 hours",
"12h": "Every 12 hours",
"1d": "Every day",
"3d": "Every 3 days"
};
var DNS_SERVER_OPTIONS = {
"1.1.1.1": "1.1.1.1 (Cloudflare)",
"8.8.8.8": "8.8.8.8 (Google)",
"9.9.9.9": "9.9.9.9 (Quad9)",
"dns.adguard-dns.com": "dns.adguard-dns.com (AdGuard Default)",
"unfiltered.adguard-dns.com": "unfiltered.adguard-dns.com (AdGuard Unfiltered)",
"family.adguard-dns.com": "family.adguard-dns.com (AdGuard Family)"
};
var BOOTSTRAP_DNS_SERVER_OPTIONS = {
"77.88.8.8": "77.88.8.8 (Yandex DNS)",
"77.88.8.1": "77.88.8.1 (Yandex DNS)",
"1.1.1.1": "1.1.1.1 (Cloudflare DNS)",
"1.0.0.1": "1.0.0.1 (Cloudflare DNS)",
"8.8.8.8": "8.8.8.8 (Google DNS)",
"8.8.4.4": "8.8.4.4 (Google DNS)",
"9.9.9.9": "9.9.9.9 (Quad9 DNS)",
"9.9.9.11": "9.9.9.11 (Quad9 DNS)"
};
var DIAGNOSTICS_UPDATE_INTERVAL = 1e4;
var CACHE_TIMEOUT = DIAGNOSTICS_UPDATE_INTERVAL - 1e3;
var ERROR_POLL_INTERVAL = 1e4;
var COMMAND_TIMEOUT = 1e4;
var FETCH_TIMEOUT = 1e4;
var BUTTON_FEEDBACK_TIMEOUT = 1e3;
var DIAGNOSTICS_INITIAL_DELAY = 100;
var COMMAND_SCHEDULING = {
P0_PRIORITY: 0,
// Highest priority (no delay)
P1_PRIORITY: 100,
// Very high priority
P2_PRIORITY: 300,
// High priority
P3_PRIORITY: 500,
// Above average
P4_PRIORITY: 700,
// Standard priority
P5_PRIORITY: 900,
// Below average
P6_PRIORITY: 1100,
// Low priority
P7_PRIORITY: 1300,
// Very low priority
P8_PRIORITY: 1500,
// Background execution
P9_PRIORITY: 1700,
// Idle mode execution
P10_PRIORITY: 1900
// Lowest priority
};
// src/podkop/api.ts
async function createBaseApiRequest(fetchFn, options) {
const wrappedFn = () => options?.timeoutMs && options?.operationName ? withTimeout(
@@ -2481,11 +2486,11 @@ async function initController() {
// src/podkop/tabs/dashboard/styles.ts
var styles = `
#cbi-podkop-dashboard-_mount_node > div {
#cbi-${PODKOP_CBI_PREFIX}-dashboard-_mount_node > div {
width: 100%;
}
#cbi-podkop-dashboard > h3 {
#cbi-${PODKOP_CBI_PREFIX}-dashboard > h3 {
display: none;
}
@@ -4888,11 +4893,11 @@ async function initController2() {
// src/podkop/tabs/diagnostic/styles.ts
var styles4 = `
#cbi-podkop-diagnostic-_mount_node > div {
#cbi-${PODKOP_CBI_PREFIX}-diagnostic-_mount_node > div {
width: 100%;
}
#cbi-podkop-diagnostic > h3 {
#cbi-${PODKOP_CBI_PREFIX}-diagnostic > h3 {
display: none;
}
@@ -5091,55 +5096,55 @@ ${PartialStyles}
/* Hide extra H3 for settings tab */
#cbi-podkop-settings > h3 {
#cbi-${PODKOP_CBI_PREFIX}-settings > h3 {
display: none;
}
/* Hide extra H3 for rules tab */
#cbi-podkop-rule > h3:nth-child(1) {
#cbi-${PODKOP_CBI_PREFIX}-rule > h3:nth-child(1) {
display: none;
}
/* Hide extra H3 for nodes tab */
#cbi-podkop-node > h3:nth-child(1) {
#cbi-${PODKOP_CBI_PREFIX}-node > h3:nth-child(1) {
display: none;
}
/* Hide extra H3 for rule set tab */
#cbi-podkop-ruleset > h3:nth-child(1) {
#cbi-${PODKOP_CBI_PREFIX}-ruleset > h3:nth-child(1) {
display: none;
}
/* Vertical align for remove rule action button */
#cbi-podkop-rule > .cbi-section-remove {
#cbi-${PODKOP_CBI_PREFIX}-rule > .cbi-section-remove {
margin-bottom: -32px;
}
#cbi-podkop-rule .cbi-section-actions > div {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-actions > div {
display: inline-flex;
align-items: center;
gap: 4px;
}
/* Rule reorder visuals */
#cbi-podkop-rule {
#cbi-${PODKOP_CBI_PREFIX}-rule {
position: relative;
}
#cbi-podkop-rule .cbi-section-table-row {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row {
position: relative;
}
#cbi-podkop-rule .cbi-section-table-row.placeholder {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.placeholder {
opacity: 1;
}
#cbi-podkop-rule .cbi-section-table-row.placeholder em {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.placeholder em {
font-style: italic;
}
#cbi-podkop-rule .cbi-section-table-row.drag-over-above::after,
#cbi-podkop-rule .cbi-section-table-row.drag-over-below::after {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.drag-over-above::after,
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.drag-over-below::after {
content: '';
position: absolute;
left: 10px;
@@ -5151,17 +5156,17 @@ ${PartialStyles}
z-index: 2;
}
#cbi-podkop-rule .cbi-section-table-row.drag-over-above::after {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.drag-over-above::after {
top: -1px;
}
#cbi-podkop-rule .cbi-section-table-row.drag-over-below::after {
#cbi-${PODKOP_CBI_PREFIX}-rule .cbi-section-table-row.drag-over-below::after {
bottom: -1px;
}
/* Vertical align for remove node action button */
#cbi-podkop-node > .cbi-section-remove,
#cbi-podkop-ruleset > .cbi-section-remove {
#cbi-${PODKOP_CBI_PREFIX}-node > .cbi-section-remove,
#cbi-${PODKOP_CBI_PREFIX}-ruleset > .cbi-section-remove {
margin-bottom: -32px;
}
@@ -5421,7 +5426,12 @@ return baseclass.extend({
FETCH_TIMEOUT,
IP_CHECK_DOMAIN,
Logger,
PODKOP_CBI_PREFIX,
PODKOP_LUCI_APP_VERSION,
PODKOP_LUCI_I18N_DOMAIN,
PODKOP_LUCI_VIEW_DIR,
PODKOP_LUCI_VIEW_NAMESPACE,
PODKOP_UCI_PACKAGE,
PodkopShellMethods,
REGIONAL_OPTIONS,
RemoteFakeIPMethods,
@@ -2,7 +2,7 @@
"require form";
"require baseclass";
"require tools.widgets as widgets";
"require view.podkop.main as main";
"require view.podkop_plus.main as main";
function createNodeContent(section) {
let o = section.option(form.Flag, "enabled", _("Enable"));
@@ -4,19 +4,22 @@
"require baseclass";
"require uci";
"require ui";
"require view.podkop.main as main";
"require view.podkop_plus.main as main";
// Global settings
"require view.podkop.settings as settings";
"require view.podkop_plus.settings as settings";
// Sections
"require view.podkop.section as section";
"require view.podkop_plus.section as section";
// Dashboard
"require view.podkop.dashboard as dashboard";
"require view.podkop_plus.dashboard as dashboard";
// Diagnostic
"require view.podkop.diagnostic as diagnostic";
"require view.podkop_plus.diagnostic as diagnostic";
const UCI_PACKAGE = main.PODKOP_UCI_PACKAGE;
const CBI_PREFIX = main.PODKOP_CBI_PREFIX;
function renderSectionAdd(sectionRef, extra_class) {
const el = form.GridSection.prototype.renderSectionAdd.apply(sectionRef, [
@@ -53,7 +56,7 @@ function renderSectionAdd(sectionRef, extra_class) {
}
function repaintRuleRowColors() {
const container = document.getElementById("cbi-podkop-rule");
const container = document.getElementById(`cbi-${CBI_PREFIX}-rule`);
if (!container) {
return;
}
@@ -62,7 +65,7 @@ function repaintRuleRowColors() {
container.querySelectorAll(".cbi-section-table-row"),
).filter(
(row) =>
row.closest("#cbi-podkop-rule") === container &&
row.closest(`#cbi-${CBI_PREFIX}-rule`) === container &&
!row.classList.contains("placeholder"),
);
@@ -278,7 +281,7 @@ function installRulePendingChanges(sectionRef) {
}
function installRuleRowInteractionSync() {
const container = document.getElementById("cbi-podkop-rule");
const container = document.getElementById(`cbi-${CBI_PREFIX}-rule`);
if (!container || container.__pdkRowColorSyncBound) {
return;
}
@@ -332,11 +335,11 @@ function configureGridSection(sectionRef, type, title, addTitle) {
sectionRef.rowcolors = true;
sectionRef.nodescriptions = true;
sectionRef.modaltitle = function (section_id) {
const label = uci.get("podkop", section_id, "label");
const label = uci.get(UCI_PACKAGE, section_id, "label");
return section_id ? `${title}: ${label || section_id}` : addTitle;
};
sectionRef.sectiontitle = function (section_id) {
return uci.get("podkop", section_id, "label") || section_id;
return uci.get(UCI_PACKAGE, section_id, "label") || section_id;
};
sectionRef.renderSectionAdd = function (extra_class) {
return renderSectionAdd(sectionRef, extra_class);
@@ -365,7 +368,7 @@ const EntryPoint = {
main.injectGlobalStyles();
const podkopMap = new form.Map(
"podkop",
UCI_PACKAGE,
_("Podkop Plus Settings"),
_("Configuration for Podkop Plus service"),
);
@@ -2,7 +2,9 @@
"require form";
"require baseclass";
"require uci";
"require view.podkop.main as main";
"require view.podkop_plus.main as main";
const UCI_PACKAGE = main.PODKOP_UCI_PACKAGE;
function createRulesetContent(section) {
let o = section.option(form.Flag, "enabled", _("Enable"));
@@ -69,7 +71,7 @@ function createRulesetContent(section) {
delete this.vallist;
this.value("", _("Direct"));
uci.sections("podkop", "node", (node) => {
uci.sections(UCI_PACKAGE, "node", (node) => {
if (node[".name"] !== section_id && node.enabled !== "0") {
this.value(node[".name"], node[".name"]);
}
@@ -5,7 +5,9 @@
"require ui";
"require tools.widgets as widgets";
"require uci";
"require view.podkop.main as main";
"require view.podkop_plus.main as main";
const UCI_PACKAGE = main.PODKOP_UCI_PACKAGE;
function valuesToText(values) {
if (!values) {
@@ -204,12 +206,12 @@ function isZapretInstalledForUi() {
}
function getRuleResolvedAction(section_id) {
const action = uci.get("podkop", section_id, "action");
const action = uci.get(UCI_PACKAGE, section_id, "action");
if (action) {
return `${action}`;
}
const connectionType = uci.get("podkop", section_id, "connection_type");
const connectionType = uci.get(UCI_PACKAGE, section_id, "connection_type");
switch (connectionType) {
case "proxy":
case "vpn":
@@ -285,16 +287,16 @@ function disableUnavailableZapretOption(node) {
}
function getConfigListValues(section_id, key) {
return normalizeOptionValues(uci.get("podkop", section_id, key));
return normalizeOptionValues(uci.get(UCI_PACKAGE, section_id, key));
}
function writeListOption(section_id, key, values) {
const normalized = normalizeOptionValues(values);
if (normalized.length) {
uci.set("podkop", section_id, key, normalized);
uci.set(UCI_PACKAGE, section_id, key, normalized);
} else {
uci.unset("podkop", section_id, key);
uci.unset(UCI_PACKAGE, section_id, key);
}
}
@@ -1382,14 +1384,14 @@ function addDynamicConditionField(section, config) {
return values;
}
const legacyText = uci.get("podkop", section_id, `${config.key}_text`);
const legacyText = uci.get(UCI_PACKAGE, section_id, `${config.key}_text`);
return legacyText ? main.parseValueList(legacyText) : [];
};
o.write = function (section_id, value) {
writeListOption(section_id, config.key, value);
uci.unset("podkop", section_id, `${config.key}_text`);
uci.unset("podkop", section_id, `${config.key}_text_mode`);
uci.unset(UCI_PACKAGE, section_id, `${config.key}_text`);
uci.unset(UCI_PACKAGE, section_id, `${config.key}_text_mode`);
};
}
@@ -1417,25 +1419,25 @@ function addTextConditionField(section, config) {
configureTextareaOption(o, config.textAnalyze);
o.load = function (section_id) {
const textValue = uci.get("podkop", section_id, `${config.key}_text`);
const textValue = uci.get(UCI_PACKAGE, section_id, `${config.key}_text`);
if (textValue) {
return textValue;
}
return valuesToText(uci.get("podkop", section_id, config.key));
return valuesToText(uci.get(UCI_PACKAGE, section_id, config.key));
};
o.write = function (section_id, value) {
const normalized = value ? `${value}`.trim() : "";
if (normalized.length) {
uci.set("podkop", section_id, `${config.key}_text`, normalized);
uci.set(UCI_PACKAGE, section_id, `${config.key}_text`, normalized);
} else {
uci.unset("podkop", section_id, `${config.key}_text`);
uci.unset(UCI_PACKAGE, section_id, `${config.key}_text`);
}
uci.unset("podkop", section_id, config.key);
uci.unset("podkop", section_id, `${config.key}_text_mode`);
uci.unset(UCI_PACKAGE, section_id, config.key);
uci.unset(UCI_PACKAGE, section_id, `${config.key}_text_mode`);
};
}
@@ -1546,7 +1548,7 @@ function createSectionContent(section) {
o.rmempty = false;
o.modalonly = true;
o.load = function (section_id) {
return uci.get("podkop", section_id, "label") || section_id;
return uci.get(UCI_PACKAGE, section_id, "label") || section_id;
};
o = section.taboption(
@@ -1591,7 +1593,7 @@ function createSectionContent(section) {
o.textarea = true;
o.modalonly = true;
o.load = function (section_id) {
const value = uci.get("podkop", section_id, "nfqws_opt");
const value = uci.get(UCI_PACKAGE, section_id, "nfqws_opt");
if (!value || value === ZAPRET_LEGACY_DEFAULT_NFQWS_OPT) {
return ZAPRET_DEFAULT_NFQWS_OPT;
}
@@ -1605,7 +1607,7 @@ function createSectionContent(section) {
? ZAPRET_DEFAULT_NFQWS_OPT
: normalized;
uci.set("podkop", section_id, "nfqws_opt", nextValue);
uci.set(UCI_PACKAGE, section_id, "nfqws_opt", nextValue);
};
o.validate = function (_section_id, value) {
const analysis = analyzeNfqwsStrategy(value);
@@ -3,7 +3,9 @@
"require uci";
"require baseclass";
"require tools.widgets as widgets";
"require view.podkop.main as main";
"require view.podkop_plus.main as main";
const UCI_PACKAGE = main.PODKOP_UCI_PACKAGE;
function createSettingsContent(section) {
let o = section.option(
@@ -301,10 +303,10 @@ function createSettingsContent(section) {
o.rmempty = false;
o.depends("download_lists_via_proxy", "1");
o.cfgvalue = function (section_id) {
return uci.get("podkop", section_id, "download_lists_via_proxy_section");
return uci.get(UCI_PACKAGE, section_id, "download_lists_via_proxy_section");
};
o.load = function () {
const sections = this.map?.data?.state?.values?.podkop ?? {};
const sections = this.map?.data?.state?.values?.[UCI_PACKAGE] ?? {};
this.keylist = [];
this.vallist = [];
+3 -3
View File
@@ -2,7 +2,7 @@
set -euo pipefail
PODIR="po"
POTFILE="$PODIR/templates/podkop.pot"
POTFILE="$PODIR/templates/podkop_plus.pot"
WIDTH=120
if [ $# -ne 1 ]; then
@@ -11,7 +11,7 @@ if [ $# -ne 1 ]; then
fi
LANG="$1"
POFILE="$PODIR/$LANG/podkop.po"
POFILE="$PODIR/$LANG/podkop_plus.po"
if [ ! -f "$POTFILE" ]; then
echo "Template $POTFILE not found. Run xgettext first."
@@ -27,4 +27,4 @@ else
msginit --no-translator --no-location --locale="$LANG" --width="$WIDTH" --input="$POTFILE" --output-file="$POFILE"
fi
echo "Translation file for $LANG updated."
echo "Translation file for $LANG updated."
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PODKOP PLUS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-04-11 21:49+0300\n"
"PO-Revision-Date: 2026-04-11 21:49+0300\n"
"POT-Creation-Date: 2026-04-11 01:33+0300\n"
"PO-Revision-Date: 2026-04-11 01:33+0300\n"
"Last-Translator: ushan0v\n"
"Language-Team: none\n"
"Language: ru\n"
@@ -4,11 +4,11 @@
"order": 42,
"action": {
"type": "view",
"path": "podkop/podkop"
"path": "podkop_plus/podkop"
},
"depends": {
"acl": [ "luci-app-podkop-plus" ],
"uci": { "podkop": true }
"uci": { "podkop_plus": true }
}
}
}
@@ -16,12 +16,12 @@
]
},
"uci": [
"podkop"
"podkop_plus"
]
},
"write": {
"uci": [
"podkop"
"podkop_plus"
]
}
}
+2 -2
View File
@@ -2,7 +2,7 @@
set -euo pipefail
SRC_DIR="htdocs/luci-static/resources/view/podkop"
OUT_POT="po/templates/podkop.pot"
OUT_POT="po/templates/podkop_plus.pot"
ENCODING="UTF-8"
WIDTH=120
@@ -24,4 +24,4 @@ xgettext --language=JavaScript \
--package-name="PODKOP" \
"${FILES[@]}"
echo "POT template generated: $OUT_POT"
echo "POT template generated: $OUT_POT"
+1 -1
View File
@@ -6,7 +6,7 @@ USE_PROCD=1
script=$(readlink "$initscript")
NAME="$(basename ${script:-$initscript})"
CONFIG_NAME="podkop"
CONFIG_NAME="podkop_plus"
PODKOP_BIN="/usr/bin/podkop-plus"
PODKOP_SERVICE_INIT="/etc/init.d/podkop-plus"
PODKOP_RELOAD_LOCK_DIR="/var/run/podkop-plus.reload.lock"
+24 -33
View File
@@ -40,7 +40,7 @@ PODKOP_RELOAD_STATE_FORMAT=1
PODKOP_NFT_POPULATE_ENABLED=1
PODKOP_ZAPRET_MISSING_WARNING_EMITTED=0
config_load "$PODKOP_CONFIG"
config_load "$PODKOP_CONFIG_NAME"
ensure_runtime_dirs() {
mkdir -p "$TMP_SING_BOX_FOLDER"
@@ -538,7 +538,7 @@ commit_podkop_config() {
# and stopping. Mark these commits so the init trigger can ignore the
# self-induced config.change event instead of scheduling another reload.
: > "$PODKOP_INTERNAL_CONFIG_TRIGGER_GUARD"
uci commit "podkop" && config_load "$PODKOP_CONFIG"
uci commit "$PODKOP_CONFIG_NAME" && config_load "$PODKOP_CONFIG_NAME"
}
migrate_legacy_section_to_rule() {
@@ -551,16 +551,16 @@ migrate_legacy_section_to_rule() {
[ -z "$label" ] && label="$section"
uci set "podkop.$section=rule"
uci set "podkop.$section.label=$label"
uci set "podkop.$section.enabled=1"
uci set "$PODKOP_CONFIG_NAME.$section=rule"
uci set "$PODKOP_CONFIG_NAME.$section.label=$label"
uci set "$PODKOP_CONFIG_NAME.$section.enabled=1"
if [ -n "$action" ]; then
uci set "podkop.$section.action=$action"
uci set "$PODKOP_CONFIG_NAME.$section.action=$action"
fi
if [ -n "$proxy_config_type" ]; then
uci set "podkop.$section.proxy_config_type=$proxy_config_type"
uci set "$PODKOP_CONFIG_NAME.$section.proxy_config_type=$proxy_config_type"
fi
legacy_migration_changed=1
@@ -610,15 +610,15 @@ migrate_builtin_rulesets_to_community_lists() {
[ "$moved" -eq 1 ] || return 0
log "Migrating built-in rule sets from rule_set to community_lists for '$section'"
uci -q delete "podkop.$section.rule_set"
uci -q delete "podkop.$section.community_lists"
uci -q delete "$PODKOP_CONFIG_NAME.$section.rule_set"
uci -q delete "$PODKOP_CONFIG_NAME.$section.community_lists"
for reference in $next_community_lists; do
uci add_list "podkop.$section.community_lists=$reference"
uci add_list "$PODKOP_CONFIG_NAME.$section.community_lists=$reference"
done
for reference in $next_rule_set; do
uci add_list "podkop.$section.rule_set=$reference"
uci add_list "$PODKOP_CONFIG_NAME.$section.rule_set=$reference"
done
legacy_migration_changed=1
@@ -636,7 +636,7 @@ migrate_legacy_zapret_nfqws_default() {
[ "$nfqws_opt" = "$ZAPRET_LEGACY_DEFAULT_NFQWS_OPT" ] || return 0
log "Migrating legacy built-in NFQWS strategy for '$section' to the Podkop Plus compatible default"
uci set "podkop.$section.nfqws_opt=$ZAPRET_DEFAULT_NFQWS_OPT"
uci set "$PODKOP_CONFIG_NAME.$section.nfqws_opt=$ZAPRET_DEFAULT_NFQWS_OPT"
legacy_migration_changed=1
}
@@ -795,7 +795,7 @@ start() {
dnsmasq_configure
fi
uci_set "podkop" "settings" "shutdown_correctly" 0
uci_set "$PODKOP_CONFIG_NAME" "settings" "shutdown_correctly" 0
commit_podkop_config
capture_reload_state
write_reload_state
@@ -810,7 +810,7 @@ stop() {
stop_main
uci_set "podkop" "settings" "shutdown_correctly" 1
uci_set "$PODKOP_CONFIG_NAME" "settings" "shutdown_correctly" 1
commit_podkop_config
clear_reload_state
}
@@ -1007,26 +1007,17 @@ uninstall() {
package_manager_remove_if_installed "luci-i18n-podkop-plus-ru"
package_manager_remove_if_installed "luci-app-podkop-plus"
package_manager_remove_if_installed "luci-i18n-podkop-ru"
package_manager_remove_if_installed "luci-app-podkop"
package_manager_remove_if_installed "podkop"
rm -rf /usr/lib/podkop-plus
rm -rf /usr/lib/podkop
rm -rf /www/luci-static/resources/view/podkop
rm -rf "$PODKOP_LUCI_VIEW_DIR"
rm -f "$PODKOP_SERVICE_INIT"
rm -f "$PODKOP_BIN"
rm -f /etc/init.d/podkop
rm -f /usr/bin/podkop
rm -f /usr/share/luci/menu.d/luci-app-podkop-plus.json
rm -f /usr/share/rpcd/acl.d/luci-app-podkop-plus.json
rm -f /usr/share/luci/menu.d/luci-app-podkop.json
rm -f /usr/share/rpcd/acl.d/luci-app-podkop.json
rm -f /etc/uci-defaults/50_luci-podkop-plus
rm -f /etc/uci-defaults/50_luci-podkop
rm -f /usr/lib/lua/luci/i18n/podkop.*.lmo
rm -f /usr/lib/lua/luci/i18n/podkop.ru.lua
rm -f /usr/lib/lua/luci/i18n/podkop.en.lua
rm -f "/usr/lib/lua/luci/i18n/${PODKOP_LUCI_I18N_DOMAIN}."*.lmo
rm -f "/usr/lib/lua/luci/i18n/${PODKOP_LUCI_I18N_DOMAIN}.ru.lua"
rm -f "/usr/lib/lua/luci/i18n/${PODKOP_LUCI_I18N_DOMAIN}.en.lua"
rm -f /var/luci-indexcache*
rm -f /tmp/luci-indexcache*
[ -x /etc/init.d/rpcd ] && /etc/init.d/rpcd reload >/dev/null 2>&1 || true
@@ -1038,7 +1029,7 @@ uninstall() {
migration() {
legacy_migration_changed=0
if ! uci show podkop | grep -q "=section"; then
if ! uci show "$PODKOP_CONFIG_NAME" | grep -q "=section"; then
config_foreach migrate_builtin_rulesets_to_community_lists "rule"
config_foreach migrate_legacy_zapret_nfqws_default "rule"
if [ "$legacy_migration_changed" -eq 1 ]; then
@@ -3137,13 +3128,13 @@ get_first_outbound_section() {
get_sections_by_connection_type() {
local connection_type="$1"
uci show podkop | grep "\.connection_type='$connection_type'" | cut -d'.' -f2
uci show "$PODKOP_CONFIG_NAME" | grep "\.connection_type='$connection_type'" | cut -d'.' -f2
}
section_by_connection_type_exists() {
local connection_type="$1"
if uci show podkop | grep -q "\.connection_type='$connection_type'"; then
if uci show "$PODKOP_CONFIG_NAME" | grep -q "\.connection_type='$connection_type'"; then
return 0
else
return 1
@@ -3374,7 +3365,7 @@ check_logs() {
fi
local logs
logs=$(logread | grep -E "podkop-plus|podkop|sing-box")
logs=$(logread | grep -E "podkop-plus|sing-box")
if [ -z "$logs" ]; then
nolog "Logs not found"
@@ -3561,8 +3552,8 @@ get_system_info() {
podkop_latest_version="$(get_podkop_latest_version)"
[ -n "$podkop_latest_version" ] || podkop_latest_version="unknown"
if [ -f /www/luci-static/resources/view/podkop/main.js ]; then
luci_app_version=$(grep 'var PODKOP_LUCI_APP_VERSION' /www/luci-static/resources/view/podkop/main.js | cut -d'"' -f2)
if [ -f "$PODKOP_LUCI_VIEW_DIR/main.js" ]; then
luci_app_version=$(grep 'var PODKOP_LUCI_APP_VERSION' "$PODKOP_LUCI_VIEW_DIR/main.js" | cut -d'"' -f2)
else
luci_app_version="not installed"
fi
+5 -1
View File
@@ -2,12 +2,16 @@
PODKOP_APP_NAME="Podkop Plus"
PODKOP_VERSION="__COMPILED_VERSION_VARIABLE__"
PODKOP_CONFIG="/etc/config/podkop"
PODKOP_CONFIG_NAME="podkop_plus"
PODKOP_CONFIG="/etc/config/$PODKOP_CONFIG_NAME"
PODKOP_BIN="/usr/bin/podkop-plus"
PODKOP_SERVICE_NAME="podkop-plus"
PODKOP_SERVICE_INIT="/etc/init.d/podkop-plus"
PODKOP_LIB_DIR="/usr/lib/podkop-plus"
PODKOP_RELEASE_REPO="ushan0v/podkop-plus"
PODKOP_LUCI_VIEW_NAMESPACE="podkop_plus"
PODKOP_LUCI_VIEW_DIR="/www/luci-static/resources/view/$PODKOP_LUCI_VIEW_NAMESPACE"
PODKOP_LUCI_I18N_DOMAIN="podkop_plus"
## Common
RESOLV_CONF="/etc/resolv.conf"
DNS_RESOLVERS="1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 9.9.9.9 9.9.9.11 94.140.14.14 94.140.15.15 208.67.220.220 208.67.222.222 77.88.8.1 77.88.8.8"
+11 -2
View File
@@ -920,8 +920,17 @@ zapret_standalone_uci_config_present() {
}
sync_zapret_standalone_config() {
[ -x "$ZAPRET_SOURCE_BASE_DIR/renew-cfg.sh" ] || return 0
"$ZAPRET_SOURCE_BASE_DIR/renew-cfg.sh" sync >/dev/null 2>&1
if [ -x "$ZAPRET_SOURCE_BASE_DIR/sync_config.sh" ]; then
"$ZAPRET_SOURCE_BASE_DIR/sync_config.sh" >/dev/null 2>&1
return $?
fi
if [ -x "$ZAPRET_SOURCE_BASE_DIR/renew-cfg.sh" ]; then
"$ZAPRET_SOURCE_BASE_DIR/renew-cfg.sh" sync >/dev/null 2>&1
return $?
fi
return 0
}
neutralize_zapret_standalone_defaults() {
+16 -6
View File
@@ -228,24 +228,34 @@ build_app_root() {
cp -a "$ROOT_DIR/luci-app-podkop-plus/htdocs/." "$output_root/www/"
fi
if [[ -d "$output_root/www/luci-static/resources/view/podkop" ]]; then
rm -rf "$output_root/www/luci-static/resources/view/podkop_plus"
mv "$output_root/www/luci-static/resources/view/podkop" \
"$output_root/www/luci-static/resources/view/podkop_plus"
fi
if [[ -d "$ROOT_DIR/luci-app-podkop-plus/root" ]]; then
cp -a "$ROOT_DIR/luci-app-podkop-plus/root/." "$output_root/"
fi
install -m 0755 "$ROOT_DIR/podkop/files/etc/init.d/podkop" "$output_root/etc/init.d/podkop-plus"
install -m 0644 "$ROOT_DIR/podkop/files/etc/config/podkop" "$output_root/etc/config/podkop"
install -m 0644 "$ROOT_DIR/podkop/files/etc/config/podkop" "$output_root/etc/config/podkop_plus"
install -m 0755 "$ROOT_DIR/podkop/files/usr/bin/podkop" "$output_root/usr/bin/podkop-plus"
cp -a "$ROOT_DIR/podkop/files/usr/lib/." "$output_root/usr/lib/podkop-plus/"
if [[ -f "$output_root/www/luci-static/resources/view/podkop_plus/main.js" ]]; then
sed -i -e "s/__COMPILED_VERSION_VARIABLE__/${RELEASE_VERSION}/g" \
"$output_root/www/luci-static/resources/view/podkop_plus/main.js"
fi
sed -i -e "s/__COMPILED_VERSION_VARIABLE__/${RELEASE_VERSION}/g" \
"$output_root/www/luci-static/resources/view/podkop/main.js" \
"$output_root/usr/lib/podkop-plus/constants.sh"
}
build_i18n_root() {
local output_root="$1"
local po2lmo_bin="$2"
local lmo_path="$output_root/usr/lib/lua/luci/i18n/podkop.ru.lmo"
local lmo_path="$output_root/usr/lib/lua/luci/i18n/podkop_plus.ru.lmo"
rm -rf "$output_root"
make_dir "$output_root/etc/uci-defaults"
@@ -255,7 +265,7 @@ build_i18n_root() {
uci set luci.languages.ru='Русский (Russian)'; uci commit luci
EOF
"$po2lmo_bin" "$ROOT_DIR/luci-app-podkop-plus/po/ru/podkop.po" "$lmo_path"
"$po2lmo_bin" "$ROOT_DIR/luci-app-podkop-plus/po/ru/podkop_plus.po" "$lmo_path"
}
generate_apk_metadata_files() {
@@ -306,7 +316,7 @@ Description: ${APP_DESCRIPTION}
EOF
cat > "$control_dir/conffiles" <<'EOF'
/etc/config/podkop
/etc/config/podkop_plus
EOF
cat > "$control_dir/postinst" <<'EOF'
@@ -692,7 +702,7 @@ main() {
build_app_root "$app_root"
build_i18n_root "$i18n_root" "$po2lmo_bin"
generate_apk_metadata_files "luci-app-podkop-plus" "$app_root" "/etc/config/podkop"
generate_apk_metadata_files "luci-app-podkop-plus" "$app_root" "/etc/config/podkop_plus"
generate_apk_metadata_files "luci-i18n-podkop-plus-ru" "$i18n_root"
app_size="$(installed_size_bytes "$app_root")"
+34 -21
View File
@@ -605,33 +605,43 @@ replace_dir() {
mv "$tmp" "$dest"
}
if [ -x /etc/init.d/podkop ]; then
/etc/init.d/podkop running >/dev/null 2>&1 && /etc/init.d/podkop stop >/dev/null 2>&1 || true
/etc/init.d/podkop enabled >/dev/null 2>&1 && /etc/init.d/podkop disable >/dev/null 2>&1 || true
fi
[ -x /etc/init.d/podkop-plus ] && /etc/init.d/podkop-plus stop >/dev/null 2>&1 || true
[ -x /etc/init.d/podkop ] && /etc/init.d/podkop stop >/dev/null 2>&1 || true
[ -x /etc/init.d/podkop ] && /etc/init.d/podkop disable >/dev/null 2>&1 || true
replace_file "$BUNDLE_DIR/etc/init.d/podkop-plus" "/etc/init.d/podkop-plus" 0755
replace_file "$BUNDLE_DIR/usr/bin/podkop-plus" "/usr/bin/podkop-plus" 0755
replace_dir "$BUNDLE_DIR/usr/lib/podkop-plus" "/usr/lib/podkop-plus"
replace_dir "$BUNDLE_DIR/www/luci-static/resources/view/podkop" "/www/luci-static/resources/view/podkop"
replace_dir "$BUNDLE_DIR/www/luci-static/resources/view/podkop_plus" "/www/luci-static/resources/view/podkop_plus"
replace_file "$BUNDLE_DIR/usr/share/luci/menu.d/luci-app-podkop-plus.json" "/usr/share/luci/menu.d/luci-app-podkop-plus.json" 0644
replace_file "$BUNDLE_DIR/usr/share/rpcd/acl.d/luci-app-podkop-plus.json" "/usr/share/rpcd/acl.d/luci-app-podkop-plus.json" 0644
replace_file "$BUNDLE_DIR/usr/lib/lua/luci/i18n/podkop.ru.lmo" "/usr/lib/lua/luci/i18n/podkop.ru.lmo" 0644
replace_file "$BUNDLE_DIR/usr/lib/lua/luci/i18n/podkop_plus.ru.lmo" "/usr/lib/lua/luci/i18n/podkop_plus.ru.lmo" 0644
replace_file "$BUNDLE_DIR/etc/uci-defaults/50_luci-podkop-plus" "/etc/uci-defaults/50_luci-podkop-plus" 0755
if [ ! -f /etc/config/podkop ]; then
replace_file "$BUNDLE_DIR/etc/config/podkop" "/etc/config/podkop" 0644
fi
is_original_podkop_present() {
opkg list-installed 2>/dev/null | grep -Eq '^podkop([[:space:]-]|$)' ||
opkg list-installed 2>/dev/null | grep -Eq '^luci-app-podkop([[:space:]-]|$)' ||
[ -x /etc/init.d/podkop ] ||
[ -x /usr/bin/podkop ] ||
[ -d /usr/lib/podkop ] ||
[ -f /usr/share/luci/menu.d/luci-app-podkop.json ] ||
[ -f /usr/share/rpcd/acl.d/luci-app-podkop.json ]
}
rm -f /etc/init.d/podkop
rm -f /usr/bin/podkop
rm -f /usr/share/luci/menu.d/luci-app-podkop.json
rm -f /usr/share/rpcd/acl.d/luci-app-podkop.json
rm -rf /usr/lib/podkop
rm -f /usr/lib/lua/luci/i18n/podkop.ru.lua
rm -f /usr/lib/lua/luci/i18n/podkop.en.lua
rm -f /usr/lib/lua/luci/i18n/podkop.en.lmo
if [ ! -f /etc/config/podkop_plus ]; then
if [ -f /etc/config/podkop ] &&
{ [ -x /etc/init.d/podkop-plus ] || [ -x /usr/bin/podkop-plus ] || [ -d /usr/lib/podkop-plus ]; } &&
! is_original_podkop_present; then
cp /etc/config/podkop /etc/config/podkop_plus
chmod 0644 /etc/config/podkop_plus || true
else
replace_file "$BUNDLE_DIR/etc/config/podkop_plus" "/etc/config/podkop_plus" 0644
fi
fi
rm -f /var/luci-indexcache* /tmp/luci-indexcache*
[ -x /etc/init.d/rpcd ] && /etc/init.d/rpcd reload >/dev/null 2>&1 || true
@@ -669,7 +679,7 @@ wait_for_service() {
/etc/init.d/podkop-plus restart >/dev/null 2>&1 || true
echo "System LuCI language: $(uci -q get luci.main.lang || echo auto)"
echo "Podkop RU catalog: $( [ -f /usr/lib/lua/luci/i18n/podkop.ru.lmo ] && echo installed || echo absent )"
echo "Podkop Plus RU catalog: $( [ -f /usr/lib/lua/luci/i18n/podkop_plus.ru.lmo ] && echo installed || echo absent )"
echo "Autostart enabled: $(/etc/init.d/podkop-plus enabled >/dev/null 2>&1 && echo yes || echo no)"
echo "Service status:"
if ! wait_for_service; then
@@ -689,7 +699,7 @@ function New-DeployBundle {
$bundleFiles = @{
'podkop/files/etc/init.d/podkop' = 'etc/init.d/podkop-plus'
'podkop/files/etc/config/podkop' = 'etc/config/podkop'
'podkop/files/etc/config/podkop' = 'etc/config/podkop_plus'
'podkop/files/usr/bin/podkop' = 'usr/bin/podkop-plus'
'luci-app-podkop-plus/root/usr/share/luci/menu.d/luci-app-podkop-plus.json' = 'usr/share/luci/menu.d/luci-app-podkop-plus.json'
'luci-app-podkop-plus/root/usr/share/rpcd/acl.d/luci-app-podkop-plus.json' = 'usr/share/rpcd/acl.d/luci-app-podkop-plus.json'
@@ -704,13 +714,16 @@ function New-DeployBundle {
}
Copy-Tree -Source (Assert-RepoPath 'podkop/files/usr/lib') -Destination (Join-Path $StageRoot 'usr/lib/podkop-plus')
Copy-Tree -Source (Assert-RepoPath 'luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop') -Destination (Join-Path $StageRoot 'www/luci-static/resources/view/podkop')
Copy-Tree -Source (Assert-RepoPath 'luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop') -Destination (Join-Path $StageRoot 'www/luci-static/resources/view/podkop_plus')
Replace-VersionPlaceholder -Path (Join-Path $StageRoot 'usr/lib/podkop-plus/constants.sh') -Version $Version
Replace-VersionPlaceholder -Path (Join-Path $StageRoot 'www/luci-static/resources/view/podkop/main.js') -Version $Version
$mainJsPath = Join-Path $StageRoot 'www/luci-static/resources/view/podkop_plus/main.js'
if (Test-Path -LiteralPath $mainJsPath) {
Replace-VersionPlaceholder -Path $mainJsPath -Version $Version
}
$poPath = Assert-RepoPath 'luci-app-podkop-plus\po\ru\podkop.po'
$lmoPath = Join-Path $StageRoot 'usr/lib/lua/luci/i18n/podkop.ru.lmo'
$poPath = Assert-RepoPath 'luci-app-podkop-plus\po\ru\podkop_plus.po'
$lmoPath = Join-Path $StageRoot 'usr/lib/lua/luci/i18n/podkop_plus.ru.lmo'
New-Item -ItemType Directory -Path (Split-Path -Parent $lmoPath) -Force | Out-Null
Convert-PoToLmo -PoPath $poPath -LmoPath $lmoPath