def __update_listing(self, d, e): """update database listing d with data of etsy listing e""" changes = False if d.state != e.state: self.log("'%s' state '%s' --> '%s'" % (d.title, d.state, e.state)) d.state = e.state if e.state != "active": #we don't care for edits much as they don't change ranking or anything storage.Events(listing = d, shop = d.shop, event = d.state).put() changes = True if hasattr(e, "title") and d.title != e.title: self.log("'%s' title --> '%s'" % (d.title, e.title)) d.title = e.title changes = True if hasattr(e, "views") and d.views != int(e.views): views = int(e.views) - (d.views or 0) self.log("'%s' views +%d" % (d.title, views)) d.views = int(e.views) self.__add_exposure(d, views) changes = True if hasattr(e, "ending_tsz") and appetsy.zero_timezone(d.ending) != appetsy.etsy_epoch(e.ending_tsz): if not d.ending: storage.Events(listing = d, shop = d.shop, event = "posted", created = appetsy.etsy_epoch(e.creation_tsz)).put() else: self.log("'%s' renewed" % d.title) storage.Events(listing = d, shop = d.shop, event = "renewed").put() d.ending = appetsy.etsy_epoch(e.ending_tsz) changes = True if hasattr(e, "price") and d.price != float(e.price): self.log("'%s' price %.2f --> %.2f" % (e.title, (d.price or 0.0), float(e.price))) d.price = float(e.price) changes = True if changes: memcache.set("listing:%d" % d.id, d) #store our memcache copy for next cron appetsy.invalidate_memcache("goods", str(d.shop.id)) #forget UI listings return changes
def faves(self, key): if isinstance(key, db.Model): item = key else: key = db.Key(key) if not key: return "need key" item = db.get(key) data = dict(today = [], other_days = []) data['shop'] = self.shop today = appetsy.today(self.shop) if item.kind() == "Fans": faves = storage.ItemFans.all() \ .filter("fan =", item) \ .order("-favored_on").fetch(500) for fave in faves: fave.image_url = fave.listing.image_url fave.str_key = fave.listing.key() fave.user_name = "" if appetsy.zero_timezone(fave.favored_on) >= today: data["today"].append(fave) else: data["other_days"].append(fave) shopfave = storage.ShopFans.all() \ .filter("fan =", item) \ .filter("shop =", self.shop).get() if shopfave: shopfave.image_url = "veikals" shopfave.str_key = "" shopfave.user_name = "" if appetsy.zero_timezone(shopfave.favored_on) >= today: data["today"].append(shopfave) data["today"] = sorted(data["today"], key=lambda x:x.favored_on, reverse = True) else: data["other_days"].append(shopfave) data["other_days"] = sorted(data["other_days"], key=lambda x:x.favored_on, reverse = True) else: itemfans = storage.ItemFans.all() \ .filter("listing =", item) \ .filter("shop =", item.shop) \ .order("-favored_on").fetch(500) for item in itemfans: fave = item.fan fave.str_key = item.fan.key() fave.user_name = item.fan.user_name if appetsy.zero_timezone(item.favored_on) >= today: data["today"].append(fave) else: data["other_days"].append(fave) return appetsy.get_template("/fans/faves.html").render(**data)
def get(self): if not self.etsy: return listing_id = self.request.get("listing") if not listing_id: self.log("no listing - exiting!") return listing = self.get_listing(listing_id) if not listing: self.log("Can't find listing with id %s" % listing_id) self.log("%s: Getting details for %s (%d known faves)..." % (listing.shop.shop_name, listing.title, listing.faves or 0)) # get all etsy fans etsy_favorers_by_timestamp = {} def get_listing_info(offset = 0): if offset > 0: self.log("%d - %d..." % (offset, offset + 100)) listing_info = self.etsy.getListing(listing.id, ["Images", "FavoredBy:100:%d" % offset]) if len(listing_info.FavoredBy) > 0 and len(listing_info.FavoredBy) % 100 == 0: listing_info.FavoredBy.extend(get_listing_info(offset + 100).FavoredBy) return listing_info listing_info = get_listing_info() for item in listing_info.FavoredBy: etsy_favorers_by_timestamp[appetsy.etsy_epoch(item.creation_tsz)] = item etsy_timestamps = set(etsy_favorers_by_timestamp.keys()) #update fan count for item listing.faves = len(etsy_timestamps) listing.image_url = listing_info.Images[0].url_75x75 listing.put() db_timestamps = memcache.get("listing:%d_fans" % listing.id) if not db_timestamps: #get all db fans db_favorers_by_timestamp = {} item_fans = db.GqlQuery("SELECT * FROM ItemFans WHERE listing = :1", listing).fetch(1000) db_timestamps = set([appetsy.zero_timezone(item.favored_on) for item in item_fans]) # if both sets match - go home if len(db_timestamps - etsy_timestamps) + len(etsy_timestamps - db_timestamps) == 0: self.log("Same fans") pending = memcache.get("items_pending_refresh") or [] if listing.id in pending: pending.remove(listing.id) memcache.set("items_pending_refresh", pending) return #new fans in etsy item_fans = [] for timestamp in (etsy_timestamps - db_timestamps): favorer = etsy_favorers_by_timestamp[timestamp] fan = self.get_fan(favorer) item_fans.append(storage.ItemFans(fan = fan, listing = listing, shop = listing.shop, favored_on = appetsy.etsy_epoch(favorer.creation_tsz))) self.log(" New fan: '%s'" % (fan.user_name or fan.key())) db.put(item_fans) #gone fans for timestamp in (db_timestamps - etsy_timestamps): # FIXME potentially expensive - this will be replaced by key name ex_favorer = storage.ItemFans.all().filter("shop =", listing.shop) \ .filter("listing =", listing) \ .filter("favored_on =", timestamp).get() self.log(" Removed fave: '%s'" % ex_favorer.fan.user_name) db.delete(ex_favorer) pending = memcache.get("items_pending_refresh") or [] if listing.id in pending: pending.remove(listing.id) memcache.set("items_pending_refresh", pending) #update listing fan cache memcache.set("listing:%d_fans" % listing.id, etsy_timestamps) appetsy.invalidate_memcache("fans", namespace = str(listing.shop.id))