kscript 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 063aeed0edf967058b4f711054a6faf7bd1d9b4648944e9d8087e53d4638a2a9
4
- data.tar.gz: c1bd30a10d30507dd8be6390d44f65c9e55a68f7a0c8079f55812156143961db
3
+ metadata.gz: 29d10d822185ae11ba6256352e357068bb95a26a5400e18182c08831d7dc955f
4
+ data.tar.gz: bd8acb2d087a1818a1cd8b60e60f2c4eb0951b6eb1e50311a8d8bfa9ba736ec9
5
5
  SHA512:
6
- metadata.gz: 066b7dd8b0d95de5e5391d1317ff9c86eb7c1c4b0aa4adcb52da652f9d4aebf055b6bc1ea9aa9f1e4b23397789232967bf4739264cdf71d92791f1dcb69c0b65
7
- data.tar.gz: 61de9beedfa35069b788c6b6e52c520b01c83bf01d715dad3d0c0d4b91b18ec5e8a2fed65fed589ffbe66774e271e5d322bd039e908e563f81831472b88a47a2
6
+ metadata.gz: ffd635c5898e3a7362ca4a6b16f3f483a69d61478aee895d90d58cdf403f181a3a0a0b7195cb844c8c77d677d10e51449378d5447d328a520f1feb222ea9405b
7
+ data.tar.gz: 4542801758b3d3e9b910f63cfa4e5f5ed389a5bfd180fafa23801813d9f029431484846215d5ff9d0d648c1a566af3884a62b5e8656f7dfc25f1ea6dc4e0ad90
data/README.md CHANGED
@@ -16,6 +16,23 @@ _ ,< _(__ )/ /__ _ / _ / __ /_/ / /_
16
16
 
17
17
  ---
18
18
 
19
+ ## 🗺️ 架构图
20
+
21
+ ```mermaid
22
+ graph TD
23
+ A[用户终端/脚本] -->|命令行| B(kscript CLI)
24
+ B --> C[插件注册与分发]
25
+ B --> D[日志系统]
26
+ B --> E[配置加载]
27
+ B --> F[Shell补全生成]
28
+ B --> G[结构化日志/美化输出]
29
+ B --> H[CI/CD自动发布]
30
+ F --> I1[zsh补全脚本]
31
+ F --> I2[bash补全脚本]
32
+ H --> J[GitHub Actions]
33
+ J --> K[RubyGems发布]
34
+ ```
35
+
19
36
  ## ✨ 特性亮点
20
37
  - 统一 CLI 框架,所有命令一键调用,美化输出
21
38
  - 插件化架构,业务命令即插件,易扩展、易维护
@@ -97,91 +114,32 @@ kscript port_scan 192.168.1.1 --log-level=debug
97
114
  | project | `vcs_cleaner` | `kscript vcs_cleaner ~/projects/src` | `[src_path]` | Clean old source code versions, keep N latest. |
98
115
  | project | `file_rename` | `kscript file_rename foo bar ./src` | `<pattern> <replacement> [path]` | Batch rename files by pattern. |
99
116
  | system | `shell_helper` | `kscript shell_helper 'ls'` | `[subcommand] [args...]` | Query shell command usage and cheatsheets. |
