diff --git a/Cargo.toml b/Cargo.toml index c15c160..02370f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "template" +name = "tgphpgen" version = "0.1.0" edition = "2021" -license = "GPL-2.0" +license = "MIT" [profile.release] strip = true @@ -11,4 +11,5 @@ lto = "on" codegen-units = 1 [dependencies] +regex = "1.11.2" diff --git a/README.md b/README.md new file mode 100644 index 0000000..f09bb80 --- /dev/null +++ b/README.md @@ -0,0 +1,85 @@ +# rust-telegram-php5-generator + +A small Rust CLI utility that parses the Telegram Bot API HTML documentation (saved from https://core.telegram.org/bots/api) and generates PHP methods for every API method, preserving argument order and copying documentation. Designed for projects stuck on PHP 5.6 that cannot use modern Telegram bindings. + +--- + +## Features + +- Parses a saved HTML page of the Telegram Bot API documentation. +- Generates PHP method stubs for every API method found. +- Preserves documentation (method description, parameter descriptions) and original argument order. +- Outputs generated PHP code to stdout; errors are written to stderr. +- Accepts optional prefix and suffix files to inject custom code around the generated method list. + +--- + +## Usage + +Build and run the utility (example assumes the compiled binary is named `tgphpgen`): + +``` +tgphpgen /path/to/bots_api.html [/path/to/prefix.php] [/path/to/suffix.php] +``` + +- First argument (required): **path to the saved HTML documentation file** (the page from core.telegram.org/bots/api). +- Second argument (optional): **path to a prefix file** whose contents will be prepended before the generated methods. +- Third argument (optional): **path to a suffix file** whose contents will be appended after the generated methods. + +Output: +- Generated PHP code is written to **stdout**. +- Parsing or file errors are written to **stderr** and the program exits with a non-zero exit code. + +--- + +## Generated PHP style + +- Each Telegram API method becomes a PHP method inside a class. +- Argument names and order match the documentation. +- Required arguments are checked against emptiness. When detected an error is returned in `['1' => ...]` for easier destructive assignment using golang-inspired `list ($res, $err) = ` +- Parameter types and descriptions are included as PHPDoc above each function when available. +- Optional parameters are given default values to maintain compatibility with PHP 5.6. +- All methods internally invoke `$this->trySend($apiMethodName, $apiMethodArgs)` implementation of which should be provided by user in a prefix/suffix file + +--- + +## Implementation notes + +- The parser expects the HTML structure from core.telegram.org/bots/api as saved by a browser. Minor variations in formatting may require adjusting the parser. +- The tool focuses on robustness for PHP 5.6 compatibility: + - No type hints in generated PHP function signatures. + - Optional params default to `null`. + - Uses associative arrays and simple return values (arrays) so integration with existing PHP5.6 code is straightforward. The errors returned in the `1` key as to be easily extractable using golang-like syntax of `list ($result, $error) = ...`. +- The utility prints helpful errors to stderr for: + - Missing input file + - Invalid HTML structure (unable to locate API method sections) + - File read errors for prefix/suffix + +--- + +## Examples + +Generate methods only: + +``` +tgphpgen bots_api.html > telegram_methods.php +``` + +Generate with a wrapper class (prefix contains class header, suffix contains closing brace): + +``` +tgphpgen bots_api.html prefix.php suffix.php > TelegramApi.php +``` + +--- + +## Contributing + +- Fixes for parsing edge cases welcome — the HTML layout on core.telegram.org may change; tests and example saved HTML files help keep the parser resilient. +- Please include a saved copy of the documentation page that reproduces any parsing bug you report. + +--- + +## License + +MIT License. diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..16e921a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,224 @@ + + +#[derive(Default, Debug, Clone)] +struct Method { + name: String, + description: String, + notes: String, + params: Vec +} + +#[derive(Default, Debug, Clone)] +struct Param { + name: String, + kind: String, + required: String, + description: String, + returns: String +} + +#[derive(Default, Clone)] +enum AlreadyParsed { + MethodName(Method), + MethodDescription(Method), + MethodParams(Method), + + Skipping, + + #[default] + Nothing +} + +fn take_between<'a>(line: &'a str, from: &str, to: &str) -> &'a str { + line + .split(from).nth(1).unwrap_or("") + .split(to).nth(0).unwrap_or("") +} + +fn main() { + + let path = std::env::args().nth(1).unwrap(); + let data = std::fs::read_to_string(path).unwrap(); + let data = take_between(&data, r#"