diff --git a/README.md b/README.md index 699b7b1..637ce42 100644 --- a/README.md +++ b/README.md @@ -336,55 +336,39 @@ Commands: command Generate code for a new command ``` -#### API code core -This generates all necessary code to implement api calls to a core module. +#### API code generator +This generates all necessary code to implement api calls to a module. -For a list of all plugin api endpoints see: - -https://github.com/opnsense/docs/tree/master/source/development/api/core - -Or: +See a list of all compatible modules: ``` +# core modules $ opn-cli new api list --module-type core -``` -Example that generates code for the core module 'cron': - -``` -$ opn-cli new api core cron -``` - -This generates a class for every controller of the core module. -Every class contains methodes to call all api endpoints of the corresponding controller. - -Please move the file from the output dir to the destination folders under opnsense_cli/. -The default output path is opnsense_cli/output/api/core/ . -#### API code plugin -This generates all necessary code to implement api calls to a plugin module. - -For a list of all plugin api endpoints see: - -https://github.com/opnsense/docs/tree/master/source/development/api/plugins - -Or: +# plugin modules +$ opn-cli new api list --module-type plugins -``` -$ opn-cli new api list --module-type plugin ``` -Example that generates code for the plugin module 'haproxy': +Examples: ``` +# generate all api code for the module core cron +$ opn-cli new api core cron + +# generate all api code for the module plugins haproxy $ opn-cli new api plugin haproxy + +# generate all api code for the module plugins unbound +$ opn-cli new api plugin unbound + ``` -This generates a class for every controller of the plugin module. -Every class contains methodes to call all api endpoints of the corresponding controller. +This generates a class for every controller of the core module. +Every class contains methods to call all api endpoints of the corresponding controller. Please move the file from the output dir to the destination folders under opnsense_cli/. -The default output path is opnsense_cli/output/api/plugins/ . - +The default output path is opnsense_cli/output/api/[core|plugins]/ . #### Core command code This generates all necessary code and tests to implement a new command from a core module. diff --git a/opnsense_cli/commands/new/api.py b/opnsense_cli/commands/new/api.py index afbfd76..b24bb09 100644 --- a/opnsense_cli/commands/new/api.py +++ b/opnsense_cli/commands/new/api.py @@ -2,8 +2,10 @@ import os from opnsense_cli.commands.new import new from opnsense_cli.code_generators.opnsense_api.codegenerator import OpnsenseApiCodeGenerator +from opnsense_cli.parser.html_parser import HtmlParser from opnsense_cli.parser.opnsense_api_reference_parser import OpnsenseApiReferenceParser from opnsense_cli.parser.opnsense_module_list_parser import OpnsenseModuleListParser +from opnsense_cli.parser.rst_parser import RstParser from opnsense_cli.template_engines.jinja2 import Jinja2TemplateEngine @@ -15,13 +17,13 @@ def api(**kwargs): @api.command() -@click.argument("plugin_module_name", required=True) +@click.argument("module_name", required=True) @click.option( "--api-reference-url", "-aru", help=("The url to the api reference in the official Opnsense documentation"), show_default=True, - default="https://github.com/opnsense/docs/tree/master/source/development/api/plugins", + default="https://raw.githubusercontent.com/opnsense/docs/master/source/development/api/plugins", required=True, ) @click.option( @@ -49,10 +51,6 @@ def plugin(**kwargs): """ Generate new api code for a plugin module. - List all plugin module names: - - $ opn-cli new api list --module-type plugin - Example: Generate api code for the 'haproxy' plugin module @@ -61,17 +59,17 @@ def plugin(**kwargs): Default output path is opn-cli/opnsense_cli/output/api/plugins/ """ - generate_api_files(kwargs["plugin_module_name"], **kwargs) + generate_api_files(**kwargs) @api.command() -@click.argument("core_module_name", required=True) +@click.argument("module_name", required=True) @click.option( "--api-reference-url", "-aru", help=("The url to the core module api reference in the official Opnsense documentation."), show_default=True, - default="https://github.com/opnsense/docs/tree/master/source/development/api/core", + default="https://raw.githubusercontent.com/opnsense/docs/master/source/development/api/core", required=True, ) @click.option( @@ -111,7 +109,7 @@ def core(**kwargs): Default output path is opn-cli/opnsense_cli/output/api/core/ """ - generate_api_files(kwargs["core_module_name"], **kwargs) + generate_api_files(**kwargs) @api.command() @@ -120,14 +118,14 @@ def core(**kwargs): "-bu", help=("The url to the api reference in the official Opnsense documentation."), show_default=True, - default="https://github.com/opnsense/docs/tree/master/source/development/api/", + default="https://github.com/opnsense/docs/tree/master/source/development/api", required=True, ) @click.option( "--module-type", "-mt", - help=("The url to the api reference in the official Opnsense documentation."), - type=click.Choice(["core", "plugin"], case_sensitive=True), + help=("What type of modules to list. core or plugins"), + type=click.Choice(["core", "plugins"], case_sensitive=True), required=True, ) def list(**kwargs): @@ -139,18 +137,27 @@ def list(**kwargs): $ opn-cli new api list --module-type plugin """ - list_modules(kwargs["module_type"], kwargs["base_url"]) + list_modules(f"{kwargs['base_url']}/{kwargs['module_type']}") -def generate_api_files(module_name, **kwargs): - controller_parser = OpnsenseApiReferenceParser( - kwargs["api_reference_url"], - "table", - module_name, - ) - controller_html_tables = controller_parser.parse() +def list_modules(url): + github_html_parser = HtmlParser(url, 'script[type="application/json"][data-target="react-app.embeddedData"]', False) + parsed_github_html_tag = github_html_parser.parse() + module_list_parser = OpnsenseModuleListParser(parsed_github_html_tag) + module_list = module_list_parser.parse() + + for module in module_list: + click.echo(module) + +def generate_api_files(**kwargs): + rst_url = f"{kwargs['api_reference_url']}/{kwargs['module_name']}.rst" + rst_parser = RstParser(rst_url, 'table') + api_reference_tables = rst_parser.parse() + + api_reference_parser = OpnsenseApiReferenceParser(api_reference_tables) + controller_html_tables = api_reference_parser.parse() template_engine = Jinja2TemplateEngine(kwargs["api_template_basedir"]) - write_api(template_engine, controller_html_tables, module_name, **kwargs) + write_api(template_engine, controller_html_tables, kwargs['plugin_module_name'], **kwargs) def write_api(template_engine, controllers, module_name, **kwargs): @@ -162,11 +169,4 @@ def write_api(template_engine, controllers, module_name, **kwargs): click.echo(api_code_generator.write_code(output_path)) -def list_modules(type, url): - if type == "core": - url += "core" - elif type == "plugin": - url += "plugins" - module_list = OpnsenseModuleListParser(url).module_list - for module in module_list: - click.echo(module) + diff --git a/opnsense_cli/commands/new/command.py b/opnsense_cli/commands/new/command.py index 5286114..c16654b 100755 --- a/opnsense_cli/commands/new/command.py +++ b/opnsense_cli/commands/new/command.py @@ -121,7 +121,7 @@ def core(**kwargs): @command.command() @click.argument("click_group") -@click.argument("opn_cli") +@click.argument("click_group") @click.option( "--model-url", "-m", @@ -225,7 +225,7 @@ def write_command(type, model_tag: Tag, template_engine, option_factory, **kwarg option_factory, kwargs["template_command"], kwargs["click_group"], - kwargs["opn_cli"], + kwargs["click_group"], kwargs["tag"], type, ) @@ -234,7 +234,7 @@ def write_command(type, model_tag: Tag, template_engine, option_factory, **kwarg form_parser = OpnsenseFormParser(kwargs["form_url"], "form") command_code_generator.help_messages = form_parser.parse() - output_path = f"{kwargs['command_output_dir']}/{kwargs['click_group']}/{kwargs['opn_cli']}.py" + output_path = f"{kwargs['command_output_dir']}/{kwargs['click_group']}/{kwargs['click_group']}.py" click.echo(command_code_generator.write_code(output_path)) @@ -246,11 +246,11 @@ def write_command_service(type, model_tag: Tag, template_engine, option_factory, option_factory, kwargs["template_service"], kwargs["click_group"], - kwargs["opn_cli"], + kwargs["click_group"], kwargs["tag"], type, ) - output_path = f"{kwargs['command_output_dir']}/{kwargs['click_group']}/services/{kwargs['click_group']}_{kwargs['opn_cli']}_service.py" # noqa: E501 + output_path = f"{kwargs['command_output_dir']}/{kwargs['click_group']}/services/{kwargs['click_group']}_{kwargs['click_group']}_service.py" # noqa: E501 click.echo(command_service_generator.write_code(output_path)) @@ -262,13 +262,13 @@ def write_command_test(type, model_tag: Tag, template_engine, option_factory, ** option_factory, kwargs["template_test"], kwargs["click_group"], - kwargs["opn_cli"], + kwargs["click_group"], kwargs["tag"], type, ) output_path = ( - f"{kwargs['command_output_dir']}/{kwargs['click_group']}/tests/test_{kwargs['click_group']}_{kwargs['opn_cli']}.py" + f"{kwargs['command_output_dir']}/{kwargs['click_group']}/tests/test_{kwargs['click_group']}_{kwargs['click_group']}.py" ) click.echo(command_test_generator.write_code(output_path)) diff --git a/opnsense_cli/commands/new/tests/fixtures/api/core.html b/opnsense_cli/commands/new/tests/fixtures/api/core.html index 172c378..9bcdc29 100644 --- a/opnsense_cli/commands/new/tests/fixtures/api/core.html +++ b/opnsense_cli/commands/new/tests/fixtures/api/core.html @@ -1,100 +1,38 @@ - - +Core +~~~~ - - +.. csv-table:: Resources (BackupController.php) +:header: "Method", "Module", "Controller", "Command", "Parameters" +:widths: 4, 15, 15, 30, 40 - +"``GET``","core","backup","backups","$host" +"``GET``","core","backup","deleteBackup","$backup" +"``GET``","core","backup","diff","$host,$backup1,$backup2" +"``GET``","core","backup","download","$host,$backup=null" +"``GET``","core","backup","providers","" +"``GET``","core","backup","revertBackup","$backup" - - - - - - - - - - - - - - - - -
MethodModuleControllerCommandParameters
POSTcronservicereconfigure 
+.. csv-table:: Resources (MenuController.php) +:header: "Method", "Module", "Controller", "Command", "Parameters" +:widths: 4, 15, 15, 30, 40 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodModuleControllerCommandParameters
POSTcronsettingsaddJob 
POSTcronsettingsdelJob$uuid
GETcronsettingsget 
GETcronsettingsgetJob$uuid=null
*cronsettingssearchJobs 
GETcronsettingsset 
POSTcronsettingssetJob$uuid
POSTcronsettingstoggleJob$uuid,$enabled=null
     
