mirror of
https://github.com/xweiba/location-spoofer.git
synced 2026-09-25 16:11:54 +08:00
84 lines
3.6 KiB
Bash
84 lines
3.6 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
CONFIG="$ROOT/Shared/AppRemoteConfiguration.swift"
|
|
CONTENT="$ROOT/App/ContentView.swift"
|
|
MAP="$ROOT/App/MapHomeView.swift"
|
|
SETUP="$ROOT/App/FirstSetupView.swift"
|
|
SETTINGS="$ROOT/App/SettingsView.swift"
|
|
|
|
fail() {
|
|
echo "FAIL: $1" >&2
|
|
exit 1
|
|
}
|
|
|
|
python3 - "$ROOT/version.txt" <<'PY' || exit 1
|
|
import json
|
|
import sys
|
|
|
|
with open(sys.argv[1], encoding="utf-8") as handle:
|
|
config = json.load(handle)
|
|
|
|
assert config["latestVersion"] == "1.0.2"
|
|
assert config["minimumSupportedVersion"] == "1.0.0"
|
|
assert "shadowrocket" not in config["communityPromptClients"]
|
|
assert set(config["communityPromptClients"]) == {
|
|
"surge", "quantumultX", "loon", "stash", "egern"
|
|
}
|
|
PY
|
|
|
|
grep -q 'static let fallback = AppRemoteConfiguration' "$CONFIG" \
|
|
|| fail "the app must ship a built-in remote-configuration fallback"
|
|
grep -q 'timeoutIntervalForRequest = 1.5' "$CONFIG" \
|
|
|| fail "remote configuration requests must use a short timeout"
|
|
grep -q 'timeoutIntervalForResource = 2' "$CONFIG" \
|
|
|| fail "remote configuration resource loading must use a short timeout"
|
|
! grep -q 'data.count' "$CONFIG" \
|
|
|| fail "the client must not impose a remote configuration file-size limit"
|
|
grep -q 'docs/releases/v\\(version).md' "$CONFIG" \
|
|
|| fail "update notes must come from the archived release document"
|
|
grep -q '/releases/latest' "$CONFIG" \
|
|
|| fail "missing release notes must fall back to the latest Release page"
|
|
grep -q '.task { await checkForUpdates() }' "$CONTENT" \
|
|
|| fail "update detection must run asynchronously outside bootstrap"
|
|
! grep -A90 'private func bootstrap() async' "$CONTENT" | grep -q 'fetch()' \
|
|
|| fail "remote configuration must not block the startup gate"
|
|
|
|
grep -q '社区分享成功配置?' "$MAP" \
|
|
|| fail "non-Shadowrocket success must offer community contribution"
|
|
grep -q 'Button("去提交")' "$MAP" \
|
|
|| fail "community contribution prompt must expose the submit action"
|
|
grep -q 'Button("复制模板")' "$MAP" \
|
|
|| fail "community contribution prompt must expose an explicit copy action"
|
|
grep -q 'Button("取消", role: .cancel)' "$MAP" \
|
|
|| fail "the first community prompts must expose cancel"
|
|
grep -q 'Button("不再提示", role: .cancel)' "$MAP" \
|
|
|| fail "the third community prompt must allow permanent suppression"
|
|
grep -q '匿名收录,不在 README 展示投稿账号' "$MAP" \
|
|
|| fail "the contribution template must offer anonymous README attribution"
|
|
grep -q 'community-config,client-\\(client.rawValue)' "$MAP" \
|
|
|| fail "community submissions must be categorized by client labels"
|
|
grep -q 'UIPasteboard.general.string = communityContributionIssueBody' "$MAP" \
|
|
|| fail "the explicit copy action must copy the issue template"
|
|
! grep -A25 'private func openCommunityContributionIssue' "$MAP" | grep -q 'UIPasteboard.general.string' \
|
|
|| fail "opening GitHub must not copy the template automatically"
|
|
|
|
for obsolete in \
|
|
'我已配置,开始检测' \
|
|
'确认完成,重新检测' \
|
|
'下一步:导入配置' \
|
|
'我已导入,检测接口连接'; do
|
|
! grep -q "$obsolete" "$SETUP" \
|
|
|| fail "setup footer must not retain dynamic label: $obsolete"
|
|
done
|
|
test "$(grep -c 'actionLabel("完成")' "$SETUP")" -eq 4 \
|
|
|| fail "all setup footer primary actions must use the fixed 完成 label"
|
|
|
|
application_line="$(grep -n 'Section("应用")' "$SETTINGS" | head -n 1 | cut -d: -f1)"
|
|
certificate_line="$(grep -n 'Section("证书")' "$SETTINGS" | head -n 1 | cut -d: -f1)"
|
|
test "$application_line" -lt "$certificate_line" \
|
|
|| fail "the APP certificate reset section must appear below the application section"
|
|
|
|
echo "PASS: update and community contribution contract"
|