drop youtube sync

This commit is contained in:
Jeremy Kauffman 2020-12-14 17:43:06 -05:00 committed by Jeremy Kauffman
parent fd48df9350
commit 40f28c39ff
30 changed files with 328 additions and 1623 deletions

View file

@ -111,7 +111,6 @@ class Controller
$router->get(['/', 'home'], 'ContentActions::executeHome');
$router->get(['/get', 'get'], 'DownloadActions::executeGet');
$router->get(['/getrubin', 'getrubin'], 'DownloadActions::executeGet');
foreach (array_keys(OS::getAll()) as $os) {
$router->get(['/' . $os, 'get-' . $os], 'DownloadActions::executeGet');
@ -132,20 +131,8 @@ class Controller
$router->any('/dmca', 'ReportActions::executeDmca');
$router->any('/dmca/{claimid}', 'ReportActions::executeDmcaWithClaimId');
$router->get('/escapeyoutube', 'AcquisitionActions::executeYouTube');
$router->get('/escapeyoutubeiframe', 'AcquisitionActions::executeYouTubeIframe');
$router->post('/youtube/edit', 'AcquisitionActions::executeYoutubeEdit');
$router->post('/youtube/token', 'AcquisitionActions::executeYoutubeToken');
$router->any('/youtube/status/{token}', 'AcquisitionActions::executeYoutubeStatus');
$router->any('/youtube/status', 'AcquisitionActions::executeRedirectYoutube');
$router->any('/youtube', 'AcquisitionActions::executeYouTube');
$router->get('/youtube/{version}', 'AcquisitionActions::executeYouTube');
$router->get('/verify/{token}', 'AcquisitionActions::executeVerify');
$router->get('/verify', 'AcquisitionActions::executeAutoVerify');
$router->get('/follow/{claim}', 'AcquisitionActions::executeFollowCampaign');
$router->get('/i18n/get/{project}/{resource}/{language}.json', 'i18nActions::executeServeTranslationFile');

View file

@ -146,9 +146,4 @@ class Request
return preg_match('/(' . join('|', $bots) . ')/i', static::getUserAgent());
}
//Method that encode html tags to special character
public static function encodeStringFromUser($string)
{
return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
}
}

View file