<<uses>>   model Cron.xml
+"``GET``","core","menu","search","" +"``GET``","core","menu","tree","" - - +.. csv-table:: Service (ServiceController.php) +:header: "Method", "Module", "Controller", "Command", "Parameters" +:widths: 4, 15, 15, 30, 40 + +"``POST``","core","service","restart","$name,$id=''" +"``GET``","core","service","search","" +"``POST``","core","service","start","$name,$id=''" +"``POST``","core","service","stop","$name,$id=''" + +.. csv-table:: Resources (SystemController.php) +:header: "Method", "Module", "Controller", "Command", "Parameters" +:widths: 4, 15, 15, 30, 40 + +"``POST``","core","system","dismissStatus","" +"``POST``","core","system","halt","" +"``POST``","core","system","reboot","" +"``GET``","core","system","status","" diff --git a/opnsense_cli/commands/new/tests/fixtures/api/core_list.html b/opnsense_cli/commands/new/tests/fixtures/api/core_list.html index 0808b54..789e464 100644 --- a/opnsense_cli/commands/new/tests/fixtures/api/core_list.html +++ b/opnsense_cli/commands/new/tests/fixtures/api/core_list.html @@ -1,28 +1,3688 @@ + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + docs/source/development/api/core at master · opnsense/docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - -captiveportal.rst -core.rst -cron.rst -diagnostics.rst -firewall.rst -firmware.rst -ids.rst -interfaces.rst -ipsec.rst -menu.rst -monit.rst -openvpn.rst -proxy.rst -routes.rst -syslog.rst -trafficshaper.rst -unbound.rst + +
+ + + +
+ Skip to content + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + +
+ + +
+
+ + + + + + +
+
+
+

