Skip to content

Commit

Permalink
Merge branch 'hotfix/1.13.2' into released
Browse files Browse the repository at this point in the history
  • Loading branch information
guanbinrui committed Aug 4, 2020
2 parents 5185b25 + 4495b02 commit 5304c3d
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 32 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "maskbook",
"version": "1.13.1",
"version": "1.13.2",
"private": true,
"license": "AGPL-3.0-or-later",
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@
"set_up_consent_data_collection_hint": "Maskbook will collect some data when you use it, but the developers of Maskbook have no access to them. The collected data are stored locally, except for the data which are necessary for enabling your friends to decrypt the posts you shared.",
"set_up_consent_data_collection_privacy_policy_1": "I agree with the ",
"set_up_consent_data_collection_privacy_policy_2": "privacy policy",
"set_up_consent_data_collection_privacy_policy_3": ".",
"set_up_create_persona": "Getting Started",
"set_up_create_persona_hint": "You may connect social network profiles to your persona in the next step.",
"set_up_connect": "Connect a Social Network Profile for \"{{name}}\"",
Expand Down
1 change: 1 addition & 0 deletions src/_locales/ja/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@
"set_up_consent_data_collection_hint": "Maskbookは利用時にデータを収集しますが、Maskbookの開発者はそれらのデータにアクセスすることはできません。収集されたデータは、友達がシェアした投稿を解読できるようにするために必要なデータを除いて、ローカルに保存されます。",
"set_up_consent_data_collection_privacy_policy_1": "同意します",
"set_up_consent_data_collection_privacy_policy_2": "プライバシーポリシー",
"set_up_consent_data_collection_privacy_policy_3": "",
"set_up_create_persona": "はじめよう",
"set_up_create_persona_hint": "次のステップでは、ソーシャルネットワークのアカウントを人格アカウントに接続することができます。",
"set_up_connect": "{{name}}に接続する",
Expand Down
1 change: 1 addition & 0 deletions src/_locales/zh/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@
"set_up_consent_data_collection_hint": "Maskbook 在使用時會收集一些數據(在隱私政策中列出),但是 Maskbook 的開發人員無法訪問它們。 除了使您的朋友解密您共享的帖子所需的數據外,收集的數據存儲在本地。",
"set_up_consent_data_collection_privacy_policy_1": "我同意",
"set_up_consent_data_collection_privacy_policy_2": "隱私政策",
"set_up_consent_data_collection_privacy_policy_3": "",
"set_up_create_persona": "開始",
"set_up_create_persona_hint": "您可以在下一步中將社交網絡個人資料連接到您的角色。",
"set_up_connect": "連接「{{name}}」的社交網絡個人資料",
Expand Down
2 changes: 1 addition & 1 deletion src/components/InjectedComponents/PostDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ export function PostDialogUI(props: PostDialogUIProps) {
</SelectRecipientsUI>
</Box>
{/* This feature is not ready for mobile version */}
{webpackEnv.genericTarget === 'browser' ? (
{webpackEnv.genericTarget !== 'facebookApp' ? (
<>
<Typography style={{ marginBottom: 10 }}>
{t('post_dialog__more_options_title')}
Expand Down
8 changes: 5 additions & 3 deletions src/extension/options-page/DashboardDialogs/Wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,14 @@ export function DashboardWalletImportDialog(props: WrappedDialogProps<object>) {
passphrase: '',
})
return Services.Plugin.invokePlugin('maskbook.wallet', 'recoverWalletFromPrivateKey', privKey).then(
({ address }) =>
Services.Plugin.invokePlugin('maskbook.wallet', 'importNewWallet', {
({ address, privateKeyValid }) => {
if (!privateKeyValid) throw new Error(t('import_failed'))
return Services.Plugin.invokePlugin('maskbook.wallet', 'importNewWallet', {
name,
address,
_private_key_: privKey,
}),
})
},
)
},
[state[0], name, mnemonic, privKey],
Expand Down
1 change: 1 addition & 0 deletions src/extension/options-page/DashboardRouters/Setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export function ConsentDataCollection() {
rel="noopener noreferrer">
{t('set_up_consent_data_collection_privacy_policy_2')}
</MuiLink>
{t('set_up_consent_data_collection_privacy_policy_3')}
</>
}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Maskbook",
"version": "1.13.1",
"version": "1.13.2",
"manifest_version": 2,
"permissions": ["storage", "downloads", "webNavigation", "activeTab"],
"optional_permissions": ["<all_urls>", "notifications"],
Expand Down
22 changes: 15 additions & 7 deletions src/plugins/Wallet/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ export async function getManagedWallets(): Promise<{
.map(WalletRecordOutDB)
.filter((x): x is ManagedWalletRecord => x.type !== 'exotic')
.map(async (record) => ({ ...record, privateKey: await makePrivateKey(record) }))
const recordWithKeys = await Promise.all(records)
return recordWithKeys.sort((a, b) => {
return (await Promise.all(records)).sort((a, b) => {
if (a._wallet_is_default) return -1
if (b._wallet_is_default) return 1
if (a.updatedAt > b.updatedAt) return -1
Expand All @@ -68,10 +67,10 @@ export async function getManagedWallets(): Promise<{
return 0
})
async function makePrivateKey(record: ManagedWalletRecord) {
const recover = record._private_key_
const { privateKey } = record._private_key_
? await recoverWalletFromPrivateKey(record._private_key_)
: await recoverWallet(record.mnemonic, record.passphrase)
return `0x${buf2hex(recover.privateKey)}`
return `0x${buf2hex(privateKey)}`
}
}
function makeTokens() {
Expand Down Expand Up @@ -174,7 +173,10 @@ export async function importNewWallet(
PluginMessageCenter.emit('maskbook.wallets.update', undefined)
async function getWalletAddress() {
if (rec.address) return rec.address
if (rec._private_key_) return (await recoverWalletFromPrivateKey(rec._private_key_)).address
if (rec._private_key_) {
const recover = await recoverWalletFromPrivateKey(rec._private_key_)
return recover.privateKeyValid ? recover.address : ''
}
return (await recoverWallet(mnemonic, passphrase)).address
}
}
Expand Down Expand Up @@ -213,18 +215,24 @@ export async function recoverWallet(mnemonic: string[], password: string) {
const walletPublicKey = wallet.publicKey
const walletPrivateKey = wallet.privateKey!
const address = EthereumAddress.from(walletPublicKey).address
return { address, privateKey: walletPrivateKey, privateKeyInHex: `0x${buf2hex(walletPrivateKey)}`, mnemonic }
return {
address,
privateKey: walletPrivateKey,
privateKeyValid: true,
privateKeyInHex: `0x${buf2hex(walletPrivateKey)}`,
mnemonic,
}
}

export async function recoverWalletFromPrivateKey(privateKey: string) {
const ec = new EC('secp256k1')
const privateKey_ = privateKey.replace(/^0x/, '') // strip 0x
if (!privateKeyVerify(privateKey_)) throw new Error('cannot import invalid private key')
const key = ec.keyFromPrivate(privateKey_)
const address = EthereumAddress.from(key.getPublic(false, 'array') as any).address
return {
address,
privateKey: hex2buf(privateKey_),
privateKeyValid: privateKeyVerify(privateKey_),
privateKeyInHex: privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`,
mnemonic: [],
}
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/Wallet/web3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ export const resetWallet = async () => {

const { wallets } = await Services.Plugin.invokePlugin('maskbook.wallet', 'getManagedWallets')
for await (const { mnemonic, passphrase, privateKey } of wallets) {
const { privateKeyInHex } =
const { privateKeyValid, privateKeyInHex } =
mnemonic && passphrase
? await Services.Plugin.invokePlugin('maskbook.wallet', 'recoverWallet', mnemonic, passphrase)
: await Services.Plugin.invokePlugin('maskbook.wallet', 'recoverWalletFromPrivateKey', privateKey)
web3.eth.accounts.wallet.add(privateKeyInHex)
if (privateKeyValid) web3.eth.accounts.wallet.add(privateKeyInHex)
}
}

Expand Down
11 changes: 5 additions & 6 deletions src/social-network-provider/twitter.com/ui/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import type {
import { PostInfo } from '../../../social-network/PostInfo'
import { deconstructPayload } from '../../../utils/type-transform/Payload'
import { instanceOfTwitterUI } from './index'
import { bioCardParser, postParser, postIdParser, postImagesParser } from '../utils/fetch'
import { isNil } from 'lodash-es'
import { bioCardParser, postParser, postIdParser, postImagesParser, postNameParser } from '../utils/fetch'
import { isNil, noop } from 'lodash-es'
import Services from '../../../extension/service'
import { twitterUrl } from '../utils/url'
import { untilElementAvailable } from '../../../utils/dom'
Expand Down Expand Up @@ -171,12 +171,11 @@ function collectPostInfo(tweetNode: HTMLDivElement | null, info: PostInfo, self:
if (!tweetNode) return
const { pid, content, handle, name, avatar } = postParser(tweetNode)
if (!pid) return

const postBy = new ProfileIdentifier(self.networkIdentifier, handle)
info.postID.value = pid
info.postContent.value = content
if (!info.postBy.value.equals(postBy)) {
info.postBy.value = postBy
}
if (!info.postBy.value.equals(postBy)) info.postBy.value = postBy
info.nickname.value = name
info.avatarURL.value = avatar || null

Expand All @@ -187,5 +186,5 @@ function collectPostInfo(tweetNode: HTMLDivElement | null, info: PostInfo, self:
.then((urls) => {
for (const url of urls) info.postMetadataImages.add(url)
})
.catch(() => {})
.catch(noop)
}
40 changes: 29 additions & 11 deletions src/social-network-provider/twitter.com/utils/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ const parseId = (t: string) => {
return regexMatch(t, /status\/(\d+)/, 1)!
}

const serializeToText = (node: ChildNode): string => {
const snippets: string[] = []
for (const childNode of Array.from(node.childNodes)) {
if (childNode.nodeType === Node.TEXT_NODE) {
if (childNode.nodeValue) snippets.push(childNode.nodeValue)
} else if (childNode.nodeName === 'IMG') {
const img = childNode as HTMLImageElement
const matched = (img.getAttribute('src') ?? '').match(/emoji\/v2\/svg\/([\d\w]+)\.svg/) ?? []
if (matched[1]) snippets.push(String.fromCodePoint(Number.parseInt(`0x${matched[1]}`)))
} else if (childNode.childNodes.length) snippets.push(serializeToText(childNode))
}
return snippets.join('')
}

const isMobilePost = (node: HTMLElement) => {
return node.classList.contains('tweet') ?? node.classList.contains('main-tweet')
}
Expand Down Expand Up @@ -98,19 +112,27 @@ export const postNameParser = (node: HTMLElement) => {
return parseNameArea(notNullable(node.querySelector<HTMLTableCellElement>('.user-info')).innerText)
} else {
const tweetElement = node.querySelector<HTMLElement>('[data-testid="tweet"]') ?? node
const nameInUniqueAnchorTweet =
tweetElement.children[1]?.querySelector<HTMLAnchorElement>('a[data-focusable="true"]')?.innerText ?? ''

// type 1:
// normal tweet
const anchorElement = tweetElement.children[1]?.querySelector<HTMLAnchorElement>('a[data-focusable="true"]')
const nameInUniqueAnchorTweet = anchorElement ? serializeToText(anchorElement) : ''

// type 2:
const nameInDoubleAnchorsTweet = Array.from(
tweetElement.children[1]?.querySelectorAll<HTMLAnchorElement>('a[data-focusable="true"]') ?? [],
)
.map((a) => a.textContent)
.map(serializeToText)
.join('')
const nameInQuoteTweet = nthChild(tweetElement, 0, 0, 0)?.innerText

// type 3:
// parse name in quoted tweet
const nameElementInQuoted = nthChild(tweetElement, 0, 0, 0)
const nameInQuoteTweet = nameElementInQuoted ? serializeToText(nameElementInQuoted) : ''
return (
[nameInUniqueAnchorTweet, nameInDoubleAnchorsTweet, nameInQuoteTweet]
.filter(Boolean)
.map((n) => parseNameArea(n!))
.map(parseNameArea)
.find((r) => r.name && r.handle) ?? {
name: '',
handle: '',
Expand Down Expand Up @@ -138,12 +160,8 @@ export const postContentParser = (node: HTMLElement) => {
}
return Array.from(containerNode.childNodes)
.map((node) => {
if (node.nodeType === Node.TEXT_NODE) {
return node.nodeValue
}
if (node.nodeName === 'A') {
return (node as HTMLAnchorElement).getAttribute('title')
}
if (node.nodeType === Node.TEXT_NODE) return node.nodeValue
if (node.nodeName === 'A') return (node as HTMLAnchorElement).getAttribute('title')
return ''
})
.join(',')
Expand Down

0 comments on commit 5304c3d

Please sign in to comment.