Support for creator-requested geoblocking (#1063)

Attempt to fix logic + case

Fix logic

Co-authored-by: Thomas Zarebczan <thomas.zarebczan@gmail.com>
This commit is contained in:
infinite-persistence 2022-03-10 11:28:54 -08:00 committed by GitHub
parent d52fd8e26e
commit ca7b98ecf5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 94 additions and 3 deletions

View file

@ -120,7 +120,7 @@ ENABLE_WILD_WEST=true
BRANDED_SITE=odysee
LOADING_BAR_COLOR=#e50054
# FIREBASE
# --- Firebase ---
FIREBASE_API_KEY=AIzaSyAgc-4QORyglpYZ3qH9E5pDauEDOJXgM3A
FIREBASE_AUTH_DOMAIN=lbry-mobile.firebaseapp.com
FIREBASE_PROJECT_ID=lbry-mobile
@ -130,6 +130,13 @@ FIREBASE_APP_ID=1:638894153788:web:35b295b15297201bd2e339
FIREBASE_MEASUREMENT_ID=G-2MPJGFEEXC
FIREBASE_VAPID_KEY=BFayEBpwMTU9GQQpXgitIJkfx-SD8-ltrFb3wLTZWgA27MfBhG4948pe0eERl432NzPrMKsbkXnA7ap_vLPgLYk
# Development
# --- Geoblock ---
# Note: our current version of dotenv doesn't support multiline definition.
#
# FORMAT: "<channel_id>; type=[livestream|video|*]; country=[xx|*]; continent=[xx|*]; | ..."
#
GEOBLOCKED_CHANNELS="148bfcb49da2c2e781ae27387e45043a4bcbd51e; types=livestream; countries=FR,MS; continents=AF,EU; | 636098f86be74be8b609c38e643e48786d58f413; types=livestream,video; countries=EU,SA; continents=EU;"
# --- Development ---
REPORT_NEW_STRINGS=false
USE_LOCAL_HOMEPAGE_DATA=false

View file

@ -90,6 +90,30 @@ const config = {
AD_KEYWORD_BLOCKLIST_CHECK_DESCRIPTION: process.env.AD_KEYWORD_BLOCKLIST_CHECK_DESCRIPTION,
};
config.GEOBLOCKED_CHANNELS = {};
if (process.env.GEOBLOCKED_CHANNELS) {
const entries = process.env.GEOBLOCKED_CHANNELS.split('|');
entries.forEach((entry) => {
const fields = entry.split(';');
if (fields.length > 0) {
const channelId = fields[0].trim();
config.GEOBLOCKED_CHANNELS[channelId] = {};
for (let i = 1; i < fields.length; ++i) {
const kv = fields[i].split('=');
if (kv.length === 2) {
const key = kv[0].trim();
const values = kv[1].trim();
config.GEOBLOCKED_CHANNELS[channelId][key] = values.split(',');
}
}
}
});
}
config.SDK_API_PATH = `${config.LBRY_WEB_API}/api/v1`;
config.PROXY_URL = `${config.SDK_API_PATH}/proxy`;

13
flow-typed/user.js vendored
View file

@ -34,3 +34,16 @@ declare type User = {
global_mod: boolean,
odyseeMembershipsPerClaimIds: ?{},
};
declare type LocaleInfo = {
continent: string,
country: string,
gdpr_required: boolean,
is_eu_member: boolean,
};
declare type GeoBlock = {
types: Array<string>,
countries: Array<string>,
continents: Array<string>,
};

View file

@ -2218,6 +2218,7 @@
"The minimum duration must not exceed Feb 8th, 2022.": "The minimum duration must not exceed Feb 8th, 2022.",
"No limit": "No limit",
"Search results are being filtered by language. Click here to change the setting.": "Search results are being filtered by language. Click here to change the setting.",
"This creator has requested that their livestream be blocked in your region.": "This creator has requested that their livestream be blocked in your region.",
"There are language translations available for your location! Do you want to switch from English?": "There are language translations available for your location! Do you want to switch from English?",
"A homepage and language translations are available for your location! Do you want to switch?": "A homepage and language translations are available for your location! Do you want to switch?",
"A homepage is available for your location! Do you want to switch?": "A homepage is available for your location! Do you want to switch?",

View file

@ -1,5 +1,6 @@
// @flow
import * as PAGES from 'constants/pages';
import * as SETTINGS from 'constants/settings';
import React, { useEffect, useRef, useState, useLayoutEffect } from 'react';
import { lazyImport } from 'util/lazyImport';
import { tusUnlockAndNotify, tusHandleTabUpdates } from 'util/tus';
@ -364,6 +365,17 @@ function App(props: Props) {
}
}, [previousRewardApproved, isRewardApproved]);
useEffect(() => {
fetchLocaleApi().then((response) => {
const locale: LocaleInfo = response?.data;
if (locale) {
// Put in 'window' for now. Can be moved to localStorage or wherever,
// but the key should remain the same so clients are not affected.
window[SETTINGS.LOCALE] = locale;
}
});
}, []);
// Load IMA3 SDK for aniview
// useEffect(() => {
// if (!isAuthenticated && SHOW_ADS) {