+ Global navigation +

+
+
+
+
+ +
+
+
+ +
+ + +
+ + + + +
+
+
+ + +

© 2024 GitHub, Inc.

+ +
+
+
+ +
+ +
+
+ + + +
+
+ + + + +
+
+
+

+ Navigate back to +

+
+
+ +
+
+
+ + + + +
+
+ +
+ +
+
+ +
+
+ + +
+ + + Create new... + + + + + + + + Issues + + + Pull requests + +
+ + + + + + + Notifications + + + + +
+ + + + + + + +
+
+
+

+ Account menu +

+
+
+ + + andreas-stuerz + + + + Andreas Stürz + +
+ + + Create new... + + + + + +
+
+
+
+ +
+
+
+ +
+ + + +
+
+
+ +
+
+ +
+
+ +
+ +
+ + + + + +
+
+
+ + + +
+ + + + +
+ +
+ + + + + + + + +
+ + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ +
+ + + + opnsense  /   + docs  /   + +
+
+ + + +
+ + +
+
+ Clear Command Palette +
+
+ + + +
+
+ Tip: + Type # to search pull requests +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type # to search issues +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type # to search discussions +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type ! to search projects +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type @ to search teams +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type @ to search people and organizations +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type > to activate command mode +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Go to your accessibility settings to change your keyboard shortcuts +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type author:@me to search your content +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type is:pr to filter to pull requests +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type is:issue to filter to issues +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type is:project to filter to projects +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type is:open to filter to open content +
+
+ Type ? for help and tips +
+
+
+ +
+ +
+
+ We’ve encountered an error and some results aren't available at this time. Type a new search or try again later. +
+
+ + No results matched your search + + + + + + + + + + +
+ + + + + Search for issues and pull requests + + # + + + + Search for issues, pull requests, discussions, and projects + + # + + + + Search for organizations, repositories, and users + + @ + + + + Search for projects + + ! + + + + Search for files + + / + + + + Activate command mode + + > + + + + Search your issues, pull requests, and discussions + + # author:@me + + + + Search your issues, pull requests, and discussions + + # author:@me + + + + Filter to pull requests + + # is:pr + + + + Filter to issues + + # is:issue + + + + Filter to discussions + + # is:discussion + + + + Filter to projects + + # is:project + + + + Filter to open issues, pull requests, and discussions + + # is:open + + + + + + + + + + + + + + + + +
+
+
+ +
+ + + + + + + + + + +
+ + +
+
+
+ + + + + + + + + + + + + + + + + + +
+ Open in github.dev + Open in a new github.dev tab + Open in codespace + + + + + + + + + + + + + + + +