100
- | system | `lvm_manage` | `kscript lvm_manage /dev/sda2 /mnt/data` | `<device> <mount_point>` | Mount and manage Linux LVM volumes. |
101
- | macos | `mac_status` | `kscript mac_status` | | Show macOS system resource monitor report. |
102
- | macos | `mac_optimize` | `kscript mac_optimize` | | Optimize macOS system performance. |
103
- | media | `ffmpeg_install` | `kscript ffmpeg_install 6.0` | `[version]` | Install and verify FFmpeg on Linux. |
104
- | elastic | `elastic_cert_finger` | `kscript elastic_cert_finger ./ca.crt` | `<cert_file>` | Generate Elasticsearch certificate SHA256 fingerprint. |
105
- | elastic | `kibana_manage` | `kscript kibana_manage export --host=localhost --index=log-*` | `[subcommand] [options]` | Kibana automation: space, index, user, role management. |
106
- | ci | `jenkins_manage` | `kscript jenkins_manage list --host=jenkins.local` | `[subcommand] [options]` | Jenkins job export/import automation. |
107
- | cloud | `aws_s3` | `kscript aws_s3 --file local.txt --bucket my-bucket ...` | `--file --bucket --key --region --access_key --secret_key` | Upload a file to AWS S3 for testing. |
108
- | finance | `usd_rate` | `kscript usd_rate CNY` | `[currency_code]` | Get latest USD exchange rates. |
109
-
110
- ---
111
-
112
- ## ⚡ Shell 自动补全 & 配置示例
113
-
114
- - 首次安装/升级自动为 zsh/bash 部署补全脚本,并生成 `~/.kscript/.env` 配置示例
115
- - 补全脚本路径:
116
- - zsh: `~/.zsh/completions/_kscript`
117
- - bash: `~/.bash_completion.d/kscript`
118
- - 配置文件路径:
119
- - `~/.kscript/.env`(自动生成,支持 ENV 变量注释说明)
120
- - 手动生成补全:
121
- ```bash
122
- kscript completion zsh > ~/.zsh/completions/_kscript
123
- kscript completion bash > ~/.bash_completion.d/kscript
124
- ```
125
-
126
- ---
127
-
128
- ## ⚙️ 全局配置(.env 格式)
129
-
130
- 所有全局参数均通过 `~/.kscript/.env` 文件(自动生成,标准 .env 格式)或环境变量注入。例如:
131
-
132
- ```env
133
- # AWS S3 upload config
134
- AWS_BUCKET=my-bucket
135
- AWS_REGION=ap-northeast-1
136
- AWS_ACCESS_KEY_ID=xxx
137
- AWS_SECRET_ACCESS_KEY=yyy
138
-
139
- # Logging config
140
- KSCRIPT_LOG_LEVEL=info
141
- LOG=1
142
- ```
143
- ---
144
-
145
- ## 🧑‍💻 插件开发规范
146
- - 插件文件统一放在 `lib/kscript/plugins/kk_xxx_utils.rb`
147
- - 类名如 `KkApnicIpUtils`,自动注册为 `apnic_ip` 命令
148
- - 支持 `self.description`、`self.usage`、`self.arguments`、`self.group`、`self.author`
149
- - 输出统一用 `logger.kinfo`/`logger.kerror`,支持结构化日志
150
- - 兼容多余参数,避免 ArgumentError
151
- - 依赖统一在主入口 require,插件只需 require 'kscript'
152
-
153
- ---
154
-
155
- ## 🚚 CI/CD 自动发布
156
-
157
- - `.github/workflows/gem-push.yml`:main 分支和 PR 自动构建、tag push 自动发布到 RubyGems
158
- - 需在 GitHub secrets 配置 `RUBYGEMS_API_KEY`
159
- - [CI 状态与历史](https://github.com/kevin197011/kscript/actions/workflows/gem-push.yml)
117
+ | system | `lvm_manage` | `kscript lvm_manage /dev/sda2 /mnt/data` | `<device> <mount_point>` | Mount and manage Linux LVM volumes. |
160
118
 
161
119
  ---
162
120
 
163
- ## 📦 依赖与兼容性
164
-
165
- - Ruby >= 3.0
166
- - 依赖:bcrypt, http, nokogiri, thor, aws-sdk-s3, httpx 等
167
- - 支持 macOS、Linux,部分工具支持 Windows
168
-
169
- ---
121
+ ## 🤝 贡献指南
170
122
 
171
- ## 📄 许可证
123
+ 欢迎提交 Issue 和 Pull Request!请遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范,确保所有代码通过 Linter 检查。详细贡献流程见 CONTRIBUTING.md(如有)。
172
124
 
173
- MIT License. 详见 [LICENSE](LICENSE)。
125
+ ## 常见问题
174
126
 
175
- ---
127
+ - **如何启用 shell 补全?**
128
+ 安装后自动生成补全脚本,重启 shell 或手动 `source ~/.zshrc`/`~/.bashrc`。
129
+ - **如何切换日志模式?**
130
+ 所有命令支持 `--log` 或 `--log-level=debug`,详见上文示例。
131
+ - **如何自定义配置?**
132
+ 编辑 `~/.kscript/.env`,可配置 AWS、日志等参数。
176
133
 
177
- ## 🤝 贡献
134
+ 如有更多问题,欢迎提交 [Issue](https://github.com/kevin197011/kscript/issues)。
178
135
 
179
- 1. Fork & PR
180
- 2. 遵循输出与插件开发规范
181
- 3. 保持文档与代码同步
136
+ ## 📬 联系方式 & 致谢
182
137
 
183
- ---
138
+ - 作者: [kk (kevin197011)](https://github.com/kevin197011)
139
+ - 邮箱: kevin197011@outlook.com
184
140
 
185
- 如需更多示例、插件开发指导或遇到问题,欢迎提 issue 或 PR!
141
+ 感谢所有贡献者和开源依赖项目!
186
142
 
143
+ ## 📄 License
187
144
 
145
+ This project is licensed under the [MIT License](LICENSE).
@@ -8,7 +8,7 @@ _kscript_completions() {
8
8
 
9
9
  # Main command list as array
10
10
  local opts=(
11
- apnic_ip aws_s3 cursor_rules elastic_cert_finger ffmpeg_install file_rename ip_lookup jenkins_manage kibana_manage lvm_manage mac_optimize mac_status port_scan project_scan shell_helper usd_rate vcs_cleaner wg_acl wg_pass
11
+ apnic_ip aws_s3 cursor_rules elastic_cert_finger ffmpeg_install file_rename hn_jobs ip_lookup jenkins_manage kibana_manage lvm_manage mac_optimize mac_status port_scan project_scan shell_helper usd_rate vcs_cleaner wg_acl wg_pass
12
12
  )
13
13
 
14
14
  if [[ ${COMP_CWORD} == 1 ]]; then
@@ -8,6 +8,7 @@ _kscript() {
8
8
  'elastic_cert_finger:kscript command'
9
9
  'ffmpeg_install:kscript command'
10
10
  'file_rename:kscript command'
11
+ 'hn_jobs:kscript command'
11
12
  'ip_lookup:kscript command'
12
13
  'jenkins_manage:kscript command'
13
14
  'kibana_manage:kscript command'
@@ -5,7 +5,7 @@
5
5
  # This software is released under the MIT License.
6
6
  # https://opensource.org/licenses/MIT
7
7
 
8
- # require 'kscript' # 移除此行
8
+ require 'httpx'
9
9
 
10
10
  module Kscript
11
11
  class KkApnicIpUtils < Kscript::Base
@@ -30,8 +30,9 @@ module Kscript
30
30
  end
31
31
  end
32
32
  url = 'https://ftp.apnic.net/stats/apnic/delegated-apnic-latest'
33
- response = HTTP.get(url)
34
- raise "Failed to download the APNIC data. HTTP Status: #{response.status}" unless response.status.success?
33
+ response = HTTPX.get(url)
34
+ response = response.first if response.is_a?(Array)
35
+ raise "Failed to download the APNIC data. HTTP Status: #{response.status}" unless response.status == 200
35
36
 
36
37
  File.write(cache_file, response.body.to_s)
37
38
  logger.kinfo("Data downloaded and saved to #{cache_file}")
@@ -68,7 +68,7 @@ module Kscript
68
68
  # Ensure .gitignore contains .cursor
69
69
  if File.exist?('.gitignore') && File.readlines('.gitignore').none? { |l| l.strip == '.cursor' }
70
70
  logger.kinfo('Adding .cursor to .gitignore...')
71
- File.open('.gitignore', 'a') { |f| f.puts '\n.cursor' }
71
+ File.open('.gitignore', 'a') { |f| f.puts "\n.cursor" }
72
72
  end
73
73
 
74
74
  logger.kinfo("\n✅ Cursor rules deploy completed!")
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2025 Kk
4
+ #
5
+ # This software is released under the MIT License.
6
+ # https://opensource.org/licenses/MIT
7
+
8
+ module Kscript
9
+ class KkHnJobsUtils < Kscript::Base
10
+ HN_JOBS_API = 'https://hacker-news.firebaseio.com/v0/jobstories.json'
11
+ HN_ITEM_API = 'https://hacker-news.firebaseio.com/v0/item'
12
+
13
+ def initialize(*args, **opts)
14
+ super
15
+ @limit = (args[0] || 10).to_i
16
+ end
17
+
18
+ def run(*args, **_opts)
19
+ with_error_handling do
20
+ limit = (args[0] || @limit || 10).to_i
21
+ logger.kinfo("Fetching latest #{limit} Hacker News jobs...")
22
+ job_ids = fetch_job_ids.first(limit)
23
+ jobs = job_ids.map { |id| extract_job_info(fetch_job_item(id)) }
24
+ display_jobs(jobs)
25
+ end
26
+ end
27
+
28
+ def self.arguments
29
+ '[limit]'
30
+ end
31
+
32
+ def self.usage
33
+ 'kscript hn_jobs [limit]'
34
+ end
35
+
36
+ def self.group
37
+ 'network'
38
+ end
39
+
40
+ def self.author
41
+ 'kk'
42
+ end
43
+
44
+ def self.description
45
+ 'Fetch and display latest Hacker News jobs: description and url.'
46
+ end
47
+
48
+ private
49
+
50
+ def fetch_job_ids
51
+ require_httpx
52
+ response = HTTPX.get(HN_JOBS_API)
53
+ response = response.first if response.is_a?(Array)
54
+ raise "Failed to fetch job ids: #{response.status}" unless response.status == 200
55
+
56
+ JSON.parse(response.body.to_s)
57
+ end
58
+
59
+ def fetch_job_item(id)
60
+ require_httpx
61
+ url = "#{HN_ITEM_API}/#{id}.json"
62
+ response = HTTPX.get(url)
63
+ response = response.first if response.is_a?(Array)
64
+ raise "Failed to fetch job item #{id}: #{response.status}" unless response.status == 200
65
+
66
+ JSON.parse(response.body.to_s)
67
+ end
68
+
69
+ # 只提取描述和 url
70
+ def extract_job_info(item)
71
+ {
72
+ description: item['title'].to_s.strip,
73
+ url: item['url'] || "https://news.ycombinator.com/item?id=#{item['id']}"
74
+ }
75
+ end
76
+
77
+ def display_jobs(jobs)
78
+ logger.kinfo('| 描述 | 链接 |')
79
+ logger.kinfo('|------|------|')
80
+ jobs.each do |job|
81
+ logger.kinfo("| #{job[:description]} | [查看](#{job[:url]}) |")
82
+ end
83
+ end
84
+
85
+ def require_httpx
86
+ require 'httpx'
87
+ rescue LoadError
88
+ abort 'Missing dependency: httpx. Please run: gem install httpx'
89
+ end
90
+ end
91
+ end
@@ -5,7 +5,7 @@
5
5
  # This software is released under the MIT License.
6
6
  # https://opensource.org/licenses/MIT
7
7
 
8
- # require 'kscript'
8
+ require 'httpx'
9
9
 
10
10
  module Kscript
11
11
  class KkJenkinsManageUtils < Kscript::Base
@@ -61,8 +61,9 @@ module Kscript
61
61
 
62
62
  def get_all_job_names
63
63
  url = "#{@jenkins_url}/api/json?tree=jobs[name]"
64
- response = HTTP.get(url, headers: { 'Authorization' => @auth_header })
65
- if response.status.success?
64
+ response = HTTPX.get(url, headers: { 'Authorization' => @auth_header })
65
+ response = response.first if response.is_a?(Array)
66
+ if response.status == 200
66
67
  jobs = JSON.parse(response.body.to_s)['jobs']
67
68
  jobs.map { |job| job['name'] }
68
69
  else
@@ -76,8 +77,9 @@ module Kscript
76
77
 
77
78
  def export_job(job_name)
78
79
  url = "#{@jenkins_url}/job/#{job_name}/config.xml"
79
- response = HTTP.get(url, headers: { 'Authorization' => @auth_header })
80
- return response.body.to_s if response.status.success?
80
+ response = HTTPX.get(url, headers: { 'Authorization' => @auth_header })
81
+ response = response.first if response.is_a?(Array)
82
+ return response.body.to_s if response.status == 200
81
83
 
82
84
  logger.kerror("Error exporting job #{job_name}: #{response.status}")
83
85
  nil
@@ -94,10 +96,11 @@ module Kscript
94
96
  create_new_job(job_name, config_xml)
95
97
  rescue StandardError
96
98
  logger.kinfo("Updating existing job #{job_name}")
97
- HTTP.put(url, body: config_xml, headers: {
98
- 'Authorization' => @auth_header,
99
- 'Content-Type' => 'application/xml'
100
- })
99
+ response = HTTPX.put(url, body: config_xml, headers: {
100
+ 'Authorization' => @auth_header,
101
+ 'Content-Type' => 'application/xml'
102
+ })
103
+ response.first if response.is_a?(Array)
101
104
  end
102
105
  end
103
106
 
@@ -125,11 +128,12 @@ module Kscript
125
128
 
126
129
  def create_new_job(job_name, config_xml)
127
130
  url = "#{@jenkins_url}/createItem?name=#{job_name}"
128
- response = HTTP.post(url, body: config_xml, headers: {
129
- 'Authorization' => @auth_header,
130
- 'Content-Type' => 'application/xml'
131
- })
132
- if response.status.success?
131
+ response = HTTPX.post(url, body: config_xml, headers: {
132
+ 'Authorization' => @auth_header,
133
+ 'Content-Type' => 'application/xml'
134
+ })
135
+ response = response.first if response.is_a?(Array)
136
+ if response.status == 200
133
137
  logger.kinfo("Successfully created new job #{job_name}")
134
138
  else
135
139
  logger.kerror("Failed to create job #{job_name}: #{response.status}")
@@ -5,7 +5,7 @@
5
5
  # This software is released under the MIT License.
6
6
  # https://opensource.org/licenses/MIT
7
7
 
8
- # require 'kscript'
8
+ require 'httpx'
9
9
 
10
10
  module Kscript
11
11
  class KkKibanaManageUtils < Kscript::Base
@@ -33,7 +33,8 @@ module Kscript
33
33
  def space_exists?
34
34
  url = "#{@base_url}/api/spaces/space/#{@space_name}"
35
35
  response = client.get(url, headers: kbn_headers)
36
- response.status.success?
36
+ response = response.first if response.is_a?(Array)
37
+ response.status == 200
37
38
  rescue StandardError => e
38
39
  logger.kerror("Error checking space existence: #{e.message}")
39
40
  false
@@ -51,7 +52,8 @@ module Kscript
51
52
  }
52
53
 
53
54
  response = client.post(url, json: body, headers: kbn_headers)
54
- if response.status.success?
55
+ response = response.first if response.is_a?(Array)
56
+ if response.status == 200
55
57
  logger.kinfo("Space '#{@space_name}' created successfully!")
56
58
  else
57
59
  logger.kerror("Failed to create space '#{@space_name}': #{response.body}")
@@ -62,12 +64,17 @@ module Kscript
62
64
 
63
65
  # Return the HTTP client with authentication
64
66
  def client
65
- @client ||= HTTP.basic_auth(user: @username, pass: @password)
67
+ @client ||= HTTPX.with(headers: { 'Authorization' => basic_auth_header })
68
+ end
69
+
70
+ def basic_auth_header
71
+ 'Basic ' + Base64.strict_encode64("#{@username}:#{@password}")
66
72
  end
67
73
 
68
74
  # Fetch all indices from Kibana
69
75
  def indices
70
76
  response = client.get("#{@base_url}/api/index_management/indices", headers: kbn_headers)
77
+ response = response.first if response.is_a?(Array)
71
78
  handle_response(response) { |body| JSON.parse(body).map { |item| item['name'] } }
72
79
  end
73
80
 
@@ -83,7 +90,8 @@ module Kscript
83
90
  },
84
91
  'version' => 1
85
92
  }
86
- client.post(url, json: body, headers: kbn_headers)
93
+ response = client.post(url, json: body, headers: kbn_headers)
94
+ response.first if response.is_a?(Array)
87
95
  end
88
96
  end
89
97
 
@@ -94,7 +102,8 @@ module Kscript
94
102
  body = index_body(index_name, uuid)
95
103
 
96
104
  response = client.post(url, json: body, headers: kbn_headers)
97
- if response.status.success?
105
+ response = response.first if response.is_a?(Array)
106
+ if response.status == 200
98
107
  logger.kinfo("#{index_name} Index creation successful!")
99
108
  else
100
109
  handle_error(response, index_name)
@@ -136,7 +145,8 @@ module Kscript
136
145
  }
137
146
  ]
