Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix twitter publisher detection #130

Merged
merged 1 commit into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions scripts/brave_rewards/publisher/twitter/detector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
export const scriptText = `

(async function() {

async function pollFor(fn, opts) {
const startTime = Date.now()
while (Date.now() - startTime < opts.timeout) {
const result = fn()
if (result) {
return result
}
await new Promise((resolve) => setTimeout(resolve, opts.interval))
}
console.log('Polling timeout occurred')
return null
}

function getElementStore(elem) {
if (!elem) {
return null
}
for (const name of Object.getOwnPropertyNames(elem)) {
if (name.startsWith('__reactProps$')) {
let store = null
try { store = elem[name].children.props.store }
catch {}
if (store && typeof store.getState === 'function') {
return store
}
}
}
return null
}

function findStore(elem, depth = 0) {
if (!elem) {
return null
}
let store = getElementStore(elem)
if (store) {
return store
}
if (depth === 4) {
return null
}
for (let child of elem.children) {
store = findStore(child, depth + 1)
if (store) {
return store
}
}
return null
}

let stateStore = null

function getStore() {
if (!stateStore) {
stateStore = findStore(document.getElementById('react-root'))
}
return stateStore
}

function getUserFromState(state, screenName) {
const userEntities = state.entities.users.entities
for (let [key, value] of Object.entries(userEntities)) {
if (value.screen_name.toLocaleLowerCase() ===
screenName.toLocaleLowerCase()) {
return {
siteID: key,
imageURL: String(value.profile_image_url_https || '')
}
}
}
return null
}

function getUserByScreenName(screenName) {
const store = getStore()
if (!store) {
return null
}
try {
return getUserFromState(store.getState(), screenName)
} catch (e) {
console.error('Error attempting to get user state', e)
}
return null
}

function getScreenNameFromPath(path) {
let match = path.match(/^\\/([^\\/]+)(\\/|\\/status\\/[\\s\\S]+)?$/)
if (match) {
return match[1]
}
return null
}

function getUserFromPath(path) {
const screenName = getScreenNameFromPath(path)
if (screenName) {
const user = getUserByScreenName(screenName)
if (user) {
return user
}
}
return null
}

const user = await pollFor(() => getUserFromPath(location.pathname), {
interval: 600,
timeout: 8000
})

document.dispatchEvent(new CustomEvent('rewards-publisher-detected', {
detail: { user }
}))

})()

`
26 changes: 24 additions & 2 deletions scripts/brave_rewards/publisher/twitter/publisherInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getPort } from '../common/messaging'

import * as commonUtils from '../common/utils'

import * as api from './api'
import * as detector from './detector'
import * as types from './types'
import * as utils from './utils'

Expand Down Expand Up @@ -71,6 +71,28 @@ const sendForExcludedPage = () => {
})
}

const injectDetectionScript = () => {
return new Promise<any>((resolve, reject) => {
const script = document.createElement('script')
script.textContent = detector.scriptText
document.head.appendChild(script)
const listener = (event: CustomEvent) => {
const { user } = event.detail
if (!user) {
reject(new Error('Unable to find user data in state store'))
return
}
resolve({
id_str: user.siteID,
profile_image_url_https: user.imageURL
})
document.removeEventListener('rewards-publisher-detected', listener)
}
document.addEventListener('rewards-publisher-detected', listener)
document.head.removeChild(script)
})
}

const sendForStandardPage = (url: URL) => {
const screenName = utils.getScreenNameFromUrl(url)
if (!screenName) {
Expand All @@ -83,7 +105,7 @@ const sendForStandardPage = (url: URL) => {
return
}

api.getUserDetails(screenName)
injectDetectionScript()
.then((userDetails: any) => {
userCache.put(screenName, userDetails)
savePublisherVisit(screenName, userDetails)
Expand Down
Loading