-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcard.py
118 lines (88 loc) · 4.4 KB
/
card.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import asyncio
from datetime import datetime
import json
import os
import aiohttp
class Card():
def __init__(self, json: dict, path: str):
self.__json = json
self.__path = path
def __get_card_path(self, path: str, id: int)-> str:
card_path = os.path.join(path, str(id))
os.makedirs(card_path, exist_ok=True)
return card_path
def __sync_card_info_id(self, card_id: int)-> bool:
path = os.path.join(self.__get_card_path(self.__path, card_id), "info.json")
modified_json = self.__json.copy()
modified_json['id'] = card_id
# Check if card info already exists
if os.path.exists(path):
with open(path, "r") as r:
existing_card = json.load(r)
if existing_card == self.__json:
print("\tCard info already exists for " + self.__json['name'] + " with id " + str(card_id))
return False
print("\tSaving card info for " + self.__json['name'] + " with id " + str(card_id))
with open(path, "w") as w:
json.dump(self.__json, w, indent=4)
return True
def sync_card_info(self) -> bool:
return any([self.__sync_card_info_id(card_id) for card_id in self.identities])
async def __download_image_async(self, session: aiohttp.ClientSession, image_url: str, image_path: str) -> bool:
print(f"\tDownloading {image_url} to {image_path}")
start_time = datetime.now()
try:
async with session.get(image_url) as response:
end_time = datetime.now()
response_time = end_time - start_time
if response.status != 200:
print(f"Failed to download image {image_url}: {response.status} ({response_time})")
return False
content = await response.read()
# Check if image already exists
if os.path.exists(image_path):
with open(image_path, "rb") as f:
existing_content = f.read()
if content == existing_content:
print(f"\tImage {image_url} already exists at {image_path} ({response_time})")
return False
with open(image_path, "wb") as f:
f.write(content)
print(f"\tDownloaded {image_url} to {image_path} ({response_time})")
return True
except Exception as e:
print(f"Error downloading {image_url}: {str(e)}")
def __get_image_dict_for_id(self, card_id: int) -> dict:
return next(image for image in self.__json['card_images'] if image['id'] == card_id)
async def download_images_async_for_id(self, session: aiohttp.ClientSession, card_id: int)-> bool:
dir = os.path.join(self.__get_card_path(self.__path, card_id), "images")
os.makedirs(dir, exist_ok=True)
images = self.__get_image_dict_for_id(card_id)
if not images:
print(f"No images found for card id {card_id}")
return False
# images is a dict with keys 'image_url', 'image_url_small', 'image_url_cropped'
tasks = []
for image_type, url_key in [("full", 'image_url'), ("small", 'image_url_small'), ("cropped", 'image_url_cropped')]:
path = os.path.join(dir, f"{image_type}.jpg")
tasks.append(self.__download_image_async(session, images[url_key], path))
# Check if any image returned True (i.e. was downloaded)
if any(await asyncio.gather(*tasks)):
print("\tImages downloaded for " + self.name)
return True
return False
async def download_images_async(self, session: aiohttp.ClientSession)-> bool:
return any([await self.download_images_async_for_id(session, card_id) for card_id in self.identities])
async def sync(self, session: aiohttp.ClientSession):
info_saved = self.sync_card_info()
image_saved = await self.download_images_async(session)
return info_saved or image_saved
@property
def name(self):
return self.__json['name']
@property
def id(self):
return self.__json['id']
@property
def identities(self):
return list(set([image['id'] for image in self.__json['card_images']]))