138
147
  }.to_json
139
- client.put(url, body: request_body, headers: kbn_headers)
148
+ response = client.put(url, body: request_body, headers: kbn_headers)
149
+ response.first if response.is_a?(Array)
140
150
  logger.kinfo("Create #{@project_name} user role sucessed!")
141
151
  end
142
152
 
@@ -149,7 +159,8 @@ module Kscript
149
159
  'email' => "#{@project_name}@devops.io",
150
160
  'roles' => [@project_name]
151
161
  }.to_json
152
- client.post(url, body: request_body, headers: kbn_headers)
162
+ response = client.post(url, body: request_body, headers: kbn_headers)
163
+ response.first if response.is_a?(Array)
153
164
  logger.kinfo("Create #{@project_name} user sucessed!")
154
165
  end
155
166
 
@@ -185,7 +196,9 @@ module Kscript
185
196
  'options' => { 'fields' => %w[title type typeMeta name] },
186
197
  'version' => 1
187
198
  }
188
- JSON.parse(client.post(url, json: body, headers: kbn_headers))['result']['result']['hits']
199
+ response = client.post(url, json: body, headers: kbn_headers)
200
+ response = response.first if response.is_a?(Array)
201
+ JSON.parse(response.body)['result']['result']['hits']
189
202
  end
