From 68bb159dc3c1d545ace7588fae7545a577589278 Mon Sep 17 00:00:00 2001 From: Joel Wachsler Date: Fri, 22 Jul 2022 14:29:01 +0000 Subject: [PATCH] Progress --- qbittorrent-web-api-gen/groups.txt | 8969 +++++++---------- .../src/generate/group/mod.rs | 427 +- .../src/generate/skeleton.rs | 12 +- .../group/method/method_tests/enum.check | 37 + .../parser/group/method/method_tests/enum.md | 12 + .../group/method/method_tests/enum.tree | 67 + .../method/method_tests/search_result.check | 262 +- .../src/parser/group/method/mod.rs | 264 +- qbittorrent-web-api-gen/src/types.rs | 92 +- qbittorrent-web-api-gen/tests/search_types.rs | 7 +- 10 files changed, 4391 insertions(+), 5758 deletions(-) create mode 100644 qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.check create mode 100644 qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.md create mode 100644 qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.tree diff --git a/qbittorrent-web-api-gen/groups.txt b/qbittorrent-web-api-gen/groups.txt index c32ae2f..4984ab4 100644 --- a/qbittorrent-web-api-gen/groups.txt +++ b/qbittorrent-web-api-gen/groups.txt @@ -7,44 +7,47 @@ description: Some( "Upon success, the response will contain a cookie with your SID. You must supply the cookie whenever you want to perform an operation that requires authentication.\n\nExample showing how to login and execute a command that requires authentication using `curl`:\n\n```sh\n$ curl -i --header 'Referer: http://localhost:8080' --data 'username=admin&password=adminadmin' http://localhost:8080/api/v2/auth/login\nHTTP/1.1 200 OK\nContent-Encoding:\nContent-Length: 3\nContent-Type: text/plain; charset=UTF-8\nSet-Cookie: SID=hBc7TxF76ERhvIw0jQQ4LZ7Z1jQUV0tQ; path=/\n$ curl http://localhost:8080/api/v2/torrents/info --cookie \"SID=hBc7TxF76ERhvIw0jQQ4LZ7Z1jQUV0tQ\"\n```\n\nNote: Set `Referer` or `Origin` header to the exact same domain and port as used in the HTTP query `Host` header.", ), - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "username", - is_optional: false, - is_list: false, - description: Some( - "Username used to access the WebUI", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "password", - is_optional: false, - is_list: false, - description: Some( - "Password used to access the WebUI", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "login", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "username", + is_optional: false, + is_list: false, + description: Some( + "Username used to access the WebUI", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "password", + is_optional: false, + is_list: false, + description: Some( + "Password used to access the WebUI", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "logout", description: None, - parameters: None, - return_type: None, url: "logout", + types: CompositeTypes { + composite_types: [], + }, }, ], description: Some( @@ -60,2532 +63,453 @@ description: Some( "The response is a string with the application version, e.g. `v4.1.3`", ), - parameters: None, - return_type: None, url: "version", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "webapiVersion", description: Some( "The response is a string with the WebAPI version, e.g. `2.0`", ), - parameters: None, - return_type: None, url: "webapiVersion", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "buildInfo", description: Some( "The response is a JSON object containing the following fields", ), - parameters: None, - return_type: Some( - ReturnType { - is_list: false, - parameters: [ - ReturnTypeParameter { - name: "qt", - description: "QT version", - return_type: String( - TypeInfo { - name: "qt", - is_optional: false, - is_list: false, - description: Some( - "QT version", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "libtorrent", - description: "libtorrent version", - return_type: String( - TypeInfo { - name: "libtorrent", - is_optional: false, - is_list: false, - description: Some( - "libtorrent version", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "boost", - description: "Boost version", - return_type: String( - TypeInfo { - name: "boost", - is_optional: false, - is_list: false, - description: Some( - "Boost version", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "openssl", - description: "OpenSSL version", - return_type: String( - TypeInfo { - name: "openssl", - is_optional: false, - is_list: false, - description: Some( - "OpenSSL version", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "bitness", - description: "Application bitness (e.g. 64-bit)", - return_type: Number( - TypeInfo { - name: "bitness", - is_optional: false, - is_list: false, - description: Some( - "Application bitness (e.g. 64-bit)", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "buildInfo", + types: CompositeTypes { + composite_types: [ + Response( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "qt", + is_optional: false, + is_list: false, + description: Some( + "QT version", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "libtorrent", + is_optional: false, + is_list: false, + description: Some( + "libtorrent version", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "boost", + is_optional: false, + is_list: false, + description: Some( + "Boost version", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "openssl", + is_optional: false, + is_list: false, + description: Some( + "OpenSSL version", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "bitness", + is_optional: false, + is_list: false, + description: Some( + "Application bitness (e.g. 64-bit)", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "shutdown", description: None, - parameters: None, - return_type: None, url: "shutdown", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "preferences", description: Some( "The response is a JSON object with several fields (key-value) pairs representing the application's settings. The contents may vary depending on which settings are present in qBittorrent.ini.\n\nPossible fields:\n\n\nPossible values of `scan_dirs`:\n\n\nPossible values of `scheduler_days`:\n\n\nPossible values of `encryption`:\n\n\nNB: the first options allows you to use both encrypted and unencrypted connections (this is the default); other options are mutually exclusive: e.g. by forcing encryption on you won't be able to use unencrypted connections and vice versa.\n\nPossible values of `proxy_type`:\n\n\nPossible values of `dyndns_service`:\n\n\nPossible values of `max_ratio_act`:\n\n\nPossible values of `bittorrent_protocol`:\n\n\nPossible values of `upload_choking_algorithm`:\n\n\nPossible values of `upload_slots_behavior`:\n\n\nPossible values of `utp_tcp_mixed_mode`:\n\n\nExample:\n\n```JSON\n{\n \"add_trackers\": \"\",\n \"add_trackers_enabled\": false,\n \"alt_dl_limit\": 10240,\n \"alt_up_limit\": 10240,\n \"alternative_webui_enabled\": false,\n \"alternative_webui_path\": \"/home/user/Documents/qbit-webui\",\n \"announce_ip\": \"\",\n \"announce_to_all_tiers\": true,\n \"announce_to_all_trackers\": false,\n \"anonymous_mode\": false,\n \"async_io_threads\": 4,\n \"auto_delete_mode\": 0,\n \"auto_tmm_enabled\": false,\n \"autorun_enabled\": false,\n \"autorun_program\": \"\",\n \"banned_IPs\": \"\",\n \"bittorrent_protocol\": 0,\n \"bypass_auth_subnet_whitelist\": \"\",\n \"bypass_auth_subnet_whitelist_enabled\": false,\n \"bypass_local_auth\": false,\n \"category_changed_tmm_enabled\": false,\n \"checking_memory_use\": 32,\n \"create_subfolder_enabled\": true,\n \"current_interface_address\": \"\",\n \"current_network_interface\": \"\",\n \"dht\": true,\n \"disk_cache\": -1,\n \"disk_cache_ttl\": 60,\n \"dl_limit\": 0,\n \"dont_count_slow_torrents\": false,\n \"dyndns_domain\": \"changeme.dyndns.org\",\n \"dyndns_enabled\": false,\n \"dyndns_password\": \"\",\n \"dyndns_service\": 0,\n \"dyndns_username\": \"\",\n \"embedded_tracker_port\": 9000,\n \"enable_coalesce_read_write\": false,\n \"enable_embedded_tracker\": false,\n \"enable_multi_connections_from_same_ip\": false,\n \"enable_os_cache\": true,\n \"enable_piece_extent_affinity\": false,\n \"enable_upload_suggestions\": false,\n \"encryption\": 0,\n \"export_dir\": \"/home/user/Downloads/all\",\n \"export_dir_fin\": \"/home/user/Downloads/completed\",\n \"file_pool_size\": 40,\n \"incomplete_files_ext\": false,\n \"ip_filter_enabled\": false,\n \"ip_filter_path\": \"\",\n \"ip_filter_trackers\": false,\n \"limit_lan_peers\": true,\n \"limit_tcp_overhead\": false,\n \"limit_utp_rate\": true,\n \"listen_port\": 58925,\n \"locale\": \"en\",\n \"lsd\": true,\n \"mail_notification_auth_enabled\": false,\n \"mail_notification_email\": \"\",\n \"mail_notification_enabled\": false,\n \"mail_notification_password\": \"\",\n \"mail_notification_sender\": \"qBittorrent_notification@example.com\",\n \"mail_notification_smtp\": \"smtp.changeme.com\",\n \"mail_notification_ssl_enabled\": false,\n \"mail_notification_username\": \"\",\n \"max_active_downloads\": 3,\n \"max_active_torrents\": 5,\n \"max_active_uploads\": 3,\n \"max_connec\": 500,\n \"max_connec_per_torrent\": 100,\n \"max_ratio\": -1,\n \"max_ratio_act\": 0,\n \"max_ratio_enabled\": false,\n \"max_seeding_time\": -1,\n \"max_seeding_time_enabled\": false,\n \"max_uploads\": -1,\n \"max_uploads_per_torrent\": -1,\n \"outgoing_ports_max\": 0,\n \"outgoing_ports_min\": 0,\n \"pex\": true,\n \"preallocate_all\": false,\n \"proxy_auth_enabled\": false,\n \"proxy_ip\": \"0.0.0.0\",\n \"proxy_password\": \"\",\n \"proxy_peer_connections\": false,\n \"proxy_port\": 8080,\n \"proxy_torrents_only\": false,\n \"proxy_type\": 0,\n \"proxy_username\": \"\",\n \"queueing_enabled\": false,\n \"random_port\": false,\n \"recheck_completed_torrents\": false,\n \"resolve_peer_countries\": true,\n \"rss_auto_downloading_enabled\":true,\n \"rss_download_repack_proper_episodes\":true,\n \"rss_max_articles_per_feed\":50,\n \"rss_processing_enabled\":true,\n \"rss_refresh_interval\":30,\n \"rss_smart_episode_filters\":\"s(\\\\d+)e(\\\\d+)\\n(\\\\d+)x(\\\\d+)\\n(\\\\d{4}[.\\\\-]\\\\d{1,2}[.\\\\-]\\\\d{1,2})\",\n \"save_path\": \"/home/user/Downloads/\",\n \"save_path_changed_tmm_enabled\": false,\n \"save_resume_data_interval\": 60,\n \"scan_dirs\":\n {\n \"/home/user/Downloads/incoming/games\": 0,\n \"/home/user/Downloads/incoming/movies\": 1,\n },\n \"schedule_from_hour\": 8,\n \"schedule_from_min\": 0,\n \"schedule_to_hour\": 20,\n \"schedule_to_min\": 0,\n \"scheduler_days\": 0,\n \"scheduler_enabled\": false,\n \"send_buffer_low_watermark\": 10,\n \"send_buffer_watermark\": 500,\n \"send_buffer_watermark_factor\": 50,\n \"slow_torrent_dl_rate_threshold\": 2,\n \"slow_torrent_inactive_timer\": 60,\n \"slow_torrent_ul_rate_threshold\": 2,\n \"socket_backlog_size\": 30,\n \"start_paused_enabled\": false,\n \"stop_tracker_timeout\": 1,\n \"temp_path\": \"/home/user/Downloads/temp\",\n \"temp_path_enabled\": false,\n \"torrent_changed_tmm_enabled\": true,\n \"up_limit\": 0,\n \"upload_choking_algorithm\": 1,\n \"upload_slots_behavior\": 0,\n \"upnp\": true,\n \"use_https\": false,\n \"utp_tcp_mixed_mode\": 0,\n \"web_ui_address\": \"*\",\n \"web_ui_ban_duration\": 3600,\n \"web_ui_clickjacking_protection_enabled\": true,\n \"web_ui_csrf_protection_enabled\": true,\n \"web_ui_custom_http_headers\": \"\",\n \"web_ui_domain_list\": \"*\",\n \"web_ui_host_header_validation_enabled\": true,\n \"web_ui_https_cert_path\": \"\",\n \"web_ui_https_key_path\": \"\",\n \"web_ui_max_auth_fail_count\": 5,\n \"web_ui_port\": 8080,\n \"web_ui_secure_cookie_enabled\": true,\n \"web_ui_session_timeout\": 3600,\n \"web_ui_upnp\": false,\n \"web_ui_use_custom_http_headers_enabled\": false,\n \"web_ui_username\": \"admin\"\n}\n```", ), - parameters: None, - return_type: Some( - ReturnType { - is_list: false, - parameters: [ - ReturnTypeParameter { - name: "locale", - description: "Currently selected language (e.g. en_GB for English)", - return_type: String( - TypeInfo { - name: "locale", - is_optional: false, - is_list: false, - description: Some( - "Currently selected language (e.g. en_GB for English)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "create_subfolder_enabled", - description: "True if a subfolder should be created when adding a torrent", - return_type: Bool( - TypeInfo { - name: "create_subfolder_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if a subfolder should be created when adding a torrent", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "start_paused_enabled", - description: "True if torrents should be added in a Paused state", - return_type: Bool( - TypeInfo { - name: "start_paused_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if torrents should be added in a Paused state", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "auto_delete_mode", - description: "TODO", - return_type: Number( - TypeInfo { - name: "auto_delete_mode", - is_optional: false, - is_list: false, - description: Some( - "TODO", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "preallocate_all", - description: "True if disk space should be pre-allocated for all files", - return_type: Bool( - TypeInfo { - name: "preallocate_all", - is_optional: false, - is_list: false, - description: Some( - "True if disk space should be pre-allocated for all files", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "incomplete_files_ext", - description: "True if \".!qB\" should be appended to incomplete files", - return_type: Bool( - TypeInfo { - name: "incomplete_files_ext", - is_optional: false, - is_list: false, - description: Some( - "True if \".!qB\" should be appended to incomplete files", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "auto_tmm_enabled", - description: "True if Automatic Torrent Management is enabled by default", - return_type: Bool( - TypeInfo { - name: "auto_tmm_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if Automatic Torrent Management is enabled by default", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "torrent_changed_tmm_enabled", - description: "True if torrent should be relocated when its Category changes", - return_type: Bool( - TypeInfo { - name: "torrent_changed_tmm_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if torrent should be relocated when its Category changes", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "save_path_changed_tmm_enabled", - description: "True if torrent should be relocated when the default save path changes", - return_type: Bool( - TypeInfo { - name: "save_path_changed_tmm_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if torrent should be relocated when the default save path changes", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "category_changed_tmm_enabled", - description: "True if torrent should be relocated when its Category's save path changes", - return_type: Bool( - TypeInfo { - name: "category_changed_tmm_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if torrent should be relocated when its Category's save path changes", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "save_path", - description: "Default save path for torrents, separated by slashes", - return_type: String( - TypeInfo { - name: "save_path", - is_optional: false, - is_list: false, - description: Some( - "Default save path for torrents, separated by slashes", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "temp_path_enabled", - description: "True if folder for incomplete torrents is enabled", - return_type: Bool( - TypeInfo { - name: "temp_path_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if folder for incomplete torrents is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "temp_path", - description: "Path for incomplete torrents, separated by slashes", - return_type: String( - TypeInfo { - name: "temp_path", - is_optional: false, - is_list: false, - description: Some( - "Path for incomplete torrents, separated by slashes", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "scan_dirs", - description: "Property: directory to watch for torrent files, value: where torrents loaded from this directory should be downloaded to (see list of possible values below). Slashes are used as path separators; multiple key/value pairs can be specified", - return_type: Object( - TypeInfo { - name: "scan_dirs", - is_optional: false, - is_list: false, - description: Some( - "Property: directory to watch for torrent files, value: where torrents loaded from this directory should be downloaded to (see list of possible values below). Slashes are used as path separators; multiple key/value pairs can be specified", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "0", - description: "Download to the monitored folder", - }, - TypeDescriptions { - value: "1", - description: "Download to the default save path", - }, - TypeDescriptions { - value: "\"/path/to/download/to\"", - description: "Download to this path", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "export_dir", - description: "Path to directory to copy .torrent files to. Slashes are used as path separators", - return_type: String( - TypeInfo { - name: "export_dir", - is_optional: false, - is_list: false, - description: Some( - "Path to directory to copy .torrent files to. Slashes are used as path separators", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "export_dir_fin", - description: "Path to directory to copy .torrent files of completed downloads to. Slashes are used as path separators", - return_type: String( - TypeInfo { - name: "export_dir_fin", - is_optional: false, - is_list: false, - description: Some( - "Path to directory to copy .torrent files of completed downloads to. Slashes are used as path separators", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "mail_notification_enabled", - description: "True if e-mail notification should be enabled", - return_type: Bool( - TypeInfo { - name: "mail_notification_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if e-mail notification should be enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "mail_notification_sender", - description: "e-mail where notifications should originate from", - return_type: String( - TypeInfo { - name: "mail_notification_sender", - is_optional: false, - is_list: false, - description: Some( - "e-mail where notifications should originate from", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "mail_notification_email", - description: "e-mail to send notifications to", - return_type: String( - TypeInfo { - name: "mail_notification_email", - is_optional: false, - is_list: false, - description: Some( - "e-mail to send notifications to", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "mail_notification_smtp", - description: "smtp server for e-mail notifications", - return_type: String( - TypeInfo { - name: "mail_notification_smtp", - is_optional: false, - is_list: false, - description: Some( - "smtp server for e-mail notifications", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "mail_notification_ssl_enabled", - description: "True if smtp server requires SSL connection", - return_type: Bool( - TypeInfo { - name: "mail_notification_ssl_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if smtp server requires SSL connection", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "mail_notification_auth_enabled", - description: "True if smtp server requires authentication", - return_type: Bool( - TypeInfo { - name: "mail_notification_auth_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if smtp server requires authentication", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "mail_notification_username", - description: "Username for smtp authentication", - return_type: String( - TypeInfo { - name: "mail_notification_username", - is_optional: false, - is_list: false, - description: Some( - "Username for smtp authentication", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "mail_notification_password", - description: "Password for smtp authentication", - return_type: String( - TypeInfo { - name: "mail_notification_password", - is_optional: false, - is_list: false, - description: Some( - "Password for smtp authentication", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "autorun_enabled", - description: "True if external program should be run after torrent has finished downloading", - return_type: Bool( - TypeInfo { - name: "autorun_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if external program should be run after torrent has finished downloading", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "autorun_program", - description: "Program path/name/arguments to run if autorun_enabled is enabled; path is separated by slashes; you can use %f and %n arguments, which will be expanded by qBittorent as path_to_torrent_file and torrent_name (from the GUI; not the .torrent file name) respectively", - return_type: String( - TypeInfo { - name: "autorun_program", - is_optional: false, - is_list: false, - description: Some( - "Program path/name/arguments to run if autorun_enabled is enabled; path is separated by slashes; you can use %f and %n arguments, which will be expanded by qBittorent as path_to_torrent_file and torrent_name (from the GUI; not the .torrent file name) respectively", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "queueing_enabled", - description: "True if torrent queuing is enabled", - return_type: Bool( - TypeInfo { - name: "queueing_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if torrent queuing is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_active_downloads", - description: "Maximum number of active simultaneous downloads", - return_type: Number( - TypeInfo { - name: "max_active_downloads", - is_optional: false, - is_list: false, - description: Some( - "Maximum number of active simultaneous downloads", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_active_torrents", - description: "Maximum number of active simultaneous downloads and uploads", - return_type: Number( - TypeInfo { - name: "max_active_torrents", - is_optional: false, - is_list: false, - description: Some( - "Maximum number of active simultaneous downloads and uploads", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_active_uploads", - description: "Maximum number of active simultaneous uploads", - return_type: Number( - TypeInfo { - name: "max_active_uploads", - is_optional: false, - is_list: false, - description: Some( - "Maximum number of active simultaneous uploads", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dont_count_slow_torrents", - description: "If true torrents w/o any activity (stalled ones) will not be counted towards max_active_* limits; see [dont_count_slow_torrents](https://www.libtorrent.org/reference-Settings.html#dont_count_slow_torrents) for more information", - return_type: Bool( - TypeInfo { - name: "dont_count_slow_torrents", - is_optional: false, - is_list: false, - description: Some( - "If true torrents w/o any activity (stalled ones) will not be counted towards max_active_* limits; see [dont_count_slow_torrents](https://www.libtorrent.org/reference-Settings.html#dont_count_slow_torrents) for more information", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "slow_torrent_dl_rate_threshold", - description: "Download rate in KiB/s for a torrent to be considered \"slow\"", - return_type: Number( - TypeInfo { - name: "slow_torrent_dl_rate_threshold", - is_optional: false, - is_list: false, - description: Some( - "Download rate in KiB/s for a torrent to be considered \"slow\"", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "slow_torrent_ul_rate_threshold", - description: "Upload rate in KiB/s for a torrent to be considered \"slow\"", - return_type: Number( - TypeInfo { - name: "slow_torrent_ul_rate_threshold", - is_optional: false, - is_list: false, - description: Some( - "Upload rate in KiB/s for a torrent to be considered \"slow\"", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "slow_torrent_inactive_timer", - description: "Seconds a torrent should be inactive before considered \"slow\"", - return_type: Number( - TypeInfo { - name: "slow_torrent_inactive_timer", - is_optional: false, - is_list: false, - description: Some( - "Seconds a torrent should be inactive before considered \"slow\"", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_ratio_enabled", - description: "True if share ratio limit is enabled", - return_type: Bool( - TypeInfo { - name: "max_ratio_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if share ratio limit is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_ratio", - description: "Get the global share ratio limit", - return_type: Float( - TypeInfo { - name: "max_ratio", - is_optional: false, - is_list: false, - description: Some( - "Get the global share ratio limit", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_ratio_act", - description: "Action performed when a torrent reaches the maximum share ratio. See list of possible values here below.", - return_type: Number( - TypeInfo { - name: "max_ratio_act", - is_optional: false, - is_list: false, - description: Some( - "Action performed when a torrent reaches the maximum share ratio. See list of possible values here below.", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "0", - description: "Pause torrent", - }, - TypeDescriptions { - value: "1", - description: "Remove torrent", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "listen_port", - description: "Port for incoming connections", - return_type: Number( - TypeInfo { - name: "listen_port", - is_optional: false, - is_list: false, - description: Some( - "Port for incoming connections", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "upnp", - description: "True if UPnP/NAT-PMP is enabled", - return_type: Bool( - TypeInfo { - name: "upnp", - is_optional: false, - is_list: false, - description: Some( - "True if UPnP/NAT-PMP is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "random_port", - description: "True if the port is randomly selected", - return_type: Bool( - TypeInfo { - name: "random_port", - is_optional: false, - is_list: false, - description: Some( - "True if the port is randomly selected", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dl_limit", - description: "Global download speed limit in KiB/s; -1 means no limit is applied", - return_type: Number( - TypeInfo { - name: "dl_limit", - is_optional: false, - is_list: false, - description: Some( - "Global download speed limit in KiB/s; -1 means no limit is applied", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "up_limit", - description: "Global upload speed limit in KiB/s; -1 means no limit is applied", - return_type: Number( - TypeInfo { - name: "up_limit", - is_optional: false, - is_list: false, - description: Some( - "Global upload speed limit in KiB/s; -1 means no limit is applied", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_connec", - description: "Maximum global number of simultaneous connections", - return_type: Number( - TypeInfo { - name: "max_connec", - is_optional: false, - is_list: false, - description: Some( - "Maximum global number of simultaneous connections", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_connec_per_torrent", - description: "Maximum number of simultaneous connections per torrent", - return_type: Number( - TypeInfo { - name: "max_connec_per_torrent", - is_optional: false, - is_list: false, - description: Some( - "Maximum number of simultaneous connections per torrent", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_uploads", - description: "Maximum number of upload slots", - return_type: Number( - TypeInfo { - name: "max_uploads", - is_optional: false, - is_list: false, - description: Some( - "Maximum number of upload slots", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_uploads_per_torrent", - description: "Maximum number of upload slots per torrent", - return_type: Number( - TypeInfo { - name: "max_uploads_per_torrent", - is_optional: false, - is_list: false, - description: Some( - "Maximum number of upload slots per torrent", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "stop_tracker_timeout", - description: "Timeout in seconds for a stopped announce request to trackers", - return_type: Number( - TypeInfo { - name: "stop_tracker_timeout", - is_optional: false, - is_list: false, - description: Some( - "Timeout in seconds for a stopped announce request to trackers", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "enable_piece_extent_affinity", - description: "True if the advanced libtorrent option piece_extent_affinity is enabled", - return_type: Bool( - TypeInfo { - name: "enable_piece_extent_affinity", - is_optional: false, - is_list: false, - description: Some( - "True if the advanced libtorrent option piece_extent_affinity is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "bittorrent_protocol", - description: "Bittorrent Protocol to use (see list of possible values below)", - return_type: Number( - TypeInfo { - name: "bittorrent_protocol", - is_optional: false, - is_list: false, - description: Some( - "Bittorrent Protocol to use (see list of possible values below)", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "0", - description: "TCP and μTP", - }, - TypeDescriptions { - value: "1", - description: "TCP", - }, - TypeDescriptions { - value: "2", - description: "μTP", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "limit_utp_rate", - description: "True if [du]l_limit should be applied to uTP connections; this option is only available in qBittorent built against libtorrent version 0.16.X and higher", - return_type: Bool( - TypeInfo { - name: "limit_utp_rate", - is_optional: false, - is_list: false, - description: Some( - "True if [du]l_limit should be applied to uTP connections; this option is only available in qBittorent built against libtorrent version 0.16.X and higher", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "limit_tcp_overhead", - description: "True if [du]l_limit should be applied to estimated TCP overhead (service data: e.g. packet headers)", - return_type: Bool( - TypeInfo { - name: "limit_tcp_overhead", - is_optional: false, - is_list: false, - description: Some( - "True if [du]l_limit should be applied to estimated TCP overhead (service data: e.g. packet headers)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "limit_lan_peers", - description: "True if [du]l_limit should be applied to peers on the LAN", - return_type: Bool( - TypeInfo { - name: "limit_lan_peers", - is_optional: false, - is_list: false, - description: Some( - "True if [du]l_limit should be applied to peers on the LAN", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "alt_dl_limit", - description: "Alternative global download speed limit in KiB/s", - return_type: Number( - TypeInfo { - name: "alt_dl_limit", - is_optional: false, - is_list: false, - description: Some( - "Alternative global download speed limit in KiB/s", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "alt_up_limit", - description: "Alternative global upload speed limit in KiB/s", - return_type: Number( - TypeInfo { - name: "alt_up_limit", - is_optional: false, - is_list: false, - description: Some( - "Alternative global upload speed limit in KiB/s", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "scheduler_enabled", - description: "True if alternative limits should be applied according to schedule", - return_type: Bool( - TypeInfo { - name: "scheduler_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if alternative limits should be applied according to schedule", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "schedule_from_hour", - description: "Scheduler starting hour", - return_type: Number( - TypeInfo { - name: "schedule_from_hour", - is_optional: false, - is_list: false, - description: Some( - "Scheduler starting hour", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "schedule_from_min", - description: "Scheduler starting minute", - return_type: Number( - TypeInfo { - name: "schedule_from_min", - is_optional: false, - is_list: false, - description: Some( - "Scheduler starting minute", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "schedule_to_hour", - description: "Scheduler ending hour", - return_type: Number( - TypeInfo { - name: "schedule_to_hour", - is_optional: false, - is_list: false, - description: Some( - "Scheduler ending hour", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "schedule_to_min", - description: "Scheduler ending minute", - return_type: Number( - TypeInfo { - name: "schedule_to_min", - is_optional: false, - is_list: false, - description: Some( - "Scheduler ending minute", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "scheduler_days", - description: "Scheduler days. See possible values here below", - return_type: Number( - TypeInfo { - name: "scheduler_days", - is_optional: false, - is_list: false, - description: Some( - "Scheduler days. See possible values here below", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "0", - description: "Every day", - }, - TypeDescriptions { - value: "1", - description: "Every weekday", - }, - TypeDescriptions { - value: "2", - description: "Every weekend", - }, - TypeDescriptions { - value: "3", - description: "Every Monday", - }, - TypeDescriptions { - value: "4", - description: "Every Tuesday", - }, - TypeDescriptions { - value: "5", - description: "Every Wednesday", - }, - TypeDescriptions { - value: "6", - description: "Every Thursday", - }, - TypeDescriptions { - value: "7", - description: "Every Friday", - }, - TypeDescriptions { - value: "8", - description: "Every Saturday", - }, - TypeDescriptions { - value: "9", - description: "Every Sunday", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "dht", - description: "True if DHT is enabled", - return_type: Bool( - TypeInfo { - name: "dht", - is_optional: false, - is_list: false, - description: Some( - "True if DHT is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "pex", - description: "True if PeX is enabled", - return_type: Bool( - TypeInfo { - name: "pex", - is_optional: false, - is_list: false, - description: Some( - "True if PeX is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "lsd", - description: "True if LSD is enabled", - return_type: Bool( - TypeInfo { - name: "lsd", - is_optional: false, - is_list: false, - description: Some( - "True if LSD is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "encryption", - description: "See list of possible values here below", - return_type: Number( - TypeInfo { - name: "encryption", - is_optional: false, - is_list: false, - description: Some( - "See list of possible values here below", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "0", - description: "Prefer encryption", - }, - TypeDescriptions { - value: "1", - description: "Force encryption on", - }, - TypeDescriptions { - value: "2", - description: "Force encryption off", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "anonymous_mode", - description: "If true anonymous mode will be enabled; read more [here](Anonymous-Mode); this option is only available in qBittorent built against libtorrent version 0.16.X and higher", - return_type: Bool( - TypeInfo { - name: "anonymous_mode", - is_optional: false, - is_list: false, - description: Some( - "If true anonymous mode will be enabled; read more [here](Anonymous-Mode); this option is only available in qBittorent built against libtorrent version 0.16.X and higher", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "proxy_type", - description: "See list of possible values here below", - return_type: Number( - TypeInfo { - name: "proxy_type", - is_optional: false, - is_list: false, - description: Some( - "See list of possible values here below", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "-1", - description: "Proxy is disabled", - }, - TypeDescriptions { - value: "1", - description: "HTTP proxy without authentication", - }, - TypeDescriptions { - value: "2", - description: "SOCKS5 proxy without authentication", - }, - TypeDescriptions { - value: "3", - description: "HTTP proxy with authentication", - }, - TypeDescriptions { - value: "4", - description: "SOCKS5 proxy with authentication", - }, - TypeDescriptions { - value: "5", - description: "SOCKS4 proxy without authentication", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "proxy_ip", - description: "Proxy IP address or domain name", - return_type: String( - TypeInfo { - name: "proxy_ip", - is_optional: false, - is_list: false, - description: Some( - "Proxy IP address or domain name", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "proxy_port", - description: "Proxy port", - return_type: Number( - TypeInfo { - name: "proxy_port", - is_optional: false, - is_list: false, - description: Some( - "Proxy port", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "proxy_peer_connections", - description: "True if peer and web seed connections should be proxified; this option will have any effect only in qBittorent built against libtorrent version 0.16.X and higher", - return_type: Bool( - TypeInfo { - name: "proxy_peer_connections", - is_optional: false, - is_list: false, - description: Some( - "True if peer and web seed connections should be proxified; this option will have any effect only in qBittorent built against libtorrent version 0.16.X and higher", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "proxy_auth_enabled", - description: "True proxy requires authentication; doesn't apply to SOCKS4 proxies", - return_type: Bool( - TypeInfo { - name: "proxy_auth_enabled", - is_optional: false, - is_list: false, - description: Some( - "True proxy requires authentication; doesn't apply to SOCKS4 proxies", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "proxy_username", - description: "Username for proxy authentication", - return_type: String( - TypeInfo { - name: "proxy_username", - is_optional: false, - is_list: false, - description: Some( - "Username for proxy authentication", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "proxy_password", - description: "Password for proxy authentication", - return_type: String( - TypeInfo { - name: "proxy_password", - is_optional: false, - is_list: false, - description: Some( - "Password for proxy authentication", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "proxy_torrents_only", - description: "True if proxy is only used for torrents", - return_type: Bool( - TypeInfo { - name: "proxy_torrents_only", - is_optional: false, - is_list: false, - description: Some( - "True if proxy is only used for torrents", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "ip_filter_enabled", - description: "True if external IP filter should be enabled", - return_type: Bool( - TypeInfo { - name: "ip_filter_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if external IP filter should be enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "ip_filter_path", - description: "Path to IP filter file (.dat, .p2p, .p2b files are supported); path is separated by slashes", - return_type: String( - TypeInfo { - name: "ip_filter_path", - is_optional: false, - is_list: false, - description: Some( - "Path to IP filter file (.dat, .p2p, .p2b files are supported); path is separated by slashes", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "ip_filter_trackers", - description: "True if IP filters are applied to trackers", - return_type: Bool( - TypeInfo { - name: "ip_filter_trackers", - is_optional: false, - is_list: false, - description: Some( - "True if IP filters are applied to trackers", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_domain_list", - description: "Comma-separated list of domains to accept when performing Host header validation", - return_type: String( - TypeInfo { - name: "web_ui_domain_list", - is_optional: false, - is_list: false, - description: Some( - "Comma-separated list of domains to accept when performing Host header validation", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_address", - description: "IP address to use for the WebUI", - return_type: String( - TypeInfo { - name: "web_ui_address", - is_optional: false, - is_list: false, - description: Some( - "IP address to use for the WebUI", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_port", - description: "WebUI port", - return_type: Number( - TypeInfo { - name: "web_ui_port", - is_optional: false, - is_list: false, - description: Some( - "WebUI port", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_upnp", - description: "True if UPnP is used for the WebUI port", - return_type: Bool( - TypeInfo { - name: "web_ui_upnp", - is_optional: false, - is_list: false, - description: Some( - "True if UPnP is used for the WebUI port", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_username", - description: "WebUI username", - return_type: String( - TypeInfo { - name: "web_ui_username", - is_optional: false, - is_list: false, - description: Some( - "WebUI username", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_password", - description: "For API ≥ v2.3.0: Plaintext WebUI password, not readable, write-only. For API < v2.3.0: MD5 hash of WebUI password, hash is generated from the following string: username:Web UI Access:plain_text_web_ui_password", - return_type: String( - TypeInfo { - name: "web_ui_password", - is_optional: false, - is_list: false, - description: Some( - "For API ≥ v2.3.0: Plaintext WebUI password, not readable, write-only. For API < v2.3.0: MD5 hash of WebUI password, hash is generated from the following string: username:Web UI Access:plain_text_web_ui_password", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_csrf_protection_enabled", - description: "True if WebUI CSRF protection is enabled", - return_type: Bool( - TypeInfo { - name: "web_ui_csrf_protection_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if WebUI CSRF protection is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_clickjacking_protection_enabled", - description: "True if WebUI clickjacking protection is enabled", - return_type: Bool( - TypeInfo { - name: "web_ui_clickjacking_protection_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if WebUI clickjacking protection is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_secure_cookie_enabled", - description: "True if WebUI cookie Secure flag is enabled", - return_type: Bool( - TypeInfo { - name: "web_ui_secure_cookie_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if WebUI cookie Secure flag is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_max_auth_fail_count", - description: "Maximum number of authentication failures before WebUI access ban", - return_type: Number( - TypeInfo { - name: "web_ui_max_auth_fail_count", - is_optional: false, - is_list: false, - description: Some( - "Maximum number of authentication failures before WebUI access ban", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_ban_duration", - description: "WebUI access ban duration in seconds", - return_type: Number( - TypeInfo { - name: "web_ui_ban_duration", - is_optional: false, - is_list: false, - description: Some( - "WebUI access ban duration in seconds", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_session_timeout", - description: "Seconds until WebUI is automatically signed off", - return_type: Number( - TypeInfo { - name: "web_ui_session_timeout", - is_optional: false, - is_list: false, - description: Some( - "Seconds until WebUI is automatically signed off", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_host_header_validation_enabled", - description: "True if WebUI host header validation is enabled", - return_type: Bool( - TypeInfo { - name: "web_ui_host_header_validation_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if WebUI host header validation is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "bypass_local_auth", - description: "True if authentication challenge for loopback address (127.0.0.1) should be disabled", - return_type: Bool( - TypeInfo { - name: "bypass_local_auth", - is_optional: false, - is_list: false, - description: Some( - "True if authentication challenge for loopback address (127.0.0.1) should be disabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "bypass_auth_subnet_whitelist_enabled", - description: "True if webui authentication should be bypassed for clients whose ip resides within (at least) one of the subnets on the whitelist", - return_type: Bool( - TypeInfo { - name: "bypass_auth_subnet_whitelist_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if webui authentication should be bypassed for clients whose ip resides within (at least) one of the subnets on the whitelist", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "bypass_auth_subnet_whitelist", - description: "(White)list of ipv4/ipv6 subnets for which webui authentication should be bypassed; list entries are separated by commas", - return_type: String( - TypeInfo { - name: "bypass_auth_subnet_whitelist", - is_optional: false, - is_list: false, - description: Some( - "(White)list of ipv4/ipv6 subnets for which webui authentication should be bypassed; list entries are separated by commas", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "alternative_webui_enabled", - description: "True if an alternative WebUI should be used", - return_type: Bool( - TypeInfo { - name: "alternative_webui_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if an alternative WebUI should be used", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "alternative_webui_path", - description: "File path to the alternative WebUI", - return_type: String( - TypeInfo { - name: "alternative_webui_path", - is_optional: false, - is_list: false, - description: Some( - "File path to the alternative WebUI", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "use_https", - description: "True if WebUI HTTPS access is enabled", - return_type: Bool( - TypeInfo { - name: "use_https", - is_optional: false, - is_list: false, - description: Some( - "True if WebUI HTTPS access is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "ssl_key", - description: "For API < v2.0.1: SSL keyfile contents (this is a not a path)", - return_type: String( - TypeInfo { - name: "ssl_key", - is_optional: false, - is_list: false, - description: Some( - "For API < v2.0.1: SSL keyfile contents (this is a not a path)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "ssl_cert", - description: "For API < v2.0.1: SSL certificate contents (this is a not a path)", - return_type: String( - TypeInfo { - name: "ssl_cert", - is_optional: false, - is_list: false, - description: Some( - "For API < v2.0.1: SSL certificate contents (this is a not a path)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_https_key_path", - description: "For API ≥ v2.0.1: Path to SSL keyfile", - return_type: String( - TypeInfo { - name: "web_ui_https_key_path", - is_optional: false, - is_list: false, - description: Some( - "For API ≥ v2.0.1: Path to SSL keyfile", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_https_cert_path", - description: "For API ≥ v2.0.1: Path to SSL certificate", - return_type: String( - TypeInfo { - name: "web_ui_https_cert_path", - is_optional: false, - is_list: false, - description: Some( - "For API ≥ v2.0.1: Path to SSL certificate", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dyndns_enabled", - description: "True if server DNS should be updated dynamically", - return_type: Bool( - TypeInfo { - name: "dyndns_enabled", - is_optional: false, - is_list: false, - description: Some( - "True if server DNS should be updated dynamically", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dyndns_service", - description: "See list of possible values here below", - return_type: Number( - TypeInfo { - name: "dyndns_service", - is_optional: false, - is_list: false, - description: Some( - "See list of possible values here below", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "0", - description: "Use DyDNS", - }, - TypeDescriptions { - value: "1", - description: "Use NOIP", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "dyndns_username", - description: "Username for DDNS service", - return_type: String( - TypeInfo { - name: "dyndns_username", - is_optional: false, - is_list: false, - description: Some( - "Username for DDNS service", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dyndns_password", - description: "Password for DDNS service", - return_type: String( - TypeInfo { - name: "dyndns_password", - is_optional: false, - is_list: false, - description: Some( - "Password for DDNS service", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dyndns_domain", - description: "Your DDNS domain name", - return_type: String( - TypeInfo { - name: "dyndns_domain", - is_optional: false, - is_list: false, - description: Some( - "Your DDNS domain name", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "rss_refresh_interval", - description: "RSS refresh interval", - return_type: Number( - TypeInfo { - name: "rss_refresh_interval", - is_optional: false, - is_list: false, - description: Some( - "RSS refresh interval", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "rss_max_articles_per_feed", - description: "Max stored articles per RSS feed", - return_type: Number( - TypeInfo { - name: "rss_max_articles_per_feed", - is_optional: false, - is_list: false, - description: Some( - "Max stored articles per RSS feed", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "rss_processing_enabled", - description: "Enable processing of RSS feeds", - return_type: Bool( - TypeInfo { - name: "rss_processing_enabled", - is_optional: false, - is_list: false, - description: Some( - "Enable processing of RSS feeds", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "rss_auto_downloading_enabled", - description: "Enable auto-downloading of torrents from the RSS feeds", - return_type: Bool( - TypeInfo { - name: "rss_auto_downloading_enabled", - is_optional: false, - is_list: false, - description: Some( - "Enable auto-downloading of torrents from the RSS feeds", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "rss_download_repack_proper_episodes", - description: "For API ≥ v2.5.1: Enable downloading of repack/proper Episodes", - return_type: Bool( - TypeInfo { - name: "rss_download_repack_proper_episodes", - is_optional: false, - is_list: false, - description: Some( - "For API ≥ v2.5.1: Enable downloading of repack/proper Episodes", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "rss_smart_episode_filters", - description: "For API ≥ v2.5.1: List of RSS Smart Episode Filters", - return_type: String( - TypeInfo { - name: "rss_smart_episode_filters", - is_optional: false, - is_list: false, - description: Some( - "For API ≥ v2.5.1: List of RSS Smart Episode Filters", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "add_trackers_enabled", - description: "Enable automatic adding of trackers to new torrents", - return_type: Bool( - TypeInfo { - name: "add_trackers_enabled", - is_optional: false, - is_list: false, - description: Some( - "Enable automatic adding of trackers to new torrents", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "add_trackers", - description: "List of trackers to add to new torrent", - return_type: String( - TypeInfo { - name: "add_trackers", - is_optional: false, - is_list: false, - description: Some( - "List of trackers to add to new torrent", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_use_custom_http_headers_enabled", - description: "For API ≥ v2.5.1: Enable custom http headers", - return_type: Bool( - TypeInfo { - name: "web_ui_use_custom_http_headers_enabled", - is_optional: false, - is_list: false, - description: Some( - "For API ≥ v2.5.1: Enable custom http headers", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "web_ui_custom_http_headers", - description: "For API ≥ v2.5.1: List of custom http headers", - return_type: String( - TypeInfo { - name: "web_ui_custom_http_headers", - is_optional: false, - is_list: false, - description: Some( - "For API ≥ v2.5.1: List of custom http headers", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_seeding_time_enabled", - description: "True enables max seeding time", - return_type: Bool( - TypeInfo { - name: "max_seeding_time_enabled", - is_optional: false, - is_list: false, - description: Some( - "True enables max seeding time", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_seeding_time", - description: "Number of minutes to seed a torrent", - return_type: Number( - TypeInfo { - name: "max_seeding_time", - is_optional: false, - is_list: false, - description: Some( - "Number of minutes to seed a torrent", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "announce_ip", - description: "TODO", - return_type: String( - TypeInfo { - name: "announce_ip", - is_optional: false, - is_list: false, - description: Some( - "TODO", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "announce_to_all_tiers", - description: "True always announce to all tiers", - return_type: Bool( - TypeInfo { - name: "announce_to_all_tiers", - is_optional: false, - is_list: false, - description: Some( - "True always announce to all tiers", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "announce_to_all_trackers", - description: "True always announce to all trackers in a tier", - return_type: Bool( - TypeInfo { - name: "announce_to_all_trackers", - is_optional: false, - is_list: false, - description: Some( - "True always announce to all trackers in a tier", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "async_io_threads", - description: "Number of asynchronous I/O threads", - return_type: Number( - TypeInfo { - name: "async_io_threads", - is_optional: false, - is_list: false, - description: Some( - "Number of asynchronous I/O threads", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "banned_IPs", - description: "List of banned IPs", - return_type: String( - TypeInfo { - name: "banned_IPs", - is_optional: false, - is_list: false, - description: Some( - "List of banned IPs", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "checking_memory_use", - description: "Outstanding memory when checking torrents in MiB", - return_type: Number( - TypeInfo { - name: "checking_memory_use", - is_optional: false, - is_list: false, - description: Some( - "Outstanding memory when checking torrents in MiB", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "current_interface_address", - description: "IP Address to bind to. Empty String means All addresses", - return_type: String( - TypeInfo { - name: "current_interface_address", - is_optional: false, - is_list: false, - description: Some( - "IP Address to bind to. Empty String means All addresses", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "current_network_interface", - description: "Network Interface used", - return_type: String( - TypeInfo { - name: "current_network_interface", - is_optional: false, - is_list: false, - description: Some( - "Network Interface used", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "disk_cache", - description: "Disk cache used in MiB", - return_type: Number( - TypeInfo { - name: "disk_cache", - is_optional: false, - is_list: false, - description: Some( - "Disk cache used in MiB", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "disk_cache_ttl", - description: "Disk cache expiry interval in seconds", - return_type: Number( - TypeInfo { - name: "disk_cache_ttl", - is_optional: false, - is_list: false, - description: Some( - "Disk cache expiry interval in seconds", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "embedded_tracker_port", - description: "Port used for embedded tracker", - return_type: Number( - TypeInfo { - name: "embedded_tracker_port", - is_optional: false, - is_list: false, - description: Some( - "Port used for embedded tracker", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "enable_coalesce_read_write", - description: "True enables coalesce reads & writes", - return_type: Bool( - TypeInfo { - name: "enable_coalesce_read_write", - is_optional: false, - is_list: false, - description: Some( - "True enables coalesce reads & writes", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "enable_embedded_tracker", - description: "True enables embedded tracker", - return_type: Bool( - TypeInfo { - name: "enable_embedded_tracker", - is_optional: false, - is_list: false, - description: Some( - "True enables embedded tracker", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "enable_multi_connections_from_same_ip", - description: "True allows multiple connections from the same IP address", - return_type: Bool( - TypeInfo { - name: "enable_multi_connections_from_same_ip", - is_optional: false, - is_list: false, - description: Some( - "True allows multiple connections from the same IP address", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "enable_os_cache", - description: "True enables os cache", - return_type: Bool( - TypeInfo { - name: "enable_os_cache", - is_optional: false, - is_list: false, - description: Some( - "True enables os cache", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "enable_upload_suggestions", - description: "True enables sending of upload piece suggestions", - return_type: Bool( - TypeInfo { - name: "enable_upload_suggestions", - is_optional: false, - is_list: false, - description: Some( - "True enables sending of upload piece suggestions", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "file_pool_size", - description: "File pool size", - return_type: Number( - TypeInfo { - name: "file_pool_size", - is_optional: false, - is_list: false, - description: Some( - "File pool size", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "outgoing_ports_max", - description: "Maximal outgoing port (0: Disabled)", - return_type: Number( - TypeInfo { - name: "outgoing_ports_max", - is_optional: false, - is_list: false, - description: Some( - "Maximal outgoing port (0: Disabled)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "outgoing_ports_min", - description: "Minimal outgoing port (0: Disabled)", - return_type: Number( - TypeInfo { - name: "outgoing_ports_min", - is_optional: false, - is_list: false, - description: Some( - "Minimal outgoing port (0: Disabled)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "recheck_completed_torrents", - description: "True rechecks torrents on completion", - return_type: Bool( - TypeInfo { - name: "recheck_completed_torrents", - is_optional: false, - is_list: false, - description: Some( - "True rechecks torrents on completion", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "resolve_peer_countries", - description: "True resolves peer countries", - return_type: Bool( - TypeInfo { - name: "resolve_peer_countries", - is_optional: false, - is_list: false, - description: Some( - "True resolves peer countries", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "save_resume_data_interval", - description: "Save resume data interval in min", - return_type: Number( - TypeInfo { - name: "save_resume_data_interval", - is_optional: false, - is_list: false, - description: Some( - "Save resume data interval in min", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "send_buffer_low_watermark", - description: "Send buffer low watermark in KiB", - return_type: Number( - TypeInfo { - name: "send_buffer_low_watermark", - is_optional: false, - is_list: false, - description: Some( - "Send buffer low watermark in KiB", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "send_buffer_watermark", - description: "Send buffer watermark in KiB", - return_type: Number( - TypeInfo { - name: "send_buffer_watermark", - is_optional: false, - is_list: false, - description: Some( - "Send buffer watermark in KiB", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "send_buffer_watermark_factor", - description: "Send buffer watermark factor in percent", - return_type: Number( - TypeInfo { - name: "send_buffer_watermark_factor", - is_optional: false, - is_list: false, - description: Some( - "Send buffer watermark factor in percent", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "socket_backlog_size", - description: "Socket backlog size", - return_type: Number( - TypeInfo { - name: "socket_backlog_size", - is_optional: false, - is_list: false, - description: Some( - "Socket backlog size", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "upload_choking_algorithm", - description: "Upload choking algorithm used (see list of possible values below)", - return_type: Number( - TypeInfo { - name: "upload_choking_algorithm", - is_optional: false, - is_list: false, - description: Some( - "Upload choking algorithm used (see list of possible values below)", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "0", - description: "Round-robin", - }, - TypeDescriptions { - value: "1", - description: "Fastest upload", - }, - TypeDescriptions { - value: "2", - description: "Anti-leech", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "upload_slots_behavior", - description: "Upload slots behavior used (see list of possible values below)", - return_type: Number( - TypeInfo { - name: "upload_slots_behavior", - is_optional: false, - is_list: false, - description: Some( - "Upload slots behavior used (see list of possible values below)", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "0", - description: "Fixed slots", - }, - TypeDescriptions { - value: "1", - description: "Upload rate based", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "upnp_lease_duration", - description: "UPnP lease duration (0: Permanent lease)", - return_type: Number( - TypeInfo { - name: "upnp_lease_duration", - is_optional: false, - is_list: false, - description: Some( - "UPnP lease duration (0: Permanent lease)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "utp_tcp_mixed_mode", - description: "μTP-TCP mixed mode algorithm (see list of possible values below)", - return_type: Number( - TypeInfo { - name: "utp_tcp_mixed_mode", - is_optional: false, - is_list: false, - description: Some( - "μTP-TCP mixed mode algorithm (see list of possible values below)", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "0", - description: "Prefer TCP", - }, - TypeDescriptions { - value: "1", - description: "Peer proportional", - }, - ], - }, - ), - }, - ), - }, - ], - }, - ), url: "preferences", + types: CompositeTypes { + composite_types: [ + Enum( + Enum { + name: "BittorrentProtocol", + values: [ + EnumValue { + description: Some( + "TCP and μTP", + ), + value: "TCPAndμTP", + original_value: "0", + }, + EnumValue { + description: Some( + "TCP", + ), + value: "TCP", + original_value: "1", + }, + EnumValue { + description: Some( + "μTP", + ), + value: "μTP", + original_value: "2", + }, + ], + }, + ), + Enum( + Enum { + name: "DyndnsService", + values: [ + EnumValue { + description: Some( + "Use DyDNS", + ), + value: "UseDyDNS", + original_value: "0", + }, + EnumValue { + description: Some( + "Use NOIP", + ), + value: "UseNOIP", + original_value: "1", + }, + ], + }, + ), + Enum( + Enum { + name: "Encryption", + values: [ + EnumValue { + description: Some( + "Prefer encryption", + ), + value: "PreferEncryption", + original_value: "0", + }, + EnumValue { + description: Some( + "Force encryption on", + ), + value: "ForceEncryptionOn", + original_value: "1", + }, + EnumValue { + description: Some( + "Force encryption off", + ), + value: "ForceEncryptionOff", + original_value: "2", + }, + ], + }, + ), + Enum( + Enum { + name: "MaxRatioAct", + values: [ + EnumValue { + description: Some( + "Pause torrent", + ), + value: "PauseTorrent", + original_value: "0", + }, + EnumValue { + description: Some( + "Remove torrent", + ), + value: "RemoveTorrent", + original_value: "1", + }, + ], + }, + ), + Enum( + Enum { + name: "ProxyType", + values: [ + EnumValue { + description: Some( + "Proxy is disabled", + ), + value: "ProxyIsDisabled", + original_value: "-1", + }, + EnumValue { + description: Some( + "HTTP proxy without authentication", + ), + value: "HTTPProxyWithoutAuthentication", + original_value: "1", + }, + EnumValue { + description: Some( + "SOCKS5 proxy without authentication", + ), + value: "SOCKS5ProxyWithoutAuthentication", + original_value: "2", + }, + EnumValue { + description: Some( + "HTTP proxy with authentication", + ), + value: "HTTPProxyWithAuthentication", + original_value: "3", + }, + EnumValue { + description: Some( + "SOCKS5 proxy with authentication", + ), + value: "SOCKS5ProxyWithAuthentication", + original_value: "4", + }, + EnumValue { + description: Some( + "SOCKS4 proxy without authentication", + ), + value: "SOCKS4ProxyWithoutAuthentication", + original_value: "5", + }, + ], + }, + ), + Enum( + Enum { + name: "ScanDirs", + values: [ + EnumValue { + description: Some( + "Download to the monitored folder", + ), + value: "DownloadToTheMonitoredFolder", + original_value: "0", + }, + EnumValue { + description: Some( + "Download to the default save path", + ), + value: "DownloadToTheDefaultSavePath", + original_value: "1", + }, + EnumValue { + description: Some( + "Download to this path", + ), + value: "\"/path/to/download/to\"", + original_value: "\"/path/to/download/to\"", + }, + ], + }, + ), + Enum( + Enum { + name: "SchedulerDays", + values: [ + EnumValue { + description: Some( + "Every day", + ), + value: "EveryDay", + original_value: "0", + }, + EnumValue { + description: Some( + "Every weekday", + ), + value: "EveryWeekday", + original_value: "1", + }, + EnumValue { + description: Some( + "Every weekend", + ), + value: "EveryWeekend", + original_value: "2", + }, + EnumValue { + description: Some( + "Every Monday", + ), + value: "EveryMonday", + original_value: "3", + }, + EnumValue { + description: Some( + "Every Tuesday", + ), + value: "EveryTuesday", + original_value: "4", + }, + EnumValue { + description: Some( + "Every Wednesday", + ), + value: "EveryWednesday", + original_value: "5", + }, + EnumValue { + description: Some( + "Every Thursday", + ), + value: "EveryThursday", + original_value: "6", + }, + EnumValue { + description: Some( + "Every Friday", + ), + value: "EveryFriday", + original_value: "7", + }, + EnumValue { + description: Some( + "Every Saturday", + ), + value: "EverySaturday", + original_value: "8", + }, + EnumValue { + description: Some( + "Every Sunday", + ), + value: "EverySunday", + original_value: "9", + }, + ], + }, + ), + Enum( + Enum { + name: "UploadChokingAlgorithm", + values: [ + EnumValue { + description: Some( + "Round-robin", + ), + value: "RoundRobin", + original_value: "0", + }, + EnumValue { + description: Some( + "Fastest upload", + ), + value: "FastestUpload", + original_value: "1", + }, + EnumValue { + description: Some( + "Anti-leech", + ), + value: "AntiLeech", + original_value: "2", + }, + ], + }, + ), + Enum( + Enum { + name: "UploadSlotsBehavior", + values: [ + EnumValue { + description: Some( + "Fixed slots", + ), + value: "FixedSlots", + original_value: "0", + }, + EnumValue { + description: Some( + "Upload rate based", + ), + value: "UploadRateBased", + original_value: "1", + }, + ], + }, + ), + Enum( + Enum { + name: "UtpTcpMixedMode", + values: [ + EnumValue { + description: Some( + "Prefer TCP", + ), + value: "PreferTCP", + original_value: "0", + }, + EnumValue { + description: Some( + "Peer proportional", + ), + value: "PeerProportional", + original_value: "1", + }, + ], + }, + ), + ], + }, }, ApiMethod { name: "setPreferences", description: Some( "1. There is no need to pass all possible preferences' `token:value` pairs if you only want to change one option\n 1. Paths in `scan_dirs` must exist, otherwise this option will have no effect\n 1. String values must be quoted; integer and boolean values must never be quoted\n\nFor a list of possible preference options see [Get application preferences](#get-application-preferences)", ), - parameters: None, - return_type: None, url: "setPreferences", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "defaultSavePath", description: Some( "The response is a string with the default save path, e.g. `C:/Users/Dayman/Downloads`.", ), - parameters: None, - return_type: None, url: "defaultSavePath", + types: CompositeTypes { + composite_types: [], + }, }, ], description: Some( @@ -2601,162 +525,100 @@ description: Some( "The response is a JSON array in which each element is an entry of the log.\n\nEach element of the array has the following properties:\n\n\nExample:\n\n```JSON\n[\n {\n \"id\":0,\n \"message\":\"qBittorrent v3.4.0 started\",\n \"timestamp\":1507969127860,\n \"type\":1\n },\n {\n \"id\":1,\n \"message\":\"qBittorrent is trying to listen on any interface port: 19036\",\n \"timestamp\":1507969127869,\n \"type\":2\n },\n {\n \"id\":2,\n \"message\":\"Peer ID: -qB3400-\",\n \"timestamp\":1507969127870,\n \"type\":1\n },\n {\n \"id\":3,\n \"message\":\"HTTP User-Agent is 'qBittorrent/3.4.0'\",\n \"timestamp\":1507969127870,\n \"type\":1\n },\n {\n \"id\":4,\n \"message\":\"DHT support [ON]\",\n \"timestamp\":1507969127871,\n \"type\":2\n },\n {\n \"id\":5,\n \"message\":\"Local Peer Discovery support [ON]\",\n \"timestamp\":1507969127871,\n \"type\":2\n },\n {\n \"id\":6,\n \"message\":\"PeX support [ON]\",\n \"timestamp\":1507969127871,\n \"type\":2\n },\n {\n \"id\":7,\n \"message\":\"Anonymous mode [OFF]\",\n \"timestamp\":1507969127871,\n \"type\":2\n },\n {\n \"id\":8,\n \"message\":\"Encryption support [ON]\",\n \"timestamp\":1507969127871,\n \"type\":2\n },\n {\n \"id\":9,\n \"message\":\"Embedded Tracker [OFF]\",\n \"timestamp\":1507969127871,\n \"type\":2\n },\n {\n \"id\":10,\n \"message\":\"UPnP / NAT-PMP support [ON]\",\n \"timestamp\":1507969127873,\n \"type\":2\n },\n {\n \"id\":11,\n \"message\":\"Web UI: Now listening on port 8080\",\n \"timestamp\":1507969127883,\n \"type\":1\n },\n {\n \"id\":12,\n \"message\":\"Options were saved successfully.\",\n \"timestamp\":1507969128055,\n \"type\":1\n },\n {\n \"id\":13,\n \"message\":\"qBittorrent is successfully listening on interface :: port: TCP/19036\",\n \"timestamp\":1507969128270,\n \"type\":2\n },\n {\n \"id\":14,\n \"message\":\"qBittorrent is successfully listening on interface 0.0.0.0 port: TCP/19036\",\n \"timestamp\":1507969128271,\n \"type\":2\n },\n {\n \"id\":15,\n \"message\":\"qBittorrent is successfully listening on interface 0.0.0.0 port: UDP/19036\",\n \"timestamp\":1507969128272,\n \"type\":2\n }\n]\n```", ), - parameters: Some( - ApiParameters { - mandatory: [], - optional: [ - Bool( - TypeInfo { - name: "normal", - is_optional: true, - is_list: false, - description: Some( - "Include normal messages (default: true)", - ), - type_description: None, - }, - ), - Bool( - TypeInfo { - name: "info", - is_optional: true, - is_list: false, - description: Some( - "Include info messages (default: true)", - ), - type_description: None, - }, - ), - Bool( - TypeInfo { - name: "warning", - is_optional: true, - is_list: false, - description: Some( - "Include warning messages (default: true)", - ), - type_description: None, - }, - ), - Bool( - TypeInfo { - name: "critical", - is_optional: true, - is_list: false, - description: Some( - "Include critical messages (default: true)", - ), - type_description: None, - }, - ), - Number( - TypeInfo { - name: "last_known_id", - is_optional: true, - is_list: false, - description: Some( - "Exclude messages with \"message id\" <= last_known_id (default: -1)", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: Some( - ReturnType { - is_list: true, - parameters: [ - ReturnTypeParameter { - name: "id", - description: "ID of the message", - return_type: Number( - TypeInfo { - name: "id", - is_optional: false, - is_list: false, - description: Some( - "ID of the message", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "message", - description: "Text of the message", - return_type: String( - TypeInfo { - name: "message", - is_optional: false, - is_list: false, - description: Some( - "Text of the message", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "timestamp", - description: "Milliseconds since epoch", - return_type: Number( - TypeInfo { - name: "timestamp", - is_optional: false, - is_list: false, - description: Some( - "Milliseconds since epoch", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "type", - description: "Type of the message: Log::NORMAL: 1, Log::INFO: 2, Log::WARNING: 4, Log::CRITICAL: 8", - return_type: Number( - TypeInfo { - name: "type", - is_optional: false, - is_list: false, - description: Some( - "Type of the message: Log::NORMAL: 1, Log::INFO: 2, Log::WARNING: 4, Log::CRITICAL: 8", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "main", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Bool( + TypeInfo { + name: "normal", + is_optional: true, + is_list: false, + description: Some( + "Include normal messages (default: true)", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "info", + is_optional: true, + is_list: false, + description: Some( + "Include info messages (default: true)", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "warning", + is_optional: true, + is_list: false, + description: Some( + "Include warning messages (default: true)", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "critical", + is_optional: true, + is_list: false, + description: Some( + "Include critical messages (default: true)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "last_known_id", + is_optional: true, + is_list: false, + description: Some( + "Exclude messages with \"message id\" <= last_known_id (default: -1)", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "peers", description: Some( "The response a JSON array. Each element of the array of objects (each object is the information relative to a peer) containing the following fields", ), - parameters: Some( - ApiParameters { - mandatory: [], - optional: [ - Number( - TypeInfo { - name: "last_known_id", - is_optional: true, - is_list: false, - description: Some( - "Exclude messages with \"message id\" <= last_known_id (default: -1)", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: None, url: "peers", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "last_known_id", + is_optional: true, + is_list: false, + description: Some( + "Exclude messages with \"message id\" <= last_known_id (default: -1)", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ], description: Some( @@ -2772,204 +634,181 @@ description: Some( "The response is a JSON object with the following possible fields\n\n\nExample:\n\n```JSON\n{\n \"rid\":15,\n \"torrents\":\n {\n \"8c212779b4abde7c6bc608063a0d008b7e40ce32\":\n {\n \"state\":\"pausedUP\"\n }\n }\n}\n```", ), - parameters: Some( - ApiParameters { - mandatory: [ - Number( - TypeInfo { - name: "rid", - is_optional: false, - is_list: false, - description: Some( - "Response ID. If not provided, rid=0 will be assumed. If the given rid is different from the one of last server reply, full_update will be true (see the server reply details for more info)", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: Some( - ReturnType { - is_list: false, - parameters: [ - ReturnTypeParameter { - name: "rid", - description: "Response ID", - return_type: Number( - TypeInfo { - name: "rid", - is_optional: false, - is_list: false, - description: Some( - "Response ID", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "full_update", - description: "Whether the response contains all the data or partial data", - return_type: Bool( - TypeInfo { - name: "full_update", - is_optional: false, - is_list: false, - description: Some( - "Whether the response contains all the data or partial data", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "torrents", - description: "Property: torrent hash, value: same as [torrent list](#get-torrent-list)", - return_type: Object( - TypeInfo { - name: "torrents", - is_optional: false, - is_list: false, - description: Some( - "Property: torrent hash, value: same as [torrent list](#get-torrent-list)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "torrents_removed", - description: "List of hashes of torrents removed since last request", - return_type: StringArray( - TypeInfo { - name: "torrents_removed", - is_optional: false, - is_list: false, - description: Some( - "List of hashes of torrents removed since last request", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "categories", - description: "Info for categories added since last request", - return_type: Object( - TypeInfo { - name: "categories", - is_optional: false, - is_list: false, - description: Some( - "Info for categories added since last request", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "categories_removed", - description: "List of categories removed since last request", - return_type: StringArray( - TypeInfo { - name: "categories_removed", - is_optional: false, - is_list: false, - description: Some( - "List of categories removed since last request", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "tags", - description: "List of tags added since last request", - return_type: StringArray( - TypeInfo { - name: "tags", - is_optional: false, - is_list: false, - description: Some( - "List of tags added since last request", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "tags_removed", - description: "List of tags removed since last request", - return_type: StringArray( - TypeInfo { - name: "tags_removed", - is_optional: false, - is_list: false, - description: Some( - "List of tags removed since last request", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "server_state", - description: "Global transfer info", - return_type: Object( - TypeInfo { - name: "server_state", - is_optional: false, - is_list: false, - description: Some( - "Global transfer info", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "maindata", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "rid", + is_optional: false, + is_list: false, + description: Some( + "Response ID. If not provided, rid=0 will be assumed. If the given rid is different from the one of last server reply, full_update will be true (see the server reply details for more info)", + ), + type_description: None, + }, + ), + ], + }, + ), + Response( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "rid", + is_optional: false, + is_list: false, + description: Some( + "Response ID", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "full_update", + is_optional: false, + is_list: false, + description: Some( + "Whether the response contains all the data or partial data", + ), + type_description: None, + }, + ), + Object( + Object { + type_info: TypeInfo { + name: "torrents", + is_optional: false, + is_list: false, + description: Some( + "Property: torrent hash, value: same as [torrent list](#get-torrent-list)", + ), + type_description: None, + }, + ref_type: "Object", + }, + ), + StringArray( + TypeInfo { + name: "torrents_removed", + is_optional: false, + is_list: false, + description: Some( + "List of hashes of torrents removed since last request", + ), + type_description: None, + }, + ), + Object( + Object { + type_info: TypeInfo { + name: "categories", + is_optional: false, + is_list: false, + description: Some( + "Info for categories added since last request", + ), + type_description: None, + }, + ref_type: "Object", + }, + ), + StringArray( + TypeInfo { + name: "categories_removed", + is_optional: false, + is_list: false, + description: Some( + "List of categories removed since last request", + ), + type_description: None, + }, + ), + StringArray( + TypeInfo { + name: "tags", + is_optional: false, + is_list: false, + description: Some( + "List of tags added since last request", + ), + type_description: None, + }, + ), + StringArray( + TypeInfo { + name: "tags_removed", + is_optional: false, + is_list: false, + description: Some( + "List of tags removed since last request", + ), + type_description: None, + }, + ), + Object( + Object { + type_info: TypeInfo { + name: "server_state", + is_optional: false, + is_list: false, + description: Some( + "Global transfer info", + ), + type_description: None, + }, + ref_type: "Object", + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "torrentPeers", description: Some( "The response is TODO", ), - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "Torrent hash", - ), - type_description: None, - }, - ), - Number( - TypeInfo { - name: "rid", - is_optional: false, - is_list: false, - description: Some( - "Response ID. If not provided, rid=0 will be assumed. If the given rid is different from the one of last server reply, full_update will be true (see the server reply details for more info)", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "torrentPeers", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "Torrent hash", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "rid", + is_optional: false, + is_list: false, + description: Some( + "Response ID. If not provided, rid=0 will be assumed. If the given rid is different from the one of last server reply, full_update will be true (see the server reply details for more info)", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ], description: Some( @@ -2985,241 +824,221 @@ description: Some( "The response is a JSON object with the following fields\n\n\nIn addition to the above in partial data requests (see [Get partial data](#get-partial-data) for more info):\n\n\nPossible values of `connection_status`:\n\nValue |\n\nExample:\n\n```JSON\n{\n \"connection_status\":\"connected\",\n \"dht_nodes\":386,\n \"dl_info_data\":681521119,\n \"dl_info_speed\":0,\n \"dl_rate_limit\":0,\n \"up_info_data\":10747904,\n \"up_info_speed\":0,\n \"up_rate_limit\":1048576\n}\n```", ), - parameters: None, - return_type: Some( - ReturnType { - is_list: false, - parameters: [ - ReturnTypeParameter { - name: "dl_info_speed", - description: "Global download rate (bytes/s)", - return_type: Number( - TypeInfo { - name: "dl_info_speed", - is_optional: false, - is_list: false, - description: Some( - "Global download rate (bytes/s)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dl_info_data", - description: "Data downloaded this session (bytes)", - return_type: Number( - TypeInfo { - name: "dl_info_data", - is_optional: false, - is_list: false, - description: Some( - "Data downloaded this session (bytes)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "up_info_speed", - description: "Global upload rate (bytes/s)", - return_type: Number( - TypeInfo { - name: "up_info_speed", - is_optional: false, - is_list: false, - description: Some( - "Global upload rate (bytes/s)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "up_info_data", - description: "Data uploaded this session (bytes)", - return_type: Number( - TypeInfo { - name: "up_info_data", - is_optional: false, - is_list: false, - description: Some( - "Data uploaded this session (bytes)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dl_rate_limit", - description: "Download rate limit (bytes/s)", - return_type: Number( - TypeInfo { - name: "dl_rate_limit", - is_optional: false, - is_list: false, - description: Some( - "Download rate limit (bytes/s)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "up_rate_limit", - description: "Upload rate limit (bytes/s)", - return_type: Number( - TypeInfo { - name: "up_rate_limit", - is_optional: false, - is_list: false, - description: Some( - "Upload rate limit (bytes/s)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dht_nodes", - description: "DHT nodes connected to", - return_type: Number( - TypeInfo { - name: "dht_nodes", - is_optional: false, - is_list: false, - description: Some( - "DHT nodes connected to", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "connection_status", - description: "Connection status. See possible values here below", - return_type: String( - TypeInfo { - name: "connection_status", - is_optional: false, - is_list: false, - description: Some( - "Connection status. See possible values here below", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "info", + types: CompositeTypes { + composite_types: [ + Response( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "dl_info_speed", + is_optional: false, + is_list: false, + description: Some( + "Global download rate (bytes/s)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "dl_info_data", + is_optional: false, + is_list: false, + description: Some( + "Data downloaded this session (bytes)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "up_info_speed", + is_optional: false, + is_list: false, + description: Some( + "Global upload rate (bytes/s)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "up_info_data", + is_optional: false, + is_list: false, + description: Some( + "Data uploaded this session (bytes)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "dl_rate_limit", + is_optional: false, + is_list: false, + description: Some( + "Download rate limit (bytes/s)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "up_rate_limit", + is_optional: false, + is_list: false, + description: Some( + "Upload rate limit (bytes/s)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "dht_nodes", + is_optional: false, + is_list: false, + description: Some( + "DHT nodes connected to", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "connection_status", + is_optional: false, + is_list: false, + description: Some( + "Connection status. See possible values here below", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "speedLimitsMode", description: Some( "The response is `1` if alternative speed limits are enabled, `0` otherwise.", ), - parameters: None, - return_type: None, url: "speedLimitsMode", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "toggleSpeedLimitsMode", description: None, - parameters: None, - return_type: None, url: "toggleSpeedLimitsMode", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "downloadLimit", description: Some( "The response is the value of current global download speed limit in bytes/second; this value will be zero if no limit is applied.", ), - parameters: None, - return_type: None, url: "downloadLimit", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "setDownloadLimit", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - Number( - TypeInfo { - name: "limit", - is_optional: false, - is_list: false, - description: Some( - "The global download speed limit to set in bytes/second", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "setDownloadLimit", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "limit", + is_optional: false, + is_list: false, + description: Some( + "The global download speed limit to set in bytes/second", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "uploadLimit", description: Some( "The response is the value of current global upload speed limit in bytes/second; this value will be zero if no limit is applied.", ), - parameters: None, - return_type: None, url: "uploadLimit", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "setUploadLimit", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - Number( - TypeInfo { - name: "limit", - is_optional: false, - is_list: false, - description: Some( - "The global upload speed limit to set in bytes/second", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "setUploadLimit", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "limit", + is_optional: false, + is_list: false, + description: Some( + "The global upload speed limit to set in bytes/second", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "banPeers", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "peers", - is_optional: false, - is_list: false, - description: Some( - "The peer to ban, or multiple peers separated by a pipe \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "banPeers", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "peers", + is_optional: false, + is_list: false, + description: Some( + "The peer to ban, or multiple peers separated by a pipe \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ], description: Some( @@ -3235,2053 +1054,2042 @@ description: Some( "The response is a JSON array with the following fields\n\n\nPossible values of `state`:\n\n\nExample:\n\n```JSON\n[\n {\n \"dlspeed\":9681262,\n \"eta\":87,\n \"f_l_piece_prio\":false,\n \"force_start\":false,\n \"hash\":\"8c212779b4abde7c6bc608063a0d008b7e40ce32\",\n \"category\":\"\",\n \"tags\": \"\",\n \"name\":\"debian-8.1.0-amd64-CD-1.iso\",\n \"num_complete\":-1,\n \"num_incomplete\":-1,\n \"num_leechs\":2,\n \"num_seeds\":54,\n \"priority\":1,\n \"progress\":0.16108787059783936,\n \"ratio\":0,\n \"seq_dl\":false,\n \"size\":657457152,\n \"state\":\"downloading\",\n \"super_seeding\":false,\n \"upspeed\":0\n },\n {\n another_torrent_info\n }\n]\n```", ), - parameters: Some( - ApiParameters { - mandatory: [], - optional: [ - String( - TypeInfo { - name: "filter", - is_optional: true, - is_list: false, - description: Some( - "Filter torrent list by state. Allowed state filters: all, downloading, seeding, completed, paused, active, inactive, resumed, stalled, stalled_uploading, stalled_downloading, errored", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "category", - is_optional: true, - is_list: false, - description: Some( - "Get torrents with the given category (empty string means \"without category\"; no \"category\" parameter means \"any category\" <- broken until [#11748](https://github.com/qbittorrent/qBittorrent/issues/11748) is resolved). Remember to URL-encode the category name. For example, My category becomes My%20category", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "tag", - is_optional: true, - is_list: false, - description: Some( - "Get torrents with the given tag (empty string means \"without tag\"; no \"tag\" parameter means \"any tag\". Remember to URL-encode the category name. For example, My tag becomes My%20tag", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "sort", - is_optional: true, - is_list: false, - description: Some( - "Sort torrents by given key. They can be sorted using any field of the response's JSON array (which are documented below) as the sort key.", - ), - type_description: None, - }, - ), - Bool( - TypeInfo { - name: "reverse", - is_optional: true, - is_list: false, - description: Some( - "Enable reverse sorting. Defaults to false", - ), - type_description: None, - }, - ), - Number( - TypeInfo { - name: "limit", - is_optional: true, - is_list: false, - description: Some( - "Limit the number of torrents returned", - ), - type_description: None, - }, - ), - Number( - TypeInfo { - name: "offset", - is_optional: true, - is_list: false, - description: Some( - "Set offset (if less than 0, offset from end)", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "hashes", - is_optional: true, - is_list: false, - description: Some( - "Filter by hashes. Can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: Some( - ReturnType { - is_list: true, - parameters: [ - ReturnTypeParameter { - name: "added_on", - description: "Time (Unix Epoch) when the torrent was added to the client", - return_type: Number( - TypeInfo { - name: "added_on", - is_optional: false, - is_list: false, - description: Some( - "Time (Unix Epoch) when the torrent was added to the client", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "amount_left", - description: "Amount of data left to download (bytes)", - return_type: Number( - TypeInfo { - name: "amount_left", - is_optional: false, - is_list: false, - description: Some( - "Amount of data left to download (bytes)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "auto_tmm", - description: "Whether this torrent is managed by Automatic Torrent Management", - return_type: Bool( - TypeInfo { - name: "auto_tmm", - is_optional: false, - is_list: false, - description: Some( - "Whether this torrent is managed by Automatic Torrent Management", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "availability", - description: "Percentage of file pieces currently available", - return_type: Float( - TypeInfo { - name: "availability", - is_optional: false, - is_list: false, - description: Some( - "Percentage of file pieces currently available", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "category", - description: "Category of the torrent", - return_type: String( - TypeInfo { - name: "category", - is_optional: false, - is_list: false, - description: Some( - "Category of the torrent", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "completed", - description: "Amount of transfer data completed (bytes)", - return_type: Number( - TypeInfo { - name: "completed", - is_optional: false, - is_list: false, - description: Some( - "Amount of transfer data completed (bytes)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "completion_on", - description: "Time (Unix Epoch) when the torrent completed", - return_type: Number( - TypeInfo { - name: "completion_on", - is_optional: false, - is_list: false, - description: Some( - "Time (Unix Epoch) when the torrent completed", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "content_path", - description: "Absolute path of torrent content (root path for multifile torrents, absolute file path for singlefile torrents)", - return_type: String( - TypeInfo { - name: "content_path", - is_optional: false, - is_list: false, - description: Some( - "Absolute path of torrent content (root path for multifile torrents, absolute file path for singlefile torrents)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dl_limit", - description: "Torrent download speed limit (bytes/s). -1 if ulimited.", - return_type: Number( - TypeInfo { - name: "dl_limit", - is_optional: false, - is_list: false, - description: Some( - "Torrent download speed limit (bytes/s). -1 if ulimited.", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "dlspeed", - description: "Torrent download speed (bytes/s)", - return_type: Number( - TypeInfo { - name: "dlspeed", - is_optional: false, - is_list: false, - description: Some( - "Torrent download speed (bytes/s)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "downloaded", - description: "Amount of data downloaded", - return_type: Number( - TypeInfo { - name: "downloaded", - is_optional: false, - is_list: false, - description: Some( - "Amount of data downloaded", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "downloaded_session", - description: "Amount of data downloaded this session", - return_type: Number( - TypeInfo { - name: "downloaded_session", - is_optional: false, - is_list: false, - description: Some( - "Amount of data downloaded this session", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "eta", - description: "Torrent ETA (seconds)", - return_type: Number( - TypeInfo { - name: "eta", - is_optional: false, - is_list: false, - description: Some( - "Torrent ETA (seconds)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "f_l_piece_prio", - description: "True if first last piece are prioritized", - return_type: Bool( - TypeInfo { - name: "f_l_piece_prio", - is_optional: false, - is_list: false, - description: Some( - "True if first last piece are prioritized", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "force_start", - description: "True if force start is enabled for this torrent", - return_type: Bool( - TypeInfo { - name: "force_start", - is_optional: false, - is_list: false, - description: Some( - "True if force start is enabled for this torrent", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "hash", - description: "Torrent hash", - return_type: String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "Torrent hash", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "last_activity", - description: "Last time (Unix Epoch) when a chunk was downloaded/uploaded", - return_type: Number( - TypeInfo { - name: "last_activity", - is_optional: false, - is_list: false, - description: Some( - "Last time (Unix Epoch) when a chunk was downloaded/uploaded", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "magnet_uri", - description: "Magnet URI corresponding to this torrent", - return_type: String( - TypeInfo { - name: "magnet_uri", - is_optional: false, - is_list: false, - description: Some( - "Magnet URI corresponding to this torrent", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_ratio", - description: "Maximum share ratio until torrent is stopped from seeding/uploading", - return_type: Float( - TypeInfo { - name: "max_ratio", - is_optional: false, - is_list: false, - description: Some( - "Maximum share ratio until torrent is stopped from seeding/uploading", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "max_seeding_time", - description: "Maximum seeding time (seconds) until torrent is stopped from seeding", - return_type: Number( - TypeInfo { - name: "max_seeding_time", - is_optional: false, - is_list: false, - description: Some( - "Maximum seeding time (seconds) until torrent is stopped from seeding", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "name", - description: "Torrent name", - return_type: String( - TypeInfo { - name: "name", - is_optional: false, - is_list: false, - description: Some( - "Torrent name", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "num_complete", - description: "Number of seeds in the swarm", - return_type: Number( - TypeInfo { - name: "num_complete", - is_optional: false, - is_list: false, - description: Some( - "Number of seeds in the swarm", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "num_incomplete", - description: "Number of leechers in the swarm", - return_type: Number( - TypeInfo { - name: "num_incomplete", - is_optional: false, - is_list: false, - description: Some( - "Number of leechers in the swarm", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "num_leechs", - description: "Number of leechers connected to", - return_type: Number( - TypeInfo { - name: "num_leechs", - is_optional: false, - is_list: false, - description: Some( - "Number of leechers connected to", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "num_seeds", - description: "Number of seeds connected to", - return_type: Number( - TypeInfo { - name: "num_seeds", - is_optional: false, - is_list: false, - description: Some( - "Number of seeds connected to", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "priority", - description: "Torrent priority. Returns -1 if queuing is disabled or torrent is in seed mode", - return_type: Number( - TypeInfo { - name: "priority", - is_optional: false, - is_list: false, - description: Some( - "Torrent priority. Returns -1 if queuing is disabled or torrent is in seed mode", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "progress", - description: "Torrent progress (percentage/100)", - return_type: Float( - TypeInfo { - name: "progress", - is_optional: false, - is_list: false, - description: Some( - "Torrent progress (percentage/100)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "ratio", - description: "Torrent share ratio. Max ratio value: 9999.", - return_type: Float( - TypeInfo { - name: "ratio", - is_optional: false, - is_list: false, - description: Some( - "Torrent share ratio. Max ratio value: 9999.", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "ratio_limit", - description: "TODO (what is different from max_ratio?)", - return_type: Float( - TypeInfo { - name: "ratio_limit", - is_optional: false, - is_list: false, - description: Some( - "TODO (what is different from max_ratio?)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "save_path", - description: "Path where this torrent's data is stored", - return_type: String( - TypeInfo { - name: "save_path", - is_optional: false, - is_list: false, - description: Some( - "Path where this torrent's data is stored", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "seeding_time", - description: "Torrent elapsed time while complete (seconds)", - return_type: Number( - TypeInfo { - name: "seeding_time", - is_optional: false, - is_list: false, - description: Some( - "Torrent elapsed time while complete (seconds)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "seeding_time_limit", - description: "TODO (what is different from max_seeding_time?) seeding_time_limit is a per torrent setting, when Automatic Torrent Management is disabled, furthermore then max_seeding_time is set to seeding_time_limit for this torrent. If Automatic Torrent Management is enabled, the value is -2. And if max_seeding_time is unset it have a default value -1.", - return_type: Number( - TypeInfo { - name: "seeding_time_limit", - is_optional: false, - is_list: false, - description: Some( - "TODO (what is different from max_seeding_time?) seeding_time_limit is a per torrent setting, when Automatic Torrent Management is disabled, furthermore then max_seeding_time is set to seeding_time_limit for this torrent. If Automatic Torrent Management is enabled, the value is -2. And if max_seeding_time is unset it have a default value -1.", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "seen_complete", - description: "Time (Unix Epoch) when this torrent was last seen complete", - return_type: Number( - TypeInfo { - name: "seen_complete", - is_optional: false, - is_list: false, - description: Some( - "Time (Unix Epoch) when this torrent was last seen complete", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "seq_dl", - description: "True if sequential download is enabled", - return_type: Bool( - TypeInfo { - name: "seq_dl", - is_optional: false, - is_list: false, - description: Some( - "True if sequential download is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "size", - description: "Total size (bytes) of files selected for download", - return_type: Number( - TypeInfo { - name: "size", - is_optional: false, - is_list: false, - description: Some( - "Total size (bytes) of files selected for download", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "state", - description: "Torrent state. See table here below for the possible values", - return_type: String( - TypeInfo { - name: "state", - is_optional: false, - is_list: false, - description: Some( - "Torrent state. See table here below for the possible values", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "error", - description: "Some error occurred, applies to paused torrents", - }, - TypeDescriptions { - value: "missingFiles", - description: "Torrent data files is missing", - }, - TypeDescriptions { - value: "uploading", - description: "Torrent is being seeded and data is being transferred", - }, - TypeDescriptions { - value: "pausedUP", - description: "Torrent is paused and has finished downloading", - }, - TypeDescriptions { - value: "queuedUP", - description: "Queuing is enabled and torrent is queued for upload", - }, - TypeDescriptions { - value: "stalledUP", - description: "Torrent is being seeded, but no connection were made", - }, - TypeDescriptions { - value: "checkingUP", - description: "Torrent has finished downloading and is being checked", - }, - TypeDescriptions { - value: "forcedUP", - description: "Torrent is forced to uploading and ignore queue limit", - }, - TypeDescriptions { - value: "allocating", - description: "Torrent is allocating disk space for download", - }, - TypeDescriptions { - value: "downloading", - description: "Torrent is being downloaded and data is being transferred", - }, - TypeDescriptions { - value: "metaDL", - description: "Torrent has just started downloading and is fetching metadata", - }, - TypeDescriptions { - value: "pausedDL", - description: "Torrent is paused and has NOT finished downloading", - }, - TypeDescriptions { - value: "queuedDL", - description: "Queuing is enabled and torrent is queued for download", - }, - TypeDescriptions { - value: "stalledDL", - description: "Torrent is being downloaded, but no connection were made", - }, - TypeDescriptions { - value: "checkingDL", - description: "Same as checkingUP, but torrent has NOT finished downloading", - }, - TypeDescriptions { - value: "forcedDL", - description: "Torrent is forced to downloading to ignore queue limit", - }, - TypeDescriptions { - value: "checkingResumeData", - description: "Checking resume data on qBt startup", - }, - TypeDescriptions { - value: "moving", - description: "Torrent is moving to another location", - }, - TypeDescriptions { - value: "unknown", - description: "Unknown status", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "super_seeding", - description: "True if super seeding is enabled", - return_type: Bool( - TypeInfo { - name: "super_seeding", - is_optional: false, - is_list: false, - description: Some( - "True if super seeding is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "tags", - description: "Comma-concatenated tag list of the torrent", - return_type: String( - TypeInfo { - name: "tags", - is_optional: false, - is_list: false, - description: Some( - "Comma-concatenated tag list of the torrent", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "time_active", - description: "Total active time (seconds)", - return_type: Number( - TypeInfo { - name: "time_active", - is_optional: false, - is_list: false, - description: Some( - "Total active time (seconds)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "total_size", - description: "Total size (bytes) of all file in this torrent (including unselected ones)", - return_type: Number( - TypeInfo { - name: "total_size", - is_optional: false, - is_list: false, - description: Some( - "Total size (bytes) of all file in this torrent (including unselected ones)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "tracker", - description: "The first tracker with working status. Returns empty string if no tracker is working.", - return_type: String( - TypeInfo { - name: "tracker", - is_optional: false, - is_list: false, - description: Some( - "The first tracker with working status. Returns empty string if no tracker is working.", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "up_limit", - description: "Torrent upload speed limit (bytes/s). -1 if ulimited.", - return_type: Number( - TypeInfo { - name: "up_limit", - is_optional: false, - is_list: false, - description: Some( - "Torrent upload speed limit (bytes/s). -1 if ulimited.", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "uploaded", - description: "Amount of data uploaded", - return_type: Number( - TypeInfo { - name: "uploaded", - is_optional: false, - is_list: false, - description: Some( - "Amount of data uploaded", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "uploaded_session", - description: "Amount of data uploaded this session", - return_type: Number( - TypeInfo { - name: "uploaded_session", - is_optional: false, - is_list: false, - description: Some( - "Amount of data uploaded this session", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "upspeed", - description: "Torrent upload speed (bytes/s)", - return_type: Number( - TypeInfo { - name: "upspeed", - is_optional: false, - is_list: false, - description: Some( - "Torrent upload speed (bytes/s)", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "info", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "filter", + is_optional: true, + is_list: false, + description: Some( + "Filter torrent list by state. Allowed state filters: all, downloading, seeding, completed, paused, active, inactive, resumed, stalled, stalled_uploading, stalled_downloading, errored", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "category", + is_optional: true, + is_list: false, + description: Some( + "Get torrents with the given category (empty string means \"without category\"; no \"category\" parameter means \"any category\" <- broken until [#11748](https://github.com/qbittorrent/qBittorrent/issues/11748) is resolved). Remember to URL-encode the category name. For example, My category becomes My%20category", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "tag", + is_optional: true, + is_list: false, + description: Some( + "Get torrents with the given tag (empty string means \"without tag\"; no \"tag\" parameter means \"any tag\". Remember to URL-encode the category name. For example, My tag becomes My%20tag", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "sort", + is_optional: true, + is_list: false, + description: Some( + "Sort torrents by given key. They can be sorted using any field of the response's JSON array (which are documented below) as the sort key.", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "reverse", + is_optional: true, + is_list: false, + description: Some( + "Enable reverse sorting. Defaults to false", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "limit", + is_optional: true, + is_list: false, + description: Some( + "Limit the number of torrents returned", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "offset", + is_optional: true, + is_list: false, + description: Some( + "Set offset (if less than 0, offset from end)", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "hashes", + is_optional: true, + is_list: false, + description: Some( + "Filter by hashes. Can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + Enum( + Enum { + name: "State", + values: [ + EnumValue { + description: Some( + "Some error occurred, applies to paused torrents", + ), + value: "Error", + original_value: "error", + }, + EnumValue { + description: Some( + "Torrent data files is missing", + ), + value: "MissingFiles", + original_value: "missingFiles", + }, + EnumValue { + description: Some( + "Torrent is being seeded and data is being transferred", + ), + value: "Uploading", + original_value: "uploading", + }, + EnumValue { + description: Some( + "Torrent is paused and has finished downloading", + ), + value: "PausedUP", + original_value: "pausedUP", + }, + EnumValue { + description: Some( + "Queuing is enabled and torrent is queued for upload", + ), + value: "QueuedUP", + original_value: "queuedUP", + }, + EnumValue { + description: Some( + "Torrent is being seeded, but no connection were made", + ), + value: "StalledUP", + original_value: "stalledUP", + }, + EnumValue { + description: Some( + "Torrent has finished downloading and is being checked", + ), + value: "CheckingUP", + original_value: "checkingUP", + }, + EnumValue { + description: Some( + "Torrent is forced to uploading and ignore queue limit", + ), + value: "ForcedUP", + original_value: "forcedUP", + }, + EnumValue { + description: Some( + "Torrent is allocating disk space for download", + ), + value: "Allocating", + original_value: "allocating", + }, + EnumValue { + description: Some( + "Torrent is being downloaded and data is being transferred", + ), + value: "Downloading", + original_value: "downloading", + }, + EnumValue { + description: Some( + "Torrent has just started downloading and is fetching metadata", + ), + value: "MetaDL", + original_value: "metaDL", + }, + EnumValue { + description: Some( + "Torrent is paused and has NOT finished downloading", + ), + value: "PausedDL", + original_value: "pausedDL", + }, + EnumValue { + description: Some( + "Queuing is enabled and torrent is queued for download", + ), + value: "QueuedDL", + original_value: "queuedDL", + }, + EnumValue { + description: Some( + "Torrent is being downloaded, but no connection were made", + ), + value: "StalledDL", + original_value: "stalledDL", + }, + EnumValue { + description: Some( + "Same as checkingUP, but torrent has NOT finished downloading", + ), + value: "CheckingDL", + original_value: "checkingDL", + }, + EnumValue { + description: Some( + "Torrent is forced to downloading to ignore queue limit", + ), + value: "ForcedDL", + original_value: "forcedDL", + }, + EnumValue { + description: Some( + "Checking resume data on qBt startup", + ), + value: "CheckingResumeData", + original_value: "checkingResumeData", + }, + EnumValue { + description: Some( + "Torrent is moving to another location", + ), + value: "Moving", + original_value: "moving", + }, + EnumValue { + description: Some( + "Unknown status", + ), + value: "Unknown", + original_value: "unknown", + }, + ], + }, + ), + Response( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "added_on", + is_optional: false, + is_list: false, + description: Some( + "Time (Unix Epoch) when the torrent was added to the client", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "amount_left", + is_optional: false, + is_list: false, + description: Some( + "Amount of data left to download (bytes)", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "auto_tmm", + is_optional: false, + is_list: false, + description: Some( + "Whether this torrent is managed by Automatic Torrent Management", + ), + type_description: None, + }, + ), + Float( + TypeInfo { + name: "availability", + is_optional: false, + is_list: false, + description: Some( + "Percentage of file pieces currently available", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "category", + is_optional: false, + is_list: false, + description: Some( + "Category of the torrent", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "completed", + is_optional: false, + is_list: false, + description: Some( + "Amount of transfer data completed (bytes)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "completion_on", + is_optional: false, + is_list: false, + description: Some( + "Time (Unix Epoch) when the torrent completed", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "content_path", + is_optional: false, + is_list: false, + description: Some( + "Absolute path of torrent content (root path for multifile torrents, absolute file path for singlefile torrents)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "dl_limit", + is_optional: false, + is_list: false, + description: Some( + "Torrent download speed limit (bytes/s). -1 if ulimited.", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "dlspeed", + is_optional: false, + is_list: false, + description: Some( + "Torrent download speed (bytes/s)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "downloaded", + is_optional: false, + is_list: false, + description: Some( + "Amount of data downloaded", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "downloaded_session", + is_optional: false, + is_list: false, + description: Some( + "Amount of data downloaded this session", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "eta", + is_optional: false, + is_list: false, + description: Some( + "Torrent ETA (seconds)", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "f_l_piece_prio", + is_optional: false, + is_list: false, + description: Some( + "True if first last piece are prioritized", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "force_start", + is_optional: false, + is_list: false, + description: Some( + "True if force start is enabled for this torrent", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "Torrent hash", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "last_activity", + is_optional: false, + is_list: false, + description: Some( + "Last time (Unix Epoch) when a chunk was downloaded/uploaded", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "magnet_uri", + is_optional: false, + is_list: false, + description: Some( + "Magnet URI corresponding to this torrent", + ), + type_description: None, + }, + ), + Float( + TypeInfo { + name: "max_ratio", + is_optional: false, + is_list: false, + description: Some( + "Maximum share ratio until torrent is stopped from seeding/uploading", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "max_seeding_time", + is_optional: false, + is_list: false, + description: Some( + "Maximum seeding time (seconds) until torrent is stopped from seeding", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "name", + is_optional: false, + is_list: false, + description: Some( + "Torrent name", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "num_complete", + is_optional: false, + is_list: false, + description: Some( + "Number of seeds in the swarm", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "num_incomplete", + is_optional: false, + is_list: false, + description: Some( + "Number of leechers in the swarm", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "num_leechs", + is_optional: false, + is_list: false, + description: Some( + "Number of leechers connected to", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "num_seeds", + is_optional: false, + is_list: false, + description: Some( + "Number of seeds connected to", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "priority", + is_optional: false, + is_list: false, + description: Some( + "Torrent priority. Returns -1 if queuing is disabled or torrent is in seed mode", + ), + type_description: None, + }, + ), + Float( + TypeInfo { + name: "progress", + is_optional: false, + is_list: false, + description: Some( + "Torrent progress (percentage/100)", + ), + type_description: None, + }, + ), + Float( + TypeInfo { + name: "ratio", + is_optional: false, + is_list: false, + description: Some( + "Torrent share ratio. Max ratio value: 9999.", + ), + type_description: None, + }, + ), + Float( + TypeInfo { + name: "ratio_limit", + is_optional: false, + is_list: false, + description: Some( + "TODO (what is different from max_ratio?)", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "save_path", + is_optional: false, + is_list: false, + description: Some( + "Path where this torrent's data is stored", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "seeding_time", + is_optional: false, + is_list: false, + description: Some( + "Torrent elapsed time while complete (seconds)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "seeding_time_limit", + is_optional: false, + is_list: false, + description: Some( + "TODO (what is different from max_seeding_time?) seeding_time_limit is a per torrent setting, when Automatic Torrent Management is disabled, furthermore then max_seeding_time is set to seeding_time_limit for this torrent. If Automatic Torrent Management is enabled, the value is -2. And if max_seeding_time is unset it have a default value -1.", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "seen_complete", + is_optional: false, + is_list: false, + description: Some( + "Time (Unix Epoch) when this torrent was last seen complete", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "seq_dl", + is_optional: false, + is_list: false, + description: Some( + "True if sequential download is enabled", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "size", + is_optional: false, + is_list: false, + description: Some( + "Total size (bytes) of files selected for download", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "state", + is_optional: false, + is_list: false, + description: Some( + "Torrent state. See table here below for the possible values", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "super_seeding", + is_optional: false, + is_list: false, + description: Some( + "True if super seeding is enabled", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "tags", + is_optional: false, + is_list: false, + description: Some( + "Comma-concatenated tag list of the torrent", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "time_active", + is_optional: false, + is_list: false, + description: Some( + "Total active time (seconds)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "total_size", + is_optional: false, + is_list: false, + description: Some( + "Total size (bytes) of all file in this torrent (including unselected ones)", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "tracker", + is_optional: false, + is_list: false, + description: Some( + "The first tracker with working status. Returns empty string if no tracker is working.", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "up_limit", + is_optional: false, + is_list: false, + description: Some( + "Torrent upload speed limit (bytes/s). -1 if ulimited.", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "uploaded", + is_optional: false, + is_list: false, + description: Some( + "Amount of data uploaded", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "uploaded_session", + is_optional: false, + is_list: false, + description: Some( + "Amount of data uploaded this session", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "upspeed", + is_optional: false, + is_list: false, + description: Some( + "Torrent upload speed (bytes/s)", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "properties", description: Some( "The response is:\n\n- empty, if the torrent hash is invalid\n- otherwise, a JSON object with the following fields\n\n\nNB: `-1` is returned if the type of the property is integer but its value is not known.\n\nExample:\n\n```JSON\n{\n \"addition_date\":1438429165,\n \"comment\":\"\\\"Debian CD from cdimage.debian.org\\\"\",\n \"completion_date\":1438429234,\n \"created_by\":\"\",\n \"creation_date\":1433605214,\n \"dl_limit\":-1,\n \"dl_speed\":0,\n \"dl_speed_avg\":9736015,\n \"eta\":8640000,\n \"last_seen\":1438430354,\n \"nb_connections\":3,\n \"nb_connections_limit\":250,\n \"peers\":1,\n \"peers_total\":89,\n \"piece_size\":524288,\n \"pieces_have\":1254,\n \"pieces_num\":1254,\n \"reannounce\":672,\n \"save_path\":\"/Downloads/debian-8.1.0-amd64-CD-1.iso\",\n \"seeding_time\":1128,\n \"seeds\":1,\n \"seeds_total\":254,\n \"share_ratio\":0.00072121022562178299,\n \"time_elapsed\":1197,\n \"total_downloaded\":681521119,\n \"total_downloaded_session\":681521119,\n \"total_size\":657457152,\n \"total_uploaded\":491520,\n \"total_uploaded_session\":491520,\n \"total_wasted\":23481724,\n \"up_limit\":-1,\n \"up_speed\":0,\n \"up_speed_avg\":410\n}\n```", ), - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent you want to get the generic properties of", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "properties", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent you want to get the generic properties of", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "trackers", description: Some( "The response is a JSON array, where each element contains info about one tracker, with the following fields\n\n\nPossible values of `status`:\n\n\nExample:\n\n```JSON\n[\n {\n \"msg\":\"\",\n \"num_peers\":100,\n \"status\":2,\n \"url\":\"http://bttracker.debian.org:6969/announce\"\n },\n {\n another_tracker_info\n }\n]\n```", ), - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent you want to get the trackers of", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: Some( - ReturnType { - is_list: true, - parameters: [ - ReturnTypeParameter { - name: "url", - description: "Tracker url", - return_type: String( - TypeInfo { - name: "url", - is_optional: false, - is_list: false, - description: Some( - "Tracker url", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "status", - description: "Tracker status. See the table below for possible values", - return_type: Number( - TypeInfo { - name: "status", - is_optional: false, - is_list: false, - description: Some( - "Tracker status. See the table below for possible values", - ), - type_description: Some( - TypeDescription { - values: [ - TypeDescriptions { - value: "0", - description: "Tracker is disabled (used for DHT, PeX, and LSD)", - }, - TypeDescriptions { - value: "1", - description: "Tracker has not been contacted yet", - }, - TypeDescriptions { - value: "2", - description: "Tracker has been contacted and is working", - }, - TypeDescriptions { - value: "3", - description: "Tracker is updating", - }, - TypeDescriptions { - value: "4", - description: "Tracker has been contacted, but it is not working (or doesn't send proper replies)", - }, - ], - }, - ), - }, - ), - }, - ReturnTypeParameter { - name: "tier", - description: "Tracker priority tier. Lower tier trackers are tried before higher tiers. Tier numbers are valid when >= 0, < 0 is used as placeholder when tier does not exist for special entries (such as DHT).", - return_type: Number( - TypeInfo { - name: "tier", - is_optional: false, - is_list: false, - description: Some( - "Tracker priority tier. Lower tier trackers are tried before higher tiers. Tier numbers are valid when >= 0, < 0 is used as placeholder when tier does not exist for special entries (such as DHT).", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "num_peers", - description: "Number of peers for current torrent, as reported by the tracker", - return_type: Number( - TypeInfo { - name: "num_peers", - is_optional: false, - is_list: false, - description: Some( - "Number of peers for current torrent, as reported by the tracker", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "num_seeds", - description: "Number of seeds for current torrent, asreported by the tracker", - return_type: Number( - TypeInfo { - name: "num_seeds", - is_optional: false, - is_list: false, - description: Some( - "Number of seeds for current torrent, asreported by the tracker", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "num_leeches", - description: "Number of leeches for current torrent, as reported by the tracker", - return_type: Number( - TypeInfo { - name: "num_leeches", - is_optional: false, - is_list: false, - description: Some( - "Number of leeches for current torrent, as reported by the tracker", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "num_downloaded", - description: "Number of completed downlods for current torrent, as reported by the tracker", - return_type: Number( - TypeInfo { - name: "num_downloaded", - is_optional: false, - is_list: false, - description: Some( - "Number of completed downlods for current torrent, as reported by the tracker", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "msg", - description: "Tracker message (there is no way of knowing what this message is - it's up to tracker admins)", - return_type: String( - TypeInfo { - name: "msg", - is_optional: false, - is_list: false, - description: Some( - "Tracker message (there is no way of knowing what this message is - it's up to tracker admins)", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "trackers", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent you want to get the trackers of", + ), + type_description: None, + }, + ), + ], + }, + ), + Enum( + Enum { + name: "Status", + values: [ + EnumValue { + description: Some( + "Tracker is disabled (used for DHT, PeX, and LSD)", + ), + value: "TrackerIsDisabled", + original_value: "0", + }, + EnumValue { + description: Some( + "Tracker has not been contacted yet", + ), + value: "TrackerHasNotBeenContactedYet", + original_value: "1", + }, + EnumValue { + description: Some( + "Tracker has been contacted and is working", + ), + value: "TrackerHasBeenContactedAndIsWorking", + original_value: "2", + }, + EnumValue { + description: Some( + "Tracker is updating", + ), + value: "TrackerIsUpdating", + original_value: "3", + }, + EnumValue { + description: Some( + "Tracker has been contacted, but it is not working (or doesn't send proper replies)", + ), + value: "TrackerHasBeenContactedButItIsNotWorking", + original_value: "4", + }, + ], + }, + ), + Response( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "url", + is_optional: false, + is_list: false, + description: Some( + "Tracker url", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "status", + is_optional: false, + is_list: false, + description: Some( + "Tracker status. See the table below for possible values", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "tier", + is_optional: false, + is_list: false, + description: Some( + "Tracker priority tier. Lower tier trackers are tried before higher tiers. Tier numbers are valid when >= 0, < 0 is used as placeholder when tier does not exist for special entries (such as DHT).", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "num_peers", + is_optional: false, + is_list: false, + description: Some( + "Number of peers for current torrent, as reported by the tracker", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "num_seeds", + is_optional: false, + is_list: false, + description: Some( + "Number of seeds for current torrent, asreported by the tracker", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "num_leeches", + is_optional: false, + is_list: false, + description: Some( + "Number of leeches for current torrent, as reported by the tracker", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "num_downloaded", + is_optional: false, + is_list: false, + description: Some( + "Number of completed downlods for current torrent, as reported by the tracker", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "msg", + is_optional: false, + is_list: false, + description: Some( + "Tracker message (there is no way of knowing what this message is - it's up to tracker admins)", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "webseeds", description: Some( "The response is a JSON array, where each element is information about one webseed, with the following fields\n\n\nExample:\n\n```JSON\n[\n {\n \"url\":\"http://some_url/\"\n },\n {\n \"url\":\"http://some_other_url/\"\n }\n]\n```", ), - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent you want to get the webseeds of", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: Some( - ReturnType { - is_list: true, - parameters: [ - ReturnTypeParameter { - name: "url", - description: "URL of the web seed", - return_type: String( - TypeInfo { - name: "url", - is_optional: false, - is_list: false, - description: Some( - "URL of the web seed", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "webseeds", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent you want to get the webseeds of", + ), + type_description: None, + }, + ), + ], + }, + ), + Response( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "url", + is_optional: false, + is_list: false, + description: Some( + "URL of the web seed", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "files", description: Some( "The response is:\n\n- empty, if the torrent hash is invalid\n- otherwise, a JSON array, where each element contains info about one file, with the following fields\n\n\nPossible values of `priority`:\n\n\nExample:\n\n```JSON\n\n[\n {\n \"index\":0,\n \"is_seed\":false,\n \"name\":\"debian-8.1.0-amd64-CD-1.iso\",\n \"piece_range\":[0,1253],\n \"priority\":1,\n \"progress\":0,\n \"size\":657457152,\n \"availability\":0.5,\n }\n]\n```", ), - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent you want to get the contents of", - ), - type_description: None, - }, - ), - ], - optional: [ - String( - TypeInfo { - name: "indexes", - is_optional: true, - is_list: false, - description: Some( - "The indexes of the files you want to retrieve. indexes can contain multiple values separated by \\", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: None, url: "files", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent you want to get the contents of", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "indexes", + is_optional: true, + is_list: false, + description: Some( + "The indexes of the files you want to retrieve. indexes can contain multiple values separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + Enum( + Enum { + name: "Priority", + values: [ + EnumValue { + description: Some( + "Do not download", + ), + value: "DoNotDownload", + original_value: "0", + }, + EnumValue { + description: Some( + "Normal priority", + ), + value: "NormalPriority", + original_value: "1", + }, + EnumValue { + description: Some( + "High priority", + ), + value: "HighPriority", + original_value: "6", + }, + EnumValue { + description: Some( + "Maximal priority", + ), + value: "MaximalPriority", + original_value: "7", + }, + ], + }, + ), + ], + }, }, ApiMethod { name: "pieceStates", description: Some( "The response is:\n\n- empty, if the torrent hash is invalid\n- otherwise, an array of states (integers) of all pieces (in order) of a specific torrent.\n\nValue meanings are defined as below:\n\n\nExample:\n\n```JSON\n[0,0,2,1,0,0,2,1]\n```", ), - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent you want to get the pieces' states of", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "pieceStates", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent you want to get the pieces' states of", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "pieceHashes", description: Some( "The response is:\n\n- empty, if the torrent hash is invalid\n- otherwise, an array of hashes (strings) of all pieces (in order) of a specific torrent.\n\nExample:\n\n```JSON\n[\"54eddd830a5b58480a6143d616a97e3a6c23c439\",\"f8a99d225aa4241db100f88407fc3bdaead583ab\",\"928fb615b9bd4dd8f9e9022552c8f8f37ef76f58\"]\n```", ), - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent you want to get the pieces' hashes of", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "pieceHashes", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent you want to get the pieces' hashes of", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "pause", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to pause. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "pause", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to pause. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "resume", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to resume. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "resume", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to resume. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "delete", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to delete. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "delete", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to delete. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + Object( + Object { + type_info: TypeInfo { + name: "deleteFiles", + is_optional: false, + is_list: false, + description: None, + type_description: None, + }, + ref_type: "If set to true, the downloaded data will also be deleted, otherwise has no effect.", + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "recheck", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to recheck. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "recheck", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to recheck. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "reannounce", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to reannounce. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "reannounce", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to reannounce. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "add", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "urls", - is_optional: false, - is_list: false, - description: Some( - "URLs separated with newlines", - ), - type_description: None, - }, - ), - ], - optional: [ - String( - TypeInfo { - name: "savepath", - is_optional: true, - is_list: false, - description: Some( - "Download folder", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "cookie", - is_optional: true, - is_list: false, - description: Some( - "Cookie sent to download the .torrent file", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "category", - is_optional: true, - is_list: false, - description: Some( - "Category for the torrent", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "tags", - is_optional: true, - is_list: false, - description: Some( - "Tags for the torrent, split by ','", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "skip_checking", - is_optional: true, - is_list: false, - description: Some( - "Skip hash checking. Possible values are true, false (default)", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "paused", - is_optional: true, - is_list: false, - description: Some( - "Add torrents in the paused state. Possible values are true, false (default)", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "root_folder", - is_optional: true, - is_list: false, - description: Some( - "Create the root folder. Possible values are true, false, unset (default)", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "rename", - is_optional: true, - is_list: false, - description: Some( - "Rename torrent", - ), - type_description: None, - }, - ), - Number( - TypeInfo { - name: "upLimit", - is_optional: true, - is_list: false, - description: Some( - "Set torrent upload speed limit. Unit in bytes/second", - ), - type_description: None, - }, - ), - Number( - TypeInfo { - name: "dlLimit", - is_optional: true, - is_list: false, - description: Some( - "Set torrent download speed limit. Unit in bytes/second", - ), - type_description: None, - }, - ), - Float( - TypeInfo { - name: "ratioLimit", - is_optional: true, - is_list: false, - description: Some( - "Set torrent share ratio limit", - ), - type_description: None, - }, - ), - Number( - TypeInfo { - name: "seedingTimeLimit", - is_optional: true, - is_list: false, - description: Some( - "Set torrent seeding time limit. Unit in seconds", - ), - type_description: None, - }, - ), - Bool( - TypeInfo { - name: "autoTMM", - is_optional: true, - is_list: false, - description: Some( - "Whether Automatic Torrent Management should be used", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "sequentialDownload", - is_optional: true, - is_list: false, - description: Some( - "Enable sequential download. Possible values are true, false (default)", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "firstLastPiecePrio", - is_optional: true, - is_list: false, - description: Some( - "Prioritize download first last piece. Possible values are true, false (default)", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: None, url: "add", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "urls", + is_optional: false, + is_list: false, + description: Some( + "URLs separated with newlines", + ), + type_description: None, + }, + ), + Object( + Object { + type_info: TypeInfo { + name: "torrents", + is_optional: false, + is_list: false, + description: Some( + "Raw data of torrent file. torrents can be presented multiple times.", + ), + type_description: None, + }, + ref_type: "Raw", + }, + ), + String( + TypeInfo { + name: "savepath", + is_optional: true, + is_list: false, + description: Some( + "Download folder", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "cookie", + is_optional: true, + is_list: false, + description: Some( + "Cookie sent to download the .torrent file", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "category", + is_optional: true, + is_list: false, + description: Some( + "Category for the torrent", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "tags", + is_optional: true, + is_list: false, + description: Some( + "Tags for the torrent, split by ','", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "skip_checking", + is_optional: true, + is_list: false, + description: Some( + "Skip hash checking. Possible values are true, false (default)", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "paused", + is_optional: true, + is_list: false, + description: Some( + "Add torrents in the paused state. Possible values are true, false (default)", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "root_folder", + is_optional: true, + is_list: false, + description: Some( + "Create the root folder. Possible values are true, false, unset (default)", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "rename", + is_optional: true, + is_list: false, + description: Some( + "Rename torrent", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "upLimit", + is_optional: true, + is_list: false, + description: Some( + "Set torrent upload speed limit. Unit in bytes/second", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "dlLimit", + is_optional: true, + is_list: false, + description: Some( + "Set torrent download speed limit. Unit in bytes/second", + ), + type_description: None, + }, + ), + Float( + TypeInfo { + name: "ratioLimit", + is_optional: true, + is_list: false, + description: Some( + "Set torrent share ratio limit", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "seedingTimeLimit", + is_optional: true, + is_list: false, + description: Some( + "Set torrent seeding time limit. Unit in seconds", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "autoTMM", + is_optional: true, + is_list: false, + description: Some( + "Whether Automatic Torrent Management should be used", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "sequentialDownload", + is_optional: true, + is_list: false, + description: Some( + "Enable sequential download. Possible values are true, false (default)", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "firstLastPiecePrio", + is_optional: true, + is_list: false, + description: Some( + "Prioritize download first last piece. Possible values are true, false (default)", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "addTrackers", description: None, - parameters: None, - return_type: None, url: "addTrackers", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "editTracker", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "origUrl", - is_optional: false, - is_list: false, - description: Some( - "The tracker URL you want to edit", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "newUrl", - is_optional: false, - is_list: false, - description: Some( - "The new URL to replace the origUrl", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "editTracker", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "origUrl", + is_optional: false, + is_list: false, + description: Some( + "The tracker URL you want to edit", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "newUrl", + is_optional: false, + is_list: false, + description: Some( + "The new URL to replace the origUrl", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "removeTrackers", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "urls", - is_optional: false, - is_list: false, - description: Some( - "URLs to remove, separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "removeTrackers", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "urls", + is_optional: false, + is_list: false, + description: Some( + "URLs to remove, separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "addPeers", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent, or multiple hashes separated by a pipe \\", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "peers", - is_optional: false, - is_list: false, - description: Some( - "The peer to add, or multiple peers separated by a pipe \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "addPeers", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent, or multiple hashes separated by a pipe \\", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "peers", + is_optional: false, + is_list: false, + description: Some( + "The peer to add, or multiple peers separated by a pipe \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "increasePrio", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to increase the priority of. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "increasePrio", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to increase the priority of. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "decreasePrio", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to decrease the priority of. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "decreasePrio", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to decrease the priority of. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "topPrio", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to set to the maximum priority. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "topPrio", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to set to the maximum priority. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "bottomPrio", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to set to the minimum priority. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "bottomPrio", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to set to the minimum priority. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "filePrio", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "id", - is_optional: false, - is_list: false, - description: Some( - "File ids, separated by \\", - ), - type_description: None, - }, - ), - Number( - TypeInfo { - name: "priority", - is_optional: false, - is_list: false, - description: Some( - "File priority to set (consult [torrent contents API](#get-torrent-contents) for possible values)", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "filePrio", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "id", + is_optional: false, + is_list: false, + description: Some( + "File ids, separated by \\", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "priority", + is_optional: false, + is_list: false, + description: Some( + "File priority to set (consult [torrent contents API](#get-torrent-contents) for possible values)", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "downloadLimit", description: None, - parameters: None, - return_type: None, url: "downloadLimit", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "setShareLimits", description: None, - parameters: None, - return_type: None, url: "setShareLimits", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "uploadLimit", description: None, - parameters: None, - return_type: None, url: "uploadLimit", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "setUploadLimit", description: None, - parameters: None, - return_type: None, url: "setUploadLimit", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "setLocation", description: None, - parameters: None, - return_type: None, url: "setLocation", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "rename", description: None, - parameters: None, - return_type: None, url: "rename", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "setCategory", description: None, - parameters: None, - return_type: None, url: "setCategory", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "categories", description: None, - parameters: None, - return_type: None, url: "categories", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "createCategory", description: None, - parameters: None, - return_type: None, url: "createCategory", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "editCategory", description: None, - parameters: None, - return_type: None, url: "editCategory", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "removeCategories", description: None, - parameters: None, - return_type: None, url: "removeCategories", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "addTags", description: None, - parameters: None, - return_type: None, url: "addTags", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "removeTags", description: None, - parameters: None, - return_type: None, url: "removeTags", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "tags", description: None, - parameters: None, - return_type: None, url: "tags", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "createTags", description: None, - parameters: None, - return_type: None, url: "createTags", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "deleteTags", description: None, - parameters: None, - return_type: None, url: "deleteTags", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "setAutoManagement", description: None, - parameters: None, - return_type: None, url: "setAutoManagement", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "toggleSequentialDownload", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to toggle sequential download for. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "toggleSequentialDownload", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to toggle sequential download for. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "toggleFirstLastPiecePrio", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hashes", - is_optional: false, - is_list: false, - description: Some( - "The hashes of the torrents you want to toggle the first/last piece priority for. hashes can contain multiple hashes separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "toggleFirstLastPiecePrio", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hashes", + is_optional: false, + is_list: false, + description: Some( + "The hashes of the torrents you want to toggle the first/last piece priority for. hashes can contain multiple hashes separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "setForceStart", description: None, - parameters: None, - return_type: None, url: "setForceStart", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "setSuperSeeding", description: None, - parameters: None, - return_type: None, url: "setSuperSeeding", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "renameFile", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "oldPath", - is_optional: false, - is_list: false, - description: Some( - "The old path of the torrent", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "newPath", - is_optional: false, - is_list: false, - description: Some( - "The new path to use for the file", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "renameFile", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "oldPath", + is_optional: false, + is_list: false, + description: Some( + "The old path of the torrent", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "newPath", + is_optional: false, + is_list: false, + description: Some( + "The new path to use for the file", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "renameFolder", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "hash", - is_optional: false, - is_list: false, - description: Some( - "The hash of the torrent", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "oldPath", - is_optional: false, - is_list: false, - description: Some( - "The old path of the torrent", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "newPath", - is_optional: false, - is_list: false, - description: Some( - "The new path to use for the file", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "renameFolder", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "hash", + is_optional: false, + is_list: false, + description: Some( + "The hash of the torrent", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "oldPath", + is_optional: false, + is_list: false, + description: Some( + "The old path of the torrent", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "newPath", + is_optional: false, + is_list: false, + description: Some( + "The new path to use for the file", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ], description: Some( @@ -5295,313 +3103,333 @@ ApiMethod { name: "addFolder", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "path", - is_optional: false, - is_list: false, - description: Some( - "Full path of added folder (e.g. \"The Pirate Bay\\Top100\")", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "addFolder", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "path", + is_optional: false, + is_list: false, + description: Some( + "Full path of added folder (e.g. \"The Pirate Bay\\Top100\")", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "addFeed", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "url", - is_optional: false, - is_list: false, - description: Some( - "URL of RSS feed (e.g. \"[http://thepiratebay.org/rss//top100/200](http://thepiratebay.org/rss//top100/200)\")", - ), - type_description: None, - }, - ), - ], - optional: [ - String( - TypeInfo { - name: "path", - is_optional: true, - is_list: false, - description: Some( - "Full path of added folder (e.g. \"The Pirate Bay\\Top100\\Video\")", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: None, url: "addFeed", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "url", + is_optional: false, + is_list: false, + description: Some( + "URL of RSS feed (e.g. \"[http://thepiratebay.org/rss//top100/200](http://thepiratebay.org/rss//top100/200)\")", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "path", + is_optional: true, + is_list: false, + description: Some( + "Full path of added folder (e.g. \"The Pirate Bay\\Top100\\Video\")", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "removeItem", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "path", - is_optional: false, - is_list: false, - description: Some( - "Full path of removed item (e.g. \"The Pirate Bay\\Top100\")", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "removeItem", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "path", + is_optional: false, + is_list: false, + description: Some( + "Full path of removed item (e.g. \"The Pirate Bay\\Top100\")", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "moveItem", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "itemPath", - is_optional: false, - is_list: false, - description: Some( - "Current full path of item (e.g. \"The Pirate Bay\\Top100\")", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "destPath", - is_optional: false, - is_list: false, - description: Some( - "New full path of item (e.g. \"The Pirate Bay\")", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "moveItem", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "itemPath", + is_optional: false, + is_list: false, + description: Some( + "Current full path of item (e.g. \"The Pirate Bay\\Top100\")", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "destPath", + is_optional: false, + is_list: false, + description: Some( + "New full path of item (e.g. \"The Pirate Bay\")", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "items", description: None, - parameters: Some( - ApiParameters { - mandatory: [], - optional: [ - Bool( - TypeInfo { - name: "withData", - is_optional: true, - is_list: false, - description: Some( - "True if you need current feed articles", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: None, url: "items", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Bool( + TypeInfo { + name: "withData", + is_optional: true, + is_list: false, + description: Some( + "True if you need current feed articles", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "markAsRead", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "itemPath", - is_optional: false, - is_list: false, - description: Some( - "Current full path of item (e.g. \"The Pirate Bay\\Top100\")", - ), - type_description: None, - }, - ), - ], - optional: [ - String( - TypeInfo { - name: "articleId", - is_optional: true, - is_list: false, - description: Some( - "ID of article", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: None, url: "markAsRead", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "itemPath", + is_optional: false, + is_list: false, + description: Some( + "Current full path of item (e.g. \"The Pirate Bay\\Top100\")", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "articleId", + is_optional: true, + is_list: false, + description: Some( + "ID of article", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "refreshItem", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "itemPath", - is_optional: false, - is_list: false, - description: Some( - "Current full path of item (e.g. \"The Pirate Bay\\Top100\")", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "refreshItem", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "itemPath", + is_optional: false, + is_list: false, + description: Some( + "Current full path of item (e.g. \"The Pirate Bay\\Top100\")", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "setRule", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "ruleName", - is_optional: false, - is_list: false, - description: Some( - "Rule name (e.g. \"Punisher\")", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "ruleDef", - is_optional: false, - is_list: false, - description: Some( - "JSON encoded rule definition", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "setRule", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "ruleName", + is_optional: false, + is_list: false, + description: Some( + "Rule name (e.g. \"Punisher\")", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "ruleDef", + is_optional: false, + is_list: false, + description: Some( + "JSON encoded rule definition", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "renameRule", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "ruleName", - is_optional: false, - is_list: false, - description: Some( - "Rule name (e.g. \"Punisher\")", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "newRuleName", - is_optional: false, - is_list: false, - description: Some( - "New rule name (e.g. \"The Punisher\")", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "renameRule", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "ruleName", + is_optional: false, + is_list: false, + description: Some( + "Rule name (e.g. \"Punisher\")", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "newRuleName", + is_optional: false, + is_list: false, + description: Some( + "New rule name (e.g. \"The Punisher\")", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "removeRule", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "ruleName", - is_optional: false, - is_list: false, - description: Some( - "Rule name (e.g. \"Punisher\")", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "removeRule", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "ruleName", + is_optional: false, + is_list: false, + description: Some( + "Rule name (e.g. \"Punisher\")", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "rules", description: None, - parameters: None, - return_type: None, url: "rules", + types: CompositeTypes { + composite_types: [], + }, }, ApiMethod { name: "matchingArticles", description: None, - parameters: None, - return_type: None, url: "matchingArticles", + types: CompositeTypes { + composite_types: [], + }, }, ], description: Some( @@ -5617,489 +3445,542 @@ description: Some( "The response is a JSON object with the following fields\n\n\nExample:\n\n```JSON\n{\n \"id\": 12345\n}\n```", ), - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "pattern", - is_optional: false, - is_list: false, - description: Some( - "Pattern to search for (e.g. \"Ubuntu 18.04\")", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "plugins", - is_optional: false, - is_list: false, - description: Some( - "Plugins to use for searching (e.g. \"legittorrents\"). Supports multiple plugins separated by \\", - ), - type_description: None, - }, - ), - String( - TypeInfo { - name: "category", - is_optional: false, - is_list: false, - description: Some( - "Categories to limit your search to (e.g. \"legittorrents\"). Available categories depend on the specified plugins. Also supports all", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: Some( - ReturnType { - is_list: false, - parameters: [ - ReturnTypeParameter { - name: "id", - description: "ID of the search job", - return_type: Number( - TypeInfo { - name: "id", - is_optional: false, - is_list: false, - description: Some( - "ID of the search job", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "start", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "pattern", + is_optional: false, + is_list: false, + description: Some( + "Pattern to search for (e.g. \"Ubuntu 18.04\")", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "plugins", + is_optional: false, + is_list: false, + description: Some( + "Plugins to use for searching (e.g. \"legittorrents\"). Supports multiple plugins separated by \\", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "category", + is_optional: false, + is_list: false, + description: Some( + "Categories to limit your search to (e.g. \"legittorrents\"). Available categories depend on the specified plugins. Also supports all", + ), + type_description: None, + }, + ), + ], + }, + ), + Response( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "id", + is_optional: false, + is_list: false, + description: Some( + "ID of the search job", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "stop", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - Number( - TypeInfo { - name: "id", - is_optional: false, - is_list: false, - description: Some( - "ID of the search job", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "stop", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "id", + is_optional: false, + is_list: false, + description: Some( + "ID of the search job", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "status", description: Some( "The response is a JSON array of objects containing the following fields\n\n\nExample:\n\n```JSON\n[\n {\n \"id\": 12345,\n \"status\": \"Running\",\n \"total\": 170\n }\n]\n```", ), - parameters: Some( - ApiParameters { - mandatory: [], - optional: [ - Number( - TypeInfo { - name: "id", - is_optional: true, - is_list: false, - description: Some( - "ID of the search job. If not specified, all search jobs are returned", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: Some( - ReturnType { - is_list: true, - parameters: [ - ReturnTypeParameter { - name: "id", - description: "ID of the search job", - return_type: Number( - TypeInfo { - name: "id", - is_optional: false, - is_list: false, - description: Some( - "ID of the search job", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "status", - description: "Current status of the search job (either Running or Stopped)", - return_type: String( - TypeInfo { - name: "status", - is_optional: false, - is_list: false, - description: Some( - "Current status of the search job (either Running or Stopped)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "total", - description: "Total number of results. If the status is Running this number may contineu to increase", - return_type: Number( - TypeInfo { - name: "total", - is_optional: false, - is_list: false, - description: Some( - "Total number of results. If the status is Running this number may contineu to increase", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "status", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "id", + is_optional: true, + is_list: false, + description: Some( + "ID of the search job. If not specified, all search jobs are returned", + ), + type_description: None, + }, + ), + ], + }, + ), + Response( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "id", + is_optional: false, + is_list: false, + description: Some( + "ID of the search job", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "status", + is_optional: false, + is_list: false, + description: Some( + "Current status of the search job (either Running or Stopped)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "total", + is_optional: false, + is_list: false, + description: Some( + "Total number of results. If the status is Running this number may contineu to increase", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "results", description: Some( "The response is a JSON object with the following fields\n\n\n\n\nExample:\n\n```JSON\n{\n \"results\": [\n {\n \"descrLink\": \"http://www.legittorrents.info/index.php?page=torrent-details&id=8d5f512e1acb687029b8d7cc6c5a84dce51d7a41\",\n \"fileName\": \"Ubuntu-10.04-32bit-NeTV.ova\",\n \"fileSize\": -1,\n \"fileUrl\": \"http://www.legittorrents.info/download.php?id=8d5f512e1acb687029b8d7cc6c5a84dce51d7a41&f=Ubuntu-10.04-32bit-NeTV.ova.torrent\",\n \"nbLeechers\": 1,\n \"nbSeeders\": 0,\n \"siteUrl\": \"http://www.legittorrents.info\"\n },\n {\n \"descrLink\": \"http://www.legittorrents.info/index.php?page=torrent-details&id=d5179f53e105dc2c2401bcfaa0c2c4936a6aa475\",\n \"fileName\": \"mangOH-Legato-17_06-Ubuntu-16_04.ova\",\n \"fileSize\": -1,\n \"fileUrl\": \"http://www.legittorrents.info/download.php?id=d5179f53e105dc2c2401bcfaa0c2c4936a6aa475&f=mangOH-Legato-17_06-Ubuntu-16_04.ova.torrent\",\n \"nbLeechers\": 0,\n \"nbSeeders\": 59,\n \"siteUrl\": \"http://www.legittorrents.info\"\n }\n ],\n \"status\": \"Running\",\n \"total\": 2\n}\n```", ), - parameters: Some( - ApiParameters { - mandatory: [ - Number( - TypeInfo { - name: "id", - is_optional: false, - is_list: false, - description: Some( - "ID of the search job", - ), - type_description: None, - }, - ), - ], - optional: [ - Number( - TypeInfo { - name: "limit", - is_optional: true, - is_list: false, - description: Some( - "max number of results to return. 0 or negative means no limit", - ), - type_description: None, - }, - ), - Number( - TypeInfo { - name: "offset", - is_optional: true, - is_list: false, - description: Some( - "result to start at. A negative number means count backwards (e.g. -2 returns the 2 most recent results)", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: Some( - ReturnType { - is_list: false, - parameters: [ - ReturnTypeParameter { - name: "results", - description: "Array of result objects- see table below", - return_type: StringArray( - TypeInfo { - name: "results", - is_optional: false, - is_list: false, - description: Some( - "Array of result objects- see table below", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "status", - description: "Current status of the search job (either Running or Stopped)", - return_type: String( - TypeInfo { - name: "status", - is_optional: false, - is_list: false, - description: Some( - "Current status of the search job (either Running or Stopped)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "total", - description: "Total number of results. If the status is Running this number may continue to increase", - return_type: Number( - TypeInfo { - name: "total", - is_optional: false, - is_list: false, - description: Some( - "Total number of results. If the status is Running this number may continue to increase", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "results", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "id", + is_optional: false, + is_list: false, + description: Some( + "ID of the search job", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "limit", + is_optional: true, + is_list: false, + description: Some( + "max number of results to return. 0 or negative means no limit", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "offset", + is_optional: true, + is_list: false, + description: Some( + "result to start at. A negative number means count backwards (e.g. -2 returns the 2 most recent results)", + ), + type_description: None, + }, + ), + ], + }, + ), + Object( + TypeWithName { + name: "Result", + types: [ + String( + TypeInfo { + name: "descrLink", + is_optional: false, + is_list: false, + description: Some( + "URL of the torrent's description page", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "fileName", + is_optional: false, + is_list: false, + description: Some( + "Name of the file", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "fileSize", + is_optional: false, + is_list: false, + description: Some( + "Size of the file in Bytes", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "fileUrl", + is_optional: false, + is_list: false, + description: Some( + "Torrent download link (usually either .torrent file or magnet link)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "nbLeechers", + is_optional: false, + is_list: false, + description: Some( + "Number of leechers", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "nbSeeders", + is_optional: false, + is_list: false, + description: Some( + "Number of seeders", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "siteUrl", + is_optional: false, + is_list: false, + description: Some( + "URL of the torrent site", + ), + type_description: None, + }, + ), + ], + }, + ), + Response( + TypeWithoutName { + types: [ + Object( + Object { + type_info: TypeInfo { + name: "results", + is_optional: false, + is_list: false, + description: Some( + "Array of result objects- see table below", + ), + type_description: None, + }, + ref_type: "Result", + }, + ), + String( + TypeInfo { + name: "status", + is_optional: false, + is_list: false, + description: Some( + "Current status of the search job (either Running or Stopped)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "total", + is_optional: false, + is_list: false, + description: Some( + "Total number of results. If the status is Running this number may continue to increase", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "delete", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - Number( - TypeInfo { - name: "id", - is_optional: false, - is_list: false, - description: Some( - "ID of the search job", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "delete", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "id", + is_optional: false, + is_list: false, + description: Some( + "ID of the search job", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "plugins", description: Some( "The response is a JSON array of objects containing the following fields\n\n\n```JSON\n[\n {\n \"enabled\": true,\n \"fullName\": \"Legit Torrents\",\n \"name\": \"legittorrents\",\n \"supportedCategories\": [{\n \"id\": \"all\",\n \"name\": \"All categories\"\n }, {\n \"id\": \"anime\",\n \"name\": \"Anime\"\n }, {\n \"id\": \"books\",\n \"name\": \"Books\"\n }, {\n \"id\": \"games\",\n \"name\": \"Games\"\n }, {\n \"id\": \"movies\",\n \"name\": \"Movies\"\n }, {\n \"id\": \"music\",\n \"name\": \"Music\"\n }, {\n \"id\": \"tv\",\n \"name\": \"TV shows\"\n }],\n \"url\": \"http://www.legittorrents.info\",\n \"version\": \"2.3\"\n }\n]\n```", ), - parameters: None, - return_type: Some( - ReturnType { - is_list: true, - parameters: [ - ReturnTypeParameter { - name: "enabled", - description: "Whether the plugin is enabled", - return_type: Bool( - TypeInfo { - name: "enabled", - is_optional: false, - is_list: false, - description: Some( - "Whether the plugin is enabled", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "fullName", - description: "Full name of the plugin", - return_type: String( - TypeInfo { - name: "fullName", - is_optional: false, - is_list: false, - description: Some( - "Full name of the plugin", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "name", - description: "Short name of the plugin", - return_type: String( - TypeInfo { - name: "name", - is_optional: false, - is_list: false, - description: Some( - "Short name of the plugin", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "supportedCategories", - description: "List of category objects", - return_type: StringArray( - TypeInfo { - name: "supportedCategories", - is_optional: false, - is_list: false, - description: Some( - "List of category objects", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "url", - description: "URL of the torrent site", - return_type: String( - TypeInfo { - name: "url", - is_optional: false, - is_list: false, - description: Some( - "URL of the torrent site", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "version", - description: "Installed version of the plugin", - return_type: String( - TypeInfo { - name: "version", - is_optional: false, - is_list: false, - description: Some( - "Installed version of the plugin", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "plugins", + types: CompositeTypes { + composite_types: [ + Response( + TypeWithoutName { + types: [ + Bool( + TypeInfo { + name: "enabled", + is_optional: false, + is_list: false, + description: Some( + "Whether the plugin is enabled", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "fullName", + is_optional: false, + is_list: false, + description: Some( + "Full name of the plugin", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "name", + is_optional: false, + is_list: false, + description: Some( + "Short name of the plugin", + ), + type_description: None, + }, + ), + StringArray( + TypeInfo { + name: "supportedCategories", + is_optional: false, + is_list: false, + description: Some( + "List of category objects", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "url", + is_optional: false, + is_list: false, + description: Some( + "URL of the torrent site", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "version", + is_optional: false, + is_list: false, + description: Some( + "Installed version of the plugin", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "installPlugin", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "sources", - is_optional: false, - is_list: false, - description: Some( - "Url or file path of the plugin to install (e.g. \"[https://raw.githubusercontent.com/qbittorrent/search-plugins/master/nova3/engines/legittorrents.py](https://raw.githubusercontent.com/qbittorrent/search-plugins/master/nova3/engines/legittorrents.py)\"). Supports multiple sources separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "installPlugin", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "sources", + is_optional: false, + is_list: false, + description: Some( + "Url or file path of the plugin to install (e.g. \"[https://raw.githubusercontent.com/qbittorrent/search-plugins/master/nova3/engines/legittorrents.py](https://raw.githubusercontent.com/qbittorrent/search-plugins/master/nova3/engines/legittorrents.py)\"). Supports multiple sources separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "uninstallPlugin", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "names", - is_optional: false, - is_list: false, - description: Some( - "Name of the plugin to uninstall (e.g. \"legittorrents\"). Supports multiple names separated by \\", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "uninstallPlugin", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "names", + is_optional: false, + is_list: false, + description: Some( + "Name of the plugin to uninstall (e.g. \"legittorrents\"). Supports multiple names separated by \\", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "enablePlugin", description: None, - parameters: Some( - ApiParameters { - mandatory: [ - String( - TypeInfo { - name: "names", - is_optional: false, - is_list: false, - description: Some( - "Name of the plugin to enable/disable (e.g. \"legittorrents\"). Supports multiple names separated by \\", - ), - type_description: None, - }, - ), - Bool( - TypeInfo { - name: "enable", - is_optional: false, - is_list: false, - description: Some( - "Whether the plugins should be enabled", - ), - type_description: None, - }, - ), - ], - optional: [], - }, - ), - return_type: None, url: "enablePlugin", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + String( + TypeInfo { + name: "names", + is_optional: false, + is_list: false, + description: Some( + "Name of the plugin to enable/disable (e.g. \"legittorrents\"). Supports multiple names separated by \\", + ), + type_description: None, + }, + ), + Bool( + TypeInfo { + name: "enable", + is_optional: false, + is_list: false, + description: Some( + "Whether the plugins should be enabled", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, }, ApiMethod { name: "updatePlugins", description: None, - parameters: None, - return_type: None, url: "updatePlugins", + types: CompositeTypes { + composite_types: [], + }, }, ], description: Some( diff --git a/qbittorrent-web-api-gen/src/generate/group/mod.rs b/qbittorrent-web-api-gen/src/generate/group/mod.rs index bf4c911..d4bb2f0 100644 --- a/qbittorrent-web-api-gen/src/generate/group/mod.rs +++ b/qbittorrent-web-api-gen/src/generate/group/mod.rs @@ -1,14 +1,11 @@ -mod method; - -use crate::parser; +use crate::{parser, types}; use case::CaseExt; +use proc_macro2::{Ident, TokenStream}; use quote::quote; -use self::method::generate_methods; - use super::{skeleton::auth_ident, util}; -pub fn generate_groups(groups: Vec) -> proc_macro2::TokenStream { +pub fn generate_groups(groups: Vec) -> TokenStream { let gr = groups .iter() // implemented manually @@ -20,30 +17,410 @@ pub fn generate_groups(groups: Vec) -> proc_macro2::TokenStrea } } -fn generate_group(group: &parser::ApiGroup) -> proc_macro2::TokenStream { - let group_name_camel = util::to_ident(&group.name.to_camel()); - let group_name_snake = util::to_ident(&group.name.to_snake()); - let auth = auth_ident(); - let methods = generate_methods(group, &auth, &group_name_camel); - - let group_method = util::add_docs( - &group.description, - quote! { - pub fn #group_name_snake(&self) -> #group_name_camel { - #group_name_camel::new(self) - } - }, - ); +fn generate_group(group: &parser::ApiGroup) -> TokenStream { + let group = group.generate(); quote! { - pub struct #group_name_camel<'a> { - auth: &'a #auth, + #group + } +} + +impl parser::ApiGroup { + fn generate(&self) -> TokenStream { + let struct_name = self.struct_name(); + let group_name_snake = self.name_snake(); + let group_methods = self.generate_group_methods(); + + let group_struct = self.group_struct(); + let group_factory = self.group_factory(); + let auth = auth_ident(); + + quote! { + pub mod #group_name_snake { + impl <'a> #struct_name<'a> { + pub fn new(auth: &'a super::#auth) -> Self { + Self { auth } + } + } + + #group_struct + #group_factory + + #(#group_methods)* + } } + } - #methods + fn generate_group_methods(&self) -> Vec { + let group_methods = self.group_methods(); + group_methods + .iter() + .map(|group_method| group_method.generate_method()) + .collect() + } - impl #auth { - #group_method + fn group_factory(&self) -> TokenStream { + let struct_name = self.struct_name(); + let name_snake = self.name_snake(); + let auth = auth_ident(); + + util::add_docs( + &self.description, + quote! { + impl super::#auth { + pub fn #name_snake(&self) -> #struct_name { + #struct_name::new(self) + } + } + }, + ) + } + + fn group_struct(&self) -> TokenStream { + let struct_name = self.struct_name(); + let auth = auth_ident(); + + quote! { + #[derive(Debug)] + pub struct #struct_name<'a> { + auth: &'a super::#auth, + } + } + } + + fn group_methods(&self) -> Vec { + self.methods + .iter() + .map(|method| GroupMethod::new(self, method)) + .collect() + } + + fn struct_name(&self) -> Ident { + self.name_camel() + } + + fn name_camel(&self) -> Ident { + util::to_ident(&self.name.to_camel()) + } + + fn name_snake(&self) -> Ident { + util::to_ident(&self.name.to_snake()) + } +} + +impl parser::ApiMethod { + fn structs(&self) -> TokenStream { + let objects = self.types.objects(); + let structs = objects.iter().map(|obj| obj.generate_struct()); + + quote! { + #(#structs)* + } + } + + fn enums(&self) -> TokenStream { + let enums = self.types.enums(); + let generated_enums = enums.iter().map(|e| e.generate()); + + quote! { + #(#generated_enums)* + } + } + + fn name_camel(&self) -> Ident { + util::to_ident(&self.name.to_camel()) + } + + fn name_snake(&self) -> Ident { + util::to_ident(&self.name.to_snake()) + } +} + +impl parser::TypeWithName { + fn generate_struct(&self) -> TokenStream { + let fields = self.types.iter().map(|obj| obj.generate_struct_field()); + let name = util::to_ident(&self.name); + + quote! { + #[derive(Debug, serde::Deserialize)] + pub struct #name { + #(#fields,)* + } + } + } +} + +impl types::Type { + fn generate_struct_field(&self) -> TokenStream { + let name_snake = self.name_snake(); + let type_name = util::to_ident(&self.to_owned_type()); + let orig_name = self.name(); + + util::add_docs( + &self.get_type_info().description, + quote! { + #[serde(rename = #orig_name)] + #name_snake: #type_name + }, + ) + } + + fn name(&self) -> String { + self.get_type_info().name.clone() + } + + fn name_camel(&self) -> Ident { + util::to_ident(&self.name().to_camel()) + } + + fn name_snake(&self) -> Ident { + util::to_ident(&self.name().to_snake()) + } +} + +impl parser::Enum { + fn generate(&self) -> TokenStream { + let values = self.values.iter().map(|enum_value| enum_value.generate()); + let name = util::to_ident(&self.name); + + quote! { + #[allow(clippy::enum_variant_names)] + #[derive(Debug, serde::Deserialize, PartialEq, Eq)] + pub enum #name { + #(#values,)* + } + } + } +} + +impl parser::EnumValue { + fn generate(&self) -> TokenStream { + util::add_docs(&self.description, self.generate_field()) + } + + fn generate_field(&self) -> TokenStream { + let orig_name = self.original_value.clone(); + + // special enum value which does not follow conventions + if orig_name == "\"/path/to/download/to\"" { + quote! { + PathToDownloadTo(String) + } + } else { + let name_camel = self.name_camel(); + quote! { + #[serde(rename = #orig_name)] + #name_camel + } + } + } + + fn name_camel(&self) -> Ident { + util::to_ident(&self.value.to_camel()) + } + + fn name_snake(&self) -> Ident { + util::to_ident(&self.value.to_snake()) + } +} + +#[derive(Debug)] +struct GroupMethod<'a> { + group: &'a parser::ApiGroup, + method: &'a parser::ApiMethod, +} + +impl<'a> GroupMethod<'a> { + fn new(group: &'a parser::ApiGroup, method: &'a parser::ApiMethod) -> Self { + Self { group, method } + } + + fn generate_response_struct(&self) -> TokenStream { + let response = match self.method.types.response() { + Some(res) => res, + None => return quote! {}, + }; + + let struct_fields = response.iter().map(|field| field.generate_struct_field()); + + quote! { + #[derive(Debug, serde::Deserialize)] + pub struct Response { + #(#struct_fields,)* + } + } + } + + fn generate_optional_builder(&self) -> TokenStream { + let optional_params = match self.method.types.optional_parameters() { + Some(params) => params, + None => return quote! {}, + }; + + let builder_methods = optional_params + .iter() + .map(|param| param.generate_optional_builder_method_with_docs()); + + let group_name = self.group.struct_name(); + let mandatory_params = self.mandatory_parameters(); + let mandatory_param_form_builder = self.mandatory_parameters_as_form_builder(); + let send_method = self.generate_optional_builder_send_method(); + + quote! { + pub struct Builder<'a> { + group: &'a super::#group_name<'a>, + form: reqwest::multipart::Form, + } + + impl<'a> Builder<'a> { + pub fn new(group: &'a super::#group_name, #mandatory_params) -> Self { + let form = reqwest::multipart::Form::new(); + #mandatory_param_form_builder + Self { group, form } + } + + #send_method + + #(#builder_methods)* + } + } + } + + fn generate_optional_builder_send_method(&self) -> TokenStream { + let method_url = format!("/api/v2/{}/{}", self.group.url, self.method.url); + + match self.method.types.response() { + Some(_) => { + quote! { + pub async fn send(self) -> super::super::Result { + let res = self + .group + .auth + .authenticated_client(#method_url) + .multipart(self.form) + .send() + .await? + .json::() + .await?; + + Ok(res) + } + } + } + None => { + quote! { + pub async fn send(self) -> super::super::Result { + let res = self + .group + .auth + .authenticated_client(#method_url) + .multipart(self.form) + .send() + .await? + .text() + .await?; + + Ok(res) + } + } + } + } + } + + fn mandatory_parameters(&self) -> TokenStream { + let mandatory_params = match self.method.types.mandatory_params() { + Some(p) => p, + None => return quote! {}, + }; + + let params = mandatory_params.iter().map(|param| param.to_parameter()); + + quote! { + #(#params),* + } + } + + fn mandatory_parameters_as_form_builder(&self) -> TokenStream { + let mandatory_params = match self.method.types.mandatory_params() { + Some(p) => p, + None => return quote! {}, + }; + + let builder = mandatory_params + .iter() + .map(|param| param.generate_form_builder(quote! { form })); + + quote! { + #(let #builder)* + } + } + + fn generate_method(&self) -> TokenStream { + let method_name = self.method.name_snake(); + let structs = self.method.structs(); + let enums = self.method.enums(); + let builder = self.generate_optional_builder(); + let response_struct = self.generate_response_struct(); + + quote! { + pub mod #method_name { + #structs + #enums + #builder + #response_struct + } + } + } +} + +impl types::Type { + fn generate_optional_builder_method_with_docs(&self) -> TokenStream { + util::add_docs( + &self.get_type_info().description, + self.generate_optional_builder_method(), + ) + } + + fn borrowed_type_ident(&self) -> Ident { + util::to_ident(&self.to_borrowed_type()) + } + + fn to_parameter(&self) -> TokenStream { + let name_snake = self.name_snake(); + let borrowed_type = self.borrowed_type(); + + quote! { #name_snake: #borrowed_type } + } + + fn generate_form_builder(&self, add_to: TokenStream) -> TokenStream { + let name_str = self.name(); + let name_snake = self.name_snake(); + + quote! { + #add_to = #add_to.text(#name_str, #name_snake.to_string()); + } + } + + fn generate_optional_builder_method(&self) -> TokenStream { + let name_snake = self.name_snake(); + let borrowed_type = self.borrowed_type(); + let form_builder = self.generate_form_builder(quote! { self.form }); + + quote! { + pub fn #name_snake(mut self, #name_snake: #borrowed_type) -> Self { + #form_builder; + self + } + } + } + + fn borrowed_type(&self) -> TokenStream { + if self.should_borrow() { + let type_ = self.borrowed_type_ident(); + quote! { &#type_ } + } else { + let type_ = self.borrowed_type_ident(); + quote! { #type_ } } } } diff --git a/qbittorrent-web-api-gen/src/generate/skeleton.rs b/qbittorrent-web-api-gen/src/generate/skeleton.rs index fb74c23..e09f91b 100644 --- a/qbittorrent-web-api-gen/src/generate/skeleton.rs +++ b/qbittorrent-web-api-gen/src/generate/skeleton.rs @@ -10,13 +10,7 @@ pub fn generate_skeleton(ident: &syn::Ident) -> proc_macro2::TokenStream { let auth = auth_ident(); quote! { - use reqwest::RequestBuilder; - use serde::Deserialize; - use thiserror::Error; - - use super::#ident; - - impl #ident { + impl super::#ident { /// Creates an authenticated client. /// base_url is the url to the qbittorrent instance, i.e. http://localhost:8080 pub async fn login( @@ -61,7 +55,7 @@ pub fn generate_skeleton(ident: &syn::Ident) -> proc_macro2::TokenStream { } #[allow(clippy::enum_variant_names)] - #[derive(Debug, Error)] + #[derive(Debug, thiserror::Error)] pub enum Error { #[error("failed to parse auth cookie")] AuthCookieParseError, @@ -81,7 +75,7 @@ pub fn generate_skeleton(ident: &syn::Ident) -> proc_macro2::TokenStream { } impl #auth { - fn authenticated_client(&self, url: &str) -> RequestBuilder { + fn authenticated_client(&self, url: &str) -> reqwest::RequestBuilder { let url = format!("{}{}", self.base_url, url); let cookie = self.auth_cookie.clone(); diff --git a/qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.check b/qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.check new file mode 100644 index 0000000..165730d --- /dev/null +++ b/qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.check @@ -0,0 +1,37 @@ +ApiMethod { + name: "foo", + description: None, + url: "foo", + types: CompositeTypes { + composite_types: [ + Enum( + Enum { + name: "ScanDirs", + values: [ + EnumValue { + description: Some( + "Download to the monitored folder", + ), + value: "DownloadToTheMonitoredFolder", + original_value: "0", + }, + EnumValue { + description: Some( + "Download to the default save path", + ), + value: "DownloadToTheDefaultSavePath", + original_value: "1", + }, + EnumValue { + description: Some( + "Download to this path", + ), + value: "\"/path/to/download/to\"", + original_value: "\"/path/to/download/to\"", + }, + ], + }, + ), + ], + }, +} \ No newline at end of file diff --git a/qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.md b/qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.md new file mode 100644 index 0000000..75f74c6 --- /dev/null +++ b/qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.md @@ -0,0 +1,12 @@ +## Testing + +Name: `foo` + +Possible values of `scan_dirs`: + +Value | Description +----------------------------|------------ +`0` | Download to the monitored folder +`1` | Download to the default save path +`"/path/to/download/to"` | Download to this path + diff --git a/qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.tree b/qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.tree new file mode 100644 index 0000000..6a8f814 --- /dev/null +++ b/qbittorrent-web-api-gen/src/parser/group/method/method_tests/enum.tree @@ -0,0 +1,67 @@ +TokenTree { + title: None, + content: [], + children: [ + TokenTree { + title: Some( + "Testing", + ), + content: [ + Text( + "", + ), + Text( + "Name: `foo`", + ), + Text( + "", + ), + Text( + "Possible values of `scan_dirs`:", + ), + Text( + "", + ), + Table( + Table { + header: TableRow { + raw: "Value | Description", + columns: [ + "Value", + "Description", + ], + }, + split: "----------------------------|------------", + rows: [ + TableRow { + raw: "`0` | Download to the monitored folder", + columns: [ + "0", + "Download to the monitored folder", + ], + }, + TableRow { + raw: "`1` | Download to the default save path", + columns: [ + "1", + "Download to the default save path", + ], + }, + TableRow { + raw: "`\"/path/to/download/to\"` | Download to this path", + columns: [ + "\"/path/to/download/to\"", + "Download to this path", + ], + }, + ], + }, + ), + Text( + "", + ), + ], + children: [], + }, + ], +} \ No newline at end of file diff --git a/qbittorrent-web-api-gen/src/parser/group/method/method_tests/search_result.check b/qbittorrent-web-api-gen/src/parser/group/method/method_tests/search_result.check index 5609adf..72dd726 100644 --- a/qbittorrent-web-api-gen/src/parser/group/method/method_tests/search_result.check +++ b/qbittorrent-web-api-gen/src/parser/group/method/method_tests/search_result.check @@ -3,98 +3,174 @@ ApiMethod { description: Some( "The response is a JSON object with the following fields\n\n\n\n\nExample:\n\n```JSON\n{\n \"results\": [\n {\n \"descrLink\": \"http://www.legittorrents.info/index.php?page=torrent-details&id=8d5f512e1acb687029b8d7cc6c5a84dce51d7a41\",\n \"fileName\": \"Ubuntu-10.04-32bit-NeTV.ova\",\n \"fileSize\": -1,\n \"fileUrl\": \"http://www.legittorrents.info/download.php?id=8d5f512e1acb687029b8d7cc6c5a84dce51d7a41&f=Ubuntu-10.04-32bit-NeTV.ova.torrent\",\n \"nbLeechers\": 1,\n \"nbSeeders\": 0,\n \"siteUrl\": \"http://www.legittorrents.info\"\n },\n {\n \"descrLink\": \"http://www.legittorrents.info/index.php?page=torrent-details&id=d5179f53e105dc2c2401bcfaa0c2c4936a6aa475\",\n \"fileName\": \"mangOH-Legato-17_06-Ubuntu-16_04.ova\",\n \"fileSize\": -1,\n \"fileUrl\": \"http://www.legittorrents.info/download.php?id=d5179f53e105dc2c2401bcfaa0c2c4936a6aa475&f=mangOH-Legato-17_06-Ubuntu-16_04.ova.torrent\",\n \"nbLeechers\": 0,\n \"nbSeeders\": 59,\n \"siteUrl\": \"http://www.legittorrents.info\"\n }\n ],\n \"status\": \"Running\",\n \"total\": 2\n}\n```", ), - parameters: Some( - ApiParameters { - mandatory: [ - Number( - TypeInfo { - name: "id", - is_optional: false, - is_list: false, - description: Some( - "ID of the search job", - ), - type_description: None, - }, - ), - ], - optional: [ - Number( - TypeInfo { - name: "limit", - is_optional: true, - is_list: false, - description: Some( - "max number of results to return. 0 or negative means no limit", - ), - type_description: None, - }, - ), - Number( - TypeInfo { - name: "offset", - is_optional: true, - is_list: false, - description: Some( - "result to start at. A negative number means count backwards (e.g. -2 returns the 2 most recent results)", - ), - type_description: None, - }, - ), - ], - }, - ), - return_type: Some( - ReturnType { - is_list: false, - parameters: [ - ReturnTypeParameter { - name: "results", - description: "Array of result objects- see table below", - return_type: StringArray( - TypeInfo { - name: "results", - is_optional: false, - is_list: false, - description: Some( - "Array of result objects- see table below", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "status", - description: "Current status of the search job (either Running or Stopped)", - return_type: String( - TypeInfo { - name: "status", - is_optional: false, - is_list: false, - description: Some( - "Current status of the search job (either Running or Stopped)", - ), - type_description: None, - }, - ), - }, - ReturnTypeParameter { - name: "total", - description: "Total number of results. If the status is Running this number may continue to increase", - return_type: Number( - TypeInfo { - name: "total", - is_optional: false, - is_list: false, - description: Some( - "Total number of results. If the status is Running this number may continue to increase", - ), - type_description: None, - }, - ), - }, - ], - }, - ), url: "results", + types: CompositeTypes { + composite_types: [ + Parameters( + TypeWithoutName { + types: [ + Number( + TypeInfo { + name: "id", + is_optional: false, + is_list: false, + description: Some( + "ID of the search job", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "limit", + is_optional: true, + is_list: false, + description: Some( + "max number of results to return. 0 or negative means no limit", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "offset", + is_optional: true, + is_list: false, + description: Some( + "result to start at. A negative number means count backwards (e.g. -2 returns the 2 most recent results)", + ), + type_description: None, + }, + ), + ], + }, + ), + Object( + TypeWithName { + name: "Result", + types: [ + String( + TypeInfo { + name: "descrLink", + is_optional: false, + is_list: false, + description: Some( + "URL of the torrent's description page", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "fileName", + is_optional: false, + is_list: false, + description: Some( + "Name of the file", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "fileSize", + is_optional: false, + is_list: false, + description: Some( + "Size of the file in Bytes", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "fileUrl", + is_optional: false, + is_list: false, + description: Some( + "Torrent download link (usually either .torrent file or magnet link)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "nbLeechers", + is_optional: false, + is_list: false, + description: Some( + "Number of leechers", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "nbSeeders", + is_optional: false, + is_list: false, + description: Some( + "Number of seeders", + ), + type_description: None, + }, + ), + String( + TypeInfo { + name: "siteUrl", + is_optional: false, + is_list: false, + description: Some( + "URL of the torrent site", + ), + type_description: None, + }, + ), + ], + }, + ), + Response( + TypeWithoutName { + types: [ + Object( + Object { + type_info: TypeInfo { + name: "results", + is_optional: false, + is_list: false, + description: Some( + "Array of result objects- see table below", + ), + type_description: None, + }, + ref_type: "Result", + }, + ), + String( + TypeInfo { + name: "status", + is_optional: false, + is_list: false, + description: Some( + "Current status of the search job (either Running or Stopped)", + ), + type_description: None, + }, + ), + Number( + TypeInfo { + name: "total", + is_optional: false, + is_list: false, + description: Some( + "Total number of results. If the status is Running this number may continue to increase", + ), + type_description: None, + }, + ), + ], + }, + ), + ], + }, } \ No newline at end of file diff --git a/qbittorrent-web-api-gen/src/parser/group/method/mod.rs b/qbittorrent-web-api-gen/src/parser/group/method/mod.rs index 1099227..5f03a1a 100644 --- a/qbittorrent-web-api-gen/src/parser/group/method/mod.rs +++ b/qbittorrent-web-api-gen/src/parser/group/method/mod.rs @@ -1,18 +1,75 @@ mod description; -mod return_type; +// mod return_type; mod url; use crate::{md_parser, types}; -pub use return_type::ReturnType; -use std::collections::HashMap; +use case::CaseExt; +use regex::Regex; +use std::collections::{BTreeMap, HashMap}; #[derive(Debug)] pub struct ApiMethod { pub name: String, pub description: Option, - pub parameters: Option, - pub return_type: Option, pub url: String, + pub types: CompositeTypes, +} + +#[derive(Debug)] +pub struct CompositeTypes { + pub composite_types: Vec, +} + +impl CompositeTypes { + pub fn new(tables: &Tables) -> Self { + Self { + composite_types: tables.get_all_tables_as_types(), + } + } + + pub fn parameters(&self) -> Option<&Vec> { + self.composite_types.iter().find_map(|type_| match type_ { + CompositeType::Parameters(p) => Some(&p.types), + _ => None, + }) + } + + pub fn optional_parameters(&self) -> Option> { + self.parameters() + .map(|params| params.iter().filter(|param| param.is_optional()).collect()) + } + + pub fn mandatory_params(&self) -> Option> { + self.parameters() + .map(|params| params.iter().filter(|param| !param.is_optional()).collect()) + } + + pub fn response(&self) -> Option<&Vec> { + self.composite_types.iter().find_map(|type_| match type_ { + CompositeType::Response(p) => Some(&p.types), + _ => None, + }) + } + + pub fn objects(&self) -> Vec<&TypeWithName> { + self.composite_types + .iter() + .filter_map(|type_| match type_ { + CompositeType::Object(p) => Some(p), + _ => None, + }) + .collect() + } + + pub fn enums(&self) -> Vec<&Enum> { + self.composite_types + .iter() + .filter_map(|type_| match type_ { + CompositeType::Enum(p) => Some(p), + _ => None, + }) + .collect() + } } #[derive(Debug)] @@ -21,24 +78,86 @@ pub struct ApiParameters { pub optional: Vec, } -impl ApiParameters { - fn new(params: Vec) -> Self { - let (mandatory, optional) = params.into_iter().fold( - (vec![], vec![]), - |(mut mandatory, mut optional), parameter| { - if parameter.get_type_info().is_optional { - optional.push(parameter); - } else { - mandatory.push(parameter); - } +#[derive(Debug)] +pub enum CompositeType { + Enum(Enum), + Object(TypeWithName), + Response(TypeWithoutName), + Parameters(TypeWithoutName), +} - (mandatory, optional) - }, - ); +#[derive(Debug)] +pub struct TypeWithName { + pub name: String, + pub types: Vec, +} +#[derive(Debug)] +pub struct TypeWithoutName { + pub types: Vec, +} + +impl TypeWithoutName { + pub fn new(types: Vec) -> Self { + Self { types } + } +} + +impl TypeWithName { + pub fn new(name: &str, types: Vec) -> Self { Self { - mandatory, - optional, + name: name.to_string(), + types, + } + } +} + +#[derive(Debug)] +pub struct Enum { + pub name: String, + pub values: Vec, +} + +#[derive(Debug)] +pub struct EnumValue { + pub description: Option, + pub value: String, + pub original_value: String, +} + +impl Enum { + fn new(name: &str, table: &md_parser::Table) -> Self { + let values = table.rows.iter().map(EnumValue::from).collect(); + + Enum { + name: name.to_string(), + values, + } + } +} + +impl From<&md_parser::TableRow> for EnumValue { + fn from(row: &md_parser::TableRow) -> Self { + let description = row.columns.get(1).cloned(); + let original_value = row.columns[0].clone(); + let value = if original_value.parse::().is_ok() { + let name = description + .clone() + .unwrap() + .replace(' ', "_") + .replace('-', "_") + .replace(',', "_"); + + let re = Regex::new(r#"\(.*\)"#).unwrap(); + re.replace_all(&name, "").to_camel() + } else { + original_value.to_camel() + }; + + EnumValue { + description, + value, + original_value, } } } @@ -56,19 +175,13 @@ impl ApiMethod { fn new(child: &md_parser::TokenTree, name: &str) -> Self { let tables = Tables::from(child); let method_description = child.parse_method_description(); - let return_type = child.parse_return_type(); - // let return_type = tables.return_type().map(|r| ReturnType::new(r)); - let parameters = tables - .get_type_containing("Parameters") - .map(ApiParameters::new); let method_url = child.get_method_url(); ApiMethod { name: name.to_string(), description: method_description, - parameters, - return_type, url: method_url, + types: CompositeTypes::new(&tables), } } } @@ -86,7 +199,7 @@ impl md_parser::TokenTree { impl<'a> From<&'a md_parser::TokenTree> for Tables<'a> { fn from(token_tree: &'a md_parser::TokenTree) -> Self { - let mut tables = HashMap::new(); + let mut tables = BTreeMap::new(); let mut prev_prev: Option<&md_parser::MdContent> = None; let mut prev: Option<&md_parser::MdContent> = None; @@ -110,28 +223,80 @@ impl<'a> From<&'a md_parser::TokenTree> for Tables<'a> { } #[derive(Debug)] -struct Tables<'a> { - tables: HashMap, +pub struct Tables<'a> { + tables: BTreeMap, +} + +impl md_parser::Table { + fn to_enum(&self, input_name: &str) -> Option { + let re = Regex::new(r"^Possible values of `(\w+)`$").unwrap(); + + if !re.is_match(input_name) { + return None; + } + + Some(CompositeType::Enum(Enum::new( + &Self::regex_to_name(&re, input_name), + self, + ))) + } + + fn to_object(&self, input_name: &str) -> Option { + let re = Regex::new(r"^(\w+) object$").unwrap(); + + if !re.is_match(input_name) { + return None; + } + + Some(CompositeType::Object(TypeWithName::new( + &Self::regex_to_name(&re, input_name), + self.to_types(), + ))) + } + + fn to_response(&self, input_name: &str) -> Option { + if !input_name.starts_with("The response is a") { + return None; + } + + Some(CompositeType::Response(TypeWithoutName::new( + self.to_types(), + ))) + } + + fn to_parameters(&self, input_name: &str) -> Option { + if !input_name.starts_with("Parameters") { + return None; + } + + Some(CompositeType::Parameters(TypeWithoutName::new( + self.to_types(), + ))) + } + + fn to_composite_type(&self, input_name: &str) -> Option { + self.to_enum(input_name) + .or_else(|| self.to_response(input_name)) + .or_else(|| self.to_object(input_name)) + .or_else(|| self.to_parameters(input_name)) + } + + fn regex_to_name(re: &Regex, input_name: &str) -> String { + re.captures(input_name) + .unwrap() + .get(1) + .unwrap() + .as_str() + .to_string() + .to_camel() + } } impl<'a> Tables<'a> { - fn get_type_containing(&self, name: &str) -> Option> { - self.get_type_containing_as_table(name) - .map(|table| table.to_types()) - } - - fn get_type_containing_as_table(&self, name: &str) -> Option<&md_parser::Table> { - self.get_all_type_containing_as_table(name) - .iter() - .map(|(_, table)| *table) - .find(|_| true) - } - - fn get_all_type_containing_as_table(&self, name: &str) -> HashMap { + fn get_all_tables_as_types(&self) -> Vec { self.tables .iter() - .filter(|(key, _)| key.contains(name)) - .map(|(k, table)| (k.clone(), *table)) + .flat_map(|(k, v)| v.to_composite_type(k)) .collect() } } @@ -207,8 +372,8 @@ mod tests { use std::path::Path; let input = include_str!(concat!(TEST_DIR!(), "/", $test_file, ".md")); - let tree = ApiMethod::try_new(input); - let api_method = parse_api_method(&tree.children[0]).unwrap(); + let tree = TokenTreeFactory::create(input); + let api_method = ApiMethod::try_new(&tree.children[0]).unwrap(); let tree_as_str = format!("{tree:#?}"); let api_method_as_str = format!("{api_method:#?}"); @@ -242,4 +407,9 @@ mod tests { fn search_result() { run_test!("search_result"); } + + #[test] + fn enum_test() { + run_test!("enum"); + } } diff --git a/qbittorrent-web-api-gen/src/types.rs b/qbittorrent-web-api-gen/src/types.rs index d56f58b..b216cc2 100644 --- a/qbittorrent-web-api-gen/src/types.rs +++ b/qbittorrent-web-api-gen/src/types.rs @@ -1,5 +1,8 @@ use std::collections::HashMap; +use case::CaseExt; +use regex::RegexBuilder; + #[derive(Debug, Clone)] pub struct TypeDescriptions { pub value: String, @@ -39,15 +42,22 @@ impl TypeInfo { } #[derive(Debug, Clone)] -pub struct TypeWithRef { +pub struct Object { pub type_info: TypeInfo, pub ref_type: String, } #[derive(Debug, Clone)] -pub struct ComplexObject { +pub struct Enum { pub type_info: TypeInfo, - pub fields: Vec, + pub values: Vec, +} + +#[derive(Debug, Clone)] +pub struct EnumValue { + pub description: Option, + pub key: String, + pub value: String, } pub const OPTIONAL: &str = "_optional_"; @@ -59,8 +69,7 @@ pub enum Type { Bool(TypeInfo), String(TypeInfo), StringArray(TypeInfo), - Object(TypeInfo), - // ComplexObject(ComplexObject), + Object(Object), } impl Type { @@ -72,7 +81,6 @@ impl Type { Type::String(_) => "String".into(), Type::StringArray(_) => "String".into(), Type::Object(_) => "String".into(), - // Type::ComplexObject(_) => panic!("Not implemented for ComplexObject"), } } @@ -88,7 +96,6 @@ impl Type { Type::String(_) => "str".into(), Type::StringArray(_) => "&[str]".into(), Type::Object(_) => "str".into(), - // Type::ComplexObject(_) => panic!("Not implemented for ComplexObject"), } } @@ -96,6 +103,10 @@ impl Type { matches!(self, Type::String(_) | Type::Object(_)) } + pub fn is_optional(&self) -> bool { + self.get_type_info().is_optional + } + pub fn get_type_info(&self) -> &TypeInfo { match self { Type::Number(t) => t, @@ -103,8 +114,7 @@ impl Type { Type::Bool(t) => t, Type::String(t) => t, Type::StringArray(t) => t, - Type::Object(t) => t, - // Type::ComplexObject(ComplexObject { type_info, .. }) => type_info, + Type::Object(t) => &t.type_info, } } @@ -132,46 +142,54 @@ impl Type { ) }; + let create_object_type = |name: &str| { + Some(Type::Object(Object { + type_info: create_type_info(), + ref_type: name.to_camel(), + })) + }; + match type_as_str { "bool" => Some(Type::Bool(create_type_info())), "integer" | "number" | "int" => Some(Type::Number(create_type_info())), "string" => Some(Type::String(create_type_info())), - "array" => Some(Type::StringArray(create_type_info())), - // "array" => description - // .clone() - // .and_then(|ref desc| get_ref_type(desc)) - // .map(|ref_type| { - // Type::ObjectArray(TypeWithRef { - // type_info: create_type_info(), - // ref_type, - // }) - // }) - // .or_else(|| Some(Type::StringArray(create_type_info()))), - "object" => Some(Type::Object(create_type_info())), + "array" => description + .extract_type() + .and_then(|t| create_object_type(&t)) + .or_else(|| Some(Type::StringArray(create_type_info()))), "float" => Some(Type::Float(create_type_info())), - _ => None, + name => create_object_type(name), } } } -// fn get_ref_type(desc: &str) -> Option { -// let re = RegexBuilder::new(r".*array of (\w+)\s?.*") -// .case_insensitive(true) -// .build() -// .unwrap(); +trait ExtractType { + fn extract_type(&self) -> Option; +} -// re.captures(desc) -// .and_then(|captures| captures.get(1)) -// .map(|m| m.as_str().to_owned()) -// } +impl ExtractType for Option { + fn extract_type(&self) -> Option { + self.as_ref().and_then(|t| { + let re = RegexBuilder::new(r".*Array of (\w+) objects.*") + .case_insensitive(true) + .build() + .unwrap(); + + let cap = re.captures(t)?; + + cap.get(1).map(|m| m.as_str().to_camel()) + }) + } +} #[cfg(test)] mod tests { - // use super::*; + use super::*; - // #[test] - // fn should_parse_object_array() { - // let ref_type = get_ref_type("Array of result objects- see table below"); - // assert_eq!("result", ref_type.unwrap()); - // } + #[test] + fn test_regex() { + let input = Some("Array of result objects- see table below".to_string()); + let res = input.extract_type(); + assert_eq!(res.unwrap(), "Result"); + } } diff --git a/qbittorrent-web-api-gen/tests/search_types.rs b/qbittorrent-web-api-gen/tests/search_types.rs index f4000e0..efd57a2 100644 --- a/qbittorrent-web-api-gen/tests/search_types.rs +++ b/qbittorrent-web-api-gen/tests/search_types.rs @@ -11,10 +11,11 @@ struct Api {} async fn main() -> Result<()> { let api = Api::login(BASE_URL, USERNAME, PASSWORD).await?; - let _ = api.search().plugins().await?; - let _ = api.search().results(1).send().await?; - let _ = api.search().delete(1).await?; let _ = api.search().install_plugin("https://raw.githubusercontent.com/qbittorrent/search-plugins/master/nova3/engines/legittorrents.py").await?; + let plugins = api.search().plugins().await?; + eprintln!("{:?}", plugins); + // let _ = api.search().results(1).send().await?; + // let _ = api.search().delete(1).await?; Ok(()) }