Files

t
+
+ + + + +
+ +
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + - - diff --git a/opnsense_cli/commands/new/tests/fixtures/api/plugin_list.html b/opnsense_cli/commands/new/tests/fixtures/api/plugin_list.html index cb642f1..19707ee 100644 --- a/opnsense_cli/commands/new/tests/fixtures/api/plugin_list.html +++ b/opnsense_cli/commands/new/tests/fixtures/api/plugin_list.html @@ -1,70 +1,3688 @@ + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + docs/source/development/api/plugins at master · opnsense/docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - -acmeclient.rst -backup.rst -bind.rst -chrony.rst -cicap.rst -clamav.rst -collectd.rst -diagnostics.rst -dnscryptproxy.rst -fetchmail.rst -firewall.rst -firewall.rst.in -firewall.sample_create.py -firewall.savepoint.py -freeradius.rst -ftpproxy.rst -haproxy.rst -helloworld.rst -hwprobe.rst -iperf.rst -lldpd.rst -maltrail.rst -mdnsrepeater.rst -muninnode.rst -netdata.rst -netsnmp.rst -nginx.rst -nodeexporter.rst -nrpe.rst -ntopng.rst -nut.rst -openconnect.rst -postfix.rst -proxysso.rst -proxyuseracl.rst -puppetagent.rst -qemuguestagent.rst -quagga.rst -radsecproxy.rst -redis.rst -relayd.rst -rspamd.rst -shadowsocks.rst -siproxd.rst -smart.rst -softether.rst -stunnel.rst -tayga.rst -telegraf.rst -tftp.rst -tinc.rst -tor.rst -udpbroadcastrelay.rst -vnstat.rst -wireguard.rst -wol.rst -zabbixagent.rst -zabbixproxy.rst -zerotier.rst + +
+ + + +
+ Skip to content + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + +
+ + +
+
+ + + + + + +
+
+
+