190
203
 
191
204
  # Construct the body for creating an index
@@ -218,7 +231,8 @@ module Kscript
218
231
 
219
232
  # Handle the response from Kibana
220
233
  def handle_response(response)
221
- if response.status.success?
234
+ response = response.first if response.is_a?(Array)
235
+ if response.status == 200
222
236
  yield response.body
223
237
  else
224
238
  handle_error(response)
@@ -6,6 +6,7 @@
6
6
  # https://opensource.org/licenses/MIT
7
7
 
8
8
  # require 'kscript'
9
+ require 'concurrent-ruby'
9
10
 
10
11
  module Kscript
11
12
  class KkPortScanUtils < Kscript::Base
@@ -36,29 +37,23 @@ module Kscript
36
37
  def scan
37
38
  msg = "Scanning #{@target} ports #{@ports} with concurrency=#{@thread_count}"
38
39
  logger.kinfo(msg)
39
- queue = Queue.new
40
- @ports.each { |port| queue << port }
41
- threads = []
42
- @thread_count.times do
43
- threads << Thread.new do
44
- until queue.empty?
45
- port = nil
46
- begin
47
- port = queue.pop(true)
48
- rescue ThreadError
49
- break
50
- end
51
- begin
52
- Socket.tcp(@target, port, connect_timeout: 0.5) do |_sock|
53
- logger.kinfo('Port open', port: port)
54
- end
55
- rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, SocketError
56
- # closed or filtered
57
- end
40
+ pool = Concurrent::ThreadPoolExecutor.new(
41
+ min_threads: [2, @thread_count].min,
42
+ max_threads: @thread_count,
43
+ max_queue: @ports.size,
44
+ fallback_policy: :caller_runs
45
+ )
46
+ @ports.each do |port|
47
+ pool.post do
48
+ Socket.tcp(@target, port, connect_timeout: 0.5) do |_sock|
49
+ logger.kinfo('Port open', port: port)
58
50
  end
