mirror of
https://github.com/SukkaW/Surge.git
synced 2026-09-12 10:34:35 +08:00
Add ChatGPT Voice IP rules (#104)
Co-authored-by: SukkaW <isukkaw@gmail.com>
This commit is contained in:
84
Build/build-ai-cidr.ts
Normal file
84
Build/build-ai-cidr.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { fastIpVersion } from 'foxts/fast-ip-version';
|
||||
import { SHARED_DESCRIPTION } from './constants/description';
|
||||
import { $$fetch } from './lib/fetch-retry';
|
||||
import { RulesetOutput } from './lib/rules/ruleset';
|
||||
import { task } from './trace';
|
||||
|
||||
const OPENAI_VOICE_IP_URL = 'https://openai.com/chatgpt-voice.json';
|
||||
|
||||
function parseOpenAIVoiceJSON(data: unknown) {
|
||||
if (
|
||||
data === null
|
||||
|| typeof data !== 'object'
|
||||
|| !('prefixes' in data)
|
||||
|| !Array.isArray(data.prefixes)
|
||||
) {
|
||||
throw new TypeError('Invalid OpenAI Voice IP list: missing prefixes array');
|
||||
}
|
||||
|
||||
if (!('creationTime' in data) || typeof data.creationTime !== 'string') {
|
||||
throw new TypeError('Invalid OpenAI Voice IP list: missing creationTime');
|
||||
}
|
||||
|
||||
const lastUpdated = new Date(data.creationTime);
|
||||
if (Number.isNaN(lastUpdated.getTime())) {
|
||||
throw new TypeError('Invalid OpenAI Voice IP list: invalid creationTime');
|
||||
}
|
||||
|
||||
const cidr4 = new Set<string>();
|
||||
const cidr6 = new Set<string>();
|
||||
|
||||
for (let i = 0, len = data.prefixes.length; i < len; i++) {
|
||||
const entry = data.prefixes[i];
|
||||
if (typeof entry !== 'object' || entry == null) {
|
||||
throw new TypeError(`Invalid OpenAI Voice IP list entry at prefixes[${i}]`);
|
||||
}
|
||||
|
||||
const prefixes = Object.values(entry);
|
||||
if (prefixes.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let j = 0, prefixLen = prefixes.length; j < prefixLen; j++) {
|
||||
const prefix = prefixes[j];
|
||||
if (typeof prefix !== 'string') {
|
||||
throw new TypeError(`Invalid IP prefix at prefixes[${i}]`);
|
||||
}
|
||||
|
||||
const version = fastIpVersion(prefix);
|
||||
if (version === 4) {
|
||||
cidr4.add(prefix);
|
||||
} else if (version === 6) {
|
||||
cidr6.add(prefix);
|
||||
} else {
|
||||
throw new TypeError(`Invalid IP prefix at prefixes[${i}]`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
cidr4: Array.from(cidr4),
|
||||
cidr6: Array.from(cidr6),
|
||||
lastUpdated
|
||||
};
|
||||
}
|
||||
|
||||
export const buildAICIDR = task(require.main === module, __filename)(async (span) => {
|
||||
const { cidr4, cidr6, lastUpdated } = await span.traceChildAsync('get OpenAI Voice IP ranges', async () => {
|
||||
const response = await $$fetch(OPENAI_VOICE_IP_URL);
|
||||
return parseOpenAIVoiceJSON(await response.json());
|
||||
});
|
||||
|
||||
return new RulesetOutput(span, 'ai', 'ip')
|
||||
.withTitle('Sukka\'s Ruleset - ChatGPT Voice IP CIDR')
|
||||
.appendDescription(
|
||||
SHARED_DESCRIPTION,
|
||||
'',
|
||||
'This file contains IP ranges used by ChatGPT Voice.'
|
||||
)
|
||||
.withDate(lastUpdated)
|
||||
.appendDataSource(`${OPENAI_VOICE_IP_URL} (last updated: ${lastUpdated.toISOString()})`)
|
||||
.bulkAddCIDR4NoResolve(cidr4)
|
||||
.bulkAddCIDR6NoResolve(cidr6)
|
||||
.write();
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { downloadPreviousBuild } from './download-previous-build';
|
||||
import { buildCommon } from './build-common';
|
||||
import { buildRejectIPList } from './build-reject-ip-list';
|
||||
import { buildAppleCdn } from './build-apple-cdn';
|
||||
import { buildAICIDR } from './build-ai-cidr';
|
||||
import { buildRejectDomainSet } from './build-reject-domainset';
|
||||
import { buildChnCidr } from './build-chn-cidr';
|
||||
import { buildSpeedtestDomainSet } from './build-speedtest-domainset';
|
||||
@@ -103,6 +104,7 @@ const buildFinishedLock = path.join(ROOT_DIR, '.BUILD_FINISHED');
|
||||
downloadPreviousBuildPromise.then(() => buildCommon()),
|
||||
downloadPreviousBuildPromise.then(() => buildRejectIPList()),
|
||||
downloadPreviousBuildPromise.then(() => buildAppleCdn()),
|
||||
downloadPreviousBuildPromise.then(() => buildAICIDR()),
|
||||
downloadPreviousBuildPromise.then(() => cdnDownloadWorker.buildCdnDownloadConf()),
|
||||
downloadPreviousBuildPromise.then(() => buildRejectDomainSet()),
|
||||
downloadPreviousBuildPromise.then(() => telegramCidrWorker.buildTelegramCIDR()),
|
||||
|
||||
17
README.md
17
README.md
@@ -423,16 +423,22 @@ rules:
|
||||
|
||||
#### AI
|
||||
|
||||
- 域名规则 人工维护
|
||||
- 域名和 IP 规则,人工维护 + 自动更新
|
||||
- 包含 OpenAI、Google Gemini、Claude、Perplexity 等
|
||||
|
||||
**Surge**
|
||||
|
||||
```ini
|
||||
# Non IP
|
||||
RULE-SET,https://ruleset.skk.moe/List/non_ip/ai.conf,[Replace with your policy]
|
||||
RULE-SET,https://ruleset.skk.moe/List/non_ip/apple_intelligence.conf,[Replace with your policy],extended-matching
|
||||
```
|
||||
|
||||
```ini
|
||||
# IP
|
||||
RULE-SET,https://ruleset.skk.moe/List/ip/ai.conf,[Replace with your policy]
|
||||
```
|
||||
|
||||
**Mihomo**
|
||||
|
||||
```yaml
|
||||
@@ -451,10 +457,19 @@ rule-providers:
|
||||
interval: 43200
|
||||
url: https://ruleset.skk.moe/Clash/non_ip/apple_intelligence.txt
|
||||
path: ./sukkaw_ruleset/apple_intelligence_non_ip.txt
|
||||
ai_ip:
|
||||
type: http
|
||||
behavior: classical
|
||||
format: text
|
||||
interval: 43200
|
||||
url: https://ruleset.skk.moe/Clash/ip/ai.txt
|
||||
path: ./sukkaw_ruleset/ai_ip.txt
|
||||
|
||||
rules:
|
||||
- RULE-SET,ai_non_ip,[Replace with your policy]
|
||||
- RULE-SET,apple_intelligence_non_ip,[Replace with your policy]
|
||||
|
||||
- RULE-SET,ai_ip,[Replace with your policy]
|
||||
```
|
||||
|
||||
#### Telegram
|
||||
|
||||
Reference in New Issue
Block a user