+ Global navigation +

+
+
+
+
+ +
+
+
+ +
+ + +
+ + + + +
+
+
+ + +

© 2024 GitHub, Inc.

+ +
+
+
+ +
+ +
+
+ + + +
+
+ + + + +
+
+
+

+ Navigate back to +

+
+
+ +
+
+
+ + + + +
+
+ +
+ +
+
+ +
+
+ + +
+ + + Create new... + + + + + + + + Issues + + + Pull requests + +
+ + + + + + + Notifications + + + + +
+ + + + + + + +
+
+
+

+ Account menu +

+
+
+ + + andreas-stuerz + + + + Andreas Stürz + +
+ + + Create new... + + + + + +
+
+
+
+ +
+
+
+ +
+ + + +
+
+
+ +
+
+ +
+
+ +
+ +
+ + + + + +
+
+
+ + + +
+ + + + +
+ +
+ + + + + + + + +
+ + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ +
+ + + + opnsense  /   + docs  /   + +
+
+ + + +
+ + +
+
+ Clear Command Palette +
+
+ + + +
+
+ Tip: + Type # to search pull requests +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type # to search issues +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type # to search discussions +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type ! to search projects +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type @ to search teams +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type @ to search people and organizations +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type > to activate command mode +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Go to your accessibility settings to change your keyboard shortcuts +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type author:@me to search your content +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type is:pr to filter to pull requests +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type is:issue to filter to issues +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type is:project to filter to projects +
+
+ Type ? for help and tips +
+
+
+ +
+
+ Tip: + Type is:open to filter to open content +
+
+ Type ? for help and tips +
+
+
+ +
+ +
+
+ We’ve encountered an error and some results aren't available at this time. Type a new search or try again later. +
+
+ + No results matched your search + + + + + + + + + + +
+ + + + + Search for issues and pull requests + + # + + + + Search for issues, pull requests, discussions, and projects + + # + + + + Search for organizations, repositories, and users + + @ + + + + Search for projects + + ! + + + + Search for files + + / + + + + Activate command mode + + > + + + + Search your issues, pull requests, and discussions + + # author:@me + + + + Search your issues, pull requests, and discussions + + # author:@me + + + + Filter to pull requests + + # is:pr + + + + Filter to issues + + # is:issue + + + + Filter to discussions + + # is:discussion + + + + Filter to projects + + # is:project + + + + Filter to open issues, pull requests, and discussions + + # is:open + + + + + + + + + + + + + + + + +
+
+
+ +
+ + + + + + + + + + +
+ + +
+
+
+ + + + + + + + + + + + + + + + + + +
+ Open in github.dev + Open in a new github.dev tab + Open in codespace + + + + + + + + + + + + + + + +

Files

t

Latest commit

History

History

