Compare commits

...

12 Commits

Author SHA1 Message Date
Loyalsoldier
4d45b17cd8 Chore: refine code (#3067) 2025-12-17 00:45:09 +08:00
Loyalsoldier
d8bd29ce92 Fix: incorrect lowercase for regexp rules (#3066) 2025-12-17 00:17:43 +08:00
Loyalsoldier
72eb885658 Refine: extract rule type (#3065) 2025-12-17 00:10:33 +08:00
风扇滑翔翼
93bfcfd142 Feat: check regexp before build (#3064)
Co-authored-by: Loyalsoldier <10487845+Loyalsoldier@users.noreply.github.com>
2025-12-16 23:40:25 +08:00
DeepChirp
cbe19f0562 picacg-ads: split from picacg 2025-12-16 21:42:59 +08:00
DeepChirp
ea99bef4a2 google-ads: comment out problematic rule 2025-12-16 21:42:59 +08:00
深鸣
9b01521761 ctyun: add new entry (#3059) 2025-12-16 21:24:37 +08:00
深鸣
8d50851b58 umeng-ads: add more domains (#3060) 2025-12-16 21:13:11 +08:00
sklimoff
16923730a4 Add wink and include it in category-ru (#3058) 2025-12-16 21:06:32 +08:00
Luo Chen
7e3137a0d1 Fix #3055 (#3056) 2025-12-16 09:54:53 +08:00
tooadstool
6b4c09860b Add Ookla Speedtest Central to the list (#3053)
* Add Ookla Speedtest Central to the list

* Update ookla-speedtest

---------

Co-authored-by: rootmelo92118 <32770959+rootmelo92118@users.noreply.github.com>
2025-12-15 22:40:47 +08:00
Jiew-KueJwiaeng
6a11042b92 Update 18comic & picacg (#2695)
* Update 18comic

* Update picacg

* Update 18comic

---------

Co-authored-by: rootmelo92118 <32770959+rootmelo92118@users.noreply.github.com>
2025-12-15 22:38:15 +08:00
12 changed files with 186 additions and 22 deletions

View File

@@ -5,11 +5,47 @@
18comic.company 18comic.company
18comic.org 18comic.org
18comic.vip 18comic.vip
asjmapihost.cc
cdnblackmyth.club
cdnmhws.cc
cdnmhwscc.vip
cdnuc.vip
cdnxxx-proxy.co
cdnxxx-proxy.xyz
jm-comic2.cc
jm18c-bbm.cc
jm18c-bbm.net
jm18c-uoi.net
jm365.work
jm365.xyz
jmapibranch1.cc
jmapibranch2.cc
jmapibranch3.cc
jmapinode.biz
jmapinode.vip
jmapinode.xyz
jmapinode1.top
jmapinode2.top
jmapinode3.top
jmapinodeudzn.net
jmapinodeudzn.xyz
jmapiproxy1.cc
jmapiproxy1.monster
jmapiproxy2.cc
jmapiproxy3.cc
jmapiproxy4.cc
jmapiproxyxxx.vip
jmcomic.group
jmcomic.ltd jmcomic.ltd
jmcomic.me jmcomic.me
jmcomic.mobi jmcomic.mobi
jmcomic.moe jmcomic.moe
jmcomic.rocks
jmcomic-fb.vip
jmcomic-zzz.one
jmcomic-zzz.org
jmcomic1.city jmcomic1.city
jmcomic1.me jmcomic1.me
jmcomic1.mobi jmcomic1.mobi
jmcomic1.rocks
jmcomic2.moe jmcomic2.moe

View File

@@ -38,6 +38,7 @@ include:newrelic-ads
include:ogury-ads include:ogury-ads
include:ookla-speedtest-ads include:ookla-speedtest-ads
include:openx-ads include:openx-ads
include:picacg-ads
include:pocoiq-ads include:pocoiq-ads
include:pubmatic-ads include:pubmatic-ads
include:qihoo360-ads include:qihoo360-ads

View File

@@ -23,5 +23,6 @@ include:mailru-group
include:okko include:okko
include:ozon include:ozon
include:rutube include:rutube
include:wink
include:x5 include:x5
include:yandex include:yandex

69
data/ctyun Normal file
View File

@@ -0,0 +1,69 @@
# 天翼云
# 京ICP备2021034386号
ctadns.cn
bjctyiptv.cn
cqctyiptv.cn
ctacdn.cn
ctaigw.cn
ctbcdn.com
ctcdn.cn
ctcdn.com.cn
ctcdnov.net
ctcloudzos.cn
ctcns.cn
ctdcdn.com
ctdns.cn
ctdns.com.cn
ctdns.net
ctecdn.cn
ctecx.cn
ctgcdn.com
cthcdn.cn
cthcdn.com
cthcdn.net
ctlcdn.cn
ctlcdn.com
ctlcdn.net
ctmcdn.cn
ctovcdn.com
ctrender.com
ctwcdn.cn
ctxcdn.cn
ctxcdn.com
ctxcdn.net
ctxirang.cn
ctxirang.com
ctycdn.cn
ctycdn.net
ctycdn.net.cn
ctydoh.cn
ctyecx.cn
ctyiptv.cn
ctyun.cn
ctyun.com.cn
ctyuncdn.cn
ctyuncs.cn
ctyuninner.com
ctyunmds.cn
ctyunwaf.cn
ctyunwaf.com
ctyunwaf1.com
ctyunwaf3.cn
ctyunxs.cn
ctyunzos.cn
ctzcdn.cn
ctzcdn.com
edgecloudx.cn
faasapp.cn
faasdev.cn
fjctyiptv.cn
gdctyiptv.cn
gsctyiptv.cn
gsjtyiptv.cn
gzctyiptv.cn
jsctyiptv.cn
modelers.cn
scctyiptv.cn
snctyiptv.cn
ynctyiptv.cn
ynjtyiptv.cn

View File

@@ -54,6 +54,7 @@ include:aws-cn
include:baishancloud include:baishancloud
include:bootcdn include:bootcdn
include:cloudflare-cn include:cloudflare-cn
include:ctyun
include:dwion include:dwion
include:maocloud include:maocloud
include:qingcloud include:qingcloud

View File

@@ -49,6 +49,7 @@ partnerad.l.google.com @ads
urchin.com @ads urchin.com @ads
full:analytics.google.com @ads full:analytics.google.com @ads
full:fundingchoicesmessages.google.com @ads # https://github.com/AdguardTeam/FiltersRegistry/pull/1154
# full:fundingchoicesmessages.google.com @ads
regexp:^adservice\.google\.([a-z]{2}|com?)(\.[a-z]{2})?$ @ads regexp:^adservice\.google\.([a-z]{2}|com?)(\.[a-z]{2})?$ @ads

View File

@@ -13,3 +13,6 @@ webtest.net
full:www.speedtest.net.cdn.cloudflare.net full:www.speedtest.net.cdn.cloudflare.net
include:ookla-speedtest-ads include:ookla-speedtest-ads
# SpeedTest Node
ookla-speedtest-central.hgconair.hgc.com.hk # HGC Global Communications 香港環電

View File

@@ -1,3 +1,5 @@
include:picacg-ads
bikaa.xyz bikaa.xyz
bikac.xyz bikac.xyz
bikaios.xyz bikaios.xyz
@@ -8,3 +10,7 @@ picacn.xyz
picacomic.com picacomic.com
picacomic.xyz picacomic.xyz
wikawika.xyz wikawika.xyz
# Image Resource Domain like `img.diwodiwo.xyz` `s3.diwodiwo.xyz` `storage.diwodiwo.xyz` `storage-b.diwodiwo.xyz`
diwodiwo.xyz

2
data/picacg-ads Normal file
View File

@@ -0,0 +1,2 @@
full:ad-channel.diwodiwo.xyz @ads
full:ad-display.diwodiwo.xyz @ads

View File

@@ -1,6 +1,24 @@
aaid.umeng.com @ads aaid.umeng.com @ads
alog.umeng.com @ads alog.umeng.com @ads
alog.umengcloud.com @ads alog.umengcloud.com @ads
alogs.umeng.com @ads
alogus.umeng.com @ads
ar.umeng.com @ads
aspect-upush.umeng.com @ads
audid.umeng.com @ads
ccs.umeng.com @ads
cnlogs.umeng.com @ads
cnlogs.umengcloud.com @ads
# https://github.com/TG-Twilight/AWAvenue-Ads-Rule/issues/185
# errlog.umeng.com @ads
# errnewlog.umeng.com @ads
new-aaid.umeng.com @ads
new-aaid.umeng.com.gds.alibabadns.com @ads
oc.umeng.com @ads
plbslog.umeng.com @ads
resolve.umeng.com @ads
ulogs.umeng.com @ads
ulogs.umengcloud.com @ads
utoken.umeng.com @ads utoken.umeng.com @ads
# CNZZ # CNZZ

3
data/wink Normal file
View File

@@ -0,0 +1,3 @@
ngenix.net
restream-media.net
wink.ru

63
main.go
View File

@@ -2,11 +2,11 @@ package main
import ( import (
"bufio" "bufio"
"errors"
"flag" "flag"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@@ -22,6 +22,14 @@ var (
exportLists = flag.String("exportlists", "", "Lists to be flattened and exported in plaintext format, separated by ',' comma") exportLists = flag.String("exportlists", "", "Lists to be flattened and exported in plaintext format, separated by ',' comma")
) )
const (
RuleTypeDomain string = "domain"
RuleTypeFullDomain string = "full"
RuleTypeKeyword string = "keyword"
RuleTypeRegexp string = "regexp"
RuleTypeInclude string = "include"
)
type Entry struct { type Entry struct {
Type string Type string
Value string Value string
@@ -64,32 +72,41 @@ func (l *ParsedList) toProto() (*router.GeoSite, error) {
} }
for _, entry := range l.Entry { for _, entry := range l.Entry {
switch entry.Type { switch entry.Type {
case "domain": case RuleTypeDomain:
site.Domain = append(site.Domain, &router.Domain{ site.Domain = append(site.Domain, &router.Domain{
Type: router.Domain_RootDomain, Type: router.Domain_RootDomain,
Value: entry.Value, Value: entry.Value,
Attribute: entry.Attrs, Attribute: entry.Attrs,
}) })
case "regexp":
case RuleTypeRegexp:
// check regexp validity to avoid runtime error
_, err := regexp.Compile(entry.Value)
if err != nil {
return nil, fmt.Errorf("invalid regexp in list %s: %s", l.Name, entry.Value)
}
site.Domain = append(site.Domain, &router.Domain{ site.Domain = append(site.Domain, &router.Domain{
Type: router.Domain_Regex, Type: router.Domain_Regex,
Value: entry.Value, Value: entry.Value,
Attribute: entry.Attrs, Attribute: entry.Attrs,
}) })
case "keyword":
case RuleTypeKeyword:
site.Domain = append(site.Domain, &router.Domain{ site.Domain = append(site.Domain, &router.Domain{
Type: router.Domain_Plain, Type: router.Domain_Plain,
Value: entry.Value, Value: entry.Value,
Attribute: entry.Attrs, Attribute: entry.Attrs,
}) })
case "full":
case RuleTypeFullDomain:
site.Domain = append(site.Domain, &router.Domain{ site.Domain = append(site.Domain, &router.Domain{
Type: router.Domain_Full, Type: router.Domain_Full,
Value: entry.Value, Value: entry.Value,
Attribute: entry.Attrs, Attribute: entry.Attrs,
}) })
default: default:
return nil, errors.New("unknown domain type: " + entry.Type) return nil, fmt.Errorf("unknown domain type: %s", entry.Type)
} }
} }
return site, nil return site, nil
@@ -99,7 +116,7 @@ func exportPlainTextList(list []string, refName string, pl *ParsedList) {
for _, listName := range list { for _, listName := range list {
if strings.EqualFold(refName, listName) { if strings.EqualFold(refName, listName) {
if err := pl.toPlainText(strings.ToLower(refName)); err != nil { if err := pl.toPlainText(strings.ToLower(refName)); err != nil {
fmt.Println("Failed: ", err) fmt.Println("Failed:", err)
continue continue
} }
fmt.Printf("'%s' has been generated successfully.\n", listName) fmt.Printf("'%s' has been generated successfully.\n", listName)
@@ -118,24 +135,30 @@ func removeComment(line string) string {
func parseDomain(domain string, entry *Entry) error { func parseDomain(domain string, entry *Entry) error {
kv := strings.Split(domain, ":") kv := strings.Split(domain, ":")
if len(kv) == 1 { if len(kv) == 1 {
entry.Type = "domain" entry.Type = RuleTypeDomain
entry.Value = strings.ToLower(kv[0]) entry.Value = strings.ToLower(kv[0])
return nil return nil
} }
if len(kv) == 2 { if len(kv) == 2 {
entry.Type = strings.ToLower(kv[0]) entry.Type = strings.ToLower(kv[0])
if strings.EqualFold(entry.Type, RuleTypeRegexp) {
entry.Value = kv[1]
} else {
entry.Value = strings.ToLower(kv[1]) entry.Value = strings.ToLower(kv[1])
}
return nil return nil
} }
return errors.New("Invalid format: " + domain) return fmt.Errorf("invalid format: %s", domain)
} }
func parseAttribute(attr string) (*router.Domain_Attribute, error) { func parseAttribute(attr string) (*router.Domain_Attribute, error) {
var attribute router.Domain_Attribute var attribute router.Domain_Attribute
if len(attr) == 0 || attr[0] != '@' { if len(attr) == 0 || attr[0] != '@' {
return &attribute, errors.New("invalid attribute: " + attr) return &attribute, fmt.Errorf("invalid attribute: %s", attr)
} }
// Trim attribute prefix `@` character // Trim attribute prefix `@` character
@@ -148,7 +171,7 @@ func parseAttribute(attr string) (*router.Domain_Attribute, error) {
attribute.Key = strings.ToLower(parts[0]) attribute.Key = strings.ToLower(parts[0])
intv, err := strconv.Atoi(parts[1]) intv, err := strconv.Atoi(parts[1])
if err != nil { if err != nil {
return &attribute, errors.New("invalid attribute: " + attr + ": " + err.Error()) return &attribute, fmt.Errorf("invalid attribute: %s: %v", attr, err)
} }
attribute.TypedValue = &router.Domain_Attribute_IntValue{IntValue: int64(intv)} attribute.TypedValue = &router.Domain_Attribute_IntValue{IntValue: int64(intv)}
} }
@@ -161,7 +184,7 @@ func parseEntry(line string) (Entry, error) {
var entry Entry var entry Entry
if len(parts) == 0 { if len(parts) == 0 {
return entry, errors.New("empty entry") return entry, fmt.Errorf("empty entry")
} }
if err := parseDomain(parts[0], &entry); err != nil { if err := parseDomain(parts[0], &entry); err != nil {
@@ -255,7 +278,7 @@ func ParseList(list *List, ref map[string]*List) (*ParsedList, error) {
newEntryList := make([]Entry, 0, len(entryList)) newEntryList := make([]Entry, 0, len(entryList))
hasInclude := false hasInclude := false
for _, entry := range entryList { for _, entry := range entryList {
if entry.Type == "include" { if entry.Type == RuleTypeInclude {
refName := strings.ToUpper(entry.Value) refName := strings.ToUpper(entry.Value)
if entry.Attrs != nil { if entry.Attrs != nil {
for _, attr := range entry.Attrs { for _, attr := range entry.Attrs {
@@ -267,7 +290,7 @@ func ParseList(list *List, ref map[string]*List) (*ParsedList, error) {
refList := ref[refName] refList := ref[refName]
if refList == nil { if refList == nil {
return nil, errors.New(entry.Value + " not found.") return nil, fmt.Errorf("list not found: %s", entry.Value)
} }
attrEntrys := createIncludeAttrEntrys(refList, attr) attrEntrys := createIncludeAttrEntrys(refList, attr)
if len(attrEntrys) != 0 { if len(attrEntrys) != 0 {
@@ -282,7 +305,7 @@ func ParseList(list *List, ref map[string]*List) (*ParsedList, error) {
pl.Inclusion[InclusionName] = true pl.Inclusion[InclusionName] = true
refList := ref[refName] refList := ref[refName]
if refList == nil { if refList == nil {
return nil, errors.New(entry.Value + " not found.") return nil, fmt.Errorf("list not found: %s", entry.Value)
} }
newEntryList = append(newEntryList, refList.Entry...) newEntryList = append(newEntryList, refList.Entry...)
} }
@@ -323,14 +346,14 @@ func main() {
return nil return nil
}) })
if err != nil { if err != nil {
fmt.Println("Failed: ", err) fmt.Println("Failed:", err)
os.Exit(1) os.Exit(1)
} }
// Create output directory if not exist // Create output directory if not exist
if _, err := os.Stat(*outputDir); os.IsNotExist(err) { if _, err := os.Stat(*outputDir); os.IsNotExist(err) {
if mkErr := os.MkdirAll(*outputDir, 0755); mkErr != nil { if mkErr := os.MkdirAll(*outputDir, 0755); mkErr != nil {
fmt.Println("Failed: ", mkErr) fmt.Println("Failed:", mkErr)
os.Exit(1) os.Exit(1)
} }
} }
@@ -340,12 +363,12 @@ func main() {
for refName, list := range ref { for refName, list := range ref {
pl, err := ParseList(list, ref) pl, err := ParseList(list, ref)
if err != nil { if err != nil {
fmt.Println("Failed: ", err) fmt.Println("Failed:", err)
os.Exit(1) os.Exit(1)
} }
site, err := pl.toProto() site, err := pl.toProto()
if err != nil { if err != nil {
fmt.Println("Failed: ", err) fmt.Println("Failed:", err)
os.Exit(1) os.Exit(1)
} }
protoList.Entry = append(protoList.Entry, site) protoList.Entry = append(protoList.Entry, site)
@@ -383,7 +406,7 @@ func main() {
os.Exit(1) os.Exit(1)
} }
if err := os.WriteFile(filepath.Join(*outputDir, *outputName), protoBytes, 0644); err != nil { if err := os.WriteFile(filepath.Join(*outputDir, *outputName), protoBytes, 0644); err != nil {
fmt.Println("Failed: ", err) fmt.Println("Failed:", err)
os.Exit(1) os.Exit(1)
} else { } else {
fmt.Println(*outputName, "has been generated successfully.") fmt.Println(*outputName, "has been generated successfully.")