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

Properly handle blacklisted claims. #7665

Merged
merged 2 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
37 changes: 37 additions & 0 deletions flow-typed/Claim.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,49 @@ declare type PurchaseReceipt = {
type: 'purchase',
};

declare type ClaimErrorCensor = {
address: string,
amount: string,
canonical_url: string,
claim_id: string,
claim_op: string,
confirmations: number,
has_signing_key: boolean,
height: number,
meta: {
activation_height: number,
claims_in_channel: number,
creation_height: number,
creation_timestamp: number,
effective_amount: string,
expiration_height: number,
is_controlling: boolean,
reposted: number,
support_amount: string,
take_over_height: number,
},
name: string,
normalized_name: string,
nout: number,
permanent_url: string,
short_url: string,
timestamp: number,
txid: string,
type: string,
value: {
public_key: string,
public_key_id: string,
},
value_type: string,
}

declare type ClaimActionResolveInfo = {
[string]: {
stream: ?StreamClaim,
channel: ?ChannelClaim,
claimsInChannel: ?number,
collection: ?CollectionClaim,
errorCensor: ?ClaimErrorCensor,
},
}

Expand Down
4 changes: 2 additions & 2 deletions ui/page/show/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
selectTitleForUri,
selectClaimIsMine,
makeSelectClaimIsPending,
makeSelectIsBlacklisted,
} from 'redux/selectors/claims';
import {
makeSelectCollectionForId,
Expand All @@ -23,7 +24,6 @@ import { normalizeURI } from 'util/lbryURI';
import * as COLLECTIONS_CONSTS from 'constants/collections';
import { push } from 'connected-react-router';
import { makeSelectChannelInSubscriptions } from 'redux/selectors/subscriptions';
import { selectBlackListedOutpoints } from 'lbryinc';
import ShowPage from './view';

const select = (state, props) => {
Expand Down Expand Up @@ -72,7 +72,6 @@ const select = (state, props) => {
uri,
claim,
isResolvingUri: selectIsUriResolving(state, uri),
blackListedOutpoints: selectBlackListedOutpoints(state),
totalPages: makeSelectTotalPagesForChannel(uri, PAGE_SIZE)(state),
isSubscribed: makeSelectChannelInSubscriptions(uri)(state),
title: selectTitleForUri(state, uri),
Expand All @@ -82,6 +81,7 @@ const select = (state, props) => {
collectionId: collectionId,
collectionUrls: makeSelectUrlsForCollectionId(collectionId)(state),
isResolvingCollection: makeSelectIsResolvingCollectionForId(collectionId)(state),
isBlacklisted: makeSelectIsBlacklisted(uri)(state),
};
};

Expand Down
58 changes: 21 additions & 37 deletions ui/page/show/view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ type Props = {
uri: string,
claim: StreamClaim,
location: UrlLocation,
blackListedOutpoints: Array<{
txid: string,
nout: number,
}>,
title: string,
claimIsMine: boolean,
claimIsPending: boolean,
Expand All @@ -35,6 +31,7 @@ type Props = {
collectionUrls: Array<string>,
isResolvingCollection: boolean,
fetchCollectionItems: (string) => void,
isBlacklisted: boolean,
};

function ShowPage(props: Props) {
Expand All @@ -43,7 +40,6 @@ function ShowPage(props: Props) {
resolveUri,
uri,
claim,
blackListedOutpoints,
location,
claimIsMine,
isSubscribed,
Expand All @@ -54,11 +50,11 @@ function ShowPage(props: Props) {
collection,
collectionUrls,
isResolvingCollection,
isBlacklisted,
} = props;

const { search } = location;

const signingChannel = claim && claim.signing_channel;
const canonicalUrl = claim && claim.canonical_url;
const claimExists = claim !== null && claim !== undefined;
const haventFetchedYet = claim === undefined;
Expand Down Expand Up @@ -103,7 +99,7 @@ function ShowPage(props: Props) {
}

let innerContent = '';
if (!claim || (claim && !claim.name)) {
if ((!claim || (claim && !claim.name)) && !isBlacklisted) {
innerContent = (
<Page>
{(claim === undefined ||
Expand Down Expand Up @@ -142,38 +138,26 @@ function ShowPage(props: Props) {
{!isResolvingUri && isSubscribed && claim === null && <AbandonedChannelPreview uri={uri} type={'large'} />}
</Page>
);
} else if (claim.name.length && claim.name[0] === '@') {
} else if (claim && claim.name.length && claim.name[0] === '@') {
innerContent = <ChannelPage uri={uri} location={location} />;
} else if (isBlacklisted && !claimIsMine) {
innerContent = (
<Page>
<Card
title={uri}
subtitle={__(
'In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications.'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just need a way to differentiate between actual US DMCA and other reasons. Possibly if blocking channel name includes "DMCA"? This should not be the message for every blocking channel.
Examples of channels here
https://github.com/lbryio/hub/blob/master/docs/blocking.md#defaults

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We hvae a few cases:

  1. it literally says DMCA in the channel name -> show DMCA text, but say "hub" did it - not "we" did it.
  2. the channel that blocks it has a description -> some way to show channel and description
  3. the channel that blocks it has no description. -> some way to show channel and generic text

I think this may need some way to display the channel that blocked (reposted) it, to resolve the channel that blocked it (possibly a claim preview component?) and display the description of the channel that blacked it.

)}
actions={
<div className="section__actions">
<Button button="link" href="https://lbry.com/faq/dmca" label={__('Read More')} />
</div>
}
/>
</Page>
);
} else if (claim) {
let isClaimBlackListed = false;

isClaimBlackListed =
blackListedOutpoints &&
blackListedOutpoints.some(
(outpoint) =>
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
);

if (isClaimBlackListed && !claimIsMine) {
innerContent = (
<Page>
<Card
title={uri}
subtitle={__(
'In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications.'
)}
actions={
<div className="section__actions">
<Button button="link" href="https://lbry.com/faq/dmca" label={__('Read More')} />
</div>
}
/>
</Page>
);
} else {
innerContent = <FilePage uri={uri} location={location} />;
}
innerContent = <FilePage uri={uri} location={location} />;
}

return <React.Fragment>{innerContent}</React.Fragment>;
Expand Down
2 changes: 1 addition & 1 deletion ui/redux/actions/claims.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export function doResolveUris(
if (uriResolveInfo) {
if (uriResolveInfo.error) {
// $FlowFixMe
resolveInfo[uri] = { ...fallbackResolveInfo };
resolveInfo[uri] = { ...fallbackResolveInfo, errorCensor: uriResolveInfo.error.censor };
} else {
if (checkReposts) {
if (uriResolveInfo.reposted_claim) {
Expand Down
14 changes: 9 additions & 5 deletions ui/redux/reducers/claims.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type State = {
createCollectionError: ?string,
channelClaimCounts: { [string]: number },
claimsByUri: { [string]: string },
blacklistedByUri: { [string]: ClaimErrorCensor },
byId: { [string]: Claim },
pendingById: { [string]: Claim }, // keep pending claims
resolvingUris: Array<string>,
Expand Down Expand Up @@ -67,6 +68,7 @@ type State = {

const reducers = {};
const defaultState = {
blacklistedByUri: {},
byId: {},
claimsByUri: {},
paginatedClaimsByChannel: {},
Expand Down Expand Up @@ -118,6 +120,7 @@ const defaultState = {
function handleClaimAction(state: State, action: any): State {
const { resolveInfo }: ClaimActionResolveInfo = action.data;

const blacklistedByUri = Object.assign({}, state.blacklistedByUri);
const byUri = Object.assign({}, state.claimsByUri);
const byId = Object.assign({}, state.byId);
const channelClaimCounts = Object.assign({}, state.channelClaimCounts);
Expand All @@ -127,9 +130,11 @@ function handleClaimAction(state: State, action: any): State {

Object.entries(resolveInfo).forEach(([url, resolveResponse]) => {
// $FlowFixMe
const { claimsInChannel, stream, channel: channelFromResolve, collection } = resolveResponse;
const { claimsInChannel, stream, channel: channelFromResolve, collection, errorCensor } = resolveResponse;
const channel = channelFromResolve || (stream && stream.signing_channel);

blacklistedByUri[url] = errorCensor;

if (stream) {
if (pendingById[stream.claim_id]) {
byId[stream.claim_id] = mergeClaim(stream, byId[stream.claim_id]);
Expand Down Expand Up @@ -197,6 +202,7 @@ function handleClaimAction(state: State, action: any): State {
});

return Object.assign({}, state, {
blacklistedByUri,
byId,
claimsByUri: byUri,
channelClaimCounts,
Expand Down Expand Up @@ -518,10 +524,8 @@ reducers[ACTIONS.UPDATE_PENDING_CLAIMS] = (state: State, action: any): State =>
};

reducers[ACTIONS.UPDATE_CONFIRMED_CLAIMS] = (state: State, action: any): State => {
const {
claims: confirmedClaims,
pending: pendingClaims,
}: { claims: Array<Claim>, pending: { [string]: Claim } } = action.data;
const { claims: confirmedClaims, pending: pendingClaims }: { claims: Array<Claim>, pending: { [string]: Claim } } =
action.data;
const byId = Object.assign({}, state.byId);
const byUri = Object.assign({}, state.claimsByUri);
//
Expand Down
33 changes: 33 additions & 0 deletions ui/redux/selectors/claims.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { selectSupportsByOutpoint } from 'redux/selectors/wallet';
import { createSelector } from 'reselect';
import { createCachedSelector } from 're-reselect';
import { isClaimNsfw, filterClaims } from 'util/claim';
import { selectBlackListedOutpoints } from 'lbryinc';
import * as CLAIM from 'constants/claim';

type State = { claims: any };
Expand Down Expand Up @@ -83,6 +84,38 @@ export const selectClaimIdForUri = (state: State, uri: string) => selectClaimIds

export const selectReflectingById = (state: State) => selectState(state).reflectingById;

export const makeSelectClaimErrorCensor = (claimUri: string) =>
createSelector(selectState, (state) => state.blacklistedByUri[claimUri]);

export const makeSelectIsBlacklisted = (claimUri: string) =>
createSelector(
makeSelectClaimErrorCensor(claimUri),
selectBlackListedOutpoints,
makeSelectClaimForUri(claimUri),
(errorCensor, legacyBlacklistedList, claim) => {
if (errorCensor) {
return true;
}
// Fallback to legacy just in case.
if (!claim) {
return false;
}
if (!legacyBlacklistedList) {
return false;
}
const signingChannel = claim.signing_channel;
if (!signingChannel) {
return false;
}
const isInLegacyBlacklist = legacyBlacklistedList.some(
(outpoint) =>
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
);
return isInLegacyBlacklist;
}
);

export const makeSelectClaimForClaimId = (claimId: string) => createSelector(selectClaimsById, (byId) => byId[claimId]);

export const selectClaimForUri = createCachedSelector(
Expand Down