@ -3,7 +3,6 @@
class Session
{
const KEY_LIST_SUB_ERROR = 'list_error',
KEY_YOUTUBE_SYNC_ERROR = 'youtube_sync_error',
KEY_USER_CULTURE = 'user_culture';
const NAMESPACE_DEFAULT = 'default',

View file

@ -2,130 +2,18 @@
class AcquisitionActions extends Actions
{
protected static $isYouTubeDisabled = false;
public static function isYouTubeSyncEnabled()
public static function executeYouTube()
{
return !static::$isYouTubeDisabled;
}
public static function executeFollowCampaign(string $claimName)
{
$claim = ChainQuery::findChannelClaim($claimName);
if (!$claim || !$claim['source_url']) {
Controller::redirect('/');
}
$title = $claim['title'] ?: $claim['name'];
$coverUrl = $claim['source_url'];
return ['acquisition/follow_campaign', [
'claim' => $claim,
'claimCount' => ChainQuery::countClaimsInChannel($claim['claim_id']),
'title' => $title,
'coverUrl' => $coverUrl,
]];
}
public static function executeYouTubeIframe()
{
return ['acquisition/youtubeiframe', ['_no_layout' => true]];
}
public static function executeYouTube(string $version = '')
{
$errorMessage = Request::getParam('error_message', '');
if (Session::getFlash(Session::KEY_YOUTUBE_SYNC_ERROR)) {
$errorMessage = Session::getFlash(Session::KEY_YOUTUBE_SYNC_ERROR);
}
return ['acquisition/youtube', [
'reward' => LBRY::youtubeReward(),
'error_message' => $errorMessage
]];
}
public static function executeVerify(string $token)
{
Response::disableHttpCache();
return ['acquisition/verify', ['token' => $token]];
}
public static function executeAutoVerify()
{
Response::disableHttpCache();
return ['acquisition/auto-verify'];
}
public static function executeYoutubeToken()
{
Response::disableHttpCache();
$channelName = Request::encodeStringFromUser($_POST['desired_lbry_channel_name']);
$immediateSync = (boolean)$_POST['immediate_sync'];
if ($channelName && $channelName[0] !== "@") {
$channelName = '@' . $channelName;
}
$token = LBRY::connectYoutube($channelName, $immediateSync);
if ($token['success'] && $token['data']) {
Controller::redirect($token['data']);
} else {
Session::setFlash(Session::KEY_YOUTUBE_SYNC_ERROR, $token['error'] ?? "An unknown error occured.");
Controller::redirect('/youtube');
}
return ['acquisition/youtube'];
}
/*
* this is disabled, but kept around because users still access these URLs from emails
*
* it should be left as long as meaningful traffic exists to it in analytics
*/
public static function executeYoutubeStatus(string $token)
{
Response::disableHttpCache();
$data = null;
if (!static::$isYouTubeDisabled) {
$data = LBRY::statusYoutube($token);
if (!$data['success']) {
Session::setFlash(Session::KEY_YOUTUBE_SYNC_ERROR, $data['error'] ?? "Error fetching your sync status.");
Controller::redirect('/youtube');
}
}
return ['acquisition/youtube_status', [
'token' => $token,
'is_disabled' => static::$isYouTubeDisabled,
'status_token' => $data,
'error_message' => Session::getFlash(Session::KEY_YOUTUBE_SYNC_ERROR)
]];
}
public static function actionYoutubeEdit($status_token, $channel_name, $email, $sync_consent)
{
$current_value = LBRY::statusYoutube($status_token);
if ($current_value['data']['email'] == $email) {
if ($channel_name === null && $sync_consent === false) {
return Controller::redirect("/youtube/status/". $status_token);
}
$status = LBRY::editYoutube($status_token, $channel_name, null, $sync_consent);
} else {
$status = LBRY::editYoutube($status_token, $channel_name, $email, $sync_consent);
}
if ($status['success'] == false) {
Session::setFlash(Session::KEY_YOUTUBE_SYNC_ERROR, $status['error']);
Controller::redirect("/youtube/status/". $status_token);
} else {
Controller::redirect("/youtube/status/" . $status_token);
}
}
public static function executeYoutubeEdit()
{
return ['acquisition/youtube_edit'];
}
public static function executeRedirectYoutube()
{
return ['acquisition/youtube_status_redirect'];
return ['acquisition/youtube_status'];
}
}

View file

@ -50,6 +50,7 @@
/lbry-linux-latest.deb: /get
/lbry-osx-latest.dmg: /get
/news/get: /get
/getrubin: /get
# Mailing List
/join-list: /list/subscribe
@ -141,3 +142,7 @@
/block-explorer: https://explorer.lbry.com/
/shop: https://shop.lbry.com/
# Legacy YouTube Sync
/escapeyoutube: /youtube
/escapeyoutubeiframe: /youtube
/youtube/status: /youtube

View file

@ -1,32 +0,0 @@
<?php
class ChainQuery
{
protected static $pdo = null;
public static function getInstance()
{
if (!static::$pdo) {
static::$pdo = new PDO(Config::get(Config::CHAINQUERY_DSN),
Config::get(Config::CHAINQUERY_USERNAME), Config::get(Config::CHAINQUERY_PASSWORD));
}
return static::$pdo;
}
public static function findChannelClaim($claimName)
{
$claimName = '@' . trim($claimName, '@');
$stmt = static::getInstance()->prepare("SELECT * FROM claim c WHERE c.name = ? AND c.bid_state = ?");
$stmt->execute([$claimName, "controlling"]);
return $stmt->fetch();
}
public static function countClaimsInChannel($claimId)
{
$stmt = static::getInstance()->prepare("SELECT COUNT(*) FROM claim c WHERE c.publisher_id = ?");
$stmt->execute([$claimId]);
$result = $stmt->fetch();
return $result[0] ?? 0;
}
}

View file

@ -1,6 +1,5 @@
<?php
class LBRY
{
const DEFAULT_TIMEOUT = 10;
@ -14,15 +13,6 @@ class LBRY
return Config::get(Config::LBRY_API_SERVER) . $endpoint;
}
public static function getLBCtoUSDRate()
{
$response = CurlWithCache::get(static::getApiUrl('/lbc/exchange_rate'), [], [
'cache' => 3600, //one hour
'json_response' => true
]);
return $response['data']['lbc_usd'] ?? 0;
}
public static function listTags($authToken)
{
$response = Curl::get(static::getApiUrl('/tag/list'), ['auth_token' => $authToken], ['json_response' => true]);
@ -53,56 +43,6 @@ class LBRY
return Curl::post(static::getApiUrl('/user/unsubscribe'), ['email' => $email], ['json_response' => true, 'timeout' => static::DEFAULT_TIMEOUT]);
}
public static function connectYoutube($channel_name, $immediateSync = false)
{
// Uncomment next line for production and comment other return
return Curl::post(static::getApiUrl('/yt/new'), [ 'desired_lbry_channel_name' => $channel_name, 'immediate_sync' => $immediateSync, 'type' => 'sync' ], [ 'json_response' => true, 'timeout' => static::DEFAULT_TIMEOUT ]);
// Uncomment next line for development and comment other return (this also requires the testnet API)
// return Curl::post(static::getApiUrl('/yt/new'), [
// 'desired_lbry_channel_name' => $channel_name,
// 'immediate_sync' => $immediateSync,
// 'return_url' => 'http://localhost:8000/youtube/status/',
// 'type' => 'sync'
// ], [
// 'json_response' => true
// ]);
}
// Check the sync status
public static function statusYoutube($status_token)
{
return Curl::get(static::getApiUrl('/yt/status'), ['status_token' => $status_token], ['json_response' => true, 'timeout' => static::DEFAULT_TIMEOUT]);
}
public static function youtubeReward()
{
return CurlWithCache::post(static::getApiUrl('/yt/rewards'), [], ['cache' => 3600, 'json_response' => true, 'timeout' => static::DEFAULT_TIMEOUT]);
}
public static function editYouTube($status_token, $channel_name, $email, $sync_consent)
{
$postParams = array('status_token' => $status_token);
if ($email) {
$postParams['new_email'] = $email;
}
if ($sync_consent) {
if ($sync_consent === 0) {
$sync_consent = null;
}
$postParams['sync_consent'] = $sync_consent;
}
if ($channel_name) {
$postParams['new_preferred_channel'] = $channel_name;
}
return Curl::post(static::getApiUrl("/yt/update"), $postParams, ['json_response' => true, 'timeout' => static::DEFAULT_TIMEOUT]);
}
public static function logWebVisitor($site, $visitorID, $IPAddress)
{
if (IS_PRODUCTION) {

View file

@ -1,89 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Verify Your Identity</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
<link rel="icon" href="images/favicon.ico"/>
<script src='https://www.google.com/recaptcha/api.js?' async defer></script>
<script>
const ENDPOINT = '<?php echo LBRY::getApiUrl('/user_email/confirm')?>'
var verifyUser = function(temporary_auth_token, email, verification_token, recaptcha) {
const url = `${ENDPOINT}?auth_token=${temporary_auth_token}&email=${encodeURIComponent(email)}&verification_token=${verification_token}&recaptcha=${recaptcha}`;
fetch(url)
.then(response => response.json())
.then((response) => {
if (response.error) {
throw Error(response.error)
}
document.getElementById("title").textContent = "Done!"
document.getElementById("verify").style.display = "none";
document.getElementById("verify-success").style.display = "block";
})
.catch(error => {
document.getElementById("title").textContent = "Uh oh"
document.getElementById("verify").style.display = "none";
document.getElementById("verify-error").style.display = "block";
document.getElementById("verify-error-text").textContent = error.message;
})
}
var verifyCallback = function(response) {
const urlParams = new URLSearchParams(window.location.search);
const temporary_auth_token = urlParams.get('auth_token');
const email = urlParams.get('email')
const verification_token = urlParams.get('verification_token');
// In the future we will have an `origin` query, to smartly redirect (or tell users they are verified)
// eg. if origin == "android" and device == "android" open the app, else say "your android app is verified"
verifyUser(temporary_auth_token, email, verification_token, response);
document.getElementById("captcha-block").style.display = "none";
document.getElementById("verify").style.display = "block";
}
var expiredCallback = function(error) {
console.log("expired", error)
}
</script>
</head>
<body>
<main class="ancillary">
<section class="hero hero--half-height">
<div class="inner-wrap inner-wrap--center-hero">
<h1 id="title">Almost Done!</h1>
</div>
</section>
<section>
<div class="inner-wrap inner-wrap--center">
<div id="captcha-block">
<p>Click the captcha to continue...</p>
<br/>
<div class="g-recaptcha" data-sitekey="6LePsJgUAAAAAFTuWOKRLnyoNKhm0HA4C3elrFMG" data-callback="verifyCallback" data-expired-callback="expiredCallback"></div>
</div>
<div style="display: none; margin-top: 10px;" id="verify">
<p>Verifying...</p>
</div>
<div style="display: none; margin-top: 10px;" id="verify-error">
<code id="verify-error-text"></code>
<p style="margin-top: 10px">There was an error, try again. Please make sure you are clicking the latest verification email. You can also resend the verification from your app, and click on that new email. Contact help@lbry.com if this keeps happening.</p>
</div>
<div style="display: none; margin-top: 10px;" id="verify-success">
<p class="spacer1">Success! Your email is now verified. Please switch back to the application or site you started verification.</p>
</div>
</div>
</section>
</main>
</body>
</html>

View file

@ -1,84 +0,0 @@
<?php Response::setMetaDescription('Watch ' . $title . ' on a platform that shares your values.') ?>
<?php Response::setMetaTitle($title . ' on LBRY') ?>
<main class="ancillary">
<section class="hero hero--half-height" style="background-image: url(<?php echo $coverUrl ?>)">
<div class="inner-wrap inner-wrap--center-hero">
<h1>Watch <?php echo $title ?></h1>
<h3>On a platform that shares your values.</h3>
</div>
</section>
<section>
<div class="inner-wrap">
<div class="inline-image-and-text">
<img
alt="cctv camera"
class="inline-image"
src="/img/icon--cctv.svg"
/>
<p>Predatory platforms like Facebook and YouTube abuse users, censor creators, enforce rules arbitrarily, and spy on everything you do.</p>
</div>
<div class="inline-image-and-text">
<p>LBRY is a user-controlled, open-source platform that stands for user freedom and personal choice. It has <em><?php echo $claimCount ?> videos from <?php echo $claim['name'] ?></em>.</p>
<img
alt="smile icon"
class="inline-image"
src="/img/icon--smile.svg"
/>
</div>
</div>
</section>
<section>
<div class="inner-wrap">
<h3>Step 1: Download LBRY</h3>
<p>LBRY is an open-source application available on Windows, macOS, Linux, and Android, with iOS coming soon.</p>
<br/>
<div class="align-text--center">
<?php echo View::render('download/_downloadButton', ['buttonStyle' => 'primary'])?>
<a href="/get?showall=1" class="button--link">show all platforms</a>
</div>
<br/>
</div>
</section>
<section>
<div class="inner-wrap">
<h3>Step 2: Search and Follow <?php echo $claim['name'] ?></h3>
<p>Type <?php echo $claim['name'] ?> in the search bar and then click Follow.</p>
<div class="align-text--center" style="margin-top: 1rem; margin-bottom: 1rem;">
<img src="https://spee.ch/e/follow-1.gif" alt="How to follow <?php echo $claim['name'] ?> on LBRY" />
</div>
<p>If you provide your email address, you'll be notified about every new video.</p>
</div>
<br/>
</section>
<section>
<div class="inner-wrap">
<h3>Step 3 (Optional): Support <?php echo $claim['name'] ?></h3>
<p>Use the Tip button to support <?php echo $claim['name'] ?> and help others discover this content.</p>
<p>If you verify your account, you'll receive free credits that you can send to <?php echo $claim['name'] ?> or other creators.</p>
<small><em>Having trouble?</em> Read <a href="/faq/rewards">the rewards FAQ</a> for help.</small>
<div class="align-text--center" style="margin-top: 1rem; margin-bottom: 1rem;">
<img src="https://spee.ch/9/follow-tip.png" alt="How to support <?php echo $claim['name'] ?> on LBRY" />
</div>
</div>
<br/>
</section>
<section>
<div class="inner-wrap">
<h3>Step 4: Enjoy Peace of Mind</h3>
<p>When you watch <?php echo $title ?> on LBRY, you're watching via a platform that is open-source, user-controlled, and censorship-resistant.</p>
<p>Unlike other platforms, it is <em>literally impossible</em> for LBRY to put it's thumb on the scales.</p>
<p>So what are you waiting for? Try LBRY today!</p>
<br/>
<div class="align-text--center">
<?php echo View::render('download/_downloadButton', ['buttonStyle' => 'primary'])?>
<a href="/get?showall=1" class="button--link">show all platforms</a>
</div>
<br/>
<div>
<small>Not enough details for you? Read the <a href="/what">manifesto</a> or the <a href="//lbry.tech">docs</a>.</small>
</div>
</div>
</section>
</main>

View file

@ -1,60 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Verify Your Identity</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
<link rel="icon" href="images/favicon.ico"/>
<script src='https://www.google.com/recaptcha/api.js'></script>
<script>
var magicLink = "#";
var verifyCallback = function(response) {
let payload = btoa(JSON.stringify({
recaptcha: response,
token: "<?php echo $token ?>"
}));
magicLink = "lbry://?verify=" + payload;
document.getElementById("magic-link-text").textContent = payload;
document.getElementById("success").style.display = "block";
document.getElementById("captcha-block").style.display = "none";
};
var expiredCallback = function() {
document.getElementById("success").style.display = "none";
document.getElementById("captcha-block").style.display = "block";
}
</script>
</head>
<body>
<main class="ancillary">
<section class="hero hero--half-height">
<div class="inner-wrap inner-wrap--center-hero">
<h1 id="title">Almost Done!</h1>
</div>
</section>
<section>
<div class="inner-wrap inner-wrap--center">
<div id="captcha-block">
<p>Click the captcha to continue...</p>
<br/>
<div class="g-recaptcha" data-sitekey="6LePsJgUAAAAAFTuWOKRLnyoNKhm0HA4C3elrFMG" data-callback="verifyCallback" data-expired-callback="expiredCallback"></div>
</div>
<div style="display: none; margin-top: 10px;" id="success">
<p>Now click the magic link below to verify your identity in app...</p>
<br/>
<a class="btn-primary btn-large spacer1" onclick="location.href=magicLink">Magic Link</a>
<p><i>When prompted, open the link with LBRY Browser on Android or LBRY on Desktop. Does the magic link not work? Not on the same device as the app? Paste this (very long) piece of text into the verification screen of the app to confirm your identity.</i></p>
<code class="multiline-code" id="magic-link-text"></code>
</div>
</div>
</section>
</main>
</body>
</html>

View file

@ -1,19 +1,10 @@
<?php
Response::addJsAsset('/js/yt2/TweenMax.min.js');
Response::addJsAsset('/js/yt2/app.js');
Response::addJsAsset('/js/yt2/FormValidation.js');
Response::addJsAsset('/js/yt2/SyncStatus.js');
Response::addJsAsset('/js/yt2/youtube_video.js');
if (in_array($_SERVER['REQUEST_URI'], ['/escapeyoutube'])) {
Response::setMetaTitle("Escape YouTube");
Response::setMetaDescription("Put your content on the LBRY blockchain before it's too late");
Response::addMetaImage('https://spee.ch/6/18OanRVGL6mQIMtj93Hb09te.jpeg');
} else {
Response::setMetaTitle("LBRY YouTube Partner Program");
Response::setMetaDescription("Put your content on the blockchain, experience true content freedom, and earn rewards.");
Response::addMetaImage(Request::getHostAndProto() . '/img/lbry-partner.png');
}
$isEnabled = AcquisitionActions::isYouTubeSyncEnabled();
Response::setMetaTitle("LBRY x YouTube Partner Program");
Response::setMetaDescription("Take back control of your channel and audience while earning more.");
Response::addMetaImage(Request::getHostAndProto() . '/img/lbry-partner.png');
$isEnabled = true;
?>
<main class="ancillary youtube youtube--landing">
@ -43,225 +34,34 @@
<div class="inner-wrap inner-wrap--center-left">
<h1 class="weight-light">LBRY &times; YouTube Sync</h1>
<h2 class="weight-light">Get your YouTube videos in front of the LBRY audience</h2>
<button
class="button button--inverse"
data-id="scroll-to-claim"
style="font-size: 1rem; margin-top: 2rem;"
type="button"
>Claim your channel now</button>
</div>
</section>
<section class="align-text--center" id="claim-section">
<div class="inner-wrap">
<?php
if ($error_message): echo "<p class='error-block'>" . "The following error occurred: ". $error_message . " For support please send an email to <a href='mailto:hello@lbry.com' title='Email LBRY for help'>hello@lbry.com</a>." . "</p>";
endif;?>
<p hidden id="lbry_error" class="error-block">LBRY channel name is either not valid (only letters, numbers and - allowed, no spaces) or your input is blank</p>
<h2>Connect with your fans while earning rewards</h2>
<?php if ($isEnabled): ?>
<form id="youtube_claim" method="post" action="/youtube/token">
<p hidden id="sync-status" class="sync-status"></p>
<input-submit style="font-size: 1rem;">
<label class="symbol-prefix">@</label>
<input
id="lbry_channel_name"
name="desired_lbry_channel_name"
placeholder="Enter desired LBRY channel name (permanent)"
type="text"
/>
<input
onClick="return submitDetailsForm()"
type="submit"
value="Claim now"
/>
</input-submit>
<br/>
<checkbox-element style="font-size: 1rem;">
<input hidden name="type" type="text" value="sync"/>
<input id="immediate-sync" name="immediate_sync" type="checkbox" value="true"/>
<label for="immediate-sync">I want to sync my content to the LBRY network and agree to <a href="/faq/youtube-terms" target="_blank">these terms</a>. I have also read and understand <a href="/faq/youtube" target="_blank">how the program works</a>.</label>
<checkbox-toggle/>
</checkbox-element>
</form>
<?php else: ?>
<div class="notice notice-info spacer1">
The YouTube Program is paused for maintenance. Enter your email address and we will notify you as soon as it returns.
If you have over 10K subs on YouTube, please <a href="https://docs.google.com/forms/d/1b9bEahq1L-hWaYN0MfnBZ8d0MnM4oQpsLFG1TlBHMrI/edit">use this form</a> for a manual sync request.
</div>
<?php echo View::render('mail/_subscribeForm', [
'tag' => 'youtube_sync_paused',
'submitLabel' => 'Get Started',
'hideDisclaimer' => true,
'largeInput' => true,
'btnClass' => 'btn-alt btn-large',
]) ?>
<?php endif ?>
<small class="meta">
This will verify you are an active YouTuber. Channel names cannot be changed once chosen, please be extra careful. Additional instructions will be emailed to you after you verify your email on the next page.
<a href="/faq/youtube">Learn more</a>
</small>
</div>
</section>
<section>
<div class="join section inner-wrap">
<h3>Join great creators already on LBRY</h3>
<p>Audiences range from 1,000+ to 10,000,000+ people. The videos below are from creators who have synced their content to LBRY.</p>
<div class="ytsync-previews">
<figure class="ytsync-preview">
<video
onclick="playVideo('video1')"
id="video1"
poster="/img/youtube/01@2x.jpg"
src="https://spee.ch/1ac47b8b3def40a25850dc726a09ce23d09e7009/ever-wonder-how-bitcoin-and-other.mp4"
></video>
<figcaption>@3Blue1Brown</figcaption>
</figure>
<figure class="ytsync-preview">
<video
onclick="playVideo('video2')"
id="video2"
poster="/img/youtube/02@2x.jpg"
src="https://spee.ch/3c96f32de285db6c04e80bd6f5fad573250541e9/casually-successful.mp4"
></video>
<figcaption>@CasuallyExplained</figcaption>
</figure>
<figure class="ytsync-preview">
<video
onclick="playVideo('video3')"
id="video3"
poster="/img/youtube/03@2x.jpg"
src="https://spee.ch/8958c5d573d71f5c2d0c1bfdf752737ce39744cb/the-historical-elements-of-wolfenstein.mp4"
></video>
<figcaption>@ColinsLastStand</figcaption>
</figure>
</div>
</div>
</section>
<section>
<div class="rewards section inner-wrap">
<h3>What you earn</h3>
<h2 class="weight-light">Keep your channel safe. Reach an audience of millions.</h2>
<br/>
<?php /*
<table>
<thead style="font-size: 80%;">
<tr>
<th>Current YouTube Subscribers</th>
<th>LBRY Credits/Year</th>
<th>USD Value <small class="meta">1 LBC = <span class="current-value"></span></small></th>
</tr>
</thead>
<a
class="button button--inverse"
href="#begin-sync"
>Claim your channel now</a>
</div>
</section>
<tbody>
<?php foreach ($reward['data'] as $subCount => $rewardAmt): ?>
<tr>
<td><?php echo number_format($subCount) ?></td>
<td><?php echo number_format($rewardAmt * 12); //API returns per month?> <small class="meta">LBC</small></td>
<td class="lbc-to-usd" data-lbc-amount="<?php echo $rewardAmt * 12 ?>"></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<p class="align-text--center">
<small> <em>Table shows yearly awards but rewards are distributed monthly. Monthly reward will be one-twelfth the above amount. These reward amounts may change at LBRY Inc.'s discretion.</em></small>
</p>
*/ ?>
<h4>
For Views
</h4>
<p>Receive up to 2 LBC (<span class="lbc-to-usd" data-lbc-amount="2"></span>) per view from verified lbry.tv accounts. This requires at least 500 subs and original content. <a href="https://lbry.com/faq/view-rewards" target="_blank">Learn more.</a>
<small> <em>These reward amounts may change at LBRY Inc.'s discretion.</em></small>
<section class="section ancillary" id="begin-sync">
<div class="inner-wrap">
<h2>Sync Your YouTube Channel</h2>
<p>
YouTube channel sync is now a feature of <a href="https://odysee.com">odysee.com</a>, the most popular way to access LBRY.
</p>
<p>
Just <a href="https://odysee.com/$/signup">sign up</a> at Odysee and you'll be prompted to sync your channel when you join.
It takes under a minute -- take back control and begin earning!
</p>
<p>
<a class="button button--primary" href="https://odysee.com">Go to Odysee.com</a>
</p>
<video style="max-height: 480px"
autoplay loop playsinline
src="https://cdn.lbryplayer.xyz/api/v3/streams/free/odyseesignupscaled/b8d8e724119cccde76afcd9a9d50e83f75b7c6d3/e47793"
></video>
<h4>
For Building on LBRY
</h4>
<p>You receive additional rewards for building an audience, starting with your first follower and continuing at various tiers.</p>
</div>
</section>
<section>
<div class="yt-how inner-wrap">
<h3>Getting on LBRY is easy</h3>
<p>When you claim your channel your most recent 1,000 YouTube videos will be automatically copied to your LBRY channel.</p>
<ol>
<li>Claim your channel</li>
<li>Authorize your content</li>
<li>Users watch your content on LBRY</li>
</ol>
<div class="steps">
<div class="path">
<div class="journey"></div>
</div>
<div class="step one enabled" data-enable="12">
<div class="circle">1</div>
<p class="text">Claim your channel</p>
</div>
<div class="step two enabled" data-enable="33">
<div class="circle">2</div>
<p class="text">Authorize your content</p>
</div>
<div class="step three enabled" data-enable="75">
<div class="circle">3</div>
<p class="text">Users watch your content on LBRY</p>
</div>
</div>
</div>
</section>
<section class="align-text--center">
<div class="inner-wrap">
<h3>Sync &amp; earn</h3>
<p>LBRY offers a single-click sync process for existing YouTubers.</p>
<br/>
<div>
<button
class="button button--inverse"
data-id="scroll-to-claim"
style="font-size: 1rem;"
type="button"
>Sync now</button>
</div>
</div>
</section>
<section>
<div class="inner-wrap">
<h3>Human available</h3>
<p>Questions, problems, or feedback? A real human is available.</p>
<div class="v-card">
<figure>
<img alt="Tom Zarebczan, Community Leader" src="https://spee.ch/@lbryteam:6/tom-zarebczan.jpg"/>
</figure>
<info>
<h3>Tom Zarebczan</h3>
<p>Community Leader</p>
<a href="mailto:tom@lbry.com?subject=YouTube+Freedom">tom@lbry.com</a>
</info>
</div>
</p>
</div>
</section>
</main>

View file

@ -1,18 +0,0 @@
<?php
$status_token = Request::encodeStringFromUser($_POST['status_token']);
$channel_name = null;
if (isset($_POST['new_preferred_channel'])) {
$channel_name = Request::encodeStringFromUser($_POST['new_preferred_channel']);
}
$email = Request::encodeStringFromUser($_POST['new_email']);
$sync_consent = isset($_POST['sync_consent']);
if ($channel_name !== "" && $channel_name !== null && !preg_match("/@[A-Za-z0-9-]+$/", $channel_name)) {
$channel_name = "@" . $channel_name;
}
if ($channel_name === "") {
$channel_name = null;
}
AcquisitionActions::actionYoutubeEdit($status_token, $channel_name, $email, $sync_consent);

View file

@ -0,0 +1,267 @@
<?php
Response::addJsAsset('/js/yt2/TweenMax.min.js');
Response::addJsAsset('/js/yt2/app.js');
Response::addJsAsset('/js/yt2/FormValidation.js');
Response::addJsAsset('/js/yt2/SyncStatus.js');
Response::addJsAsset('/js/yt2/youtube_video.js');
if (in_array($_SERVER['REQUEST_URI'], ['/escapeyoutube'])) {
Response::setMetaTitle("Escape YouTube");
Response::setMetaDescription("Put your content on the LBRY blockchain before it's too late");
Response::addMetaImage('https://spee.ch/6/18OanRVGL6mQIMtj93Hb09te.jpeg');
} else {
Response::setMetaTitle("LBRY YouTube Partner Program");
Response::setMetaDescription("Put your content on the blockchain, experience true content freedom, and earn rewards.");
Response::addMetaImage(Request::getHostAndProto() . '/img/lbry-partner.png');
}
$isEnabled = true;
?>
<main class="ancillary youtube youtube--landing">
<section class="hero hero--youtube">
<div class="shape">
<svg>
<path d="M 0,0" data-from="-1"/>
<path d="M 0,0" data-from="0"/>
<path d="M 0,0" data-from="0"/>
<path d="M 0,0" data-from="1"/>
<path d="M 0,0" data-from="1"/>
<path d="M 0,0" data-from="2"/>
<path d="M 0,0" data-from="2"/>
<path d="M 0,0" data-from="2"/>
</svg>
<div class="circle one"></div>
<div class="circle two"></div>
<div class="circle three"></div>
<div class="dot a"></div>
<div class="dot b"></div>
<div class="dot c"></div>
<div class="dot d"></div>
<div class="dot e"></div>
</div>
<div class="inner-wrap inner-wrap--center-left">
<h1 class="weight-light">LBRY &times; YouTube Sync</h1>
<h2 class="weight-light">Get your YouTube videos in front of the LBRY audience</h2>
<button
class="button button--inverse"
data-id="scroll-to-claim"
style="font-size: 1rem; margin-top: 2rem;"
type="button"
>Claim your channel now</button>
</div>
</section>
<section class="align-text--center" id="claim-section">
<div class="inner-wrap">
<?php
if ($error_message): echo "<p class='error-block'>" . "The following error occurred: ". $error_message . " For support please send an email to <a href='mailto:hello@lbry.com' title='Email LBRY for help'>hello@lbry.com</a>." . "</p>";
endif;?>
<p hidden id="lbry_error" class="error-block">LBRY channel name is either not valid (only letters, numbers and - allowed, no spaces) or your input is blank</p>
<h2>Connect with your fans while earning rewards</h2>
<?php if ($isEnabled): ?>
<form id="youtube_claim" method="post" action="/youtube/token">
<p hidden id="sync-status" class="sync-status"></p>
<input-submit style="font-size: 1rem;">
<label class="symbol-prefix">@</label>
<input
id="lbry_channel_name"
name="desired_lbry_channel_name"
placeholder="Enter desired LBRY channel name (permanent)"
type="text"
/>
<input
onClick="return submitDetailsForm()"
type="submit"
value="Claim now"
/>
</input-submit>
<br/>
<checkbox-element style="font-size: 1rem;">
<input hidden name="type" type="text" value="sync"/>
<input id="immediate-sync" name="immediate_sync" type="checkbox" value="true"/>
<label for="immediate-sync">I want to sync my content to the LBRY network and agree to <a href="/faq/youtube-terms" target="_blank">these terms</a>. I have also read and understand <a href="/faq/youtube" target="_blank">how the program works</a>.</label>
<checkbox-toggle/>
</checkbox-element>
</form>
<?php else: ?>
<div class="notice notice-info spacer1">
The YouTube Program is paused for maintenance. Enter your email address and we will notify you as soon as it returns.
If you have over 10K subs on YouTube, please <a href="https://docs.google.com/forms/d/1b9bEahq1L-hWaYN0MfnBZ8d0MnM4oQpsLFG1TlBHMrI/edit">use this form</a> for a manual sync request.
</div>
<?php echo View::render('mail/_subscribeForm', [
'tag' => 'youtube_sync_paused',
'submitLabel' => 'Get Started',
'hideDisclaimer' => true,
'largeInput' => true,
'btnClass' => 'btn-alt btn-large',
]) ?>
<?php endif ?>
<small class="meta">
This will verify you are an active YouTuber. Channel names cannot be changed once chosen, please be extra careful. Additional instructions will be emailed to you after you verify your email on the next page.
<a href="/faq/youtube">Learn more</a>
</small>
</div>
</section>
<section>
<div class="join section inner-wrap">
<h3>Join great creators already on LBRY</h3>
<p>Audiences range from 1,000+ to 10,000,000+ people. The videos below are from creators who have synced their content to LBRY.</p>
<div class="ytsync-previews">
<figure class="ytsync-preview">
<video
onclick="playVideo('video1')"
id="video1"
poster="/img/youtube/01@2x.jpg"
src="https://spee.ch/1ac47b8b3def40a25850dc726a09ce23d09e7009/ever-wonder-how-bitcoin-and-other.mp4"
></video>
<figcaption>@3Blue1Brown</figcaption>
</figure>
<figure class="ytsync-preview">
<video
onclick="playVideo('video2')"
id="video2"
poster="/img/youtube/02@2x.jpg"
src="https://spee.ch/3c96f32de285db6c04e80bd6f5fad573250541e9/casually-successful.mp4"
></video>
<figcaption>@CasuallyExplained</figcaption>
</figure>
<figure class="ytsync-preview">
<video
onclick="playVideo('video3')"
id="video3"
poster="/img/youtube/03@2x.jpg"
src="https://spee.ch/8958c5d573d71f5c2d0c1bfdf752737ce39744cb/the-historical-elements-of-wolfenstein.mp4"
></video>
<figcaption>@ColinsLastStand</figcaption>
</figure>
</div>
</div>
</section>
<section>
<div class="rewards section inner-wrap">
<h3>What you earn</h3>
<br/>
<?php /*
<table>
<thead style="font-size: 80%;">
<tr>
<th>Current YouTube Subscribers</th>
<th>LBRY Credits/Year</th>
<th>USD Value <small class="meta">1 LBC = <span class="current-value"></span></small></th>
</tr>
</thead>
<tbody>
<?php foreach ($reward['data'] as $subCount => $rewardAmt): ?>
<tr>
<td><?php echo number_format($subCount) ?></td>
<td><?php echo number_format($rewardAmt * 12); //API returns per month?> <small class="meta">LBC</small></td>
<td class="lbc-to-usd" data-lbc-amount="<?php echo $rewardAmt * 12 ?>"></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<p class="align-text--center">
<small> <em>Table shows yearly awards but rewards are distributed monthly. Monthly reward will be one-twelfth the above amount. These reward amounts may change at LBRY Inc.'s discretion.</em></small>
</p>
*/ ?>
<h4>
For Views
</h4>
<p>Receive up to 2 LBC (<span class="lbc-to-usd" data-lbc-amount="2"></span>) per view from verified lbry.tv accounts. This requires at least 500 subs and original content. <a href="https://lbry.com/faq/view-rewards" target="_blank">Learn more.</a>
<small> <em>These reward amounts may change at LBRY Inc.'s discretion.</em></small>
</p>
<h4>
For Building on LBRY
</h4>
<p>You receive additional rewards for building an audience, starting with your first follower and continuing at various tiers.</p>
</div>
</section>
<section>
<div class="yt-how inner-wrap">
<h3>Getting on LBRY is easy</h3>
<p>When you claim your channel your most recent 1,000 YouTube videos will be automatically copied to your LBRY channel.</p>
<ol>
<li>Claim your channel</li>
<li>Authorize your content</li>
<li>Users watch your content on LBRY</li>
</ol>
<div class="steps">
<div class="path">
<div class="journey"></div>
</div>
<div class="step one enabled" data-enable="12">
<div class="circle">1</div>
<p class="text">Claim your channel</p>
</div>
<div class="step two enabled" data-enable="33">
<div class="circle">2</div>
<p class="text">Authorize your content</p>
</div>
<div class="step three enabled" data-enable="75">
<div class="circle">3</div>
<p class="text">Users watch your content on LBRY</p>
</div>
</div>
</div>
</section>
<section class="align-text--center">
<div class="inner-wrap">
<h3>Sync &amp; earn</h3>
<p>LBRY offers a single-click sync process for existing YouTubers.</p>
<br/>
<div>
<button
class="button button--inverse"
data-id="scroll-to-claim"
style="font-size: 1rem;"
type="button"
>Sync now</button>
</div>
</div>
</section>
<section>
<div class="inner-wrap">
<h3>Human available</h3>
<p>Questions, problems, or feedback? A real human is available.</p>
<div class="v-card">
<figure>
<img alt="Tom Zarebczan, Community Leader" src="https://spee.ch/@lbryteam:6/tom-zarebczan.jpg"/>
</figure>
<info>
<h3>Tom Zarebczan</h3>
<p>Community Leader</p>
<a href="mailto:tom@lbry.com?subject=YouTube+Freedom">tom@lbry.com</a>
</info>
</div>
</div>
</section>
</main>

View file

@ -1,232 +1,22 @@
<?php Response::setMetaDescription('YouTuber? Take back control! LBRY allows publication on your terms. It\'s open-source, decentralized, and gives you 100% of the profit.') ?>
<?php Response::setMetaTitle(__('YouTubers! Take back control.')) ?>
<?php Response::addJsAsset('/js/yt2/FormValidation.js') ?>
<?php Response::addJsAsset('/js/yt2/youtube_status.js') ?>
<?php Response::addJsAsset('/js/yt2/youtube_video.js') ?>
<?php Response::addJsAsset('//www.googleadservices.com/pagead/conversion_async.js') ?>
<?php if (!$is_disabled): ?>
<?php $statusData = $status_token['data'] ?>
<?php $isSyncAgreed = in_array($statusData['status'], ["failed", "finalized", "pendingemail", "queued", "synced", "syncing","pendingupgrade","abandoned"]) ?>
<?php $isRewardClaimed = $statusData['redeemed_reward'] > 0 ?>
<?php $isRewardable = $statusData['expected_reward'] > 0 ?>
<?php $isTransferred = $statusData['transferred'] ?>
<?php if (IS_PRODUCTION): ?>
<?php js_start() ?>
if (!localStorage.getItem('status_token')) {
ga('send', 'event', 'YT Sync', '<?php echo $isSyncAgreed ? "pending" : "queued" ?>', '');
fbq('track', 'Lead');
window.google_conversion_id = 980489749;
window.google_conversion_label = "B0ZpCIuLgV0QlazE0wM";
window.google_remarketing_only = false;
window.google_conversion_format = "3";
var opt = new Object();
var conv_handler = window['google_trackConversion'];
opt.onload_callback = function() { };
if (typeof(conv_handler) === 'function')
conv_handler(opt);
}
<?php js_end() ?>
<?php endif ?>
<?php else: ?>
<?php $isSyncAgreed = false ?>
<?php $isRewardClaimed = false ?>
<?php $isTransferred = false ?>
<?php $statusData = [
'email' => 'error@lbry.com',
'subscribers' => 101,
'editable' => false,
'status' => 'failed',
'videos' => 1,
'lbry_channel_name' => '@lbry',
'expected_reward' => 1,
'has_verified_email' => true
] ?>
<?php endif ?>
<main class="ancillary youtube">
<section class="section channel">
<div class="inner-wrap">
<?php if ($is_disabled): ?>
<div class="notice notice-error spacer1">
<p>The YouTube program is down for maintenance. It will return soon.</p>
<p>Until it is back up, you cannot edit your submission. Email <?php echo Config::HELP_CONTACT_EMAIL ?> if you need immediate assistance.</p>
<main class="ancillary">
<section class="hero hero--half-height">
<div class="inner-wrap inner-wrap--center-hero">
<h1>YouTube Sync Status</h1>
</div>
<?php endif ?>
<?php if (preg_match('/^[A-Za-z0-9._%+-]+@plusgoogle.com$/', $statusData['email'])): ?>
<p class="error-block" id="email-google-plus-error">
Your email address is set as <?php echo $statusData['email']; ?>.<br/>
If this is not your email address, please change it below.<br/>
If you have a LBRY Account, please use that email here so the accounts are merged.
</section>
<section class="section">
<div class="inner-wrap">
<p>
The YouTube sync program has been integrated into <a href="https://odysee.com">Odysee</a>.
</p>
<?php endif ?>
<p>
Please sign into <a href="https://odysee.com">odysee.com</a> using the email you joined the program with. If you accessed this page from an email, use the email address you clicked the link from.
</p>
<p>
If you encounter any problems, please contact <a href="mailto:help@lbry.com">help@lbry.com</a>.
</p>
<p><img src="https://spee.ch/9/a539dc79e6ba1b6e.jpg" /></p>
<h2><?php echo $isSyncAgreed && $isTransferred ? "You're all set!" : "Almost done!" ?></h2>
<div class="confirmation-steps">
<ul class="bulletless">
<li>
<span></span>
<p>Confirm your channel</p>
</li>
<li class="<?php echo $isSyncAgreed ? "" : "disabled" ?>">
<span><?php echo $isSyncAgreed ? "" : "·" ?></span>
<p>Agree to sync</p>
</li>
<li class="<?php echo $isTransferred && $isSyncAgreed ? "" : "disabled" ?>">
<span><?php echo $isTransferred ? "" : "·" ?></span>
<p>Claim content</p>
<p <?php echo ($isSyncAgreed === true && $isTransferred === false) ? "" : "hidden" ?>>(<a href="https://lbry.tv">Sign in to lbry.tv</a> or <a href="/get">get the app</a>)</p>
</li>
</ul>
<hr/>
</div>
<table>
<thead>
<tr>
<th>Your Sync Status</th>
<th>Subscribers</th>
<th>Videos</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<?php switch ($statusData['status']) {
case "pending":
echo __("Pending Agreement");
break;
case "pendingemail":
echo __("Pending Email Confirmation. Please refresh after confirming.");
break;
case "queued":
echo __("Queued");
break;
case "syncing":
echo __("Sync in Progress!");
break;
case "synced":
echo __("Content is Live!");
break;
case "failed":
echo __("Something went wrong, check back later!");
break;
case "finalized":
echo __("The content is in your control!");
break;
case "abandoned":
echo __("Does not qualify or cannot sync anymore!");
break;
default:
echo __("");
break;
} ?>
</td>
<td>
<?php echo $statusData['subscribers'] === 0 ? "" : $statusData['subscribers'] ?>
</td>
<td>
<?php echo $statusData['videos'] === 0 ? "" : $statusData['videos'] ?>
</td>
</tr>
</tbody>
</table>
</div>
</section>
<section class="section settings">
<div class="inner-wrap">
<form id="youtube_settings" action="/youtube/edit" method="post">
<div>
<input type="hidden" name="status_token" id="status_token" value="<?php echo $token ?>"/>
</div>
<?php if ($error_message): echo "<p class='error-block'>" . "The following error occurred: <strong>" . $error_message . "</strong> For support please send an email to hello@lbry.com" . "</p>"; endif; ?>
<fieldset>
<legend>Confirm your preferences</legend>
<p <?php echo $statusData['email']==="" ? "" : "hidden" ?> class="error-block">
You need to provide an email
</p>
<p <?php echo ($statusData['has_verified_email']===false && $statusData['email']!=="") ? "" : "hidden"?> class="error-block">
You need to verify your email! <a href="https://api.lbry.com/yt/resend_verification_email?status_token=<?php echo $token ?>&email=<?php echo $statusData['email'] ?>">Click here to resend a verification email</a>
</p>
<fieldset-group>
<fieldset-section>
<label for="channel-name">Desired LBRY Channel Name (i.e. @MyChannel)</label>
<input
type="text" id="channel-name" name="new_preferred_channel"
placeholder="@YourPreferredChannelName"
value="<?php echo $statusData['lbry_channel_name']; ?>" <?php echo $statusData['editable'] ? "" : "disabled" ?>
/>
<div hidden id="channel-name-error" class="error">Channel is invalid or blank (only letters, numbers and - allowed, no spaces)</div>
</fieldset-section>
<fieldset-section>
<label for="email">Email (use existing LBRY account if signed up)</label>
<input
type="text"
id="email"
name="new_email"
placeholder="bill@gmail.com"
value="<?php echo $statusData['email']; ?>"
/>
<div hidden id="email-error" class="error">Email is invalid or blank</div>
<div hidden id="email-google-plus-error" class="error">Google plus email addresses cannot be used</div>
</fieldset-section>
</fieldset-group>
<checkbox-element
<?php echo (($statusData['status'] === 'pending' || $statusData['status'] === 'queued') && !$statusData['transferred']) ? "" : "disabled "; ?>
<?php echo !$statusData['has_verified_email'] ? "hidden" : "" ?>
>
<input
id="sync_consent"
name="sync_consent"
type="checkbox"
<?php echo $isSyncAgreed ? "checked" : "" ?> <?php echo (($statusData['status'] === 'pending' || $statusData['status'] === 'queued') && !$statusData['transferred']) ? "" : "disabled "; ?>
/>
<label for="sync_consent" <?php echo !$statusData['has_verified_email'] ? "hidden" : "" ?>>
I want to sync my content to the LBRY network and agree to <a href="/faq/youtube-terms" target="_blank">these terms</a>. I have also read and understand <a href="/faq/youtube" target="_blank">how the program works</a>.
<p hidden id="sync-consent-error" class="error">In order to continue, you must agree to sync.</p>
</label>
<checkbox-toggle/>
</checkbox-element>
<div>
<button type="submit" onClick="return submitEditForm()">Save Changes</button>
</div>
</fieldset>
</form>
<br/><br/>
<?php if ($isSyncAgreed && !$isTransferred && in_array($statusData['status'], ['queued', 'syncing', 'synced', 'finalized', 'pendingupgrade'])): ?>
<fieldset>
<legend>Claim channel and content</legend>
<p>Just one step left! Take permanent ownership of your content after it's been synced to LBRY. You'll do this by claiming it on the Channels page of lbry.tv/Desktop</p>
<ul>
<li><a href="https://lbry.tv">On the web</a></li>
<li><a href="https://lbry.com/get">Desktop and mobile apps</a></li>
</ul>
</fieldset>
<?php endif ?>
<p>Have questions, problems, or feedback? Check out the <a href="/faq/youtube" title="YouTube FAQ">YouTube FAQ</a> or send us an <a href="mailto:hello@lbry.com">email</a>.</p>
<p><a href="/termsofservice" title="View Terms of Service">View Terms of Service</a>.</p>
</div>
</section>
</main>

View file

@ -1,9 +0,0 @@
<?php js_start() ?>
if (localStorage.getItem("status_token")) {
const status_token = localStorage.getItem("status_token");
url = "/youtube/status/" + status_token;
$(location).attr("href", url);
} else {
$(location).attr("href", "/youtube");
}
<?php js_end() ?>

View file

@ -1 +0,0 @@
<iframe width="640" height="360" src="https://api.lbry.tv/content/claims/escapeyoutube/8e0a6c66760bdcb80b296ca2e64f1832346244b8/stream" allowfullscreen></iframe>

View file

@ -10,7 +10,7 @@
<section>
<div class="inner-wrap">
<p class="align-text--center">Top priorities, definitions of success, status, and target completion dates for key initiatives in
<p>Top priorities, definitions of success, status, and target completion dates for key initiatives in
<select id="roadmap-year-select">
<?php foreach ($years as $aYear): ?>
<option value="<?php echo $aYear ?>" <?php echo $aYear == $year ? 'selected="selected"' : '' ?>>

View file

@ -57,8 +57,8 @@
<meta name="msapplication-TileImage" content="/img/fav/mstile-144x144.png"/>
<meta name="theme-color" content="#155B4A"/>
<meta name="twitter:site" content="@lbryio"/>
<meta name="twitter:creator" content="@lbryio"/>
<meta name="twitter:site" content="@lbrycom"/>
<meta name="twitter:creator" content="@lbrycom"/>
<meta name="twitter:description" content="<?php echo Response::getMetaDescription() ?>"/>
<meta name="twitter:title" content="<?php echo $title ?>" />
@ -68,13 +68,6 @@
<meta name="twitter:app:name:googleplay" content="LBRY beta"/>
<meta name="twitter:app:id:googleplay" content="io.lbry.browser"/>
<meta name="twitter:app:url:googleplay" content="https://play.google.com/store/apps/details?id=io.lbry.browser"/>
<?php elseif (in_array($_SERVER['REQUEST_URI'], ['/escapeyoutube'])): ?>
<meta name="twitter:card" content="player">
<meta name="twitter:player" content="https://lbry.com/escapeyoutubeiframe" />
<meta name="twitter:player:width" content="640" />
<meta name="twitter:player:height" content="360" />
<meta name="twitter:player:stream" content="https://api.lbry.tv/content/claims/escapeyoutube/8e0a6c66760bdcb80b296ca2e64f1832346244b8/stream" />
<meta name="twitter:player:stream:content_type" content="video/mp4" />
<?php else: ?>
<meta name="twitter:card" content="summary_large_image">
<?php endif ?>

View file

@ -1,20 +0,0 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient fy="0" gradientTransform="rotate(60 0.5 0.5)" id="gradient">
<stop offset="0" stop-color="#60e1ba"></stop>
<stop offset="0" stop-color="#339af0">
<animate
attributeName="offset"
dur="25s"
from="0"
repeatCount="indefinite"
to="1"
values="0;0;1;1;0"
/>
</stop>
<stop offset="1" stop-color="#60e1ba"/>
</linearGradient>
</defs>
<path d="m0 10.926 2.805 7.707 7.442-2.709-6.659-6.304zm20.684 6.837-1.684-1.263v-3.762l3.683-1.341c1.038-.378 1.573-1.525 1.195-2.563l-2.736-7.518c-.378-1.038-1.525-1.573-2.563-1.195l-15.973 5.815 9.742 9.224 4.652-1.694v4.034l3.023 2.268c-.004.078-.023.152-.023.232 0 2.209 1.791 4 4 4v-8c-1.38 0-2.598.699-3.316 1.763z" fill="url(#gradient)"/>
</svg>

Before

Width:  |  Height:  |  Size: 878 B

View file

@ -1,20 +0,0 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient fy="0" gradientTransform="rotate(60 0.5 0.5)" id="gradient">
<stop offset="0" stop-color="#60e1ba"></stop>
<stop offset="0" stop-color="#339af0">
<animate
attributeName="offset"
dur="25s"
from="0"
repeatCount="indefinite"
to="1"
values="0;0;1;1;0"
/>
</stop>
<stop offset="1" stop-color="#60e1ba"/>
</linearGradient>
</defs>
<path d="m12 6c-.552 0-1 .448-1 1v5h-3c-.552 0-1 .448-1 1s.448 1 1 1h5v-7c0-.552-.448-1-1-1zm0-6c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm0 21c-4.97 0-9-4.03-9-9 0-4.971 4.03-9 9-9 4.971 0 9 4.029 9 9 0 4.97-4.029 9-9 9z" fill="url(#gradient)"/>
</svg>

Before

Width:  |  Height:  |  Size: 806 B

View file

@ -1,20 +0,0 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient fy="0" gradientTransform="rotate(60 0.5 0.5)" id="gradient">
<stop offset="0" stop-color="#60e1ba"></stop>
<stop offset="0" stop-color="#339af0">
<animate
attributeName="offset"
dur="25s"
from="0"
repeatCount="indefinite"
to="1"
values="0;0;1;1;0"
/>
</stop>
<stop offset="1" stop-color="#60e1ba"/>
</linearGradient>
</defs>
<path d="m17 15.012v1.988h-3.08l-4.286-5 4.286-5h3.08v1.988c0 .9 1.185 1.35 1.878.714l5.122-4.702-5.122-4.702c-.693-.636-1.878-.186-1.878.714v1.988h-4.92l-6 7h-4.08c-1.105 0-2 .895-2 2 0 1.104.895 2 2 2h4.08l6 7h4.92v1.988c0 .9 1.185 1.35 1.878.714l5.122-4.702-5.122-4.702c-.693-.636-1.878-.186-1.878.714z" fill="url(#gradient)"/>
</svg>

Before

Width:  |  Height:  |  Size: 862 B

View file

@ -1,20 +0,0 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient fy="0" gradientTransform="rotate(60 0.5 0.5)" id="gradient">
<stop offset="0" stop-color="#60e1ba"></stop>
<stop offset="0" stop-color="#339af0">
<animate
attributeName="offset"
dur="25s"
from="0"
repeatCount="indefinite"
to="1"
values="0;0;1;1;0"
/>
</stop>
<stop offset="1" stop-color="#60e1ba"/>
</linearGradient>
</defs>
<path d="m12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-4.5 8c.828 0 1.5.672 1.5 1.5s-.672 1.5-1.5 1.5-1.5-.672-1.5-1.5.672-1.5 1.5-1.5zm10.197 8.717c-1.515 1.472-3.539 2.283-5.697 2.283s-4.182-.811-5.697-2.283c-.396-.385-.405-1.018-.02-1.414.384-.395 1.018-.405 1.414-.02 1.14 1.108 2.668 1.717 4.303 1.717s3.163-.609 4.303-1.717c.396-.386 1.03-.375 1.414.02.386.396.376 1.029-.02 1.414zm-1.197-5.717c-.828 0-1.5-.672-1.5-1.5s.672-1.5 1.5-1.5 1.5.672 1.5 1.5-.672 1.5-1.5 1.5z" fill="url(#gradient)"/>
</svg>

Before

Width:  |  Height:  |  Size: 1 KiB

View file

@ -1,77 +0,0 @@
var is_first_time = true;
function submitEditForm() {
$("#youtube_settings").submit(function (event) {
// get value from id
var lbry_channel_name = $.trim($('#channel-name').val());
var email = $.trim($('#email').val());
// Hide the error message
$('#channel-name-error').hide();
$('#email-error').hide();
// If the channel name is invalid or blank stop the post request
if (!validateLBRYName(lbry_channel_name) || lbry_channel_name === '') {
$('#lbry_channel_name').addClass('error_form');
$('#channel-name-error').show();
event.preventDefault();
}
if (!validateEmail(email) || email === '') {
$('#email').addClass('error_form');
$('#email-error').show();
event.preventDefault();
}
else if (!validateEmailIsNotGooglePlus(email)) {
$('#email').addClass('error_form');
if (is_first_time) {
$('#email').addClass('error_form');
$('#email-google-plus-error').show();
is_first_time = false;
event.preventDefault()
}
}
localStorage.setItem("status_token", $.trim($('#status_token').val()));
localStorage.setItem("lbry_channel_name_sync", $.trim($('#channel-name').val()));
});
}
function submitDetailsForm() {
$("#youtube_claim").submit(function (event) {
// get value from id
var lbry_channel_name = $.trim($('#lbry_channel_name').val());
// Make sure that the error message are hidden before trying to validate value
$('#lbry_error').hide();
// If the lbry name is invalid or blank stop the post request
if (!validateLBRYName(lbry_channel_name) || lbry_channel_name === '') {
$('#lbry_channel_name').addClass('error_form');
$('#lbry_error').show();
event.preventDefault();
}
});
}
function validateEmail(email) {
var re = /\S+@\S+\.\S+/;
return re.test(email);
}
function validateLBRYName(lbry_channel_name) {
var re = /^[@A-Za-z0-9-]*$/g;
return re.test(lbry_channel_name);
}
function validateYoutubeChannelUrl(youtube_channel_url) {
var re = /^UC[A-Za-z0-9_-]{22}$/;
return re.test(youtube_channel_url);
}
function validateEmailIsNotGooglePlus(email) {
var re = /^[A-Za-z0-9._%+-]+@(?!plusgoogle.com)[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/;
return re.test(email);
}

View file

@ -1,10 +0,0 @@
$(document).ready(function () {
var status_token = localStorage.getItem("status_token");
var lbry_channel_name_sync = localStorage.getItem("lbry_channel_name_sync");
if (status_token || lbry_channel_name_sync) {
var url = "/youtube/status/" + status_token;
$("#sync-status").show();
$("#sync-status").html("Hey, " + lbry_channel_name_sync + "! " + "<a href='" + url + "'>" + "See your channel sync status here</a>.");
}
});

View file

@ -38,64 +38,10 @@ App.prototype._onLoad = function() {
this._lines.push(l);
}, this);
// Section how
this._how = document.getElementsByClassName("yt-how")[0];
this._percent = 0;
this._offset = 100;
this._journey = this._how.getElementsByClassName("journey")[0];
this._steps = Array.prototype.slice.call(this._how.getElementsByClassName("step"), 0);
this._start = this._how.offsetTop - this._how.scrollTop - window.innerHeight / 2 - this._offset;
this._end = this._start + window.innerHeight / 2;
// XHR request
this._getDataFromCoinMarketCap();
// Binding events
this._bindEvents();
};
App.prototype._getDataFromCoinMarketCap = function(e) {
this._xhr = new XMLHttpRequest();
this._xhr.addEventListener("readystatechange", this._onReadyStateChange.bind(this), false);
this._xhr.open("GET", "https://api.lbry.com/lbc/exchange_rate");
this._xhr.send();
};
App.prototype._onReadyStateChange = function(e) {
if (this._xhr.readyState === 4) {
if (this._xhr.status === 200) {
const response = JSON.parse(this._xhr.responseText);
const lines = document.querySelectorAll(".lbc-to-usd");
const price = parseFloat(response.data.lbc_usd);
lines.forEach(function(line) {
const amount = line.dataset.lbcAmount;
const total = amount * price; //api returns per month
line.innerHTML = this._addCommas(total.toFixed(2)) + " <small class='meta'>USD</small>";
}, this);
document.getElementsByClassName("current-value")[0].innerHTML = `$${price.toFixed(4)} USD`;
}
}
};
App.prototype._addCommas = function(nStr) {
nStr += "";
const rgx = /(\d+)(\d{3})/;
const x = nStr.split(".");
const x2 = x.length > 1 ?
"." + x[1] :
"";
let x1 = x[0];
while (rgx.test(x1))
x1 = x1.replace(rgx, "$1" + "," + "$2");
return x1 + x2;
};
App.prototype._bindEvents = function() {
TweenMax.ticker.addEventListener("tick", this._onTick.bind(this));
this._elem.addEventListener("resize", this._onResize.bind(this), false);
@ -247,37 +193,3 @@ Line.prototype.draw = function(from, to) {
// Let's start :)
new App();
// Clicking CTAs introduces a smooth scroll to the appropriate section
const youtubeCtas = document.querySelectorAll("[data-id='scroll-to-claim']");
youtubeCtas.forEach(cta => {
cta.onclick = () => {
const element = document.getElementById("claim-section");
const elementOffset = element.offsetTop - 2;
window.scroll({ top: elementOffset, behavior: "smooth" });
setTimeout(() => { // give the scroll time to finish before focusing
document.getElementById("lbry_channel_name").focus();
}, 300);
};
});
// Scroll to error messages if they exist
window.addEventListener("load", (event) => {
const youtubeErrors = document.querySelectorAll(".error-block");
youtubeErrors.forEach(error => {
if (!error.hidden) {
const errorDivOffset = error.offsetTop;
window.scroll({ top: errorDivOffset });
return;
}
});
});

View file

@ -1,14 +0,0 @@
$("#scroll_email").click(function () {
$('html, body').animate({
scrollTop: $("#email").offset().top
}, 2000);
$('#email').select();
$("#email").focus();
});
$("#scroll-sync").click(function () {
$('html, body').animate({
scrollTop: $("#sync-consent").offset().top
}, 2000);
});

View file

@ -1,10 +0,0 @@
"use strict";
function playVideo(id) {
const video = document.getElementById(id);
video.play();
video.controls = true;
}

View file

@ -27,9 +27,7 @@ h2,
h3,
h4,
h5 {
&:not(.weight-light):not(.weight-normal) {
font-weight: 600;
}
font-weight: 600;
&.weight-light {
font-weight: 200;
@ -198,10 +196,6 @@ input::placeholder {
}
}
.align-text--center {
text-align: center;
}
.inner-wrap {
max-width: 1200px;
margin-right: auto;

View file

@ -271,29 +271,4 @@
margin-top: 1.25rem;
}
}
.button {
+ h2,
+ h3 { // join-us page
padding-top: 3.25rem;
}
}
.inline-image-and-text {
align-items: center;
display: flex;
justify-content: space-between;
margin-bottom: 3rem;
> *:not(.inline-image) {
flex: 1;
padding-right: 1rem;
padding-left: 1rem;
}
}
.inline-image {
width: 5rem; height: 5rem;
margin: 0; padding: 1rem;
}
}

View file

@ -1,100 +1,5 @@
$lbry-yt-blue: mix($lbry-blue-5, $lbry-black, 50%);
.ytsync-previews {
display: flex;
justify-content: space-between;
padding-top: 1.25rem;
@media (max-width: 950px) {
flex-direction: column;
}
}
.ytsync-preview {
position: relative;
@media (min-width: 951px) {
width: 33%;
}
&:not(:hover) {
&::before {
opacity: 0;
}
}
&:hover {
&::before {
opacity: 1;
}
}
&::before {
width: 0; height: 0;
border-top: 2rem solid transparent;
border-bottom: 2rem solid transparent;
border-left: 3.5rem solid var(--lbry-white);
content: "";
pointer-events: none;
position: absolute;
top: calc(50% - 3rem);
transition: opacity 0.2s;
}
video {
cursor: pointer;
margin-bottom: 0.5rem;
}
}
.v-card {
display: flex;
figure {
margin-bottom: 0;
margin-right: 1.25rem;
width: 12rem;
}
info {
display: block;
padding-top: 4rem;
}
}
.error-block,
.sync-status {
margin: 0 auto 0.5rem; padding: 0.5rem 0.75rem;
border-style: solid;
border-width: 1px;
font-size: 0.8rem;
@media (min-width: 951px) {
max-width: 80%;
}
}
.error-block {
background-color: var(--lbry-red-4);
border-color: var(--lbry-red-5);
color: var(--lbry-white);
a {
color: inherit !important;
font-weight: 600;
}
}
.sync-status {
background-color: rgba($lbry-black, 0.05);
border-color: var(--lbry-gray-3);
}
.hero--youtube {
.shape {
width: 100%; height: 100%;
@ -188,264 +93,3 @@ $lbry-yt-blue: mix($lbry-blue-5, $lbry-black, 50%);
}
}
}
.youtube {
&.youtube--landing {
section {
&:nth-child(odd) {
background-color: rgba($lbry-black, 0.05);
}
}
input-submit {
margin-right: auto;
margin-left: auto;
@media (min-width: 951px) {
max-width: 80%;
}
}
}
.channel {
h2 {
@media (min-width: 951px) {
text-align: center;
}
}
}
.confirmation-steps {
padding-top: 1rem;
ul {
display: flex;
margin-bottom: 3rem;
@media (min-width: 951px) {
flex-direction: row;
}
@media (max-width: 950px) {
flex-direction: column;
}
}
li {
@media (min-width: 951px) {
text-align: center;
width: 33%;
}
@media (max-width: 950px) {
width: 100%;
&:not(:last-of-type) {
margin-bottom: 1rem;
}
}
&:not(.disabled) {
span {
background-color: var(--lbry-teal-3);
padding-top: 0.5rem;
}
}
&.disabled {
span {
background-color: var(--lbry-gray-3);
padding-top: 0.5rem;
// Mobile Safari override
@media not all and (min-resolution: 0.001dpcm) {
font-size: 1rem;
padding-top: 1rem;
}
}
}
p {
@media (max-width: 950px) {
display: inline-block;
position: relative;
top: -0.3rem;
}
}
span {
width: 3rem; height: 3rem;
border-radius: 50%;
color: var(--lbry-white);
cursor: default;
font-size: 2rem;
line-height: 1;
text-align: center;
@media (min-width: 951px) {
display: block;
margin: 0 auto 0.5rem;
}
@media (max-width: 950px) {
display: inline-block;
margin-right: 0.5rem;
}
}
}
}
section {
&.hero {
margin-bottom: 0;
}
&:not(.hero) {
margin-bottom: 0;
padding-top: 3rem;
padding-bottom: 3rem;
}
}
fieldset-group {
@media (max-width: 950px) {
flex-direction: column;
fieldset-section {
width: 100%;
}
}
}
checkbox-element {
&[disabled] {
checkbox-toggle {
border-color: initial;
opacity: 0.3;
}
label {
opacity: 0.3;
a {
pointer-events: initial;
}
}
}
&[hidden] {
display: none;
}
}
}
.yt-how {
ol {
@media (min-width: 951px) {
display: none;
}
}
.steps {
width: 100%; height: 260px;
margin-top: 80px;
position: relative;
@media (max-width: 950px) {
display: none;
}
.journey,
.path {
background-position: 0 0;
background-repeat: no-repeat;
background-size: 752px;
height: 287px;
position: absolute;
}
.journey {
top: 0; left: 0;
background-image: url("../img/youtube/path-complete@2x.png");
overflow: hidden;
width: 120px;
}
.path {
top: -52px; left: 0;
background-image: url("../img/youtube/path@2x.png");
width: 752px;
}
}
.step {
position: absolute;
&.enabled {
.circle {
background-color: var(--lbry-gray-5);
}
.text {
color: var(--lbry-gray-5);
}
}
&.one {
top: 0; left: 60px;
.text {
width: 226px;
}
}
&.two {
top: 160px; left: 225px;
.text {
width: 552px;
}
}
&.three {
top: 0; left: 550px;
.text {
width: 390px;
}
}
.circle {
width: 62px; height: 62px;
top: 0; left: 0;
background-color: $lbry-yt-blue;
border-radius: 50%;
box-shadow: 0 20px 50px 0 rgba($lbry-black, 0.15);
color: var(--lbry-white);
font-size: 24px;
font-weight: 600;
line-height: 62px;
position: absolute;
text-align: center;
transition: background-color 0.4s;
}
.text {
top: 0; left: 82px;
color: $lbry-yt-blue;
font-size: 18px;
font-weight: 600;
line-height: 3.4;
position: absolute;
transition: color 0.4s;
}
}
}