OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python2 |
| 2 # Copyright 2017 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 from __future__ import absolute_import |
| 7 from __future__ import division |
| 8 from __future__ import print_function |
| 9 |
| 10 import argparse |
| 11 import contextlib |
| 12 import glob |
| 13 import io |
| 14 import json |
| 15 import os |
| 16 import sys |
| 17 import urllib |
| 18 import Image |
| 19 |
| 20 """ |
| 21 This script downloads the default popular sites and large icons associated |
| 22 with it. If an icon is too large, it will get resized in the process. |
| 23 """ |
| 24 |
| 25 DEFAULT_POPULAR_SITES = ("https://www.gstatic.com/chrome/ntp/" |
| 26 "suggested_sites_DEFAULT_5.json") |
| 27 |
| 28 LARGE_ICON_KEY = "large_icon_url" |
| 29 SITE_TITLE_KEY = "title" |
| 30 MAXIMAL_SIZE = 144 |
| 31 SITE_ICON_DELETE = "icon[0-9].png" |
| 32 SITE_ICON_FORMAT = "icon%d.png" |
| 33 NTP_TILES_RESOURCE_PATH = os.path.join( |
| 34 os.path.dirname(os.path.realpath(__file__)), "resources") |
| 35 DEFAULT_POPULAR_SITES_PATH = os.path.join(NTP_TILES_RESOURCE_PATH, |
| 36 "default_popular_sites.json") |
| 37 |
| 38 def download_as_json(url): |
| 39 """Downloads data from the given |url| and returns it in JSON format.""" |
| 40 print("Downloading popular sites... (" + url + ")") |
| 41 with contextlib.closing(urllib.urlopen(url=url)) as url_data: |
| 42 data = json.load(url_data) |
| 43 print("... done. (%d sites found)" % len(data)) |
| 44 return data |
| 45 |
| 46 def download_as_image(url): |
| 47 """Downloads data from the given |url| and returns it as Image.""" |
| 48 with contextlib.closing(urllib.urlopen(url=url)) as url_data: |
| 49 image_response_data = url_data.read() |
| 50 return Image.open(io.BytesIO(image_response_data)) |
| 51 |
| 52 def write_to_json(data, out_path, pretty_print): |
| 53 """Writes |data| to the given |out_path|. Minifies the JSON unless |
| 54 |pretty_print| is set to true.""" |
| 55 separators = (",", ":") |
| 56 indent = None |
| 57 sort = False |
| 58 if pretty_print: |
| 59 separators = (",", ": ") |
| 60 indent = 4 |
| 61 sort = True |
| 62 with open(out_path, "w") as f: |
| 63 json.dump(data, f, sort_keys=sort, indent=indent, separators=separators) |
| 64 print("JSON was written to " + out_path) |
| 65 |
| 66 def delete_old_icons(): |
| 67 """Deletes all PNG icons within the resource path.""" |
| 68 print("Deleting old icons..") |
| 69 for f in glob.glob(os.path.join(NTP_TILES_RESOURCE_PATH, SITE_ICON_DELETE)): |
| 70 os.remove(os.path.join(f)) |
| 71 print("... done.") |
| 72 |
| 73 def resize_if_too_large(image, max_size): |
| 74 """Takes a square icon and resizes if it exceeds the maximal width.""" |
| 75 if image.size[0] > max_size: |
| 76 print("... and resizing image from %s to %s ..." % |
| 77 (image.size, (max_size, max_size))); |
| 78 image.thumbnail((max_size, max_size), Image.ANTIALIAS) |
| 79 |
| 80 |
| 81 |
| 82 def lacks_required_keys(site): |
| 83 """A site must at least provide a title and a large icon to be processed.""" |
| 84 return not SITE_TITLE_KEY in site or not LARGE_ICON_KEY in site |
| 85 |
| 86 |
| 87 def main(): |
| 88 parser = argparse.ArgumentParser( |
| 89 description="Downloads the latest popular sites and their icons. \n\n" |
| 90 "It is possible to customize the default like this:\n" |
| 91 " 1. python " + __file__ + " -o temp.json --no_icons " |
| 92 "--pretty_print\n" |
| 93 " 2. Adjust the downloaded temp.json\n" |
| 94 " 3. python " + __file__ + " -f temp.json -s 96\n\n" |
| 95 "The result would be a minified version of your customized JSON " |
| 96 "and all icons would be downloaded as you specified.\n The icons " |
| 97 "had a max size of 96x96.", |
| 98 formatter_class=argparse.RawTextHelpFormatter) |
| 99 parser.add_argument("-s", "--size", metavar="size_in_px", type=int, |
| 100 default=MAXIMAL_SIZE, |
| 101 help="size to scale too large icons down to; defaults " |
| 102 "to 144px") |
| 103 parser.add_argument("-u", "--url", type=str, |
| 104 default=DEFAULT_POPULAR_SITES, |
| 105 help="the endpoint to query for json of sites") |
| 106 parser.add_argument("--no_icons", action="store_true", |
| 107 help="do not download icons") |
| 108 parser.add_argument("--no_resizing", action="store_true", |
| 109 help="do not resize any icons") |
| 110 parser.add_argument("-f", "--in_file", metavar="path_to_json_file", |
| 111 type=str, |
| 112 help="skip download and load icons for a local json") |
| 113 parser.add_argument("-o", "--out_path", metavar="path_to_out_file", |
| 114 type=str, default=DEFAULT_POPULAR_SITES_PATH, |
| 115 help="skip download and load icons for a local json") |
| 116 parser.add_argument("-p", "--pretty_print", action="store_true", |
| 117 help="pretty_print instead of minifying the JSON") |
| 118 args = parser.parse_args() |
| 119 |
| 120 if args.in_file: |
| 121 with open(args.in_file) as f: |
| 122 popular_sites = json.load(f) |
| 123 else: |
| 124 popular_sites = download_as_json(args.url) |
| 125 write_to_json(popular_sites, args.out_path, args.pretty_print) |
| 126 |
| 127 if args.no_icons: |
| 128 return |
| 129 |
| 130 delete_old_icons() |
| 131 for i, site in enumerate(popular_sites): |
| 132 if lacks_required_keys(site): |
| 133 print("Could not download large image for site: %r" % site) |
| 134 continue |
| 135 print("Downloading icon for '%r'..." % site[SITE_TITLE_KEY]) |
| 136 image = download_as_image(site[LARGE_ICON_KEY]) |
| 137 if not args.no_resizing: |
| 138 resize_if_too_large(image, args.size) |
| 139 image_name = SITE_ICON_FORMAT % i |
| 140 image.save(os.path.join(NTP_TILES_RESOURCE_PATH, image_name), "PNG", |
| 141 optimize=True) |
| 142 print("... done. (Stored as " + image_name + ")"); |
| 143 |
| 144 |
| 145 if __name__ == "__main__": |
| 146 main() |
OLD | NEW |