51
+ rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, SocketError
52
+ # closed or filtered
59
53
  end
60
54
  end
61
- threads.each(&:join)
55
+ pool.shutdown
56
+ pool.wait_for_termination
62
57
  end
63
58
 
64
59
  # 支持多种端口参数格式: 22,80,443 或 1..1024
@@ -5,7 +5,7 @@
5
5
  # This software is released under the MIT License.
6
6
  # https://opensource.org/licenses/MIT
7
7
 
8
- require 'net/http'
8
+ require 'httpx'
9
9
  require 'json'
10
10
 
11
11
  module Kscript
@@ -25,9 +25,9 @@ module Kscript
25
25
  end
26
26
 
27
27
  def fetch_rates
28
- uri = URI(API_URL)
29
- response = Net::HTTP.get(uri)
30
- data = JSON.parse(response)
28
+ response = HTTPX.get(API_URL)
29
+ response = response.first if response.is_a?(Array)
30
+ data = JSON.parse(response.body.to_s)
31
31
  if @currency_code && data['rates'][@currency_code.upcase]
32
32
  rate = data['rates'][@currency_code.upcase]
33
33
  logger.kinfo("1 USD = #{rate} #{@currency_code.upcase}")
@@ -6,5 +6,5 @@
6
6
  # https://opensource.org/licenses/MIT
