|    129             self.size = details.span.data.data |    129             self.size = details.span.data.data | 
|    130             self.md5 = details.a.attrs["href"] |    130             self.md5 = details.a.attrs["href"] | 
|    131         else: |    131         else: | 
|    132             self.size = "Unknown" |    132             self.size = "Unknown" | 
|    133             self.md5 = "Unknown" |    133             self.md5 = "Unknown" | 
|    134     def score(self): |         | 
|    135         if self.dltype == "audio": |         | 
|    136             if "FLAC" in self.attrs: |         | 
|    137                 return 2 |         | 
|    138             if "MP3" in self.attrs: |         | 
|    139                 return 1 |         | 
|    140             if "website" in self.attrs: |         | 
|    141                 return -1 |         | 
|    142             raise Exception("Unknow audio type: %r" % (self.attrs)) |         | 
|    143         if self.dltype in ("mac","windows"): |         | 
|    144             return -1 |         | 
|    145         if self.dltype == "linux": |         | 
|    146             score = 1 |         | 
|    147             if "x64" in self.attrs: |         | 
|    148                 score += 1 |         | 
|    149             if "deb" in self.attrs: |         | 
|    150                 score += 1 |         | 
|    151             return score |         | 
|    152         if self.dltype == "android": |         | 
|    153             return 0 |         | 
|    154         raise Exception("Unknown dls type: %r" % (self,)) |         | 
|    155     def format(self, prefix=""): |    134     def format(self, prefix=""): | 
|    156         res = prefix + '<download id="' + self.id + '">\n' |    135         res = prefix + '<download id="' + self.id + '">\n' | 
|    157         res += prefix + "  <web>" + self.web + "</web>\n" |    136         res += prefix + "  <web>" + self.web + "</web>\n" | 
|    158         res += prefix + "  <torrent>" + self.torrent + "</torrent>\n" |    137         res += prefix + "  <torrent>" + self.torrent + "</torrent>\n" | 
|    159         res += prefix + "  <size>" + self.size + "</size>\n" |    138         res += prefix + "  <size>" + self.size + "</size>\n" | 
|    193             for o in self.others: |    172             for o in self.others: | 
|    194                 res += o.format(prefix + "    ") + "\n" |    173                 res += o.format(prefix + "    ") + "\n" | 
|    195             res += prefix + "  </others>\n" |    174             res += prefix + "  </others>\n" | 
|    196         res += prefix + "</downloads>" |    175         res += prefix + "</downloads>" | 
|    197         return res |    176         return res | 
|    198     def choose(self): |         | 
|    199         scores = list((dl.score(),dl) for dl in self if dl.score() >= 0) |         | 
|    200         scores.sort(key = lambda x: x[0], reverse = True) |         | 
|    201         for s, dl in scores: |         | 
|    202             return [dl] |         | 
|    203         return [] |         | 
|    204     def __repr__(self): |    177     def __repr__(self): | 
|    205         return self.format() |    178         return self.format() | 
|    206          |    179          | 
|    207 class Game: |    180 class Game: | 
|    208     def __init__(self, dom): |    181     def __init__(self, dom): | 
|    232                 res += o.format("    ") + "\n" |    205                 res += o.format("    ") + "\n" | 
|    233             res += "  </others>\n" |    206             res += "  </others>\n" | 
|    234         res += "</game>" |    207         res += "</game>" | 
|    235         return res |    208         return res | 
|    236  |    209  | 
|    237 def parseGames(dom): |    210 def parseGamesFromDom(dom): | 
|    238     for row in findRows(dom): |    211     for row in findRows(dom): | 
|    239         yield Game(row) |    212         yield Game(row) | 
|    240  |    213  | 
|    241 parser = BundleParser() |    214 def parseGamesFromFile(filename): | 
|    242 with open("tidy_bundle.html") as f: |    215     parser = BundleParser() | 
|    243     for l in f: |    216     for l in open(filename): | 
|    244         parser.feed(l) |    217         parser.feed(l) | 
|    245  |    218     for game in parseGamesFromDom(parser.dom): | 
|    246 for game in parseGames(parser.dom): |    219         yield game | 
|         |    220  | 
|         |    221 class FileSelector:     | 
|         |    222     def scoreDownload(self, dl): | 
|         |    223         if dl.dltype == "audio": | 
|         |    224             if "FLAC" in dl.attrs: | 
|         |    225                 return 2 | 
|         |    226             if "MP3" in dl.attrs: | 
|         |    227                 return 1 | 
|         |    228             if "website" in dl.attrs: | 
|         |    229                 return -1 | 
|         |    230             raise Exception("Unknow audio type: %r" % (dl.attrs)) | 
|         |    231         if dl.dltype in ("mac","windows"): | 
|         |    232             return -1 | 
|         |    233         if dl.dltype == "linux": | 
|         |    234             score = 1 | 
|         |    235             if "x64" in dl.attrs: | 
|         |    236                 score += 1 | 
|         |    237             if "deb" in dl.attrs: | 
|         |    238                 score += 1 | 
|         |    239             return score | 
|         |    240         if dl.dltype == "android": | 
|         |    241             return -1 | 
|         |    242         raise Exception("Unknown dls type: %r" % (dl,)) | 
|         |    243  | 
|         |    244     def chooseDownloads(self, dls): | 
|         |    245         return sorted(((self.scoreDownload(dl),dl) for dl in dls), key=lambda x: x[0], reverse=True) | 
|         |    246  | 
|         |    247     def __call__(self, dls): | 
|         |    248         return self.chooseDownloads(dls) | 
|         |    249  | 
|         |    250 selector = FileSelector() | 
|         |    251  | 
|         |    252 downloads = [] | 
|         |    253 for game in parseGamesFromFile("tidy_bundle.html"): | 
|    247     for dls in game.downloads: |    254     for dls in game.downloads: | 
|    248         choosen = dls.choose() |    255         scores = selector(dls) | 
|    249         for dl in dls: |    256         choosen = list(dl for score, dl in scores if score >= 0)[:1] | 
|    250             print("%s | %-20s | %-10s | %-25s | %s " % ( |    257         for score, dl in scores: | 
|         |    258             print("[%s] %2d | %-20s | %-10s | %-25s | %s " % ( | 
|    251                     "*" if dl in choosen else " ", |    259                     "*" if dl in choosen else " ", | 
|         |    260                     score, | 
|    252                     game.title,  |    261                     game.title,  | 
|    253                     dls.id, |    262                     dls.id, | 
|    254                     ", ".join(sorted(dl.attrs)), |    263                     ", ".join(sorted(dl.attrs)), | 
|    255                     dl.torrent)) |    264                     dl.torrent)) | 
|         |    265             if dl in choosen: | 
|         |    266                 downloads.append(dl) | 
|         |    267         if not scores: | 
|         |    268             print("No download for",dls.id) | 
|         |    269         print("-" * 80) | 
|         |    270  | 
|         |    271 import urllib.request | 
|         |    272 import urllib.parse | 
|         |    273 import os | 
|         |    274 opener = urllib.request.build_opener() | 
|         |    275 for dl in downloads: | 
|         |    276     fn = os.path.basename(urllib.parse.urlsplit(dl.torrent).path) | 
|         |    277     print("Saving",dl.torrent,"as",fn) | 
|         |    278     with opener.open(dl.torrent) as u: | 
|         |    279         with open(fn,"wb") as f: | 
|         |    280             f.write(u.read()) | 
|         |    281  |