4
4
"regexp"
5
5
"sort"
6
6
"strings"
7
+ "time"
7
8
8
9
"github.com/gocolly/colly/v2"
9
10
"github.com/pkg/errors"
@@ -24,6 +25,10 @@ type BetaIPSW struct {
24
25
BuildID string `json:"buildid,omitempty"`
25
26
}
26
27
28
+ type Keys map [string ]string
29
+ type BuildKeys map [string ]Keys
30
+ type DeviceKeys map [string ]BuildKeys
31
+
27
32
func trimQuotes (s string ) string {
28
33
if len (s ) > 0 && s [0 ] == '"' {
29
34
s = s [1 :]
@@ -126,3 +131,69 @@ func ScrapeURLs(build string) (map[string]BetaIPSW, error) {
126
131
127
132
return ipsws , nil
128
133
}
134
+
135
+ // ScrapeKeys will scrape the iPhone Wiki for firmware keys
136
+ func ScrapeKeys (version string ) (map [string ]map [string ]map [string ]string , error ) {
137
+ keys := make (map [string ]map [string ]map [string ]string , 1000 )
138
+
139
+ c := colly .NewCollector (
140
+ colly .AllowedDomains ("www.theiphonewiki.com" ),
141
+ colly .URLFilters (
142
+ regexp .MustCompile ("https://www.theiphonewiki.com/wiki/(.+)$" ),
143
+ ),
144
+ // colly.Async(true),
145
+ colly .MaxDepth (1 ),
146
+ colly .UserAgent ("free0" ),
147
+ colly .IgnoreRobotsTxt (),
148
+ )
149
+
150
+ // On every a element which has href attribute call callback
151
+ c .OnHTML ("a[href]" , func (e * colly.HTMLElement ) {
152
+ if strings .Contains (e .Attr ("href" ), "/wiki/" ) && ! strings .Contains (e .Attr ("href" ), "redlink=1" ) {
153
+ c .Visit (e .Request .AbsoluteURL (e .Attr ("href" )))
154
+ }
155
+ })
156
+
157
+ c .OnHTML ("body" , func (e * colly.HTMLElement ) {
158
+ e .ForEach ("code" , func (_ int , code * colly.HTMLElement ) {
159
+ if len (code .Attr ("id" )) > 0 {
160
+ if strings .Contains (code .Attr ("id" ), "-iv" ) || strings .Contains (code .Attr ("id" ), "-key" ) {
161
+ if code .Text != "Unknown" {
162
+ urlParts := strings .Split (code .Request .URL .Path , "_" )
163
+ buildID := urlParts [1 ]
164
+ deviceID := strings .Trim (urlParts [2 ], "()" )
165
+ if keys [deviceID ] == nil {
166
+ keys [deviceID ] = map [string ]map [string ]string {}
167
+ }
168
+ if keys [deviceID ][buildID ] == nil {
169
+ keys [deviceID ][buildID ] = map [string ]string {}
170
+ }
171
+ keys [deviceID ][buildID ][strings .TrimPrefix (code .Attr ("id" ), "keypage-" )] = code .Text
172
+ // fmt.Printf("%#v\n", keys[deviceID])
173
+ }
174
+
175
+ }
176
+ }
177
+ })
178
+ })
179
+
180
+ // Set error handler
181
+ // c.OnError(func(r *colly.Response, err error) {
182
+ // // fmt.Println("Request URL:", r.Request.URL, "failed with response:", r, "\nError:", err)
183
+ // fmt.Println("Error:", err)
184
+ // })
185
+
186
+ c .SetRequestTimeout (60 * time .Second )
187
+
188
+ // for _, v := range []string{"1.x", "2.x", "3.x", "4.x", "5.x", "6.x", "7.x", "8.x", "9.x", "10.x", "11.x", "12.x", "13.x", "14.x"} {
189
+ for _ , v := range []string {"13.x" , "14.x" } {
190
+ err := c .Visit ("https://www.theiphonewiki.com/wiki/Firmware_Keys/" + v )
191
+ if err != nil {
192
+ return nil , errors .Wrap (err , "failed to scrape https://www.theiphonewiki.com/wiki/Firmware_Keys/" + v )
193
+ }
194
+ }
195
+
196
+ c .Wait ()
197
+
198
+ return keys , nil
199
+ }
0 commit comments