View file

@ -40,6 +40,7 @@ export const SUPPORT_OPTION = 'support_option';
export const TILE_LAYOUT = 'tile_layout';
export const VIDEO_THEATER_MODE = 'video_theater_mode';
export const VIDEO_PLAYBACK_RATE = 'video_playback_rate';
export const LOCALE = 'odysee_user_locale';
export const SETTINGS_GRP = {
APPEARANCE: 'appearance',

View file

@ -6,11 +6,32 @@ import analytics from 'analytics';
import LivestreamLayout from 'component/livestreamLayout';
import moment from 'moment';
import Page from 'component/page';
import Yrbl from 'component/yrbl';
import { GEOBLOCKED_CHANNELS } from 'config';
import * as SETTINGS from 'constants/settings';
import React from 'react';
import { useIsMobile } from 'effects/use-screensize';
const LivestreamChatLayout = lazyImport(() => import('component/livestreamChatLayout' /* webpackChunkName: "chat" */));
function isLivestreamGeoAllowed(channelId: ?string, isLive: boolean) {
const locale: LocaleInfo = window[SETTINGS.LOCALE];
const geoBlock: GeoBlock = GEOBLOCKED_CHANNELS[channelId];
if (locale && geoBlock) {
const typeBlocked = geoBlock.types && geoBlock.types.includes('livestream');
const countryBlocked = geoBlock.countries && geoBlock.countries.includes(locale.country);
const europeanUnionOnly = geoBlock.continents && geoBlock.continents.includes('EU-UNION') && locale.is_eu_member;
const continentBlocked =
europeanUnionOnly || (geoBlock.continents && geoBlock.continents.includes(locale.continent));
return typeBlocked && !countryBlocked && !continentBlocked;
}
// If 'locale/get' fails, we don't know whether to block or not. Flaw?
return true;
}
type Props = {
activeLivestreamForChannel: any,
activeLivestreamInitialized: boolean,
@ -54,6 +75,7 @@ export default function LivestreamPage(props: Props) {
const claimId = claim && claim.claim_id;
const isCurrentClaimLive = isChannelBroadcasting && activeLivestreamForChannel.claimId === claimId;
const livestreamChannelId = channelClaimId || '';
const isGeoBlocked = !isLivestreamGeoAllowed(channelClaimId, isCurrentClaimLive);
// $FlowFixMe
const release = moment.unix(claim.value.release_time);
@ -160,6 +182,7 @@ export default function LivestreamPage(props: Props) {
livestream
chatDisabled={hideComments}
rightSide={
!isGeoBlocked &&
!hideComments &&
isInitialized && (
<React.Suspense fallback={null}>
@ -168,7 +191,17 @@ export default function LivestreamPage(props: Props) {
)
}
>
{isInitialized && (
{isGeoBlocked && (
<div className="main--empty">
<Yrbl
title={__('This creator has requested that their livestream be blocked in your region.')}
type="sad"
alwaysShow
/>
</div>
)}
{isInitialized && !isGeoBlocked && (
<LivestreamLayout
uri={uri}
hideComments={hideComments}