Skip to content

Commit

Permalink
Merge pull request #136 from vvbbnn00/feat-sub-loon
Browse files Browse the repository at this point in the history
feat: add support for loon subscription format
  • Loading branch information
vvbbnn00 authored Mar 8, 2024
2 parents 0744926 + 8c3414b commit 52e9f07
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 1 deletion.
44 changes: 44 additions & 0 deletions services/subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,3 +393,47 @@ def generateSingBoxSubFile(account: Account = None,
sing_box_json["outbounds"][1]["outbounds"].extend(name_list)

return json.dumps(sing_box_json, ensure_ascii=False)


def generateLoonSubFile(account: Account = None,
logger=logging.getLogger(__name__),
random_name=False,
best=False,
ipv6=False):
"""
Generate Loon subscription file
:param account:
:param logger:
:param random_name:
:param best:
:param ipv6:
:return:
"""

account = getCurrentAccount(logger) if account is None else account

random_points, msg = getRandomEntryPoints(best, logger, ipv6)

if random_points is None:
return msg

# Initialize NodeNameGenerator
node_name_generator = NodeNameGenerator(random_name)
loon_list = []

# Use len() instead of RANDOM_COUNT because the entrypoints may be less than RANDOM_COUNT
for i in range(len(random_points)):
point = random_points[i]
country = GEOIP.lookup(point.ip)
country_emoji = GEOIP.lookup_emoji(point.ip)
name = node_name_generator.next(country_emoji, country)

if ipv6:
point.ip = f"[{point.ip}]"

loon_list.append(
'%s = WireGuard,interface-ip=172.16.0.2,private-key="%s",mtu=1280,dns=1.1.1.1,keepalive=30,peers='
'[{public-key="%s",allowed-ips="0.0.0.0/0,::0/0",endpoint=%s:%s}]' %
(name, account.private_key, CF_CONFIG.get("publicKey"), point.ip, point.port))

return "# Generated by WARP-Clash-API\n" + "\n".join(loon_list)
12 changes: 11 additions & 1 deletion services/web_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from services.account import resetAccountKey, doUpdateLicenseKey
from services.common import getCurrentAccount
from services.subscription import generateClashSubFile, generateWireguardSubFile, generateSurgeSubFile, \
generateShadowRocketSubFile, generateSingBoxSubFile
generateShadowRocketSubFile, generateSingBoxSubFile, generateLoonSubFile

RATE_LIMIT_MAP = {}

Expand Down Expand Up @@ -124,6 +124,8 @@ def httpAutoSub():
return httpSubscription("surge")
elif "sing-box" in user_agent: # Sing Box
return httpSubscription("sing-box")
elif "loon" in user_agent: # Loon
return httpSubscription("loon")

# By default, return Clash
return httpSubscription("clash")
Expand Down Expand Up @@ -242,6 +244,14 @@ def httpSubscription(sub_type: str):
ipv6=ipv6)
file_name = f'SingBox-{fake.color_name()}.json'

elif sub_type == 'loon': # Loon
file_data = generateLoonSubFile(account,
logger,
best=best,
random_name=random_name,
ipv6=ipv6)
file_name = f'Loon-{fake.color_name()}.conf'

# This might be deprecated in the future.
elif sub_type == "only_proxies": # Only proxies
file_data = generateClashSubFile(account,
Expand Down
6 changes: 6 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ <h2>ShadowRocket</h2>
<div id="qrcode_sr"></div>
<h2>Surge</h2>
<textarea id="subSurgeScriptionLink" rows="3" readonly onclick="copyText('subSurgeScriptionLink')"></textarea>
<h2>Sing-Box</h2>
<textarea id="subSingBoxScriptionLink" rows="3" readonly onclick="copyText('subSingBoxScriptionLink')"></textarea>
<h2>Loon</h2>
<textarea id="subLoonScriptionLink" rows="3" readonly onclick="copyText('subLoonScriptionLink')"></textarea>
<h2>Wireguard</h2>
<textarea id="WireguardLink" rows="3" readonly onclick="copyText('WireguardLink')"></textarea>
<div id="qrcode_wg"></div>
Expand Down Expand Up @@ -180,6 +184,8 @@ <h2>账户信息</h2>
document.getElementById('subscriptionLink').textContent = baseUrl + "api/clash?" + queryParams.toString();
document.getElementById('subShadowRocketSubscriptionLink').textContent = baseUrl + "api/shadowrocket?" + queryParams.toString();
document.getElementById('subSurgeScriptionLink').textContent = baseUrl + "api/surge?" + queryParams.toString();
document.getElementById('subSingBoxScriptionLink').textContent = baseUrl + "api/sing-box?" + queryParams.toString();
document.getElementById('subLoonScriptionLink').textContent = baseUrl + "api/loon?" + queryParams.toString();
document.getElementById('WireguardLink').textContent = baseUrl + "api/wireguard?" + queryParams.toString();
document.getElementById('AccountLink').href = baseUrl + "api/account?" + queryParams.toString();

Expand Down

0 comments on commit 52e9f07

Please sign in to comment.