Skip to content

Commit

Permalink
Proposes alternative tipping logic
Browse files Browse the repository at this point in the history
Addresses #100
  • Loading branch information
jonathansampson committed Sep 27, 2023
1 parent f0079ae commit 9f73f12
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 79 deletions.
137 changes: 58 additions & 79 deletions scripts/brave_rewards/publisher/twitter/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,101 +2,80 @@
* 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 = async (tweetId: string): Promise<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 = async (screenName: string): Promise<types.UserDetails> => {
if (!screenName) {
return Promise.reject(new Error('Invalid parameters'))
throw new Error('Invalid parameters')
}

const url =
`https://api.twitter.com/1.1/users/show.json?screen_name=${screenName}`
return sendAPIRequest('GetUserDetails', url)
let user: types.UserEntity | null = null
const users = getEntities().users.entities as types.UserEntities

for (const value of Object.values(users)) {
const nameLowered = value.screen_name.toLowerCase()
const screenNameLowered = screenName.toLowerCase()
if (nameLowered === screenNameLowered) {
user = value
break
}
}

if (!user) {
throw new Error('User not found')
}

return {
id_str: user.id_str,
profile_image_url_https: user.profile_image_url_https
}
}
26 changes: 26 additions & 0 deletions scripts/brave_rewards/publisher/twitter/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,29 @@ 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
}

export type UserEntity = {
screen_name: string
id_str: string
profile_image_url_https: string
}

export type UserEntities = {
[key: string]: UserEntity
}

0 comments on commit 9f73f12

Please sign in to comment.