7
7
 
8
8
  module Kscript
9
- VERSION = '1.1.0'
9
+ VERSION = '1.1.2'
10
10
  end
data/lib/kscript.rb CHANGED
@@ -20,8 +20,6 @@ require 'open3'
20
20
  require 'openssl'
21
21
 
22
22
  # 第三方 gem
23
- require 'http'
24
- require 'bcrypt'
25
23
  require 'nokogiri'
26
24
  require 'thor'
27
25
  require 'aws-sdk-s3'
metadata CHANGED
@@ -1,139 +1,155 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kscript
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-07-11 00:00:00.000000000 Z
11
+ date: 2025-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-s3
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.130'
19
+ version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.130'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bcrypt
28
+ name: concurrent-ruby
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '3.1'
34
- - - "<"
35
- - !ruby/object:Gem::Version
36
- version: '4.0'
33
+ version: '0'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
38
  - - ">="
42
39
  - !ruby/object:Gem::Version
43
- version: '3.1'
44
- - - "<"
45
- - !ruby/object:Gem::Version
46
- version: '4.0'
40
+ version: '0'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: dotenv
49
43
  requirement: !ruby/object:Gem::Requirement
50
44
  requirements:
51
- - - "~>"
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
- version: '3.0'
47
+ version: '0'
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
51
  requirements:
