mirror of
https://github.com/MarshalX/telegram-crawler.git
synced 2025-03-14 04:51:42 +01:00
Update content of files
This commit is contained in:
parent
3143f1578a
commit
40d0a6f339
28 changed files with 39897 additions and 0 deletions
229
data/web/promote.telegram.org.html
Normal file
229
data/web/promote.telegram.org.html
Normal file
|
@ -0,0 +1,229 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Telegram Ads</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="MobileOptimized" content="176" />
|
||||
<meta name="HandheldFriendly" content="True" /><meta name="twitter:card" content="summary"></meta>
|
||||
<meta property="og:title" content="Telegram Ad Platform">
|
||||
<meta property="og:description" content="The Telegram Ad Platform is a privacy-conscious tool to create sponsored messages in public one-to-many channels with 1000+ subscribers.">
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="/img/website_icon.svg?4">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
|
||||
<link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" />
|
||||
<script>document.cookie="stel_dt="+encodeURIComponent((new Date).getTimezoneOffset())+";path=/;max-age=31536000;samesite=None;secure"</script>
|
||||
|
||||
<link href="//telegram.org/css/font-roboto.css?1" rel="stylesheet" type="text/css">
|
||||
<link href="//telegram.org/css/bootstrap.min.css?3" rel="stylesheet">
|
||||
<link href="//telegram.org/css/bootstrap-extra.css?2" rel="stylesheet">
|
||||
<link href="/css/telegram.css?236" rel="stylesheet">
|
||||
<link href="/css/widget-frame.css?67" rel="stylesheet">
|
||||
<link href="/css/promote.css?84" rel="stylesheet">
|
||||
<link href="/css/jquery-ui.min.css?1" rel="stylesheet">
|
||||
<link href="/css/tchart.min.css?10" rel="stylesheet">
|
||||
|
||||
</head>
|
||||
<body class="emoji_image no-transition">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
|
||||
<defs>
|
||||
<path id="icon-currency-ton" d="m2.68 4h10.63c.22 0 .4.18.4.41 0 .07-.01.14-.05.2l-5.04 9.08c-.22.4-.72.54-1.11.32-.14-.08-.25-.19-.32-.33l-4.87-9.08c-.1-.2-.03-.45.17-.55.06-.03.12-.05.19-.05zm5.32 9.78v-9.78z" fill="none" stroke="currentColor" stroke-width="1.3"/>
|
||||
</defs>
|
||||
</svg>
|
||||
<div id="aj_progress" class="progress-bar"></div>
|
||||
|
||||
<div id="aj_content"><div class="pr-container pr-main">
|
||||
<section class="pr-content">
|
||||
<div class="pr-main-content-new">
|
||||
<div class="pr-main-intro">
|
||||
<img class="pr-main-intro-img" src="/img/AdsIntro.png" width="360" height="200">
|
||||
<h1 class="pr-main-intro-header">Telegram Ads</h1>
|
||||
<p class="pr-main-intro-text">Every month, <b>900 million</b> Telegram users generate <b>1 trillion views</b> in public broadcast channels.<br/><br/>Anyone can display ads in specific <b>Telegram broadcast channels</b> — using this platform.</p>
|
||||
<div class="pr-main-intro-button-wrap">
|
||||
<a href="/auth" class="btn pr-btn login-link">
|
||||
Log in to Start Advertizing
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-features">
|
||||
<div class="pr-main-feature icon-feature1">
|
||||
<div class="pr-main-feature-title">
|
||||
Precise and Efficient
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
You can define specific channels where you want to show your ads to ensure the context is relevant.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-feature2">
|
||||
<div class="pr-main-feature-title">
|
||||
Privacy-Conscious
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
Ads on Telegram do not rely on users' personal information and are based on the channels where they are shown.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-feature3">
|
||||
<div class="pr-main-feature-title">
|
||||
Beneficial For Content Creators
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
50% of the revenue from Telegram Ads goes to the owners of channels where they are displayed.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-feature4">
|
||||
<div class="pr-main-feature-title">
|
||||
Easy to Set Up
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
All it takes is to type up to 160 characters, add a Telegram link to promote, and specify the channels in which to place your ad.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-before icon-feature5">
|
||||
<div class="pr-main-feature-title">
|
||||
Paid with Cryptocurrency
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
You can pay for your ad with TON — a cryptocurrency Telegram uses for its high speed and low commissions.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div><div class="popup-container login-popup-container hide" id="login-popup-container">
|
||||
<div class="popup">
|
||||
<div class="popup-body">
|
||||
<section>
|
||||
<h2>Log In</h2>
|
||||
<p>Log in here to manage your ads. Please enter your <b>phone number</b> in the <a target="_blank" rel="noopener" href="https://telegram.org/faq#login-and-sms">international format</a> and we will send a confirmation message to your account via Telegram.</p>
|
||||
|
||||
<form id="send-form" class="login-form">
|
||||
<div class="form-group">
|
||||
<input type="tel" class="form-control pr-form-control input-lg" id="phone-number" placeholder="+12223334455" autocomplete="off"/>
|
||||
</div>
|
||||
<div class="popup-buttons">
|
||||
<a class="btn btn-link btn-lg login-cancel-btn">Cancel</a><button type="submit" class="btn btn-link btn-lg">Next</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="login-form" class="hide">
|
||||
<div class="form-group">
|
||||
<span class="form-control pr-form-control input input-lg input-disabled"><strong id="phone-number-field"></strong> (<a class="login-back" href="/auth">Incorrect?</a>)</span>
|
||||
<p class="help-block dots-animated">We've just sent you a message.<br/>Please confirm access via Telegram</p>
|
||||
</div>
|
||||
<div class="popup-buttons">
|
||||
<a class="btn btn-link btn-lg login-cancel-btn">Cancel</a><a class="btn btn-link btn-lg login-back">Back</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
<script src="//telegram.org/js/jquery.min.js?1"></script>
|
||||
<script src="//telegram.org/js/bootstrap.min.js"></script>
|
||||
<script src="//telegram.org/js/main-aj.js?68"></script>
|
||||
<script src="/js/main.js?47"></script>
|
||||
<script src="/js/widget-frame.js?62"></script>
|
||||
<script src="/js/promote.js?81"></script>
|
||||
<script src="/js/jquery-ui.min.js?1"></script>
|
||||
<script src="/js/jquery-ex.js?18"></script>
|
||||
<script src="/js/tchart.min.js?18"></script>
|
||||
<script src="/js/health.js?19"></script>
|
||||
<script src="/js/tgsticker.js?31"></script>
|
||||
|
||||
<script>ajInit({"version":985,"apiUrl":"\/api?hash=telegram-crawler","unauth":true});</script>
|
||||
<script id="aj_script">l.add({"WEB_AB_WARNING_HEADER":"Turn off ad blocker","WEB_POPUP_CLOSE_BTN":"Close","WEB_AB_WARNING_TEXT":"You appear to be using an ad blocker that may prevent pages on the Telegram Ad Platform from working as expected.<br\/><br\/>Please turn off your ad blocker or add <a href=\"http:\/\/promote.telegram.org\/\">promote.telegram.org<\/a> as an exception to manage your promoted messages."});
|
||||
Ads.init();
|
||||
Aj.onLoad(function(state) {
|
||||
function requestConfirmation(event) {
|
||||
event && event.preventDefault();
|
||||
var phone = $('#phone-number').val();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/auth/request',
|
||||
data: {
|
||||
phone: phone
|
||||
},
|
||||
success: function(result) {
|
||||
$('#phone-number-field').text(phone);
|
||||
$('#send-form').addClass('hide');
|
||||
$('#login-form').removeClass('hide');
|
||||
checkAuth(result.temp_session);
|
||||
},
|
||||
error: function(xhr) {
|
||||
showAlert(xhr.responseText || 'Server error');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
function cancelConfirmation(event) {
|
||||
event && event.preventDefault();
|
||||
$('#phone-number-field').text('');
|
||||
$('#send-form').removeClass('hide');
|
||||
$('#login-form').addClass('hide');
|
||||
$('#phone-number').focus();
|
||||
clearTimeout(window.authTimeout);
|
||||
return false;
|
||||
}
|
||||
function checkAuth(temp_session) {
|
||||
clearTimeout(window.authTimeout);
|
||||
window.authTimeout = setTimeout(function doCheckAuth() {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/auth/login',
|
||||
data: {
|
||||
temp_session: temp_session
|
||||
},
|
||||
success: function(result) {
|
||||
if (result) {
|
||||
location.reload();
|
||||
} else {
|
||||
checkAuth(temp_session);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
showAlert(xhr.responseText || 'Server error');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
}, 700);
|
||||
}
|
||||
$('#login-popup-container').on('popup:open', function() {
|
||||
$('#phone-number').focus();
|
||||
});
|
||||
$('#login-popup-container').on('popup:close', function() {
|
||||
cancelConfirmation();
|
||||
if (location.pathname == '/auth') {
|
||||
window.history && history.replaceState(null, null, '/');
|
||||
}
|
||||
});
|
||||
$('#login-popup-container #send-form').on('submit', requestConfirmation);
|
||||
$('#login-popup-container .login-cancel-btn').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
closePopup('#login-popup-container');
|
||||
});
|
||||
$('#login-popup-container .login-back').on('click', cancelConfirmation);
|
||||
$('.login-link').on('click', function(e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
openPopup('#login-popup-container');
|
||||
});
|
||||
});
|
||||
Aj.onUnload(function(state) {
|
||||
$('#login-popup-container').off('popup:open');
|
||||
$('#login-popup-container').off('popup:close');
|
||||
$('#login-popup-container #send-form').off('submit');
|
||||
$('#login-popup-container .login-cancel-btn').off('click');
|
||||
$('#login-popup-container .login-back').off('click');
|
||||
$('.login-link').off('click');
|
||||
});
|
||||
</script>
|
||||
<script>Aj.pageLoaded();</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
230
data/web/promote.telegram.org/auth.html
Normal file
230
data/web/promote.telegram.org/auth.html
Normal file
|
@ -0,0 +1,230 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Telegram Ads</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="MobileOptimized" content="176" />
|
||||
<meta name="HandheldFriendly" content="True" /><meta name="twitter:card" content="summary"></meta>
|
||||
<meta property="og:title" content="Telegram Ad Platform">
|
||||
<meta property="og:description" content="The Telegram Ad Platform is a privacy-conscious tool to create sponsored messages in public one-to-many channels with 1000+ subscribers.">
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="/img/website_icon.svg?4">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
|
||||
<link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" />
|
||||
<script>document.cookie="stel_dt="+encodeURIComponent((new Date).getTimezoneOffset())+";path=/;max-age=31536000;samesite=None;secure"</script>
|
||||
|
||||
<link href="//telegram.org/css/font-roboto.css?1" rel="stylesheet" type="text/css">
|
||||
<link href="//telegram.org/css/bootstrap.min.css?3" rel="stylesheet">
|
||||
<link href="//telegram.org/css/bootstrap-extra.css?2" rel="stylesheet">
|
||||
<link href="/css/telegram.css?236" rel="stylesheet">
|
||||
<link href="/css/widget-frame.css?67" rel="stylesheet">
|
||||
<link href="/css/promote.css?84" rel="stylesheet">
|
||||
<link href="/css/jquery-ui.min.css?1" rel="stylesheet">
|
||||
<link href="/css/tchart.min.css?10" rel="stylesheet">
|
||||
|
||||
</head>
|
||||
<body class="emoji_image no-transition">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
|
||||
<defs>
|
||||
<path id="icon-currency-ton" d="m2.68 4h10.63c.22 0 .4.18.4.41 0 .07-.01.14-.05.2l-5.04 9.08c-.22.4-.72.54-1.11.32-.14-.08-.25-.19-.32-.33l-4.87-9.08c-.1-.2-.03-.45.17-.55.06-.03.12-.05.19-.05zm5.32 9.78v-9.78z" fill="none" stroke="currentColor" stroke-width="1.3"/>
|
||||
</defs>
|
||||
</svg>
|
||||
<div id="aj_progress" class="progress-bar"></div>
|
||||
|
||||
<div id="aj_content"><div class="pr-container pr-main">
|
||||
<section class="pr-content">
|
||||
<div class="pr-main-content-new">
|
||||
<div class="pr-main-intro">
|
||||
<img class="pr-main-intro-img" src="/img/AdsIntro.png" width="360" height="200">
|
||||
<h1 class="pr-main-intro-header">Telegram Ads</h1>
|
||||
<p class="pr-main-intro-text">Every month, <b>900 million</b> Telegram users generate <b>1 trillion views</b> in public broadcast channels.<br/><br/>Anyone can display ads in specific <b>Telegram broadcast channels</b> — using this platform.</p>
|
||||
<div class="pr-main-intro-button-wrap">
|
||||
<a href="/auth" class="btn pr-btn login-link">
|
||||
Log in to Start Advertizing
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-features">
|
||||
<div class="pr-main-feature icon-feature1">
|
||||
<div class="pr-main-feature-title">
|
||||
Precise and Efficient
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
You can define specific channels where you want to show your ads to ensure the context is relevant.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-feature2">
|
||||
<div class="pr-main-feature-title">
|
||||
Privacy-Conscious
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
Ads on Telegram do not rely on users' personal information and are based on the channels where they are shown.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-feature3">
|
||||
<div class="pr-main-feature-title">
|
||||
Beneficial For Content Creators
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
50% of the revenue from Telegram Ads goes to the owners of channels where they are displayed.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-feature4">
|
||||
<div class="pr-main-feature-title">
|
||||
Easy to Set Up
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
All it takes is to type up to 160 characters, add a Telegram link to promote, and specify the channels in which to place your ad.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-before icon-feature5">
|
||||
<div class="pr-main-feature-title">
|
||||
Paid with Cryptocurrency
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
You can pay for your ad with TON — a cryptocurrency Telegram uses for its high speed and low commissions.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div><div class="popup-container login-popup-container hide" id="login-popup-container">
|
||||
<div class="popup">
|
||||
<div class="popup-body">
|
||||
<section>
|
||||
<h2>Log In</h2>
|
||||
<p>Log in here to manage your ads. Please enter your <b>phone number</b> in the <a target="_blank" rel="noopener" href="https://telegram.org/faq#login-and-sms">international format</a> and we will send a confirmation message to your account via Telegram.</p>
|
||||
|
||||
<form id="send-form" class="login-form">
|
||||
<div class="form-group">
|
||||
<input type="tel" class="form-control pr-form-control input-lg" id="phone-number" placeholder="+12223334455" autocomplete="off"/>
|
||||
</div>
|
||||
<div class="popup-buttons">
|
||||
<a class="btn btn-link btn-lg login-cancel-btn">Cancel</a><button type="submit" class="btn btn-link btn-lg">Next</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="login-form" class="hide">
|
||||
<div class="form-group">
|
||||
<span class="form-control pr-form-control input input-lg input-disabled"><strong id="phone-number-field"></strong> (<a class="login-back" href="/auth">Incorrect?</a>)</span>
|
||||
<p class="help-block dots-animated">We've just sent you a message.<br/>Please confirm access via Telegram</p>
|
||||
</div>
|
||||
<div class="popup-buttons">
|
||||
<a class="btn btn-link btn-lg login-cancel-btn">Cancel</a><a class="btn btn-link btn-lg login-back">Back</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
<script src="//telegram.org/js/jquery.min.js?1"></script>
|
||||
<script src="//telegram.org/js/bootstrap.min.js"></script>
|
||||
<script src="//telegram.org/js/main-aj.js?68"></script>
|
||||
<script src="/js/main.js?47"></script>
|
||||
<script src="/js/widget-frame.js?62"></script>
|
||||
<script src="/js/promote.js?81"></script>
|
||||
<script src="/js/jquery-ui.min.js?1"></script>
|
||||
<script src="/js/jquery-ex.js?18"></script>
|
||||
<script src="/js/tchart.min.js?18"></script>
|
||||
<script src="/js/health.js?19"></script>
|
||||
<script src="/js/tgsticker.js?31"></script>
|
||||
|
||||
<script>ajInit({"version":985,"apiUrl":"\/api?hash=telegram-crawler","unauth":true});</script>
|
||||
<script id="aj_script">l.add({"WEB_AB_WARNING_HEADER":"Turn off ad blocker","WEB_POPUP_CLOSE_BTN":"Close","WEB_AB_WARNING_TEXT":"You appear to be using an ad blocker that may prevent pages on the Telegram Ad Platform from working as expected.<br\/><br\/>Please turn off your ad blocker or add <a href=\"http:\/\/promote.telegram.org\/\">promote.telegram.org<\/a> as an exception to manage your promoted messages."});
|
||||
openPopup('#login-popup-container');
|
||||
Ads.init();
|
||||
Aj.onLoad(function(state) {
|
||||
function requestConfirmation(event) {
|
||||
event && event.preventDefault();
|
||||
var phone = $('#phone-number').val();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/auth/request',
|
||||
data: {
|
||||
phone: phone
|
||||
},
|
||||
success: function(result) {
|
||||
$('#phone-number-field').text(phone);
|
||||
$('#send-form').addClass('hide');
|
||||
$('#login-form').removeClass('hide');
|
||||
checkAuth(result.temp_session);
|
||||
},
|
||||
error: function(xhr) {
|
||||
showAlert(xhr.responseText || 'Server error');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
function cancelConfirmation(event) {
|
||||
event && event.preventDefault();
|
||||
$('#phone-number-field').text('');
|
||||
$('#send-form').removeClass('hide');
|
||||
$('#login-form').addClass('hide');
|
||||
$('#phone-number').focus();
|
||||
clearTimeout(window.authTimeout);
|
||||
return false;
|
||||
}
|
||||
function checkAuth(temp_session) {
|
||||
clearTimeout(window.authTimeout);
|
||||
window.authTimeout = setTimeout(function doCheckAuth() {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/auth/login',
|
||||
data: {
|
||||
temp_session: temp_session
|
||||
},
|
||||
success: function(result) {
|
||||
if (result) {
|
||||
location.reload();
|
||||
} else {
|
||||
checkAuth(temp_session);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
showAlert(xhr.responseText || 'Server error');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
}, 700);
|
||||
}
|
||||
$('#login-popup-container').on('popup:open', function() {
|
||||
$('#phone-number').focus();
|
||||
});
|
||||
$('#login-popup-container').on('popup:close', function() {
|
||||
cancelConfirmation();
|
||||
if (location.pathname == '/auth') {
|
||||
window.history && history.replaceState(null, null, '/');
|
||||
}
|
||||
});
|
||||
$('#login-popup-container #send-form').on('submit', requestConfirmation);
|
||||
$('#login-popup-container .login-cancel-btn').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
closePopup('#login-popup-container');
|
||||
});
|
||||
$('#login-popup-container .login-back').on('click', cancelConfirmation);
|
||||
$('.login-link').on('click', function(e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
openPopup('#login-popup-container');
|
||||
});
|
||||
});
|
||||
Aj.onUnload(function(state) {
|
||||
$('#login-popup-container').off('popup:open');
|
||||
$('#login-popup-container').off('popup:close');
|
||||
$('#login-popup-container #send-form').off('submit');
|
||||
$('#login-popup-container .login-cancel-btn').off('click');
|
||||
$('#login-popup-container .login-back').off('click');
|
||||
$('.login-link').off('click');
|
||||
});
|
||||
</script>
|
||||
<script>Aj.pageLoaded();</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
229
data/web/promote.telegram.org/basics.html
Normal file
229
data/web/promote.telegram.org/basics.html
Normal file
|
@ -0,0 +1,229 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Telegram Ads</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="MobileOptimized" content="176" />
|
||||
<meta name="HandheldFriendly" content="True" /><meta name="twitter:card" content="summary"></meta>
|
||||
<meta property="og:title" content="Telegram Ad Platform">
|
||||
<meta property="og:description" content="The Telegram Ad Platform is a privacy-conscious tool to create sponsored messages in public one-to-many channels with 1000+ subscribers.">
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="/img/website_icon.svg?4">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
|
||||
<link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" />
|
||||
<script>document.cookie="stel_dt="+encodeURIComponent((new Date).getTimezoneOffset())+";path=/;max-age=31536000;samesite=None;secure"</script>
|
||||
|
||||
<link href="//telegram.org/css/font-roboto.css?1" rel="stylesheet" type="text/css">
|
||||
<link href="//telegram.org/css/bootstrap.min.css?3" rel="stylesheet">
|
||||
<link href="//telegram.org/css/bootstrap-extra.css?2" rel="stylesheet">
|
||||
<link href="/css/telegram.css?236" rel="stylesheet">
|
||||
<link href="/css/widget-frame.css?67" rel="stylesheet">
|
||||
<link href="/css/promote.css?84" rel="stylesheet">
|
||||
<link href="/css/jquery-ui.min.css?1" rel="stylesheet">
|
||||
<link href="/css/tchart.min.css?10" rel="stylesheet">
|
||||
|
||||
</head>
|
||||
<body class="emoji_image no-transition">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
|
||||
<defs>
|
||||
<path id="icon-currency-ton" d="m2.68 4h10.63c.22 0 .4.18.4.41 0 .07-.01.14-.05.2l-5.04 9.08c-.22.4-.72.54-1.11.32-.14-.08-.25-.19-.32-.33l-4.87-9.08c-.1-.2-.03-.45.17-.55.06-.03.12-.05.19-.05zm5.32 9.78v-9.78z" fill="none" stroke="currentColor" stroke-width="1.3"/>
|
||||
</defs>
|
||||
</svg>
|
||||
<div id="aj_progress" class="progress-bar"></div>
|
||||
|
||||
<div id="aj_content"><div class="pr-container pr-main">
|
||||
<section class="pr-content">
|
||||
<div class="pr-main-content-new">
|
||||
<div class="pr-main-intro">
|
||||
<img class="pr-main-intro-img" src="/img/AdsIntro.png" width="360" height="200">
|
||||
<h1 class="pr-main-intro-header">Telegram Ads</h1>
|
||||
<p class="pr-main-intro-text">Every month, <b>900 million</b> Telegram users generate <b>1 trillion views</b> in public broadcast channels.<br/><br/>Anyone can display ads in specific <b>Telegram broadcast channels</b> — using this platform.</p>
|
||||
<div class="pr-main-intro-button-wrap">
|
||||
<a href="/auth" class="btn pr-btn login-link">
|
||||
Log in to Start Advertizing
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-features">
|
||||
<div class="pr-main-feature icon-feature1">
|
||||
<div class="pr-main-feature-title">
|
||||
Precise and Efficient
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
You can define specific channels where you want to show your ads to ensure the context is relevant.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-feature2">
|
||||
<div class="pr-main-feature-title">
|
||||
Privacy-Conscious
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
Ads on Telegram do not rely on users' personal information and are based on the channels where they are shown.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-feature3">
|
||||
<div class="pr-main-feature-title">
|
||||
Beneficial For Content Creators
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
50% of the revenue from Telegram Ads goes to the owners of channels where they are displayed.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-feature4">
|
||||
<div class="pr-main-feature-title">
|
||||
Easy to Set Up
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
All it takes is to type up to 160 characters, add a Telegram link to promote, and specify the channels in which to place your ad.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pr-main-feature icon-before icon-feature5">
|
||||
<div class="pr-main-feature-title">
|
||||
Paid with Cryptocurrency
|
||||
</div>
|
||||
<div class="pr-main-feature-text">
|
||||
You can pay for your ad with TON — a cryptocurrency Telegram uses for its high speed and low commissions.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div><div class="popup-container login-popup-container hide" id="login-popup-container">
|
||||
<div class="popup">
|
||||
<div class="popup-body">
|
||||
<section>
|
||||
<h2>Log In</h2>
|
||||
<p>Log in here to manage your ads. Please enter your <b>phone number</b> in the <a target="_blank" rel="noopener" href="https://telegram.org/faq#login-and-sms">international format</a> and we will send a confirmation message to your account via Telegram.</p>
|
||||
|
||||
<form id="send-form" class="login-form">
|
||||
<div class="form-group">
|
||||
<input type="tel" class="form-control pr-form-control input-lg" id="phone-number" placeholder="+12223334455" autocomplete="off"/>
|
||||
</div>
|
||||
<div class="popup-buttons">
|
||||
<a class="btn btn-link btn-lg login-cancel-btn">Cancel</a><button type="submit" class="btn btn-link btn-lg">Next</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="login-form" class="hide">
|
||||
<div class="form-group">
|
||||
<span class="form-control pr-form-control input input-lg input-disabled"><strong id="phone-number-field"></strong> (<a class="login-back" href="/auth">Incorrect?</a>)</span>
|
||||
<p class="help-block dots-animated">We've just sent you a message.<br/>Please confirm access via Telegram</p>
|
||||
</div>
|
||||
<div class="popup-buttons">
|
||||
<a class="btn btn-link btn-lg login-cancel-btn">Cancel</a><a class="btn btn-link btn-lg login-back">Back</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
<script src="//telegram.org/js/jquery.min.js?1"></script>
|
||||
<script src="//telegram.org/js/bootstrap.min.js"></script>
|
||||
<script src="//telegram.org/js/main-aj.js?68"></script>
|
||||
<script src="/js/main.js?47"></script>
|
||||
<script src="/js/widget-frame.js?62"></script>
|
||||
<script src="/js/promote.js?81"></script>
|
||||
<script src="/js/jquery-ui.min.js?1"></script>
|
||||
<script src="/js/jquery-ex.js?18"></script>
|
||||
<script src="/js/tchart.min.js?18"></script>
|
||||
<script src="/js/health.js?19"></script>
|
||||
<script src="/js/tgsticker.js?31"></script>
|
||||
|
||||
<script>ajInit({"version":985,"apiUrl":"\/api?hash=telegram-crawler","unauth":true});</script>
|
||||
<script id="aj_script">l.add({"WEB_AB_WARNING_HEADER":"Turn off ad blocker","WEB_POPUP_CLOSE_BTN":"Close","WEB_AB_WARNING_TEXT":"You appear to be using an ad blocker that may prevent pages on the Telegram Ad Platform from working as expected.<br\/><br\/>Please turn off your ad blocker or add <a href=\"http:\/\/promote.telegram.org\/\">promote.telegram.org<\/a> as an exception to manage your promoted messages."});
|
||||
Ads.init();
|
||||
Aj.onLoad(function(state) {
|
||||
function requestConfirmation(event) {
|
||||
event && event.preventDefault();
|
||||
var phone = $('#phone-number').val();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/auth/request',
|
||||
data: {
|
||||
phone: phone
|
||||
},
|
||||
success: function(result) {
|
||||
$('#phone-number-field').text(phone);
|
||||
$('#send-form').addClass('hide');
|
||||
$('#login-form').removeClass('hide');
|
||||
checkAuth(result.temp_session);
|
||||
},
|
||||
error: function(xhr) {
|
||||
showAlert(xhr.responseText || 'Server error');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
function cancelConfirmation(event) {
|
||||
event && event.preventDefault();
|
||||
$('#phone-number-field').text('');
|
||||
$('#send-form').removeClass('hide');
|
||||
$('#login-form').addClass('hide');
|
||||
$('#phone-number').focus();
|
||||
clearTimeout(window.authTimeout);
|
||||
return false;
|
||||
}
|
||||
function checkAuth(temp_session) {
|
||||
clearTimeout(window.authTimeout);
|
||||
window.authTimeout = setTimeout(function doCheckAuth() {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/auth/login',
|
||||
data: {
|
||||
temp_session: temp_session
|
||||
},
|
||||
success: function(result) {
|
||||
if (result) {
|
||||
location.reload();
|
||||
} else {
|
||||
checkAuth(temp_session);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
showAlert(xhr.responseText || 'Server error');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
}, 700);
|
||||
}
|
||||
$('#login-popup-container').on('popup:open', function() {
|
||||
$('#phone-number').focus();
|
||||
});
|
||||
$('#login-popup-container').on('popup:close', function() {
|
||||
cancelConfirmation();
|
||||
if (location.pathname == '/auth') {
|
||||
window.history && history.replaceState(null, null, '/');
|
||||
}
|
||||
});
|
||||
$('#login-popup-container #send-form').on('submit', requestConfirmation);
|
||||
$('#login-popup-container .login-cancel-btn').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
closePopup('#login-popup-container');
|
||||
});
|
||||
$('#login-popup-container .login-back').on('click', cancelConfirmation);
|
||||
$('.login-link').on('click', function(e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
openPopup('#login-popup-container');
|
||||
});
|
||||
});
|
||||
Aj.onUnload(function(state) {
|
||||
$('#login-popup-container').off('popup:open');
|
||||
$('#login-popup-container').off('popup:close');
|
||||
$('#login-popup-container #send-form').off('submit');
|
||||
$('#login-popup-container .login-cancel-btn').off('click');
|
||||
$('#login-popup-container .login-back').off('click');
|
||||
$('.login-link').off('click');
|
||||
});
|
||||
</script>
|
||||
<script>Aj.pageLoaded();</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
6
data/web/promote.telegram.org/css/jquery-ui.min.css
vendored
Normal file
6
data/web/promote.telegram.org/css/jquery-ui.min.css
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
/*! jQuery UI - v1.12.0 - 2016-09-10
|
||||
* http://jqueryui.com
|
||||
* Includes: draggable.css, core.css, resizable.css
|
||||
* Copyright jQuery Foundation and other contributors; Licensed MIT */
|
||||
|
||||
.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}
|
4917
data/web/promote.telegram.org/css/promote.css
Normal file
4917
data/web/promote.telegram.org/css/promote.css
Normal file
File diff suppressed because it is too large
Load diff
1
data/web/promote.telegram.org/css/tchart.min.css
vendored
Normal file
1
data/web/promote.telegram.org/css/tchart.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
5087
data/web/promote.telegram.org/css/telegram.css
Normal file
5087
data/web/promote.telegram.org/css/telegram.css
Normal file
File diff suppressed because it is too large
Load diff
2198
data/web/promote.telegram.org/css/widget-frame.css
Normal file
2198
data/web/promote.telegram.org/css/widget-frame.css
Normal file
File diff suppressed because it is too large
Load diff
359
data/web/promote.telegram.org/guidelines.html
Normal file
359
data/web/promote.telegram.org/guidelines.html
Normal file
|
@ -0,0 +1,359 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Telegram Ads</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="MobileOptimized" content="176" />
|
||||
<meta name="HandheldFriendly" content="True" /><meta name="twitter:card" content="summary"></meta>
|
||||
<meta property="og:title" content="Ad Policies and Guidelines">
|
||||
<meta property="og:description" content="These Ad Policies and Guidelines apply to all ads displayed on the Telegram Ad Platform and describe what ad content is…">
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="/img/website_icon.svg?4">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
|
||||
<link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" />
|
||||
<script>document.cookie="stel_dt="+encodeURIComponent((new Date).getTimezoneOffset())+";path=/;max-age=31536000;samesite=None;secure"</script>
|
||||
|
||||
<link href="//telegram.org/css/font-roboto.css?1" rel="stylesheet" type="text/css">
|
||||
<link href="//telegram.org/css/bootstrap.min.css?3" rel="stylesheet">
|
||||
<link href="//telegram.org/css/bootstrap-extra.css?2" rel="stylesheet">
|
||||
<link href="/css/telegram.css?236" rel="stylesheet">
|
||||
<link href="/css/widget-frame.css?67" rel="stylesheet">
|
||||
<link href="/css/promote.css?84" rel="stylesheet">
|
||||
<link href="/css/jquery-ui.min.css?1" rel="stylesheet">
|
||||
<link href="/css/tchart.min.css?10" rel="stylesheet">
|
||||
|
||||
</head>
|
||||
<body class="emoji_image no-transition">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
|
||||
<defs>
|
||||
<path id="icon-currency-ton" d="m2.68 4h10.63c.22 0 .4.18.4.41 0 .07-.01.14-.05.2l-5.04 9.08c-.22.4-.72.54-1.11.32-.14-.08-.25-.19-.32-.33l-4.87-9.08c-.1-.2-.03-.45.17-.55.06-.03.12-.05.19-.05zm5.32 9.78v-9.78z" fill="none" stroke="currentColor" stroke-width="1.3"/>
|
||||
</defs>
|
||||
</svg>
|
||||
<div id="aj_progress" class="progress-bar"></div>
|
||||
|
||||
<div id="aj_content"><div class="pr-container pr-docs-container">
|
||||
<div class="pr-header">
|
||||
<div class="pr-header-auth">
|
||||
<div class="pr-header-auth-item"><a class="header-auth-link login-link" href="/auth">Log In</a></div>
|
||||
</div>
|
||||
<ol class="pr-breadcrumb"><li class="pr-logo compact"><a href="/"><i class="pr-icon"></i><span class="pr-logo-title">Telegram Ads</span></a></li><li class="pr-breadcrumb-item">Ad Policies and Guidelines</li></ol>
|
||||
</div>
|
||||
<section class="pr-content"><div id="dev_page_content_wrap" class=" ">
|
||||
<div class="dev_page_bread_crumbs"></div>
|
||||
<h1 id="dev_page_title">Ad Policies and Guidelines</h1>
|
||||
|
||||
<div id="dev_page_content"><!-- scroll_nav -->
|
||||
|
||||
<p>These Ad Policies and Guidelines apply to all ads displayed on the Telegram Ad Platform and describe what ad content is allowed on Telegram.</p>
|
||||
<p>Advertisers are responsible for their ads and for complying with:</p>
|
||||
<ul>
|
||||
<li>these Ad Policies and Guidelines</li>
|
||||
<li><a href="https://promote.telegram.org/tos">Telegram Ad Platform Terms of Service</a></li>
|
||||
<li><a href="https://telegram.org/tos">Telegram Terms of Service</a> and</li>
|
||||
<li><a href="https://telegram.org/privacy">Telegram Privacy Policy</a>.</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h3><a class="anchor" name="1-ad-format" href="#1-ad-format"><i class="anchor-icon"></i></a>1. Ad format</h3>
|
||||
<p>Each ad consists of an ad text and a button that opens a link to the advertised product. The maximum length of the ad text is <strong>160 characters</strong> including spaces.</p>
|
||||
<h3><a class="anchor" name="2-editorial-requirements" href="#2-editorial-requirements"><i class="anchor-icon"></i></a>2. Editorial requirements</h3>
|
||||
<p>Standard requirements of style, clarity, spelling and punctuation apply to all ads. Numbers, marks and symbols must be used properly. The following is not allowed:</p>
|
||||
<ul>
|
||||
<li>Profanity or vulgarity, <em>including slur acronyms and spelling variations, in any language, and masked vulgarity (e.g., f**k)</em></li>
|
||||
<li>Unrecognizable or unclear meaning, <em>such as overbroad or vague descriptions, repetition of words and phrases</em></li>
|
||||
<li>Excessive or gimmicky use of CaPiTaLiZaTiOn, <strong>highlighting</strong>, s p a c i n g and s,y,m,b,o,l,s, <em>including Unicode art, ASCII art and box-drawing</em></li>
|
||||
<li>Intrusive, excessive or gimmicky use of <strong>emoji</strong> and other emoticons</li>
|
||||
<li>Line breaks, bullet points, numbering lists</li>
|
||||
</ul>
|
||||
<h3><a class="anchor" name="3-link-format" href="#3-link-format"><i class="anchor-icon"></i></a>3. Link format</h3>
|
||||
<p>In addition to the main ad link submitted in the ‘URL’ field, ads may also include one optional link in the ad text itself, using the format the format <code>@link</code>, <code>t.me/link</code>, or <code>t.me/link/123</code>. The ad link and the link in the ad text must both lead to the same destination. If the destination is a Telegram bot, links may include <a href="https://core.telegram.org/bots/features#deep-linking">start parameters for the bot</a>.</p>
|
||||
<p>Links must be used properly. Particularly, the following is not allowed:</p>
|
||||
<ul>
|
||||
<li>Using more than one link in the ad text</li>
|
||||
<li>Adding external links to the ad text.</li>
|
||||
<li>Using any unacceptable link formats, <em>such as URL shorteners or an IP-address in the place of the link, even if it ultimately leads to a valid destination</em></li>
|
||||
</ul>
|
||||
<h3><a class="anchor" name="4-destination-requirements" href="#4-destination-requirements"><i class="anchor-icon"></i></a>4. Destination requirements</h3>
|
||||
<p>To keep all ads beneficial for both Telegram users and advertisers, these Ad Policies and Guidelines set out requirements for proper destinations.</p>
|
||||
<h4><a class="anchor" name="4-1-destination-quality" href="#4-1-destination-quality"><i class="anchor-icon"></i></a>4.1. Destination quality</h4>
|
||||
<p>Ad destinations must have quality, original content and provide a proper user experience. Particularly, the following applies:</p>
|
||||
<ul>
|
||||
<li>Telegram channels and bots must have both a profile image and a complete text in their ‘about’ or ‘description’ section.</li>
|
||||
<li>Bots must be <em>beneficial</em> to the user and are expected to provide a user experience and interfaces that are consistent with the capabilities of the <a href="https://core.telegram.org/bots/features">Bot Platform</a>.</li>
|
||||
<li>Destinations using excessive CAPITALIZATION, <strong>highlighting</strong>, emoji, punctuation (exclamation marks etc.) or strong language are not allowed.</li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="4-2-destination-functionality" href="#4-2-destination-functionality"><i class="anchor-icon"></i></a>4.2. Destination functionality</h4>
|
||||
<p>Ad destinations must be functional, technically complete, and active. Particularly, the following applies:</p>
|
||||
<ul>
|
||||
<li>Empty or abandoned Telegram channels are not allowed as destinations.</li>
|
||||
<li>Telegram channels must have had some activity at least once in the two weeks prior to review.</li>
|
||||
<li>Destination bots must respond to commands properly on both mobile and desktop devices.</li>
|
||||
<li>Inactive, expired and inaccessible websites are not allowed. This covers websites “under construction”, websites returning error codes, preventing access by a paywall or login form, websites unavailable from targeted locations, and websites that fail to load.</li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="4-3-irrelevant-destinations" href="#4-3-irrelevant-destinations"><i class="anchor-icon"></i></a>4.3. Irrelevant destinations</h4>
|
||||
<p>Destinations must match the ad text and may not be used only for redirecting to other landing pages. Particularly, the following is not allowed:</p>
|
||||
<ul>
|
||||
<li>The <strong>language</strong> of the targeted channel must be the same as the language of the ad and of the destination.</li>
|
||||
<li>Destinations not corresponding with the ad text, <em>e.g., cat food ads with links to an online clothing store</em></li>
|
||||
<li>Mock destinations created solely for displaying other ads or collecting user data with “call me back” forms or similar</li>
|
||||
<li>Mostly noninteractive bots designed to redirect elsewhere</li>
|
||||
<li>Websites that automatically redirect users to a different webpage or domain, <em>e.g., through 302-redirect or .htaccess-redirect</em></li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="4-4-manipulation-of-content" href="#4-4-manipulation-of-content"><i class="anchor-icon"></i></a>4.4. Manipulation of content</h4>
|
||||
<p>The contents of a destination may not be altered to scam users or evade moderation review. Advertisers using manipulated destinations may be suspended without notice. Particularly, the following is not allowed:</p>
|
||||
<ul>
|
||||
<li>Concealing or replacing the content of the destination to pass the ad review</li>
|
||||
<li>Spoofing and cloaking, <em>such as when a destination imitates a legitimate website or uses names of other brands to mislead visitors</em></li>
|
||||
</ul>
|
||||
<h3><a class="anchor" name="5-prohibited-content" href="#5-prohibited-content"><i class="anchor-icon"></i></a>5. Prohibited content</h3>
|
||||
<p>These Ad Policies and Guidelines prohibit some types of content to ensure a safe and pleasant experience for Telegram users. The following requirements apply to ads on the Telegram Ad Platform and to the products they promote, whether implied or explicit. <strong>All examples given are non-exhaustive.</strong></p>
|
||||
<h4><a class="anchor" name="5-1-graphic-shocking-or-sexual-content" href="#5-1-graphic-shocking-or-sexual-content"><i class="anchor-icon"></i></a>5.1. Graphic, shocking, or sexual content</h4>
|
||||
<p>Ads must not promote graphic, shocking, or sexual content, products and services.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Gruesome, disgusting, or shocking imagery, <em>including gore, bodily fluids, accident photos, graphic details of torture</em></li>
|
||||
<li>Nudity, sexually explicit and sexually suggestive content, <em>including excessively exposed intimate body parts, sexual merchandize and entertainment, dating services</em></li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-2-hate-violence-harassment" href="#5-2-hate-violence-harassment"><i class="anchor-icon"></i></a>5.2. Hate, violence, harassment</h4>
|
||||
<p>Ads must not promote hatred, intolerance, harassment, discrimination, violence, or abuse.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Violence and its promotion, <em>including supporting organizations or movements with ties to violence</em></li>
|
||||
<li>Promoting harassment or bullying, <em>including dehumanizing speech, statements of inferiority, defamatory content, disclosing contact details or personal data</em></li>
|
||||
<li>Discrimination towards individuals, groups, or organizations, <em>including hateful messages on the basis of race, religion, color, national or ethnic origin, age, beliefs, sexual orientation or practices, physical or mental abilities</em></li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-3-third-party-rights" href="#5-3-third-party-rights"><i class="anchor-icon"></i></a>5.3. Third party rights</h4>
|
||||
<p>Ads and promoted content must not violate third party rights, including trademark, copyright, privacy or other personal or proprietary rights.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Unauthorized distribution of copyrighted content, <em>including pirated software and content such as movies, music, or books</em></li>
|
||||
<li>Plagiarism, <em>including impersonating public figures or brands, misusing brand logos or assets, e.g., the Telegram logo</em></li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-4-deceptive-misleading-or-predatory-advertising" href="#5-4-deceptive-misleading-or-predatory-advertising"><i class="anchor-icon"></i></a>5.4. Deceptive, misleading, or predatory advertising</h4>
|
||||
<p>Ads must not contain information that is false, misleading or simply does not match the product. This includes false statements, claims or offers, together with predatory advertising practices. </p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Clickbait or similar unrealistic statements, <em>including you-just-won-X claims, shock or scare tactics</em></li>
|
||||
<li>Exaggerated comparisons and absolute claims, <em>including unsupported use of comparatives and superlatives: “highest incomes”, “best company”, and comparing your brand to a different one</em></li>
|
||||
<li>Highlighting personal characteristics (e.g., ethnicity, religion, location, financial status), <em>including asking personal questions: “Do you like channels about finance?”, “Looking to pay off high debt?”</em></li>
|
||||
<li>Implying negative outcomes for the viewer: <em>“Check out our channel so you don't get scammed”</em></li>
|
||||
<li>Capitalizing on tragedies, health crises or acts of mass violence</li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-5-political-ads-sensitive-topics-religion" href="#5-5-political-ads-sensitive-topics-religion"><i class="anchor-icon"></i></a>5.5. Political ads, sensitive topics, religion</h4>
|
||||
<p>Ads must not promote political campaigns, elections, political parties, candidates, political or religious movements. Ads that are related to ongoing sensitive events or sensitive topics can be suspended for the meantime.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Advocating for or against a politician, political party, or political movement</li>
|
||||
<li>Exploiting political controversy, <em>including encouraging political unrest, disrupting public order</em></li>
|
||||
<li>Advocating for or against religious beliefs, <em>including promotion of religious practices, rituals</em></li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-6-gambling" href="#5-6-gambling"><i class="anchor-icon"></i></a>5.6. Gambling</h4>
|
||||
<p>Ads must not promote online or offline gambling, gaming, or casino-based activities involving real money, prizes, or goods of any value.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Games of chance or casinos, <em>including sports betting, lotteries, bingo, fantasy sports</em></li>
|
||||
<li>Tips, odds, forecasts, <em>including sports picks, odds calculators</em></li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-7-deceptive-or-harmful-financial-products-or-services" href="#5-7-deceptive-or-harmful-financial-products-or-services"><i class="anchor-icon"></i></a>5.7. Deceptive or harmful financial products or services</h4>
|
||||
<p>Ads must not promote content, products, or services associated with deceptive or harmful financial practices. When ads or destinations promote a paid product, the terms of purchase must be explicit and easy to understand.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Payday loans, cash loans, predatory lending, <em>including short-term loans</em></li>
|
||||
<li>Get-rich-quick offers, pyramid schemes, multilevel marketing, <em>including offers of investment with guaranteed return, claims on providing insider tips on investments</em></li>
|
||||
<li>Concealing or masking significant information about the promoted paid product, such as fees, terms, payment deadlines.</li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-8-uncertified-medical-services-medications-supplements" href="#5-8-uncertified-medical-services-medications-supplements"><i class="anchor-icon"></i></a>5.8. Uncertified medical services, medications, supplements</h4>
|
||||
<p>Promoted products must comply with all local regulations and sellers must be properly licensed. Ads must not promote content, products or services implicitly or explicitly related to any unverified health and wellness benefits.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Nutrition products, including weight loss or gain products, herbal drugs, dietary supplements, pregnancy, and fertility-related products</li>
|
||||
<li>Medicines not approved by the respective local regulatory body</li>
|
||||
<li>Sale of medicines or medical products by a shop or entity that is not government-registered and authorized</li>
|
||||
<li>Unlicensed medical devices, services and treatments</li>
|
||||
<li>Prescriptions for medications</li>
|
||||
<li>Products with unverified claims of healthful, curative or stimulating effects, <em>including methods suggesting unrealistic health improvements</em></li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-9-drugs-alcohol-tobacco" href="#5-9-drugs-alcohol-tobacco"><i class="anchor-icon"></i></a>5.9. Drugs, alcohol, tobacco</h4>
|
||||
<p>Ads must not promote psychoactive substances, alcoholic beverages or tobacco products.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Alcoholic beverages, <em>including home brewing kits, non-alcoholic beer</em></li>
|
||||
<li>Tobacco, <em>including e-cigarettes, rolling papers, chewing tobacco</em></li>
|
||||
<li>Recreational drugs, <em>including equipment and paraphernalia, e.g., pipes, bongs</em></li>
|
||||
<li>Instructions on producing drugs</li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-10-weapons-firearms-explosives-ammunition" href="#5-10-weapons-firearms-explosives-ammunition"><i class="anchor-icon"></i></a>5.10. Weapons, firearms, explosives, ammunition</h4>
|
||||
<p>Ads must not promote the sale of weapons, explosives or ammunition, or any related content.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Firearms, <em>including sporting, recreational guns, or any antique functioning guns that can cause harm</em></li>
|
||||
<li>Ammunition or accessories, <em>including any firearm parts or components, even unfinished, such as magazines, scopes, silencers</em></li>
|
||||
<li>Knives and other melee weapons, <em>including pepper spray, daggers, axes</em></li>
|
||||
<li>Explosives, <em>including bombs, grenades, fireworks, or firecrackers</em></li>
|
||||
<li>Instructions on assembling or acquiring any product covered in this section</li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-11-spam-software-malware-hacking" href="#5-11-spam-software-malware-hacking"><i class="anchor-icon"></i></a>5.11. Spam software, malware, hacking</h4>
|
||||
<p>Ads must not promote content, products, or services that facilitate unsolicited communications, are intended to harm or gain unauthorized access to a user's device, or cause deceptive or unexpected consequences.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Social media growth manipulation, <em>including encouraging growth of social media profiles</em></li>
|
||||
<li>Incentivized or automated clicks, <em>including requests to perform actions on websites or services, complete online surveys</em></li>
|
||||
<li>Services for generating automated traffic, <em>including services for inflating metrics/followers, sending automated content to social media platforms or other services</em></li>
|
||||
<li>Phishing, <em>including promotion of services that trick a user into providing personal or other information</em></li>
|
||||
<li>Software causing deceptive or unexpected consequences, <em>including modified apps containing malware, viruses, or any other malicious code</em></li>
|
||||
</ul>
|
||||
<h4><a class="anchor" name="5-12-products-of-questionable-legality" href="#5-12-products-of-questionable-legality"><i class="anchor-icon"></i></a>5.12. Products of questionable legality</h4>
|
||||
<p>Ads must not promote content, products, or services of questionable legality.</p>
|
||||
<p><strong>Examples:</strong></p>
|
||||
<ul>
|
||||
<li>Forgery, <em>including fake IDs, passports, visas, official documents</em></li>
|
||||
<li>Human-trafficking, <em>including marriage brokering</em></li>
|
||||
<li>Stolen or leaked data, <em>including carding, passwords to subscription services</em></li>
|
||||
<li>Sale of body parts, <em>including bodily fluids</em></li>
|
||||
<li>Counterfeit products, <em>including fake or bootleg goods, inauthentic artwork or digital goods, counterfeit currency</em></li>
|
||||
</ul>
|
||||
<hr>
|
||||
<p><strong>All examples on this page are non-exhaustive.</strong></p>
|
||||
</div>
|
||||
|
||||
</div></section>
|
||||
</div><div class="popup-container login-popup-container hide" id="login-popup-container">
|
||||
<div class="popup">
|
||||
<div class="popup-body">
|
||||
<section>
|
||||
<h2>Log In</h2>
|
||||
<p>Log in here to manage your ads. Please enter your <b>phone number</b> in the <a target="_blank" rel="noopener" href="https://telegram.org/faq#login-and-sms">international format</a> and we will send a confirmation message to your account via Telegram.</p>
|
||||
|
||||
<form id="send-form" class="login-form">
|
||||
<div class="form-group">
|
||||
<input type="tel" class="form-control pr-form-control input-lg" id="phone-number" placeholder="+12223334455" autocomplete="off"/>
|
||||
</div>
|
||||
<div class="popup-buttons">
|
||||
<a class="btn btn-link btn-lg login-cancel-btn">Cancel</a><button type="submit" class="btn btn-link btn-lg">Next</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="login-form" class="hide">
|
||||
<div class="form-group">
|
||||
<span class="form-control pr-form-control input input-lg input-disabled"><strong id="phone-number-field"></strong> (<a class="login-back" href="/auth">Incorrect?</a>)</span>
|
||||
<p class="help-block dots-animated">We've just sent you a message.<br/>Please confirm access via Telegram</p>
|
||||
</div>
|
||||
<div class="popup-buttons">
|
||||
<a class="btn btn-link btn-lg login-cancel-btn">Cancel</a><a class="btn btn-link btn-lg login-back">Back</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
<script src="//telegram.org/js/jquery.min.js?1"></script>
|
||||
<script src="//telegram.org/js/bootstrap.min.js"></script>
|
||||
<script src="//telegram.org/js/main-aj.js?68"></script>
|
||||
<script src="/js/main.js?47"></script>
|
||||
<script src="/js/widget-frame.js?62"></script>
|
||||
<script src="/js/promote.js?81"></script>
|
||||
<script src="/js/jquery-ui.min.js?1"></script>
|
||||
<script src="/js/jquery-ex.js?18"></script>
|
||||
<script src="/js/tchart.min.js?18"></script>
|
||||
<script src="/js/health.js?19"></script>
|
||||
<script src="/js/tgsticker.js?31"></script>
|
||||
|
||||
<script>ajInit({"version":985,"apiUrl":"\/api?hash=telegram-crawler","unauth":true});</script>
|
||||
<script id="aj_script">l.add({"WEB_AB_WARNING_HEADER":"Turn off ad blocker","WEB_POPUP_CLOSE_BTN":"Close","WEB_AB_WARNING_TEXT":"You appear to be using an ad blocker that may prevent pages on the Telegram Ad Platform from working as expected.<br\/><br\/>Please turn off your ad blocker or add <a href=\"http:\/\/promote.telegram.org\/\">promote.telegram.org<\/a> as an exception to manage your promoted messages."});
|
||||
window.initDevPageNav&&initDevPageNav();
|
||||
window.enableInlineVideo&&$('video').each(function(){enableInlineVideo(this)});
|
||||
Ads.init();
|
||||
Aj.onLoad(function(state) {
|
||||
function requestConfirmation(event) {
|
||||
event && event.preventDefault();
|
||||
var phone = $('#phone-number').val();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/auth/request',
|
||||
data: {
|
||||
phone: phone
|
||||
},
|
||||
success: function(result) {
|
||||
$('#phone-number-field').text(phone);
|
||||
$('#send-form').addClass('hide');
|
||||
$('#login-form').removeClass('hide');
|
||||
checkAuth(result.temp_session);
|
||||
},
|
||||
error: function(xhr) {
|
||||
showAlert(xhr.responseText || 'Server error');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
function cancelConfirmation(event) {
|
||||
event && event.preventDefault();
|
||||
$('#phone-number-field').text('');
|
||||
$('#send-form').removeClass('hide');
|
||||
$('#login-form').addClass('hide');
|
||||
$('#phone-number').focus();
|
||||
clearTimeout(window.authTimeout);
|
||||
return false;
|
||||
}
|
||||
function checkAuth(temp_session) {
|
||||
clearTimeout(window.authTimeout);
|
||||
window.authTimeout = setTimeout(function doCheckAuth() {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/auth/login',
|
||||
data: {
|
||||
temp_session: temp_session
|
||||
},
|
||||
success: function(result) {
|
||||
if (result) {
|
||||
location.reload();
|
||||
} else {
|
||||
checkAuth(temp_session);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
showAlert(xhr.responseText || 'Server error');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
}, 700);
|
||||
}
|
||||
$('#login-popup-container').on('popup:open', function() {
|
||||
$('#phone-number').focus();
|
||||
});
|
||||
$('#login-popup-container').on('popup:close', function() {
|
||||
cancelConfirmation();
|
||||
if (location.pathname == '/auth') {
|
||||
window.history && history.replaceState(null, null, '/');
|
||||
}
|
||||
});
|
||||
$('#login-popup-container #send-form').on('submit', requestConfirmation);
|
||||
$('#login-popup-container .login-cancel-btn').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
closePopup('#login-popup-container');
|
||||
});
|
||||
$('#login-popup-container .login-back').on('click', cancelConfirmation);
|
||||
$('.login-link').on('click', function(e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
openPopup('#login-popup-container');
|
||||
});
|
||||
});
|
||||
Aj.onUnload(function(state) {
|
||||
$('#login-popup-container').off('popup:open');
|
||||
$('#login-popup-container').off('popup:close');
|
||||
$('#login-popup-container #send-form').off('submit');
|
||||
$('#login-popup-container .login-cancel-btn').off('click');
|
||||
$('#login-popup-container .login-back').off('click');
|
||||
$('.login-link').off('click');
|
||||
});
|
||||
</script>
|
||||
<script>Aj.pageLoaded();</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
339
data/web/promote.telegram.org/js/health.js
Normal file
339
data/web/promote.telegram.org/js/health.js
Normal file
|
@ -0,0 +1,339 @@
|
|||
function prepareGraphJson(json) {
|
||||
var callableParams = ['xTickFormatter', 'xTooltipFormatter', 'xRangeFormatter', 'yTickFormatter', 'yTooltipFormatter', 'x_on_zoom', 'sideLegend'];
|
||||
callableParams.forEach(function (k) {
|
||||
if (typeof json[k] === 'string') {
|
||||
json[k] = eval('(' + json[k] + ')');
|
||||
}
|
||||
});
|
||||
console.log('new json', json);
|
||||
return json;
|
||||
}
|
||||
|
||||
function zoomGraphX(x, tokenData) {
|
||||
return fetch('/zoomed', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
|
||||
},
|
||||
body: 'x=' + x + '&id=' + tokenData.id + '&date=' + tokenData.date + '&token=' + tokenData.token
|
||||
}).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
console.error('Zoom fetch error. Status Code: ', response);
|
||||
return Promise.reject();
|
||||
}
|
||||
return response.json().then(function (json) {
|
||||
return prepareGraphJson(json);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function fetchGraph(id, tokenData, retry) {
|
||||
var domEl = document.getElementById(id);
|
||||
if (!domEl) {
|
||||
console.warn('graph el #' + id + ' not found');
|
||||
return;
|
||||
}
|
||||
var loadingEl = domEl.querySelector('.chart_wrap_loading');
|
||||
retry = retry || 0;
|
||||
return fetch('/asyncgraph' + (tokenData.test ? '?_test=1' : ''), {
|
||||
method: 'post',
|
||||
headers: {
|
||||
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
|
||||
},
|
||||
body: 'id=' + tokenData.id + '&date=' + tokenData.date + '&token=' + tokenData.token
|
||||
}).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
console.error('Async graph fetch error. Status Code: ', response);
|
||||
if (response.status === 500) {
|
||||
loadingEl.innerHTML = 'Internal Server Error, Retrying '+(++retry) +'...';
|
||||
setTimeout(function () {
|
||||
fetchGraph(id, tokenData, retry)
|
||||
}, 1000 * retry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return response.json().then(function (json) {
|
||||
renderGraph(id, json);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderGraph(id, json, initial) {
|
||||
var domEl = document.getElementById(id);
|
||||
var loadingEl = domEl.querySelector('.chart_wrap_loading');
|
||||
if (!json.columns.length ||
|
||||
json.columns[0].length <= 2) {
|
||||
if (loadingEl) {
|
||||
loadingEl.innerHTML = 'Not enough data to display.';
|
||||
}
|
||||
return;
|
||||
}
|
||||
json = prepareGraphJson(json);
|
||||
var chart = Graph.render(domEl, json);
|
||||
domEl.classList.add('chart_wrap_rendered');
|
||||
window.charts = window.charts || {};
|
||||
window.charts[id] = chart;
|
||||
setTimeout(function () {
|
||||
if (loadingEl) {
|
||||
loadingEl.parentNode.removeChild(loadingEl)
|
||||
}
|
||||
}, 1000);
|
||||
if (json.csvExport) {
|
||||
var exportHTML = '<div class="chart_csv_export_wrap"><a class="csv_link btn btn-default" href="' + json.csvExport + '"><span class="glyphicon glyphicon-download-alt"></span> CSV</a></div>';
|
||||
var t = document.createElement('div');
|
||||
t.innerHTML = exportHTML;
|
||||
domEl.appendChild(t.firstChild);
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
function statsFormatXCategories(x, categories) {
|
||||
return categories[x] === undefined ? '' : categories[x];
|
||||
}
|
||||
|
||||
function statsFormatKMBT(x, kmbt, precision) {
|
||||
return window.Graph.units.TUtils.statsFormatKMBT(x, kmbt, precision);
|
||||
}
|
||||
|
||||
function statsFormatDayHourFull(hour) {
|
||||
return hour + ':00-' + hour + ':59';
|
||||
}
|
||||
function statsFormatDayHour(hour) {
|
||||
return hour + ':00';
|
||||
}
|
||||
|
||||
var statShortMonths = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
var statShortWeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||
|
||||
|
||||
function statsFormat(period) {
|
||||
switch (period) {
|
||||
case 'minute':
|
||||
case '5min':
|
||||
return statsFormat5min;
|
||||
|
||||
case 'hour':
|
||||
return statsFormatHour;
|
||||
|
||||
case 'week':
|
||||
return statsFormatWeek;
|
||||
|
||||
case 'month':
|
||||
return statsFormatMonth;
|
||||
|
||||
case 'day':
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function statsTooltipFormat(period) {
|
||||
switch (period) {
|
||||
case 'week':
|
||||
return statsFormatWeekFull;
|
||||
case 'month':
|
||||
return statsFormatMonthFull;
|
||||
}
|
||||
return statsFormat(period);
|
||||
}
|
||||
|
||||
function formatNumber(number, decimals, decPoint, thousandsSep) {
|
||||
number = (number + '').replace(/[^0-9+\-Ee.]/g, '')
|
||||
var n = !isFinite(+number) ? 0 : +number
|
||||
var prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
|
||||
var sep = (typeof thousandsSep === 'undefined') ? ',' : thousandsSep
|
||||
var dec = (typeof decPoint === 'undefined') ? '.' : decPoint
|
||||
var s = ''
|
||||
var toFixedFix = function (n, prec) {
|
||||
if (('' + n).indexOf('e') === -1) {
|
||||
return +(Math.round(n + 'e+' + prec) + 'e-' + prec)
|
||||
} else {
|
||||
var arr = ('' + n).split('e')
|
||||
var sig = ''
|
||||
if (+arr[1] + prec > 0) {
|
||||
sig = '+'
|
||||
}
|
||||
return (+(Math.round(+arr[0] + 'e' + sig + (+arr[1] + prec)) + 'e-' + prec)).toFixed(prec)
|
||||
}
|
||||
}
|
||||
s = (prec ? toFixedFix(n, prec).toString() : '' + Math.round(n)).split('.')
|
||||
if (s[0].length > 3) {
|
||||
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep)
|
||||
}
|
||||
if ((s[1] || '').length < prec) {
|
||||
s[1] = s[1] || ''
|
||||
s[1] += new Array(prec - s[1].length + 1).join('0')
|
||||
}
|
||||
return s.join(dec)
|
||||
}
|
||||
|
||||
function statsFormatAxisAmountTpl(tpl, value) {
|
||||
if (value % 1000000 > 0) {
|
||||
var decimals = 2;
|
||||
while (value % Math.pow(10, 6 - decimals)) {
|
||||
decimals++;
|
||||
if (decimals >= 3) break;
|
||||
}
|
||||
value = formatNumber(value / 1000000, decimals, '.', ',');
|
||||
} else {
|
||||
value = statsFormatKMBT(value / 1000000);
|
||||
}
|
||||
return tpl.replace('{value}', value);
|
||||
}
|
||||
|
||||
function statsFormatAxisAmountFn(tpl) {
|
||||
return function(value) {
|
||||
return statsFormatAxisAmountTpl(tpl, value);
|
||||
};
|
||||
}
|
||||
|
||||
function statsFormatAxisAmount(value) {
|
||||
return statsFormatAxisAmountTpl('€ {value}', value);
|
||||
}
|
||||
|
||||
function statsFormatAmountTpl(tpl, value) {
|
||||
var decimals = 2;
|
||||
while (value % Math.pow(10, 6 - decimals) &&
|
||||
value < Math.pow(10, 10 - decimals)) {
|
||||
decimals++;
|
||||
}
|
||||
value = formatNumber(value / 1000000, decimals, '.', ',');
|
||||
return tpl.replace('{value}', value);
|
||||
}
|
||||
|
||||
function statsFormatAmountFn(tpl) {
|
||||
return function(value) {
|
||||
return statsFormatAmountTpl(tpl, value);
|
||||
};
|
||||
}
|
||||
|
||||
function statsFormatAmount(value) {
|
||||
return statsFormatAmountTpl('€ {value}', value);
|
||||
}
|
||||
|
||||
function statsFormat5min(time) {
|
||||
return new Date(time).toUTCString().match(/(\d+:\d+):/)[1];
|
||||
}
|
||||
|
||||
function statsFormatHour(time) {
|
||||
var date = new Date(time);
|
||||
return statShortMonths[date.getUTCMonth()] + ', ' + date.getUTCDate() + ' ' + date.toUTCString().match(/(\d+:\d+):/)[1];
|
||||
}
|
||||
|
||||
function statsFormatPeriod(time, days) {
|
||||
var dt = new Date(time),
|
||||
de = new Date(time + (days - 1) * 86400000);
|
||||
var dtm = dt.getUTCMonth(), dem = de.getUTCMonth(),
|
||||
dtd = dt.getUTCDate(), ded = de.getUTCDate();
|
||||
|
||||
if (dtm == dem) {
|
||||
return dtd + '-' + ded + ' ' + statShortMonths[dtm];
|
||||
} else {
|
||||
return dtd + ' ' + statShortMonths[dtm] + ' - ' + ded + ' ' + statShortMonths[dem];
|
||||
}
|
||||
}
|
||||
|
||||
function statsFormatPeriodFull(time, days) {
|
||||
var dt = new Date(time),
|
||||
de = new Date(time + (days - 1) * 86400000);
|
||||
var dty = dt.getUTCFullYear(), dey = de.getUTCFullYear(),
|
||||
dtm = dt.getUTCMonth(), dem = de.getUTCMonth(),
|
||||
dtd = dt.getUTCDate(), ded = de.getUTCDate();
|
||||
|
||||
if (dty != dey) {
|
||||
return dtd + ' ' + statShortMonths[dtm] + ' ' + dty + ' – ' + ded + ' ' + statShortMonths[dem] + ' ' + dey;
|
||||
} else {
|
||||
return dtd + ' ' + statShortMonths[dtm] + ' – ' + ded + ' ' + statShortMonths[dem] + ' ' + dey;
|
||||
}
|
||||
}
|
||||
|
||||
function statsFormatWeek(time) {
|
||||
return statsFormatPeriod(time, 7);
|
||||
}
|
||||
|
||||
function statsFormatWeekFull(time) {
|
||||
return statsFormatPeriodFull(time, 7);
|
||||
}
|
||||
|
||||
function statsFormatMonth(time) {
|
||||
return statsFormatPeriod(time, 30);
|
||||
}
|
||||
|
||||
function statsFormatMonthFull(time) {
|
||||
return statsFormatPeriodFull(time, 30);
|
||||
}
|
||||
|
||||
function statsFormatTooltipValue(val) {
|
||||
if (val.toLocaleString) {
|
||||
return val.toLocaleString();
|
||||
}
|
||||
return val + '';
|
||||
// return statsFormatNumber(val)
|
||||
}
|
||||
|
||||
function statsFormatEmpty() {
|
||||
return '';
|
||||
}
|
||||
|
||||
function statsOnZoom(zoomToken) {
|
||||
return function (x) {
|
||||
return zoomGraphX(x, zoomToken);
|
||||
}
|
||||
}
|
||||
|
||||
function statsNeedSideLegend() {
|
||||
var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
||||
return width > 1200;
|
||||
}
|
||||
|
||||
function dropdownFilterChange(el, event) {
|
||||
var query = el.value.toString().trim().toLowerCase();
|
||||
var menu = el.parentNode.parentNode;
|
||||
var items = menu.querySelectorAll('li');
|
||||
var len = items.length;
|
||||
var i, item, text, matches;
|
||||
for (i = 0; i < len; i++) {
|
||||
item = items[i];
|
||||
if (item.classList.contains('dropdown-filter')) {
|
||||
continue;
|
||||
}
|
||||
text = item.innerText.trim().toLowerCase();
|
||||
matches = !query.length ||
|
||||
text.startsWith(query) ||
|
||||
text.indexOf(' ' + query) != -1 ||
|
||||
text.indexOf('.' + query) != -1;
|
||||
item.classList.toggle('hidden', !matches);
|
||||
if (event && event.keyCode == 13 && matches) {
|
||||
location.href = item.querySelector('a').href;
|
||||
return cancelEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function dropdownToggle(el) {
|
||||
var field = el.parentNode.querySelector('.dropdown-filter-field');
|
||||
if (field) {
|
||||
field.value = '';
|
||||
dropdownFilterChange(field);
|
||||
setTimeout(function () {
|
||||
field.focus();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
function cancelEvent(event) {
|
||||
event = event || window.event;
|
||||
if (event) event = event.originalEvent || event;
|
||||
|
||||
if (event.stopPropagation) event.stopPropagation();
|
||||
if (event.preventDefault) event.preventDefault();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
window.addEventListener('load', function () {
|
||||
var hlWrapper = document.querySelector('#hl-wrapper');
|
||||
if (hlWrapper) {
|
||||
hlWrapper.classList.add('transitions-ready');
|
||||
}
|
||||
});
|
1805
data/web/promote.telegram.org/js/jquery-ex.js
vendored
Normal file
1805
data/web/promote.telegram.org/js/jquery-ex.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
9
data/web/promote.telegram.org/js/jquery-ui.min.js
vendored
Normal file
9
data/web/promote.telegram.org/js/jquery-ui.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4082
data/web/promote.telegram.org/js/libwebp-0.2.0.js
Normal file
4082
data/web/promote.telegram.org/js/libwebp-0.2.0.js
Normal file
File diff suppressed because it is too large
Load diff
715
data/web/promote.telegram.org/js/main.js
Normal file
715
data/web/promote.telegram.org/js/main.js
Normal file
|
@ -0,0 +1,715 @@
|
|||
var startTime = +(new Date());
|
||||
function dT() {
|
||||
return '[' + ((+(new Date()) - startTime)/ 1000.0) + '] ';
|
||||
}
|
||||
|
||||
var jsonpCallbacks = [];
|
||||
function twitterCustomShareInit () {
|
||||
var btns = document.querySelectorAll
|
||||
? document.querySelectorAll('.tl_twitter_share_btn')
|
||||
: [document.getElementById('tl_twitter_share_btn')];
|
||||
|
||||
if (!btns.length) {
|
||||
return;
|
||||
}
|
||||
var head = document.getElementsByTagName('head')[0], i, script;
|
||||
for (i = 0; i < btns.length; i++) {
|
||||
(function (btn) {
|
||||
var status = btn.getAttribute('data-text'),
|
||||
url = btn.getAttribute('data-url') || location.toString() || 'https://telegram.org/',
|
||||
via = btn.getAttribute('data-via'),
|
||||
urlEncoded = encodeURIComponent(url),
|
||||
popupUrl = 'https://twitter.com/intent/tweet?text=' + encodeURIComponent(status) + '&url=' + urlEncoded + '&via=' + encodeURIComponent(via);
|
||||
|
||||
btn.setAttribute('href', popupUrl);
|
||||
btn.href = popupUrl;
|
||||
|
||||
btn.addEventListener('click', function (e) {
|
||||
var popupW = 550,
|
||||
popupH = 450,
|
||||
params = [
|
||||
'width=' + popupW,
|
||||
'height=' + popupH,
|
||||
'left=' + Math.round(screen.width / 2 - popupW / 2),
|
||||
'top=' + Math.round(screen.height / 2 - popupH / 2),
|
||||
'personalbar=0',
|
||||
'toolbar=0',
|
||||
'scrollbars=1',
|
||||
'resizable=1'
|
||||
].join(','),
|
||||
popup = window.open(popupUrl, '_blank', params);
|
||||
|
||||
if (popup) {
|
||||
try {
|
||||
popup.focus();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
return cancelEvent(e);
|
||||
}, false);
|
||||
})(btns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function blogRecentNewsInit () {
|
||||
if (document.querySelectorAll) {
|
||||
var sideImages = document.querySelectorAll('.blog_side_image_wrap');
|
||||
var sideImage, parent, i;
|
||||
var len = len = sideImages.length;
|
||||
for (i = 0; i < len; i++) {
|
||||
sideImage = sideImages[i];
|
||||
parent = sideImage.parentNode.parentNode;
|
||||
if (parent) {
|
||||
parent.insertBefore(sideImage, parent.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var moreBtn = document.getElementById('tlb_blog_head_more_link');
|
||||
if (!moreBtn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var activeClassName = 'tlb_blog_head_recent_active';
|
||||
moreBtn.addEventListener('click', function (event) {
|
||||
var parent = this.parentNode;
|
||||
var className = parent.className;
|
||||
if (className.indexOf(activeClassName) == -1) {
|
||||
className += ' ' + activeClassName;
|
||||
} else {
|
||||
className = className.replace(' ' + activeClassName, '');
|
||||
}
|
||||
parent.className = className;
|
||||
|
||||
return cancelEvent(event);
|
||||
});
|
||||
}
|
||||
|
||||
function blogSideImageUpdate(argument) {
|
||||
var isDesktop = document.documentElement.offsetWidth >= 1000
|
||||
document.querySelectorAll('.blog_side_image_wrap').forEach(function (imageWrap) {
|
||||
if (isDesktop) {
|
||||
var titleHeight = imageWrap.parentNode.previousElementSibling.clientHeight;
|
||||
var beforeTitleEl = imageWrap.parentNode.previousElementSibling.previousElementSibling;
|
||||
if (beforeTitleEl) {
|
||||
titleHeight += beforeTitleEl.clientHeight;
|
||||
}
|
||||
imageWrap.firstElementChild.style.marginTop = (-titleHeight - 8) + 'px';
|
||||
} else {
|
||||
imageWrap.firstElementChild.style.marginTop = '';
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function blogSideImageInit() {
|
||||
window.addEventListener('resize', blogSideImageUpdate, false);
|
||||
setTimeout(blogSideImageUpdate, 0);
|
||||
}
|
||||
|
||||
function cancelEvent (event) {
|
||||
event = event || window.event;
|
||||
if (event) event = event.originalEvent || event;
|
||||
|
||||
if (event.stopPropagation) event.stopPropagation();
|
||||
if (event.preventDefault) event.preventDefault();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function trackDlClick (element, event) {
|
||||
var href = element.getAttribute('href'),
|
||||
track = element.getAttribute('data-track') || false;
|
||||
|
||||
if (!track || !window.ga) {
|
||||
return;
|
||||
}
|
||||
|
||||
var trackData = track.toString().split('/');
|
||||
|
||||
ga('send', 'event', trackData[0], trackData[1], href);
|
||||
|
||||
if ((element.getAttribute('target') || '').toLowerCase() != '_blank') {
|
||||
setTimeout(function() { location.href = href; }, 200);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var toTopWrapEl,
|
||||
toTopEl,
|
||||
pageContentWrapEl,
|
||||
curVisible,
|
||||
curShown = false;
|
||||
function backToTopInit (labelHtml) {
|
||||
pageContentWrapEl = document.getElementById('dev_page_content_wrap');
|
||||
if (!pageContentWrapEl) {
|
||||
return false;
|
||||
}
|
||||
var t = document.createElement('div');
|
||||
|
||||
t.innerHTML = '<div class="back_to_top"><i class="icon icon-to-top"></i>' + labelHtml + '</div>';
|
||||
toTopEl = t.firstChild;
|
||||
t.innerHTML = '<a class="back_to_top_wrap' + (pageContentWrapEl.classList.contains('is_rtl') ? ' is_rtl' : '') + '" onclick="backToTopGo()"></a>';
|
||||
toTopWrapEl = t.firstChild;
|
||||
|
||||
toTopWrapEl.appendChild(toTopEl);
|
||||
document.body.appendChild(toTopWrapEl);
|
||||
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('resize', backToTopResize, false);
|
||||
window.addEventListener('scroll', backToTopScroll, false);
|
||||
}
|
||||
backToTopResize();
|
||||
}
|
||||
|
||||
function backToTopGo () {
|
||||
window.scroll(0, 0);
|
||||
backToTopScroll();
|
||||
}
|
||||
|
||||
function backToTopResize () {
|
||||
var left = getXY(pageContentWrapEl)[0],
|
||||
dwidth = Math.max(window.innerWidth, document.documentElement.clientWidth, 0),
|
||||
dheight = Math.max(window.innerHeight, document.documentElement.clientHeight);
|
||||
|
||||
curVisible = pageContentWrapEl && left > 130 && dwidth > 640;
|
||||
toTopWrapEl.style.width = left + 'px';
|
||||
toTopEl.style.height = dheight + 'px';
|
||||
backToTopScroll();
|
||||
}
|
||||
|
||||
function backToTopScroll () {
|
||||
var st = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop || document.documentElement.scrollTop;
|
||||
if ((st > 400 && curVisible) != curShown) {
|
||||
curShown = !curShown;
|
||||
if (curShown) {
|
||||
toTopWrapEl.classList.add('back_to_top_shown');
|
||||
} else {
|
||||
toTopWrapEl.classList.remove('back_to_top_shown');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removePreloadInit() {
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('load', function () {
|
||||
document.body.classList.remove('preload');
|
||||
}, false);
|
||||
} else {
|
||||
setTimeout(function () {
|
||||
document.body.classList.remove('preload');
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
function getXY (obj) {
|
||||
if (!obj) return [0, 0];
|
||||
|
||||
var left = 0, top = 0;
|
||||
if (obj.offsetParent) {
|
||||
do {
|
||||
left += obj.offsetLeft;
|
||||
top += obj.offsetTop;
|
||||
} while (obj = obj.offsetParent);
|
||||
}
|
||||
return [left, top];
|
||||
}
|
||||
|
||||
|
||||
var onDdBodyClick,
|
||||
currentDd;
|
||||
function dropdownClick (element, event) {
|
||||
var parent = element.parentNode;
|
||||
var isOpen = (parent.className || '').indexOf('open') > 0;
|
||||
if (currentDd && currentDd != parent) {
|
||||
dropdownHide(currentDd);
|
||||
}
|
||||
if (!isOpen) {
|
||||
parent.className = (parent.className || '') + ' open';
|
||||
if (!onDdBodyClick) {
|
||||
window.addEventListener('click', dropdownPageClick, false);
|
||||
}
|
||||
currentDd = parent;
|
||||
} else {
|
||||
dropdownHide(currentDd);
|
||||
currentDd = false;
|
||||
}
|
||||
event.cancelBubble = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function dropdownHide (parent) {
|
||||
parent.className = parent.className.replace(' open', '');
|
||||
}
|
||||
|
||||
function dropdownPageClick (event) {
|
||||
if (currentDd) {
|
||||
dropdownHide(currentDd);
|
||||
currentDd = false;
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHTML (html) {
|
||||
html = html || '';
|
||||
return html.replace(/&/g, '&')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/</g, '<')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function videoTogglePlay(el) {
|
||||
if (el.paused) {
|
||||
el.play();
|
||||
} else {
|
||||
el.pause();
|
||||
}
|
||||
}
|
||||
|
||||
function getDevPageNav() {
|
||||
// console.time('page nav');
|
||||
var menu = $('<ul class="nav navbar-nav navbar-default"></ul>');
|
||||
var lastLi = false;
|
||||
var items = 0;
|
||||
$('a.anchor').each(function (k, anchor) {
|
||||
var parentTag = anchor.parentNode.tagName;
|
||||
var matches = parentTag.match(/^h([34])$/i);
|
||||
var anchorName = anchor.name;
|
||||
if (!matches || !anchorName) {
|
||||
return;
|
||||
}
|
||||
anchor.id = anchor.name;
|
||||
var level = parseInt(matches[1]);
|
||||
var li = $('<li><a href="#'+ anchorName +'" data-target="#'+ anchorName +'" onmouseenter="showTitleIfOverflows(this)">' + escapeHTML(anchor.nextSibling.textContent) + '</a></li>');
|
||||
if (level == 3) {
|
||||
li.appendTo(menu);
|
||||
lastLi = li;
|
||||
} else {
|
||||
// console.log(lastLi);
|
||||
if (!lastLi) {
|
||||
return;
|
||||
}
|
||||
var subMenu = $('ul', lastLi)[0] || $('<ul class="nav"></ul>').appendTo(lastLi);
|
||||
// console.log(subMenu);
|
||||
li.appendTo(subMenu);
|
||||
}
|
||||
items++;
|
||||
});
|
||||
// console.log(items, menu);
|
||||
// console.timeEnd('page nav');
|
||||
if (items < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
function showTitleIfOverflows(element) {
|
||||
if (element &&
|
||||
element.innerText &&
|
||||
element.scrollWidth &&
|
||||
element.offsetWidth &&
|
||||
element.offsetWidth < element.scrollWidth) {
|
||||
element.setAttribute('title', element.innerText);
|
||||
}
|
||||
else if (element.removeAttribute) {
|
||||
element.removeAttribute('title');
|
||||
}
|
||||
}
|
||||
|
||||
function initDevPageNav() {
|
||||
window.hasDevPageNav = true;
|
||||
var menu = getDevPageNav();
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
var sideNavCont = $('#dev_side_nav_cont');
|
||||
if (!sideNavCont.length) {
|
||||
sideNavCont = $('#dev_page_content_wrap');
|
||||
}
|
||||
var sideNavWrap = $('<div class="dev_side_nav_wrap"></div>').prependTo(sideNavCont);
|
||||
var sideNav = $('<div class="dev_side_nav"></div>').appendTo(sideNavWrap);
|
||||
menu.appendTo(sideNav);
|
||||
$('body').css({position: 'relative'}).scrollspy({ target: '.dev_side_nav' });
|
||||
|
||||
$('body').on('activate.bs.scrollspy', function () {
|
||||
$('.dev_side_nav > ul').affix('checkPosition');
|
||||
var active_el = $('.dev_side_nav li.active').get(-1);
|
||||
if (active_el) {
|
||||
if (active_el.scrollIntoViewIfNeeded) {
|
||||
active_el.scrollIntoViewIfNeeded();
|
||||
} else if (active_el.scrollIntoView) {
|
||||
active_el.scrollIntoView(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
$('body').trigger('activate.bs.scrollspy');
|
||||
|
||||
updateMenuAffix(menu);
|
||||
}
|
||||
|
||||
function updateDevPageNav() {
|
||||
if (!window.hasDevPageNav) {
|
||||
return;
|
||||
}
|
||||
var menu = getDevPageNav() || $('<ul></ul>');
|
||||
$('.dev_side_nav > ul').replaceWith(menu);
|
||||
$('body').scrollspy('refresh');
|
||||
updateMenuAffix(menu);
|
||||
}
|
||||
|
||||
function updateMenuAffix(menu) {
|
||||
menu.affix({
|
||||
offset: {
|
||||
top: function () {
|
||||
return $('.dev_side_nav_wrap').offset().top;
|
||||
},
|
||||
bottom: function () {
|
||||
return (this.bottom = $('.footer_wrap').outerHeight(true) + 20)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function initScrollVideos(desktop) {
|
||||
var videos = document.querySelectorAll
|
||||
? document.querySelectorAll('video.tl_blog_vid_autoplay')
|
||||
: [];
|
||||
|
||||
window.pageVideos = Array.prototype.slice.apply(videos);
|
||||
if (!pageVideos.length) {
|
||||
return;
|
||||
}
|
||||
window.pageVideosPlaying = {};
|
||||
|
||||
var index = 1;
|
||||
var tgStickersCnt = document.querySelectorAll('.js-tgsticker_image').length;
|
||||
var preloadVideos = tgStickersCnt > 1 ? 0 : (tgStickersCnt ? 1 : 2);
|
||||
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||
for (var i = 0; i < pageVideos.length; i++) {
|
||||
var videoEl = pageVideos[i];
|
||||
videoEl.setAttribute('vindex', index++);
|
||||
var preloadValue = i >= preloadVideos ? (isSafari ? 'none' : 'metadata') : 'auto';
|
||||
videoEl.setAttribute('preload', preloadValue);
|
||||
videoEl.preload = preloadValue;
|
||||
if (desktop) {
|
||||
videoEl.removeAttribute('controls');
|
||||
videoEl.autoplay = false;
|
||||
videoEl.removeAttribute('autoplay');
|
||||
} else {
|
||||
videoEl.autoplay = true;
|
||||
videoEl.playsinline = true;
|
||||
videoEl.setAttribute('autoplay', 'autoplay');
|
||||
videoEl.setAttribute('playsinline', 'playsinline');
|
||||
videoEl.controls = false;
|
||||
videoEl.removeAttribute('controls');
|
||||
}
|
||||
var posterUrl = videoEl.poster;
|
||||
if (posterUrl && isSafari) {
|
||||
videoEl.parentNode.style.background = "url('" + escapeHTML(posterUrl) + "') center no-repeat";
|
||||
videoEl.parentNode.style.backgroundSize = "cover";
|
||||
videoEl.parentNode.style.lineHeight = "0";
|
||||
videoPreloadPosterDimensions(videoEl, posterUrl);
|
||||
}
|
||||
}
|
||||
if (!desktop) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', checkScrollVideos, false);
|
||||
window.addEventListener('resize', checkScrollVideos, false);
|
||||
setTimeout(checkScrollVideos, 1000);
|
||||
}
|
||||
|
||||
function checkScrollVideos() {
|
||||
var w = window,
|
||||
d = document,
|
||||
e = d.documentElement,
|
||||
g = d.getElementsByTagName('body')[0],
|
||||
winWidth = w.innerWidth || e.clientWidth || g.clientWidth,
|
||||
winHeight = w.innerHeight|| e.clientHeight|| g.clientHeight,
|
||||
scrollTop = e.scrollTop || g.scrollTop || w.pageYOffset;
|
||||
|
||||
for (var i = 0; i < pageVideos.length; i++) {
|
||||
var videoEl = pageVideos[i];
|
||||
var curIndex = videoEl.getAttribute('vindex');
|
||||
var posY = getFullOffsetY(videoEl);
|
||||
var height = videoEl.offsetHeight;
|
||||
// console.log(scrollTop, winHeight, posY, height);
|
||||
|
||||
|
||||
if (isVisibleEnough(posY, height, scrollTop, winHeight, 0.7, 0.9)) {
|
||||
if (!pageVideosPlaying[curIndex]) {
|
||||
pageVideosPlaying[curIndex] = true;
|
||||
console.log('play', videoEl);
|
||||
videoEl.play();
|
||||
}
|
||||
} else {
|
||||
if (pageVideosPlaying[curIndex]) {
|
||||
delete pageVideosPlaying[curIndex];
|
||||
console.log('pause', videoEl);
|
||||
videoEl.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function videoPreloadPosterDimensions(videoEl, posterUrl) {
|
||||
var img = new Image();
|
||||
img.onload = function () {
|
||||
if (img.width > 0 && img.height > 0) {
|
||||
videoEl.style.aspectRatio = img.width / img.height;
|
||||
}
|
||||
};
|
||||
img.src = posterUrl;
|
||||
}
|
||||
|
||||
function isVisibleEnough(boxOffset, boxSize, viewOffset, viewSize, boxThreshold, viewThreshold) {
|
||||
var boxEnd = boxOffset + boxSize;
|
||||
var viewEnd = viewOffset + viewSize;
|
||||
var viewBox = Math.min(viewEnd, boxEnd) - Math.max(boxOffset, viewOffset);
|
||||
if (viewBox < 0) {
|
||||
return false;
|
||||
}
|
||||
if (viewBox / boxSize > boxThreshold) {
|
||||
return true;
|
||||
}
|
||||
if (viewThreshold && viewBox / viewSize > viewThreshold) {
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function getFullOffsetY(el) {
|
||||
var offsetTop = el.offsetTop || 0;
|
||||
if (el.offsetParent) {
|
||||
offsetTop += getFullOffsetY(el.offsetParent);
|
||||
}
|
||||
return offsetTop;
|
||||
}
|
||||
|
||||
function redraw(el) {
|
||||
el.offsetTop + 1;
|
||||
}
|
||||
|
||||
function initRipple() {
|
||||
if (!document.querySelectorAll) return;
|
||||
var rippleTextFields = document.querySelectorAll('.textfield-item input.form-control');
|
||||
for (var i = 0; i < rippleTextFields.length; i++) {
|
||||
(function(rippleTextField) {
|
||||
function onTextRippleStart(e) {
|
||||
if (document.activeElement === rippleTextField) return;
|
||||
var rect = rippleTextField.getBoundingClientRect();
|
||||
if (e.type == 'touchstart') {
|
||||
var clientX = e.targetTouches[0].clientX;
|
||||
} else {
|
||||
var clientX = e.clientX;
|
||||
}
|
||||
var ripple = rippleTextField.parentNode.querySelector('.textfield-item-underline');
|
||||
var rippleX = (clientX - rect.left) / rippleTextField.offsetWidth * 100;
|
||||
ripple.style.transition = 'none';
|
||||
redraw(ripple);
|
||||
ripple.style.left = rippleX + '%';
|
||||
ripple.style.right = (100 - rippleX) + '%';
|
||||
redraw(ripple);
|
||||
ripple.style.left = '';
|
||||
ripple.style.right = '';
|
||||
ripple.style.transition = '';
|
||||
}
|
||||
rippleTextField.removeEventListener('mousedown', onTextRippleStart);
|
||||
rippleTextField.removeEventListener('touchstart', onTextRippleStart);
|
||||
rippleTextField.addEventListener('mousedown', onTextRippleStart);
|
||||
rippleTextField.addEventListener('touchstart', onTextRippleStart);
|
||||
})(rippleTextFields[i]);
|
||||
}
|
||||
var rippleHandlers = document.querySelectorAll('.ripple-handler');
|
||||
for (var i = 0; i < rippleHandlers.length; i++) {
|
||||
(function(rippleHandler) {
|
||||
function onRippleStart(e) {
|
||||
var rippleMask = rippleHandler.querySelector('.ripple-mask');
|
||||
if (!rippleMask) return;
|
||||
var rect = rippleMask.getBoundingClientRect();
|
||||
if (e.type == 'touchstart') {
|
||||
var clientX = e.targetTouches[0].clientX;
|
||||
var clientY = e.targetTouches[0].clientY;
|
||||
} else {
|
||||
var clientX = e.clientX;
|
||||
var clientY = e.clientY;
|
||||
}
|
||||
var rippleX = (clientX - rect.left) - rippleMask.offsetWidth / 2;
|
||||
var rippleY = (clientY - rect.top) - rippleMask.offsetHeight / 2;
|
||||
var ripple = rippleHandler.querySelector('.ripple');
|
||||
ripple.style.transition = 'none';
|
||||
redraw(ripple);
|
||||
ripple.style.transform = 'translate3d(' + rippleX + 'px, ' + rippleY + 'px, 0) scale3d(0.2, 0.2, 1)';
|
||||
ripple.style.opacity = 1;
|
||||
redraw(ripple);
|
||||
ripple.style.transform = 'translate3d(' + rippleX + 'px, ' + rippleY + 'px, 0) scale3d(1, 1, 1)';
|
||||
ripple.style.transition = '';
|
||||
|
||||
function onRippleEnd(e) {
|
||||
ripple.style.transitionDuration = '.2s';
|
||||
ripple.style.opacity = 0;
|
||||
document.removeEventListener('mouseup', onRippleEnd);
|
||||
document.removeEventListener('touchend', onRippleEnd);
|
||||
document.removeEventListener('touchcancel', onRippleEnd);
|
||||
}
|
||||
document.addEventListener('mouseup', onRippleEnd);
|
||||
document.addEventListener('touchend', onRippleEnd);
|
||||
document.addEventListener('touchcancel', onRippleEnd);
|
||||
}
|
||||
rippleHandler.removeEventListener('mousedown', onRippleStart);
|
||||
rippleHandler.removeEventListener('touchstart', onRippleStart);
|
||||
rippleHandler.addEventListener('mousedown', onRippleStart);
|
||||
rippleHandler.addEventListener('touchstart', onRippleStart);
|
||||
})(rippleHandlers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function mainInitRetinaVideos() {
|
||||
var videoEls = document.querySelectorAll('video.video__init_retina');
|
||||
var isRetina = window.devicePixelRatio >= 1.5;
|
||||
var videoEl, i, badChildren, j, badChild, sources, sourceEl;
|
||||
for (i = 0; i < videoEls.length; i++) {
|
||||
videoEl = videoEls[i];
|
||||
sources = (videoEl.getAttribute('data-sources')||'').split(',');
|
||||
sourceEl = document.createElement('source');
|
||||
sourceEl.type = 'video/mp4';
|
||||
sourceEl.src = sources[isRetina ? 1 : 0];
|
||||
videoEl.appendChild(sourceEl);
|
||||
videoEl.classList.remove('video__init_retina');
|
||||
videoEl.setAttribute('preload', 'auto');
|
||||
}
|
||||
}
|
||||
|
||||
function mainInitDemoAutoplay(videoLinkElsSelector) {
|
||||
var videoLinkEls = document.querySelectorAll(videoLinkElsSelector);
|
||||
var videoLinkEl, videoEl, i;
|
||||
for (i = 0; i < videoLinkEls.length; i++) {
|
||||
videoLinkEl = videoLinkEls[i];
|
||||
videoEl = videoLinkEl.querySelector('video');
|
||||
if (!videoEl) {
|
||||
continue;
|
||||
}
|
||||
if (videoEl.readyState > 1) {
|
||||
mainDemoVideoHover(videoLinkEl, 1);
|
||||
} else {
|
||||
videoEl.load();
|
||||
videoEl.addEventListener('loadeddata', (function(el) {
|
||||
return function () {
|
||||
setTimeout(function () {
|
||||
mainDemoVideoHover(el, 1);
|
||||
}, 0)
|
||||
}
|
||||
})(videoLinkEl), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mainDemoVideoHover(videoLinkEl, isHover) {
|
||||
var outTimeout = videoLinkEl.outTimeout;
|
||||
var curIsHover = videoLinkEl.isHover || 0;
|
||||
if (outTimeout) {
|
||||
clearTimeout(outTimeout);
|
||||
}
|
||||
if (curIsHover == isHover) {
|
||||
return false;
|
||||
}
|
||||
if (!isHover) {
|
||||
outTimeout = setTimeout(function () {
|
||||
mainDemoVideoDoHover(videoLinkEl, isHover)
|
||||
}, 100);
|
||||
videoLinkEl.outTimeout = outTimeout;
|
||||
return false;
|
||||
}
|
||||
mainDemoVideoDoHover(videoLinkEl, isHover);
|
||||
}
|
||||
|
||||
function mainDemoVideoDoHover(videoLinkEl, isHover) {
|
||||
delete videoLinkEl.outTimeout;
|
||||
|
||||
var videoEl = videoLinkEl.querySelector('video');
|
||||
if (isHover) {
|
||||
if (videoEl.readyState > 1) {
|
||||
videoLinkEl.classList.add('video_play');
|
||||
videoEl.play();
|
||||
videoLinkEl.isHover = 1;
|
||||
}
|
||||
} else {
|
||||
videoLinkEl.isHover = 0;
|
||||
}
|
||||
if (!videoEl.inited) {
|
||||
videoEl.inited = true;
|
||||
// videoEl.onended =
|
||||
videoEl.addEventListener('ended', function onVideoEnded(e) {
|
||||
if (videoLinkEl.isHover) {
|
||||
videoEl.currentTime = 0;
|
||||
videoEl.play();
|
||||
} else {
|
||||
videoEl.pause();
|
||||
videoEl.currentTime = 0;
|
||||
videoLinkEl.classList.remove('video_play')
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
function mainInitLogo(logo_url) {
|
||||
var img = new Image();
|
||||
img.onload = function() {
|
||||
var logo = document.querySelector('div.tl_main_logo');
|
||||
logo.style.backgroundImage = 'url(\'' + logo_url + '\')';
|
||||
logo.classList.add('play');
|
||||
};
|
||||
img.src = logo_url;
|
||||
}
|
||||
|
||||
function mainInitTgStickers(options) {
|
||||
options = options || {};
|
||||
if (!RLottie.isSupported) {
|
||||
if (options.unsupportedURL) {
|
||||
if (!getCookie('stel_notgs')) {
|
||||
setCookie('stel_notgs', 1, 7);
|
||||
}
|
||||
location = options.unsupportedURL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
document.querySelectorAll('.js-tgsticker_image').forEach(function (imgEl) {
|
||||
RLottie.init(imgEl, options);
|
||||
});
|
||||
}
|
||||
|
||||
function setCookie(name, value, days) {
|
||||
var expires = '';
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 86400000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
var nameEQ = name + '=';
|
||||
var ca = document.cookie.split(';');
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') {
|
||||
c = c.substr(1, c.length);
|
||||
}
|
||||
if (c.indexOf(nameEQ) == 0) {
|
||||
return c.substr(nameEQ.length, c.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function mainScrollTo(element) {
|
||||
if (typeof element === 'string') {
|
||||
element = document.querySelector(element)
|
||||
}
|
||||
if (element) {
|
||||
window.scroll(0, getFullOffsetY(element));
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
30
data/web/promote.telegram.org/js/ogvjs/ogv-demuxer-ogg.js
Normal file
30
data/web/promote.telegram.org/js/ogvjs/ogv-demuxer-ogg.js
Normal file
File diff suppressed because one or more lines are too long
272
data/web/promote.telegram.org/js/ogvjs/ogv-support.js
Normal file
272
data/web/promote.telegram.org/js/ogvjs/ogv-support.js
Normal file
|
@ -0,0 +1,272 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
//
|
||||
// -- ogv-support.js
|
||||
// https://github.com/brion/ogv.js
|
||||
// Copyright (c) 2013-2016 Brion Vibber
|
||||
//
|
||||
|
||||
(function() {
|
||||
|
||||
var OGVCompat = __webpack_require__(1),
|
||||
OGVVersion = ("1.4.2-20170425024925-504d7197");
|
||||
|
||||
if (window) {
|
||||
// 1.0-compat globals
|
||||
window.OGVCompat = OGVCompat;
|
||||
window.OGVVersion = OGVVersion;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
OGVCompat: OGVCompat,
|
||||
OGVVersion: OGVVersion
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 1 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var BogoSlow = __webpack_require__(2);
|
||||
|
||||
var OGVCompat = {
|
||||
benchmark: new BogoSlow(),
|
||||
|
||||
hasTypedArrays: function() {
|
||||
// emscripten-compiled code requires typed arrays
|
||||
return !!window.Uint32Array;
|
||||
},
|
||||
|
||||
hasWebAudio: function() {
|
||||
return !!(window.AudioContext || window.webkitAudioContext);
|
||||
},
|
||||
|
||||
hasFlash: function() {
|
||||
if (navigator.userAgent.indexOf('Trident') !== -1) {
|
||||
// We only do the ActiveX test because we only need Flash in
|
||||
// Internet Explorer 10/11. Other browsers use Web Audio directly
|
||||
// (Edge, Safari) or native playback, so there's no need to test
|
||||
// other ways of loading Flash.
|
||||
try {
|
||||
var obj = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
hasAudio: function() {
|
||||
return this.hasWebAudio() || this.hasFlash();
|
||||
},
|
||||
|
||||
isBlacklisted: function(userAgent) {
|
||||
// JIT bugs in old Safari versions
|
||||
var blacklist = [
|
||||
/\(i.* OS [67]_.* like Mac OS X\).* Mobile\/.* Safari\//,
|
||||
/\(Macintosh.* Version\/6\..* Safari\/\d/
|
||||
];
|
||||
var blacklisted = false;
|
||||
blacklist.forEach(function(regex) {
|
||||
if (userAgent.match(regex)) {
|
||||
blacklisted = true;
|
||||
}
|
||||
});
|
||||
return blacklisted;
|
||||
},
|
||||
|
||||
isSlow: function() {
|
||||
return this.benchmark.slow;
|
||||
},
|
||||
|
||||
isTooSlow: function() {
|
||||
return this.benchmark.tooSlow;
|
||||
},
|
||||
|
||||
supported: function(component) {
|
||||
if (component === 'OGVDecoder') {
|
||||
return (this.hasTypedArrays() && !this.isBlacklisted(navigator.userAgent));
|
||||
}
|
||||
if (component === 'OGVPlayer') {
|
||||
return (this.supported('OGVDecoder') && this.hasAudio() && !this.isTooSlow());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = OGVCompat;
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 2 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/**
|
||||
* A quick CPU/JS engine benchmark to guesstimate whether we're
|
||||
* fast enough to handle 360p video in JavaScript.
|
||||
*/
|
||||
function BogoSlow() {
|
||||
var self = this;
|
||||
|
||||
var timer;
|
||||
// FIXME: avoid to use window scope here
|
||||
if (window.performance && window.performance.now) {
|
||||
timer = function() {
|
||||
return window.performance.now();
|
||||
};
|
||||
} else {
|
||||
timer = function() {
|
||||
return Date.now();
|
||||
};
|
||||
}
|
||||
|
||||
var savedSpeed = null;
|
||||
function run() {
|
||||
var ops = 0;
|
||||
var fibonacci = function(n) {
|
||||
ops++;
|
||||
if (n < 2) {
|
||||
return n;
|
||||
} else {
|
||||
return fibonacci(n - 2) + fibonacci(n - 1);
|
||||
}
|
||||
};
|
||||
|
||||
var start = timer();
|
||||
|
||||
fibonacci(30);
|
||||
|
||||
var delta = timer() - start;
|
||||
savedSpeed = (ops / delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a scale value of operations/sec from the benchmark.
|
||||
* If the benchmark has already been run, uses a memoized result.
|
||||
*
|
||||
* @property {number}
|
||||
*/
|
||||
Object.defineProperty(self, 'speed', {
|
||||
get: function() {
|
||||
if (savedSpeed === null) {
|
||||
run();
|
||||
}
|
||||
return savedSpeed;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Return the defined cutoff speed value for 'slow' devices,
|
||||
* based on results measured from some test devices.
|
||||
*
|
||||
* @property {number}
|
||||
*/
|
||||
Object.defineProperty(self, 'slowCutoff', {
|
||||
get: function() {
|
||||
// 2012 Retina MacBook Pro (Safari 7) ~150,000
|
||||
// 2009 Dell T5500 (IE 11) ~100,000
|
||||
// iPad Air (iOS 7) ~65,000
|
||||
// 2010 MBP / OS X 10.9 (Safari 7) ~62,500
|
||||
// 2010 MBP / Win7 VM (IE 11) ~50,000+-
|
||||
// ^ these play 360p ok
|
||||
// ----------- line of moderate doom ----------
|
||||
return 50000;
|
||||
// v these play 160p ok
|
||||
// iPad Mini non-Retina (iOS 8 beta) ~25,000
|
||||
// Dell Inspiron Duo (IE 11) ~25,000
|
||||
// Surface RT (IE 11) ~18,000
|
||||
// iPod Touch 5th-gen (iOS 8 beta) ~16,000
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Return the defined cutoff speed value for 'too slow' devices,
|
||||
* based on results measured from some test devices.
|
||||
*
|
||||
* No longer used.
|
||||
*
|
||||
* @property {number}
|
||||
* @deprecated
|
||||
*/
|
||||
Object.defineProperty(self, 'tooSlowCutoff', {
|
||||
get: function() {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 'Slow' devices can play audio and should sorta play our
|
||||
* extra-tiny Wikimedia 160p15 transcodes
|
||||
*
|
||||
* @property {boolean}
|
||||
*/
|
||||
Object.defineProperty(self, 'slow', {
|
||||
get: function() {
|
||||
return (self.speed < self.slowCutoff);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 'Too slow' devices aren't reliable at all
|
||||
*
|
||||
* @property {boolean}
|
||||
*/
|
||||
Object.defineProperty(self, 'tooSlow', {
|
||||
get: function() {
|
||||
return (self.speed < self.tooSlowCutoff);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = BogoSlow;
|
||||
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
701
data/web/promote.telegram.org/js/ogvjs/ogv-worker-audio.js
Normal file
701
data/web/promote.telegram.org/js/ogvjs/ogv-worker-audio.js
Normal file
|
@ -0,0 +1,701 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__(1);
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 1 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var OGVWorkerSupport = __webpack_require__(2);
|
||||
|
||||
var proxy = new OGVWorkerSupport([
|
||||
'loadedMetadata',
|
||||
'audioFormat',
|
||||
'audioBuffer',
|
||||
'cpuTime'
|
||||
], {
|
||||
init: function(args, callback) {
|
||||
this.target.init(callback);
|
||||
},
|
||||
|
||||
processHeader: function(args, callback) {
|
||||
this.target.processHeader(args[0], function(ok) {
|
||||
callback([ok]);
|
||||
});
|
||||
},
|
||||
|
||||
processAudio: function(args, callback) {
|
||||
this.target.processAudio(args[0], function(ok) {
|
||||
callback([ok]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = proxy;
|
||||
|
||||
/***/ }),
|
||||
/* 2 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var OGVLoader = __webpack_require__(3);
|
||||
|
||||
/**
|
||||
* Web Worker wrapper for codec fun
|
||||
*/
|
||||
function OGVWorkerSupport(propList, handlers) {
|
||||
|
||||
var transferables = (function() {
|
||||
var buffer = new ArrayBuffer(1024),
|
||||
bytes = new Uint8Array(buffer);
|
||||
try {
|
||||
postMessage({
|
||||
action: 'transferTest',
|
||||
bytes: bytes
|
||||
}, [buffer]);
|
||||
if (buffer.byteLength) {
|
||||
// No transferable support
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
|
||||
var self = this;
|
||||
self.target = null;
|
||||
|
||||
var sentProps = {},
|
||||
pendingEvents = [];
|
||||
|
||||
function copyObject(obj) {
|
||||
var copy = {};
|
||||
for (var prop in obj) {
|
||||
if (obj.hasOwnProperty(prop)) {
|
||||
copy[prop] = obj[prop];
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
function copyAudioBuffer(data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
} else {
|
||||
// Array of Float32Arrays
|
||||
var copy = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
copy[i] = new Float32Array(data[i]);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
function handleEvent(data) {
|
||||
handlers[data.action].call(self, data.args, function(args) {
|
||||
args = args || [];
|
||||
|
||||
// Collect and send any changed properties...
|
||||
var props = {},
|
||||
transfers = [];
|
||||
propList.forEach(function(propName) {
|
||||
var propVal = self.target[propName];
|
||||
|
||||
if (sentProps[propName] !== propVal) {
|
||||
// Save this value for later reference...
|
||||
sentProps[propName] = propVal;
|
||||
|
||||
if (propName == 'duration' && isNaN(propVal) && isNaN(sentProps[propName])) {
|
||||
// NaN is not === itself. Nice!
|
||||
// no need to update it here.
|
||||
} else if (propName == 'audioBuffer') {
|
||||
// Don't send the entire emscripten heap!
|
||||
propVal = copyAudioBuffer(propVal);
|
||||
props[propName] = propVal;
|
||||
if (propVal) {
|
||||
for (var i = 0; i < propVal.length; i++) {
|
||||
transfers.push(propVal[i].buffer);
|
||||
}
|
||||
}
|
||||
} else if (propName == 'frameBuffer') {
|
||||
// We already extract ahead of time now,
|
||||
// so transfer the small buffers.
|
||||
props[propName] = propVal;
|
||||
if (propVal) {
|
||||
transfers.push(propVal.y.bytes.buffer);
|
||||
transfers.push(propVal.u.bytes.buffer);
|
||||
transfers.push(propVal.v.bytes.buffer);
|
||||
}
|
||||
} else {
|
||||
props[propName] = propVal;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var out = {
|
||||
action: 'callback',
|
||||
callbackId: data.callbackId,
|
||||
args: args,
|
||||
props: props
|
||||
};
|
||||
if (transferables) {
|
||||
postMessage(out, transfers);
|
||||
} else {
|
||||
postMessage(out);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handlers.construct = function(args, callback) {
|
||||
var className = args[0],
|
||||
options = args[1];
|
||||
|
||||
OGVLoader.loadClass(className, function(classObj) {
|
||||
self.target = new classObj(options);
|
||||
callback();
|
||||
while (pendingEvents.length) {
|
||||
handleEvent(pendingEvents.shift());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
addEventListener('message', function workerOnMessage(event) {
|
||||
var data = event.data;
|
||||
if (!data || typeof data !== 'object') {
|
||||
// invalid
|
||||
return;
|
||||
} else if (data.action == 'transferTest') {
|
||||
// ignore
|
||||
} else if (typeof data.action !== 'string' || typeof data.callbackId !== 'string' || typeof data.args !== 'object') {
|
||||
console.log('invalid message data', data);
|
||||
} else if (!(data.action in handlers)) {
|
||||
console.log('invalid message action', data.action);
|
||||
} else if (data.action == 'construct') {
|
||||
// always handle constructor
|
||||
handleEvent(data);
|
||||
} else if (!self.target) {
|
||||
// queue until constructed
|
||||
pendingEvents.push(data);
|
||||
} else {
|
||||
handleEvent(data);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
module.exports = OGVWorkerSupport;
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 3 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var OGVVersion = ("1.4.2-20170425024925-504d7197");
|
||||
|
||||
(function() {
|
||||
var global = this;
|
||||
|
||||
var scriptMap = {
|
||||
OGVDemuxerOgg: 'ogv-demuxer-ogg.js',
|
||||
OGVDemuxerOggW: 'ogv-demuxer-ogg-wasm.js',
|
||||
OGVDemuxerWebM: 'ogv-demuxer-webm.js',
|
||||
OGVDemuxerWebMW: 'ogv-demuxer-webm-wasm.js',
|
||||
OGVDecoderAudioOpus: 'ogv-decoder-audio-opus.js',
|
||||
OGVDecoderAudioOpusW: 'ogv-decoder-audio-opus-wasm.js',
|
||||
OGVDecoderAudioVorbis: 'ogv-decoder-audio-vorbis.js',
|
||||
OGVDecoderAudioVorbisW: 'ogv-decoder-audio-vorbis-wasm.js',
|
||||
OGVDecoderVideoTheora: 'ogv-decoder-video-theora.js',
|
||||
OGVDecoderVideoTheoraW: 'ogv-decoder-video-theora-wasm.js',
|
||||
OGVDecoderVideoVP8: 'ogv-decoder-video-vp8.js',
|
||||
OGVDecoderVideoVP8W: 'ogv-decoder-video-vp8-wasm.js',
|
||||
OGVDecoderVideoVP8MT: 'ogv-decoder-video-vp8-mt.js',
|
||||
OGVDecoderVideoVP9: 'ogv-decoder-video-vp9.js',
|
||||
OGVDecoderVideoVP9W: 'ogv-decoder-video-vp9-wasm.js',
|
||||
OGVDecoderVideoVP9MT: 'ogv-decoder-video-vp9-mt.js'
|
||||
};
|
||||
|
||||
// @fixme make this less awful
|
||||
var proxyTypes = {
|
||||
OGVDecoderAudioOpus: 'audio',
|
||||
OGVDecoderAudioOpusW: 'audio',
|
||||
OGVDecoderAudioVorbis: 'audio',
|
||||
OGVDecoderAudioVorbisW: 'audio',
|
||||
OGVDecoderVideoTheora: 'video',
|
||||
OGVDecoderVideoTheoraW: 'video',
|
||||
OGVDecoderVideoVP8: 'video',
|
||||
OGVDecoderVideoVP8W: 'video',
|
||||
OGVDecoderVideoVP9: 'video',
|
||||
OGVDecoderVideoVP9W: 'video'
|
||||
};
|
||||
var proxyInfo = {
|
||||
audio: {
|
||||
proxy: __webpack_require__(4),
|
||||
worker: 'ogv-worker-audio.js',
|
||||
},
|
||||
video: {
|
||||
proxy: __webpack_require__(6),
|
||||
worker: 'ogv-worker-video.js'
|
||||
}
|
||||
}
|
||||
|
||||
function urlForClass(className) {
|
||||
var scriptName = scriptMap[className];
|
||||
if (scriptName) {
|
||||
return urlForScript(scriptName);
|
||||
} else {
|
||||
throw new Error('asked for URL for unknown class ' + className);
|
||||
}
|
||||
};
|
||||
|
||||
function urlForScript(scriptName) {
|
||||
if (scriptName) {
|
||||
var base = OGVLoader.base;
|
||||
if (base === undefined) {
|
||||
base = '';
|
||||
} else {
|
||||
base += '/';
|
||||
}
|
||||
return base + scriptName + '?version=' + encodeURIComponent(OGVVersion);
|
||||
} else {
|
||||
throw new Error('asked for URL for unknown script ' + scriptName);
|
||||
}
|
||||
};
|
||||
|
||||
var scriptStatus = {},
|
||||
scriptCallbacks = {};
|
||||
function loadWebScript(src, callback) {
|
||||
if (scriptStatus[src] == 'done') {
|
||||
callback();
|
||||
} else if (scriptStatus[src] == 'loading') {
|
||||
scriptCallbacks[src].push(callback);
|
||||
} else {
|
||||
scriptStatus[src] = 'loading';
|
||||
scriptCallbacks[src] = [callback];
|
||||
|
||||
var scriptNode = document.createElement('script');
|
||||
function done(event) {
|
||||
var callbacks = scriptCallbacks[src];
|
||||
delete scriptCallbacks[src];
|
||||
scriptStatus[src] = 'done';
|
||||
|
||||
callbacks.forEach(function(cb) {
|
||||
cb();
|
||||
});
|
||||
}
|
||||
scriptNode.addEventListener('load', done);
|
||||
scriptNode.addEventListener('error', done);
|
||||
scriptNode.src = src;
|
||||
document.querySelector('head').appendChild(scriptNode);
|
||||
}
|
||||
}
|
||||
|
||||
function loadWebAssembly(src, callback) {
|
||||
if (!src.match(/-wasm\.js/)) {
|
||||
callback(null);
|
||||
} else {
|
||||
var wasmSrc = src.replace(/-wasm\.js/, '-wasm.wasm');
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onload = function() {
|
||||
callback(xhr.response);
|
||||
};
|
||||
xhr.onerror = function() {
|
||||
callback(null);
|
||||
};
|
||||
xhr.open('GET', wasmSrc);
|
||||
xhr.send();
|
||||
}
|
||||
}
|
||||
|
||||
function defaultBase() {
|
||||
if (typeof global.window === 'object') {
|
||||
|
||||
// for browser, try to autodetect
|
||||
var scriptNodes = document.querySelectorAll('script'),
|
||||
regex = /^(?:|(.*)\/)ogv(?:-support)?\.js(?:\?|#|$)/,
|
||||
path,
|
||||
matches;
|
||||
for (var i = 0; i < scriptNodes.length; i++) {
|
||||
path = scriptNodes[i].getAttribute('src');
|
||||
if (path) {
|
||||
matches = path.match(regex);
|
||||
if (matches) {
|
||||
return matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined; // current dir
|
||||
|
||||
} else {
|
||||
|
||||
// for workers, assume current directory
|
||||
// if not a worker, too bad.
|
||||
return undefined;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var OGVLoader = {
|
||||
base: defaultBase(),
|
||||
|
||||
loadClass: function(className, callback, options) {
|
||||
options = options || {};
|
||||
if (options.worker) {
|
||||
this.workerProxy(className, callback);
|
||||
return;
|
||||
}
|
||||
var url = urlForClass(className);
|
||||
loadWebAssembly(url, function(wasmBinary) {
|
||||
function wasmClassWrapper(options) {
|
||||
options = options || {};
|
||||
if (wasmBinary !== null) {
|
||||
options.wasmBinary = wasmBinary;
|
||||
}
|
||||
return new global[className](options);
|
||||
}
|
||||
if (typeof global[className] === 'function') {
|
||||
// already loaded!
|
||||
callback(wasmClassWrapper);
|
||||
} else if (typeof global.window === 'object') {
|
||||
loadWebScript(url, function() {
|
||||
callback(wasmClassWrapper);
|
||||
});
|
||||
} else if (typeof global.importScripts === 'function') {
|
||||
// worker has convenient sync importScripts
|
||||
global.importScripts(url);
|
||||
callback(wasmClassWrapper);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
workerProxy: function(className, callback) {
|
||||
var proxyType = proxyTypes[className],
|
||||
info = proxyInfo[proxyType];
|
||||
|
||||
if (!info) {
|
||||
throw new Error('Requested worker for class with no proxy: ' + className);
|
||||
}
|
||||
|
||||
var proxyClass = info.proxy,
|
||||
workerScript = info.worker,
|
||||
codecUrl = urlForScript(scriptMap[className]),
|
||||
workerUrl = urlForScript(workerScript),
|
||||
worker;
|
||||
|
||||
var construct = function(options) {
|
||||
return new proxyClass(worker, className, options);
|
||||
};
|
||||
|
||||
if (workerUrl.match(/^https?:|\/\//i)) {
|
||||
// Can't load workers natively cross-domain, but if CORS
|
||||
// is set up we can fetch the worker stub and the desired
|
||||
// class and load them from a blob.
|
||||
var getCodec,
|
||||
getWorker,
|
||||
codecResponse,
|
||||
workerResponse,
|
||||
codecLoaded = false,
|
||||
workerLoaded = false,
|
||||
blob;
|
||||
|
||||
function completionCheck() {
|
||||
if ((codecLoaded == true) && (workerLoaded == true)) {
|
||||
try {
|
||||
blob = new Blob([codecResponse + " " + workerResponse], {type: 'application/javascript'});
|
||||
} catch (e) { // Backwards-compatibility
|
||||
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
|
||||
blob = new BlobBuilder();
|
||||
blob.append(codecResponse + " " + workerResponse);
|
||||
blob = blob.getBlob();
|
||||
}
|
||||
// Create the web worker
|
||||
worker = new Worker(URL.createObjectURL(blob));
|
||||
callback(construct);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the codec
|
||||
getCodec = new XMLHttpRequest();
|
||||
getCodec.open("GET", codecUrl, true);
|
||||
getCodec.onreadystatechange = function() {
|
||||
if(getCodec.readyState == 4 && getCodec.status == 200) {
|
||||
codecResponse = getCodec.responseText;
|
||||
// Update the codec response loaded flag
|
||||
codecLoaded = true;
|
||||
completionCheck();
|
||||
}
|
||||
};
|
||||
getCodec.send();
|
||||
|
||||
// Load the worker
|
||||
getWorker = new XMLHttpRequest();
|
||||
getWorker.open("GET", workerUrl, true);
|
||||
getWorker.onreadystatechange = function() {
|
||||
if(getWorker.readyState == 4 && getWorker.status == 200) {
|
||||
workerResponse = getWorker.responseText;
|
||||
// Update the worker response loaded flag
|
||||
workerLoaded = true;
|
||||
completionCheck();
|
||||
}
|
||||
};
|
||||
getWorker.send();
|
||||
} else {
|
||||
// Local URL; load it directly for simplicity.
|
||||
worker = new Worker(workerUrl);
|
||||
callback(construct);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = OGVLoader;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 4 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var OGVProxyClass = __webpack_require__(5);
|
||||
|
||||
var OGVDecoderAudioProxy = OGVProxyClass({
|
||||
loadedMetadata: false,
|
||||
audioFormat: null,
|
||||
audioBuffer: null,
|
||||
cpuTime: 0
|
||||
}, {
|
||||
init: function(callback) {
|
||||
this.proxy('init', [], callback);
|
||||
},
|
||||
|
||||
processHeader: function(data, callback) {
|
||||
this.proxy('processHeader', [data], callback, [data]);
|
||||
},
|
||||
|
||||
processAudio: function(data, callback) {
|
||||
this.proxy('processAudio', [data], callback, [data]);
|
||||
},
|
||||
|
||||
close: function() {
|
||||
this.terminate();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = OGVDecoderAudioProxy;
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 5 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/**
|
||||
* Proxy object for web worker interface for codec classes.
|
||||
*
|
||||
* Used by the high-level player interface.
|
||||
*
|
||||
* @author Brion Vibber <brion@pobox.com>
|
||||
* @copyright 2015
|
||||
* @license MIT-style
|
||||
*/
|
||||
function OGVProxyClass(initialProps, methods) {
|
||||
return function(worker, className, options) {
|
||||
options = options || {};
|
||||
var self = this;
|
||||
|
||||
var transferables = (function() {
|
||||
var buffer = new ArrayBuffer(1024),
|
||||
bytes = new Uint8Array(buffer);
|
||||
try {
|
||||
worker.postMessage({
|
||||
action: 'transferTest',
|
||||
bytes: bytes
|
||||
}, [buffer]);
|
||||
if (buffer.byteLength) {
|
||||
// No transferable support
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
|
||||
// Set up proxied property getters
|
||||
var props = {};
|
||||
for (var iPropName in initialProps) {
|
||||
if (initialProps.hasOwnProperty(iPropName)) {
|
||||
(function(propName) {
|
||||
props[propName] = initialProps[propName];
|
||||
Object.defineProperty(self, propName, {
|
||||
get: function getProperty() {
|
||||
return props[propName];
|
||||
}
|
||||
});
|
||||
})(iPropName);
|
||||
}
|
||||
}
|
||||
|
||||
// Current player wants to avoid async confusion.
|
||||
var processingQueue = 0;
|
||||
Object.defineProperty(self, 'processing', {
|
||||
get: function() {
|
||||
return (processingQueue > 0);
|
||||
}
|
||||
});
|
||||
|
||||
// Set up proxied methods
|
||||
for (var method in methods) {
|
||||
if (methods.hasOwnProperty(method)) {
|
||||
self[method] = methods[method];
|
||||
}
|
||||
}
|
||||
|
||||
// And some infrastructure!
|
||||
var messageCount = 0,
|
||||
pendingCallbacks = {};
|
||||
this.proxy = function(action, args, callback, transfers) {
|
||||
if (!worker) {
|
||||
throw 'Tried to call "' + action + '" method on closed proxy object';
|
||||
}
|
||||
var callbackId = 'callback-' + (++messageCount) + '-' + action;
|
||||
if (callback) {
|
||||
pendingCallbacks[callbackId] = callback;
|
||||
}
|
||||
var out = {
|
||||
'action': action,
|
||||
'callbackId': callbackId,
|
||||
'args': args || []
|
||||
};
|
||||
processingQueue++;
|
||||
if (transferables) {
|
||||
worker.postMessage(out, transfers || []);
|
||||
} else {
|
||||
worker.postMessage(out);
|
||||
}
|
||||
};
|
||||
this.terminate = function() {
|
||||
if (worker) {
|
||||
worker.terminate();
|
||||
worker = null;
|
||||
processingQueue = 0;
|
||||
pendingCallbacks = {};
|
||||
}
|
||||
};
|
||||
|
||||
worker.addEventListener('message', function proxyOnMessage(event) {
|
||||
processingQueue--;
|
||||
if (event.data.action !== 'callback') {
|
||||
// ignore
|
||||
return;
|
||||
}
|
||||
|
||||
var data = event.data,
|
||||
callbackId = data.callbackId,
|
||||
args = data.args,
|
||||
callback = pendingCallbacks[callbackId];
|
||||
|
||||
// Save any updated properties returned to us...
|
||||
if (data.props) {
|
||||
for (var propName in data.props) {
|
||||
if (data.props.hasOwnProperty(propName)) {
|
||||
props[propName] = data.props[propName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
delete pendingCallbacks[callbackId];
|
||||
callback.apply(this, args);
|
||||
}
|
||||
});
|
||||
|
||||
// Tell the proxy to load and initialize the appropriate class
|
||||
self.proxy('construct', [className, options], function() {});
|
||||
|
||||
return self;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = OGVProxyClass;
|
||||
|
||||
/***/ }),
|
||||
/* 6 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var OGVProxyClass = __webpack_require__(5);
|
||||
|
||||
var OGVDecoderVideoProxy = OGVProxyClass({
|
||||
loadedMetadata: false,
|
||||
videoFormat: null,
|
||||
frameBuffer: null,
|
||||
cpuTime: 0
|
||||
}, {
|
||||
init: function(callback) {
|
||||
this.proxy('init', [], callback);
|
||||
},
|
||||
|
||||
processHeader: function(data, callback) {
|
||||
this.proxy('processHeader', [data], callback, [data]);
|
||||
},
|
||||
|
||||
processFrame: function(data, callback) {
|
||||
this.proxy('processFrame', [data], callback, [data]);
|
||||
},
|
||||
|
||||
close: function() {
|
||||
this.terminate();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = OGVDecoderVideoProxy;
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
9663
data/web/promote.telegram.org/js/ogvjs/ogv.js
Normal file
9663
data/web/promote.telegram.org/js/ogvjs/ogv.js
Normal file
File diff suppressed because it is too large
Load diff
1
data/web/promote.telegram.org/js/pako-inflate.min.js
vendored
Normal file
1
data/web/promote.telegram.org/js/pako-inflate.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4952
data/web/promote.telegram.org/js/promote.js
Normal file
4952
data/web/promote.telegram.org/js/promote.js
Normal file
File diff suppressed because it is too large
Load diff
1
data/web/promote.telegram.org/js/rlottie-wasm.js
Normal file
1
data/web/promote.telegram.org/js/rlottie-wasm.js
Normal file
File diff suppressed because one or more lines are too long
1
data/web/promote.telegram.org/js/tchart.min.js
vendored
Normal file
1
data/web/promote.telegram.org/js/tchart.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
209
data/web/promote.telegram.org/js/tgsticker-worker.js
Normal file
209
data/web/promote.telegram.org/js/tgsticker-worker.js
Normal file
|
@ -0,0 +1,209 @@
|
|||
importScripts('rlottie-wasm.js');
|
||||
importScripts('pako-inflate.min.js');
|
||||
|
||||
function RLottieItem(reqId, jsString, width, height, fps) {
|
||||
this.stringOnWasmHeap = null;
|
||||
this.handle = null;
|
||||
this.frameCount = 0;
|
||||
|
||||
this.reqId = reqId;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.fps = Math.max(1, Math.min(60, fps || 60));
|
||||
|
||||
this.dead = false;
|
||||
|
||||
this.init(jsString, width, height);
|
||||
|
||||
reply('loaded', this.reqId, this.frameCount, this.fps);
|
||||
}
|
||||
|
||||
RLottieItem.prototype.init = function(jsString) {
|
||||
try {
|
||||
this.handle = RLottieWorker.Api.init();
|
||||
|
||||
this.stringOnWasmHeap = allocate(intArrayFromString(jsString), 'i8', 0);
|
||||
|
||||
this.frameCount = RLottieWorker.Api.loadFromData(this.handle, this.stringOnWasmHeap);
|
||||
|
||||
RLottieWorker.Api.resize(this.handle, this.width, this.height);
|
||||
} catch(e) {
|
||||
console.error('init RLottieItem error:', e);
|
||||
}
|
||||
};
|
||||
|
||||
RLottieItem.prototype.render = function(frameNo, clamped) {
|
||||
if (this.dead) return;
|
||||
|
||||
var realFrameNo = frameNo;
|
||||
if (frameNo < 0) {
|
||||
realFrameNo = 0;
|
||||
} else if (frameNo >= this.frameCount) {
|
||||
realFrameNo = this.frameCount - 1;
|
||||
}
|
||||
|
||||
try {
|
||||
RLottieWorker.Api.render(this.handle, realFrameNo);
|
||||
|
||||
var bufferPointer = RLottieWorker.Api.buffer(this.handle);
|
||||
|
||||
var data = Module.HEAPU8.subarray(bufferPointer, bufferPointer + (this.width * this.height * 4));
|
||||
|
||||
if(!clamped) {
|
||||
clamped = new Uint8ClampedArray(data);
|
||||
} else {
|
||||
clamped.set(data);
|
||||
}
|
||||
|
||||
reply('frame', this.reqId, frameNo, clamped);
|
||||
} catch(e) {
|
||||
console.error('Render error:', e);
|
||||
this.dead = true;
|
||||
}
|
||||
};
|
||||
|
||||
RLottieItem.prototype.destroy = function() {
|
||||
this.dead = true;
|
||||
|
||||
RLottieWorker.Api.destroy(this.handle);
|
||||
};
|
||||
|
||||
var RLottieWorker = (function() {
|
||||
var worker = {};
|
||||
worker.Api = {};
|
||||
|
||||
function initApi() {
|
||||
worker.Api = {
|
||||
init: Module.cwrap('lottie_init', '', []),
|
||||
destroy: Module.cwrap('lottie_destroy', '', ['number']),
|
||||
resize: Module.cwrap('lottie_resize', '', ['number', 'number', 'number']),
|
||||
buffer: Module.cwrap('lottie_buffer', 'number', ['number']),
|
||||
frameCount: Module.cwrap('lottie_frame_count', 'number', ['number']),
|
||||
render: Module.cwrap('lottie_render', '', ['number', 'number']),
|
||||
loadFromData: Module.cwrap('lottie_load_from_data', 'number', ['number', 'number']),
|
||||
};
|
||||
}
|
||||
|
||||
worker.init = function() {
|
||||
initApi();
|
||||
reply('ready');
|
||||
};
|
||||
|
||||
return worker;
|
||||
}());
|
||||
|
||||
Module.onRuntimeInitialized = function() {
|
||||
RLottieWorker.init();
|
||||
};
|
||||
|
||||
var items = {};
|
||||
var queryableFunctions = {
|
||||
loadFromData: function(reqId, url, width, height) {
|
||||
getUrlContent(url, function(err, data) {
|
||||
if (err) {
|
||||
return console.warn('Can\'t fetch file ' + url, err);
|
||||
}
|
||||
try {
|
||||
var json = pako.inflate(data, {to: 'string'});
|
||||
var json_parsed = JSON.parse(json);
|
||||
items[reqId] = new RLottieItem(reqId, json, width, height, json_parsed.fr);
|
||||
} catch (e) {
|
||||
return console.warn('Invalid file ' + url);
|
||||
}
|
||||
});
|
||||
},
|
||||
destroy: function(reqId) {
|
||||
items[reqId].destroy();
|
||||
delete items[reqId];
|
||||
},
|
||||
renderFrame: function(reqId, frameNo, clamped) {
|
||||
items[reqId].render(frameNo, clamped);
|
||||
}
|
||||
};
|
||||
|
||||
function defaultReply(message) {
|
||||
// your default PUBLIC function executed only when main page calls the queryableWorker.postMessage() method directly
|
||||
// do something
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when run in WebKit derived browsers.
|
||||
* This is used as a workaround for a memory leak in Safari caused by using Transferable objects to
|
||||
* transfer data between WebWorkers and the main thread.
|
||||
* https://github.com/mapbox/mapbox-gl-js/issues/8771
|
||||
*
|
||||
* This should be removed once the underlying Safari issue is fixed.
|
||||
*
|
||||
* @private
|
||||
* @param scope {WindowOrWorkerGlobalScope} Since this function is used both on the main thread and WebWorker context,
|
||||
* let the calling scope pass in the global scope object.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
var _isSafari = null;
|
||||
function isSafari(scope) {
|
||||
if(_isSafari == null) {
|
||||
var userAgent = scope.navigator ? scope.navigator.userAgent : null;
|
||||
_isSafari = !!scope.safari ||
|
||||
!!(userAgent && (/\b(iPad|iPhone|iPod)\b/.test(userAgent) || (!!userAgent.match('Safari') && !userAgent.match('Chrome'))));
|
||||
}
|
||||
return _isSafari;
|
||||
}
|
||||
|
||||
function reply() {
|
||||
if(arguments.length < 1) {
|
||||
throw new TypeError('reply - not enough arguments');
|
||||
}
|
||||
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if(isSafari(self)) {
|
||||
postMessage({ 'queryMethodListener': arguments[0], 'queryMethodArguments': args });
|
||||
} else {
|
||||
var transfer = [];
|
||||
for(var i = 0; i < args.length; i++) {
|
||||
if(args[i] instanceof ArrayBuffer) {
|
||||
transfer.push(args[i]);
|
||||
}
|
||||
|
||||
if(args[i].buffer && args[i].buffer instanceof ArrayBuffer) {
|
||||
transfer.push(args[i].buffer);
|
||||
}
|
||||
}
|
||||
|
||||
postMessage({ 'queryMethodListener': arguments[0], 'queryMethodArguments': args }, transfer);
|
||||
}
|
||||
}
|
||||
|
||||
onmessage = function(oEvent) {
|
||||
if(oEvent.data instanceof Object && oEvent.data.hasOwnProperty('queryMethod') && oEvent.data.hasOwnProperty('queryMethodArguments')) {
|
||||
queryableFunctions[oEvent.data.queryMethod].apply(self, oEvent.data.queryMethodArguments);
|
||||
} else {
|
||||
defaultReply(oEvent.data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
function getUrlContent(path, callback) {
|
||||
try {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', path, true);
|
||||
if ('responseType' in xhr) {
|
||||
xhr.responseType = 'arraybuffer';
|
||||
}
|
||||
if (xhr.overrideMimeType) {
|
||||
xhr.overrideMimeType('text/plain; charset=x-user-defined');
|
||||
}
|
||||
xhr.onreadystatechange = function (event) {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status === 200 || xhr.status === 0) {
|
||||
callback(null, xhr.response || xhr.responseText);
|
||||
} else {
|
||||
callback(new Error('Ajax error: ' + this.status + ' ' + this.statusText));
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
} catch (e) {
|
||||
callback(new Error(e));
|
||||
}
|
||||
};
|
808
data/web/promote.telegram.org/js/tgsticker.js
Normal file
808
data/web/promote.telegram.org/js/tgsticker.js
Normal file
|
@ -0,0 +1,808 @@
|
|||
var RLottie = (function () {
|
||||
var rlottie = {}, apiInitStarted = false, apiInited = false, initCallbacks = [];
|
||||
var deviceRatio = window.devicePixelRatio || 1;
|
||||
|
||||
var startTime = +(new Date());
|
||||
function dT() {
|
||||
return '[' + ((+(new Date()) - startTime)/ 1000.0) + '] ';
|
||||
}
|
||||
|
||||
rlottie.Api = {};
|
||||
rlottie.players = Object.create(null);;
|
||||
rlottie.WORKERS_LIMIT = 4;
|
||||
|
||||
var reqId = 0;
|
||||
var mainLoopAf = false;
|
||||
var mainLoopTo = false;
|
||||
var mainLoopInited = false;
|
||||
var checkViewportDate = false;
|
||||
var lastRenderDate = false;
|
||||
|
||||
var userAgent = window.navigator.userAgent;
|
||||
var isSafari = !!window.safari ||
|
||||
!!(userAgent && (/\b(iPad|iPhone|iPod)\b/.test(userAgent) || (!!userAgent.match('Safari') && !userAgent.match('Chrome'))));
|
||||
var isRAF = isSafari;
|
||||
rlottie.isSafari = isSafari;
|
||||
|
||||
function wasmIsSupported() {
|
||||
try {
|
||||
if (typeof WebAssembly === 'object' &&
|
||||
typeof WebAssembly.instantiate === 'function') {
|
||||
const module = new WebAssembly.Module(Uint8Array.of(
|
||||
0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00
|
||||
));
|
||||
if (module instanceof WebAssembly.Module) {
|
||||
return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isSupported() {
|
||||
return (
|
||||
wasmIsSupported() &&
|
||||
typeof Uint8ClampedArray !== 'undefined' &&
|
||||
typeof Worker !== 'undefined' &&
|
||||
typeof ImageData !== 'undefined'
|
||||
);
|
||||
}
|
||||
|
||||
rlottie.isSupported = isSupported();
|
||||
|
||||
function mainLoop() {
|
||||
var key, rlPlayer, delta, rendered;
|
||||
var isEmpty = true;
|
||||
var now = +Date.now();
|
||||
var checkViewport = !checkViewportDate || (now - checkViewportDate) > 1000;
|
||||
for (key in rlottie.players) {
|
||||
rlPlayer = rlottie.players[key];
|
||||
if (rlPlayer &&
|
||||
rlPlayer.frameCount) {
|
||||
delta = now - rlPlayer.frameThen;
|
||||
if (delta > rlPlayer.frameInterval) {
|
||||
rendered = render(rlPlayer, checkViewport);
|
||||
if (rendered) {
|
||||
lastRenderDate = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// var delay = !lastRenderDate || now - lastRenderDate < 100 ? 16 : 500;
|
||||
var delay = 16;
|
||||
if (delay < 20 && isRAF) {
|
||||
mainLoopAf = requestAnimationFrame(mainLoop)
|
||||
} else {
|
||||
mainLoopTo = setTimeout(mainLoop, delay);
|
||||
}
|
||||
mainLoopInited = true;
|
||||
if (checkViewport) {
|
||||
checkViewportDate = now;
|
||||
}
|
||||
}
|
||||
function setupMainLoop() {
|
||||
var isEmpty = true, forceRender = false, rlPlayer;
|
||||
for (key in rlottie.players) {
|
||||
rlPlayer = rlottie.players[key];
|
||||
if (rlPlayer &&
|
||||
rlPlayer.frameCount) {
|
||||
if (rlPlayer.forceRender) {
|
||||
forceRender = true;
|
||||
}
|
||||
isEmpty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mainLoopInited === isEmpty || forceRender) {
|
||||
mainLoopAf && cancelAnimationFrame(mainLoopAf);
|
||||
mainLoopTo && clearTimeout(mainLoopTo);
|
||||
mainLoopInited = false;
|
||||
if (!isEmpty) {
|
||||
if (isRAF) {
|
||||
mainLoopAf = requestAnimationFrame(mainLoop);
|
||||
} else {
|
||||
mainLoopTo = setTimeout(mainLoop, 0);
|
||||
}
|
||||
mainLoopInited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initApi(callback) {
|
||||
if (apiInited) {
|
||||
callback && callback();
|
||||
} else {
|
||||
callback && initCallbacks.push(callback);
|
||||
if (!apiInitStarted) {
|
||||
console.log(dT(), 'tgsticker init');
|
||||
apiInitStarted = true;
|
||||
QueryableWorkerProxy.init('/js/tgsticker-worker.js?14', rlottie.WORKERS_LIMIT, function() {
|
||||
apiInited = true;
|
||||
for (var i = 0; i < initCallbacks.length; i++) {
|
||||
initCallbacks[i]();
|
||||
}
|
||||
initCallbacks = [];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function destroyWorkers() {
|
||||
QueryableWorkerProxy.destroy();
|
||||
apiInitStarted = apiInited = false;
|
||||
}
|
||||
|
||||
function initPlayer(el, options) {
|
||||
if (el.rlPlayer) return;
|
||||
if (el.tagName.toLowerCase() != 'picture') {
|
||||
console.warn('only picture tag allowed');
|
||||
return;
|
||||
}
|
||||
options = options || {};
|
||||
var rlPlayer = el.rlPlayer = {};
|
||||
rlPlayer.thumb = el.querySelector('img');
|
||||
var tgs_sources = el.querySelectorAll('source[type="application/x-tgsticker"]');
|
||||
var multi_source = el.hasAttribute('data-multi-source');
|
||||
var urls = [], urls_map = {};
|
||||
for (var i = 0; i < tgs_sources.length; i++) {
|
||||
var tgs_source = tgs_sources[i];
|
||||
var url = tgs_source && tgs_source.getAttribute('srcset') || '';
|
||||
var frames_align = tgs_source && tgs_source.getAttribute('data-frames-align') || '';
|
||||
if (url && !urls_map[url]) {
|
||||
urls_map[url] = true;
|
||||
urls.push({
|
||||
url: url,
|
||||
framesAlign: frames_align
|
||||
});
|
||||
if (!multi_source) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!urls.length) {
|
||||
console.warn('picture source application/x-tgsticker not found');
|
||||
return;
|
||||
}
|
||||
var pic_width = el.clientWidth || el.getAttribute('width');
|
||||
var pic_height = el.clientHeight || el.getAttribute('height');
|
||||
var curDeviceRatio = options.maxDeviceRatio ? Math.min(options.maxDeviceRatio, deviceRatio) : deviceRatio;
|
||||
if (!pic_width || !pic_height) {
|
||||
pic_width = pic_height = 256;
|
||||
}
|
||||
rlPlayer.reqId = ++reqId;
|
||||
rlottie.players[reqId] = rlPlayer;
|
||||
rlPlayer.el = el;
|
||||
rlPlayer.frameNo = false;
|
||||
rlPlayer.nextFrameNo = false;
|
||||
rlPlayer.frames = {};
|
||||
rlPlayer.width = Math.trunc(pic_width * curDeviceRatio);
|
||||
rlPlayer.height = Math.trunc(pic_height * curDeviceRatio);
|
||||
rlPlayer.workerProxy = QueryableWorkerProxy.create(rlPlayer.reqId, onFrame, onLoaded);
|
||||
rlPlayer.options = options;
|
||||
rlPlayer.isVisible = true;
|
||||
rlPlayer.paused = !!options.noAutoPlay;
|
||||
rlPlayer.needPlayOnce = !!options.playOnce;
|
||||
rlPlayer.needPlayUntilEnd = !!options.playUntilEnd;
|
||||
rlPlayer.repeatCount = false;
|
||||
rlPlayer.waitForFirstFrame = false;
|
||||
rlPlayer.stopOnFirstFrame = false;
|
||||
rlPlayer.stopOnLastFrame = false;
|
||||
rlPlayer.forcePlayFrames = 0;
|
||||
rlPlayer.times = [];
|
||||
rlPlayer.imageData = new ImageData(rlPlayer.width, rlPlayer.height);
|
||||
rlPlayer.workerProxy.loadFromData(urls, rlPlayer.width, rlPlayer.height);
|
||||
triggerEvent(rlPlayer.el, 'tg:init');
|
||||
}
|
||||
|
||||
function destroyPlayer(el) {
|
||||
if (!el.rlPlayer) return;
|
||||
var rlPlayer = el.rlPlayer;
|
||||
delete rlottie.players[rlPlayer.reqId];
|
||||
delete rlPlayer;
|
||||
setupMainLoop();
|
||||
}
|
||||
|
||||
function render(rlPlayer, checkViewport) {
|
||||
if (!rlPlayer.canvas ||
|
||||
rlPlayer.canvas.width == 0 ||
|
||||
rlPlayer.canvas.height == 0) {
|
||||
return false;
|
||||
}
|
||||
if (!rlPlayer.forceRender) {
|
||||
var focused = window.isFocused ? isFocused() : document.hasFocus();
|
||||
if (!focused ||
|
||||
rlPlayer.paused ||
|
||||
!rlPlayer.isVisible ||
|
||||
!rlPlayer.frameCount) {
|
||||
return false;
|
||||
}
|
||||
var isInViewport = rlPlayer.isInViewport;
|
||||
if (isInViewport === undefined || checkViewport) {
|
||||
var rect = rlPlayer.el.getBoundingClientRect();
|
||||
if (rect.bottom < 0 ||
|
||||
rect.right < 0 ||
|
||||
rect.top > (window.innerHeight || document.documentElement.clientHeight) ||
|
||||
rect.left > (window.innerWidth || document.documentElement.clientWidth)) {
|
||||
isInViewport = false;
|
||||
} else {
|
||||
isInViewport = true;
|
||||
}
|
||||
rlPlayer.isInViewport = isInViewport;
|
||||
}
|
||||
if (!isInViewport) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var frame = rlPlayer.frameQueue.shift();
|
||||
if (frame !== null) {
|
||||
doRender(rlPlayer, frame);
|
||||
var nextFrameNo = rlPlayer.nextFrameNo;
|
||||
if (rlPlayer.stopOnLastFrame &&
|
||||
frame.no == rlPlayer.frameCount - 1) {
|
||||
rlPlayer.stopOnLastFrame = false;
|
||||
if (!rlPlayer.paused) {
|
||||
rlPlayer.paused = true;
|
||||
triggerEvent(rlPlayer.el, 'tg:pause');
|
||||
}
|
||||
}
|
||||
if (rlPlayer.stopOnFirstFrame &&
|
||||
frame.no == 0) {
|
||||
if (rlPlayer.waitForFirstFrame) {
|
||||
rlPlayer.waitForFirstFrame = false;
|
||||
} else {
|
||||
rlPlayer.stopOnFirstFrame = false;
|
||||
if (!rlPlayer.paused) {
|
||||
rlPlayer.paused = true;
|
||||
triggerEvent(rlPlayer.el, 'tg:pause');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nextFrameNo !== false) {
|
||||
rlPlayer.nextFrameNo = false;
|
||||
requestFrame(rlPlayer.reqId, nextFrameNo);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function doRender(rlPlayer, frame) {
|
||||
rlPlayer.forceRender = false;
|
||||
rlPlayer.imageData.data.set(frame.frame);
|
||||
rlPlayer.context.putImageData(rlPlayer.imageData, 0, 0);
|
||||
rlPlayer.frameNo = frame.no;
|
||||
var now = +(new Date());
|
||||
if (rlPlayer.frameThen) {
|
||||
rlPlayer.times.push(now - rlPlayer.frameThen)
|
||||
}
|
||||
rlPlayer.frameThen = now - (now % rlPlayer.frameInterval);
|
||||
if (rlPlayer.thumb) {
|
||||
rlPlayer.el.removeChild(rlPlayer.thumb);
|
||||
delete rlPlayer.thumb;
|
||||
}
|
||||
// console.log(dT(), '['+rlPlayer.reqId+']', 'render frame#'+frame.no);
|
||||
}
|
||||
|
||||
function requestFrame(reqId, frameNo) {
|
||||
var rlPlayer = rlottie.players[reqId];
|
||||
var frame = rlPlayer.frames[frameNo];
|
||||
if (frame) {
|
||||
// console.log(dT(), '['+reqId+']', 'request frame#'+frameNo+' (cache)');
|
||||
onFrame(reqId, frameNo, frame);
|
||||
} else {
|
||||
// console.log(dT(), '['+reqId+']', 'request frame#'+frameNo+' (worker)');
|
||||
rlPlayer.workerProxy.renderFrame(frameNo, !isSafari);
|
||||
}
|
||||
}
|
||||
|
||||
function onFrame(reqId, frameNo, frame) {
|
||||
var rlPlayer = rlottie.players[reqId];
|
||||
if (!rlPlayer || !rlPlayer.frames) {
|
||||
return;
|
||||
}
|
||||
if (!rlPlayer.frames[frameNo] &&
|
||||
(!frameNo || (rlPlayer.options.cachingModulo && ((reqId + frameNo) % rlPlayer.options.cachingModulo)))) {
|
||||
rlPlayer.frames[frameNo] = new Uint8ClampedArray(frame)
|
||||
}
|
||||
var prevNo = frameNo > 0 ? frameNo - 1 : rlPlayer.frameCount - 1;
|
||||
var lastQueueFrame = rlPlayer.frameQueue.last();
|
||||
if (lastQueueFrame &&
|
||||
lastQueueFrame.no != prevNo) {
|
||||
return;
|
||||
}
|
||||
rlPlayer.frameQueue.push({
|
||||
no: frameNo,
|
||||
frame: frame
|
||||
});
|
||||
var nextFrameNo = ++frameNo;
|
||||
if (nextFrameNo >= rlPlayer.frameCount) {
|
||||
nextFrameNo = 0;
|
||||
if (rlPlayer.times.length) {
|
||||
// var avg = 0;
|
||||
// for (var i = 0; i < rlPlayer.times.length; i++) {
|
||||
// avg += rlPlayer.times[i] / rlPlayer.times.length;
|
||||
// }
|
||||
// console.log('avg time: ' + avg + ', ' + rlPlayer.fps);
|
||||
rlPlayer.times = [];
|
||||
}
|
||||
}
|
||||
if (rlPlayer.frameQueue.needsMore()) {
|
||||
requestFrame(reqId, nextFrameNo)
|
||||
} else {
|
||||
rlPlayer.nextFrameNo = nextFrameNo;
|
||||
}
|
||||
}
|
||||
|
||||
function onLoaded(reqId, frameCount, fps) {
|
||||
var rlPlayer = rlottie.players[reqId];
|
||||
|
||||
rlPlayer.canvas = document.createElement('canvas');
|
||||
rlPlayer.canvas.width = rlPlayer.width;
|
||||
rlPlayer.canvas.height = rlPlayer.height;
|
||||
rlPlayer.el.appendChild(rlPlayer.canvas);
|
||||
rlPlayer.context = rlPlayer.canvas.getContext('2d');
|
||||
|
||||
rlPlayer.fps = fps;
|
||||
rlPlayer.frameInterval = 1000 / rlPlayer.fps;
|
||||
rlPlayer.frameThen = Date.now();
|
||||
rlPlayer.frameCount = frameCount;
|
||||
rlPlayer.forceRender = true;
|
||||
rlPlayer.frameQueue = new FrameQueue(fps / 4);
|
||||
setupMainLoop();
|
||||
requestFrame(reqId, 0);
|
||||
triggerEvent(rlPlayer.el, 'tg:load');
|
||||
if (frameCount > 0) {
|
||||
if (rlPlayer.needPlayOnce) {
|
||||
delete rlPlayer.needPlayOnce;
|
||||
delete rlPlayer.needPlayUntilEnd;
|
||||
rlPlayer.paused = false;
|
||||
rlPlayer.stopOnFirstFrame = true;
|
||||
rlPlayer.stopOnLastFrame = false;
|
||||
if (rlPlayer.frameNo === false ||
|
||||
rlPlayer.frameNo > 0) {
|
||||
rlPlayer.waitForFirstFrame = true;
|
||||
}
|
||||
} else if (rlPlayer.needPlayUntilEnd) {
|
||||
delete rlPlayer.needPlayOnce;
|
||||
delete rlPlayer.needPlayUntilEnd;
|
||||
rlPlayer.paused = false;
|
||||
rlPlayer.stopOnFirstFrame = false;
|
||||
rlPlayer.stopOnLastFrame = true;
|
||||
}
|
||||
}
|
||||
if (!rlPlayer.paused) {
|
||||
triggerEvent(rlPlayer.el, 'tg:play');
|
||||
}
|
||||
}
|
||||
|
||||
rlottie.init = function(el, options) {
|
||||
if (!rlottie.isSupported) {
|
||||
return false;
|
||||
}
|
||||
initApi(function() {
|
||||
el && initPlayer(el, options);
|
||||
});
|
||||
}
|
||||
|
||||
rlottie.destroy = function(el) {
|
||||
destroyPlayer(el);
|
||||
}
|
||||
|
||||
rlottie.playOnce = function(el) {
|
||||
if (el && el.rlPlayer) {
|
||||
var rlPlayer = el.rlPlayer;
|
||||
if (rlPlayer.frameCount > 0) {
|
||||
rlPlayer.stopOnFirstFrame = true;
|
||||
rlPlayer.stopOnLastFrame = false;
|
||||
if (rlPlayer.frameNo > 0) {
|
||||
rlPlayer.waitForFirstFrame = true;
|
||||
}
|
||||
if (rlPlayer.paused) {
|
||||
rlPlayer.paused = false;
|
||||
triggerEvent(el, 'tg:play');
|
||||
}
|
||||
} else {
|
||||
rlPlayer.needPlayOnce = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rlottie.playUntilEnd = function(el) {
|
||||
if (el && el.rlPlayer) {
|
||||
var rlPlayer = el.rlPlayer;
|
||||
if (rlPlayer.frameCount > 0) {
|
||||
rlPlayer.stopOnFirstFrame = false;
|
||||
rlPlayer.stopOnLastFrame = true;
|
||||
if (rlPlayer.paused) {
|
||||
rlPlayer.paused = false;
|
||||
triggerEvent(el, 'tg:play');
|
||||
}
|
||||
} else {
|
||||
rlPlayer.needPlayUntilEnd = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rlottie.play = function(el, reset) {
|
||||
if (el && el.rlPlayer) {
|
||||
if (reset) {
|
||||
rlottie.reset(el);
|
||||
}
|
||||
el.rlPlayer.paused = false;
|
||||
}
|
||||
}
|
||||
|
||||
rlottie.pause = function(el) {
|
||||
if (el && el.rlPlayer) {
|
||||
el.rlPlayer.paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
rlottie.reset = function(el) {
|
||||
if (el && el.rlPlayer) {
|
||||
var rlPlayer = el.rlPlayer;
|
||||
rlPlayer.frameQueue.clear();
|
||||
rlPlayer.forceRender = true;
|
||||
requestFrame(rlPlayer.reqId, 0);
|
||||
setupMainLoop();
|
||||
}
|
||||
}
|
||||
|
||||
rlottie.destroyWorkers = function() {
|
||||
destroyWorkers();
|
||||
}
|
||||
|
||||
return rlottie;
|
||||
}());
|
||||
|
||||
|
||||
var QueryableWorkerProxy = (function() {
|
||||
var workerproxy = {};
|
||||
var proxyId = 0;
|
||||
var wReqId = 0;
|
||||
var rObjs = {};
|
||||
var wrMap = {};
|
||||
var proxies = {};
|
||||
var rlottieWorkers = [], curWorkerNum = 0;
|
||||
|
||||
var startTime = +(new Date());
|
||||
function dT() {
|
||||
return '[' + ((+(new Date()) - startTime)/ 1000.0) + '] ';
|
||||
}
|
||||
|
||||
function Proxy(playerId, onFrame, onLoaded) {
|
||||
this.proxyId = ++proxyId;
|
||||
this.playerId = playerId;
|
||||
this.onFrame = onFrame;
|
||||
this.onLoaded = onLoaded;
|
||||
this.items = [];
|
||||
this.itemsMap = {};
|
||||
proxies[this.proxyId] = this;
|
||||
return this;
|
||||
};
|
||||
Proxy.prototype.loadFromData = function(urls, width, height) {
|
||||
if (this.items.length > 0) {
|
||||
console.warn('already loaded');
|
||||
return;
|
||||
}
|
||||
this.clampedSize = width * height * 4;
|
||||
for (var i = 0; i < urls.length; i++) {
|
||||
var url = urls[i];
|
||||
var _wReqId = ++wReqId;
|
||||
var worker = rlottieWorkers[curWorkerNum++];
|
||||
if (curWorkerNum >= rlottieWorkers.length) {
|
||||
curWorkerNum = 0;
|
||||
}
|
||||
worker.sendQuery('loadFromData', _wReqId, url.url, width, height);
|
||||
var item = {
|
||||
reqId: _wReqId,
|
||||
worker: worker,
|
||||
url: url.url,
|
||||
loaded: false,
|
||||
clamped: new Uint8ClampedArray(this.clampedSize),
|
||||
frameLoaded: {}
|
||||
};
|
||||
if (url.framesAlign) {
|
||||
item.framesAlign = url.framesAlign;
|
||||
}
|
||||
this.items.push(item);
|
||||
this.itemsMap[_wReqId] = item;
|
||||
wrMap[_wReqId] = this.proxyId;
|
||||
}
|
||||
if (this.items.length > 1) {
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.canvas.width = width;
|
||||
this.canvas.height = height;
|
||||
this.context = this.canvas.getContext('2d');
|
||||
this.imageData = new ImageData(width, height);
|
||||
}
|
||||
};
|
||||
Proxy.prototype.renderFrame = function(frameNo, need_clamped) {
|
||||
for (var i = 0; i < this.items.length; i++) {
|
||||
var item = this.items[i];
|
||||
var realFrameNo = frameNo;
|
||||
if (item.framesAlign == 'right') {
|
||||
realFrameNo = frameNo - (this.frameCount - item.frameCount);
|
||||
}
|
||||
if (need_clamped) {
|
||||
if(!item.clamped.length) { // fix detached
|
||||
item.clamped = new Uint8ClampedArray(this.clampedSize);
|
||||
}
|
||||
item.worker.sendQuery('renderFrame', item.reqId, realFrameNo, item.clamped);
|
||||
} else {
|
||||
item.worker.sendQuery('renderFrame', item.reqId, realFrameNo);
|
||||
}
|
||||
// console.log(dT(), '['+this.playerId+'.'+item.reqId+']', 'request frame#'+frameNo+' (worker)');
|
||||
}
|
||||
};
|
||||
|
||||
function onFrame(wReqId, realFrameNo, frame) {
|
||||
var proxyId = wrMap[wReqId];
|
||||
var proxy = proxies[proxyId];
|
||||
var item = proxy.itemsMap[wReqId];
|
||||
var frameNo = realFrameNo;
|
||||
if (item.framesAlign == 'right') {
|
||||
frameNo = realFrameNo + (proxy.frameCount - item.frameCount);
|
||||
}
|
||||
// console.log(dT(), '['+proxy.playerId+'.'+item.reqId+']', 'onframe#'+frameNo+' (worker)');
|
||||
item.frameLoaded[frameNo] = frame;
|
||||
var finished = true;
|
||||
for (var i = 0; i < proxy.items.length; i++) {
|
||||
var item = proxy.items[i];
|
||||
var loadedFrame = item.frameLoaded[frameNo];
|
||||
if (!loadedFrame) {
|
||||
finished = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (finished) {
|
||||
if (proxy.items.length == 1) {
|
||||
var loadedFrame = proxy.items[0].frameLoaded[frameNo];
|
||||
proxy.onFrame(proxy.playerId, frameNo, loadedFrame);
|
||||
delete proxy.items[0].frameLoaded[frameNo];
|
||||
} else {
|
||||
var promises = [];
|
||||
for (var i = 0; i < proxy.items.length; i++) {
|
||||
var item = proxy.items[i];
|
||||
var loadedFrame = item.frameLoaded[frameNo];
|
||||
proxy.imageData.data.set(loadedFrame);
|
||||
var promise = createImageBitmap(proxy.imageData);
|
||||
promises.push(promise);
|
||||
delete item.frameLoaded[frameNo];
|
||||
}
|
||||
Promise.all(promises).then(function(bitmaps) {
|
||||
proxy.context.clearRect(0, 0, proxy.canvas.width, proxy.canvas.height);
|
||||
for (var i = 0; i < bitmaps.length; i++) {
|
||||
proxy.context.drawImage(bitmaps[i], 0, 0);
|
||||
}
|
||||
var imageData = proxy.context.getImageData(0, 0, proxy.canvas.width, proxy.canvas.height);
|
||||
proxy.onFrame(proxy.playerId, frameNo, imageData.data);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
delete frameDatas;
|
||||
}
|
||||
}
|
||||
|
||||
function onLoaded(wReqId, frameCount, fps) {
|
||||
var proxyId = wrMap[wReqId];
|
||||
var proxy = proxies[proxyId];
|
||||
var item = proxy.itemsMap[wReqId];
|
||||
item.loaded = true;
|
||||
item.frameCount = frameCount;
|
||||
item.fps = fps;
|
||||
var finished = true;
|
||||
frameCount = null; fps = null;
|
||||
for (var i = 0; i < proxy.items.length; i++) {
|
||||
var item = proxy.items[i];
|
||||
if (!item.framesAlign) {
|
||||
if (frameCount === null) {
|
||||
frameCount = item.frameCount;
|
||||
} else if (frameCount !== false && frameCount !== item.frameCount) {
|
||||
frameCount = false;
|
||||
}
|
||||
}
|
||||
if (fps === null) {
|
||||
fps = item.fps;
|
||||
} else if (fps !== false && fps !== item.fps) {
|
||||
fps = false;
|
||||
}
|
||||
if (!item.loaded) {
|
||||
finished = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (finished) {
|
||||
if (frameCount === null) {
|
||||
console.warn('Frame count not defined'); return;
|
||||
}
|
||||
if (frameCount === false) {
|
||||
console.warn('Frame count is different'); return;
|
||||
}
|
||||
if (fps === null) {
|
||||
console.warn('FPS not defined'); return;
|
||||
}
|
||||
if (fps === false) {
|
||||
console.warn('FPS is different'); return;
|
||||
}
|
||||
proxy.frameCount = frameCount;
|
||||
proxy.fps = fps;
|
||||
proxy.onLoaded(proxy.playerId, frameCount, fps);
|
||||
}
|
||||
}
|
||||
|
||||
workerproxy.init = function(worker_url, workers_limit, callback) {
|
||||
var workersRemain = workers_limit;
|
||||
var firstWorker = rlottieWorkers[0] = new QueryableWorker(worker_url);
|
||||
firstWorker.addListener('ready', function () {
|
||||
console.log(dT(), 'worker #0 ready');
|
||||
firstWorker.addListener('frame', onFrame);
|
||||
firstWorker.addListener('loaded', onLoaded);
|
||||
--workersRemain;
|
||||
if (!workersRemain) {
|
||||
console.log(dT(), 'workers ready');
|
||||
callback && callback();
|
||||
} else {
|
||||
for (var workerNum = 1; workerNum < workers_limit; workerNum++) {
|
||||
(function(workerNum) {
|
||||
var rlottieWorker = rlottieWorkers[workerNum] = new QueryableWorker(worker_url);
|
||||
rlottieWorker.addListener('ready', function () {
|
||||
console.log(dT(), 'worker #' + workerNum + ' ready');
|
||||
rlottieWorker.addListener('frame', onFrame);
|
||||
rlottieWorker.addListener('loaded', onLoaded);
|
||||
--workersRemain;
|
||||
if (!workersRemain) {
|
||||
console.log(dT(), 'workers ready');
|
||||
callback && callback();
|
||||
}
|
||||
});
|
||||
})(workerNum);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
workerproxy.create = function(playerId, onFrame, onLoaded) {
|
||||
return new Proxy(playerId, onFrame, onLoaded);
|
||||
};
|
||||
workerproxy.destroy = function() {
|
||||
for (var workerNum = 0; workerNum < rlottieWorkers.length; workerNum++) {
|
||||
rlottieWorkers[workerNum].terminate();
|
||||
console.log('worker #' + workerNum + ' terminated');
|
||||
}
|
||||
console.log('workers destroyed');
|
||||
rlottieWorkers = [];
|
||||
};
|
||||
|
||||
return workerproxy;
|
||||
}());
|
||||
|
||||
function QueryableWorker(url, defaultListener, onError) {
|
||||
var instance = this;
|
||||
var worker = new Worker(url);
|
||||
var listeners = {};
|
||||
|
||||
this.defaultListener = defaultListener || function() {};
|
||||
|
||||
if (onError) {worker.onerror = onError;}
|
||||
|
||||
this.postMessage = function(message) {
|
||||
worker.postMessage(message);
|
||||
}
|
||||
|
||||
this.terminate = function() {
|
||||
worker.terminate();
|
||||
}
|
||||
|
||||
this.addListener = function(name, listener) {
|
||||
listeners[name] = listener;
|
||||
}
|
||||
|
||||
this.removeListener = function(name) {
|
||||
delete listeners[name];
|
||||
}
|
||||
|
||||
/*
|
||||
This functions takes at least one argument, the method name we want to query.
|
||||
Then we can pass in the arguments that the method needs.
|
||||
*/
|
||||
this.sendQuery = function(queryMethod) {
|
||||
if (arguments.length < 1) {
|
||||
throw new TypeError('QueryableWorker.sendQuery takes at least one argument');
|
||||
return;
|
||||
}
|
||||
var queryMethod = arguments[0];
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (RLottie.isSafari) {
|
||||
worker.postMessage({
|
||||
'queryMethod': queryMethod,
|
||||
'queryMethodArguments': args
|
||||
});
|
||||
} else {
|
||||
var transfer = [];
|
||||
for(var i = 0; i < args.length; i++) {
|
||||
if(args[i] instanceof ArrayBuffer) {
|
||||
transfer.push(args[i]);
|
||||
}
|
||||
|
||||
if(args[i].buffer && args[i].buffer instanceof ArrayBuffer) {
|
||||
transfer.push(args[i].buffer);
|
||||
}
|
||||
}
|
||||
|
||||
worker.postMessage({
|
||||
'queryMethod': queryMethod,
|
||||
'queryMethodArguments': args
|
||||
}, transfer);
|
||||
}
|
||||
}
|
||||
|
||||
worker.onmessage = function(event) {
|
||||
if (event.data instanceof Object &&
|
||||
event.data.hasOwnProperty('queryMethodListener') &&
|
||||
event.data.hasOwnProperty('queryMethodArguments')) {
|
||||
listeners[event.data.queryMethodListener].apply(instance, event.data.queryMethodArguments);
|
||||
} else {
|
||||
this.defaultListener.call(instance, event.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function FrameQueue(maxLength) {
|
||||
this.queue = [];
|
||||
this.maxLength = maxLength;
|
||||
}
|
||||
|
||||
FrameQueue.prototype.needsMore = function frameQueueNeedsMore() {
|
||||
return this.queue.length < this.maxLength;
|
||||
}
|
||||
|
||||
FrameQueue.prototype.empty = function frameQueueEmpty() {
|
||||
return !this.queue.length;
|
||||
}
|
||||
|
||||
FrameQueue.prototype.notEmpty = function frameQueueEmpty() {
|
||||
return this.queue.length > 0;
|
||||
}
|
||||
|
||||
FrameQueue.prototype.push = function frameQueuePush(element) {
|
||||
return this.queue.push(element);
|
||||
}
|
||||
|
||||
FrameQueue.prototype.shift = function frameQueueShift() {
|
||||
return this.queue.length ? this.queue.shift() : null;
|
||||
}
|
||||
|
||||
FrameQueue.prototype.last = function frameQueueLast(element) {
|
||||
return this.queue.length ? this.queue[this.queue.length - 1] : null;
|
||||
}
|
||||
|
||||
FrameQueue.prototype.clear = function frameQueueClear() {
|
||||
this.queue = [];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (!this.CustomEvent || typeof this.CustomEvent === "object") {
|
||||
(function() {
|
||||
this.CustomEvent = function CustomEvent(type, eventInitDict) {
|
||||
var event;
|
||||
eventInitDict = eventInitDict || {bubbles: false, cancelable: false, detail: undefined};
|
||||
|
||||
try {
|
||||
event = document.createEvent('CustomEvent');
|
||||
event.initCustomEvent(type, eventInitDict.bubbles, eventInitDict.cancelable, eventInitDict.detail);
|
||||
} catch (error) {
|
||||
event = document.createEvent('Event');
|
||||
event.initEvent(type, eventInitDict.bubbles, eventInitDict.cancelable);
|
||||
event.detail = eventInitDict.detail;
|
||||
}
|
||||
|
||||
return event;
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
function triggerEvent(el, event_type, init_dict) {
|
||||
var event = new CustomEvent(event_type, init_dict);
|
||||
el.dispatchEvent(event);
|
||||
}
|
2727
data/web/promote.telegram.org/js/widget-frame.js
Normal file
2727
data/web/promote.telegram.org/js/widget-frame.js
Normal file
File diff suppressed because it is too large
Load diff
264
data/web/promote.telegram.org/tos.html
Normal file
264
data/web/promote.telegram.org/tos.html
Normal file
|
@ -0,0 +1,264 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Telegram Ads</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="MobileOptimized" content="176" />
|
||||
<meta name="HandheldFriendly" content="True" /><meta name="twitter:card" content="summary"></meta>
|
||||
<meta property="og:title" content="Telegram Ad Platform Terms of Service">
|
||||
<meta property="og:description" content="1. TERMS AND DEFINITIONS
|
||||
1.1. Account – a personalized record of the Advertiser within the Telegram Ad Platform with…">
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="/img/website_icon.svg?4">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
|
||||
<link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" />
|
||||
<script>document.cookie="stel_dt="+encodeURIComponent((new Date).getTimezoneOffset())+";path=/;max-age=31536000;samesite=None;secure"</script>
|
||||
|
||||
<link href="//telegram.org/css/font-roboto.css?1" rel="stylesheet" type="text/css">
|
||||
<link href="//telegram.org/css/bootstrap.min.css?3" rel="stylesheet">
|
||||
<link href="//telegram.org/css/bootstrap-extra.css?2" rel="stylesheet">
|
||||
<link href="/css/telegram.css?236" rel="stylesheet">
|
||||
<link href="/css/widget-frame.css?67" rel="stylesheet">
|
||||
<link href="/css/promote.css?84" rel="stylesheet">
|
||||
<link href="/css/jquery-ui.min.css?1" rel="stylesheet">
|
||||
<link href="/css/tchart.min.css?10" rel="stylesheet">
|
||||
|
||||
</head>
|
||||
<body class="emoji_image no-transition">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
|
||||
<defs>
|
||||
<path id="icon-currency-ton" d="m2.68 4h10.63c.22 0 .4.18.4.41 0 .07-.01.14-.05.2l-5.04 9.08c-.22.4-.72.54-1.11.32-.14-.08-.25-.19-.32-.33l-4.87-9.08c-.1-.2-.03-.45.17-.55.06-.03.12-.05.19-.05zm5.32 9.78v-9.78z" fill="none" stroke="currentColor" stroke-width="1.3"/>
|
||||
</defs>
|
||||
</svg>
|
||||
<div id="aj_progress" class="progress-bar"></div>
|
||||
|
||||
<div id="aj_content"><div class="pr-container pr-docs-container">
|
||||
<div class="pr-header">
|
||||
<div class="pr-header-auth">
|
||||
<div class="pr-header-auth-item"><a class="header-auth-link login-link" href="/auth">Log In</a></div>
|
||||
</div>
|
||||
<ol class="pr-breadcrumb"><li class="pr-logo compact"><a href="/"><i class="pr-icon"></i><span class="pr-logo-title">Telegram Ads</span></a></li><li class="pr-breadcrumb-item">Telegram Ad Platform Terms of Service</li></ol>
|
||||
</div>
|
||||
<section class="pr-content"><div id="dev_page_content_wrap" class=" ">
|
||||
<div class="dev_page_bread_crumbs"></div>
|
||||
<h1 id="dev_page_title">Telegram Ad Platform Terms of Service</h1>
|
||||
|
||||
<div id="dev_page_content"><h3><a class="anchor" name="1-terms-and-definitions" href="#1-terms-and-definitions"><i class="anchor-icon"></i></a>1. TERMS AND DEFINITIONS</h3>
|
||||
<p>1.1. <strong>Account</strong> – a personalized record of the Advertiser within the Telegram Ad Platform with unique access details, containing the information on the Services, Statistics, Advertiser’s information, Ads and their status, Balance, operating tools and features.</p>
|
||||
<p>1.2. <strong>Ad</strong> – an advertisement created using the Telegram Ad Platform that specifies where, how, when and which Advertising Materials are to be displayed, including the type and format of the Advertising Materials, their placement (particular channels, groups, games), CPM, Maximum Budget.</p>
|
||||
<p>1.3. <strong>Advertiser</strong> – the person or entity who has entered into the Agreement with the Company.</p>
|
||||
<p>1.4. <strong>Advertising Materials</strong> – any graphic/media file and/or any and all accompanying information supplied by the Advertiser to the Company to be displayed for advertising purposes in Publication Spaces. The Advertiser retains all rights, whether owned by the Advertiser or by a third party, and/or licensed or otherwise used by the Advertiser, in relation to any Advertising Materials and grants to the Company a worldwide, non-sublicensable, non-exclusive, royalty-free license to use, serve, copy, reproduce, distribute and display the Advertising Materials, in any known, agreed or hereafter developed manner.</p>
|
||||
<p>1.5. <strong>Agreement</strong> – the present Terms of Service along with the Advertising Agreement reached between the Company and the Advertiser.</p>
|
||||
<p>1.6. <strong>Auction</strong> – the automated system that uses certain algorithms to determine the best offered CPM in relation to an Ad for the provision of the Services. </p>
|
||||
<p>1.7. <strong>Balance</strong> – the amount of money which is available on the Account and can be spent on the Services.</p>
|
||||
<p>1.8. <strong>Confidential Information</strong> – all information of a Party including, without limitation, information and/or personal data provided by a Party, its related corporations, affiliates, employees, agents, representatives, advisors, or consultants, whether disclosed or communicated verbally, in writing or in any other tangible form, and whether relating to a Party’s business, operations, processes, plans, requirements, inventions, product or service information, pricing, know-how, design rights, trade secrets, software, systems, market opportunities, customers and business affairs.</p>
|
||||
<p>1.9. <strong>CPM</strong> – Cost-Per-Mille, the price for one thousand Impressions of an Ad.</p>
|
||||
<p>1.10. <strong>Company</strong> – the legal entity which belongs to Telegram group of companies and has a right to enter the Agreement with the Advertiser for the Services.</p>
|
||||
<p>1.11. <strong>Data Protection Laws</strong> – the following legislations to the extent applicable from time to time: (a) national laws implementing the Directive on Privacy and Electronic Communications (2002/58/EC) (as amended by Directive 2009/136); (b) the General Data Protection Regulation (2016/679) (the <strong>GDPR</strong>) and the UK GDPR and any national law supplementing the GDPR or UK GDPR (such as, in the UK, the Data Protection Act 2018), and (c) any other data protection or privacy laws, regulations, or regulatory requirements, guidance and codes of practice applicable to the processing of personal data (as amended and/or replaced from time to time).</p>
|
||||
<p>1.12. <strong>Impression</strong> – each occurrence of a display of an Ad to a user in a Publication Space, as evidenced by Statistics.</p>
|
||||
<p>1.13. <strong>Improper Advertising</strong> – any act or omission which violates the Consumer Protection from Unfair Trading Regulations 2008 or any other applicable laws or regulations relating to advertising or marketing standards.</p>
|
||||
<p>1.14. <strong>Intellectual Property Rights</strong> – trademarks, service marks, rights in trade names, business names, logos or get-up, goodwill and the right to sue for passing off, patents, supplementary protection certificates, rights in inventions, registered and unregistered design rights, copyrights (including rights in software), database rights, image rights and rights to personality, rights in domain names and URLs and social media presence accounts, and all other similar rights in any part of the world (including in confidential information, trade secrets and know-how) and whether registered or not, including, where such rights are obtained or enhanced by registration, any registration of such rights and applications and rights to apply for such registrations.</p>
|
||||
<p>1.15. <strong>Maximum Budget</strong> – the maximum amount of funds, confirmed by the Advertiser, that can be deducted from the Balance for displaying a particular Ad in a Publication Space. Reaching the Maximum Budget shall result in the Ad being put on hold.</p>
|
||||
<p>1.16. <strong>Publication Space</strong> – a digital space for Advertising Materials made available by the Company including, without limitation, in Telegram channels, Telegram groups and Telegram games.</p>
|
||||
<p>1.17. <strong>Reporting Period</strong> – calendar month. The first Reporting Period commences on the date of signing of the Agreement and lasts up to the last day of the relevant calendar month (as an example, June 10 – June 30), the last Reporting Period commences on the first day of the relevant calendar month and lasts up to the date of the Agreement’s termination (as an example, June 01 – June 15).</p>
|
||||
<p>1.18. <strong>Services</strong> – the display of the Advertising Materials in the context of a particular Ad, in the relevant Publication Space. </p>
|
||||
<p>1.19. <strong>Statistics</strong> – a detailed report on the Advertiser’s Ads, which specifies the scope of the Services provided. It includes the Advertising Materials data, the cost of the Services in the Reporting Period and other data generated by the Company upon the results of automated checks.</p>
|
||||
<p>1.20. <strong>Telegram App</strong> – a cloud-based mobile and desktop messaging app with a focus on security and speed, including but not limited to mobile apps for iPhone/iPad/Android/Windows phone, desktop apps for PC/Mac/Linux/macOS/Web-browser, Telegram web and all other interfaces and/or versions which exist or will be created in future.</p>
|
||||
<p>1.21. <strong>Telegram Ad Platform</strong> – the software solution which provides the Advertiser with the opportunity to create Ads that participate in Auctions for Publication Spaces, control and terminate their Ads, and access the relevant Statistics within the Account.</p>
|
||||
<p>1.22. <strong>Telegram Ad Policies and Guidelines</strong> – Telegram Ad Policies and Guidelines as available at: <a href="https://promote.telegram.org/guidelines"><a href="https://promote.telegram.org/guidelines">https://promote.telegram.org/guidelines</a></a>.</p>
|
||||
<p>1.23. <strong>Telegram Privacy Policy</strong> – Telegram Privacy Policy as available at: <a href="https://telegram.org/privacy"><a href="https://telegram.org/privacy">https://telegram.org/privacy</a></a>.</p>
|
||||
<p>1.24. <strong>Telegram Terms of Service</strong> – Telegram Terms of Service as available at: <a href="https://telegram.org/tos"><a href="https://telegram.org/tos">https://telegram.org/tos</a></a>.</p>
|
||||
<p>1.25. <strong>Terms of Service</strong> – Telegram Ad Platform Terms of Service as available at: <a href="https://promote.telegram.org/tos"><a href="https://promote.telegram.org/tos">https://promote.telegram.org/tos</a></a>.</p>
|
||||
<h3><a class="anchor" name="2-requirements-for-advertising-materials" href="#2-requirements-for-advertising-materials"><i class="anchor-icon"></i></a>2. REQUIREMENTS FOR ADVERTISING MATERIALS</h3>
|
||||
<p><strong>2.1.</strong> Advertising Materials shall be in compliance with all applicable laws, rules and regulations, present Terms of Service, Telegram Terms of Service, Telegram Privacy Policy, Apple App Store terms and rules as may be applicable, and Google Play terms and rules as may be applicable.</p>
|
||||
<p><strong>2.2.</strong> Advertising Materials shall be in compliance with Telegram Ad Policies and Guidelines. Advertising Materials must not relate to the topics as indicated at <a href="https://promote.telegram.org/guidelines#5-prohibited-content">Ad Policies and Guidelines/Prohibited Content</a>.</p>
|
||||
<p><strong>2.3.</strong> The Company reserves the right to update <a href="https://promote.telegram.org/guidelines">Telegram Ad Policies and Guidelines</a> and the list of topics at clause 2.2 from time to time. </p>
|
||||
<h3><a class="anchor" name="3-rights-and-obligations" href="#3-rights-and-obligations"><i class="anchor-icon"></i></a>3. RIGHTS AND OBLIGATIONS</h3>
|
||||
<h4><a class="anchor" name="3-1-the-company-shall" href="#3-1-the-company-shall"><i class="anchor-icon"></i></a>3.1. The Company shall:</h4>
|
||||
<p><strong>(a)</strong> pursuant to and in accordance with the Advertiser’s instructions submitted via the Telegram Ad Platform in relation to a particular Ad, provide the Services whenever the Advertiser’s CPM bid wins the Auction for a particular Publication Space, for as long as the Ad’s Maximum Budget and the Advertiser’s Balance allow.</p>
|
||||
<h4><a class="anchor" name="3-2-the-company-may-at-its-sole-discretion" href="#3-2-the-company-may-at-its-sole-discretion"><i class="anchor-icon"></i></a>3.2. The Company may, at its sole discretion:</h4>
|
||||
<p><strong>(a)</strong> conduct an audit of the Advertising Materials to verify their compliance with all applicable laws, rules and regulations, present Terms of Service, Telegram Ad Policies and Guidelines, Telegram Terms of Service, Telegram Privacy Policy, Apple App Store terms and rules as may be applicable, and Google Play terms and rules as may be applicable. The Company shall not be bound by any time frames in conducting an audit under this clause 3.2(a);</p>
|
||||
<p><strong>(b)</strong> terminate or suspend the Services without any liability in the event that the Advertising Materials, as may be evidenced by the results of any audit undertaken by the Company under clause 3.2(a) above, are in conflict with any applicable laws, rules and regulations, present Terms of Services, Telegram Ad Policies and Guidelines, Telegram Terms of Service, Telegram Privacy Policy, Apple App Store terms and rules as may be applicable, and Google Play terms and rules as may be applicable, and inter alia, contain any elements of Improper Advertising, and/or explicitly violate the generally accepted moral and ethical standards, and/or are inconsistent with the Company’s values and principles, including the Company’s stance on fundamental human rights, freedom of speech and data privacy;</p>
|
||||
<p><strong>(c)</strong> request any supporting documentation regarding Advertising Materials, including, without limitation, the relevant licenses/permits/certificates for licensed goods/services, agreements with Advertiser’s customers for distribution of goods/services which contain Intellectual Property Rights, and suspend provision of Services until and unless such information is provided to the satisfaction of the Company;</p>
|
||||
<p><strong>(d)</strong> request any supporting documentation on Advertiser’s legal status, including, but not limited to, its constitutional documents, tax numbers, residency and related details, powers and rights of representatives, and suspend provision of Services until and unless such information is provided to satisfaction of the Company;</p>
|
||||
<p><strong>(e)</strong> transfer any information concerning Advertiser and the Advertising Materials which is required to be disclosed by any regulatory authority, any auditor of the Parties, by judicial or administrative process or otherwise by applicable law or regulation; </p>
|
||||
<p><strong>(f)</strong> change the parameters of the Services in the Telegram Ad Platform and, in particular, change the list of available Publication Spaces and minimum CPM; and</p>
|
||||
<p><strong>(g)</strong> make changes to these Terms of Service at any time by uploading an updated version of the Terms of Service to its website, which can be accessed here: <a href="https://promote.telegram.org/tos"><a href="https://promote.telegram.org/tos">https://promote.telegram.org/tos</a></a>.</p>
|
||||
<h4><a class="anchor" name="3-3-the-advertiser-shall" href="#3-3-the-advertiser-shall"><i class="anchor-icon"></i></a>3.3. The Advertiser shall:</h4>
|
||||
<p><strong>(a)</strong> be fully responsible for the compliance of the placed Advertising Materials and the methods of their placement, including the use of any settings and placement parameters of the Telegram Ad Platform, with all applicable laws, rules and regulations, these Terms of Services, Telegram Ad Policies and Guidelines, Telegram Terms of Service, Telegram Privacy Policy, Apple App Store terms and rules as may be applicable, and Google Play terms and rules as may be applicable;</p>
|
||||
<p><strong>(b)</strong> promptly provide the Company with any information, documents and other materials that the Company may request from time to time in accordance with clauses 3.2(c) to 3.2(e) above;</p>
|
||||
<p><strong>(c)</strong> promptly inform the Company of all changes impacting the Company under this Agreement, including but not limited to the Advertiser’s business, contact details, bank details and authorized persons; </p>
|
||||
<p><strong>(d)</strong> mark the Advertising Materials, if so required by applicable law, with an indication of the age category of persons for whom it is addressed and any other indications. The Advertiser is solely responsible for correct labelling of the Advertising Materials;</p>
|
||||
<p><strong>(e)</strong> not permit any third party to put forward a bid at an Auction using its Account; and</p>
|
||||
<p><strong>(f)</strong> obtain any requisite consents, licences and approvals required in connection with the performance of the Agreement (including the use of any settings and placement parameters of the Telegram Ad Platform), and fully comply with its obligations under the same.</p>
|
||||
<h4><a class="anchor" name="3-4-the-advertiser-may" href="#3-4-the-advertiser-may"><i class="anchor-icon"></i></a>3.4. The Advertiser may:</h4>
|
||||
<p><strong>(a)</strong> place requests for the Services by creating Ads on the Telegram Ad Platform;</p>
|
||||
<p><strong>(b)</strong> use the Telegram Ad Platform interfaces to interact with their Ads, e.g. launch Ads and put them on hold, submit changes to the CPM and Maximum Budget of Ads, etc. Without prejudice to clause 3.2(a), changes will be usually applied after fifteen (15) minutes, but no later than in sixty (60) minutes after the request is registered by the Telegram Ad Platform; and</p>
|
||||
<p><strong>(c)</strong> be informed of the Statistics.</p>
|
||||
<h3><a class="anchor" name="4-liability" href="#4-liability"><i class="anchor-icon"></i></a>4. LIABILITY</h3>
|
||||
<p><strong>4.1.</strong> In case of non-compliance or inadequate performance by the Parties of their respective obligations under this Agreement, the Parties will incur liability as provided for under applicable law; except that the Company shall not be liable for failure to fulfill or the improper fulfillment of the Agreement caused by breakdown of telecommunication and energy networks, effects of malicious software or fraudulent acts by the third parties.</p>
|
||||
<p><strong>4.2.</strong> The Company undertakes all possible effort to provide the best Services it can. Notwithstanding clause 4.1 above, however, these Services are provided "as is” and “as available” and the Company makes no guarantees that the Services always will be error-free, or that they will function without delays and disruptions. The Company disclaims all warranties, whether express or implied, including the implied warranties of merchantability, fitness for a particular purpose, title, and non-infringement.</p>
|
||||
<p><strong>4.3.</strong> Without prejudice to the generality of clause 4.1 above, the Advertiser shall be liable for security of the access details to the Account and shall compensate the Company for any losses related to such use by the persons not authorized to act on behalf of the Advertiser. For the avoidance of doubt, where the Advertiser is in violation of its obligations under this Agreement, the Advertiser shall reimburse the Company for any and all losses incurred as a result of such violation.</p>
|
||||
<p><strong>4.4.</strong> The Company's total aggregate liability under this Agreement whether in contract, tort (including negligence), under a warranty, undertaking or representation under statute or otherwise, for any losses or damages suffered or incurred by the Advertiser shall not exceed the total amount of the Advertiser's Balance spent in the previous calendar year.</p>
|
||||
<p><strong>4.5.</strong> The Company shall not be liable under or in connection with this Agreement whether in contract, tort (including negligence), under a warranty, undertaking or representation under statute or otherwise, for any indirect or consequential losses, any loss of business, business opportunities or goodwill, or any loss of revenue, savings or profits, whether actual or prospective or for any punitive damages, howsoever arising, whether such losses or damage were foreseeable or in the contemplation of the Advertiser or the Company.</p>
|
||||
<p><strong>4.6.</strong> Nothing in this Agreement shall limit or exclude any liability for (i) death or personal injury resulting from negligence, (ii) fraud, fraudulent misrepresentation or willful default, or (iii) for any other liability to the extent it cannot be lawfully excluded or limited.</p>
|
||||
<h3><a class="anchor" name="5-warranties-and-indemnification" href="#5-warranties-and-indemnification"><i class="anchor-icon"></i></a>5. WARRANTIES AND INDEMNIFICATION</h3>
|
||||
<p><strong>5.1.</strong> <strong>Warranties</strong> – Each Party warrants to the other that:</p>
|
||||
<p><strong>(a)</strong> to the best of its knowledge, nothing in this Agreement violates any applicable law, including Data Protection Laws; </p>
|
||||
<p><strong>(b)</strong> it has the necessary financial resources to perform its obligations under this Agreement;</p>
|
||||
<p><strong>(c)</strong> it has the requisite legal right, power and authority to execute, deliver, and to perform its obligations under this Agreement;</p>
|
||||
<p><strong>(d)</strong> this Agreement constitutes its binding obligations in accordance with its terms; and</p>
|
||||
<p><strong>(e)</strong> nothing contained in this Agreement will result in a breach of any provision of its constitutional documents or result in a breach of any agreement, license or other instrument, order, judgment or decree of any court or governmental body to which it is bound.</p>
|
||||
<p><strong>5.2.</strong> <strong>Indemnity</strong> – The Advertiser hereby indemnifies, defends and holds harmless on an after tax basis the Company and each of the companies in the Company’s group and its and their directors, employees, officers, contractors, agents and any other related parties (each an <strong>Indemnified Person</strong>) from and against:</p>
|
||||
<p><strong>(a)</strong> all or any claims, actions, proceedings, liabilities, investigations, demands, judgements and/or awards (in each case whether or not successful, compromised or settled and whether joint or several) (together <strong>Claims</strong> and each a <strong>Claim</strong>) which may be asserted, established, instituted, made, pending, threatened or alleged against or otherwise involve an Indemnified Person in any jurisdiction by any person whatsoever, including without limitation by a third party or by any supervisory or regulatory agency or body; and/or</p>
|
||||
<p><strong>(b)</strong> all or any loss, damage, cost, liability, demand, charge, expense or tax (including, without limitation, (i) any direct, indirect or consequential losses, loss of profit, loss of business, business opportunities or goodwill, loss of reputation, (ii) all interest, penalties, legal costs and all other professional costs and expenses, (iii) all losses suffered or incurred in investigating, preparing for or disputing or defending or providing evidence in connection with or settling any Claim and/or in establishing its right to be indemnified pursuant to this clause 5.2 and/or in seeking advice regarding any Claim and/or in any way related to or in connection with the indemnity contained in this clause 5.2) (together <strong>Losses</strong> and each a <strong>Loss</strong>) which may be suffered or incurred by an Indemnified Person,</p>
|
||||
<p>which, directly or indirectly, arise out of, or are attributable to, or are connected with the performance of the Agreement, the Ads, the Advertising Materials, the advertised goods or services or consumption thereof, or non-compliance by the Advertiser with any terms of this Agreement. </p>
|
||||
<h4><a class="anchor" name="5-3-conduct-of-claims" href="#5-3-conduct-of-claims"><i class="anchor-icon"></i></a>5.3. Conduct of claims</h4>
|
||||
<p><strong>(a)</strong> Each Indemnified Person shall give notice as soon as reasonably practicable to the Advertiser of any action commenced against it after receipt of a written notice of any Claim or the commencement of any action or proceeding in respect of which a Claim for indemnification may be sought hereunder, insofar as may be consistent with any obligation of confidentiality or other legal or regulatory obligation which that Indemnified Person owes to any third party or to any regulatory request that has been made of it, but failure to so notify the Advertiser shall not relieve the Advertiser from any liability or any obligation to indemnify the Advertiser and in any event shall not relieve the Advertiser from any liability which the Advertiser may have. Legal advisers to any Indemnified Person shall be selected by such Indemnified Person in its absolute discretion.</p>
|
||||
<p><strong>(b)</strong> The Advertiser shall, at the request of any Indemnified Person, conduct the defense of any such action and shall do so at its own expense; provided, however, that legal advisers to the Advertiser shall be reasonably satisfactory to the Indemnified Persons and shall not (except with the consent of the Indemnified Person) also be legal advisers to the Indemnified Person. If the Advertiser conducts the defense of an action, it shall provide each relevant Indemnified Person with all relevant information in respect of any such action on a timely basis (including, without limitation, on request) and the Advertiser will take such action, in each case, as each relevant Indemnified Person may reasonably request.</p>
|
||||
<p><strong>(c)</strong> The Advertiser shall not, without the prior written consent of the Indemnified Persons, settle or compromise or consent to the entry of any judgment with respect to any litigation, or any investigation or proceeding by any supervisory or regulatory agency or body, commenced or threatened, or any claim whatsoever in respect of which indemnification could be sought under clause 5.2 (whether or not the Indemnified Persons are actual or potential parties thereto), unless such settlement, compromise or consent: (i) includes an unconditional release of each Indemnified Person from all liability arising out of such Claim; and (ii) does not include a statement as to or an admission of fault, culpability or a failure to act by or on behalf of any Indemnified Person.</p>
|
||||
<p><strong>(d)</strong> The provisions of this clause 5 shall not affect or be affected by any other agreement to which any Indemnified Person is a party with respect to indemnification.</p>
|
||||
<p><strong>5.4. Contracts (Rights of Third Parties) Act 1999</strong> – Each Indemnified Person will have the right under the Contracts (Rights of Third Parties) Act 1999 to enforce its rights against the Advertiser under this clause 5; provided that only the consent of the specified parties to the Agreement shall be required to make any amendment of the Agreement or give any waiver under the Agreement.</p>
|
||||
</div>
|
||||
|
||||
</div></section>
|
||||
</div><div class="popup-container login-popup-container hide" id="login-popup-container">
|
||||
<div class="popup">
|
||||
<div class="popup-body">
|
||||
<section>
|
||||
<h2>Log In</h2>
|
||||
<p>Log in here to manage your ads. Please enter your <b>phone number</b> in the <a target="_blank" rel="noopener" href="https://telegram.org/faq#login-and-sms">international format</a> and we will send a confirmation message to your account via Telegram.</p>
|
||||
|
||||
<form id="send-form" class="login-form">
|
||||
<div class="form-group">
|
||||
<input type="tel" class="form-control pr-form-control input-lg" id="phone-number" placeholder="+12223334455" autocomplete="off"/>
|
||||
</div>
|
||||
<div class="popup-buttons">
|
||||
<a class="btn btn-link btn-lg login-cancel-btn">Cancel</a><button type="submit" class="btn btn-link btn-lg">Next</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="login-form" class="hide">
|
||||
<div class="form-group">
|
||||
<span class="form-control pr-form-control input input-lg input-disabled"><strong id="phone-number-field"></strong> (<a class="login-back" href="/auth">Incorrect?</a>)</span>
|
||||
<p class="help-block dots-animated">We've just sent you a message.<br/>Please confirm access via Telegram</p>
|
||||
</div>
|
||||
<div class="popup-buttons">
|
||||
<a class="btn btn-link btn-lg login-cancel-btn">Cancel</a><a class="btn btn-link btn-lg login-back">Back</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
<script src="//telegram.org/js/jquery.min.js?1"></script>
|
||||
<script src="//telegram.org/js/bootstrap.min.js"></script>
|
||||
<script src="//telegram.org/js/main-aj.js?68"></script>
|
||||
<script src="/js/main.js?47"></script>
|
||||
<script src="/js/widget-frame.js?62"></script>
|
||||
<script src="/js/promote.js?81"></script>
|
||||
<script src="/js/jquery-ui.min.js?1"></script>
|
||||
<script src="/js/jquery-ex.js?18"></script>
|
||||
<script src="/js/tchart.min.js?18"></script>
|
||||
<script src="/js/health.js?19"></script>
|
||||
<script src="/js/tgsticker.js?31"></script>
|
||||
|
||||
<script>ajInit({"version":985,"apiUrl":"\/api?hash=telegram-crawler","unauth":true});</script>
|
||||
<script id="aj_script">l.add({"WEB_AB_WARNING_HEADER":"Turn off ad blocker","WEB_POPUP_CLOSE_BTN":"Close","WEB_AB_WARNING_TEXT":"You appear to be using an ad blocker that may prevent pages on the Telegram Ad Platform from working as expected.<br\/><br\/>Please turn off your ad blocker or add <a href=\"http:\/\/promote.telegram.org\/\">promote.telegram.org<\/a> as an exception to manage your promoted messages."});
|
||||
window.enableInlineVideo&&$('video').each(function(){enableInlineVideo(this)});
|
||||
Ads.init();
|
||||
Aj.onLoad(function(state) {
|
||||
function requestConfirmation(event) {
|
||||
event && event.preventDefault();
|
||||
var phone = $('#phone-number').val();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/auth/request',
|
||||
data: {
|
||||
phone: phone
|
||||
},
|
||||
success: function(result) {
|
||||
$('#phone-number-field').text(phone);
|
||||
$('#send-form').addClass('hide');
|
||||
$('#login-form').removeClass('hide');
|
||||
checkAuth(result.temp_session);
|
||||
},
|
||||
error: function(xhr) {
|
||||
showAlert(xhr.responseText || 'Server error');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
function cancelConfirmation(event) {
|
||||
event && event.preventDefault();
|
||||
$('#phone-number-field').text('');
|
||||
$('#send-form').removeClass('hide');
|
||||
$('#login-form').addClass('hide');
|
||||
$('#phone-number').focus();
|
||||
clearTimeout(window.authTimeout);
|
||||
return false;
|
||||
}
|
||||
function checkAuth(temp_session) {
|
||||
clearTimeout(window.authTimeout);
|
||||
window.authTimeout = setTimeout(function doCheckAuth() {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/auth/login',
|
||||
data: {
|
||||
temp_session: temp_session
|
||||
},
|
||||
success: function(result) {
|
||||
if (result) {
|
||||
location.reload();
|
||||
} else {
|
||||
checkAuth(temp_session);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
showAlert(xhr.responseText || 'Server error');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
}, 700);
|
||||
}
|
||||
$('#login-popup-container').on('popup:open', function() {
|
||||
$('#phone-number').focus();
|
||||
});
|
||||
$('#login-popup-container').on('popup:close', function() {
|
||||
cancelConfirmation();
|
||||
if (location.pathname == '/auth') {
|
||||
window.history && history.replaceState(null, null, '/');
|
||||
}
|
||||
});
|
||||
$('#login-popup-container #send-form').on('submit', requestConfirmation);
|
||||
$('#login-popup-container .login-cancel-btn').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
closePopup('#login-popup-container');
|
||||
});
|
||||
$('#login-popup-container .login-back').on('click', cancelConfirmation);
|
||||
$('.login-link').on('click', function(e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
openPopup('#login-popup-container');
|
||||
});
|
||||
});
|
||||
Aj.onUnload(function(state) {
|
||||
$('#login-popup-container').off('popup:open');
|
||||
$('#login-popup-container').off('popup:close');
|
||||
$('#login-popup-container #send-form').off('submit');
|
||||
$('#login-popup-container .login-cancel-btn').off('click');
|
||||
$('#login-popup-container .login-back').off('click');
|
||||
$('.login-link').off('click');
|
||||
});
|
||||
</script>
|
||||
<script>Aj.pageLoaded();</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Add table
Reference in a new issue