yourimageshare 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ee8bed4a3f8b3383ae8ca06a4031231c404aa4c843bc65578ff7b2d8b8c1eed4
4
+ data.tar.gz: 5f7201b52c57bb2d283da2730ef68d79386d2748bb03c99b8fc9348f5e3e1e8c
5
+ SHA512:
6
+ metadata.gz: 2fa5756c5aa8d1f779301b731b6532e70f0d99ea068d4f0f6baa7b2361fef9c5857a817909c76c54054f6bf554d6b97fa59fbc29f70828ea3011490e7fb9a5e1
7
+ data.tar.gz: 10571f3b239e22ee6dd9b544a1db000938dde0a7f03110cb64f52c6e0826a586c8e01b4376a7d1934594c3a9c8c5ea9a6b1731b642f9d33b0b91ac5dde283926
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 YourImageShare
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # yourimageshare-api/ruby
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/yourimageshare.svg)](https://rubygems.org/gems/yourimageshare)
4
+ [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
+
6
+ Official Ruby SDK for the [YourImageShare](https://yourimageshare.com)
7
+ upload API. Zero gem dependencies (standard library only), Ruby 2.7+.
8
+
9
+ - **Get an API key:** sign in and open the **API** tab at
10
+ [yourimageshare.com/my-account](https://yourimageshare.com/my-account).
11
+ - **Full HTTP reference:** [yourimageshare.com/about/api](https://yourimageshare.com/about/api)
12
+ or [API.md in this repo](../API.md).
13
+ - Same API, same result shapes, in [JavaScript/TypeScript](https://www.npmjs.com/package/yourimageshare), [Python](https://pypi.org/project/yourimageshare/), [PHP](https://packagist.org/packages/yourimageshare/yourimageshare-php), and [Go](https://pkg.go.dev/github.com/MediaShareORG/yourimageshare/go) too.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ gem install yourimageshare
19
+ ```
20
+
21
+ Or add to your Gemfile:
22
+
23
+ ```ruby
24
+ gem "yourimageshare"
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```ruby
30
+ require "yourimageshare"
31
+
32
+ client = YourImageShare::Client.new("YOUR_API_KEY")
33
+
34
+ # Upload a file by path
35
+ result = client.upload("photo.jpg")
36
+ puts result.direct # https://yourimageshare.com/ib/aB3xY9qRz1
37
+
38
+ # Upload with auto-delete after 1 hour
39
+ client.upload("photo.jpg", expires_in: 3600)
40
+
41
+ # Upload from any IO-like object (a network stream, an in-memory buffer, ...)
42
+ # client.upload_io(io, "photo.jpg")
43
+
44
+ # List your uploads (paginated, 50 per page)
45
+ listing = client.list
46
+ listing.data.each { |item| puts "#{item.id} #{item.direct}" }
47
+
48
+ # Delete an upload
49
+ client.delete(result.id)
50
+ ```
51
+
52
+ ### Error handling
53
+
54
+ Unlike the Go SDK's `(result, error)` return style, the Ruby SDK follows
55
+ Ruby convention and raises `YourImageShare::APIError` (`.status` is the
56
+ HTTP status code, `.message` is the server's error text):
57
+
58
+ ```ruby
59
+ begin
60
+ client.upload("photo.jpg")
61
+ rescue YourImageShare::APIError => e
62
+ puts "#{e.status}: #{e.message}"
63
+ end
64
+ ```
65
+
66
+ ## API
67
+
68
+ ### `YourImageShare::Client.new(api_key, base_url: "https://yourimageshare.com/api", timeout: 30)`
69
+
70
+ `base_url` and `timeout` are keyword overrides, mainly for testing.
71
+
72
+ ### `client.upload(file_path, expires_in: nil) -> UploadResult`
73
+
74
+ Streams the file from disk rather than buffering the whole thing in memory
75
+ first - uploads can be up to 200MB. `expires_in` is seconds, 60 to
76
+ 2,592,000 (30 days); nil means a permanent upload. Returns an
77
+ `UploadResult` with `id`, `type`, `path`, `src`, `direct`, `expires_at`.
78
+
79
+ ### `client.upload_io(io, filename, expires_in: nil) -> UploadResult`
80
+
81
+ Same as `upload`, but from any IO-like object instead of a file path.
82
+
83
+ ### `client.list(page = nil) -> ListResult`
84
+
85
+ Returns a `ListResult` with `data` (an array of `ListedUpload` - `id`,
86
+ `type`, `title`, `path`, `src`, `direct`, `expires_at`, `created_at`) and
87
+ `meta` (`ListMeta` - `current_page`, `last_page`, `total`).
88
+
89
+ ### `client.delete(id) -> nil`
90
+
91
+ Raises `APIError` on a 404/401.
92
+
93
+ ## Rate limits
94
+
95
+ 20 requests/minute and 500/day per key by default (2,000/day per IP as a
96
+ backstop). Not currently surfaced on the return values from this SDK - read
97
+ the `X-RateLimit-Limit`/`X-RateLimit-Remaining` response headers yourself if
98
+ you need them, or open an issue to request them on the result types.
99
+
100
+ ## License
101
+
102
+ MIT
103
+
104
+ ## Support
105
+
106
+ [yourimageshare.com/contact](https://yourimageshare.com/contact)
@@ -0,0 +1,97 @@
1
+ require "net/http"
2
+ require "uri"
3
+ require "json"
4
+
5
+ module YourImageShare
6
+ DEFAULT_BASE_URL = "https://yourimageshare.com/api"
7
+
8
+ # Talks to the YourImageShare upload API. Create one with
9
+ # YourImageShare::Client.new(api_key). Get a key from the API tab at
10
+ # https://yourimageshare.com/my-account.
11
+ class Client
12
+ def initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: 30)
13
+ raise ArgumentError, "api_key is required" if api_key.nil? || api_key.empty?
14
+
15
+ @api_key = api_key
16
+ @base_url = base_url
17
+ @timeout = timeout
18
+ end
19
+
20
+ # Uploads a local file by path. expires_in (seconds, 60 to 2,592,000 =
21
+ # 30 days) auto-deletes the upload later; nil means a permanent upload.
22
+ def upload(file_path, expires_in: nil)
23
+ File.open(file_path, "rb") do |f|
24
+ upload_io(f, File.basename(file_path), expires_in: expires_in)
25
+ end
26
+ end
27
+
28
+ # Uploads from any IO-like object (must respond to #read). filename
29
+ # should include a real extension so the server can infer content type.
30
+ def upload_io(io, filename, expires_in: nil)
31
+ uri = URI(@base_url)
32
+ request = Net::HTTP::Post.new(uri)
33
+ set_common_headers(request)
34
+
35
+ form = [["uploads", io, { filename: filename }]]
36
+ form << ["expires_in", expires_in.to_s] if expires_in && expires_in > 0
37
+ # Net::HTTP streams IO form values in chunks rather than buffering
38
+ # the whole file into memory - important since uploads can be up to
39
+ # 200MB (video).
40
+ request.set_form(form, "multipart/form-data")
41
+
42
+ body = execute(uri, request)
43
+ UploadResult.from_json(body["data"] || {})
44
+ end
45
+
46
+ # Returns your uploads, newest first, 50 per page. page < 2 fetches the
47
+ # first page.
48
+ def list(page = nil)
49
+ uri = URI(@base_url)
50
+ uri.query = URI.encode_www_form(page: page) if page && page > 1
51
+
52
+ request = Net::HTTP::Get.new(uri)
53
+ set_common_headers(request)
54
+
55
+ ListResult.from_json(execute(uri, request))
56
+ end
57
+
58
+ # Removes one of your uploads by id. Raises APIError on failure.
59
+ def delete(id)
60
+ uri = URI("#{@base_url}/#{URI.encode_www_form_component(id)}")
61
+ request = Net::HTTP::Delete.new(uri)
62
+ set_common_headers(request)
63
+
64
+ execute(uri, request)
65
+ nil
66
+ end
67
+
68
+ private
69
+
70
+ def set_common_headers(request)
71
+ request["X-API-Key"] = @api_key
72
+ request["User-Agent"] = "yourimageshare-ruby/#{VERSION}"
73
+ end
74
+
75
+ def execute(uri, request)
76
+ response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https",
77
+ open_timeout: @timeout, read_timeout: @timeout) do |http|
78
+ http.request(request)
79
+ end
80
+
81
+ envelope = begin
82
+ JSON.parse(response.body.to_s)
83
+ rescue JSON::ParserError
84
+ raise APIError.new(response.code.to_i, "unexpected non-JSON response (HTTP #{response.code})")
85
+ end
86
+
87
+ status = response.code.to_i
88
+ if status < 200 || status >= 300 || envelope["type"] == "error"
89
+ message = envelope["errors"]
90
+ message = "request failed (HTTP #{status})" if message.nil? || message.empty?
91
+ raise APIError.new(status, message)
92
+ end
93
+
94
+ envelope
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,15 @@
1
+ module YourImageShare
2
+ # Raised for any non-2xx response or a `{"type":"error"}` payload -
3
+ # mirrors the Go/JS/Python/PHP SDKs' error shape (status + message) so
4
+ # error-handling logic reads the same across every official SDK. Ruby
5
+ # convention is to raise, not to return an error object like Go does.
6
+ class APIError < StandardError
7
+ attr_reader :status, :message
8
+
9
+ def initialize(status, message)
10
+ @status = status
11
+ @message = message
12
+ super("yourimageshare: [#{status}] #{message}")
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ module YourImageShare
2
+ # Response shape for a successful upload - same fields as the
3
+ # Go/JS/Python/PHP SDKs' UploadResult.
4
+ UploadResult = Struct.new(:id, :type, :path, :src, :direct, :expires_at, keyword_init: true) do
5
+ def self.from_json(h)
6
+ new(id: h["id"], type: h["type"], path: h["path"], src: h["src"],
7
+ direct: h["direct"], expires_at: h["expires_at"])
8
+ end
9
+ end
10
+
11
+ # One row of a #list result.
12
+ ListedUpload = Struct.new(:id, :type, :title, :path, :src, :direct, :expires_at, :created_at, keyword_init: true) do
13
+ def self.from_json(h)
14
+ new(id: h["id"], type: h["type"], title: h["title"], path: h["path"],
15
+ src: h["src"], direct: h["direct"], expires_at: h["expires_at"],
16
+ created_at: h["created_at"])
17
+ end
18
+ end
19
+
20
+ # Pagination info for a #list result.
21
+ ListMeta = Struct.new(:current_page, :last_page, :total, keyword_init: true) do
22
+ def self.from_json(h)
23
+ new(current_page: h["current_page"], last_page: h["last_page"], total: h["total"])
24
+ end
25
+ end
26
+
27
+ # Response shape for #list.
28
+ ListResult = Struct.new(:data, :meta, keyword_init: true) do
29
+ def self.from_json(h)
30
+ new(data: (h["data"] || []).map { |row| ListedUpload.from_json(row) },
31
+ meta: ListMeta.from_json(h["meta"] || {}))
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module YourImageShare
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,14 @@
1
+ require_relative "yourimageshare/version"
2
+ require_relative "yourimageshare/errors"
3
+ require_relative "yourimageshare/types"
4
+ require_relative "yourimageshare/client"
5
+
6
+ # The official Ruby client for the YourImageShare upload API
7
+ # (https://yourimageshare.com/about/api). It mirrors the existing Go, JS
8
+ # (npm), and Python (PyPI) SDKs - same method names, same result shapes,
9
+ # same error semantics - just idiomatic Ruby on top (raises APIError
10
+ # instead of Go's (result, error) return style).
11
+ #
12
+ # Zero gem dependencies - only the Ruby standard library.
13
+ module YourImageShare
14
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yourimageshare
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - YourImageShare
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-08-27 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Upload, list, and delete files through the YourImageShare (https://yourimageshare.com)
14
+ JSON/REST API. Zero gem dependencies - standard library only.
15
+ email:
16
+ - support@yourimageshare.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - LICENSE
22
+ - README.md
23
+ - lib/yourimageshare.rb
24
+ - lib/yourimageshare/client.rb
25
+ - lib/yourimageshare/errors.rb
26
+ - lib/yourimageshare/types.rb
27
+ - lib/yourimageshare/version.rb
28
+ homepage: https://yourimageshare.com/about/api
29
+ licenses:
30
+ - MIT
31
+ metadata:
32
+ homepage_uri: https://yourimageshare.com/about/api
33
+ source_code_uri: https://github.com/MediaShareORG/yourimageshare/tree/main/ruby
34
+ changelog_uri: https://github.com/MediaShareORG/yourimageshare/tree/main/ruby/README.md
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 2.7.0
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubygems_version: 3.4.20
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: Official Ruby client for the YourImageShare upload API
54
+ test_files: []