@@ -20,24 +20,26 @@ import (
2020// complements /arm (Gentoo only), since Gentoo's arm64 keywording is sometimes incomplete
2121// while a package may well be available on other ARM distros.
2222
23- // gentooArmStatus resolves a Gentoo atom and reports its arm64 keyword status.
24- func (v * Verifier ) gentooArmStatus (ctx context.Context , name string ) string {
23+ // gentooArmStatus resolves a Gentoo atom and reports its arm64 keyword status plus a link
24+ // to the package's packages.gentoo.org page (a search link if the atom doesn't resolve).
25+ func (v * Verifier ) gentooArmStatus (ctx context.Context , name string ) (status , url string ) {
2526 atoms := searchMainTree (ctx , name )
2627 if len (atoms ) == 0 {
27- return "❌ 不在 Gentoo 官方树"
28+ return "❌ 不在官方树" , "https://packages.gentoo.org/packages/search?q=" + neturl . QueryEscape ( name )
2829 }
30+ url = "https://packages.gentoo.org/packages/" + atoms [0 ]
2931 stable , testing , ok := armStatus (ctx , atoms [0 ])
3032 switch {
3133 case ! ok :
32- return "⚠️ 查询失败"
34+ return "⚠️ 查询失败" , url
3335 case stable != "" && testing != "" :
34- return fmt .Sprintf ("✅ 稳定 %s · 🧪 ~%s" , stable , testing )
36+ return fmt .Sprintf ("✅ 稳定 %s · 🧪 ~%s" , stable , testing ), url
3537 case stable != "" :
36- return "✅ 稳定 " + stable
38+ return "✅ 稳定 " + stable , url
3739 case testing != "" :
38- return "🧪 仅 ~arm64 " + testing
40+ return "🧪 仅 ~arm64 " + testing , url
3941 default :
40- return "❌ 未 keyword arm64"
42+ return "❌ 未 keyword arm64" , url
4143 }
4244}
4345
@@ -70,8 +72,8 @@ func parseMadison(body string) []madEntry {
7072 return ordered
7173}
7274
73- // madisonArmStatus queries a madison endpoint (arch-filtered to arm64) and summarises the
74- // newest few suites that ship the package on arm64.
75+ // madisonArmStatus queries a madison endpoint (arch-filtered to arm64) and reports the
76+ // newest suite that ships the package on arm64.
7577func madisonArmStatus (ctx context.Context , madisonURL , pkg string ) string {
7678 body , err := httpGetBody (ctx , madisonURL + neturl .QueryEscape (pkg )+ "&text=on&a=arm64" , 1 << 20 )
7779 if err != nil {
@@ -81,25 +83,20 @@ func madisonArmStatus(ctx context.Context, madisonURL, pkg string) string {
8183 if len (entries ) == 0 {
8284 return "❌ 无 arm64 包"
8385 }
84- // newest first, at most 3
85- var parts []string
86- for i := len (entries ) - 1 ; i >= 0 && len (parts ) < 3 ; i -- {
87- parts = append (parts , entries [i ].suite + " " + entries [i ].ver )
88- }
89- return "✅ " + strings .Join (parts , " · " )
86+ e := entries [len (entries )- 1 ] // madison lists oldest-first, so the last is the newest suite
87+ return fmt .Sprintf ("✅ %s %s" , e .suite , e .ver )
9088}
9189
9290// fedoraArmStatus checks Fedora rawhide via mdapi. aarch64 is a Fedora primary arch, so a
9391// package present in Fedora is built for aarch64 (barring an explicit ExcludeArch).
9492func fedoraArmStatus (ctx context.Context , pkg string ) string {
9593 var r struct {
9694 Version string `json:"version"`
97- Release string `json:"release"`
9895 }
9996 if err := httpGetJSON (ctx , "https://mdapi.fedoraproject.org/rawhide/pkg/" + neturl .PathEscape (pkg ), nil , & r ); err != nil || r .Version == "" {
100- return "❌ 未找到(Fedora rawhide) "
97+ return "❌ 不在 Fedora "
10198 }
102- return fmt . Sprintf ( "✅ rawhide %s(aarch64 主架构)" , r .Version )
99+ return "✅ rawhide " + r .Version
103100}
104101
105102var aurArchRe = regexp .MustCompile (`(?i)arch=\(([^)]*)\)` )
@@ -157,40 +154,48 @@ func (v *Verifier) onArmpkgs(ctx *th.Context, update telego.Update) error {
157154 }
158155 hc , cancel := context .WithTimeout (context .Background (), 25 * time .Second )
159156 defer cancel ()
157+ pe := neturl .PathEscape (name )
160158
161- // Each source is independent — query them concurrently.
162- type srcResult struct { label , status string }
159+ // Each source is independent — query them concurrently. fn returns (status, link).
163160 sources := []struct {
164161 label string
165- fn func () string
162+ fn func () ( string , string )
166163 }{
167- {"Gentoo" , func () string { return v .gentooArmStatus (hc , name ) }},
168- {"Debian" , func () string { return madisonArmStatus (hc , "https://qa.debian.org/madison.php?package=" , name ) }},
169- {"Ubuntu" , func () string {
170- return madisonArmStatus (hc , "https://people.canonical.com/~ubuntu-archive/madison.cgi?package=" , name )
164+ {"Gentoo" , func () (string , string ) { return v .gentooArmStatus (hc , name ) }},
165+ {"Debian" , func () (string , string ) {
166+ return madisonArmStatus (hc , "https://qa.debian.org/madison.php?package=" , name ), "https://tracker.debian.org/pkg/" + pe
167+ }},
168+ {"Ubuntu" , func () (string , string ) {
169+ return madisonArmStatus (hc , "https://people.canonical.com/~ubuntu-archive/madison.cgi?package=" , name ), "https://launchpad.net/ubuntu/+source/" + pe
170+ }},
171+ {"Fedora" , func () (string , string ) {
172+ return fedoraArmStatus (hc , name ), "https://packages.fedoraproject.org/pkgs/" + pe + "/"
173+ }},
174+ {"Arch Linux ARM" , func () (string , string ) {
175+ return alarmArmStatus (hc , name ), "https://archlinuxarm.org/packages/aarch64/" + pe
171176 }},
172- {"Fedora" , func () string { return fedoraArmStatus (hc , name ) }},
173- {"Arch Linux ARM" , func () string { return alarmArmStatus (hc , name ) }},
174- {"AUR" , func () string { return v .aurArmStatus (hc , name ) }},
177+ {"AUR" , func () (string , string ) { return v .aurArmStatus (hc , name ), "https://aur.archlinux.org/packages/" + pe }},
175178 }
179+ type srcResult struct { label , status , url string }
176180 results := make ([]srcResult , len (sources ))
177181 var wg sync.WaitGroup
178182 for i , s := range sources {
179183 wg .Add (1 )
180- go func (i int , label string , fn func () string ) {
184+ go func (i int , label string , fn func () ( string , string ) ) {
181185 defer wg .Done ()
182- results [i ] = srcResult {label , fn ()}
186+ status , url := fn ()
187+ results [i ] = srcResult {label , status , url }
183188 }(i , s .label , s .fn )
184189 }
185190 wg .Wait ()
186191
187192 esc := html .EscapeString
188193 var b strings.Builder
189- fmt .Fprintf (& b , "🦾 <b>%s</b> 的 ARM (aarch64) 跨发行版支持: " , esc (name ))
194+ fmt .Fprintf (& b , "🦾 <b>%s</b> · arm64 (aarch64) 跨发行版支持" , esc (name ))
190195 for _ , r := range results {
191- fmt .Fprintf (& b , "\n • <b >%s</b >:%s" , esc (r .label ), esc (r .status ))
196+ fmt .Fprintf (& b , "\n • <a href= \" %s \" >%s</a >:%s" , esc ( r . url ) , esc (r .label ), esc (r .status ))
192197 }
193- b .WriteString ("\n <i>提示:若 Gentoo 未 keyword arm64 但其它发行版已支持,通常意味着实际可用 —— 可 ACCEPT_KEYWORDS=\" ~arm64\" 强制开启自行编译。各发行版按各自包名查询;AUR 显示 PKGBUILD 声明的架构(未声明 aarch64 也常能从源码构建) 。</i>" )
198+ b .WriteString ("\n <i>Gentoo 未标但其它发行版支持 → 多半实际可用, 可 ACCEPT_KEYWORDS=\" ~arm64\" 自行编译 。</i>" )
194199 sent , _ := bot .SendMessage (c , htmlMessage (msg .Chat .ID , b .String ()).WithReplyParameters (replyParams (msg .MessageID )))
195200 v .scheduleLookupCleanup (bot , msg .Chat .ID , msg .MessageID , msgID (sent ))
196201 return nil
0 commit comments