58
- - - "~>"
52
+ - - ">="
59
53
  - !ruby/object:Gem::Version
60
- version: '3.0'
54
+ version: '0'
61
55
  - !ruby/object:Gem::Dependency
62
56
  name: httpx
63
57
  requirement: !ruby/object:Gem::Requirement
64
58
  requirements:
65
- - - "~>"
59
+ - - ">="
66
60
  - !ruby/object:Gem::Version
67
- version: '1.5'
61
+ version: '0'
68
62
  type: :runtime
69
63
  prerelease: false
70
64
  version_requirements: !ruby/object:Gem::Requirement
71
65
  requirements:
72
- - - "~>"
66
+ - - ">="
73
67
  - !ruby/object:Gem::Version
74
- version: '1.5'
68
+ version: '0'
75
69
  - !ruby/object:Gem::Dependency
76
70
  name: nokogiri
77
71
  requirement: !ruby/object:Gem::Requirement
78
72
  requirements:
79
73
  - - ">="
80
74
  - !ruby/object:Gem::Version
81
- version: '1.13'
82
- - - "<"
83
- - !ruby/object:Gem::Version
84
- version: '2.0'
75
+ version: '0'
85
76
  type: :runtime
86
77
  prerelease: false
87
78
  version_requirements: !ruby/object:Gem::Requirement
