Bugfixes
This commit is contained in:
parent
ec5e23131e
commit
3154b97763
173
bots/MadelineProto_bot.php
Executable file
173
bots/MadelineProto_bot.php
Executable file
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/*
|
||||
Copyright 2016-2017 Daniil Gentili
|
||||
(https://daniil.it)
|
||||
This file is part of MadelineProto.
|
||||
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||
If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
$settings = [];
|
||||
$MadelineProto = false;
|
||||
try {
|
||||
$MadelineProto = \danog\MadelineProto\Serialization::deserialize('MadelineProto_bot.madeline');
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
}
|
||||
|
||||
if (file_exists('token.php') && $MadelineProto === false) {
|
||||
include_once 'token.php';
|
||||
$MadelineProto = new \danog\MadelineProto\API($settings);
|
||||
$authorization = $MadelineProto->bot_login($MadelineProto_token);
|
||||
\danog\MadelineProto\Logger::log([$authorization], \danog\MadelineProto\Logger::NOTICE);
|
||||
}
|
||||
$reply_markup = ['inline_keyboard' =>
|
||||
[
|
||||
[ // Row 1
|
||||
['text' => 'Row 1 b1'],
|
||||
['text' => 'Row 1 b2'],
|
||||
['text' => 'Row 1 b3'],
|
||||
],
|
||||
[ // Row 2
|
||||
['text' => 'Row 2 b1'],
|
||||
['text' => 'Row 2 b2'],
|
||||
['text' => 'Row 2 b3'],
|
||||
],
|
||||
[ // Row 3
|
||||
['text' => 'Row 3 b1'],
|
||||
['text' => 'Row 3 b2'],
|
||||
['text' => 'Row 3 b3'],
|
||||
],
|
||||
]
|
||||
|
||||
];
|
||||
$start = "This bot can create inline text buttons.
|
||||
To use it, simply type an inline query with the following syntax:
|
||||
|
||||
Row 1 b1 | Row 1 b2 | Row 1 b3
|
||||
Row 2 b1 | Row 2 b2 | Row 2 b3
|
||||
Row 3 b1 | Row 3 b2 | Row 3 b3
|
||||
|
||||
This will create a keyboard exactly like the one used in this message (click the buttons ;D)
|
||||
|
||||
Created by [Daniil Gentili](mention:@danogentili) (@daniilgentili) using the [MadelineProto PHP MTProto client](daniil.it/MadelineProto).";
|
||||
while (true) {
|
||||
$updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
|
||||
foreach ($updates as $update) {
|
||||
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
|
||||
switch ($update['update']['_']) {
|
||||
case 'updateNewMessage':
|
||||
if (isset($update['update']['message']['out']) && $update['update']['message']['out']) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (preg_match('|/start|', $update['update']['message']['message'])) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['from_id'], 'message' => $start, 'reply_to_msg_id' => $update['update']['message']['id'], 'parse_mode' => 'markdown', 'reply_markup' => $reply_markup]);
|
||||
}
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
}
|
||||
break;
|
||||
case 'updateNewChannelMessage':
|
||||
if (isset($update['update']['message']['out']) && $update['update']['message']['out']) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (preg_match('|/start|', $update['update']['message']['message'])) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['to_id'], 'message' => $start, 'reply_to_msg_id' => $update['update']['message']['id'], 'parse_mode' => 'markdown', 'reply_markup' => $reply_markup]);
|
||||
}
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
}
|
||||
break;
|
||||
case 'updateBotInlineQuery':
|
||||
try {
|
||||
$sswitch = ['_' => 'inlineBotSwitchPM', 'text' => 'FAQ', 'start_param' => 'lel'];
|
||||
if ($update['update']['query'] === '') {
|
||||
$MadelineProto->messages->setInlineBotResults(['query_id' => $update['update']['query_id'], 'results' => [], 'cache_time' => 0, 'switch_pm' => $sswitch]);
|
||||
} else {
|
||||
$toset = ['query_id' => $update['update']['query_id'], 'results' => [], 'cache_time' => 0, 'private' => true];
|
||||
if (preg_match('|\$\s*$|', $update['update']['query'])) {
|
||||
$exploded = explode('|', preg_replace('/\$\s*$/', '', $update['update']['query']));
|
||||
array_walk($exploded, function (&$value, $key) {
|
||||
$value = preg_replace(['/^\s+/', '/\s+$/'], '', $value);
|
||||
});
|
||||
$query = array_shift($exploded);
|
||||
foreach ($exploded as $current => $botq) {
|
||||
$bot = preg_replace('|:.*|', '', $botq);
|
||||
if ($bot === '' || $uMadelineProto->get_info($bot)['bot_api_id'] === $MadelineProto->API->datacenter->authorization['user']['id']) {
|
||||
$toset['switch_pm'] = $sswitch;
|
||||
break;
|
||||
}
|
||||
$select = preg_replace('|'.$bot.':|', '', $botq);
|
||||
$results = $uMadelineProto->messages->getInlineBotResults(['bot' => $bot, 'peer' => $update['update']['user_id'], 'query' => $query, 'offset' => $offset]);
|
||||
if (isset($results['switch_pm'])) {
|
||||
$toset['switch_pm'] = $results['switch_pm'];
|
||||
break;
|
||||
}
|
||||
$toset['gallery'] = $results['gallery'];
|
||||
$toset['results'] = [];
|
||||
if (is_numeric($select)) {
|
||||
$toset['results'][0] = $results['results'][$select - 1];
|
||||
} elseif ($select === '') {
|
||||
$toset['results'] = $results['results'];
|
||||
} else {
|
||||
foreach ($results['results'] as $result) {
|
||||
if (isset($result['send_message']['message']) && preg_match('|'.$select.'|', $result['send_message']['message'])) {
|
||||
$toset['results'][0] = $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isset($toset['results'][0])) {
|
||||
$toset['results'] = $results['results'];
|
||||
}
|
||||
if (count($exploded) - 1 === $current || !isset($toset['results'][0]['send_message']['message'])) {
|
||||
break;
|
||||
}
|
||||
$query = $toset['results'][0]['send_message']['message'];
|
||||
}
|
||||
}
|
||||
if (empty($toset['results'])) {
|
||||
$toset['switch_pm'] = $sswitch;
|
||||
} else {
|
||||
array_walk($toset['results'], 'translate');
|
||||
}
|
||||
$MadelineProto->messages->setInlineBotResults($toset);
|
||||
}
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
try {
|
||||
$MadelineProto->messages->sendMessage(['peer' => $update['update']['user_id'], 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
}
|
||||
try {
|
||||
$toset['switch_pm'] = $sswitch;
|
||||
$MadelineProto->messages->setInlineBotResults($toset);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
}
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
try {
|
||||
$MadelineProto->messages->sendMessage(['peer' => $update['update']['user_id'], 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
}
|
||||
try {
|
||||
$toset['switch_pm'] = $sswitch;
|
||||
$MadelineProto->messages->setInlineBotResults($toset);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
\danog\MadelineProto\Serialization::serialize('MadelineProto_bot.madeline', $MadelineProto);
|
||||
}
|
@ -15,7 +15,7 @@ require 'vendor/autoload.php';
|
||||
$settings = [];
|
||||
$MadelineProto = false;
|
||||
try {
|
||||
$MadelineProto = \danog\MadelineProto\Serialization::deserialize('bot.madeline');
|
||||
$MadelineProto = \danog\MadelineProto\Serialization::deserialize('pipesbot.madeline');
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
}
|
||||
$uMadelineProto = \danog\MadelineProto\Serialization::deserialize('pwr.madeline');
|
||||
@ -92,9 +92,9 @@ $offset = 0;
|
||||
$start = "This bot can create a pipeline between inline bots.
|
||||
To use it, simply type an inline query with the following syntax:
|
||||
|
||||
Query | @ainlinebot:1 | @binlinebot:lel | @inlinebot \$
|
||||
@pipesbot Hey I'm writing this using the leet filter of @filtersbot w/ @lolcatzbot | @filtersbot:eleet | @lolcatzbot \$
|
||||
|
||||
This will make an inline query with text \"Query\" to @ainlinebot, take the first result if it's a text message (entities will be ignored, if it's a media message you will be redirected here), then it will make an inline query to @binlinebot with the text received out of the first bot, select the result that is a text message with the word \"lel\" in it (regexes are supported), and finally pipe it to @inlinebot, fetch all results and return them to you.
|
||||
This will make an inline query with text \"Hey I'm writing this using the leet filter of @filtersbot w/ @lolcatzbot\" to @filtersbot, take the result that has the word \"eleet\" (regexes are supported. you can specify just the username to select the first result), in the title, if it's a text message (entities will be ignored, if it's a media message you will be redirected here), then it will make an inline query to @lolcatzbot with the text received out of the first bot fetch all results and return them to you.
|
||||
Note that the query must be terminated by a \$
|
||||
|
||||
Created by @danogentili (@daniilgentili) using the daniil.it/MadelineProto PHP MTProto client.";
|
@ -15,6 +15,7 @@
|
||||
"require": {
|
||||
"php": ">=5.6.0",
|
||||
"danog/phpstruct": "dev-fast",
|
||||
"danog/primemodule": "dev-master",
|
||||
"phpseclib/phpseclib": "dev-ige",
|
||||
"vlucas/phpdotenv": "^2.4",
|
||||
"krakjoe/pthreads-polyfill": "dev-master",
|
||||
|
@ -15,7 +15,7 @@ namespace danog\MadelineProto;
|
||||
/**
|
||||
* Manages all of the mtproto stuff.
|
||||
*/
|
||||
class MTProto extends PrimeModule
|
||||
class MTProto
|
||||
{
|
||||
use \danog\MadelineProto\MTProtoTools\AckHandler;
|
||||
use \danog\MadelineProto\MTProtoTools\AuthKeyHandler;
|
||||
|
@ -83,16 +83,14 @@ trait AuthKeyHandler
|
||||
* ***********************************************************************
|
||||
* Compute p and q
|
||||
*/
|
||||
$pq = new \phpseclib\Math\BigInteger($pq_bytes, 256);
|
||||
list($p, $q) = $this->PrimeFactors($pq);
|
||||
$p = new \phpseclib\Math\BigInteger($p);
|
||||
$q = new \phpseclib\Math\BigInteger($q);
|
||||
|
||||
if ($p->compare($q) > 0) {
|
||||
$pq = \danog\PHP\Struct::unpack('>Q', $pq_bytes)[0];
|
||||
$p = \danog\PrimeModule::auto_single($pq);
|
||||
$q = $pq / $p;
|
||||
if ($p > $q) {
|
||||
list($p, $q) = [$q, $p];
|
||||
}
|
||||
|
||||
if (!($pq->equals($p->multiply($q)) && $p->compare($q) < 0)) {
|
||||
if ($pq !== $p*$q) {
|
||||
throw new \danog\MadelineProto\Exception("couldn't compute p and q.");
|
||||
}
|
||||
|
||||
@ -102,8 +100,8 @@ trait AuthKeyHandler
|
||||
* ***********************************************************************
|
||||
* Serialize object for req_DH_params
|
||||
*/
|
||||
$p_bytes = \danog\PHP\Struct::pack('>I', (string) $p);
|
||||
$q_bytes = \danog\PHP\Struct::pack('>I', (string) $q);
|
||||
$p_bytes = \danog\PHP\Struct::pack('>I', $p);
|
||||
$q_bytes = \danog\PHP\Struct::pack('>I', $q);
|
||||
|
||||
$new_nonce = $this->random(32);
|
||||
|
||||
|
@ -1,135 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright 2016-2017 Daniil Gentili
|
||||
(https://daniil.it)
|
||||
This file is part of MadelineProto.
|
||||
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with the MadelineProto.
|
||||
If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
class PrimeModule
|
||||
{
|
||||
// Uses https://github.com/LonamiWebs/Telethon/blob/master/telethon/crypto/factorizator.py, thank you so freaking much!
|
||||
public function find_small_multiplier_lopatin($what)
|
||||
{
|
||||
$g = 0;
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
$q = (rand(0, 127) & 15) + 17;
|
||||
$x = rand(0, 1000000000) + 1;
|
||||
$y = $x;
|
||||
$lim = 1 << ($i + 18);
|
||||
for ($j = 1; $j <= $lim; $j++) {
|
||||
list($a, $b, $c) = [$x, $x, $q];
|
||||
while ($b != 0) {
|
||||
if (($b & 1) != 0) {
|
||||
$c += $a;
|
||||
if ($c >= $what) {
|
||||
$c -= $what;
|
||||
}
|
||||
}
|
||||
$a += $a;
|
||||
if ($a >= $what) {
|
||||
$a -= $what;
|
||||
}
|
||||
$b >>= 1;
|
||||
}
|
||||
$x = $c;
|
||||
$z = ($x < $y) ? $y - $x : $x - $y;
|
||||
$g = $this->gcd($z, $what);
|
||||
if ($g != 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (($j & ($j - 1)) === 0) {
|
||||
$y = $x;
|
||||
}
|
||||
}
|
||||
if ($g > 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$p = $what; // g
|
||||
return min($p, $g);
|
||||
}
|
||||
|
||||
public function gcd($a, $b)
|
||||
{
|
||||
while ($a != 0 && $b != 0) {
|
||||
while ($b & 1 === 0) {
|
||||
$b >>= 1;
|
||||
}
|
||||
while ($a & 1 === 0) {
|
||||
$a >>= 1;
|
||||
}
|
||||
if ($a > $b) {
|
||||
$a -= $b;
|
||||
} else {
|
||||
$b -= $a;
|
||||
}
|
||||
}
|
||||
|
||||
return ($b === 0) ? $a : $b;
|
||||
}
|
||||
|
||||
public function PrimeFactors($pq)
|
||||
{
|
||||
$pqstr = (string) $pq;
|
||||
|
||||
\danog\MadelineProto\Logger::log(['Trying to use the python factorization module'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
if (function_exists('shell_exec')) {
|
||||
try {
|
||||
$res = json_decode(shell_exec('python '.__DIR__.'/getpq.py '.$pqstr));
|
||||
if (count($res) === 2) {
|
||||
return $res;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
\danog\MadelineProto\Logger::log(['Trying to use the wolfram alpha factorization module'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
try {
|
||||
$query = 'Do prime factorization of '.$pqstr;
|
||||
$params = [
|
||||
'async' => true,
|
||||
'banners' => 'raw',
|
||||
'debuggingdata' => false,
|
||||
'format' => 'moutput',
|
||||
'formattimeout' => 8,
|
||||
'input' => $query,
|
||||
'output' => 'JSON',
|
||||
'proxycode' => json_decode(file_get_contents('http://www.wolframalpha.com/api/v1/code'), true)['code'],
|
||||
];
|
||||
$url = 'https://www.wolframalpha.com/input/json.jsp?'.http_build_query($params);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Referer: https://www.wolframalpha.com/input/?i='.urlencode($query)]);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
$res = json_decode(curl_exec($ch), true);
|
||||
curl_close($ch);
|
||||
foreach ($res['queryresult']['pods'] as $cur) {
|
||||
if ($cur['id'] === 'Divisors') {
|
||||
$res = explode(', ', preg_replace(["/{\d+, /", "/, \d+}$/"], '', $cur['subpods'][0]['moutput']));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (count($res) === 2) {
|
||||
return $res;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
\danog\MadelineProto\Logger::log(['Trying to use the native factorization module'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
$res = $this->find_small_multiplier_lopatin((int) $pqstr);
|
||||
$res = [$res, $pqstr / $res];
|
||||
if ($res[1] != 1) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
throw new Exception("Couldn't calculate pq!");
|
||||
}
|
||||
}
|
@ -115,6 +115,13 @@ trait Login
|
||||
|
||||
return $this->API->datacenter->authorization = $this->account->getPassword();
|
||||
}
|
||||
if ($e->getMessage() === 'PHONE_NUMBER_UNOCCUPIED') {
|
||||
\danog\MadelineProto\Logger::log(['An account has not been created for this number, you will have to call the complete_signup function...'], \danog\MadelineProto\Logger::NOTICE);
|
||||
$this->API->datacenter->login_temp_status = 'waiting_signup';
|
||||
$this->API->should_serialize = true;
|
||||
$this->API->datacenter->authorization['phone_code'] = $code;
|
||||
return ['_' => 'account.needSignup'];
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
$this->API->datacenter->authorization = $authorization;
|
||||
@ -127,6 +134,31 @@ trait Login
|
||||
return $this->API->datacenter->authorization;
|
||||
}
|
||||
|
||||
public function complete_signup($first_name, $last_name)
|
||||
{
|
||||
if ($this->API->datacenter->login_temp_status !== 'waiting_signup') {
|
||||
throw new \danog\MadelineProto\Exception("I'm not waiting for the password! Please call the phone_login and the complete_phone_login methods first!");
|
||||
}
|
||||
$this->API->datacenter->login_temp_status = 'none';
|
||||
\danog\MadelineProto\Logger::log(['Signing up as a normal user...'], \danog\MadelineProto\Logger::NOTICE);
|
||||
$this->API->datacenter->authorization = $this->API->method_call(
|
||||
'auth.signUp',
|
||||
[
|
||||
'phone_number' => $this->API->datacenter->authorization['phone_number'],
|
||||
'phone_code_hash' => $this->API->datacenter->authorization['phone_code_hash'],
|
||||
'phone_code' => $this->API->datacenter->authorization['phone_code'],
|
||||
'first_name' => $first_name,
|
||||
'last_name' => $last_name,
|
||||
]
|
||||
);
|
||||
$this->API->datacenter->authorized = true;
|
||||
$this->API->get_updates_state();
|
||||
$this->API->should_serialize = true;
|
||||
|
||||
\danog\MadelineProto\Logger::log(['Signed up in successfully!'], \danog\MadelineProto\Logger::NOTICE);
|
||||
|
||||
return $this->API->datacenter->authorization;
|
||||
}
|
||||
public function complete_2fa_login($password)
|
||||
{
|
||||
if ($this->API->datacenter->login_temp_status !== 'waiting_password') {
|
||||
@ -143,9 +175,7 @@ trait Login
|
||||
$this->API->datacenter->authorized = true;
|
||||
$this->API->get_updates_state();
|
||||
$this->API->should_serialize = true;
|
||||
|
||||
\danog\MadelineProto\Logger::log(['Logged in successfully!'], \danog\MadelineProto\Logger::NOTICE);
|
||||
|
||||
return $this->API->datacenter->authorization;
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import prime
|
||||
import sys
|
||||
import json
|
||||
|
||||
def eprint(*args, **kwargs):
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
pq = prime.primefactors(long(sys.argv[1]))
|
||||
|
||||
sys.stdout.write(json.dumps(pq))
|
||||
sys.stdout.flush()
|
@ -1,141 +0,0 @@
|
||||
# NOTICE!!! This is copied from https://stackoverflow.com/questions/4643647/fast-prime-factorization-module
|
||||
|
||||
import random
|
||||
|
||||
def primesbelow(N):
|
||||
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
|
||||
#""" Input N>=6, Returns a list of primes, 2 <= p < N """
|
||||
correction = N % 6 > 1
|
||||
N = {0:N, 1:N-1, 2:N+4, 3:N+3, 4:N+2, 5:N+1}[N%6]
|
||||
sieve = [True] * (N // 3)
|
||||
sieve[0] = False
|
||||
for i in range(int(N ** .5) // 3 + 1):
|
||||
if sieve[i]:
|
||||
k = (3 * i + 1) | 1
|
||||
sieve[k*k // 3::2*k] = [False] * ((N//6 - (k*k)//6 - 1)//k + 1)
|
||||
sieve[(k*k + 4*k - 2*k*(i%2)) // 3::2*k] = [False] * ((N // 6 - (k*k + 4*k - 2*k*(i%2))//6 - 1) // k + 1)
|
||||
return [2, 3] + [(3 * i + 1) | 1 for i in range(1, N//3 - correction) if sieve[i]]
|
||||
|
||||
smallprimeset = set(primesbelow(100000))
|
||||
_smallprimeset = 100000
|
||||
|
||||
def isprime(n, precision=7):
|
||||
# http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time
|
||||
if n == 1 or n % 2 == 0:
|
||||
return False
|
||||
elif n < 1:
|
||||
raise ValueError("Out of bounds, first argument must be > 0")
|
||||
elif n < _smallprimeset:
|
||||
return n in smallprimeset
|
||||
|
||||
|
||||
d = n - 1
|
||||
s = 0
|
||||
while d % 2 == 0:
|
||||
d //= 2
|
||||
s += 1
|
||||
|
||||
for repeat in range(precision):
|
||||
a = random.randrange(2, n - 2)
|
||||
x = pow(a, d, n)
|
||||
|
||||
if x == 1 or x == n - 1: continue
|
||||
|
||||
for r in range(s - 1):
|
||||
x = pow(x, 2, n)
|
||||
if x == 1: return False
|
||||
if x == n - 1: break
|
||||
else: return False
|
||||
|
||||
return True
|
||||
|
||||
# https://comeoncodeon.wordpress.com/2010/09/18/pollard-rho-brent-integer-factorization/
|
||||
def pollard_brent(n):
|
||||
if n % 2 == 0: return 2
|
||||
if n % 3 == 0: return 3
|
||||
|
||||
y, c, m = random.randint(1, n-1), random.randint(1, n-1), random.randint(1, n-1)
|
||||
|
||||
g, r, q = 1, 1, 1
|
||||
while g == 1:
|
||||
x = y
|
||||
for i in range(r):
|
||||
y = (pow(y, 2, n) + c) % n
|
||||
|
||||
k = 0
|
||||
while k < r and g==1:
|
||||
ys = y
|
||||
for i in range(min(m, r-k)):
|
||||
y = (pow(y, 2, n) + c) % n
|
||||
q = q * abs(x-y) % n
|
||||
|
||||
g = gcd(q, n)
|
||||
k += m
|
||||
r *= 2
|
||||
if g == n:
|
||||
while True:
|
||||
ys = (pow(ys, 2, n) + c) % n
|
||||
g = gcd(abs(x - ys), n)
|
||||
if g > 1:
|
||||
break
|
||||
|
||||
return g
|
||||
|
||||
smallprimes = primesbelow(10000) # might seem low, but 1000*1000 = 1000000, so this will fully factor every composite < 1000000
|
||||
def primefactors(n, sort=False):
|
||||
factors = []
|
||||
|
||||
limit = int(n ** .5) + 1
|
||||
for checker in smallprimes:
|
||||
if checker > limit: break
|
||||
while n % checker == 0:
|
||||
factors.append(checker)
|
||||
n //= checker
|
||||
limit = int(n ** .5) + 1
|
||||
if checker > limit: break
|
||||
|
||||
if n < 2: return factors
|
||||
|
||||
while n > 1:
|
||||
if isprime(n):
|
||||
factors.append(n)
|
||||
break
|
||||
factor = pollard_brent(n) # trial division did not fully factor, switch to pollard-brent
|
||||
factors.extend(primefactors(factor)) # recurse to factor the not necessarily prime factor returned by pollard-brent
|
||||
n //= factor
|
||||
|
||||
if sort: factors.sort()
|
||||
|
||||
return factors
|
||||
|
||||
def factorization(n):
|
||||
factors = {}
|
||||
for p1 in primefactors(n):
|
||||
try:
|
||||
factors[p1] += 1
|
||||
except KeyError:
|
||||
factors[p1] = 1
|
||||
return factors
|
||||
|
||||
totients = {}
|
||||
def totient(n):
|
||||
if n == 0: return 1
|
||||
|
||||
try: return totients[n]
|
||||
except KeyError: pass
|
||||
|
||||
tot = 1
|
||||
for p, exp in factorization(n).items():
|
||||
tot *= (p - 1) * p ** (exp - 1)
|
||||
|
||||
totients[n] = tot
|
||||
return tot
|
||||
|
||||
def gcd(a, b):
|
||||
if a == b: return a
|
||||
while b > 0: a, b = b, a % b
|
||||
return a
|
||||
|
||||
def lcm(a, b):
|
||||
return abs(a * b) // gcd(a, b)
|
||||
|
@ -54,6 +54,10 @@ if ($MadelineProto === false) {
|
||||
\danog\MadelineProto\Logger::log(['2FA is enabled'], \danog\MadelineProto\Logger::NOTICE);
|
||||
$authorization = $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
}
|
||||
if ($authorization['_'] === 'account.needSignup') {
|
||||
\danog\MadelineProto\Logger::log(['Registering new user'], \danog\MadelineProto\Logger::NOTICE);
|
||||
$authorization = $MadelineProto->complete_signup($code, readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
}
|
||||
echo 'Serializing MadelineProto to session.madeline...'.PHP_EOL;
|
||||
echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('session.madeline', $MadelineProto).' bytes'.PHP_EOL;
|
||||
} else {
|
||||
@ -62,7 +66,8 @@ if ($MadelineProto === false) {
|
||||
}
|
||||
$message = (getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sembre) (yo lavorar siempre) (mi labori ĉiam) (я всегда работать) (Ik werkuh altijd)' : ('Travis ci tests in progress: commit '.getenv('TRAVIS_COMMIT').', job '.getenv('TRAVIS_JOB_NUMBER').', PHP version: '.getenv('TRAVIS_PHP_VERSION'));
|
||||
|
||||
$flutter = 'https://storage.pwrtelegram.xyz/pwrtelegrambot/document/file_6570.mp4';
|
||||
var_dump( $MadelineProto->API->get_full_info('@pwrtelegram'));
|
||||
|
||||
$mention = $MadelineProto->get_info(getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id
|
||||
$mention = $mention['user_id']; // Selects only the numeric user id
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user