plugins

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
+
+ + + + +
+ +
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + - - diff --git a/opnsense_cli/commands/new/tests/test_new_api.py b/opnsense_cli/commands/new/tests/test_new_api.py index 1c3fc56..bb88ace 100644 --- a/opnsense_cli/commands/new/tests/test_new_api.py +++ b/opnsense_cli/commands/new/tests/test_new_api.py @@ -227,7 +227,7 @@ def test_list(self, mock_model_get: Mock): runner = CliRunner() result_plugin = runner.invoke( api, - ["list", "--module-type", "plugin", "--base-url", "https://fake.githubusercontent.com/module/plugin.html"], + ["list", "--module-type", "plugins", "--base-url", "https://fake.githubusercontent.com/module/plugin.html"], catch_exceptions=False, ) self.assertIn("haproxy", result_plugin.output) diff --git a/opnsense_cli/parser/html_parser.py b/opnsense_cli/parser/html_parser.py index 6e8cefd..dffaa9a 100644 --- a/opnsense_cli/parser/html_parser.py +++ b/opnsense_cli/parser/html_parser.py @@ -4,15 +4,15 @@ class HtmlParser(Parser): - def __init__(self, url, tag): + def __init__(self, url, html_selector, find_all=True): self._url = url - self._tag = tag + self._html_selector = html_selector + self._find_all = find_all def _set_content(self): webpage_response = requests.get(self._url, verify=True) - webpage = webpage_response.content - self._content = BeautifulSoup(webpage, "html.parser") + self._content = BeautifulSoup(webpage_response.content, "html.parser") def _parse_content(self): - tags = self._content.find_all(self._tag) - return tags + elements = self._content.select(self._html_selector) if self._find_all else self._content.select_one(self._html_selector) + return elements diff --git a/opnsense_cli/parser/opnsense_api_reference_parser.py b/opnsense_cli/parser/opnsense_api_reference_parser.py index 7fc0cb5..9b12cc7 100644 --- a/opnsense_cli/parser/opnsense_api_reference_parser.py +++ b/opnsense_cli/parser/opnsense_api_reference_parser.py @@ -1,28 +1,16 @@ -from bs4 import BeautifulSoup -import requests -from opnsense_cli.parser.html_parser import HtmlParser +from opnsense_cli.parser.base import Parser -class OpnsenseApiReferenceParser(HtmlParser): - def __init__(self, url, tag, module_name): - super().__init__(url, tag) - self._module_name = module_name +class OpnsenseApiReferenceParser(Parser): + def __init__(self, controller_html_tables): + self._controller_html_tables = controller_html_tables + def _parse_content(self) -> dict: - controller_html_tables = super()._parse_content() - return self._get_api_endpoints(controller_html_tables) + return self._get_api_endpoints(self._content) def _set_content(self): - super()._set_content() - github_url = "https://github.com" - links = self._content.find_all("a", href=True) - for link in links: - if link["href"].endswith(".rst"): - url_component_list = link["href"].split("/") - if self._check_url_components(url_component_list): - webpage_plugin_response = requests.get(github_url + link["href"], verify=True) - webpage_plugin = webpage_plugin_response.content - self._content = BeautifulSoup(webpage_plugin, "html.parser") + self._content = self._controller_html_tables def _check_url_components(self, url_components): if len(url_components) > 2: diff --git a/opnsense_cli/parser/opnsense_module_list_parser.py b/opnsense_cli/parser/opnsense_module_list_parser.py index 86763d1..94bc027 100644 --- a/opnsense_cli/parser/opnsense_module_list_parser.py +++ b/opnsense_cli/parser/opnsense_module_list_parser.py @@ -1,24 +1,13 @@ -from opnsense_cli.parser.html_parser import HtmlParser - - -class OpnsenseModuleListParser(HtmlParser): - def __init__(self, url): - super().__init__(url, "a") - self.module_list = self._list_all_modules() - - def _list_all_modules(self): - super()._set_content() - links = self._content.find_all(self._tag, href=True) - module_list = [] - for link in links: - if link["href"].endswith(".rst"): - url_component_list = link["href"].split("/") - module = self._get_module(url_component_list) - module_list.append(module) - return module_list - - def _get_module(self, url_components): - if len(url_components) > 2: - module_type = url_components[-2] - if module_type == "plugins" or module_type == "core": - return url_components[-1].split(".")[0] +from opnsense_cli.parser.base import Parser +import json +from bs4.element import Tag + + +class OpnsenseModuleListParser(Parser): + def __init__(self, parsed_html_tag_from_gh: Tag): + self._parsed_html_tag_from_gh = parsed_html_tag_from_gh + def _set_content(self): + json_content = self._parsed_html_tag_from_gh.string.strip() + self._content = json.loads(json_content) + def _parse_content(self) -> dict: + return [item["name"].split(".")[0] for item in self._content["payload"]["tree"]["items"]] diff --git a/opnsense_cli/parser/rst_parser.py b/opnsense_cli/parser/rst_parser.py new file mode 100644 index 0000000..fdd0284 --- /dev/null +++ b/opnsense_cli/parser/rst_parser.py @@ -0,0 +1,20 @@ +from bs4 import BeautifulSoup +import requests +from opnsense_cli.parser.base import Parser +from docutils import core + +class RstParser(Parser): + def __init__(self, url, html_selector, find_all=True): + self._url = url + self._html_selector = html_selector + self._find_all = find_all + + def _set_content(self): + webpage_response = requests.get(self._url, verify=True) + rst_content = webpage_response.content + html_content = core.publish_string(rst_content, writer_name='html') + self._content = BeautifulSoup(html_content, "html.parser") + + def _parse_content(self): + elements = self._content.select(self._html_selector) if self._find_all else self._content.select_one(self._html_selector) + return elements