88
79
  requirements:
89
80
  - - ">="
90
81
  - !ruby/object:Gem::Version
91
- version: '1.13'
92
- - - "<"
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: parallel
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
93
95
  - !ruby/object:Gem::Version
94
- version: '2.0'
96
+ version: '0'
95
97
  - !ruby/object:Gem::Dependency
96
98
  name: rake
97
99
  requirement: !ruby/object:Gem::Requirement
98
100
  requirements:
99
- - - "~>"
101
+ - - ">="
100
102
  - !ruby/object:Gem::Version
101
- version: '13.0'
103
+ version: '0'
102
104
  type: :runtime
103
105
  prerelease: false
104
106
  version_requirements: !ruby/object:Gem::Requirement
105
107
  requirements:
106
- - - "~>"
108
+ - - ">="
107
109
  - !ruby/object:Gem::Version
108
- version: '13.0'
110
+ version: '0'
109
111
  - !ruby/object:Gem::Dependency
110
112
  name: thor
111
113
  requirement: !ruby/object:Gem::Requirement
112
114
  requirements:
113
- - - '='
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: tty-prompt
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
114
130
  - !ruby/object:Gem::Version
115
- version: 1.3.2
131
+ version: '0'
116
132
  type: :runtime
117
133
  prerelease: false
118
134
  version_requirements: !ruby/object:Gem::Requirement
119
135
  requirements:
120
- - - '='
136
+ - - ">="
121
137
  - !ruby/object:Gem::Version
122
- version: 1.3.2
138
+ version: '0'
123
139
  - !ruby/object:Gem::Dependency
124
140
  name: rubocop
125
141
  requirement: !ruby/object:Gem::Requirement
126
142
  requirements:
127
- - - "~>"
143
+ - - ">="
128
144
  - !ruby/object:Gem::Version
129
- version: '1.21'
145
+ version: '0'
130
146
  type: :development
131
147
  prerelease: false
132
148
  version_requirements: !ruby/object:Gem::Requirement
133
149
  requirements:
134
- - - "~>"
150
+ - - ">="
135
151
  - !ruby/object:Gem::Version
136
- version: '1.21'
152
+ version: '0'
137
153
  description: Kscript provides a set of handy Ruby scripts for system administration,
138
154
  development, and automation.
139
155
  email:
@@ -162,6 +178,7 @@ files:
162
178
  - lib/kscript/plugins/kk_elastic_cert_finger_utils.rb
163
179
  - lib/kscript/plugins/kk_ffmpeg_install_utils.rb
164
180
  - lib/kscript/plugins/kk_file_rename_utils.rb
181
+ - lib/kscript/plugins/kk_hn_jobs_utils.rb
165
182
  - lib/kscript/plugins/kk_ip_lookup_utils.rb
166
183
  - lib/kscript/plugins/kk_jenkins_manage_utils.rb
167
184
  - lib/kscript/plugins/kk_kibana_manage_utils.rb