From a66921a6bc99f4aa0479d7b6a1bed821c7cef68f Mon Sep 17 00:00:00 2001 From: Sampson Date: Tue, 26 Sep 2023 19:28:14 -0500 Subject: [PATCH] Proposes alternative tipping logic Addresses #100 --- .../brave_rewards/publisher/twitter/api.ts | 133 +++++++----------- .../brave_rewards/publisher/twitter/types.ts | 16 +++ 2 files changed, 70 insertions(+), 79 deletions(-) diff --git a/scripts/brave_rewards/publisher/twitter/api.ts b/scripts/brave_rewards/publisher/twitter/api.ts index e01bdc2..d880be1 100644 --- a/scripts/brave_rewards/publisher/twitter/api.ts +++ b/scripts/brave_rewards/publisher/twitter/api.ts @@ -2,101 +2,76 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { getPort } from '../common/messaging' -import { getAuthHeaders, hasRequiredAuthHeaders } from './auth' - import * as types from './types' -let lastRequestTime = 0 - -const sendAPIRequest = (name: string, url: string) => { - return new Promise((resolve, reject) => { - if (!name || !url) { - reject(new Error('Invalid parameters')) - return - } - - if (!hasRequiredAuthHeaders()) { - reject(new Error('Missing auth headers')) - return - } - - const port = getPort() - if (!port) { - reject(new Error('Invalid port')) - return - } +let cachedXStore: any | null = null - if ((lastRequestTime !== 0) && (Date.now() - lastRequestTime < 3000)) { - reject(new Error('Ignoring API request due to network throttle')) - return - } +const getXState = () => { + if (cachedXStore) { + return cachedXStore.getState() + } - lastRequestTime = Date.now() + const hostNode = document.querySelector('#react-root > div > div') + const descriptors = Object.getOwnPropertyDescriptors(hostNode || {}) - const authHeaders = getAuthHeaders() - port.postMessage({ - type: 'OnAPIRequest', - mediaType: types.mediaType, - data: { - name, - url, - init: { - credentials: 'include', - headers: { - ...authHeaders - }, - referrerPolicy: 'no-referrer-when-downgrade', - method: 'GET', - redirect: 'follow' + if (hostNode) { + for (const propertyName in descriptors) { + if (propertyName.startsWith('__reactProps$')) { + const reactProps = hostNode[propertyName] + const store = reactProps?.children?.props?.store + if (store) { + cachedXStore = store + return cachedXStore.getState() } } - }) + } + } - port.onMessage.addListener(function onMessageListener (msg: any) { - if (!port) { - reject(new Error('Invalid port')) - return - } - if (!msg || !msg.data) { - port.onMessage.removeListener(onMessageListener) - reject(new Error('Invalid message')) - return - } - if (msg.type === 'OnAPIResponse') { - if (!msg.data.name || (!msg.data.response && !msg.data.error)) { - port.onMessage.removeListener(onMessageListener) - reject(new Error('Invalid message')) - return - } - if (msg.data.name === name) { - port.onMessage.removeListener(onMessageListener) - if (msg.data.error) { - reject(new Error(msg.data.error)) - return - } - resolve(msg.data.response) - } - } - }) - }) + throw new Error('XStore initialization failed') } -export const getTweetDetails = async (tweetId: string) => { +const getEntities = () => getXState().entities + +export const getTweetDetails = (tweetId: string): types.TweetDetails => { if (!tweetId) { - return Promise.reject(new Error('Invalid parameters')) + throw new Error('Invalid parameters') } - const url = `https://api.twitter.com/1.1/statuses/show.json?id=${tweetId}` - return sendAPIRequest('GetTweetDetails', url) + const entities = getEntities() + const tweet = entities.tweets.entities[tweetId] + const tweetUser = entities.users.entities[tweet.user] + + return { + user: { + id_str: tweetUser.id_str, + screen_name: tweetUser.screen_name, + name: tweetUser.name, + profile_image_url_https: tweetUser.profile_image_url_https + }, + created_at: tweet.created_at, + text: tweet.text + } } -export const getUserDetails = async (screenName: string) => { +export const getUserDetails = (screenName: string): types.UserDetails => { if (!screenName) { - return Promise.reject(new Error('Invalid parameters')) + throw new Error('Invalid parameters') + } + + let user + const users = getEntities().users.entities + + for (const value of Object.values(users)) { + const nameLowered = value.screen_name.toLowerCase() + const screenNameLowered = screenName.toLowerCase() + if (nameLowered === screenNameLowered) { + user = value + break + } } - const url = - `https://api.twitter.com/1.1/users/show.json?screen_name=${screenName}` - return sendAPIRequest('GetUserDetails', url) + return { + id_str: user.id_str, + profile_image_url_https: user.profile_image_url_https + } } diff --git a/scripts/brave_rewards/publisher/twitter/types.ts b/scripts/brave_rewards/publisher/twitter/types.ts index 5eac9a7..079f898 100644 --- a/scripts/brave_rewards/publisher/twitter/types.ts +++ b/scripts/brave_rewards/publisher/twitter/types.ts @@ -7,3 +7,19 @@ export const mediaDomain = 'twitter.com' export const sendHeadersUrls = ['https://api.twitter.com/1.1/*'] export const sendHeadersExtra = ['requestHeaders', 'extraHeaders'] + +export type TweetDetails = { + user: { + id_str: string + screen_name: string + name: string + profile_image_url_https: string + } + created_at: string + text: string +} + +export type UserDetails = { + id_str: string + profile_image_url_https: string +}