-
Notifications
You must be signed in to change notification settings - Fork 888
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17314 from brave/feed-item-parse-cleanup
[brave-today] Feed item parsing clean up
- Loading branch information
Showing
11 changed files
with
234 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Copyright (c) 2023 The Brave Authors. All rights reserved. | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
# You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
import("//tools/json_schema_compiler/json_schema_api.gni") | ||
|
||
generated_types("api") { | ||
sources = [ "combined_feed.idl" ] | ||
|
||
root_namespace = "brave_news::api::%(namespace)s" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright (c) 2023 The Brave Authors. All rights reserved. | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
// You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
// Schema types used by brave today feed. | ||
|
||
[generate_error_messages] | ||
namespace combined_feed { | ||
|
||
// A dictionary with fields representing a feed item. | ||
dictionary Item { | ||
// A url for the item. | ||
DOMString url; | ||
|
||
// A string with a url for an image used for padding. | ||
DOMString padded_img; | ||
|
||
// The id code for the publisher. | ||
DOMString publisher_id; | ||
|
||
// The category the feed belongs to. | ||
DOMString category; | ||
|
||
// The title of the feed. | ||
DOMString title; | ||
|
||
// A description field for the feed item to be shown. | ||
DOMString description; | ||
|
||
// The name of the publisher of the item. | ||
DOMString publisher_name; | ||
|
||
// The score of the item. Should be logged when not present. | ||
double? score; | ||
|
||
// A publish date/time string in the format YYYY-MM-DD HH:MM:SS. | ||
DOMString publish_time; | ||
|
||
// The type of content of this feed. | ||
DOMString content_type; | ||
|
||
// An id for the creative instance. | ||
DOMString? creative_instance_id; | ||
|
||
// An offers category field. | ||
DOMString? offers_category; | ||
}; | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
// Copyright (c) 2021 The Brave Authors. All rights reserved. | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
// You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
#include "brave/components/brave_news/browser/combined_feed_parsing.h" | ||
|
||
#include <string> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "base/logging.h" | ||
#include "base/notreached.h" | ||
#include "base/strings/strcat.h" | ||
#include "base/strings/utf_string_conversions.h" | ||
#include "base/time/time.h" | ||
#include "base/types/expected.h" | ||
#include "brave/components/brave_news/api/combined_feed.h" | ||
#include "brave/components/brave_news/common/brave_news.mojom-forward.h" | ||
#include "brave/components/brave_news/common/brave_news.mojom-shared.h" | ||
#include "brave/components/brave_news/common/brave_news.mojom.h" | ||
#include "third_party/abseil-cpp/absl/types/optional.h" | ||
#include "ui/base/l10n/time_format.h" | ||
#include "url/gurl.h" | ||
|
||
namespace brave_news { | ||
|
||
namespace { | ||
|
||
base::expected<mojom::FeedItemPtr, std::string> ParseFeedItem( | ||
const base::Value& value) { | ||
std::u16string error; | ||
auto parsed_feed_item = api::combined_feed::Item::FromValue(value, &error); | ||
if (!parsed_feed_item) { | ||
return base::unexpected(base::StrCat( | ||
{"Failed to parse feed item. ", base::UTF16ToASCII(error)})); | ||
} | ||
api::combined_feed::Item& feed_item = *parsed_feed_item; | ||
|
||
auto url = GURL(feed_item.url); | ||
if (url.is_empty() || !url.has_host()) { | ||
return base::unexpected(base::StrCat( | ||
{"Found feed item with an invalid url value. title=", feed_item.title, | ||
", url=", feed_item.url})); | ||
} | ||
|
||
if (!url.SchemeIsHTTPOrHTTPS()) { | ||
return base::unexpected( | ||
base::StrCat({"Item url was not HTTP or HTTPS: url=", url.spec()})); | ||
} | ||
|
||
if (feed_item.padded_img.empty()) { | ||
return base::unexpected(base::StrCat( | ||
{"Found feed item with missing image. url=", feed_item.url})); | ||
} | ||
|
||
if (feed_item.publisher_id.empty()) { | ||
return base::unexpected(base::StrCat( | ||
{"Found feed item with missing publisher id. url=", feed_item.url})); | ||
} | ||
|
||
if (feed_item.title.empty()) { | ||
return base::unexpected(base::StrCat( | ||
{"Found feed item with missing title. url=", feed_item.url})); | ||
} | ||
|
||
if (!feed_item.score.has_value()) { | ||
// We just warn, as this is an optional field. | ||
VLOG(1) << "Item was missing score: " << feed_item.url; | ||
} | ||
|
||
auto metadata = mojom::FeedItemMetadata::New(); | ||
metadata->category_name = feed_item.category; | ||
metadata->title = feed_item.title; | ||
metadata->description = feed_item.description; | ||
metadata->publisher_id = feed_item.publisher_id; | ||
metadata->publisher_name = feed_item.publisher_name; | ||
metadata->image = mojom::Image::NewPaddedImageUrl(GURL(feed_item.padded_img)); | ||
metadata->url = std::move(url); | ||
|
||
// Further weight according to history | ||
metadata->score = feed_item.score.value_or(20.0); | ||
|
||
// Extract time | ||
if (!base::Time::FromUTCString(feed_item.publish_time.c_str(), | ||
&metadata->publish_time)) { | ||
VLOG(1) << "Bad time string for feed item: " << feed_item.publish_time; | ||
} else { | ||
// Successful, get language-specific relative time | ||
base::TimeDelta relative_time_delta = | ||
base::Time::Now() - metadata->publish_time; | ||
metadata->relative_time_description = | ||
base::UTF16ToUTF8(ui::TimeFormat::Simple( | ||
ui::TimeFormat::Format::FORMAT_ELAPSED, | ||
ui::TimeFormat::Length::LENGTH_LONG, relative_time_delta)); | ||
} | ||
// Detect type | ||
if (feed_item.content_type == "brave_partner") { | ||
if (!feed_item.creative_instance_id || | ||
feed_item.creative_instance_id->empty()) { | ||
return base::unexpected( | ||
base::StrCat({"Promoted item has empty creative_instance_id. url=", | ||
feed_item.url})); | ||
} | ||
|
||
auto item = mojom::PromotedArticle::New(); | ||
item->creative_instance_id = *feed_item.creative_instance_id; | ||
item->data = std::move(metadata); | ||
return mojom::FeedItem::NewPromotedArticle(std::move(item)); | ||
} else if (feed_item.content_type == "product") { | ||
auto item = mojom::Deal::New(); | ||
if (feed_item.offers_category) { | ||
item->offers_category = *feed_item.offers_category; | ||
} | ||
item->data = std::move(metadata); | ||
return mojom::FeedItem::NewDeal(std::move(item)); | ||
} else if (feed_item.content_type == "article") { | ||
auto item = mojom::Article::New(); | ||
item->data = std::move(metadata); | ||
return mojom::FeedItem::NewArticle(std::move(item)); | ||
} | ||
|
||
// An unknown content_type could be something introduced for future use. | ||
return base::unexpected( | ||
base::StrCat({"Feed item of unknown content type. content_type=", | ||
feed_item.content_type})); | ||
} | ||
|
||
} // namespace | ||
|
||
std::vector<mojom::FeedItemPtr> ParseFeedItems(const base::Value& value) { | ||
std::vector<mojom::FeedItemPtr> items; | ||
if (!value.is_list()) { | ||
NOTREACHED(); | ||
return items; | ||
} | ||
for (const base::Value& feed_item : value.GetList()) { | ||
auto item = ParseFeedItem(feed_item); | ||
if (item.has_value()) { | ||
items.push_back(std::move(*item)); | ||
} else { | ||
VLOG(1) << item.error(); | ||
} | ||
} | ||
return items; | ||
} | ||
|
||
} // namespace brave_news |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.