micompress 0.1.0 → 0.1.1

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: 5bb22286474daaaaa3282785ff4887fa39cc071050e9a90a29834cc2c2d06eb2
4
- data.tar.gz: 22e556306149811d188f7e278100898e33400957a2fc6de1c29c6cdb5f567286
3
+ metadata.gz: d3bcea3dd6d4bbf59978e96584f47451821f2f63b72fd36508057b7cdce962e4
4
+ data.tar.gz: e3f437b6b225fdceabf5c6b18cdb213aeb26aeba00fe0efa57497f4116c01df1
5
5
  SHA512:
6
- metadata.gz: f8814ecd628c6ebe11627886effaf7d0b18b3a082787b6b7ed5efd8900b43ed1e3211d4f12ff33b4e8055743a563cfdd8a2726d126e68d46de285563a76c34d0
7
- data.tar.gz: c4af22c5e3561ab916574050bb7aa4d7fd32ef8b3b6667291baabc0c1e3127bd47c2fc3ebab99f03d0c4890d09311855153eccfffcae310f24f4327635922638
6
+ metadata.gz: 0d8314810b0c1f84b0112210f00bdcd2ede98f864cdeac87ae14ec4983918f61dbfd740afddfb014c540b0f0f313feaec1404675d347c4528e0cd4d83e5454a8
7
+ data.tar.gz: a89bfadabe4f7effa41257fb22a5c6ee7e0c20f48c17060d71dd98de10199085bea9c35afc2100784b440b19f55de6130ce32f354deec82633727466ec340644
data/README.md CHANGED
@@ -17,6 +17,28 @@ micompress *.png --preset extreme
17
17
  micompress report.pdf -o out/
18
18
  ```
19
19
 
20
+ ## API key
21
+
22
+ Small files work without an account. For bigger files and a monthly allowance, use your personal API key
23
+ (`mc_…`), shown on your [account page](https://micompress.com/account) — creating an account is free.
24
+
25
+ ```bash
26
+ export MICOMPRESS_API_KEY=mc_your_key_here
27
+ micompress big-video.mp4
28
+ micompress big-video.mp4 --api-key mc_your_key_here # the flag wins over the env var
29
+ ```
30
+
31
+ | Plan | Compressions per month | Notes |
32
+ |------|------------------------|-------|
33
+ | No key (anonymous) | Anonymous limits | Small files only |
34
+ | Free account | 50 via the API | Files up to 100 MB |
35
+ | Plus ($9.99/mo) | 1,000 | Shared with website usage |
36
+ | Pro ($19.99/mo) | 5,000 | Shared with website usage |
37
+
38
+ When the allowance is used up you get `API_QUOTA_REACHED` (free) or `USAGE_LIMIT_REACHED` (paid) —
39
+ see [micompress.com/plans](https://micompress.com/plans). `--token` is the older login-token option and
40
+ still works. Keep the key secret: anyone who has it can spend your quota.
41
+
20
42
  ## Library
21
43
 
22
44
  ```ruby
@@ -25,15 +47,16 @@ require "micompress"
25
47
  bytes, meta = Micompress.compress_file("photo.jpg", preset: "extreme")
26
48
  File.binwrite("photo-min.jpg", bytes)
27
49
  puts "#{meta['savedPercent']}% smaller"
50
+
51
+ # With an API key; errors raise Micompress::Error, whose #code holds the server code
52
+ bytes, meta = Micompress.compress_file("big.pdf", api_key: ENV["MICOMPRESS_API_KEY"])
28
53
  ```
29
54
 
30
55
  ## Build & publish
31
56
 
32
- Requires Ruby (not available on this build server):
33
-
34
57
  ```bash
35
58
  gem build micompress.gemspec
