def _get_feed(timeline): """Generates a feed from timeline.""" items = [] for tweet in timeline: item = {"id": tweet["id_str"]} try: item["time"] = int( calendar.timegm( dateutil.parser.parse(tweet["created_at"]).utctimetuple())) if tweet.get("retweeted_status") is None: real_tweet = tweet item["title"] = tweet["user"]["name"] else: real_tweet = tweet["retweeted_status"] item["title"] = "{} (retweeted by {})".format( real_tweet["user"]["name"], tweet["user"]["name"]) item["url"] = _twitter_user_url( real_tweet["user"] ["screen_name"]) + "/status/" + real_tweet["id_str"] item["text"] = _image_block( _twitter_user_url(real_tweet["user"]["screen_name"]), real_tweet["user"]["profile_image_url_https"], _parse_text(real_tweet["full_text"], real_tweet["entities"])) except Exception: LOG.exception("Failed to process the following tweet:\n%s", pprint.pformat(tweet)) item.setdefault("title", "Internal server error") item.setdefault( "text", "Internal server error has occurred during processing this tweet" ) items.append(item) return { "title": "Twitter", "url": _TWITTER_URL, "image": _TWITTER_URL + "images/resources/twitter-bird-light-bgs.png", "description": "Twitter timeline", "items": items, }
def _get_feed(timeline): """Generates a feed from timeline.""" items = [] for tweet in timeline: item = { "id": tweet["id_str"] } try: item["time"] = int(calendar.timegm(dateutil.parser.parse(tweet["created_at"]).utctimetuple())) if tweet.get("retweeted_status") is None: real_tweet = tweet item["title"] = tweet["user"]["name"] else: real_tweet = tweet["retweeted_status"] item["title"] = "{} (retweeted by {})".format( real_tweet["user"]["name"], tweet["user"]["name"]) item["url"] = _twitter_user_url(real_tweet["user"]["screen_name"]) + "/status/" + real_tweet["id_str"] item["text"] = _image_block( _twitter_user_url(real_tweet["user"]["screen_name"]), real_tweet["user"]["profile_image_url_https"], _parse_text(real_tweet["text"], real_tweet["entities"])) except Exception: LOG.exception("Failed to process the following tweet:\n%s", pprint.pformat(tweet)) item.setdefault("title", "Internal server error") item.setdefault("text", "Internal server error has occurred during processing this tweet") items.append(item) return { "title": "Twitter", "url": _TWITTER_URL, "image": _TWITTER_URL + "images/resources/twitter-bird-light-bgs.png", "description": "Twitter timeline", "items": items, }
def _get_newsfeed(access_token): """Returns VK news feed.""" response = vk_api.call(access_token, "newsfeed.get", max_photos=10) try: items = [] users = _get_users(response["profiles"], response["groups"]) # For now always log the complete newsfeed for easy debugging until # the project become mature LOG.info("Newsfeed: %s", pprint.pformat(response["items"])) for api_item in response["items"]: try: user = users[api_item["source_id"]] if api_item["type"] == "post": item = _post_item(users, user, api_item) elif api_item["type"] in ("photo", "photo_tag"): item = _photo_item(users, user, api_item) elif api_item["type"] == "wall_photo": continue # It duplicates post items with any photo elif api_item["type"] == "friend": item = _friend_item(users, user, api_item) elif api_item["type"] == "note": item = _note_item(users, user, api_item) else: raise Error("Unknown news item type.") # This item should be skipped if item is None: continue item["author"] = user["name"] item["text"] = _image_block(_get_user_url(user["id"]), user["photo"], item["text"]) item.setdefault("categories", set()).update([ _CATEGORY_TYPE + api_item["type"], (_CATEGORY_SOURCE_GROUP if user["id"] < 0 else _CATEGORY_SOURCE_USER) + _get_profile_name(user["id"]), ]) except Exception: LOG.exception("Failed to process news feed item:\n%s", pprint.pformat(api_item)) item = { "title": "Внутренняя ошибка сервера", "text": "При обработке новости произошла внутренняя ошибка сервера", } item["id"] = "{}/{}/{}".format( _get_profile_name(api_item["source_id"]), api_item["type"], api_item["date"]) item["time"] = api_item["date"] items.append(item) except Exception: LOG.exception("Failed to process news feed:\n%s", pprint.pformat(response)) raise return { "title": "ВКонтакте: Новости", "url": _vk_url(), "image": _vk_url("press/Simple.png"), "description": "Новостная лента ВКонтакте", "items": items, }
def _post_item(users, user, item): """Parses a wall post item.""" attachment_order = ( "doc", "note", "page", "poll", "album", "posted_photo", "photo", "graffiti", "app", "video", "link", "audio", ) def attachment_sort_key(attachment): try: return attachment_order.index(attachment["type"]) except ValueError: return len(attachment_order) top_html = "" bottom_html = "" categories = set() unknown_attachments = set() attachments = sorted( item.get("attachments", []), key=attachment_sort_key) if not item["text"] and not attachments and "geo" in item: LOG.debug("Skip check-in item from %s from %s.", user["name"], item["date"]) return if ( "attachment" in item and item["text"] == item["attachment"][item["attachment"]["type"]].get("title") ): main_html = "" else: main_html = _parse_text(item["text"]) photo_count = functools.reduce( lambda count, attachment: count + ( attachment["type"] in ("app", "graffiti", "photo", "posted_photo") ), attachments, 0) big_image = photo_count == 1 for attachment in attachments: attachment_category = attachment["type"] # Notice: attachment object is not always stored in # attachment[attachment["type"]] - sometimes it's stored under a # different key, so we can't obtain it here for all attachment types. if attachment["type"] == "app": info = attachment[attachment["type"]] top_html += _block( _vk_link(_vk_id("app", info["app_id"]), _image(info["src_big" if big_image else "src"]))) elif attachment["type"] == "graffiti": info = attachment[attachment["type"]] top_html += _block( _vk_link(_vk_id("graffiti", info["gid"]), _image(info["src_big" if big_image else "src"]))) elif attachment["type"] == "link": info = attachment[attachment["type"]] link_block = _em("Ссылка: " + _link(info["url"], info["title"])) link_description = _parse_text(info["description"]) or info["title"] if "image_src" in info: if link_description: link_block += _image_block(info["url"], info["image_src"], link_description) else: link_block += _block(_link(info["url"], _image(info["image_src"]))) elif link_description: link_block += _block(link_description) top_html += _block(link_block) elif attachment["type"] == "album": info = attachment[attachment["type"]] top_html += _image_block( _vk_url("album", info["owner_id"], info["aid"]), info["thumb"]["src"], "Альбом: {description} ({size} фото)".format(description=info["description"].strip(), size=info["size"])) elif attachment["type"] == "photo": top_html += _photo(attachment[attachment["type"]], big_image) attachment_category = "posted_photo" elif attachment["type"] == "posted_photo": top_html += _photo(attachment[attachment["type"]], big_image) elif attachment["type"] == "photos_list": # It seems like photos_list always duplicates photo attachments attachment_category = "posted_photo" elif attachment["type"] == "audio": info = attachment[attachment["type"]] bottom_html += _block(_em( "Аудиозапись: " + _vk_link( "search?" + urlencode({ "c[q]": info["performer"] + " - " + info["title"], "c[section]": "audio" }), "{} - {} ({})".format(info["performer"], info["title"], _duration(info["duration"]))))) elif attachment["type"] == "doc": info = attachment[attachment["type"]] if "url" in info and "thumb" in info: bottom_html += _block(_image_block( info["url"], info["thumb"], _link(info["url"], info["title"]))) else: bottom_html += _block(_em("Документ: {}".format(info["title"]))) elif attachment["type"] == "video": info = attachment[attachment["type"]] top_html += _block( _image(info["image"]) + _block(_em("{} ({})".format(info["title"], _duration(info["duration"]))))) elif attachment["type"] == "note": top_html += _block(_em("Заметка: {}".format( attachment[attachment["type"]]["title"]))) elif attachment["type"] == "page": top_html += _block(_em("Страница: {}".format( attachment[attachment["type"]]["title"]))) elif attachment["type"] == "poll": top_html += _block(_em("Опрос: {}".format( attachment[attachment["type"]]["question"]))) else: unknown_attachments.add(attachment["type"]) categories.add(_CATEGORY_TYPE + attachment_category) if unknown_attachments: LOG.error("Got a post with unknown attachment type (%s):\n%s", ", ".join(unknown_attachments), pprint.pformat(item)) html = top_html + main_html + bottom_html if "copy_owner_id" in item and "copy_post_id" in item: html = _block( _em(_link( _get_user_url(item["copy_owner_id"]), users[item["copy_owner_id"]]["name"] )) + " пишет:" ) + html if "copy_text" in item: html = _quote_block(item["copy_text"], html) categories.add(_CATEGORY_TYPE_REPOST) return { "title": user["name"] + ": запись на стене", "text": html, "url": _vk_url("wall", user["id"], item["post_id"]), "categories": categories, }
def _get_newsfeed(access_token, show_user_avatars): """Returns VK news feed.""" response = vk_api.call(access_token, "newsfeed.get", max_photos=10) try: items = [] users = _get_users(response["profiles"], response["groups"]) LOG.debug("Newsfeed: %s", pprint.pformat(response["items"])) for api_item in response["items"]: try: user = users[api_item["source_id"]] if api_item["type"] == "post": item = _post_item(users, user, api_item) elif api_item["type"] in ("photo", "photo_tag"): item = _photo_item(users, user, api_item) elif api_item["type"] in ("audio", "video"): continue # Don't generate items for every song or movie added by someone elif api_item["type"] == "wall_photo": continue # It duplicates post items with any photo elif api_item["type"] == "friend": item = _friend_item(users, user, api_item) elif api_item["type"] == "note": item = _note_item(users, user, api_item) else: raise Error("Unknown news item type.") # This item should be skipped if item is None: continue item["author"] = user["name"] if show_user_avatars: item["text"] = _image_block(_get_user_url(user["id"]), user["photo"], item["text"]) item["categories"] = sorted( item.get("categories", set()) | { _CATEGORY_TYPE + api_item["type"], (_CATEGORY_SOURCE_GROUP if user["id"] < 0 else _CATEGORY_SOURCE_USER) + _get_profile_name(user["id"]), }) except Exception: LOG.exception("Failed to process news feed item:\n%s", pprint.pformat(api_item)) item = { "title": "Внутренняя ошибка сервера", "text": "При обработке новости произошла внутренняя ошибка сервера", } item["id"] = "{}/{}/{}".format( _get_profile_name(api_item["source_id"]), api_item["type"], api_item["date"]) item["time"] = api_item["date"] items.append(item) except Exception: LOG.exception("Failed to process news feed:\n%s", pprint.pformat(response)) raise return { "title": "ВКонтакте: Новости", "url": _vk_url(), "image": _vk_url("press/Simple.png"), "description": "Новостная лента ВКонтакте", "items": items, }
def _post_item(users, user, item): """Parses a wall post item.""" attachment_order = ( "doc", "note", "page", "poll", "album", "posted_photo", "photo", "graffiti", "app", "video", "link", "audio", ) def attachment_sort_key(attachment): try: return attachment_order.index(attachment["type"]) except ValueError: return len(attachment_order) top_html = "" bottom_html = "" categories = set() unknown_attachments = set() attachments = sorted(item.get("attachments", []), key=attachment_sort_key) if not item["text"] and not attachments and "geo" in item: LOG.debug("Skip check-in item from %s from %s.", user["name"], item["date"]) return if ("attachment" in item and item["text"] == item["attachment"][item["attachment"]["type"]].get("title")): main_html = "" else: main_html = _parse_text(item["text"]) photo_count = functools.reduce( lambda count, attachment: count + (attachment["type"] in ("app", "graffiti", "photo", "posted_photo")), attachments, 0) big_image = photo_count == 1 for attachment in attachments: attachment_category = attachment["type"] # Notice: attachment object is not always stored in # attachment[attachment["type"]] - sometimes it's stored under a # different key, so we can't obtain it here for all attachment types. if attachment["type"] == "app": info = attachment[attachment["type"]] top_html += _block( _vk_link( _vk_id("app", info["id"]), _image(info["photo_604" if big_image else "photo_130"]))) elif attachment["type"] == "graffiti": info = attachment[attachment["type"]] top_html += _block( _vk_link( _vk_id("graffiti", info["id"]), _image(info["photo_604" if big_image else "photo_130"]))) elif attachment["type"] == "link": info = attachment[attachment["type"]] link_block = _em("Ссылка: " + _link(info["url"], info["title"])) link_description = _parse_text( info["description"]) or info["title"] if "photo" in info: if link_description: link_block += _image_block(info["url"], info["photo"]["photo_130"], link_description) else: link_block += _block( _link(info["url"], _image(info["photo"]["photo_130"]))) elif link_description: link_block += _block(link_description) top_html += _block(link_block) elif attachment["type"] == "album": info = attachment[attachment["type"]] top_html += _image_block( _vk_url("album", info["owner_id"], info["id"]), info["thumb"]["photo_130"], "Альбом: {description} ({size} фото)".format( description=info["description"].strip(), size=info["size"])) elif attachment["type"] == "photo": top_html += _photo(attachment[attachment["type"]], big_image) attachment_category = "posted_photo" elif attachment["type"] == "posted_photo": top_html += _photo(attachment[attachment["type"]], big_image) elif attachment["type"] == "photos_list": # It seems like photos_list always duplicates photo attachments attachment_category = "posted_photo" elif attachment["type"] == "audio": info = attachment[attachment["type"]] bottom_html += _block( _em("Аудиозапись: " + _vk_link( "search?" + urlencode({ "c[q]": info["artist"] + " - " + info["title"], "c[section]": "audio" }), "{} - {} ({})".format(info["artist"], info["title"], _duration(info["duration"]))))) elif attachment["type"] == "doc": info = attachment[attachment["type"]] bottom_html += _block(_em("Документ: {}".format(info["title"]))) elif attachment["type"] == "video": info = attachment[attachment["type"]] video_block = _block( _em("{} ({})".format(info["title"], _duration(info["duration"])))) # Restricted videos may appear without image if "photo_320" in info: video_block = _block(_image(info["photo_320"]) + video_block) top_html += video_block categories.add(_CATEGORY_ATTACHMENT + "video/" + str(info["id"])) elif attachment["type"] == "note": top_html += _block( _em("Заметка: {}".format( attachment[attachment["type"]]["title"]))) elif attachment["type"] == "page": top_html += _block( _em("Страница: {}".format( attachment[attachment["type"]]["title"]))) elif attachment["type"] == "poll": top_html += _block( _em("Опрос: {}".format( attachment[attachment["type"]]["question"]))) else: unknown_attachments.add(attachment["type"]) categories.add(_CATEGORY_TYPE + attachment_category) if unknown_attachments: LOG.error("Got a post with unknown attachment type (%s):\n%s", ", ".join(unknown_attachments), pprint.pformat(item)) html = top_html + main_html + bottom_html if "copy_owner_id" in item and "copy_post_id" in item: html = _block( _em( _link(_get_user_url(item["copy_owner_id"]), users[ item["copy_owner_id"]]["name"])) + " пишет:") + html if "copy_text" in item: html = _quote_block(item["copy_text"], html) categories.add(_CATEGORY_TYPE_REPOST) return { "title": user["name"] + ": запись на стене", "text": html, "url": _vk_url("wall", user["id"], item["post_id"]), "categories": categories, }