Skip to content

Commit

Permalink
Fix twitter publisher detection
Browse files Browse the repository at this point in the history
  • Loading branch information
zenparsing committed Sep 3, 2024
1 parent 78cc508 commit 1968990
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 2 deletions.
119 changes: 119 additions & 0 deletions scripts/brave_rewards/publisher/twitter/detector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
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))
}
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 === screenName) {
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: 6000
})
document.dispatchEvent(new CustomEvent('rewards-publisher-detected', {
detail: { user }
}))
})()
`
22 changes: 20 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,24 @@ const sendForExcludedPage = () => {
})
}

const injectDetectionScript = () => {
return new Promise<any>((resolve) => {
const script = document.createElement('script')
script.textContent = detector.scriptText
document.head.appendChild(script)
const listener = (event: CustomEvent) => {
const { user } = event.detail
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 +101,7 @@ const sendForStandardPage = (url: URL) => {
return
}

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

0 comments on commit 1968990

Please sign in to comment.