36
- gem push micompress-0.1.0.gem
59
+ gem push micompress-0.1.1.gem
37
60
  ```
38
61
 
39
62
  ## License
data/exe/micompress CHANGED
@@ -10,7 +10,8 @@ parser = OptionParser.new do |o|
10
10
  o.on("-o", "--output DIR", "Output directory") { |v| options[:output] = v }
11
11
  o.on("-p", "--preset NAME", %w[lossless recommended extreme], "lossless|recommended|extreme") { |v| options[:preset] = v }
12
12
  o.on("--max-width PX", Integer, "Resize images to max width") { |v| options[:max_width] = v }
13
- o.on("--token JWT", "Auth token for higher limits") { |v| options[:token] = v }
13
+ o.on("--api-key KEY", "Personal API key from micompress.com/account (default: $MICOMPRESS_API_KEY)") { |v| options[:api_key] = v }
14
+ o.on("--token JWT", "Legacy login token (JWT); prefer --api-key") { |v| options[:token] = v }
14
15
  o.on("--api URL", "API base URL") { |v| options[:base_url] = v }
15
16
  o.on("--suffix STR", "Default output suffix (default -min)") { |v| options[:suffix] = v }
16
17
  o.on("-q", "--quiet", "Only print errors") { options[:quiet] = true }
@@ -18,6 +19,9 @@ parser = OptionParser.new do |o|
18
19
  o.on("-h", "--help", "Show help") { puts o; exit }
19
20
  end
20
21
  files = parser.parse(ARGV)
22
+ # Flag wins over the environment variable.
23
+ api_key = (options[:api_key] || ENV["MICOMPRESS_API_KEY"]).to_s.strip
24
+ options[:api_key] = api_key.empty? ? nil : api_key
21
25
 
22
26
  if files.empty?
23
27
  puts parser
@@ -53,7 +57,8 @@ files.each do |file|
53
57
  begin
54
58
  bytes, meta = Micompress.compress_file(
55
59
  file, base_url: options[:base_url], preset: options[:preset],
56
- max_width: options[:max_width], token: options[:token]
60
+ max_width: options[:max_width], token: options[:token],
61
+ api_key: options[:api_key]
57
62
  )
58
63
  dest = out_path(file, options)
59
64
  File.binwrite(dest, bytes)
@@ -4,16 +4,33 @@ require "net/http"
4
4
  require "uri"
5
5
  require "json"
6
6
  require_relative "categories"
7
+ # VERSION is used below; requiring it here keeps this file loadable on its own
8
+ # instead of depending on micompress.rb having run first.
9
+ require_relative "version"
7
10
 
8
11
  module Micompress
9
12
  DEFAULT_BASE = "https://micompress.com"
10
13
  UTM = "utm_source=rubygems&utm_medium=cli&utm_campaign=extend"
11
14
  USER_AGENT = "micompress-ruby/#{VERSION} (+https://micompress.com)"
15
+ # Where users get a personal API key, and where to upgrade when its quota runs out.
16
+ ACCOUNT_URL = "#{DEFAULT_BASE}/account"
17
+ PLANS_URL = "#{DEFAULT_BASE}/plans"
12
18
 
13
- class Error < StandardError; end
19
+ class Error < StandardError
20
+ # Machine-readable server code, e.g. "INVALID_API_KEY" (nil for local errors).
21
+ attr_reader :code
22
+
23
+ def initialize(message = nil, code = nil)
24
+ super(message)
25
+ @code = code
26
+ end
27
+ end
14
28
 
15
29
  # Compress a single file. Returns [bytes, meta_hash].
16
- def self.compress_file(path, base_url: DEFAULT_BASE, preset: "recommended", max_width: nil, token: nil)
30
+ # api_key: personal key ("mc_...") from micompress.com/account, sent as X-API-Key.
31
+ # token: legacy login JWT, still sent as a Bearer header if given.
32
+ def self.compress_file(path, base_url: DEFAULT_BASE, preset: "recommended", max_width: nil, token: nil,
33
+ api_key: nil)
17
34
  base = base_url.chomp("/")
18
35
  filename = File.basename(path)
19
36
  category = category_for(filename)
@@ -24,6 +41,8 @@ module Micompress
24
41
  req = Net::HTTP::Post.new(uri)
25
42
  req["Accept"] = "application/json"
26
43
  req["User-Agent"] = USER_AGENT
44
+ req["X-MiCompress-Client"] = "ruby/#{VERSION}"
45
+ req["X-API-Key"] = api_key if api_key
27
46
  req["Authorization"] = "Bearer #{token}" if token
28
47
 
29
48
  form = [["file", File.open(path, "rb"), { filename: filename, content_type: "application/octet-stream" }],
@@ -32,14 +51,34 @@ module Micompress
32
51
  req.set_form(form, "multipart/form-data")
33
52
 
34
53
  json = request_json(uri, req)
35
- unless json["success"] && json["downloadUrl"]
36
- raise Error, (json["error"] || "Compression failed")
37
- end
54
+ raise api_error(json, base) unless json["success"] && json["downloadUrl"]
38
55
 
39
56
  bytes = download("#{base}#{json['downloadUrl']}", token)
40
57
  [bytes, json]
41
58
  end
42
59
 
60
+ # Append "<lead> <url>" unless the server's message already names the URL.
61
+ def self.with_hint(message, lead, url)
62
+ message.include?(url.sub(%r{\Ahttps?://}, "")) ? message : "#{message} #{lead} #{url}"
63
+ end
64
+
65
+ def self.api_error(json, base)
66
+ code = json["code"]
67
+ message =
68
+ case code
69
+ when "LOGIN_REQUIRED"
70
+ "File exceeds the anonymous size limit. Pass --api-key <key> (free key at #{ACCOUNT_URL}) " \
71
+ "or compress it online at #{base}/?#{UTM}"
72
+ when "INVALID_API_KEY"
73
+ with_hint(json["error"] || "Invalid API key.", "Check your key at", ACCOUNT_URL)
74
+ when "API_QUOTA_REACHED", "USAGE_LIMIT_REACHED"
75
+ with_hint(json["error"] || "Monthly compression quota reached.", "Upgrade for a bigger monthly quota:", PLANS_URL)
76
+ else
77
+ json["error"] || "Compression failed"
78
+ end
79
+ Error.new(message, code)
80
+ end
81
+
43
82
  def self.request_json(uri, req)
44
83
  res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
45
84
  http.read_timeout = 120
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Micompress
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: micompress
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - MiCompress
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-29 00:00:00.000000000 Z
11
+ date: 2026-10-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A tiny command-line client and library for the micompress.com compression
14
14
  API.