From 3995cd5b91ce420dcca2097fcb9f0eb6c4f214d5 Mon Sep 17 00:00:00 2001 From: NejcZdovc Date: Wed, 6 Mar 2019 23:03:03 +0100 Subject: [PATCH] Fixes twitch panel Resolves https://github.com/brave/brave-browser/issues/3590 Resolves https://github.com/brave/brave-browser/issues/4680 --- .../browser/publisher_info_database.cc | 2 +- .../publisher_info_database_unittest.cc | 2 +- .../actions/rewards_panel_actions.ts | 2 +- .../brave_rewards/background/api/tabs_api.ts | 2 +- .../background/events/tabEvents.ts | 2 +- .../brave_rewards/components/app.tsx | 25 +- .../reducers/rewards_panel_reducer_test.ts | 69 ++++- .../include/bat/ledger/publisher_info.h | 3 +- .../src/bat/ledger/internal/bat_publishers.cc | 4 +- .../src/bat/ledger/internal/media/twitch.cc | 284 +++++++++--------- .../src/bat/ledger/internal/media/twitch.h | 8 +- .../ledger/internal/media/twitch_unittest.cc | 167 ++++++---- 12 files changed, 340 insertions(+), 230 deletions(-) diff --git a/components/brave_rewards/browser/publisher_info_database.cc b/components/brave_rewards/browser/publisher_info_database.cc index 3e9719987845..4813d88a3168 100644 --- a/components/brave_rewards/browser/publisher_info_database.cc +++ b/components/brave_rewards/browser/publisher_info_database.cc @@ -275,7 +275,7 @@ bool PublisherInfoDatabase::InsertOrUpdatePublisherInfo( "UPDATE publisher_info SET favIcon = ? " "WHERE publisher_id = ?")); - if (favicon == ledger::_clear_favicon) { + if (favicon == ledger::kClearFavicon) { favicon.clear(); } diff --git a/components/brave_rewards/browser/publisher_info_database_unittest.cc b/components/brave_rewards/browser/publisher_info_database_unittest.cc index 1ed276b14ef2..dc8f5bda2e44 100644 --- a/components/brave_rewards/browser/publisher_info_database_unittest.cc +++ b/components/brave_rewards/browser/publisher_info_database_unittest.cc @@ -257,7 +257,7 @@ TEST_F(PublisherInfoDatabaseTest, InsertOrUpdatePublisherInfo) { /** * If favicon is marked as clear, clear it */ - info.favicon_url = ledger::_clear_favicon; + info.favicon_url = ledger::kClearFavicon; success = publisher_info_database_->InsertOrUpdatePublisherInfo(info); EXPECT_TRUE(success); diff --git a/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts b/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts index c402128dbefe..a6fd88f000a1 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/actions/rewards_panel_actions.ts @@ -17,7 +17,7 @@ export const onTabId = (tabId: number | undefined) => action(types.ON_TAB_ID, { tabId }) -export const onTabRetrieved = (tab: chrome.tabs.Tab, publisherBlob: string) => action(types.ON_TAB_RETRIEVED, { +export const onTabRetrieved = (tab: chrome.tabs.Tab, publisherBlob: string = 'ignore') => action(types.ON_TAB_RETRIEVED, { tab, publisherBlob }) diff --git a/components/brave_rewards/resources/extension/brave_rewards/background/api/tabs_api.ts b/components/brave_rewards/resources/extension/brave_rewards/background/api/tabs_api.ts index 9f3ea1af17ae..68e0e67cb330 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/background/api/tabs_api.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/background/api/tabs_api.ts @@ -5,5 +5,5 @@ export const getTabData = (tabId: number) => chrome.tabs.get(tabId, (tab: chrome.tabs.Tab) => { const rewardsPanelActions = require('../actions/rewardsPanelActions').default - rewardsPanelActions.onTabRetrieved(tab, '') + rewardsPanelActions.onTabRetrieved(tab) }) diff --git a/components/brave_rewards/resources/extension/brave_rewards/background/events/tabEvents.ts b/components/brave_rewards/resources/extension/brave_rewards/background/events/tabEvents.ts index 34f38b3b970d..a9d9ae883d54 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/background/events/tabEvents.ts +++ b/components/brave_rewards/resources/extension/brave_rewards/background/events/tabEvents.ts @@ -5,7 +5,7 @@ import rewardsPanelActions from '../actions/rewardsPanelActions' chrome.tabs.onUpdated.addListener((tabId: number, changeInfo: chrome.tabs.TabChangeInfo, tab: chrome.tabs.Tab) => { - rewardsPanelActions.onTabRetrieved(tab, '') + rewardsPanelActions.onTabRetrieved(tab) }) chrome.tabs.onActivated.addListener((activeInfo: chrome.tabs.TabActiveInfo) => { diff --git a/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx b/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx index bbd74a8c6cc0..e62d70803452 100644 --- a/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx +++ b/components/brave_rewards/resources/extension/brave_rewards/components/app.tsx @@ -71,28 +71,24 @@ export class RewardsPanel extends React.Component { if (!tabs || !tabs.length) { return } - const pollTwitchPage = (tab: chrome.tabs.Tab, tabId: number, publisherBlob: string) => { + const pollTwitchPage = (tab: chrome.tabs.Tab, tabId: number) => { // use an interval here to monitor when the DOM has finished // generating. clear after the data is present. // Check every second no more than 'limit' times // clear the interval if panel closes - const markupMatch = '
' + - '
' + - '\"' { clearInterval(interval) const rewardsPanelActions = require('../background/actions/rewardsPanelActions').default - rewardsPanelActions.onTabRetrieved(tab, publisherBlob) + rewardsPanelActions.onTabRetrieved(tab) } } }) @@ -115,15 +111,14 @@ export class RewardsPanel extends React.Component { } const pollData = (tab: chrome.tabs.Tab, tabId: number, url: URL) => { - let publisherBlob = '' if (url && url.href.startsWith('https://www.twitch.tv/')) { chrome.storage.local.get(['rewards_panel_open'], function (result) { if (result['rewards_panel_open'] === 'true') { - pollTwitchPage(tab, tabId, publisherBlob) + pollTwitchPage(tab, tabId) } }) } else { - this.props.actions.onTabRetrieved(tab, publisherBlob) + this.props.actions.onTabRetrieved(tab) } } let tab = tabs[0] @@ -132,10 +127,10 @@ export class RewardsPanel extends React.Component { if (url && url.host.endsWith('.twitch.tv')) { pollData(tab, tab.id, url) } else { - this.props.actions.onTabRetrieved(tab, '') + this.props.actions.onTabRetrieved(tab) } } else { - this.props.actions.onTabRetrieved(tab, '') + this.props.actions.onTabRetrieved(tab) } }) } diff --git a/components/test/brave_rewards/extension/brave_rewards/background/reducers/rewards_panel_reducer_test.ts b/components/test/brave_rewards/extension/brave_rewards/background/reducers/rewards_panel_reducer_test.ts index 713e58a89487..acbde03050c8 100644 --- a/components/test/brave_rewards/extension/brave_rewards/background/reducers/rewards_panel_reducer_test.ts +++ b/components/test/brave_rewards/extension/brave_rewards/background/reducers/rewards_panel_reducer_test.ts @@ -59,8 +59,8 @@ describe('rewards panel reducer', () => { state.rewardsPanelData.publishers = { id_1: { tabUrl: 'https://clifton.io', - name: 'Clifton', - publisher_key: 'clifton.io' + publisher_key: 'clifton.io', + name: 'Clifton' } } @@ -72,8 +72,63 @@ describe('rewards panel reducer', () => { publishers: { id_1: { tabUrl: 'https://clifton.io', - name: 'Clifton', - publisher_key: 'clifton.io' + publisher_key: 'clifton.io', + name: 'Clifton' + } + } + } + + state = reducers(state, { + type: types.ON_TAB_RETRIEVED, + payload + }) + + expect(state.rewardsPanelData).toEqual(expectedState2) + }) + + it('url is the same, but publisher was not saved correctly', () => { + const initState: Rewards.State = { ...defaultState, walletCreated: true } + const payload = { + tab: { + url: 'https://clifton.io', + incognito: false, + active: true, + windowId: 1 + } + } + + // first visit + const expectedState1: Rewards.State = { + ...defaultState, + walletCreated: true, + publishers: { + id_1: { + tabUrl: 'https://clifton.io' + } + } + } + + let state = reducers({ rewardsPanelData: initState }, { + type: types.ON_TAB_RETRIEVED, + payload + }) + + expect(state.rewardsPanelData).toEqual(expectedState1) + + // imitates ON_PUBLISHER_DATA + state.rewardsPanelData.publishers = { + id_1: { + tabUrl: 'https://clifton.io' + } + } + + // second visit + const expectedState2: Rewards.State = { + ...defaultState, + walletCreated: true, + publishers: { + id_1: { + tabUrl: 'https://clifton.io' } } } @@ -122,9 +177,9 @@ describe('rewards panel reducer', () => { // imitates ON_PUBLISHER_DATA state.rewardsPanelData.publishers = { id_1: { - tabUrl: 'https://clifton.io', - name: 'Clifton', - publisher_key: 'clifton.io' + tabUrl: 'clifton.io', + publisher_key: 'clifton.io', + name: 'Clifton' } } diff --git a/vendor/bat-native-ledger/include/bat/ledger/publisher_info.h b/vendor/bat-native-ledger/include/bat/ledger/publisher_info.h index 93a9e1ec0f59..478ce806f2f9 100644 --- a/vendor/bat-native-ledger/include/bat/ledger/publisher_info.h +++ b/vendor/bat-native-ledger/include/bat/ledger/publisher_info.h @@ -15,7 +15,8 @@ namespace ledger { -const char _clear_favicon[] = "clear"; +const char kClearFavicon[] = "clear"; +const char kIgnorePublisherBlob[] = "ignore"; LEDGER_EXPORT enum REWARDS_CATEGORY { AUTO_CONTRIBUTE = 1 << 1, // 2 diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/bat_publishers.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/bat_publishers.cc index e7b7268c9403..44dfc0cce594 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/bat_publishers.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/bat_publishers.cc @@ -168,7 +168,7 @@ void BatPublishers::saveVisitInternal( publisher_info->favicon_url = fav_icon; } } else { - publisher_info->favicon_url = ledger::_clear_favicon; + publisher_info->favicon_url = ledger::kClearFavicon; } publisher_info->name = visit_data.name; @@ -219,7 +219,7 @@ void BatPublishers::saveVisitInternal( } if (panel_info && window_id > 0) { - if (panel_info->favicon_url == ledger::_clear_favicon) { + if (panel_info->favicon_url == ledger::kClearFavicon) { panel_info->favicon_url = std::string(); } diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch.cc index a8a366a6b7e8..eada0a8fa78d 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch.cc @@ -8,6 +8,7 @@ #include #include +#include "base/strings/string_util.h" #include "bat/ledger/internal/bat_helper.h" #include "bat/ledger/internal/ledger_impl.h" #include "bat/ledger/internal/media/twitch.h" @@ -36,8 +37,10 @@ MediaTwitch::~MediaTwitch() { } // static -std::string MediaTwitch::GetMediaIdFromParts( +std::pair MediaTwitch::GetMediaIdFromParts( const std::map& parts) { + std::string id; + std::string user_id; std::map::const_iterator iter = parts.find("event"); if (iter != parts.end() && parts.find("properties") != parts.end()) { @@ -45,9 +48,9 @@ std::string MediaTwitch::GetMediaIdFromParts( for (size_t i = 0; i < size; i++) { if (iter->second == _twitch_events[i]) { iter = parts.find("channel"); - std::string id(""); if (iter != parts.end()) { id = iter->second; + user_id = id; } iter = parts.find("vod"); if (iter != parts.end()) { @@ -56,13 +59,10 @@ std::string MediaTwitch::GetMediaIdFromParts( id += "_vod_" + braveledger_bat_helper::split(idAddition, 'v')[1]; } } - - return id; } } } - - return std::string(); + return std::make_pair(id, user_id); } // static @@ -199,11 +199,7 @@ std::string MediaTwitch::GetMediaIdFromUrl( if (url.find("twitch.tv/videos/") != std::string::npos) { mediaId = braveledger_media::ExtractData(publisher_blob, - "" - "
" - "\"",", ""); } // static @@ -251,12 +245,11 @@ std::string MediaTwitch::GetFaviconUrl( return std::string(); } - return braveledger_media::ExtractData(publisher_blob, - "
" - "
" - "\"""); + + return braveledger_media::ExtractData(wrapper, "src=\"", "\""); } // static @@ -293,7 +286,9 @@ void MediaTwitch::OnMediaActivityError(const ledger::VisitData& visit_data, void MediaTwitch::ProcessMedia(const std::map& parts, const ledger::VisitData& visit_data) { - std::string media_id = GetMediaIdFromParts(parts); + std::pair site_ids(GetMediaIdFromParts(parts)); + std::string media_id = site_ids.first; + std::string user_id = site_ids.second; if (media_id.empty()) { return; } @@ -321,6 +316,7 @@ void MediaTwitch::ProcessMedia(const std::map& parts, twitch_info, visit_data, 0, + user_id, _1, _2)); } @@ -328,36 +324,34 @@ void MediaTwitch::ProcessMedia(const std::map& parts, void MediaTwitch::ProcessActivityFromUrl(uint64_t window_id, const ledger::VisitData& visit_data, const std::string& publisher_blob) { - if (!publisher_blob.empty()) { - std::string media_id = GetMediaIdFromUrl(visit_data.url, - publisher_blob); - std::transform(media_id.begin(), - media_id.end(), - media_id.begin(), - ::tolower); - std::string media_key = GetMediaKeyFromUrl(media_id, visit_data.url); - if (!media_key.empty() && !media_id.empty()) { - ledger_->GetMediaPublisherInfo( - media_key, - std::bind(&MediaTwitch::OnMediaPublisherActivity, - this, - window_id, - visit_data, - media_key, - media_id, - publisher_blob, - _1, - _2)); - } else { - OnMediaActivityError(visit_data, window_id); - } - } else { - ledger::VisitData new_visit_data(visit_data); - new_visit_data.path = std::string(); - ledger_->GetPublisherActivityFromUrl(window_id, - new_visit_data, - std::string()); + if (publisher_blob.empty() || + publisher_blob == ledger::kIgnorePublisherBlob) { + OnMediaActivityError(visit_data, window_id); + return; + } + + std::string media_id = GetMediaIdFromUrl(visit_data.url, + publisher_blob); + + media_id = base::ToLowerASCII(media_id); + std::string media_key = GetMediaKeyFromUrl(media_id, visit_data.url); + + if (media_key.empty() || media_id.empty()) { + OnMediaActivityError(visit_data, window_id); + return; } + + ledger_->GetMediaPublisherInfo( + media_key, + std::bind(&MediaTwitch::OnMediaPublisherActivity, + this, + window_id, + visit_data, + media_key, + media_id, + publisher_blob, + _1, + _2)); } void MediaTwitch::OnMediaPublisherInfo( @@ -366,6 +360,7 @@ void MediaTwitch::OnMediaPublisherInfo( const ledger::TwitchEventInfo& twitch_info, const ledger::VisitData& visit_data, const uint64_t window_id, + const std::string& user_id, ledger::Result result, std::unique_ptr publisher_info) { if (result != ledger::Result::LEDGER_OK && @@ -375,11 +370,7 @@ void MediaTwitch::OnMediaPublisherInfo( return; } - if (!publisher_info && !publisher_info.get()) { - if (media_id.empty()) { - return; - } - + if (publisher_info) { ledger::TwitchEventInfo old_event; std::map::const_iterator iter = twitch_events.find(media_key); @@ -390,86 +381,81 @@ void MediaTwitch::OnMediaPublisherInfo( ledger::TwitchEventInfo new_event(twitch_info); new_event.status_ = GetTwitchStatus(old_event, new_event); - uint64_t real_duration = GetTwitchDuration(old_event, new_event); + const uint64_t real_duration = GetTwitchDuration(old_event, new_event); twitch_events[media_key] = new_event; - if (real_duration == 0) { - return; - } - - ledger::VisitData updated_visit_data(visit_data); - updated_visit_data.favicon_url = ""; - updated_visit_data.provider = TWITCH_MEDIA_TYPE; - + SavePublisherInfo(real_duration, + std::string(), + publisher_info->url, + publisher_info->name, + visit_data, + window_id, + publisher_info->favicon_url, + std::string(), + publisher_info->id); + return; + } + if (media_id.empty()) { + return; + } - if (media_id.find("_vod_") != std::string::npos) { - // VOD - std::vector media_props = - braveledger_bat_helper::split(media_id, MEDIA_DELIMITER); - if (media_props.empty()) { - return; - } + ledger::TwitchEventInfo old_event; + auto iter = twitch_events.find(media_key); + if (iter != twitch_events.end()) { + old_event = iter->second; + } - std::string new_id = media_props[0]; - std::string media_url = GetMediaURL(new_id); - std::string oembed_url = - (std::string)TWITCH_VOD_URL + media_props[media_props.size() - 1]; - updated_visit_data.name = new_id; - updated_visit_data.url = media_url + "/videos"; - - auto callback = std::bind( - &MediaTwitch::OnEmbedResponse, - this, - real_duration, - media_key, - media_url, - updated_visit_data, - window_id, - _1, - _2, - _3); - - const std::string url = (std::string)TWITCH_PROVIDER_URL + "?json&url=" + - ledger_->URIEncode(oembed_url); - - FetchDataFromUrl(url, callback); - return; - } + ledger::TwitchEventInfo new_event(twitch_info); + new_event.status_ = GetTwitchStatus(old_event, new_event); - // Live stream - std::string publisher_key = GetPublisherKey(media_id); - updated_visit_data.name = media_id; - updated_visit_data.url = GetMediaURL(media_id) + "/videos"; + const uint64_t real_duration = GetTwitchDuration(old_event, new_event); + twitch_events[media_key] = new_event; - ledger_->SaveMediaVisit(publisher_key, - updated_visit_data, - real_duration, - window_id); - ledger_->SetMediaPublisherInfo(media_key, publisher_key); - } else { - ledger::VisitData updated_visit_data(visit_data); - updated_visit_data.name = publisher_info->name; - updated_visit_data.url = publisher_info->url; - updated_visit_data.provider = TWITCH_MEDIA_TYPE; - updated_visit_data.favicon_url = publisher_info->favicon_url; + if (real_duration == 0) { + return; + } - ledger::TwitchEventInfo old_event; - std::map::const_iterator iter = - twitch_events.find(media_key); - if (iter != twitch_events.end()) { - old_event = iter->second; + if (media_id.find("_vod_") != std::string::npos) { + // VOD + std::vector media_props = + braveledger_bat_helper::split(media_id, MEDIA_DELIMITER); + if (media_props.empty()) { + return; } - ledger::TwitchEventInfo new_event(twitch_info); - new_event.status_ = GetTwitchStatus(old_event, new_event); - - uint64_t real_duration = GetTwitchDuration(old_event, new_event); - twitch_events[media_key] = new_event; - - std::string id = publisher_info->id; - ledger_->SaveMediaVisit(id, updated_visit_data, real_duration, window_id); + std::string media_url = GetMediaURL(user_id); + std::string oembed_url = + (std::string)TWITCH_VOD_URL + media_props[media_props.size() - 1]; + + auto callback = std::bind(&MediaTwitch::OnEmbedResponse, + this, + real_duration, + media_key, + media_url, + visit_data, + window_id, + user_id, + _1, + _2, + _3); + + const std::string url = (std::string)TWITCH_PROVIDER_URL + "?json&url=" + + ledger_->URIEncode(oembed_url); + + FetchDataFromUrl(url, callback); + return; } + + // Live stream + SavePublisherInfo(real_duration, + media_key, + GetMediaURL(media_id), + media_id, + visit_data, + window_id, + std::string(), + media_id); } void MediaTwitch::FetchDataFromUrl( @@ -489,6 +475,7 @@ void MediaTwitch::OnEmbedResponse( const std::string& media_url, const ledger::VisitData& visit_data, const uint64_t window_id, + const std::string& user_id, int response_status_code, const std::string& response, const std::map& headers) { @@ -506,18 +493,14 @@ void MediaTwitch::OnEmbedResponse( std::string author_name; braveledger_bat_helper::getJSONValue("author_name", response, &author_name); - std::string twitchMediaID = visit_data.name; - std::string id = (std::string)TWITCH_MEDIA_TYPE + "#author:" + twitchMediaID; - - ledger::VisitData updated_visit_data(visit_data); - updated_visit_data.name = author_name; - - if (fav_icon.length() > 0) { - updated_visit_data.favicon_url = fav_icon; - } - - ledger_->SaveMediaVisit(id, updated_visit_data, duration, window_id); - ledger_->SetMediaPublisherInfo(media_key, id); + SavePublisherInfo(duration, + media_key, + media_url, + author_name, + visit_data, + window_id, + fav_icon, + user_id); } void MediaTwitch::OnMediaPublisherActivity( @@ -551,6 +534,7 @@ void MediaTwitch::OnMediaPublisherActivity( if (info->verified && info->favicon_url.empty()) { std::string publisher_name; std::string publisher_favicon_url; + UpdatePublisherData(&publisher_name, &publisher_favicon_url, publisher_blob); @@ -558,7 +542,7 @@ void MediaTwitch::OnMediaPublisherActivity( if (!publisher_favicon_url.empty()) { SavePublisherInfo(0, media_key, - visit_data.url, + GetMediaURL(media_id), publisher_name, visit_data, window_id, @@ -589,13 +573,18 @@ void MediaTwitch::OnPublisherInfo( if (!publisher_info || result == ledger::Result::NOT_FOUND) { std::string publisher_name; std::string publisher_favicon_url; + UpdatePublisherData(&publisher_name, &publisher_favicon_url, publisher_blob); + if (publisher_name.empty()) { + publisher_name = media_id; + } + SavePublisherInfo(0, media_key, - visit_data.url, + GetMediaURL(media_id), publisher_name, visit_data, window_id, @@ -615,17 +604,20 @@ void MediaTwitch::SavePublisherInfo(const uint64_t duration, const ledger::VisitData& visit_data, const uint64_t window_id, const std::string& fav_icon, - const std::string& channel_id) { - if (channel_id.empty()) { + const std::string& channel_id, + const std::string& publisher_key) { + if (channel_id.empty() && publisher_key.empty()) { BLOG(ledger_, ledger::LogLevel::LOG_ERROR) << "author id is missing for: " << media_key; return; } - std::string publisher_id = GetPublisherKey(channel_id); - std::string url = publisher_url + "/videos"; + std::string key = publisher_key; + if (key.empty()) { + key = GetPublisherKey(channel_id); + } - if (publisher_id.empty()) { + if (key.empty()) { BLOG(ledger_, ledger::LogLevel::LOG_ERROR) << "Publisher id is missing for: " << media_key; return; @@ -639,14 +631,14 @@ void MediaTwitch::SavePublisherInfo(const uint64_t duration, updated_visit_data.provider = TWITCH_MEDIA_TYPE; updated_visit_data.name = publisher_name; - updated_visit_data.url = url; + updated_visit_data.url = publisher_url + "/videos"; - ledger_->SaveMediaVisit(publisher_id, + ledger_->SaveMediaVisit(key, updated_visit_data, duration, window_id); if (!media_key.empty()) { - ledger_->SetMediaPublisherInfo(media_key, publisher_id); + ledger_->SetMediaPublisherInfo(media_key, key); } } diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch.h b/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch.h index 2d1bf9a1b6b0..2fb02c3d9307 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch.h +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "base/gtest_prod_util.h" #include "bat/ledger/ledger.h" @@ -41,7 +42,7 @@ class MediaTwitch : public ledger::LedgerCallbackHandler { const std::string& referrer); private: - static std::string GetMediaIdFromParts( + static std::pair GetMediaIdFromParts( const std::map& parts); static std::string GetMediaURL(const std::string& mediaId); @@ -77,6 +78,7 @@ class MediaTwitch : public ledger::LedgerCallbackHandler { const ledger::TwitchEventInfo& twitch_info, const ledger::VisitData& visit_data, const uint64_t window_id, + const std::string& user_id, ledger::Result result, std::unique_ptr publisher_info); @@ -90,6 +92,7 @@ class MediaTwitch : public ledger::LedgerCallbackHandler { const std::string& media_url, const ledger::VisitData& visit_data, const uint64_t window_id, + const std::string& user_id, int response_status_code, const std::string& response, const std::map& headers); @@ -119,7 +122,8 @@ class MediaTwitch : public ledger::LedgerCallbackHandler { const ledger::VisitData& visit_data, const uint64_t window_id, const std::string& fav_icon, - const std::string& channel_id); + const std::string& channel_id, + const std::string& publisher_key = ""); bat_ledger::LedgerImpl* ledger_; // NOT OWNED std::map twitch_events; diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch_unittest.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch_unittest.cc index 06f1283da2f9..b8c22a3d7fa2 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch_unittest.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch_unittest.cc @@ -15,85 +15,128 @@ class MediaTwitchTest : public testing::Test { }; const char profile_html[] = + "
" "
\"dakotaz\"
dakotaz
" - "
Verified User
"; + "class=\"tw-border-radius-rounded tw-overflow-hidden\">\"bravesoftware\"" + "
bravesoftware
" + "
Videos
0
"; TEST(MediaTwitchTest, GetMediaIdFromParts) { + std::string media_id; + std::string user_id; // empty - std::string result = MediaTwitch::GetMediaIdFromParts({}); - ASSERT_EQ(result, ""); + std::pair result = + MediaTwitch::GetMediaIdFromParts({}); + media_id = result.first; + user_id = result.second; + EXPECT_TRUE(user_id.empty()); + ASSERT_TRUE(media_id.empty()); // event is not on the list result = MediaTwitch::GetMediaIdFromParts({ {"event", "test"}, {"properties", ""} }); - ASSERT_EQ(result, ""); + media_id = result.first; + user_id = result.second; + EXPECT_TRUE(user_id.empty()); + ASSERT_TRUE(media_id.empty()); // properties are missing result = MediaTwitch::GetMediaIdFromParts({ {"event", "minute-watched"} }); - ASSERT_EQ(result, ""); + media_id = result.first; + user_id = result.second; + EXPECT_TRUE(user_id.empty()); + ASSERT_TRUE(media_id.empty()); // channel is missing result = MediaTwitch::GetMediaIdFromParts({ {"event", "minute-watched"}, {"properties", ""} }); - ASSERT_EQ(result, ""); + media_id = result.first; + user_id = result.second; + EXPECT_TRUE(user_id.empty()); + ASSERT_TRUE(media_id.empty()); // channel is provided result = MediaTwitch::GetMediaIdFromParts({ {"event", "minute-watched"}, {"properties", ""}, - {"channel", "dakotaz"} + {"channel", "bravesoftware"} }); - ASSERT_EQ(result, "dakotaz"); + media_id = result.first; + user_id = result.second; + EXPECT_EQ(user_id, "bravesoftware"); + ASSERT_EQ(media_id, "bravesoftware"); // vod is missing leading v result = MediaTwitch::GetMediaIdFromParts({ {"event", "minute-watched"}, {"properties", ""}, - {"channel", "dakotaz"}, + {"channel", "bravesoftware"}, {"vod", "123312312"} }); - ASSERT_EQ(result, "dakotaz"); + media_id = result.first; + user_id = result.second; + EXPECT_EQ(user_id, "bravesoftware"); + ASSERT_EQ(media_id, "bravesoftware"); // vod is provided result = MediaTwitch::GetMediaIdFromParts({ {"event", "minute-watched"}, {"properties", ""}, - {"channel", "dakotaz"}, + {"channel", "bravesoftware"}, + {"vod", "v123312312"} + }); + media_id = result.first; + user_id = result.second; + EXPECT_EQ(user_id, "bravesoftware"); + ASSERT_EQ(media_id, "bravesoftware_vod_123312312"); + + // live stream username has '_' + result = MediaTwitch::GetMediaIdFromParts({ + {"event", "minute-watched"}, + {"properties", ""}, + {"channel", "anatomyz_2"} + }); + media_id = result.first; + user_id = result.second; + EXPECT_EQ(user_id, "anatomyz_2"); + ASSERT_EQ(media_id, "anatomyz_2"); + + // vod has '_' + result = MediaTwitch::GetMediaIdFromParts({ + {"event", "minute-watched"}, + {"properties", ""}, + {"channel", "anatomyz_2"}, {"vod", "v123312312"} }); - ASSERT_EQ(result, "dakotaz_vod_123312312"); + media_id = result.first; + user_id = result.second; + EXPECT_EQ(user_id, "anatomyz_2"); + ASSERT_EQ(media_id, "anatomyz_2_vod_123312312"); } TEST(MediaTwitchTest, GetMediaURL) { @@ -102,8 +145,8 @@ TEST(MediaTwitchTest, GetMediaURL) { ASSERT_EQ(result, ""); // all ok - result = MediaTwitch::GetMediaURL("dakotaz"); - ASSERT_EQ(result, "https://www.twitch.tv/dakotaz"); + result = MediaTwitch::GetMediaURL("bravesoftware"); + ASSERT_EQ(result, "https://www.twitch.tv/bravesoftware"); } TEST(MediaTwitchTest, GetTwitchStatus) { @@ -141,7 +184,27 @@ TEST(MediaTwitchTest, GetTwitchStatus) { ASSERT_EQ(result, "playing"); } -TEST(MediaTwitchTest, GetLinkType ) { +TEST(MediaTwitchTest, GetMediaIdFromUrl) { + // for live stream + std::string result = MediaTwitch::GetMediaIdFromUrl( + "https://www.twitch.tv/bravesoftware", profile_html); + + ASSERT_EQ(result, "bravesoftware"); + + // longer url + result = MediaTwitch::GetMediaIdFromUrl( + "https://www.twitch.tv/bravesoftware/clips", profile_html); + + ASSERT_EQ(result, "bravesoftware"); + + // video + result = MediaTwitch::GetMediaIdFromUrl( + "https://www.twitch.tv/videos/11111", profile_html); + + ASSERT_EQ(result, "bravesoftware"); +} + +TEST(MediaTwitchTest, GetLinkType) { const std::string url("https://k8923479-sub.cdn.ttvnw.net/v1/segment/"); // url is not correct @@ -180,13 +243,13 @@ TEST(MediaTwitchTest, GetMediaKeyFromUrl) { // get vod id result = MediaTwitch::GetMediaKeyFromUrl( - "dakotaz", + "bravesoftware", "https://www.twitch.tv/videos/411403500"); - ASSERT_EQ(result, "twitch_dakotaz_vod_411403500"); + ASSERT_EQ(result, "twitch_bravesoftware_vod_411403500"); // regular id - result = MediaTwitch::GetMediaKeyFromUrl("dakotaz", ""); - ASSERT_EQ(result, "twitch_dakotaz"); + result = MediaTwitch::GetMediaKeyFromUrl("bravesoftware", ""); + ASSERT_EQ(result, "twitch_bravesoftware"); } TEST(MediaTwitchTest, GetPublisherKey) { @@ -206,7 +269,7 @@ TEST(MediaTwitchTest, GetPublisherName) { // all ok result = MediaTwitch::GetPublisherName(profile_html); - ASSERT_EQ(result, "dakotaz"); + ASSERT_EQ(result, "bravesoftware"); } TEST(MediaTwitchTest, GetFaviconUrl) { @@ -215,14 +278,14 @@ TEST(MediaTwitchTest, GetFaviconUrl) { ASSERT_EQ(result, ""); // blob is not correct - result = MediaTwitch::GetFaviconUrl("dfsfsdfsdfds", "dakotaz"); + result = MediaTwitch::GetFaviconUrl("dfsfsdfsdfds", "bravesoftware"); ASSERT_EQ(result, ""); // all ok - result = MediaTwitch::GetFaviconUrl(profile_html, "dakotaz"); + result = MediaTwitch::GetFaviconUrl(profile_html, "bravesoftware"); ASSERT_EQ(result, - "https://static-cdn.jtvnw.net/jtv_user_pictures/473aea0f-a724-498" - "f-b7f1-e344f806ba8a-profile_image-70x70.png"); + "https://static-cdn.jtvnw.net/user-default-pictures/" + "0ecbb6c3-fecb-4016-8115-aa467b7c36ed-profile_image-70x70.jpg"); } TEST(MediaTwitchTest, UpdatePublisherData) { @@ -243,10 +306,10 @@ TEST(MediaTwitchTest, UpdatePublisherData) { &favicon_url, profile_html); - ASSERT_EQ(name, "dakotaz"); + ASSERT_EQ(name, "bravesoftware"); ASSERT_EQ(favicon_url, - "https://static-cdn.jtvnw.net/jtv_user_pictures/473aea0f-a724-498" - "f-b7f1-e344f806ba8a-profile_image-70x70.png"); + "https://static-cdn.jtvnw.net/user-default-pictures/" + "0ecbb6c3-fecb-4016-8115-aa467b7c36ed-profile_image-70x70.jpg"); } } // namespace braveledger_media