mirror of
https://github.com/Sysbot-org/tgscraper.git
synced 2025-01-24 09:37:31 +01:00
Added 'version' field (might not work on older versions), improved Postman schema, initial OpenAPI implementation
This commit is contained in:
parent
3eef215858
commit
137960dea2
@ -33,13 +33,33 @@ class SchemaExtractor
|
|||||||
'answerPreCheckoutQuery'
|
'answerPreCheckoutQuery'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
private Dom $dom;
|
||||||
|
|
||||||
|
private string $version;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SchemaExtractor constructor.
|
* SchemaExtractor constructor.
|
||||||
* @param LoggerInterface $logger
|
* @param LoggerInterface $logger
|
||||||
* @param string $url
|
* @param string $url
|
||||||
|
* @throws ChildNotFoundException
|
||||||
|
* @throws CircularException
|
||||||
|
* @throws ClientExceptionInterface
|
||||||
|
* @throws ContentLengthException
|
||||||
|
* @throws LogicalException
|
||||||
|
* @throws StrictException
|
||||||
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public function __construct(private LoggerInterface $logger, private string $url = Versions::LATEST)
|
public function __construct(private LoggerInterface $logger, private string $url = Versions::LATEST)
|
||||||
{
|
{
|
||||||
|
$this->dom = new Dom();
|
||||||
|
try {
|
||||||
|
$this->dom->loadFromURL($this->url);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$this->logger->critical(sprintf('Unable to load data from URL "%s": %s', $this->url, $e->getMessage()));
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
$this->version = $this->parseVersion();
|
||||||
|
$this->logger->info('Bot API version: ' . $this->version);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,6 +96,28 @@ class SchemaExtractor
|
|||||||
return ['description' => $description, 'table' => $table, 'extended_by' => $extendedBy];
|
return ['description' => $description, 'table' => $table, 'extended_by' => $extendedBy];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function parseVersion(): string
|
||||||
|
{
|
||||||
|
/** @var Dom\Node\AbstractNode $element */
|
||||||
|
$element = $this->dom->find('h3')[0];
|
||||||
|
$tag = '';
|
||||||
|
while ($tag != 'p') {
|
||||||
|
try {
|
||||||
|
$element = $element->nextSibling();
|
||||||
|
} catch (ChildNotFoundException | ParentNotFoundException) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$tag = $element->tag->name();
|
||||||
|
}
|
||||||
|
$versionNumbers = explode('.', str_replace('Bot API ', '', $element->innerText));
|
||||||
|
return sprintf(
|
||||||
|
'%s.%s.%s',
|
||||||
|
$versionNumbers[0] ?? '1',
|
||||||
|
$versionNumbers[1] ?? '0',
|
||||||
|
$versionNumbers[2] ?? '0'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
* @throws ChildNotFoundException
|
* @throws ChildNotFoundException
|
||||||
@ -88,28 +130,24 @@ class SchemaExtractor
|
|||||||
* @throws ClientExceptionInterface
|
* @throws ClientExceptionInterface
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
|
#[ArrayShape(['version' => "string", 'methods' => "array", 'types' => "array"])]
|
||||||
public function extract(): array
|
public function extract(): array
|
||||||
{
|
{
|
||||||
$dom = new Dom;
|
|
||||||
try {
|
try {
|
||||||
$dom->loadFromURL($this->url);
|
$elements = $this->dom->find('h4');
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
$this->logger->critical(sprintf('Unable to load data from URL "%s": %s', $this->url, $e->getMessage()));
|
$this->logger->critical(sprintf('Unable to load data from URL "%s": %s', $this->url, $e->getMessage()));
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
try {
|
$data = ['version' => $this->version];
|
||||||
$elements = $dom->find('h4');
|
|
||||||
} catch (Throwable $e) {
|
|
||||||
$this->logger->critical(sprintf('Unable to load data from URL "%s": %s', $this->url, $e->getMessage()));
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
$data = [];
|
|
||||||
/* @var Dom\Node\AbstractNode $element */
|
/* @var Dom\Node\AbstractNode $element */
|
||||||
foreach ($elements as $element) {
|
foreach ($elements as $element) {
|
||||||
if (!str_contains($name = $element->text, ' ')) {
|
if (!str_contains($name = $element->text, ' ')) {
|
||||||
$isMethod = lcfirst($name) == $name;
|
$isMethod = lcfirst($name) == $name;
|
||||||
$path = $isMethod ? 'methods' : 'types';
|
$path = $isMethod ? 'methods' : 'types';
|
||||||
['description' => $description, 'table' => $table, 'extended_by' => $extendedBy] = self::parseNode($element);
|
['description' => $description, 'table' => $table, 'extended_by' => $extendedBy] = self::parseNode(
|
||||||
|
$element
|
||||||
|
);
|
||||||
$data[$path][] = self::generateElement(
|
$data[$path][] = self::generateElement(
|
||||||
$name,
|
$name,
|
||||||
trim($description),
|
trim($description),
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace TgScraper;
|
namespace TgScraper;
|
||||||
|
|
||||||
|
use BadMethodCallException;
|
||||||
use Exception;
|
use Exception;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use JetBrains\PhpStorm\ArrayShape;
|
use JetBrains\PhpStorm\ArrayShape;
|
||||||
@ -27,6 +28,11 @@ use Throwable;
|
|||||||
class Generator
|
class Generator
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path to templates directory.
|
||||||
|
*/
|
||||||
|
public const TEMPLATES_DIRECTORY = __DIR__ . '/../templates';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
@ -53,8 +59,8 @@ class Generator
|
|||||||
?array $schema = null
|
?array $schema = null
|
||||||
) {
|
) {
|
||||||
if (empty($schema)) {
|
if (empty($schema)) {
|
||||||
$extractor = new SchemaExtractor($this->logger, $this->url);
|
|
||||||
try {
|
try {
|
||||||
|
$extractor = new SchemaExtractor($this->logger, $this->url);
|
||||||
$this->logger->info('Schema not provided, extracting from URL.');
|
$this->logger->info('Schema not provided, extracting from URL.');
|
||||||
$schema = $extractor->extract();
|
$schema = $extractor->extract();
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
@ -179,6 +185,14 @@ class Generator
|
|||||||
return Yaml::dump($this->schema, $inline, $indent, $flags);
|
return Yaml::dump($this->schema, $inline, $indent, $flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function toOpenApi(): string
|
||||||
|
{
|
||||||
|
throw new BadMethodCallException('Not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thanks to davtur19 (https://github.com/davtur19/TuriBotGen/blob/master/postman.php)
|
* Thanks to davtur19 (https://github.com/davtur19/TuriBotGen/blob/master/postman.php)
|
||||||
@ -189,24 +203,16 @@ class Generator
|
|||||||
public function toPostman(
|
public function toPostman(
|
||||||
int $options = 0
|
int $options = 0
|
||||||
): string {
|
): string {
|
||||||
$result = [
|
$template = file_get_contents(self::TEMPLATES_DIRECTORY . '/postman.json');
|
||||||
'info' => [
|
$result = json_decode($template, true);
|
||||||
'name' => 'Telegram Bot API',
|
$result['info']['version'] = $this->schema['version'];
|
||||||
'schema' => 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json'
|
|
||||||
],
|
|
||||||
'variable' => [
|
|
||||||
'key' => 'token',
|
|
||||||
'value' => '1234:AAbbcc',
|
|
||||||
'type' => 'string'
|
|
||||||
]
|
|
||||||
];
|
|
||||||
foreach ($this->schema['methods'] as $method) {
|
foreach ($this->schema['methods'] as $method) {
|
||||||
$formData = [];
|
$formData = [];
|
||||||
if (!empty($method['fields'])) {
|
if (!empty($method['fields'])) {
|
||||||
foreach ($method['fields'] as $field) {
|
foreach ($method['fields'] as $field) {
|
||||||
$formData[] = [
|
$formData[] = [
|
||||||
'key' => $field['name'],
|
'key' => $field['name'],
|
||||||
'value' => '',
|
'disabled' => !$field['required'],
|
||||||
'description' => sprintf(
|
'description' => sprintf(
|
||||||
'%s. %s',
|
'%s. %s',
|
||||||
$field['required'] ? 'Required' : 'Optional',
|
$field['required'] ? 'Required' : 'Optional',
|
||||||
|
144
templates/openapi.json
Normal file
144
templates/openapi.json
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Telegram Bot API",
|
||||||
|
"description": "Auto-generated OpenAPI schema by TGScraper.",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "https://api.telegram.org/bot{token}",
|
||||||
|
"variables": {
|
||||||
|
"token": {
|
||||||
|
"default": "1234:AAbbcc",
|
||||||
|
"description": "Bot's unique authentication token, given by @BotFather."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"externalDocs": {
|
||||||
|
"description": "Official Telegram Bot API documentation",
|
||||||
|
"url": "https://core.telegram.org/bots/api"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"responses": {
|
||||||
|
"BadRequest": {
|
||||||
|
"description": "Bad request, you have provided malformed data.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Unauthorized": {
|
||||||
|
"description": "The authorization token is invalid or it has been revoked.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Forbidden": {
|
||||||
|
"description": "This action is forbidden.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NotFound": {
|
||||||
|
"description": "The specified resource was not found.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Conflict": {
|
||||||
|
"description": "There is a conflict with another instance using webhook or polling.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TooManyRequests": {
|
||||||
|
"description": "You're doing too many requests, retry after a while.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"schemas": {
|
||||||
|
"Response": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"ok"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"ok": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Success": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Response"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"result"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"result": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Error": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Response"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"error_code",
|
||||||
|
"description"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"error_code": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"parameters": {
|
||||||
|
"$ref": "#/components/schemas/ResponseParameters"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"paths": {}
|
||||||
|
}
|
15
templates/postman.json
Normal file
15
templates/postman.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"name": "Telegram Bot API",
|
||||||
|
"description": "Auto-generated Postman collection by TGScraper.",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"variable": {
|
||||||
|
"key": "token",
|
||||||
|
"description": "Bot's unique authentication token, given by @BotFather.",
|
||||||
|
"type": "string",
|
||||||
|
"value": "1234:AAbbcc"
|
||||||
|
},
|
||||||
|
"item": []
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user